diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a08542df255..969b7f8f9fa 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -35,6 +35,6 @@ and help. ## Configuration, dependencies, and tests -Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/devguide) +Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/geth-developer/dev-guide) for more details on configuring your environment, managing project dependencies and testing procedures. diff --git a/.travis.yml b/.travis.yml index 9209f1cba70..925e23b1a57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,18 +5,15 @@ jobs: allow_failures: - stage: build os: osx - go: 1.17.x env: - azure-osx - - azure-ios - - cocoapods-ios include: # This builder only tests code linters on latest version of Go - stage: lint os: linux dist: bionic - go: 1.19.x + go: 1.20.x env: - lint git: @@ -31,7 +28,7 @@ jobs: os: linux arch: amd64 dist: bionic - go: 1.19.x + go: 1.20.x env: - docker services: @@ -48,7 +45,7 @@ jobs: os: linux arch: arm64 dist: bionic - go: 1.19.x + go: 1.20.x env: - docker services: @@ -60,37 +57,13 @@ jobs: script: - go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go - # This builder does the Ubuntu PPA upload - - stage: build - if: type = push - os: linux - dist: bionic - go: 1.19.x - env: - - ubuntu-ppa - - GO111MODULE=on - git: - submodules: false # avoid cloning ethereum/tests - addons: - apt: - packages: - - devscripts - - debhelper - - dput - - fakeroot - - python-bzrlib - - python-paramiko - script: - - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts - - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " - # This builder does the Linux Azure uploads - stage: build if: type = push os: linux dist: bionic sudo: required - go: 1.19.x + go: 1.20.x env: - azure-linux - GO111MODULE=on @@ -120,43 +93,81 @@ jobs: - go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + # This builder does the OSX Azure uploads + - stage: build + if: type = push + os: osx + go: 1.20.x + env: + - azure-osx + - GO111MODULE=on + git: + submodules: false # avoid cloning ethereum/tests + script: + - go run build/ci.go install -dlgo + - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds + # These builders run the tests - stage: build os: linux arch: amd64 dist: bionic - go: 1.19.x + go: 1.20.x env: - GO111MODULE=on script: - - go run build/ci.go test -coverage $TEST_PACKAGES + - go run build/ci.go test $TEST_PACKAGES - stage: build if: type = pull_request os: linux arch: arm64 dist: bionic - go: 1.18.x + go: 1.19.x + env: + - GO111MODULE=on + script: + - go run build/ci.go test $TEST_PACKAGES + + - stage: build + os: linux + dist: bionic + go: 1.19.x env: - GO111MODULE=on script: - - go run build/ci.go test -coverage $TEST_PACKAGES + - go run build/ci.go test $TEST_PACKAGES + # This builder does the Ubuntu PPA nightly uploads - stage: build + if: type = cron || (type = push && tag ~= /^v[0-9]/) os: linux dist: bionic - go: 1.18.x + go: 1.20.x env: + - ubuntu-ppa - GO111MODULE=on + git: + submodules: false # avoid cloning ethereum/tests + addons: + apt: + packages: + - devscripts + - debhelper + - dput + - fakeroot + - python-bzrlib + - python-paramiko script: - - go run build/ci.go test -coverage $TEST_PACKAGES + - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts + - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " # This builder does the Azure archive purges to avoid accumulating junk - stage: build if: type = cron os: linux dist: bionic - go: 1.19.x + go: 1.20.x env: - azure-purge - GO111MODULE=on @@ -170,9 +181,9 @@ jobs: if: type = cron os: linux dist: bionic - go: 1.19.x + go: 1.20.x env: - GO111MODULE=on script: - - go run build/ci.go test -race -coverage $TEST_PACKAGES + - go run build/ci.go test -race $TEST_PACKAGES diff --git a/Dockerfile b/Dockerfile index c16b0ba87bf..1951fed8ef8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG VERSION="" ARG BUILDNUM="" # Build Geth in a stock Go builder container -FROM golang:1.19-alpine as builder +FROM golang:1.20-alpine as builder RUN apk add --no-cache gcc musl-dev linux-headers git diff --git a/Dockerfile.alltools b/Dockerfile.alltools index 044a9a68950..70ccc39825e 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -4,7 +4,7 @@ ARG VERSION="" ARG BUILDNUM="" # Build Geth in a stock Go builder container -FROM golang:1.19-alpine as builder +FROM golang:1.20-alpine as builder RUN apk add --no-cache gcc musl-dev linux-headers git diff --git a/README.md b/README.md index 9835b004589..34bd8b94c98 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ archives are published at https://geth.ethereum.org/downloads/. For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth). -Building `geth` requires both a Go (version 1.18 or later) and a C compiler. You can install +Building `geth` requires both a Go (version 1.19 or later) and a C compiler. You can install them using your favourite package manager. Once the dependencies are installed, run ```shell @@ -36,10 +36,10 @@ directory. | Command | Description | | :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/interface/command-line-options) for command line options. | +| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. | | `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. | | `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. | -| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/dapp/native-bindings) page for details. | +| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. | | `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. | | `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). | | `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). | @@ -47,7 +47,7 @@ directory. ## Running `geth` Going through all the possible command line flags is out of scope here (please consult our -[CLI Wiki page](https://geth.ethereum.org/docs/interface/command-line-options)), +[CLI Wiki page](https://geth.ethereum.org/docs/fundamentals/command-line-options)), but we've enumerated a few common parameter combos to get you up to speed quickly on how you can run your own `geth` instance. @@ -82,10 +82,10 @@ This command will: * Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag), causing it to download more data in exchange for avoiding processing the entire history of the Ethereum network, which is very CPU intensive. - * Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interface/javascript-console), + * Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interacting-with-geth/javascript-console), (via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md) (note: the `web3` version bundled within `geth` is very old, and not up to date with official docs), - as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/rpc/server). + as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc). This tool is optional and if you leave it out you can always attach it to an already running `geth` instance with `geth attach`. @@ -175,7 +175,7 @@ accessible from the outside. As a developer, sooner rather than later you'll want to start interacting with `geth` and the Ethereum network via your own programs and not manually through the console. To aid this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/) -and [`geth` specific APIs](https://geth.ethereum.org/docs/rpc/server)). +and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)). These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based platforms, and named pipes on Windows). diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 008c71feaa7..8ec905b9bdd 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -95,7 +95,10 @@ func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.Genesis backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{}) backend.events = filters.NewEventSystem(backend.filterSystem, false) - backend.rollback(blockchain.CurrentBlock()) + header := backend.blockchain.CurrentBlock() + block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64()) + + backend.rollback(block) return backend } @@ -135,7 +138,10 @@ func (b *SimulatedBackend) Rollback() { b.mu.Lock() defer b.mu.Unlock() - b.rollback(b.blockchain.CurrentBlock()) + header := b.blockchain.CurrentBlock() + block := b.blockchain.GetBlock(header.Hash(), header.Number.Uint64()) + + b.rollback(block) } func (b *SimulatedBackend) rollback(parent *types.Block) { @@ -174,7 +180,7 @@ func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error { // stateByBlockNumber retrieves a state by a given blocknumber. func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) { - if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 { + if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 { return b.blockchain.State() } block, err := b.blockByNumber(ctx, blockNumber) @@ -303,7 +309,7 @@ func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) ( // (associated with its hash) if found without Lock. func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 { - return b.blockchain.CurrentBlock(), nil + return b.blockByHash(ctx, b.blockchain.CurrentBlock().Hash()) } block := b.blockchain.GetBlockByNumber(uint64(number.Int64())) @@ -431,7 +437,7 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM b.mu.Lock() defer b.mu.Unlock() - if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { + if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 { return nil, errBlockNumberUnsupported } stateDB, err := b.blockchain.State() @@ -455,7 +461,7 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereu defer b.mu.Unlock() defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot()) - res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) + res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState) if err != nil { return nil, err } @@ -549,7 +555,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs call.Gas = gas snapshot := b.pendingState.Snapshot() - res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) + res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState) b.pendingState.RevertToSnapshot(snapshot) if err != nil { @@ -599,7 +605,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs // callContract implements common code between normal and pending contract calls. // state is modified during execution, make sure to copy it if necessary. -func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) { +func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, header *types.Header, stateDB *state.StateDB) (*core.ExecutionResult, error) { // Gas prices post 1559 need to be initialized if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") @@ -638,20 +644,40 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM if call.Value == nil { call.Value = new(big.Int) } + // Set infinite balance to the fake caller account. from := stateDB.GetOrNewStateObject(call.From) from.SetBalance(math.MaxBig256) + + var excessDataGas *big.Int + // Get the last block header + ph := b.blockchain.GetHeaderByHash(header.ParentHash) + if ph != nil { + excessDataGas = ph.ExcessDataGas + } + // Execute the call. - msg := callMsg{call} + msg := &core.Message{ + From: call.From, + To: call.To, + Value: call.Value, + GasLimit: call.Gas, + GasPrice: call.GasPrice, + GasFeeCap: call.GasFeeCap, + GasTipCap: call.GasTipCap, + Data: call.Data, + AccessList: call.AccessList, + SkipAccountChecks: true, + } - txContext := core.NewEVMTxContext(msg) - evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. + txContext := core.NewEVMTxContext(msg) + evmContext := core.NewEVMBlockContext(header, excessDataGas, b.blockchain, nil) vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}) - gasPool := new(core.GasPool).AddGas(math.MaxUint64) + gasPool := new(core.GasPool).AddGas(math.MaxUint64).AddDataGas(params.MaxDataGasPerBlock) - return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb() + return core.ApplyMessage(vmEnv, msg, gasPool) } // SendTransaction updates the pending block to include the given transaction. @@ -665,7 +691,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa return fmt.Errorf("could not fetch parent") } // Check transaction validity - signer := types.MakeSigner(b.blockchain.Config(), block.Number()) + signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time()) sender, err := types.Sender(signer, tx) if err != nil { return fmt.Errorf("invalid transaction: %v", err) @@ -815,23 +841,6 @@ func (b *SimulatedBackend) Blockchain() *core.BlockChain { return b.blockchain } -// callMsg implements core.Message to allow passing it as a transaction simulator. -type callMsg struct { - ethereum.CallMsg -} - -func (m callMsg) From() common.Address { return m.CallMsg.From } -func (m callMsg) Nonce() uint64 { return 0 } -func (m callMsg) IsFake() bool { return true } -func (m callMsg) To() *common.Address { return m.CallMsg.To } -func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } -func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap } -func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap } -func (m callMsg) Gas() uint64 { return m.CallMsg.Gas } -func (m callMsg) Value() *big.Int { return m.CallMsg.Value } -func (m callMsg) Data() []byte { return m.CallMsg.Data } -func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList } - // filterBackend implements filters.Backend to support filtering for logs without // taking bloom-bits acceleration structures into account. type filterBackend struct { @@ -854,15 +863,9 @@ func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNum case rpc.LatestBlockNumber: return fb.bc.CurrentHeader(), nil case rpc.FinalizedBlockNumber: - if block := fb.bc.CurrentFinalizedBlock(); block != nil { - return block.Header(), nil - } - return nil, errors.New("finalized block not found") + return fb.bc.CurrentFinalBlock(), nil case rpc.SafeBlockNumber: - if block := fb.bc.CurrentSafeBlock(); block != nil { - return block.Header(), nil - } - return nil, errors.New("safe block not found") + return fb.bc.CurrentSafeBlock(), nil default: return fb.bc.GetHeaderByNumber(uint64(number.Int64())), nil } diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index 40699e01163..698bfc57657 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -1189,7 +1189,7 @@ func TestFork(t *testing.T) { sim.Commit() } // 3. - if sim.blockchain.CurrentBlock().NumberU64() != uint64(n) { + if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n) { t.Error("wrong chain length") } // 4. @@ -1199,7 +1199,7 @@ func TestFork(t *testing.T) { sim.Commit() } // 6. - if sim.blockchain.CurrentBlock().NumberU64() != uint64(n+1) { + if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n+1) { t.Error("wrong chain length") } } @@ -1344,7 +1344,7 @@ func TestCommitReturnValue(t *testing.T) { sim := simTestBackend(testAddr) defer sim.Close() - startBlockHeight := sim.blockchain.CurrentBlock().NumberU64() + startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64() // Test if Commit returns the correct block hash h1 := sim.Commit() diff --git a/accounts/external/backend.go b/accounts/external/backend.go index d403b7e562d..e8b9dcf44ff 100644 --- a/accounts/external/backend.go +++ b/accounts/external/backend.go @@ -217,6 +217,18 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio case types.DynamicFeeTxType: args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap()) args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap()) + case types.BlobTxType: + hashes, _, blobs, proofs := tx.BlobWrapData() + if len(hashes) != len(blobs) { + return nil, fmt.Errorf("missing blobs data, expected %d blobs", len(hashes)) + } + if len(hashes) != len(proofs) { + return nil, fmt.Errorf("missing proofs data, expected %d proofs", len(proofs)) + } + + args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap()) + args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap()) + args.Blobs = blobs default: return nil, fmt.Errorf("unsupported tx type %d", tx.Type()) } diff --git a/accounts/keystore/account_cache_test.go b/accounts/keystore/account_cache_test.go index 01db587d159..aa71c120182 100644 --- a/accounts/keystore/account_cache_test.go +++ b/accounts/keystore/account_cache_test.go @@ -113,7 +113,6 @@ func TestWatchNewFile(t *testing.T) { func TestWatchNoDir(t *testing.T) { t.Parallel() // Create ks but not the directory that it watches. - rand.Seed(time.Now().UnixNano()) dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int())) ks := NewKeyStore(dir, LightScryptN, LightScryptP) list := ks.Accounts() @@ -322,7 +321,6 @@ func TestUpdatedKeyfileContents(t *testing.T) { t.Parallel() // Create a temporary keystore to test with - rand.Seed(time.Now().UnixNano()) dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int())) ks := NewKeyStore(dir, LightScryptN, LightScryptP) diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go index cda94280fdd..723df0f2b35 100644 --- a/accounts/usbwallet/ledger.go +++ b/accounts/usbwallet/ledger.go @@ -59,6 +59,8 @@ const ( ledgerP1InitTransactionData ledgerParam1 = 0x00 // First transaction data block for signing ledgerP1ContTransactionData ledgerParam1 = 0x80 // Subsequent transaction data block for signing ledgerP2DiscardAddressChainCode ledgerParam2 = 0x00 // Do not return the chain code along with the address + + ledgerEip155Size int = 3 // Size of the EIP-155 chain_id,r,s in unsigned transactions ) // errLedgerReplyInvalidHeader is the error message returned by a Ledger data exchange @@ -347,9 +349,15 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction op = ledgerP1InitTransactionData reply []byte ) + + // 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-- { + } + for len(payload) > 0 { // Calculate the size of the next data chunk - chunk := 255 if chunk > len(payload) { chunk = len(payload) } diff --git a/appveyor.yml b/appveyor.yml index d477e6db9f5..114aec644b2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,7 +26,7 @@ for: - go run build/ci.go lint - go run build/ci.go install -dlgo test_script: - - go run build/ci.go test -dlgo -coverage + - go run build/ci.go test -dlgo # linux/386 is disabled. - matrix: @@ -54,4 +54,4 @@ for: - go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds test_script: - - go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -coverage + - go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% diff --git a/beacon/engine/errors.go b/beacon/engine/errors.go index b2f31139256..769001b9e3d 100644 --- a/beacon/engine/errors.go +++ b/beacon/engine/errors.go @@ -74,12 +74,11 @@ var ( // - newPayloadV1: if the payload was accepted, but not processed (side chain) ACCEPTED = "ACCEPTED" - INVALIDBLOCKHASH = "INVALID_BLOCK_HASH" - GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"} UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"} InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"} InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"} + TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"} InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"} STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil} diff --git a/beacon/engine/gen_ed.go b/beacon/engine/gen_ed.go index 336dfc6cc75..d03d842238c 100644 --- a/beacon/engine/gen_ed.go +++ b/beacon/engine/gen_ed.go @@ -32,6 +32,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { BlockHash common.Hash `json:"blockHash" gencodec:"required"` Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` + ExcessDataGas *hexutil.Big `json:"excessDataGas"` } var enc ExecutableData enc.ParentHash = e.ParentHash @@ -54,6 +55,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { } } enc.Withdrawals = e.Withdrawals + enc.ExcessDataGas = (*hexutil.Big)(e.ExcessDataGas) return json.Marshal(&enc) } @@ -75,6 +77,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error { BlockHash *common.Hash `json:"blockHash" gencodec:"required"` Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` + ExcessDataGas *hexutil.Big `json:"excessDataGas"` } var dec ExecutableData if err := json.Unmarshal(input, &dec); err != nil { @@ -142,5 +145,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error { if dec.Withdrawals != nil { e.Withdrawals = dec.Withdrawals } + if dec.ExcessDataGas != nil { + e.ExcessDataGas = (*big.Int)(dec.ExcessDataGas) + } return nil } diff --git a/beacon/engine/gen_epe.go b/beacon/engine/gen_epe.go index cc66cef6cd3..d3fa102cd31 100644 --- a/beacon/engine/gen_epe.go +++ b/beacon/engine/gen_epe.go @@ -15,20 +15,23 @@ var _ = (*executionPayloadEnvelopeMarshaling)(nil) // MarshalJSON marshals as JSON. func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) { type ExecutionPayloadEnvelope struct { - ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` - BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` + ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` + BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` + BlobsBundle *BlobsBundle `json:"blobsBundle" gencodec:"omitempty"` } var enc ExecutionPayloadEnvelope enc.ExecutionPayload = e.ExecutionPayload enc.BlockValue = (*hexutil.Big)(e.BlockValue) + enc.BlobsBundle = e.BlobsBundle return json.Marshal(&enc) } // UnmarshalJSON unmarshals from JSON. func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error { type ExecutionPayloadEnvelope struct { - ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` - BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` + ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` + BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` + BlobsBundle *BlobsBundle `json:"blobsBundle" gencodec:"omitempty"` } var dec ExecutionPayloadEnvelope if err := json.Unmarshal(input, &dec); err != nil { @@ -42,5 +45,8 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'blockValue' for ExecutionPayloadEnvelope") } e.BlockValue = (*big.Int)(dec.BlockValue) + if dec.BlobsBundle != nil { + e.BlobsBundle = dec.BlobsBundle + } return nil } diff --git a/beacon/engine/types.go b/beacon/engine/types.go index 58f72631194..61da5fe614c 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -42,6 +42,13 @@ type payloadAttributesMarshaling struct { Timestamp hexutil.Uint64 } +// BlobsBundle holds the blobs of an execution payload +type BlobsBundle struct { + Commitments []types.KZGCommitment `json:"commitments" gencodec:"required"` + Blobs []types.Blob `json:"blobs" gencodec:"required"` + Proofs []types.KZGProof `json:"proofs" gencodec:"required"` +} + //go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go // ExecutableData is the data necessary to execute an EL payload. @@ -61,6 +68,7 @@ type ExecutableData struct { BlockHash common.Hash `json:"blockHash" gencodec:"required"` Transactions [][]byte `json:"transactions" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` + ExcessDataGas *big.Int `json:"excessDataGas"` // New in EIP-4844 } // JSON type overrides for executableData. @@ -70,6 +78,7 @@ type executableDataMarshaling struct { GasUsed hexutil.Uint64 Timestamp hexutil.Uint64 BaseFeePerGas *hexutil.Big + ExcessDataGas *hexutil.Big ExtraData hexutil.Bytes LogsBloom hexutil.Bytes Transactions []hexutil.Bytes @@ -78,8 +87,9 @@ type executableDataMarshaling struct { //go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go type ExecutionPayloadEnvelope struct { - ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` - BlockValue *big.Int `json:"blockValue" gencodec:"required"` + ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` + BlockValue *big.Int `json:"blockValue" gencodec:"required"` + BlobsBundle *BlobsBundle `json:"blobsBundle" gencodec:"omitempty"` } // JSON type overrides for ExecutionPayloadEnvelope. @@ -132,7 +142,7 @@ type ForkchoiceStateV1 struct { func encodeTransactions(txs []*types.Transaction) [][]byte { var enc = make([][]byte, len(txs)) for i, tx := range txs { - enc[i], _ = tx.MarshalBinary() + enc[i], _ = tx.MarshalMinimal() } return enc } @@ -141,7 +151,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) { var txs = make([]*types.Transaction, len(enc)) for i, encTx := range enc { var tx types.Transaction - if err := tx.UnmarshalBinary(encTx); err != nil { + if err := tx.UnmarshalMinimal(encTx); err != nil { return nil, fmt.Errorf("invalid transaction %d: %v", i, err) } txs[i] = &tx @@ -182,6 +192,12 @@ func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) { h := types.DeriveSha(types.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil)) withdrawalsRoot = &h } + // Check that number of blobs are valid + for _, tx := range txs { + if tx.Type() == types.BlobTxType && len(tx.DataHashes()) == 0 { + return nil, fmt.Errorf("zero blobs within a blob transaction") + } + } header := &types.Header{ ParentHash: params.ParentHash, UncleHash: types.EmptyUncleHash, @@ -199,6 +215,7 @@ func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) { Extra: params.ExtraData, MixDigest: params.Random, WithdrawalsHash: withdrawalsRoot, + ExcessDataGas: params.ExcessDataGas, } block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals) if block.Hash() != params.BlockHash { @@ -226,6 +243,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int) *ExecutionPayloadE Random: block.MixDigest(), ExtraData: block.Extra(), Withdrawals: block.Withdrawals(), + ExcessDataGas: block.ExcessDataGas(), } return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees} } @@ -233,5 +251,27 @@ func BlockToExecutableData(block *types.Block, fees *big.Int) *ExecutionPayloadE // ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1 type ExecutionPayloadBodyV1 struct { TransactionData []hexutil.Bytes `json:"transactions"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` +} + +func BlockToBlobData(block *types.Block) (*BlobsBundle, error) { + blobsBundle := &BlobsBundle{ + Blobs: []types.Blob{}, + Commitments: []types.KZGCommitment{}, + Proofs: []types.KZGProof{}, + } + for i, tx := range block.Transactions() { + if tx.Type() == types.BlobTxType { + versionedHashes, commitments, blobs, proofs := tx.BlobWrapData() + if len(versionedHashes) != len(commitments) || len(versionedHashes) != len(blobs) || len(blobs) != len(proofs) { + return nil, fmt.Errorf("tx %d in block %s has inconsistent blobs (%d) / commitments (%d)"+ + " / versioned hashes (%d) / proofs (%d)", i, block.Hash(), len(blobs), len(commitments), len(versionedHashes), len(proofs)) + } + + blobsBundle.Blobs = append(blobsBundle.Blobs, blobs...) + blobsBundle.Commitments = append(blobsBundle.Commitments, commitments...) + blobsBundle.Proofs = append(blobsBundle.Proofs, proofs...) + } + } + return blobsBundle, nil } diff --git a/build/checksums.txt b/build/checksums.txt index ca6bd4f6de7..e349d3eba03 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -1,19 +1,19 @@ # This file contains sha256 checksums of optional build dependencies. -8e486e8e85a281fc5ce3f0bedc5b9d2dbf6276d7db0b25d3ec034f313da0375f go1.19.5.src.tar.gz -23d22bb6571bbd60197bee8aaa10e702f9802786c2e2ddce5c84527e86b66aa0 go1.19.5.darwin-amd64.tar.gz -4a67f2bf0601afe2177eb58f825adf83509511d77ab79174db0712dc9efa16c8 go1.19.5.darwin-arm64.tar.gz -b18a5e1e60130003896e1d1c8a9e142c7cccf6f5063d52c55dd42006434419c1 go1.19.5.freebsd-386.tar.gz -317996f7427691ff3a7ffd1b6aa089b9c66cd76f32e9107443f2f6aad1bb568a go1.19.5.freebsd-amd64.tar.gz -f68331aa7458a3598060595f5601d5731fd452bb2c62ff23095ddad68854e510 go1.19.5.linux-386.tar.gz -36519702ae2fd573c9869461990ae550c8c0d955cd28d2827a6b159fda81ff95 go1.19.5.linux-amd64.tar.gz -fc0aa29c933cec8d76f5435d859aaf42249aa08c74eb2d154689ae44c08d23b3 go1.19.5.linux-arm64.tar.gz -ec14f04bdaf4a62bdcf8b55b9b6434cc27c2df7d214d0bb7076a7597283b026a go1.19.5.linux-armv6l.tar.gz -e4032e7c52ebc48bad5c58ba8de0759b6091d9b1e59581a8a521c8c9d88dbe93 go1.19.5.linux-ppc64le.tar.gz -764871cbca841a99a24e239b63c68a4aaff4104658e3165e9ca450cac1fcbea3 go1.19.5.linux-s390x.tar.gz -8873f5871d996106b701febd979c5af022e6ea58bdbbb3817a28ab948b22c286 go1.19.5.windows-386.zip -167db91a2e40aeb453d3e59d213ecab06f62e1c4a84d13a06ccda1d999961caa go1.19.5.windows-amd64.zip -85a75555e82d8aa6f486d8d29491c593389682acce9f0c270090d5938eee30ef go1.19.5.windows-arm64.zip +4d0e2850d197b4ddad3bdb0196300179d095bb3aefd4dfbc3b36702c3728f8ab go1.20.2.src.tar.gz +c93b8ced9517d07e1cd4c362c6e2d5242cb139e29b417a328fbf19aded08764c go1.20.2.darwin-amd64.tar.gz +7343c87f19e79c0063532e82e1c4d6f42175a32d99f7a4d15e658e88bf97f885 go1.20.2.darwin-arm64.tar.gz +14f9be2004e042b3a64d0facb0c020756a9084a5c7333e33b0752b393b6016ea go1.20.2.freebsd-386.tar.gz +b41b67b4f1b56797a7cecf6ee7f47fcf4f93960b2788a3683c07dd009d30b2a4 go1.20.2.freebsd-amd64.tar.gz +ee240ed33ae57504c41f04c12236aeaa17fbeb6ea9fcd096cd9dc7a89d10d4db go1.20.2.linux-386.tar.gz +4eaea32f59cde4dc635fbc42161031d13e1c780b87097f4b4234cfce671f1768 go1.20.2.linux-amd64.tar.gz +78d632915bb75e9a6356a47a42625fd1a785c83a64a643fedd8f61e31b1b3bef go1.20.2.linux-arm64.tar.gz +d79d56bafd6b52b8d8cbe3f8e967caaac5383a23d7a4fa9ac0e89778cd16a076 go1.20.2.linux-armv6l.tar.gz +850564ddb760cb703db63bf20182dc4407abd2ff090a95fa66d6634d172fd095 go1.20.2.linux-ppc64le.tar.gz +8da24c5c4205fe8115f594237e5db7bcb1d23df67bc1fa9a999954b1976896e8 go1.20.2.linux-s390x.tar.gz +31838b291117495bbb93683603e98d5118bfabd2eb318b4d07540bfd524bab86 go1.20.2.windows-386.zip +fe439f0e438f7555a7f5f7194ddb6f4a07b0de1fa414385d19f2aeb26d9f43db go1.20.2.windows-amd64.zip +ac5010c8b8b22849228a8dea698d58b9c7be2195d30c6d778cce0f709858fa64 go1.20.2.windows-arm64.zip fba08acc4027f69f07cef48fbff70b8a7ecdfaa1c2aba9ad3fb31d60d9f5d4bc golangci-lint-1.51.1-darwin-amd64.tar.gz 75b8f0ff3a4e68147156be4161a49d4576f1be37a0b506473f8c482140c1e7f2 golangci-lint-1.51.1-darwin-arm64.tar.gz @@ -41,3 +41,6 @@ c4f58b7e227b9fd41f0e9310dc83f4a4e7d026598e2f6e95b78761081a6d9bd2 golangci-lint- eb57f9bcb56646f2e3d6ccaf02ec227815fb05077b2e0b1bf9e755805acdc2b9 golangci-lint-1.51.1-windows-arm64.zip bce02f7232723cb727755ee11f168a700a00896a25d37f87c4b173bce55596b4 golangci-lint-1.51.1-windows-armv6.zip cf6403f84707ce8c98664736772271bc8874f2e760c2fd0f00cf3e85963507e9 golangci-lint-1.51.1-windows-armv7.zip + +# This is the builder on PPA that will build Go itself (inception-y), don't modify! +d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz diff --git a/build/ci.go b/build/ci.go index 094ae0a77bc..49926621bda 100644 --- a/build/ci.go +++ b/build/ci.go @@ -128,7 +128,7 @@ var ( "focal": "golang-go", // EOL: 04/2030 "jammy": "golang-go", // EOL: 04/2032 "kinetic": "golang-go", // EOL: 07/2023 - //"lunar": "golang-go", // EOL: 01/2024 + "lunar": "golang-go", // EOL: 01/2024 } debGoBootPaths = map[string]string{ @@ -136,10 +136,18 @@ var ( "golang-go": "/usr/lib/go", } - // This is the version of go that will be downloaded by + // This is the version of Go that will be downloaded by // // go run ci.go install -dlgo - dlgoVersion = "1.19.5" + dlgoVersion = "1.20.2" + + // This is the version of Go that will be used to bootstrap the PPA builder. + // + // This version is fine to be old and full of security holes, we just use it + // to build the latest Go. Don't change it. If it ever becomes insufficient, + // we need to switch over to a recursive builder to jumpt across supported + // versions. + gobootVersion = "1.19.6" ) var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) @@ -655,10 +663,11 @@ func doDebianSource(cmdline []string) { gpg.Stdin = bytes.NewReader(key) build.MustRun(gpg) } - - // Download and verify the Go source package. - gobundle := downloadGoSources(*cachedir) - + // Download and verify the Go source packages. + var ( + gobootbundle = downloadGoBootstrapSources(*cachedir) + gobundle = downloadGoSources(*cachedir) + ) // Download all the dependencies needed to build the sources and run the ci script srcdepfetch := tc.Go("mod", "download") srcdepfetch.Env = append(srcdepfetch.Env, "GOPATH="+filepath.Join(*workdir, "modgopath")) @@ -675,12 +684,19 @@ func doDebianSource(cmdline []string) { meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables) pkgdir := stageDebianSource(*workdir, meta) - // Add Go source code + // Add bootstrapper Go source code + if err := build.ExtractArchive(gobootbundle, pkgdir); err != nil { + log.Fatalf("Failed to extract bootstrapper Go sources: %v", err) + } + if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".goboot")); err != nil { + log.Fatalf("Failed to rename bootstrapper Go source folder: %v", err) + } + // Add builder Go source code if err := build.ExtractArchive(gobundle, pkgdir); err != nil { - log.Fatalf("Failed to extract Go sources: %v", err) + log.Fatalf("Failed to extract builder Go sources: %v", err) } if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil { - log.Fatalf("Failed to rename Go source folder: %v", err) + log.Fatalf("Failed to rename builder Go source folder: %v", err) } // Add all dependency modules in compressed form os.MkdirAll(filepath.Join(pkgdir, ".mod", "cache"), 0755) @@ -709,6 +725,19 @@ func doDebianSource(cmdline []string) { } } +// downloadGoBootstrapSources downloads the Go source tarball that will be used +// to bootstrap the builder Go. +func downloadGoBootstrapSources(cachedir string) string { + csdb := build.MustLoadChecksums("build/checksums.txt") + file := fmt.Sprintf("go%s.src.tar.gz", gobootVersion) + url := "https://dl.google.com/go/" + file + dst := filepath.Join(cachedir, file) + if err := csdb.DownloadFile(url, dst); err != nil { + log.Fatal(err) + } + return dst +} + // downloadGoSources downloads the Go source tarball. func downloadGoSources(cachedir string) string { csdb := build.MustLoadChecksums("build/checksums.txt") diff --git a/build/deb/ethereum/deb.rules b/build/deb/ethereum/deb.rules index 0677ef91e40..475e628b2f5 100644 --- a/build/deb/ethereum/deb.rules +++ b/build/deb/ethereum/deb.rules @@ -16,7 +16,11 @@ override_dh_auto_build: # We can't download a fresh Go within Launchpad, so we're shipping and building # one on the fly. However, we can't build it inside the go-ethereum folder as # bootstrapping clashes with go modules, so build in a sibling folder. - (mv .go ../ && cd ../.go/src && ./make.bash) + # + # We're also shipping the bootstrapper as of Go 1.20 as it had minimum version + # requirements opposed to older versions of Go. + (mv .goboot ../ && cd ../.goboot/src && ./make.bash) + (mv .go ../ && cd ../.go/src && GOROOT_BOOTSTRAP=`pwd`/../../.goboot ./make.bash) # We can't download external go modules within Launchpad, so we're shipping the # entire dependency source cache with go-ethereum. diff --git a/cmd/checkpoint-admin/README.md b/cmd/checkpoint-admin/README.md index 7c0c657eb5c..1067ead0564 100644 --- a/cmd/checkpoint-admin/README.md +++ b/cmd/checkpoint-admin/README.md @@ -46,7 +46,7 @@ Deploy checkpoint oracle contract. `--signers` indicates the specified trusted s checkpoint-admin deploy --rpc --clef --signer --signers --threshold 1 ``` -It is worth noting that checkpoint-admin only supports clef as a signer for transactions and plain text(checkpoint). For more clef usage, please see the clef [tutorial](https://geth.ethereum.org/docs/clef/tutorial) . +It is worth noting that checkpoint-admin only supports clef as a signer for transactions and plain text(checkpoint). For more clef usage, please see the clef [tutorial](https://geth.ethereum.org/docs/tools/clef/tutorial) . #### Sign diff --git a/cmd/devp2p/crawl.go b/cmd/devp2p/crawl.go index 0d8127684e6..8c9755ac1cd 100644 --- a/cmd/devp2p/crawl.go +++ b/cmd/devp2p/crawl.go @@ -17,6 +17,8 @@ package main import ( + "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/log" @@ -34,6 +36,7 @@ type crawler struct { // settings revalidateInterval time.Duration + mu sync.RWMutex } const ( @@ -67,7 +70,7 @@ func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler return c } -func (c *crawler) run(timeout time.Duration) nodeSet { +func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet { var ( timeoutTimer = time.NewTimer(timeout) timeoutCh <-chan time.Time @@ -75,35 +78,51 @@ func (c *crawler) run(timeout time.Duration) nodeSet { doneCh = make(chan enode.Iterator, len(c.iters)) liveIters = len(c.iters) ) + if nthreads < 1 { + nthreads = 1 + } defer timeoutTimer.Stop() defer statusTicker.Stop() for _, it := range c.iters { go c.runIterator(doneCh, it) } - var ( - added int - updated int - skipped int - recent int - removed int + added uint64 + updated uint64 + skipped uint64 + recent uint64 + removed uint64 + wg sync.WaitGroup ) + wg.Add(nthreads) + for i := 0; i < nthreads; i++ { + go func() { + defer wg.Done() + for { + select { + case n := <-c.ch: + switch c.updateNode(n) { + case nodeSkipIncompat: + atomic.AddUint64(&skipped, 1) + case nodeSkipRecent: + atomic.AddUint64(&recent, 1) + case nodeRemoved: + atomic.AddUint64(&removed, 1) + case nodeAdded: + atomic.AddUint64(&added, 1) + default: + atomic.AddUint64(&updated, 1) + } + case <-c.closed: + return + } + } + }() + } + loop: for { select { - case n := <-c.ch: - switch c.updateNode(n) { - case nodeSkipIncompat: - skipped++ - case nodeSkipRecent: - recent++ - case nodeRemoved: - removed++ - case nodeAdded: - added++ - default: - updated++ - } case it := <-doneCh: if it == c.inputIter { // Enable timeout when we're done revalidating the input nodes. @@ -119,8 +138,11 @@ loop: break loop case <-statusTicker.C: log.Info("Crawling in progress", - "added", added, "updated", updated, "removed", removed, - "ignored(recent)", recent, "ignored(incompatible)", skipped) + "added", atomic.LoadUint64(&added), + "updated", atomic.LoadUint64(&updated), + "removed", atomic.LoadUint64(&removed), + "ignored(recent)", atomic.LoadUint64(&removed), + "ignored(incompatible)", atomic.LoadUint64(&skipped)) } } @@ -131,6 +153,7 @@ loop: for ; liveIters > 0; liveIters-- { <-doneCh } + wg.Wait() return c.output } @@ -148,7 +171,9 @@ func (c *crawler) runIterator(done chan<- enode.Iterator, it enode.Iterator) { // updateNode updates the info about the given node, and returns a status // about what changed func (c *crawler) updateNode(n *enode.Node) int { + c.mu.RLock() node, ok := c.output[n.ID()] + c.mu.RUnlock() // Skip validation of recently-seen nodes. if ok && time.Since(node.LastCheck) < c.revalidateInterval { @@ -156,10 +181,9 @@ func (c *crawler) updateNode(n *enode.Node) int { } // Request the node record. - nn, err := c.disc.RequestENR(n) - node.LastCheck = truncNow() status := nodeUpdated - if err != nil { + node.LastCheck = truncNow() + if nn, err := c.disc.RequestENR(n); err != nil { if node.Score == 0 { // Node doesn't implement EIP-868. log.Debug("Skipping node", "id", n.ID()) @@ -176,8 +200,9 @@ func (c *crawler) updateNode(n *enode.Node) int { } node.LastResponse = node.LastCheck } - // Store/update node in output set. + c.mu.Lock() + defer c.mu.Unlock() if node.Score <= 0 { log.Debug("Removing node", "id", n.ID()) delete(c.output, n.ID()) diff --git a/cmd/devp2p/discv4cmd.go b/cmd/devp2p/discv4cmd.go index 94e61c36f32..63122634780 100644 --- a/cmd/devp2p/discv4cmd.go +++ b/cmd/devp2p/discv4cmd.go @@ -78,7 +78,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}), + Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}), } discv4TestCommand = &cli.Command{ Name: "test", @@ -120,6 +120,11 @@ var ( Usage: "Time limit for the crawl.", Value: 30 * time.Minute, } + crawlParallelismFlag = &cli.IntFlag{ + Name: "parallel", + Usage: "How many parallel discoveries to attempt.", + Value: 16, + } remoteEnodeFlag = &cli.StringFlag{ Name: "remote", Usage: "Enode of the remote node under test", @@ -195,7 +200,7 @@ func discv4ResolveJSON(ctx *cli.Context) error { defer disc.Close() c := newCrawler(inputSet, disc, enode.IterNodes(nodeargs)) c.revalidateInterval = 0 - output := c.run(0) + output := c.run(0, 1) writeNodesJSON(nodesFile, output) return nil } @@ -214,7 +219,7 @@ func discv4Crawl(ctx *cli.Context) error { defer disc.Close() c := newCrawler(inputSet, disc, disc.RandomNodes()) c.revalidateInterval = 10 * time.Minute - output := c.run(ctx.Duration(crawlTimeoutFlag.Name)) + output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name)) writeNodesJSON(nodesFile, output) return nil } diff --git a/cmd/devp2p/discv5cmd.go b/cmd/devp2p/discv5cmd.go index 343e2a0d5d4..832a4bc1f42 100644 --- a/cmd/devp2p/discv5cmd.go +++ b/cmd/devp2p/discv5cmd.go @@ -110,7 +110,7 @@ func discv5Crawl(ctx *cli.Context) error { defer disc.Close() c := newCrawler(inputSet, disc, disc.RandomNodes()) c.revalidateInterval = 10 * time.Minute - output := c.run(ctx.Duration(crawlTimeoutFlag.Name)) + output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name)) writeNodesJSON(nodesFile, output) return nil } diff --git a/cmd/devp2p/dns_cloudflare.go b/cmd/devp2p/dns_cloudflare.go index 92c6faf272e..bfe92257ee5 100644 --- a/cmd/devp2p/dns_cloudflare.go +++ b/cmd/devp2p/dns_cloudflare.go @@ -126,11 +126,16 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string) } // Iterate over the new records and inject anything missing. + log.Info("Updating DNS entries") + created := 0 + updated := 0 + skipped := 0 for path, val := range records { old, exists := existing[path] if !exists { // Entry is unknown, push a new one to Cloudflare. - log.Info(fmt.Sprintf("Creating %s = %q", path, val)) + log.Debug(fmt.Sprintf("Creating %s = %q", path, val)) + created++ ttl := rootTTL if path != name { ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare @@ -139,27 +144,33 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string) _, err = c.CreateDNSRecord(context.Background(), c.zoneID, record) } else if old.Content != val { // Entry already exists, only change its content. - log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val)) + log.Debug(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val)) + updated++ old.Content = val err = c.UpdateDNSRecord(context.Background(), c.zoneID, old.ID, old) } else { + skipped++ log.Debug(fmt.Sprintf("Skipping %s = %q", path, val)) } if err != nil { return fmt.Errorf("failed to publish %s: %v", path, err) } } - + log.Info("Updated DNS entries", "new", created, "updated", updated, "untouched", skipped) // Iterate over the old records and delete anything stale. + deleted := 0 + log.Info("Deleting stale DNS entries") for path, entry := range existing { if _, ok := records[path]; ok { continue } // Stale entry, nuke it. - log.Info(fmt.Sprintf("Deleting %s = %q", path, entry.Content)) + log.Debug(fmt.Sprintf("Deleting %s = %q", path, entry.Content)) + deleted++ if err := c.DeleteDNSRecord(context.Background(), c.zoneID, entry.ID); err != nil { return fmt.Errorf("failed to delete %s: %v", path, err) } } + log.Info("Deleted stale DNS entries", "count", deleted) return nil } diff --git a/cmd/devp2p/dns_route53.go b/cmd/devp2p/dns_route53.go index 4aab0856ff9..81734eb2ad8 100644 --- a/cmd/devp2p/dns_route53.go +++ b/cmd/devp2p/dns_route53.go @@ -329,8 +329,9 @@ func (c *route53Client) collectRecords(name string) (map[string]recordSet, error var req route53.ListResourceRecordSetsInput req.HostedZoneId = &c.zoneID existing := make(map[string]recordSet) + log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID) for page := 0; ; page++ { - log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page) + log.Debug("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page) resp, err := c.api.ListResourceRecordSets(context.TODO(), &req) if err != nil { return existing, err @@ -360,7 +361,7 @@ func (c *route53Client) collectRecords(name string) (map[string]recordSet, error req.StartRecordName = resp.NextRecordName req.StartRecordType = resp.NextRecordType } - + log.Info("Loaded existing TXT records", "name", name, "zone", c.zoneID, "records", len(existing)) return existing, nil } diff --git a/cmd/devp2p/internal/ethtest/snap.go b/cmd/devp2p/internal/ethtest/snap.go index 754d7850d53..f947e4bc9ba 100644 --- a/cmd/devp2p/internal/ethtest/snap.go +++ b/cmd/devp2p/internal/ethtest/snap.go @@ -23,6 +23,7 @@ import ( "math/rand" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/internal/utesting" @@ -210,13 +211,6 @@ type byteCodesTest struct { expHashes int } -var ( - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - // emptyCode is the known hash of the empty EVM bytecode. - emptyCode = common.HexToHash("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470") -) - // TestSnapGetByteCodes various forms of GetByteCodes requests. func (s *Suite) TestSnapGetByteCodes(t *utesting.T) { // The halfchain import should yield these bytecodes @@ -263,15 +257,15 @@ func (s *Suite) TestSnapGetByteCodes(t *utesting.T) { }, // Empties { - nBytes: 10000, hashes: []common.Hash{emptyRoot}, + nBytes: 10000, hashes: []common.Hash{types.EmptyRootHash}, expHashes: 0, }, { - nBytes: 10000, hashes: []common.Hash{emptyCode}, + nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash}, expHashes: 1, }, { - nBytes: 10000, hashes: []common.Hash{emptyCode, emptyCode, emptyCode}, + nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash}, expHashes: 3, }, // The existing bytecodes @@ -363,7 +357,7 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) { for i := 1; i <= 65; i++ { accPaths = append(accPaths, pathTo(i)) } - empty := emptyCode + empty := types.EmptyCodeHash for i, tc := range []trieNodesTest{ { root: s.chain.RootAt(999), diff --git a/cmd/devp2p/internal/ethtest/transaction.go b/cmd/devp2p/internal/ethtest/transaction.go index bf3a4b7f063..d5f2309aefd 100644 --- a/cmd/devp2p/internal/ethtest/transaction.go +++ b/cmd/devp2p/internal/ethtest/transaction.go @@ -66,7 +66,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction return fmt.Errorf("peering failed: %v", err) } // Send the transaction - if err = sendConn.Write(&Transactions{tx}); err != nil { + if err = sendConn.Write(&Transactions{types.NewNetworkTransaction(tx)}); err != nil { return fmt.Errorf("failed to write to connection: %v", err) } // peer receiving connection to node @@ -84,7 +84,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction recTxs := *msg // if you receive an old tx propagation, read from connection again if len(recTxs) == 1 && prevTx != nil { - if recTxs[0] == prevTx { + if recTxs[0].Tx == prevTx { continue } } @@ -184,7 +184,7 @@ func sendMaliciousTx(s *Suite, tx *types.Transaction) error { } // write malicious tx - if err = conn.Write(&Transactions{tx}); err != nil { + if err = conn.Write(&Transactions{types.NewNetworkTransaction(tx)}); err != nil { return fmt.Errorf("failed to write to connection: %v", err) } return nil @@ -195,7 +195,11 @@ var nonce = uint64(99) // sendMultipleSuccessfulTxs sends the given transactions to the node and // expects the node to accept and propagate them. func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction) error { - txMsg := Transactions(txs) + ntxs := make([]*types.NetworkTransaction, len(txs)) + for i := range txs { + ntxs[i] = types.NewNetworkTransaction(txs[i]) + } + txMsg := Transactions(ntxs) t.Logf("sending %d txs\n", len(txs)) sendConn, recvConn, err := s.createSendAndRecvConns() diff --git a/cmd/devp2p/main.go b/cmd/devp2p/main.go index 9e13d29ab72..8461a8b9b5e 100644 --- a/cmd/devp2p/main.go +++ b/cmd/devp2p/main.go @@ -29,7 +29,6 @@ import ( var app = flags.NewApp("go-ethereum devp2p tool") func init() { - app.HideVersion = true app.Flags = append(app.Flags, debug.Flags...) app.Before = func(ctx *cli.Context) error { flags.MigrateGlobalFlags(ctx) diff --git a/cmd/evm/internal/t8ntool/block.go b/cmd/evm/internal/t8ntool/block.go index 1140daa2c27..a8249bf90ec 100644 --- a/cmd/evm/internal/t8ntool/block.go +++ b/cmd/evm/internal/t8ntool/block.go @@ -55,16 +55,18 @@ type header struct { Nonce *types.BlockNonce `json:"nonce"` BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ExcessDataGas *big.Int `json:"excessDataGas" rlp:"optional"` } type headerMarshaling struct { - Difficulty *math.HexOrDecimal256 - Number *math.HexOrDecimal256 - GasLimit math.HexOrDecimal64 - GasUsed math.HexOrDecimal64 - Time math.HexOrDecimal64 - Extra hexutil.Bytes - BaseFee *math.HexOrDecimal256 + Difficulty *math.HexOrDecimal256 + Number *math.HexOrDecimal256 + GasLimit math.HexOrDecimal64 + GasUsed math.HexOrDecimal64 + Time math.HexOrDecimal64 + Extra hexutil.Bytes + BaseFee *math.HexOrDecimal256 + ExcessDataGas *math.HexOrDecimal256 } type bbInput struct { @@ -120,8 +122,8 @@ func (i *bbInput) ToBlock() *types.Block { UncleHash: types.EmptyUncleHash, Coinbase: common.Address{}, Root: i.Header.Root, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, Bloom: i.Header.Bloom, Difficulty: common.Big0, Number: i.Header.Number, @@ -132,6 +134,7 @@ func (i *bbInput) ToBlock() *types.Block { MixDigest: i.Header.MixDigest, BaseFee: i.Header.BaseFee, WithdrawalsHash: i.Header.WithdrawalsHash, + ExcessDataGas: i.Header.ExcessDataGas, } // Fill optional values. diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 2c68659945e..309d6c46e0e 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -58,6 +58,7 @@ type ExecutionResult struct { GasUsed math.HexOrDecimal64 `json:"gasUsed"` BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"` + ExcessDataGas *math.HexOrDecimal256 `json:"currentExcessDataGas,omitempty"` } type ommer struct { @@ -67,37 +68,39 @@ type ommer struct { //go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go type stEnv struct { - Coinbase common.Address `json:"currentCoinbase" gencodec:"required"` - Difficulty *big.Int `json:"currentDifficulty"` - Random *big.Int `json:"currentRandom"` - ParentDifficulty *big.Int `json:"parentDifficulty"` - ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"` - ParentGasUsed uint64 `json:"parentGasUsed,omitempty"` - ParentGasLimit uint64 `json:"parentGasLimit,omitempty"` - GasLimit uint64 `json:"currentGasLimit" gencodec:"required"` - Number uint64 `json:"currentNumber" gencodec:"required"` - Timestamp uint64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp uint64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *big.Int `json:"currentBaseFee,omitempty"` - ParentUncleHash common.Hash `json:"parentUncleHash"` + Coinbase common.Address `json:"currentCoinbase" gencodec:"required"` + Difficulty *big.Int `json:"currentDifficulty"` + Random *big.Int `json:"currentRandom"` + ParentDifficulty *big.Int `json:"parentDifficulty"` + ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"` + ParentGasUsed uint64 `json:"parentGasUsed,omitempty"` + ParentGasLimit uint64 `json:"parentGasLimit,omitempty"` + ParentExcessDataGas *big.Int `json:"parentExcessDataGas,omitempty"` + GasLimit uint64 `json:"currentGasLimit" gencodec:"required"` + Number uint64 `json:"currentNumber" gencodec:"required"` + Timestamp uint64 `json:"currentTimestamp" gencodec:"required"` + ParentTimestamp uint64 `json:"parentTimestamp,omitempty"` + BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` + Ommers []ommer `json:"ommers,omitempty"` + Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` + BaseFee *big.Int `json:"currentBaseFee,omitempty"` + ParentUncleHash common.Hash `json:"parentUncleHash"` } type stEnvMarshaling struct { - Coinbase common.UnprefixedAddress - Difficulty *math.HexOrDecimal256 - Random *math.HexOrDecimal256 - ParentDifficulty *math.HexOrDecimal256 - ParentBaseFee *math.HexOrDecimal256 - ParentGasUsed math.HexOrDecimal64 - ParentGasLimit math.HexOrDecimal64 - GasLimit math.HexOrDecimal64 - Number math.HexOrDecimal64 - Timestamp math.HexOrDecimal64 - ParentTimestamp math.HexOrDecimal64 - BaseFee *math.HexOrDecimal256 + Coinbase common.UnprefixedAddress + Difficulty *math.HexOrDecimal256 + Random *math.HexOrDecimal256 + ParentDifficulty *math.HexOrDecimal256 + ParentBaseFee *math.HexOrDecimal256 + ParentGasUsed math.HexOrDecimal64 + ParentGasLimit math.HexOrDecimal64 + ParentExcessDataGas *math.HexOrDecimal256 + GasLimit math.HexOrDecimal64 + Number math.HexOrDecimal64 + Timestamp math.HexOrDecimal64 + ParentTimestamp math.HexOrDecimal64 + BaseFee *math.HexOrDecimal256 } type rejectedTx struct { @@ -125,7 +128,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, } var ( statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre) - signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number)) + signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) gaspool = new(core.GasPool) blockHash = common.Hash{0x13, 0x37} rejectedTxs []*rejectedTx @@ -134,7 +137,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, receipts = make(types.Receipts, 0) txIndex = 0 ) + // TODO(4844): Add DataGasLimit to prestate gaspool.AddGas(pre.Env.GasLimit) + gaspool.AddDataGas(params.MaxDataGasPerBlock) vmContext := vm.BlockContext{ CanTransfer: core.CanTransfer, Transfer: core.Transfer, @@ -154,6 +159,14 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, rnd := common.BigToHash(pre.Env.Random) vmContext.Random = &rnd } + // If excess data gas is defined, add it to vmContext + if chainConfig.IsCancun(pre.Env.Timestamp) { + if pre.Env.ParentExcessDataGas != nil { + vmContext.ExcessDataGas = pre.Env.ParentExcessDataGas + } else { + vmContext.ExcessDataGas = big.NewInt(0) + } + } // If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's // done in StateProcessor.Process(block, ...), right before transactions are applied. if chainConfig.DAOForkSupport && @@ -163,7 +176,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, } for i, tx := range txs { - msg, err := tx.AsMessage(signer, pre.Env.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee) + if tx.Type() == types.BlobTxType && len(tx.DataHashes()) == 0 { + err = fmt.Errorf("blob transaction with zero blobs") + } if err != nil { log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) @@ -176,16 +192,23 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, vmConfig.Tracer = tracer vmConfig.Debug = (tracer != nil) statedb.SetTxContext(tx.Hash(), txIndex) - txContext := core.NewEVMTxContext(msg) - snapshot := statedb.Snapshot() + + var ( + txContext = core.NewEVMTxContext(msg) + snapshot = statedb.Snapshot() + prevGas = gaspool.Gas() + prevDataGas = gaspool.DataGas() + ) evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) // (ret []byte, usedGas uint64, failed bool, err error) msgResult, err := core.ApplyMessage(evm, msg, gaspool) if err != nil { statedb.RevertToSnapshot(snapshot) - log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) + log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) + gaspool.SetGas(prevGas) + gaspool.SetDataGas(prevDataGas) continue } includedTxs = append(includedTxs, tx) @@ -215,7 +238,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, receipt.GasUsed = msgResult.UsedGas // If the transaction created a contract, store the creation address in the receipt. - if msg.To() == nil { + if msg.To == nil { receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce()) } @@ -284,6 +307,16 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil)) execRs.WithdrawalsRoot = &h } + if vmContext.ExcessDataGas != nil { + // calculate and set the excess data gas at the end of this block execution + newBlobs := 0 + for _, tx := range txs { + if tx.Type() == types.BlobTxType { + newBlobs += len(tx.DataHashes()) + } + } + execRs.ExcessDataGas = (*math.HexOrDecimal256)(misc.CalcExcessDataGas(vmContext.ExcessDataGas, newBlobs)) + } return statedb, execRs, nil } diff --git a/cmd/evm/internal/t8ntool/gen_header.go b/cmd/evm/internal/t8ntool/gen_header.go index 76228394dc1..310fafae927 100644 --- a/cmd/evm/internal/t8ntool/gen_header.go +++ b/cmd/evm/internal/t8ntool/gen_header.go @@ -35,6 +35,7 @@ func (h header) MarshalJSON() ([]byte, error) { Nonce *types.BlockNonce `json:"nonce"` BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ExcessDataGas *math.HexOrDecimal256 `json:"excessDataGas" rlp:"optional"` } var enc header enc.ParentHash = h.ParentHash @@ -54,6 +55,7 @@ func (h header) MarshalJSON() ([]byte, error) { enc.Nonce = h.Nonce enc.BaseFee = (*math.HexOrDecimal256)(h.BaseFee) enc.WithdrawalsHash = h.WithdrawalsHash + enc.ExcessDataGas = (*math.HexOrDecimal256)(h.ExcessDataGas) return json.Marshal(&enc) } @@ -77,6 +79,7 @@ func (h *header) UnmarshalJSON(input []byte) error { Nonce *types.BlockNonce `json:"nonce"` BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ExcessDataGas *math.HexOrDecimal256 `json:"excessDataGas" rlp:"optional"` } var dec header if err := json.Unmarshal(input, &dec); err != nil { @@ -137,5 +140,8 @@ func (h *header) UnmarshalJSON(input []byte) error { if dec.WithdrawalsHash != nil { h.WithdrawalsHash = dec.WithdrawalsHash } + if dec.ExcessDataGas != nil { + h.ExcessDataGas = (*big.Int)(dec.ExcessDataGas) + } return nil } diff --git a/cmd/evm/internal/t8ntool/gen_stenv.go b/cmd/evm/internal/t8ntool/gen_stenv.go index c2cc3a2c8a3..e0dbd902cf2 100644 --- a/cmd/evm/internal/t8ntool/gen_stenv.go +++ b/cmd/evm/internal/t8ntool/gen_stenv.go @@ -17,22 +17,23 @@ var _ = (*stEnvMarshaling)(nil) // MarshalJSON marshals as JSON. func (s stEnv) MarshalJSON() ([]byte, error) { type stEnv struct { - Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` - Random *math.HexOrDecimal256 `json:"currentRandom"` - ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` - ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` - ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` - ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` - GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` - ParentUncleHash common.Hash `json:"parentUncleHash"` + Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` + Random *math.HexOrDecimal256 `json:"currentRandom"` + ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` + ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` + ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` + ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` + ParentExcessDataGas *math.HexOrDecimal256 `json:"parentExcessDataGas,omitempty"` + GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` + Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` + Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` + ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` + BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` + Ommers []ommer `json:"ommers,omitempty"` + Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` + BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` + ParentUncleHash common.Hash `json:"parentUncleHash"` } var enc stEnv enc.Coinbase = common.UnprefixedAddress(s.Coinbase) @@ -42,6 +43,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) { enc.ParentBaseFee = (*math.HexOrDecimal256)(s.ParentBaseFee) enc.ParentGasUsed = math.HexOrDecimal64(s.ParentGasUsed) enc.ParentGasLimit = math.HexOrDecimal64(s.ParentGasLimit) + enc.ParentExcessDataGas = (*math.HexOrDecimal256)(s.ParentExcessDataGas) enc.GasLimit = math.HexOrDecimal64(s.GasLimit) enc.Number = math.HexOrDecimal64(s.Number) enc.Timestamp = math.HexOrDecimal64(s.Timestamp) @@ -57,22 +59,23 @@ func (s stEnv) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (s *stEnv) UnmarshalJSON(input []byte) error { type stEnv struct { - Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` - Random *math.HexOrDecimal256 `json:"currentRandom"` - ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` - ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` - ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` - ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` - GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` - ParentUncleHash *common.Hash `json:"parentUncleHash"` + Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` + Random *math.HexOrDecimal256 `json:"currentRandom"` + ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` + ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` + ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` + ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` + ParentExcessDataGas *math.HexOrDecimal256 `json:"parentExcessDataGas,omitempty"` + GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` + Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` + Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` + ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` + BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` + Ommers []ommer `json:"ommers,omitempty"` + Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` + BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` + ParentUncleHash *common.Hash `json:"parentUncleHash"` } var dec stEnv if err := json.Unmarshal(input, &dec); err != nil { @@ -100,6 +103,9 @@ func (s *stEnv) UnmarshalJSON(input []byte) error { if dec.ParentGasLimit != nil { s.ParentGasLimit = uint64(*dec.ParentGasLimit) } + if dec.ParentExcessDataGas != nil { + s.ParentExcessDataGas = (*big.Int)(dec.ParentExcessDataGas) + } if dec.GasLimit == nil { return errors.New("missing required field 'currentGasLimit' for stEnv") } diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 21279e8f0a8..b1f65815b72 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -112,7 +112,7 @@ func Transaction(ctx *cli.Context) error { return NewError(ErrorIO, errors.New("only rlp supported")) } } - signer := types.MakeSigner(chainConfig, new(big.Int)) + signer := types.MakeSigner(chainConfig, new(big.Int), 0) // We now have the transactions in 'body', which is supposed to be an // rlp list of transactions it, err := rlp.NewListIterator([]byte(body)) diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index cb7466d86ca..f1139cba571 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -241,7 +241,7 @@ func Transition(ctx *cli.Context) error { } } // We may have to sign the transactions. - signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number))) + signer := types.LatestSignerForChainID(chainConfig.ChainID) if txs, err = signUnsignedTransactions(txsWithKeys, signer); err != nil { return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err)) diff --git a/cmd/evm/testdata/10/readme.md b/cmd/evm/testdata/10/readme.md index c34be80bb71..afa37872381 100644 --- a/cmd/evm/testdata/10/readme.md +++ b/cmd/evm/testdata/10/readme.md @@ -9,71 +9,77 @@ INFO [05-09|22:11:59.436] rejected tx index=3 hash= Output: ```json { - "alloc": { - "0x1111111111111111111111111111111111111111": { - "code": "0xfe", - "balance": "0x10000000000", - "nonce": "0x1" + "alloc": { + "0x1111111111111111111111111111111111111111": { + "code": "0xfe", + "balance": "0x10000000000", + "nonce": "0x1" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x10000000000", + "nonce": "0x1" + }, + "0xd02d72e067e77158444ef2020ff2d325f929b363": { + "balance": "0xff5beffffc95", + "nonce": "0x4" + } }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x10000000000", - "nonce": "0x1" - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "balance": "0xff5beffffc95", - "nonce": "0x4" - } - }, - "result": { - "stateRoot": "0xf91a7ec08e4bfea88719aab34deabb000c86902360532b52afa9599d41f2bb8b", - "txRoot": "0xda925f2306a52fa24c15d5cd212d736ee016415fd8dd0c45fd368de7917d64bb", - "receiptRoot": "0x439a25f7fc424c10fb1f89800e4aa1df74156b137239d9ac3eaa7c911c353cd5", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x10000001", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x88980f6efcc5358d9c359663e7b9414722d430497637340ea056b076bc206701", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x10000001", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - }, - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x20000001", + "result": { + "stateRoot": "0xf91a7ec08e4bfea88719aab34deabb000c86902360532b52afa9599d41f2bb8b", + "txRoot": "0xda925f2306a52fa24c15d5cd212d736ee016415fd8dd0c45fd368de7917d64bb", + "receiptsRoot": "0x439a25f7fc424c10fb1f89800e4aa1df74156b137239d9ac3eaa7c911c353cd5", + "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0xd7bf3886f4e2aef74d525ae072c680f3846f550254401b67cbfda4a233757582", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x10000000", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x1" - }, - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x30000001", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x50308296760f01f1eeec7500e9e73cad67469249b1f59e9a9f55e6625a4923db", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x10000000", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x2" - } - ], - "rejected": [ - 3 - ] - } + "receipts": [ + { + "type": "0x2", + "root": "0x", + "status": "0x0", + "cumulativeGasUsed": "0x10000001", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": null, + "transactionHash": "0x88980f6efcc5358d9c359663e7b9414722d430497637340ea056b076bc206701", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x10000001", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0" + }, + { + "type": "0x2", + "root": "0x", + "status": "0x0", + "cumulativeGasUsed": "0x20000001", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": null, + "transactionHash": "0xd7bf3886f4e2aef74d525ae072c680f3846f550254401b67cbfda4a233757582", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x10000000", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x1" + }, + { + "type": "0x2", + "root": "0x", + "status": "0x0", + "cumulativeGasUsed": "0x30000001", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": null, + "transactionHash": "0x50308296760f01f1eeec7500e9e73cad67469249b1f59e9a9f55e6625a4923db", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x10000000", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x2" + } + ], + "rejected": [ + { + "index": 3, + "error": "gas limit reached" + } + ], + "currentDifficulty": "0x20000", + "gasUsed": "0x30000001", + "currentBaseFee": "0x36b" + } } ``` diff --git a/cmd/evm/testdata/12/readme.md b/cmd/evm/testdata/12/readme.md index b0177ecc24b..e3195be48ba 100644 --- a/cmd/evm/testdata/12/readme.md +++ b/cmd/evm/testdata/12/readme.md @@ -11,29 +11,32 @@ dir=./testdata/12 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json With the fix applied, the result is: ``` dir=./testdata/12 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout --output.result=stdout -INFO [07-21|19:03:50.276] rejected tx index=0 hash=ccc996..d83435 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032" -INFO [07-21|19:03:50.276] Trie dumping started root=e05f81..6597a5 -INFO [07-21|19:03:50.276] Trie dumping complete accounts=1 elapsed="39.549µs" +INFO [03-09|10:43:12.649] rejected tx index=0 hash=ccc996..d83435 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032" +INFO [03-09|10:43:12.650] Trie dumping started root=e05f81..6597a5 +INFO [03-09|10:43:12.650] Trie dumping complete accounts=1 elapsed="46.393µs" { - "alloc": { - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x501bd00" + "alloc": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x501bd00" + } + }, + "result": { + "stateRoot": "0xe05f81f8244a76503ceec6f88abfcd03047a612a1001217f37d30984536597a5", + "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "receipts": [], + "rejected": [ + { + "index": 0, + "error": "insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032" + } + ], + "currentDifficulty": "0x20000", + "gasUsed": "0x0", + "currentBaseFee": "0x20" } - }, - "result": { - "stateRoot": "0xe05f81f8244a76503ceec6f88abfcd03047a612a1001217f37d30984536597a5", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "rejected": [ - { - "index": 0, - "error": "insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032" - } - ] - } } ``` diff --git a/cmd/evm/testdata/14/readme.md b/cmd/evm/testdata/14/readme.md index 9d0dc9569c6..40dd75486ee 100644 --- a/cmd/evm/testdata/14/readme.md +++ b/cmd/evm/testdata/14/readme.md @@ -5,36 +5,40 @@ This test shows how the `evm t8n` can be used to calculate the (ethash) difficul Calculating it (with an empty set of txs) using `London` rules (and no provided unclehash for the parent block): ``` [user@work evm]$ ./evm t8n --input.alloc=./testdata/14/alloc.json --input.txs=./testdata/14/txs.json --input.env=./testdata/14/env.json --output.result=stdout --state.fork=London -INFO [08-30|20:43:09.352] Trie dumping started root=6f0588..7f4bdc -INFO [08-30|20:43:09.352] Trie dumping complete accounts=2 elapsed="82.533µs" -INFO [08-30|20:43:09.352] Wrote file file=alloc.json +INFO [03-09|10:43:57.070] Trie dumping started root=6f0588..7f4bdc +INFO [03-09|10:43:57.070] Trie dumping complete accounts=2 elapsed="214.663µs" +INFO [03-09|10:43:57.071] Wrote file file=alloc.json { "result": { "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "receipts": [], - "currentDifficulty": "0x2000020000000" + "currentDifficulty": "0x2000020000000", + "gasUsed": "0x0", + "currentBaseFee": "0x500" } } ``` Same thing, but this time providing a non-empty (and non-`emptyKeccak`) unclehash, which leads to a slightly different result: ``` [user@work evm]$ ./evm t8n --input.alloc=./testdata/14/alloc.json --input.txs=./testdata/14/txs.json --input.env=./testdata/14/env.uncles.json --output.result=stdout --state.fork=London -INFO [08-30|20:44:33.102] Trie dumping started root=6f0588..7f4bdc -INFO [08-30|20:44:33.102] Trie dumping complete accounts=2 elapsed="72.91µs" -INFO [08-30|20:44:33.102] Wrote file file=alloc.json +INFO [03-09|10:44:20.511] Trie dumping started root=6f0588..7f4bdc +INFO [03-09|10:44:20.511] Trie dumping complete accounts=2 elapsed="184.319µs" +INFO [03-09|10:44:20.512] Wrote file file=alloc.json { "result": { "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "receipts": [], - "currentDifficulty": "0x1ff8020000000" + "currentDifficulty": "0x1ff8020000000", + "gasUsed": "0x0", + "currentBaseFee": "0x500" } } ``` diff --git a/cmd/evm/testdata/19/readme.md b/cmd/evm/testdata/19/readme.md index 095d4525d4f..9c7c4b3656b 100644 --- a/cmd/evm/testdata/19/readme.md +++ b/cmd/evm/testdata/19/readme.md @@ -6,4 +6,20 @@ this time on `GrayGlacier` (Eip 5133). Calculating it (with an empty set of txs) using `GrayGlacier` rules (and no provided unclehash for the parent block): ``` [user@work evm]$ ./evm t8n --input.alloc=./testdata/19/alloc.json --input.txs=./testdata/19/txs.json --input.env=./testdata/19/env.json --output.result=stdout --state.fork=GrayGlacier +INFO [03-09|10:45:26.777] Trie dumping started root=6f0588..7f4bdc +INFO [03-09|10:45:26.777] Trie dumping complete accounts=2 elapsed="176.471µs" +INFO [03-09|10:45:26.777] Wrote file file=alloc.json +{ + "result": { + "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", + "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "receipts": [], + "currentDifficulty": "0x2000000004000", + "gasUsed": "0x0", + "currentBaseFee": "0x500" + } +} ``` \ No newline at end of file diff --git a/cmd/evm/testdata/7/readme.md b/cmd/evm/testdata/7/readme.md index c9826e0ba67..59e0dbef99b 100644 --- a/cmd/evm/testdata/7/readme.md +++ b/cmd/evm/testdata/7/readme.md @@ -3,5 +3,373 @@ DAO-transition works Example: ``` -./statet8n --input.alloc=./testdata/7/alloc.json --input.txs=./testdata/7/txs.json --input.env=./testdata/7/env.json --output.alloc=stdout --state.fork=HomesteadToDaoAt5 + ./evm t8n --input.alloc=./testdata/7/alloc.json --input.txs=./testdata/7/txs.json --input.env=./testdata/7/env.json --output.alloc=stdout --state.fork=HomesteadToDaoAt5 +INFO [03-09|10:47:37.255] Trie dumping started root=157847..2891b7 +INFO [03-09|10:47:37.256] Trie dumping complete accounts=120 elapsed="715.635µs" +INFO [03-09|10:47:37.256] Wrote file file=result.json +{ + "alloc": { + "0x005f5cee7a43331d5a3d3eec71305925a62f34b6": { + "balance": "0x0" + }, + "0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9": { + "balance": "0x0" + }, + "0x057b56736d32b86616a10f619859c6cd6f59092a": { + "balance": "0x0" + }, + "0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936": { + "balance": "0x0" + }, + "0x0737a6b837f97f46ebade41b9bc3e1c509c85c53": { + "balance": "0x0" + }, + "0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a": { + "balance": "0x0" + }, + "0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d": { + "balance": "0x0" + }, + "0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00": { + "balance": "0x0" + }, + "0x12e626b0eebfe86a56d633b9864e389b45dcb260": { + "balance": "0x0" + }, + "0x1591fc0f688c81fbeb17f5426a162a7024d430c2": { + "balance": "0x0" + }, + "0x17802f43a0137c506ba92291391a8a8f207f487d": { + "balance": "0x0" + }, + "0x1975bd06d486162d5dc297798dfc41edd5d160a7": { + "balance": "0x0" + }, + "0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b": { + "balance": "0x0" + }, + "0x1cba23d343a983e9b5cfd19496b9a9701ada385f": { + "balance": "0x0" + }, + "0x200450f06520bdd6c527622a273333384d870efb": { + "balance": "0x0" + }, + "0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241": { + "balance": "0x0" + }, + "0x23b75c2f6791eef49c69684db4c6c1f93bf49a50": { + "balance": "0x0" + }, + "0x24c4d950dfd4dd1902bbed3508144a54542bba94": { + "balance": "0x0" + }, + "0x253488078a4edf4d6f42f113d1e62836a942cf1a": { + "balance": "0x0" + }, + "0x27b137a85656544b1ccb5a0f2e561a5703c6a68f": { + "balance": "0x0" + }, + "0x2a5ed960395e2a49b1c758cef4aa15213cfd874c": { + "balance": "0x0" + }, + "0x2b3455ec7fedf16e646268bf88846bd7a2319bb2": { + "balance": "0x0" + }, + "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f": { + "balance": "0x0" + }, + "0x304a554a310c7e546dfe434669c62820b7d83490": { + "balance": "0x0" + }, + "0x319f70bab6845585f412ec7724b744fec6095c85": { + "balance": "0x0" + }, + "0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b": { + "balance": "0x0" + }, + "0x3ba4d81db016dc2890c81f3acec2454bff5aada5": { + "balance": "0x0" + }, + "0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5": { + "balance": "0x0" + }, + "0x40b803a9abce16f50f36a77ba41180eb90023925": { + "balance": "0x0" + }, + "0x440c59b325d2997a134c2c7c60a8c61611212bad": { + "balance": "0x0" + }, + "0x4486a3d68fac6967006d7a517b889fd3f98c102b": { + "balance": "0x0" + }, + "0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a": { + "balance": "0x0" + }, + "0x47e7aa56d6bdf3f36be34619660de61275420af8": { + "balance": "0x0" + }, + "0x4863226780fe7c0356454236d3b1c8792785748d": { + "balance": "0x0" + }, + "0x492ea3bb0f3315521c31f273e565b868fc090f17": { + "balance": "0x0" + }, + "0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c": { + "balance": "0x0" + }, + "0x4deb0033bb26bc534b197e61d19e0733e5679784": { + "balance": "0x0" + }, + "0x4fa802324e929786dbda3b8820dc7834e9134a2a": { + "balance": "0x0" + }, + "0x4fd6ace747f06ece9c49699c7cabc62d02211f75": { + "balance": "0x0" + }, + "0x51e0ddd9998364a2eb38588679f0d2c42653e4a6": { + "balance": "0x0" + }, + "0x52c5317c848ba20c7504cb2c8052abd1fde29d03": { + "balance": "0x0" + }, + "0x542a9515200d14b68e934e9830d91645a980dd7a": { + "balance": "0x0" + }, + "0x5524c55fb03cf21f549444ccbecb664d0acad706": { + "balance": "0x0" + }, + "0x579a80d909f346fbfb1189493f521d7f48d52238": { + "balance": "0x0" + }, + "0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb": { + "balance": "0x0" + }, + "0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5": { + "balance": "0x0" + }, + "0x5c8536898fbb74fc7445814902fd08422eac56d0": { + "balance": "0x0" + }, + "0x5d2b2e6fcbe3b11d26b525e085ff818dae332479": { + "balance": "0x0" + }, + "0x5dc28b15dffed94048d73806ce4b7a4612a1d48f": { + "balance": "0x0" + }, + "0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c": { + "balance": "0x0" + }, + "0x6131c42fa982e56929107413a9d526fd99405560": { + "balance": "0x0" + }, + "0x6231b6d0d5e77fe001c2a460bd9584fee60d409b": { + "balance": "0x0" + }, + "0x627a0a960c079c21c34f7612d5d230e01b4ad4c7": { + "balance": "0x0" + }, + "0x63ed5a272de2f6d968408b4acb9024f4cc208ebf": { + "balance": "0x0" + }, + "0x6966ab0d485353095148a2155858910e0965b6f9": { + "balance": "0x0" + }, + "0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb": { + "balance": "0x0" + }, + "0x6d87578288b6cb5549d5076a207456a1f6a63dc0": { + "balance": "0x0" + }, + "0x6f6704e5a10332af6672e50b3d9754dc460dfa4d": { + "balance": "0x0" + }, + "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97": { + "balance": "0x0" + }, + "0x779543a0491a837ca36ce8c635d6154e3c4911a6": { + "balance": "0x0" + }, + "0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6": { + "balance": "0x0" + }, + "0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4": { + "balance": "0x0" + }, + "0x807640a13483f8ac783c557fcdf27be11ea4ac7a": { + "balance": "0x0" + }, + "0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd": { + "balance": "0x0" + }, + "0x84ef4b2357079cd7a7c69fd7a37cd0609a679106": { + "balance": "0x0" + }, + "0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915": { + "balance": "0x0" + }, + "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { + "balance": "0xfeedbead" + }, + "0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6": { + "balance": "0x0" + }, + "0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79": { + "balance": "0x0" + }, + "0x97f43a37f595ab5dd318fb46e7a155eae057317a": { + "balance": "0x0" + }, + "0x9aa008f65de0b923a2a4f02012ad034a5e2e2192": { + "balance": "0x0" + }, + "0x9c15b54878ba618f494b38f0ae7443db6af648ba": { + "balance": "0x0" + }, + "0x9c50426be05db97f5d64fc54bf89eff947f0a321": { + "balance": "0x0" + }, + "0x9da397b9e80755301a3b32173283a91c0ef6c87e": { + "balance": "0x0" + }, + "0x9ea779f907f0b315b364b0cfc39a0fde5b02a416": { + "balance": "0x0" + }, + "0x9f27daea7aca0aa0446220b98d028715e3bc803d": { + "balance": "0x0" + }, + "0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339": { + "balance": "0x0" + }, + "0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7": { + "balance": "0x0" + }, + "0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6": { + "balance": "0x0" + }, + "0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90": { + "balance": "0x0" + }, + "0xa82f360a8d3455c5c41366975bde739c37bfeb8a": { + "balance": "0x0" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x5ffd4878be161d74", + "nonce": "0xac" + }, + "0xac1ecab32727358dba8962a0f3b261731aad9723": { + "balance": "0x0" + }, + "0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6": { + "balance": "0x0" + }, + "0xacd87e28b0c9d1254e868b81cba4cc20d9a32225": { + "balance": "0x0" + }, + "0xadf80daec7ba8dcf15392f1ac611fff65d94f880": { + "balance": "0x0" + }, + "0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c": { + "balance": "0x0" + }, + "0xb136707642a4ea12fb4bae820f03d2562ebff487": { + "balance": "0x0" + }, + "0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e": { + "balance": "0x0" + }, + "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425": { + "balance": "0x0" + }, + "0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab": { + "balance": "0x0" + }, + "0xb9637156d330c0d605a791f1c31ba5890582fe1c": { + "balance": "0x0" + }, + "0xbb9bc244d798123fde783fcc1c72d3bb8c189413": { + "balance": "0x0" + }, + "0xbc07118b9ac290e4622f5e77a0853539789effbe": { + "balance": "0x0" + }, + "0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76": { + "balance": "0x0" + }, + "0xbe8539bfe837b67d1282b2b1d61c3f723966f049": { + "balance": "0x0" + }, + "0xbf4ed7b27f1d666546e30d74d50d173d20bca754": { + "balance": "0x0" + }, + "0xc4bbd073882dd2add2424cf47d35213405b01324": { + "balance": "0x0" + }, + "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x0" + }, + "0xca544e5c4687d109611d0f8f928b53a25af72448": { + "balance": "0x0" + }, + "0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7": { + "balance": "0x0" + }, + "0xcc34673c6c40e791051898567a1222daf90be287": { + "balance": "0x0" + }, + "0xceaeb481747ca6c540a000c1f3641f8cef161fa7": { + "balance": "0x0" + }, + "0xd131637d5275fd1a68a3200f4ad25c71a2a9522e": { + "balance": "0x0" + }, + "0xd164b088bd9108b60d0ca3751da4bceb207b0782": { + "balance": "0x0" + }, + "0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091": { + "balance": "0x0" + }, + "0xd343b217de44030afaa275f54d31a9317c7f441e": { + "balance": "0x0" + }, + "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728": { + "balance": "0x0" + }, + "0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b": { + "balance": "0x0" + }, + "0xda2fef9e4a3230988ff17df2165440f37e8b1708": { + "balance": "0x0" + }, + "0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940": { + "balance": "0x0" + }, + "0xe308bd1ac5fda103967359b2712dd89deffb7973": { + "balance": "0x0" + }, + "0xe4ae1efdfc53b73893af49113d8694a057b9c0d1": { + "balance": "0x0" + }, + "0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5": { + "balance": "0x0" + }, + "0xecd135fa4f61a655311e86238c92adcd779555d2": { + "balance": "0x0" + }, + "0xf0b1aa0eb660754448a7937c022e30aa692fe0c5": { + "balance": "0x0" + }, + "0xf1385fb24aad0cd7432824085e42aff90886fef5": { + "balance": "0x0" + }, + "0xf14c14075d6c4ed84b86798af0956deef67365b5": { + "balance": "0x0" + }, + "0xf4c64518ea10f995918a454158c6b61407ea345c": { + "balance": "0x0" + }, + "0xfe24cdd8648121a43a7c86d289be4dd2951ed49f": { + "balance": "0x0" + } + } +} ``` \ No newline at end of file diff --git a/cmd/evm/testdata/8/readme.md b/cmd/evm/testdata/8/readme.md index e021cd7e2ee..c991fb21779 100644 --- a/cmd/evm/testdata/8/readme.md +++ b/cmd/evm/testdata/8/readme.md @@ -23,41 +23,37 @@ There are three transactions, each invokes the contract above. Running it yields: ``` -dir=./testdata/8 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --trace && cat trace-* | grep SLOAD -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x3"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x3"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memory":"0x","memSize":0,"stack":["0x3"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} - +dir=./testdata/8 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --trace 2>/dev/null && cat trace-* | grep SLOAD +{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} ``` Simlarly, we can provide the input transactions via `stdin` instead of as file: ``` -dir=./testdata/8 \ +$ dir=./testdata/8 \ && cat $dir/txs.json | jq "{txs: .}" \ | ./evm t8n --state.fork=Berlin \ --input.alloc=$dir/alloc.json \ --input.txs=stdin \ --input.env=$dir/env.json \ --trace \ + 2>/dev/null \ && cat trace-* | grep SLOAD - -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x3"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x3"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memory":"0x","memSize":0,"stack":["0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memory":"0x","memSize":0,"stack":["0x3"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} +{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} ``` If we try to execute it on older rules: ``` -dir=./testdata/8 && ./evm t8n --state.fork=Istanbul --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json -INFO [01-21|23:21:51.265] rejected tx index=0 hash=d2818d..6ab3da error="tx type not supported" -INFO [01-21|23:21:51.265] rejected tx index=1 hash=26ea00..81c01b from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="nonce too high: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B, tx: 1 state: 0" -INFO [01-21|23:21:51.265] rejected tx index=2 hash=698d01..369cee error="tx type not supported" +$ dir=./testdata/8 && ./evm t8n --state.fork=Istanbul --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json +ERROR(10): failed signing transactions: ERROR(10): tx 0: failed to sign tx: transaction type not supported ``` -Number `1` and `3` are not applicable, and therefore number `2` has wrong nonce. \ No newline at end of file diff --git a/cmd/evm/testdata/9/env.json b/cmd/evm/testdata/9/env.json index ec5164b9952..082bff778a3 100644 --- a/cmd/evm/testdata/9/env.json +++ b/cmd/evm/testdata/9/env.json @@ -1,7 +1,7 @@ { "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty": "0x20000", - "currentGasTarget": "0x1000000000", + "currentGasLimit": "0x1000000000", "currentBaseFee": "0x3B9ACA00", "currentNumber": "0x1000000", "currentTimestamp": "0x04" diff --git a/cmd/evm/testdata/9/readme.md b/cmd/evm/testdata/9/readme.md index 88f0f12aaaa..b1446446554 100644 --- a/cmd/evm/testdata/9/readme.md +++ b/cmd/evm/testdata/9/readme.md @@ -22,35 +22,37 @@ There are two transactions, each invokes the contract above. Running it yields: ``` -$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --trace && cat trace-* | grep SLOAD -{"pc":2,"op":84,"gas":"0x48c28","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0","0x1"],"returnStack":null,"returnD -ata":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":3,"op":84,"gas":"0x483f4","gasCost":"0x64","memory":"0x","memSize":0,"stack":["0x0","0x0"],"returnStack":null,"returnDa -ta":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":2,"op":84,"gas":"0x49cf4","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0","0x1"],"returnStack":null,"returnD -ata":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} -{"pc":3,"op":84,"gas":"0x494c0","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0","0x0"],"returnStack":null,"returnD -ata":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""} +$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --trace 2>/dev/null && cat trace-* | grep SLOAD +{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":2,"op":84,"gas":"0x48c28","gasCost":"0x834","memSize":0,"stack":["0x0","0x1"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":3,"op":84,"gas":"0x483f4","gasCost":"0x64","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":2,"op":84,"gas":"0x49cf4","gasCost":"0x834","memSize":0,"stack":["0x0","0x1"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":3,"op":84,"gas":"0x494c0","gasCost":"0x834","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} +{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} ``` We can also get the post-alloc: ``` -$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout +$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout 2>/dev/null { - "alloc": { - "0x000000000000000000000000000000000000aaaa": { - "code": "0x58585454", - "balance": "0x3", - "nonce": "0x1" - }, - "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { - "balance": "0xbfc02677a000" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xff104fcfea7800", - "nonce": "0x2" + "alloc": { + "0x000000000000000000000000000000000000aaaa": { + "code": "0x58585454", + "balance": "0x3", + "nonce": "0x1" + }, + "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { + "balance": "0x5bb10ddef6e0" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0xff745ee8832120", + "nonce": "0x2" + } } - } } ``` @@ -65,10 +67,12 @@ by feeding it presigned transactions, located in `txs_signed.json`. ``` dir=./testdata/9 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs_signed.json --input.env=$dir/env.json -INFO [05-07|12:28:42.072] rejected tx index=0 hash=b4821e..536819 error="transaction type not supported" -INFO [05-07|12:28:42.072] rejected tx index=1 hash=a9c6c6..fa4036 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="nonce too high: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B, tx: 1 state: 0" -INFO [05-07|12:28:42.073] Wrote file file=alloc.json -INFO [05-07|12:28:42.073] Wrote file file=result.json +WARN [03-09|11:06:22.065] rejected tx index=0 hash=334e09..f8dce5 error="transaction type not supported" +INFO [03-09|11:06:22.066] rejected tx index=1 hash=a9c6c6..fa4036 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="nonce too high: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B, tx: 1 state: 0" +INFO [03-09|11:06:22.066] Trie dumping started root=6eebe9..a0fda5 +INFO [03-09|11:06:22.066] Trie dumping complete accounts=2 elapsed="55.844µs" +INFO [03-09|11:06:22.066] Wrote file file=alloc.json +INFO [03-09|11:06:22.066] Wrote file file=result.json ``` Number `0` is not applicable, and therefore number `1` has wrong nonce, and both are rejected. diff --git a/cmd/evm/testdata/9/txs_signed.json b/cmd/evm/testdata/9/txs_signed.json new file mode 100644 index 00000000000..dcddf011b44 --- /dev/null +++ b/cmd/evm/testdata/9/txs_signed.json @@ -0,0 +1,37 @@ +[ + { + "gas": "0x4ef00", + "maxFeePerGas": "0x2", + "maxPriorityFeePerGas": "0x12A05F200", + "chainId": "0x1", + "input": "0x", + "nonce": "0x0", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "type" : "0x2", + "accessList": [ + {"address": "0x000000000000000000000000000000000000aaaa", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xd77c8ff989789b5d9d99254cbae2e2996dc7e6215cba4d55254c14e6d6b9f314", + "s": "0x5cc021481e7e6bb444bbb87ab32071e8fd0a8d1e125c7bb352d2879bd7ff5c0a", + "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + }, + { + "gas": "0x4ef00", + "gasPrice": "0x12A05F200", + "chainId": "0x1", + "input": "0x", + "nonce": "0x1", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "v": "0x25", + "r": "0xbee5ec9f6650020266bf3455a852eece2b073a2fa918c4d1836a1af69c2aa50c", + "s": "0x556c897a58dbc007a6b09814e1fba7502adb76effd2146da4365816926f387ce", + "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + } +] diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 10af6f32f49..96999075a31 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -349,8 +349,8 @@ func exportChain(ctx *cli.Context) error { if first < 0 || last < 0 { utils.Fatalf("Export error: block number must be greater than 0\n") } - if head := chain.CurrentFastBlock(); uint64(last) > head.NumberU64() { - utils.Fatalf("Export error: block number %d larger than head block %d\n", uint64(last), head.NumberU64()) + if head := chain.CurrentSnapBlock(); uint64(last) > head.Number.Uint64() { + utils.Fatalf("Export error: block number %d larger than head block %d\n", uint64(last), head.Number.Uint64()) } err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last)) } diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 61b7ed5ec1e..0b856d1c1b7 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -47,10 +47,10 @@ var ( dumpConfigCommand = &cli.Command{ Action: dumpConfig, Name: "dumpconfig", - Usage: "Show configuration values", - ArgsUsage: "", + Usage: "Export configuration values in a TOML format", + ArgsUsage: "", Flags: flags.Merge(nodeFlags, rpcFlags), - Description: `The dumpconfig command shows configuration values.`, + Description: `Export configuration values in TOML format (to stdout by default).`, } configFileFlag = &cli.StringFlag{ diff --git a/cmd/geth/consolecmd.go b/cmd/geth/consolecmd.go index 23f6fd277c6..aeee6f9c9e4 100644 --- a/cmd/geth/consolecmd.go +++ b/cmd/geth/consolecmd.go @@ -37,7 +37,7 @@ var ( 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. -See https://geth.ethereum.org/docs/interface/javascript-console.`, +See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console.`, } attachCommand = &cli.Command{ @@ -49,7 +49,7 @@ See https://geth.ethereum.org/docs/interface/javascript-console.`, 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. -See https://geth.ethereum.org/docs/interface/javascript-console. +See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console. This command allows to open a console on a running geth node.`, } @@ -61,7 +61,7 @@ This command allows to open a console on a running geth node.`, Flags: flags.Merge(nodeFlags, consoleFlags), Description: ` The JavaScript VM exposes a node admin interface as well as the Ðapp -JavaScript API. See https://geth.ethereum.org/docs/interface/javascript-console`, +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 4deb081ed8f..b409b19260e 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -694,41 +694,19 @@ func showMetaData(ctx *cli.Context) error { if err != nil { fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err) } - pp := func(val *uint64) string { - if val == nil { - return "" - } - return fmt.Sprintf("%d (%#x)", *val, *val) - } - data := [][]string{ - {"databaseVersion", pp(rawdb.ReadDatabaseVersion(db))}, - {"headBlockHash", fmt.Sprintf("%v", rawdb.ReadHeadBlockHash(db))}, - {"headFastBlockHash", fmt.Sprintf("%v", rawdb.ReadHeadFastBlockHash(db))}, - {"headHeaderHash", fmt.Sprintf("%v", rawdb.ReadHeadHeaderHash(db))}} + data := rawdb.ReadChainMetadata(db) + data = append(data, []string{"frozen", fmt.Sprintf("%d items", ancients)}) + data = append(data, []string{"snapshotGenerator", snapshot.ParseGeneratorStatus(rawdb.ReadSnapshotGenerator(db))}) if b := rawdb.ReadHeadBlock(db); b != nil { data = append(data, []string{"headBlock.Hash", fmt.Sprintf("%v", b.Hash())}) data = append(data, []string{"headBlock.Root", fmt.Sprintf("%v", b.Root())}) data = append(data, []string{"headBlock.Number", fmt.Sprintf("%d (%#x)", b.Number(), b.Number())}) } - if b := rawdb.ReadSkeletonSyncStatus(db); b != nil { - data = append(data, []string{"SkeletonSyncStatus", string(b)}) - } if h := rawdb.ReadHeadHeader(db); h != nil { data = append(data, []string{"headHeader.Hash", fmt.Sprintf("%v", h.Hash())}) data = append(data, []string{"headHeader.Root", fmt.Sprintf("%v", h.Root)}) data = append(data, []string{"headHeader.Number", fmt.Sprintf("%d (%#x)", h.Number, h.Number)}) } - data = append(data, [][]string{{"frozen", fmt.Sprintf("%d items", ancients)}, - {"lastPivotNumber", pp(rawdb.ReadLastPivotNumber(db))}, - {"len(snapshotSyncStatus)", fmt.Sprintf("%d bytes", len(rawdb.ReadSnapshotSyncStatus(db)))}, - {"snapshotGenerator", snapshot.ParseGeneratorStatus(rawdb.ReadSnapshotGenerator(db))}, - {"snapshotDisabled", fmt.Sprintf("%v", rawdb.ReadSnapshotDisabled(db))}, - {"snapshotJournal", fmt.Sprintf("%d bytes", len(rawdb.ReadSnapshotJournal(db)))}, - {"snapshotRecoveryNumber", pp(rawdb.ReadSnapshotRecoveryNumber(db))}, - {"snapshotRoot", fmt.Sprintf("%v", rawdb.ReadSnapshotRoot(db))}, - {"txIndexTail", pp(rawdb.ReadTxIndexTail(db))}, - {"fastTxLookupLimit", pp(rawdb.ReadFastTxLookupLimit(db))}, - }...) table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Field", "Value"}) table.AppendBulk(data) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 5ba07024989..a6d3aedefd6 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -205,7 +205,6 @@ var app = flags.NewApp("the go-ethereum command line interface") func init() { // Initialize the CLI app and start Geth app.Action = geth - app.HideVersion = true // we have a command to print the version app.Copyright = "Copyright 2013-2023 The go-ethereum Authors" app.Commands = []*cli.Command{ // See chaincmd.go: @@ -283,6 +282,9 @@ func prepare(ctx *cli.Context) { case ctx.IsSet(utils.SepoliaFlag.Name): log.Info("Starting Geth on Sepolia testnet...") + case ctx.IsSet(utils.Eip4844Flag.Name): + log.Info("Starting Geth on EIP4844 testnet...") + case ctx.IsSet(utils.DeveloperFlag.Name): log.Info("Starting Geth in ephemeral dev mode...") log.Warn(`You are running Geth in --dev mode. Please note the following: @@ -310,6 +312,7 @@ func prepare(ctx *cli.Context) { if !ctx.IsSet(utils.SepoliaFlag.Name) && !ctx.IsSet(utils.RinkebyFlag.Name) && !ctx.IsSet(utils.GoerliFlag.Name) && + !ctx.IsSet(utils.Eip4844Flag.Name) && !ctx.IsSet(utils.DeveloperFlag.Name) { // Nope, we're really on mainnet. Bump that cache up! log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096) diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index 7175bb953de..0759341fd96 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -38,14 +38,6 @@ import ( cli "github.com/urfave/cli/v2" ) -var ( - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // emptyCode is the known hash of the empty EVM bytecode. - emptyCode = crypto.Keccak256(nil) -) - var ( snapshotCommand = &cli.Command{ Name: "snapshot", @@ -308,7 +300,7 @@ func traverseState(ctx *cli.Context) error { log.Error("Invalid account encountered during traversal", "err", err) return err } - if acc.Root != emptyRoot { + if acc.Root != types.EmptyRootHash { id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root) storageTrie, err := trie.NewStateTrie(id, triedb) if err != nil { @@ -324,7 +316,7 @@ func traverseState(ctx *cli.Context) error { return storageIter.Err } } - if !bytes.Equal(acc.CodeHash, emptyCode) { + if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash)) return errors.New("missing code") @@ -423,7 +415,7 @@ func traverseRawState(ctx *cli.Context) error { log.Error("Invalid account encountered during traversal", "err", err) return errors.New("invalid account") } - if acc.Root != emptyRoot { + if acc.Root != types.EmptyRootHash { id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root) storageTrie, err := trie.NewStateTrie(id, triedb) if err != nil { @@ -461,7 +453,7 @@ func traverseRawState(ctx *cli.Context) error { return storageIter.Error() } } - if !bytes.Equal(acc.CodeHash, emptyCode) { + if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey())) return errors.New("missing code") @@ -536,7 +528,7 @@ func dumpState(ctx *cli.Context) error { CodeHash: account.CodeHash, SecureKey: accIt.Hash().Bytes(), } - if !conf.SkipCode && !bytes.Equal(account.CodeHash, emptyCode) { + if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash)) } if !conf.SkipStorage { diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index d1d900a6da9..e1bafc53c31 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -222,7 +222,7 @@ func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block head := chain.CurrentBlock() for i, block := range blocks { // If we're behind the chain head, only check block, state is available at head - if head.NumberU64() > block.NumberU64() { + if head.Number.Uint64() > block.NumberU64() { if !chain.HasBlock(block.Hash(), block.NumberU64()) { return blocks[i:] } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 08de71ee831..47053e1fa59 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -157,6 +157,11 @@ var ( Usage: "Sepolia network: pre-configured proof-of-work test network", Category: flags.EthCategory, } + Eip4844Flag = &cli.BoolFlag{ + Name: "eip4844", + Usage: "EIP-4844 (proto-danksharding) network: pre-configured proof-of-authority to proof-of-stake test network", + Category: flags.EthCategory, + } // Dev mode DeveloperFlag = &cli.BoolFlag{ @@ -1002,6 +1007,7 @@ var ( RinkebyFlag, GoerliFlag, SepoliaFlag, + Eip4844Flag, } // NetworkFlags is the flag group of all built-in supported networks. NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...) @@ -1035,6 +1041,9 @@ func MakeDataDir(ctx *cli.Context) string { if ctx.Bool(SepoliaFlag.Name) { return filepath.Join(path, "sepolia") } + if ctx.Bool(Eip4844Flag.Name) { + return filepath.Join(path, "eip4844") + } return path } Fatalf("Cannot determine default data directory, please set manually (--datadir)") @@ -1087,6 +1096,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls = params.RinkebyBootnodes case ctx.Bool(GoerliFlag.Name): urls = params.GoerliBootnodes + case ctx.Bool(Eip4844Flag.Name): + urls = params.Eip4844Bootnodes } // don't apply defaults if BootstrapNodes is already set @@ -1538,6 +1549,8 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli") case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir(): cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia") + case ctx.Bool(Eip4844Flag.Name) && cfg.DataDir == node.DefaultDataDir(): + cfg.DataDir = filepath.Join(node.DefaultDataDir(), "eip4844") } } @@ -1728,7 +1741,7 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) { // SetEthConfig applies eth-related command line flags to the config. func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { // Avoid conflicting network flags - CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RinkebyFlag, GoerliFlag, SepoliaFlag) + CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RinkebyFlag, GoerliFlag, SepoliaFlag, Eip4844Flag) CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light") CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { @@ -1894,6 +1907,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } cfg.Genesis = core.DefaultGoerliGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash) + case ctx.Bool(Eip4844Flag.Name): + if !ctx.IsSet(NetworkIdFlag.Name) { + cfg.NetworkId = 1331 + } + cfg.Genesis = core.DefaultEIP4844GenesisBlock() + SetDNSDiscoveryDefaults(cfg, params.Eip4844GenesisHash) case ctx.Bool(DeveloperFlag.Name): if !ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = 1337 @@ -2214,6 +2233,8 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis { genesis = core.DefaultRinkebyGenesisBlock() case ctx.Bool(GoerliFlag.Name): genesis = core.DefaultGoerliGenesisBlock() + case ctx.Bool(Eip4844Flag.Name): + genesis = core.DefaultEIP4844GenesisBlock() case ctx.Bool(DeveloperFlag.Name): Fatalf("Developer chains are ephemeral") } diff --git a/common/lru/basiclru_test.go b/common/lru/basiclru_test.go index 68e13bfc92e..e2d3559f55d 100644 --- a/common/lru/basiclru_test.go +++ b/common/lru/basiclru_test.go @@ -17,6 +17,7 @@ package lru import ( + crand "crypto/rand" "fmt" "io" "math/rand" @@ -181,9 +182,9 @@ func BenchmarkLRU(b *testing.B) { } for i := range keys { b := make([]byte, 32) - rand.Read(b) + crand.Read(b) keys[i] = string(b) - rand.Read(b) + crand.Read(b) values[i] = b } diff --git a/common/math/big.go b/common/math/big.go index 48427810e1c..1c2afa749ab 100644 --- a/common/math/big.go +++ b/common/math/big.go @@ -49,6 +49,17 @@ func NewHexOrDecimal256(x int64) *HexOrDecimal256 { return &h } +// UnmarshalJSON implements json.Unmarshaler. +// +// It is similar to UnmarshalText, but allows parsing real decimals too, not just +// quoted decimal strings. +func (i *HexOrDecimal256) UnmarshalJSON(input []byte) error { + if len(input) > 0 && input[0] == '"' { + input = input[1 : len(input)-1] + } + return i.UnmarshalText(input) +} + // UnmarshalText implements encoding.TextUnmarshaler. func (i *HexOrDecimal256) UnmarshalText(input []byte) error { bigint, ok := ParseBig256(string(input)) diff --git a/common/math/integer.go b/common/math/integer.go index 50d3eba1f57..da01c0a08e0 100644 --- a/common/math/integer.go +++ b/common/math/integer.go @@ -41,6 +41,17 @@ const ( // HexOrDecimal64 marshals uint64 as hex or decimal. type HexOrDecimal64 uint64 +// UnmarshalJSON implements json.Unmarshaler. +// +// It is similar to UnmarshalText, but allows parsing real decimals too, not just +// quoted decimal strings. +func (i *HexOrDecimal64) UnmarshalJSON(input []byte) error { + if len(input) > 0 && input[0] == '"' { + input = input[1 : len(input)-1] + } + return i.UnmarshalText(input) +} + // UnmarshalText implements encoding.TextUnmarshaler. func (i *HexOrDecimal64) UnmarshalText(input []byte) error { int, ok := ParseUint64(string(input)) diff --git a/common/math/modexp_test.go b/common/math/modexp_test.go deleted file mode 100644 index bd90076f84f..00000000000 --- a/common/math/modexp_test.go +++ /dev/null @@ -1,53 +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 math - -import ( - "math/big" - "testing" - - big2 "github.com/holiman/big" -) - -// TestFastModexp tests some cases found during fuzzing. -func TestFastModexp(t *testing.T) { - for i, tc := range []struct { - base string - exp string - mod string - }{ - {"0xeffffff900002f00", "0x40000000000000", "0x200"}, - {"0xf000", "0x4f900b400080000", "0x400000d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9ffffff005aeffd310000000000000000000000000000000000009f9f9f9f0000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000befffa5a5a5fff900002f000040000000000000000000000000000000029d9d9d000000000000009f9f9f00000000000000009f9f9f000000f3a080ab00000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f0000000000002900009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000cf000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000befffff0000c0800000000800000000000000000000000000000002000000000000009f9f9f0000000000000000008000ff000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000befffa5a5a5fff900002f000040000000000000000000000000000000029d9d9d000000000000009f9f9f00000000000000009f9f9f000000f3a080ab00000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f0000000000002900009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000beffffff900002f0000400000c100000000000000000000000000000000000000006160600000000000000000008000ff0000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f0000"}, - {"5", "1435700818", "72"}, - {"0xffff", "0x300030003000300030003000300030003000302a3000300030003000300030003000300030003000300030003000300030003030623066307f3030783062303430383064303630343036", "0x300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, - {"0x3133", "0x667f00000000000000000000000000ff002a000000000000000000000000000000000000000000000000000000000000667fff30783362773057ee756a6c266134643831646230313630", "0x3030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, - } { - var ( - base, _ = new(big.Int).SetString(tc.base, 0) - exp, _ = new(big.Int).SetString(tc.exp, 0) - mod, _ = new(big.Int).SetString(tc.mod, 0) - base2, _ = new(big2.Int).SetString(tc.base, 0) - exp2, _ = new(big2.Int).SetString(tc.exp, 0) - mod2, _ = new(big2.Int).SetString(tc.mod, 0) - ) - var a = new(big2.Int).Exp(base2, exp2, mod2).String() - var b = new(big.Int).Exp(base, exp, mod).String() - if a != b { - t.Errorf("test %d: %#x ^ %#x mod %#x \n have %x\n want %x", i, base, exp, mod, a, b) - } - } -} diff --git a/common/prque/lazyqueue_test.go b/common/prque/lazyqueue_test.go index 9a831d628b6..ffb7e5e9e38 100644 --- a/common/prque/lazyqueue_test.go +++ b/common/prque/lazyqueue_test.go @@ -56,7 +56,6 @@ func testSetIndex(a interface{}, i int) { } func TestLazyQueue(t *testing.T) { - rand.Seed(time.Now().UnixNano()) clock := &mclock.Simulated{} q := NewLazyQueue(testSetIndex, testPriority, testMaxPriority, clock, testQueueRefresh) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index eb5aa58ca88..b2c3d3f4f02 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -268,6 +268,20 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa if !shanghai && header.WithdrawalsHash != nil { return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash) } + // Verify existence / non-existence of excessDataGas. + cancun := chain.Config().IsCancun(header.Time) + if cancun { + if header.ExcessDataGas == nil { + return fmt.Errorf("missing excessDataGas") + } + // Verify the header's EIP-4844 attributes. + if err := misc.VerifyEip4844Header(chain.Config(), parent, header); err != nil { + return err + } + } + if !cancun && header.ExcessDataGas != nil { + return fmt.Errorf("invalied ExcessDataGas: have %v, expected nil", header.ExcessDataGas) + } return nil } @@ -344,6 +358,13 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. // The block reward is no longer handled here. It's done by the // external consensus engine. header.Root = state.IntermediateRoot(true) + if chain.Config().IsCancun(header.Time) { + if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil { + header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs))) + } else { + header.SetExcessDataGas(new(big.Int)) + } + } } // FinalizeAndAssemble implements consensus.Engine, setting the final state and diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 4706bbac1ca..79cb648f49b 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -348,6 +348,14 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header // Verify the header's EIP-1559 attributes. return err } + if !chain.Config().IsCancun(header.Time) { + if header.ExcessDataGas != nil { + return fmt.Errorf("invalid excessDataGas before fork: have %v, want ", header.ExcessDataGas) + } + } else if err := misc.VerifyEip4844Header(chain.Config(), parent, header); err != nil { + // Verify the header's EIP-4844 attributes. + return err + } // Retrieve the snapshot needed to verify this header and cache it snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) if err != nil { @@ -571,6 +579,13 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) + if chain.Config().IsCancun(header.Time) { + if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil { + header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs))) + } else { + header.SetExcessDataGas(new(big.Int)) + } + } } // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, @@ -753,6 +768,9 @@ func encodeSigHeader(w io.Writer, header *types.Header) { if header.WithdrawalsHash != nil { panic("unexpected withdrawal hash value in clique") } + if header.ExcessDataGas != nil { + panic("unexpected excessDataGas value in clique") + } if err := rlp.Encode(w, enc); err != nil { panic("can't encode: " + err.Error()) } diff --git a/consensus/clique/clique_test.go b/consensus/clique/clique_test.go index f213bc8247d..f2c6d740c08 100644 --- a/consensus/clique/clique_test.go +++ b/consensus/clique/clique_test.go @@ -93,7 +93,7 @@ func TestReimportMirroredState(t *testing.T) { if _, err := chain.InsertChain(blocks[:2]); err != nil { t.Fatalf("failed to insert initial blocks: %v", err) } - if head := chain.CurrentBlock().NumberU64(); head != 2 { + if head := chain.CurrentBlock().Number.Uint64(); head != 2 { t.Fatalf("chain head mismatch: have %d, want %d", head, 2) } @@ -106,7 +106,7 @@ func TestReimportMirroredState(t *testing.T) { if _, err := chain.InsertChain(blocks[2:]); err != nil { t.Fatalf("failed to insert final block: %v", err) } - if head := chain.CurrentBlock().NumberU64(); head != 3 { + if head := chain.CurrentBlock().Number.Uint64(); head != 3 { t.Fatalf("chain head mismatch: have %d, want %d", head, 3) } } diff --git a/consensus/ethash/algorithm_test.go b/consensus/ethash/algorithm_test.go index 88769d277c0..3ecd7306819 100644 --- a/consensus/ethash/algorithm_test.go +++ b/consensus/ethash/algorithm_test.go @@ -709,11 +709,11 @@ func TestConcurrentDiskCacheGeneration(t *testing.T) { block := types.NewBlockWithHeader(&types.Header{ Number: big.NewInt(3311058), ParentHash: common.HexToHash("0xd783efa4d392943503f28438ad5830b2d5964696ffc285f338585e9fe0a37a05"), - UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), + UncleHash: types.EmptyUncleHash, Coinbase: common.HexToAddress("0xc0ea08a2d404d3172d2add29a45be56da40e2949"), Root: common.HexToHash("0x77d14e10470b5850332524f8cd6f69ad21f070ce92dca33ab2858300242ef2f1"), - TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), - ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, Difficulty: big.NewInt(167925187834220), GasLimit: 4015682, GasUsed: 0, diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index da29e16597b..498eaac531a 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -306,6 +306,14 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa // Verify the header's EIP-1559 attributes. return err } + if !chain.Config().IsCancun(header.Time) { + if header.ExcessDataGas != nil { + return fmt.Errorf("invalid excessDataGas before fork: have %v, expected 'nil'", header.ExcessDataGas) + } + } else if err := misc.VerifyEip4844Header(chain.Config(), parent, header); err != nil { + // Verify the header's EIP-4844 attributes. + return err + } // Verify that the block number is parent's +1 if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { return consensus.ErrInvalidNumber @@ -604,6 +612,13 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types. // Accumulate any block and uncle rewards and commit the final state root accumulateRewards(chain.Config(), state, header, uncles) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) + if chain.Config().IsCancun(header.Time) { + if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil { + header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs))) + } else { + header.SetExcessDataGas(new(big.Int)) + } + } } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and @@ -644,6 +659,9 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) { if header.WithdrawalsHash != nil { panic("withdrawal hash set on ethash") } + if header.ExcessDataGas != nil { + panic("excessDataGas set on ethash") + } rlp.Encode(hasher, enc) hasher.Sum(hash[:0]) return hash diff --git a/consensus/ethash/consensus_test.go b/consensus/ethash/consensus_test.go index db997d737e6..e3793cd1b01 100644 --- a/consensus/ethash/consensus_test.go +++ b/consensus/ethash/consensus_test.go @@ -17,6 +17,7 @@ package ethash import ( + crand "crypto/rand" "encoding/binary" "encoding/json" "math/big" @@ -90,16 +91,15 @@ func TestCalcDifficulty(t *testing.T) { func randSlice(min, max uint32) []byte { var b = make([]byte, 4) - rand.Read(b) + crand.Read(b) a := binary.LittleEndian.Uint32(b) size := min + a%(max-min) out := make([]byte, size) - rand.Read(out) + crand.Read(out) return out } func TestDifficultyCalculators(t *testing.T) { - rand.Seed(2) for i := 0; i < 5000; i++ { // 1 to 300 seconds diff var timeDelta = uint64(1 + rand.Uint32()%3000) diff --git a/consensus/misc/eip4844.go b/consensus/misc/eip4844.go new file mode 100644 index 00000000000..41b5011d105 --- /dev/null +++ b/consensus/misc/eip4844.go @@ -0,0 +1,96 @@ +// Copyright 2021 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 misc + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" +) + +// CalcExcessDataGas implements calc_excess_data_gas from EIP-4844 +func CalcExcessDataGas(parentExcessDataGas *big.Int, newBlobs int) *big.Int { + excessDataGas := new(big.Int) + if parentExcessDataGas != nil { + excessDataGas.Set(parentExcessDataGas) + } + consumedGas := big.NewInt(params.DataGasPerBlob) + consumedGas.Mul(consumedGas, big.NewInt(int64(newBlobs))) + + excessDataGas.Add(excessDataGas, consumedGas) + targetGas := big.NewInt(params.TargetDataGasPerBlock) + if excessDataGas.Cmp(targetGas) < 0 { + return new(big.Int) + } + return new(big.Int).Set(excessDataGas.Sub(excessDataGas, targetGas)) +} + +// CountBlobs returns the number of blob transactions in txs +func CountBlobs(txs []*types.Transaction) int { + var count int + for _, tx := range txs { + count += len(tx.DataHashes()) + } + return count +} + +// VerifyEip4844Header verifies that the header is not malformed but does *not* check the value of excessDataGas. +// See VerifyExcessDataGas for the full check. +func VerifyEip4844Header(config *params.ChainConfig, parent, header *types.Header) error { + if header.ExcessDataGas == nil { + return fmt.Errorf("header is missing excessDataGas") + } + return nil +} + +// VerifyExcessDataGas verifies the excess_data_gas in the block header +func VerifyExcessDataGas(chainReader ChainReader, block *types.Block) error { + excessDataGas := block.ExcessDataGas() + if !chainReader.Config().IsCancun(block.Time()) { + if excessDataGas != nil { + return fmt.Errorf("unexpected excessDataGas in header") + } + return nil + + } + if excessDataGas == nil { + return fmt.Errorf("header is missing excessDataGas") + } + + number, parent := block.NumberU64()-1, block.ParentHash() + parentBlock := chainReader.GetBlock(parent, number) + if parentBlock == nil { + return fmt.Errorf("parent block not found") + } + numBlobs := CountBlobs(block.Transactions()) + expectedEDG := CalcExcessDataGas(parentBlock.ExcessDataGas(), numBlobs) + if excessDataGas.Cmp(expectedEDG) != 0 { + return fmt.Errorf("invalid excessDataGas: have %s want %v", excessDataGas, expectedEDG) + } + return nil +} + +// ChainReader defines a small collection of methods needed to access the local +// blockchain for EIP4844 block verifcation. +type ChainReader interface { + Config() *params.ChainConfig + // GetBlock retrieves a block from the database by hash and number. + GetBlock(hash common.Hash, number uint64) *types.Block +} diff --git a/consensus/misc/eip4844_test.go b/consensus/misc/eip4844_test.go new file mode 100644 index 00000000000..c4e2d23c3d7 --- /dev/null +++ b/consensus/misc/eip4844_test.go @@ -0,0 +1,55 @@ +// 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 misc + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/params" +) + +func TestCalcExcessDataGas(t *testing.T) { + var tests = []struct { + parentExcessDataGas int64 + newBlobs int + want int64 + }{ + {0, 0, 0}, + {0, 1, 0}, + {0, params.TargetDataGasPerBlock / params.DataGasPerBlob, 0}, + {0, (params.TargetDataGasPerBlock / params.DataGasPerBlob) + 1, params.DataGasPerBlob}, + {100000, (params.TargetDataGasPerBlock / params.DataGasPerBlob) + 1, params.DataGasPerBlob + 100000}, + {params.TargetDataGasPerBlock, 1, params.DataGasPerBlob}, + {params.TargetDataGasPerBlock, 0, 0}, + {params.TargetDataGasPerBlock, (params.TargetDataGasPerBlock / params.DataGasPerBlob), params.TargetDataGasPerBlock}, + } + + for _, tt := range tests { + parentExcessDataGas := big.NewInt(tt.parentExcessDataGas) + result := CalcExcessDataGas(parentExcessDataGas, tt.newBlobs) + if tt.want != result.Int64() { + t.Errorf("got %v want %v", result, tt.want) + } + } + + // Test nil value for parentExcessDataGas + result := CalcExcessDataGas(nil, (params.TargetDataGasPerBlock/params.DataGasPerBlob)+1) + if result.Int64() != params.DataGasPerBlob { + t.Errorf("got %v want %v", result, params.DataGasPerBlob) + } +} diff --git a/core/bench_test.go b/core/bench_test.go index 7fc8a760f70..1cb169cc930 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) { toaddr := common.Address{} data := make([]byte, nbytes) gas, _ := IntrinsicGas(data, nil, false, false, false, false) - signer := types.MakeSigner(gen.config, big.NewInt(int64(i))) + signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), 0) gasPrice := big.NewInt(0) if gen.header.BaseFee != nil { gasPrice = gen.header.BaseFee @@ -128,7 +128,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) { if gen.header.BaseFee != nil { gasPrice = gen.header.BaseFee } - signer := types.MakeSigner(gen.config, big.NewInt(int64(i))) + signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), 0) for { gas -= params.TxGas if gas < params.TxGas { @@ -252,8 +252,8 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) { ParentHash: hash, Difficulty: big.NewInt(1), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, } hash = header.Hash() diff --git a/core/block_validator.go b/core/block_validator.go index 3704158c11b..1688355766c 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" @@ -55,6 +56,9 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { return ErrKnownBlock } + if err := misc.VerifyExcessDataGas(v.bc, block); err != nil { + return err + } // Header validity is known at this point. Here we verify that uncles, transactions // and withdrawals given in the block body match the header. header := block.Header() @@ -76,6 +80,9 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash { return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash) } + } else if block.Withdrawals() != nil { + // Withdrawals are not allowed prior to shanghai fork + return fmt.Errorf("withdrawals present in block body") } if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { diff --git a/core/blockchain.go b/core/blockchain.go index 98d2e7a774a..39072dc1637 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -199,10 +199,10 @@ type BlockChain struct { // Readers don't need to take it, they can just read the database. chainmu *syncx.ClosableMutex - currentBlock atomic.Value // Current head of the block chain - currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!) - currentFinalizedBlock atomic.Value // Current finalized head - currentSafeBlock atomic.Value // Current safe head + currentBlock atomic.Pointer[types.Header] // Current head of the chain + currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync + currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block + currentSafeBlock atomic.Pointer[types.Header] // Latest (consensus) safe block bodyCache *lru.Cache[common.Hash, *types.Body] bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] @@ -289,11 +289,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis return nil, ErrNoGenesis } - var nilBlock *types.Block - bc.currentBlock.Store(nilBlock) - bc.currentFastBlock.Store(nilBlock) - bc.currentFinalizedBlock.Store(nilBlock) - bc.currentSafeBlock.Store(nilBlock) + bc.currentBlock.Store(nil) + bc.currentSnapBlock.Store(nil) + bc.currentFinalBlock.Store(nil) + bc.currentSafeBlock.Store(nil) // If Geth is initialized with an external ancient store, re-initialize the // missing chain indexes and chain flags. This procedure can survive crash @@ -307,7 +306,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis } // Make sure the state associated with the block is available head := bc.CurrentBlock() - if !bc.HasState(head.Root()) { + if !bc.HasState(head.Root) { // Head state is missing, before the state recovery, find out the // disk layer point of snapshot(if it's enabled). Make sure the // rewound point is lower than disk layer. @@ -316,9 +315,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis diskRoot = rawdb.ReadSnapshotRoot(bc.db) } if diskRoot != (common.Hash{}) { - log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash(), "snaproot", diskRoot) + log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "snaproot", diskRoot) - snapDisk, err := bc.setHeadBeyondRoot(head.NumberU64(), 0, diskRoot, true) + snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true) if err != nil { return nil, err } @@ -327,13 +326,12 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk) } } else { - log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash()) - if _, err := bc.setHeadBeyondRoot(head.NumberU64(), 0, common.Hash{}, true); err != nil { + log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash()) + if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil { return nil, err } } } - // Ensure that a previous crash in SetHead doesn't leave extra ancients if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 { var ( @@ -344,18 +342,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // blockchain repair. If the head full block is even lower than the ancient // chain, truncate the ancient store. fullBlock := bc.CurrentBlock() - if fullBlock != nil && fullBlock.Hash() != bc.genesisBlock.Hash() && fullBlock.NumberU64() < frozen-1 { + if fullBlock != nil && fullBlock.Hash() != bc.genesisBlock.Hash() && fullBlock.Number.Uint64() < frozen-1 { needRewind = true - low = fullBlock.NumberU64() + low = fullBlock.Number.Uint64() } // In fast sync, it may happen that ancient data has been written to the // ancient store, but the LastFastBlock has not been updated, truncate the // extra data here. - fastBlock := bc.CurrentFastBlock() - if fastBlock != nil && fastBlock.NumberU64() < frozen-1 { + snapBlock := bc.CurrentSnapBlock() + if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 { needRewind = true - if fastBlock.NumberU64() < low || low == 0 { - low = fastBlock.NumberU64() + if snapBlock.Number.Uint64() < low || low == 0 { + low = snapBlock.Number.Uint64() } } if needRewind { @@ -395,8 +393,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis var recover bool head := bc.CurrentBlock() - if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer >= head.NumberU64() { - log.Warn("Enabling snapshot recovery", "chainhead", head.NumberU64(), "diskbase", *layer) + if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer >= head.Number.Uint64() { + log.Warn("Enabling snapshot recovery", "chainhead", head.Number, "diskbase", *layer) recover = true } snapconfig := snapshot.Config{ @@ -405,7 +403,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis NoBuild: bc.cacheConfig.SnapshotNoBuild, AsyncBuild: !bc.cacheConfig.SnapshotWait, } - bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root()) + bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root) } // Start future block processor. @@ -469,32 +467,32 @@ func (bc *BlockChain) loadLastState() error { return bc.Reset() } // Make sure the entire head block is available - currentBlock := bc.GetBlockByHash(head) - if currentBlock == nil { + headBlock := bc.GetBlockByHash(head) + if headBlock == nil { // Corrupt or empty database, init from scratch log.Warn("Head block missing, resetting chain", "hash", head) return bc.Reset() } // Everything seems to be fine, set as the head block - bc.currentBlock.Store(currentBlock) - headBlockGauge.Update(int64(currentBlock.NumberU64())) + bc.currentBlock.Store(headBlock.Header()) + headBlockGauge.Update(int64(headBlock.NumberU64())) // Restore the last known head header - currentHeader := currentBlock.Header() + headHeader := headBlock.Header() if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) { if header := bc.GetHeaderByHash(head); header != nil { - currentHeader = header + headHeader = header } } - bc.hc.SetCurrentHeader(currentHeader) + bc.hc.SetCurrentHeader(headHeader) // Restore the last known head fast block - bc.currentFastBlock.Store(currentBlock) - headFastBlockGauge.Update(int64(currentBlock.NumberU64())) + bc.currentSnapBlock.Store(headBlock.Header()) + headFastBlockGauge.Update(int64(headBlock.NumberU64())) if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) { if block := bc.GetBlockByHash(head); block != nil { - bc.currentFastBlock.Store(block) + bc.currentSnapBlock.Store(block.Header()) headFastBlockGauge.Update(int64(block.NumberU64())) } } @@ -504,27 +502,31 @@ func (bc *BlockChain) loadLastState() error { // known finalized block on startup if head := rawdb.ReadFinalizedBlockHash(bc.db); head != (common.Hash{}) { if block := bc.GetBlockByHash(head); block != nil { - bc.currentFinalizedBlock.Store(block) + bc.currentFinalBlock.Store(block.Header()) headFinalizedBlockGauge.Update(int64(block.NumberU64())) - bc.currentSafeBlock.Store(block) + bc.currentSafeBlock.Store(block.Header()) headSafeBlockGauge.Update(int64(block.NumberU64())) } } // Issue a status log for the user - currentFastBlock := bc.CurrentFastBlock() - currentFinalizedBlock := bc.CurrentFinalizedBlock() - - headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64()) - blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) - fastTd := bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()) - - log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(currentHeader.Time), 0))) - log.Info("Loaded most recent local full block", "number", currentBlock.Number(), "hash", currentBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(currentBlock.Time()), 0))) - log.Info("Loaded most recent local fast block", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(int64(currentFastBlock.Time()), 0))) + var ( + currentSnapBlock = bc.CurrentSnapBlock() + currentFinalBlock = bc.CurrentFinalBlock() - if currentFinalizedBlock != nil { - finalTd := bc.GetTd(currentFinalizedBlock.Hash(), currentFinalizedBlock.NumberU64()) - log.Info("Loaded most recent local finalized block", "number", currentFinalizedBlock.Number(), "hash", currentFinalizedBlock.Hash(), "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalizedBlock.Time()), 0))) + headerTd = bc.GetTd(headHeader.Hash(), headHeader.Number.Uint64()) + blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64()) + ) + if headHeader.Hash() != headBlock.Hash() { + log.Info("Loaded most recent local header", "number", headHeader.Number, "hash", headHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(headHeader.Time), 0))) + } + log.Info("Loaded most recent local block", "number", headBlock.Number(), "hash", headBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0))) + if headBlock.Hash() != currentSnapBlock.Hash() { + fastTd := bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64()) + log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0))) + } + if currentFinalBlock != nil { + finalTd := bc.GetTd(currentFinalBlock.Hash(), currentFinalBlock.Number.Uint64()) + log.Info("Loaded most recent local finalized block", "number", currentFinalBlock.Number, "hash", currentFinalBlock.Hash(), "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalBlock.Time), 0))) } if pivot := rawdb.ReadLastPivotNumber(bc.db); pivot != nil { log.Info("Loaded last fast-sync pivot marker", "number", *pivot) @@ -540,7 +542,16 @@ func (bc *BlockChain) SetHead(head uint64) error { return err } // Send chain head event to update the transaction pool - bc.chainHeadFeed.Send(ChainHeadEvent{Block: bc.CurrentBlock()}) + header := bc.CurrentBlock() + block := bc.GetBlock(header.Hash(), header.Number.Uint64()) + if block == nil { + // This should never happen. In practice, previsouly currentBlock + // contained the entire block whereas now only a "marker", so there + // is an ever so slight chance for a race we should handle. + log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) + return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4]) + } + bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) return nil } @@ -553,16 +564,25 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error { return err } // Send chain head event to update the transaction pool - bc.chainHeadFeed.Send(ChainHeadEvent{Block: bc.CurrentBlock()}) + header := bc.CurrentBlock() + block := bc.GetBlock(header.Hash(), header.Number.Uint64()) + if block == nil { + // This should never happen. In practice, previsouly currentBlock + // contained the entire block whereas now only a "marker", so there + // is an ever so slight chance for a race we should handle. + log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) + return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4]) + } + bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) return nil } // SetFinalized sets the finalized block. -func (bc *BlockChain) SetFinalized(block *types.Block) { - bc.currentFinalizedBlock.Store(block) - if block != nil { - rawdb.WriteFinalizedBlockHash(bc.db, block.Hash()) - headFinalizedBlockGauge.Update(int64(block.NumberU64())) +func (bc *BlockChain) SetFinalized(header *types.Header) { + bc.currentFinalBlock.Store(header) + if header != nil { + rawdb.WriteFinalizedBlockHash(bc.db, header.Hash()) + headFinalizedBlockGauge.Update(int64(header.Number.Uint64())) } else { rawdb.WriteFinalizedBlockHash(bc.db, common.Hash{}) headFinalizedBlockGauge.Update(0) @@ -570,10 +590,10 @@ func (bc *BlockChain) SetFinalized(block *types.Block) { } // SetSafe sets the safe block. -func (bc *BlockChain) SetSafe(block *types.Block) { - bc.currentSafeBlock.Store(block) - if block != nil { - headSafeBlockGauge.Update(int64(block.NumberU64())) +func (bc *BlockChain) SetSafe(header *types.Header) { + bc.currentSafeBlock.Store(header) + if header != nil { + headSafeBlockGauge.Update(int64(header.Number.Uint64())) } else { headSafeBlockGauge.Update(0) } @@ -609,7 +629,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha // Rewind the blockchain, ensuring we don't end up with a stateless head // block. Note, depth equality is permitted to allow using SetHead as a // chain reparation mechanism without deleting any data! - if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.NumberU64() { + if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.Number.Uint64() { newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) if newHeadBlock == nil { log.Error("Gap in the chain, rewinding to genesis", "number", header.Number, "hash", header.Hash()) @@ -667,27 +687,27 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha // In theory we should update all in-memory markers in the // last step, however the direction of SetHead is from high // to low, so it's safe to update in-memory markers directly. - bc.currentBlock.Store(newHeadBlock) + bc.currentBlock.Store(newHeadBlock.Header()) headBlockGauge.Update(int64(newHeadBlock.NumberU64())) } // Rewind the fast block in a simpleton way to the target head - if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && header.Number.Uint64() < currentFastBlock.NumberU64() { - newHeadFastBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) + if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock != nil && header.Number.Uint64() < currentSnapBlock.Number.Uint64() { + newHeadSnapBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) // If either blocks reached nil, reset to the genesis state - if newHeadFastBlock == nil { - newHeadFastBlock = bc.genesisBlock + if newHeadSnapBlock == nil { + newHeadSnapBlock = bc.genesisBlock } - rawdb.WriteHeadFastBlockHash(db, newHeadFastBlock.Hash()) + rawdb.WriteHeadFastBlockHash(db, newHeadSnapBlock.Hash()) // Degrade the chain markers if they are explicitly reverted. // In theory we should update all in-memory markers in the // last step, however the direction of SetHead is from high // to low, so it's safe the update in-memory markers directly. - bc.currentFastBlock.Store(newHeadFastBlock) - headFastBlockGauge.Update(int64(newHeadFastBlock.NumberU64())) + bc.currentSnapBlock.Store(newHeadSnapBlock.Header()) + headFastBlockGauge.Update(int64(newHeadSnapBlock.NumberU64())) } var ( - headHeader = bc.CurrentBlock().Header() + headHeader = bc.CurrentBlock() headNumber = headHeader.Number.Uint64() ) // If setHead underflown the freezer threshold and the block processing @@ -723,7 +743,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha // If SetHead was only called as a chain reparation method, try to skip // touching the header chain altogether, unless the freezer is broken if repair { - if target, force := updateFn(bc.db, bc.CurrentBlock().Header()); force { + if target, force := updateFn(bc.db, bc.CurrentBlock()); force { bc.hc.SetHead(target.Number.Uint64(), updateFn, delFn) } } else { @@ -746,15 +766,14 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha bc.futureBlocks.Purge() // Clear safe block, finalized block if needed - if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.NumberU64() { + if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.Number.Uint64() { log.Warn("SetHead invalidated safe block") bc.SetSafe(nil) } - if finalized := bc.CurrentFinalizedBlock(); finalized != nil && head < finalized.NumberU64() { + if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() { log.Error("SetHead invalidated finalized block") bc.SetFinalized(nil) } - return rootNumber, bc.loadLastState() } @@ -774,7 +793,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error { if !bc.chainmu.TryLock() { return errChainStopped } - bc.currentBlock.Store(block) + bc.currentBlock.Store(block.Header()) headBlockGauge.Update(int64(block.NumberU64())) bc.chainmu.Unlock() @@ -815,18 +834,18 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error { // Last update all in-memory chain markers bc.genesisBlock = genesis - bc.currentBlock.Store(bc.genesisBlock) + bc.currentBlock.Store(bc.genesisBlock.Header()) headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) bc.hc.SetGenesis(bc.genesisBlock.Header()) bc.hc.SetCurrentHeader(bc.genesisBlock.Header()) - bc.currentFastBlock.Store(bc.genesisBlock) + bc.currentSnapBlock.Store(bc.genesisBlock.Header()) headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) return nil } // Export writes the active chain to the given writer. func (bc *BlockChain) Export(w io.Writer) error { - return bc.ExportN(w, uint64(0), bc.CurrentBlock().NumberU64()) + return bc.ExportN(w, uint64(0), bc.CurrentBlock().Number.Uint64()) } // ExportN writes a subset of the active chain to the given writer. @@ -883,10 +902,10 @@ func (bc *BlockChain) writeHeadBlock(block *types.Block) { // Update all in-memory chain markers in the last step bc.hc.SetCurrentHeader(block.Header()) - bc.currentFastBlock.Store(block) + bc.currentSnapBlock.Store(block.Header()) headFastBlockGauge.Update(int64(block.NumberU64())) - bc.currentBlock.Store(block) + bc.currentBlock.Store(block.Header()) headBlockGauge.Update(int64(block.NumberU64())) } @@ -927,7 +946,7 @@ func (bc *BlockChain) Stop() { var snapBase common.Hash if bc.snaps != nil { var err error - if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root()); err != nil { + if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil { log.Error("Failed to journal state snapshot", "err", err) } } @@ -941,7 +960,7 @@ func (bc *BlockChain) Stop() { triedb := bc.triedb for _, offset := range []uint64{0, 1, TriesInMemory - 1} { - if number := bc.CurrentBlock().NumberU64(); number > offset { + if number := bc.CurrentBlock().Number.Uint64(); number > offset { recent := bc.GetBlockByNumber(number - offset) log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root()) @@ -1059,7 +1078,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ // Rewind may have occurred, skip in that case. if bc.CurrentHeader().Number.Cmp(head.Number()) >= 0 { - reorg, err := bc.forker.ReorgNeeded(bc.CurrentFastBlock().Header(), head.Header()) + reorg, err := bc.forker.ReorgNeeded(bc.CurrentSnapBlock(), head.Header()) if err != nil { log.Warn("Reorg failed", "err", err) return false @@ -1067,13 +1086,12 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ return false } rawdb.WriteHeadFastBlockHash(bc.db, head.Hash()) - bc.currentFastBlock.Store(head) + bc.currentSnapBlock.Store(head.Header()) headFastBlockGauge.Update(int64(head.NumberU64())) return true } return false } - // writeAncient writes blockchain and corresponding receipt chain into ancient store. // // this function only accepts canonical chain data. All side chain will be reverted @@ -1135,8 +1153,8 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ if batch.ValueSize() > ethdb.IdealBatchSize || i == len(blockChain)-1 { size += int64(batch.ValueSize()) if err = batch.Write(); err != nil { - fastBlock := bc.CurrentFastBlock().NumberU64() - if err := bc.db.TruncateHead(fastBlock + 1); err != nil { + snapBlock := bc.CurrentSnapBlock().Number.Uint64() + if err := bc.db.TruncateHead(snapBlock + 1); err != nil { log.Error("Can't truncate ancient store after failed insert", "err", err) } return 0, err @@ -1150,11 +1168,11 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ return 0, err } // Update the current fast block because all block data is now present in DB. - previousFastBlock := bc.CurrentFastBlock().NumberU64() + previousSnapBlock := bc.CurrentSnapBlock().Number.Uint64() if !updateHead(blockChain[len(blockChain)-1]) { // We end up here if the header chain has reorg'ed, and the blocks/receipts // don't match the canonical chain. - if err := bc.db.TruncateHead(previousFastBlock + 1); err != nil { + if err := bc.db.TruncateHead(previousSnapBlock + 1); err != nil { log.Error("Can't truncate ancient store after failed insert", "err", err) } return 0, errSideChainReceipts @@ -1278,7 +1296,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ if stats.ignored > 0 { context = append(context, []interface{}{"ignored", stats.ignored}...) } - log.Info("Imported new block receipts", context...) + log.Debug("Imported new block receipts", context...) return 0, nil } @@ -1414,7 +1432,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types return NonStatTy, err } currentBlock := bc.CurrentBlock() - reorg, err := bc.forker.ReorgNeeded(currentBlock.Header(), block.Header()) + reorg, err := bc.forker.ReorgNeeded(currentBlock, block.Header()) if err != nil { return NonStatTy, err } @@ -1523,7 +1541,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) } // Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss) - SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain) + signer := types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()) + SenderCacher.RecoverFromBlocks(signer, chain) var ( stats = insertStats{startTime: mclock.Now()} @@ -1562,7 +1581,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) current = bc.CurrentBlock() ) for block != nil && bc.skipBlock(err, it) { - reorg, err = bc.forker.ReorgNeeded(current.Header(), block.Header()) + reorg, err = bc.forker.ReorgNeeded(current, block.Header()) if err != nil { return it.index, err } @@ -1572,7 +1591,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) // In eth2 the forker always returns true for reorg decision (blindly trusting // the external consensus engine), but in order to prevent the unnecessary // reorgs when importing known blocks, the special case is handled here. - if block.NumberU64() > current.NumberU64() || bc.GetCanonicalHash(block.NumberU64()) != block.Hash() { + if block.NumberU64() > current.Number.Uint64() || bc.GetCanonicalHash(block.NumberU64()) != block.Hash() { break } } @@ -1722,20 +1741,20 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) if followup, err := it.peek(); followup != nil && err == nil { throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps) - go func(start time.Time, followup *types.Block, throwaway *state.StateDB, interrupt *uint32) { - bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) + go func(start time.Time, followup *types.Block, throwaway *state.StateDB) { + bc.prefetcher.Prefetch(followup, parent.ExcessDataGas, throwaway, bc.vmConfig, &followupInterrupt) blockPrefetchExecuteTimer.Update(time.Since(start)) - if atomic.LoadUint32(interrupt) == 1 { + if atomic.LoadUint32(&followupInterrupt) == 1 { blockPrefetchInterruptMeter.Mark(1) } - }(time.Now(), followup, throwaway, &followupInterrupt) + }(time.Now(), followup, throwaway) } } // Process block using the parent state as reference point substart := time.Now() - receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig) + receipts, logs, usedGas, err := bc.processor.Process(block, parent.ExcessDataGas, statedb, bc.vmConfig) if err != nil { bc.reportBlock(block, receipts, err) atomic.StoreUint32(&followupInterrupt, 1) @@ -1872,7 +1891,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i err := consensus.ErrPrunedAncestor for ; block != nil && errors.Is(err, consensus.ErrPrunedAncestor); block, err = it.next() { // Check the canonical state root for that number - if number := block.NumberU64(); current.NumberU64() >= number { + if number := block.NumberU64(); current.Number.Uint64() >= number { canonical := bc.GetBlockByNumber(number) if canonical != nil && canonical.Hash() == block.Hash() { // Not a sidechain block, this is a re-import of a canon block which has it's state pruned @@ -1922,12 +1941,12 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i // // If the externTd was larger than our local TD, we now need to reimport the previous // blocks to regenerate the required state - reorg, err := bc.forker.ReorgNeeded(current.Header(), lastBlock.Header()) + reorg, err := bc.forker.ReorgNeeded(current, lastBlock.Header()) if err != nil { return it.index, err } if !reorg { - localTd := bc.GetTd(current.Hash(), current.NumberU64()) + localTd := bc.GetTd(current.Hash(), current.Number.Uint64()) log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd) return it.index, err } @@ -2031,7 +2050,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error) // the processing of a block. These logs are later announced as deleted or reborn. func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log { receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64()) - receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Transactions()) + receipts.DeriveLogFields(b.Hash(), b.NumberU64(), b.Transactions()) var logs []*types.Log for _, receipt := range receipts { @@ -2051,7 +2070,7 @@ func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log { // potential missing transactions and post an event about them. // Note the new head block won't be processed here, callers need to handle it // externally. -func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { +func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error { var ( newChain types.Blocks oldChain types.Blocks @@ -2060,6 +2079,12 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { deletedTxs []common.Hash addedTxs []common.Hash ) + oldBlock := bc.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) + if oldBlock == nil { + return errors.New("current head block missing") + } + newBlock := newHead + // Reduce the longer chain to the same number as the shorter one if oldBlock.NumberU64() > newBlock.NumberU64() { // Old chain is longer, gather all transactions and logs as deleted ones @@ -2076,10 +2101,10 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { } } if oldBlock == nil { - return fmt.Errorf("invalid old chain") + return errors.New("invalid old chain") } if newBlock == nil { - return fmt.Errorf("invalid new chain") + return errors.New("invalid new chain") } // Both sides of the reorg are at the same number, reduce both until the common // ancestor is found diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index e8a5d952a24..21a9c6676bd 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -40,26 +40,26 @@ func (bc *BlockChain) CurrentHeader() *types.Header { // CurrentBlock retrieves the current head block of the canonical chain. The // block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentBlock() *types.Block { - return bc.currentBlock.Load().(*types.Block) +func (bc *BlockChain) CurrentBlock() *types.Header { + return bc.currentBlock.Load() } -// CurrentFastBlock retrieves the current fast-sync head block of the canonical +// CurrentSnapBlock retrieves the current snap-sync head block of the canonical // chain. The block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentFastBlock() *types.Block { - return bc.currentFastBlock.Load().(*types.Block) +func (bc *BlockChain) CurrentSnapBlock() *types.Header { + return bc.currentSnapBlock.Load() } -// CurrentFinalizedBlock retrieves the current finalized block of the canonical +// CurrentFinalBlock retrieves the current finalized block of the canonical // chain. The block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentFinalizedBlock() *types.Block { - return bc.currentFinalizedBlock.Load().(*types.Block) +func (bc *BlockChain) CurrentFinalBlock() *types.Header { + return bc.currentFinalBlock.Load() } // CurrentSafeBlock retrieves the current safe block of the canonical // chain. The block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentSafeBlock() *types.Block { - return bc.currentSafeBlock.Load().(*types.Block) +func (bc *BlockChain) CurrentSafeBlock() *types.Header { + return bc.currentSafeBlock.Load() } // HasHeader checks if a block header is present in the database or not, caching @@ -315,7 +315,7 @@ func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) { // State returns a new mutable state based on the current HEAD block. func (bc *BlockChain) State() (*state.StateDB, error) { - return bc.StateAt(bc.CurrentBlock().Root()) + return bc.StateAt(bc.CurrentBlock().Root) } // StateAt returns a new mutable state based on a particular point in time. @@ -351,7 +351,7 @@ func (bc *BlockChain) StateCache() state.Database { // GasLimit returns the gas limit of the current HEAD block. func (bc *BlockChain) GasLimit() uint64 { - return bc.CurrentBlock().GasLimit() + return bc.CurrentBlock().GasLimit } // Genesis retrieves the chain's genesis block. diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 5db0fb5703d..6a4a9c9d22b 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -1857,11 +1857,11 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { if head := newChain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) } - if head := newChain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock { - t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock) + if head := newChain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { + t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) } - if head := newChain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock { - t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock) + if head := newChain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { + t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) } if frozen, err := db.(freezer).Ancients(); err != nil { t.Errorf("Failed to retrieve ancient count: %v\n", err) @@ -1973,11 +1973,11 @@ func TestIssue23496(t *testing.T) { if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) } - if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) { - t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) + if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { + t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) } - if head := chain.CurrentBlock(); head.NumberU64() != uint64(1) { - t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(1)) + if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(1) { + t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(1)) } // Reinsert B2-B4 @@ -1987,11 +1987,11 @@ func TestIssue23496(t *testing.T) { if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) } - if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) { - t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) + if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { + t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) } - if head := chain.CurrentBlock(); head.NumberU64() != uint64(4) { - t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) + if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) { + t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4)) } if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { t.Error("Failed to regenerate the snapshot of known state") diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index 825a0e16b43..9dc350db849 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -2047,11 +2047,11 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) } - if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock { - t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock) + if head := chain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { + t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) } - if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock { - t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock) + if head := chain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { + t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) } if frozen, err := db.(freezer).Ancients(); err != nil { t.Errorf("Failed to retrieve ancient count: %v\n", err) diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index b34ea573c1a..3bd876a58ec 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -136,11 +136,11 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [ if head := chain.CurrentHeader(); head.Number.Uint64() != basic.expHeadHeader { t.Errorf("Head header mismatch: have %d, want %d", head.Number, basic.expHeadHeader) } - if head := chain.CurrentFastBlock(); head.NumberU64() != basic.expHeadFastBlock { - t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), basic.expHeadFastBlock) + if head := chain.CurrentSnapBlock(); head.Number.Uint64() != basic.expHeadFastBlock { + t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, basic.expHeadFastBlock) } - if head := chain.CurrentBlock(); head.NumberU64() != basic.expHeadBlock { - t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), basic.expHeadBlock) + if head := chain.CurrentBlock(); head.Number.Uint64() != basic.expHeadBlock { + t.Errorf("Head block mismatch: have %d, want %d", head.Number, basic.expHeadBlock) } // Check the disk layer, ensure they are matched diff --git a/core/blockchain_test.go b/core/blockchain_test.go index ae77d0b7f66..72b586557f9 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -40,6 +40,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" + "github.com/protolambda/ztyp/view" ) // So we can deterministically seed different blockchains @@ -109,7 +110,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara headerChainB []*types.Header ) if full { - blockChainB = makeBlockChain(blockchain2.chainConfig, blockchain2.CurrentBlock(), n, ethash.NewFaker(), genDb, forkSeed) + blockChainB = makeBlockChain(blockchain2.chainConfig, blockchain2.GetBlockByHash(blockchain2.CurrentBlock().Hash()), n, ethash.NewFaker(), genDb, forkSeed) if _, err := blockchain2.InsertChain(blockChainB); err != nil { t.Fatalf("failed to insert forking chain: %v", err) } @@ -124,7 +125,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara if full { cur := blockchain.CurrentBlock() - tdPre = blockchain.GetTd(cur.Hash(), cur.NumberU64()) + tdPre = blockchain.GetTd(cur.Hash(), cur.Number.Uint64()) if err := testBlockChainImport(blockChainB, blockchain); err != nil { t.Fatalf("failed to import forked block chain: %v", err) } @@ -158,11 +159,12 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { } return err } - statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil) + parent := blockchain.GetBlockByHash(block.ParentHash()) + statedb, err := state.New(parent.Root(), blockchain.stateCache, nil) if err != nil { return err } - receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{}) + receipts, _, usedGas, err := blockchain.processor.Process(block, parent.Header().ExcessDataGas, statedb, vm.Config{}) if err != nil { blockchain.reportBlock(block, receipts, err) return err @@ -206,7 +208,7 @@ func TestLastBlock(t *testing.T) { } defer blockchain.Stop() - blocks := makeBlockChain(blockchain.chainConfig, blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), genDb, 0) + blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 1, ethash.NewFullFaker(), genDb, 0) if _, err := blockchain.InsertChain(blocks); err != nil { t.Fatalf("Failed to insert block: %v", err) } @@ -240,11 +242,11 @@ func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full b // Extend the newly created chain if full { - blockChainB := makeBlockChain(blockchain2.chainConfig, blockchain2.CurrentBlock(), n, ethash.NewFaker(), genDb, forkSeed) + blockChainB := makeBlockChain(blockchain2.chainConfig, blockchain2.GetBlockByHash(blockchain2.CurrentBlock().Hash()), n, ethash.NewFaker(), genDb, forkSeed) if _, err := blockchain2.InsertChain(blockChainB); err != nil { t.Fatalf("failed to insert forking chain: %v", err) } - if blockchain2.CurrentBlock().NumberU64() != blockChainB[len(blockChainB)-1].NumberU64() { + if blockchain2.CurrentBlock().Number.Uint64() != blockChainB[len(blockChainB)-1].NumberU64() { t.Fatalf("failed to reorg to the given chain") } if blockchain2.CurrentBlock().Hash() != blockChainB[len(blockChainB)-1].Hash() { @@ -477,7 +479,7 @@ func testBrokenChain(t *testing.T, full bool) { // Create a forked chain, and try to insert with a missing link if full { - chain := makeBlockChain(blockchain.chainConfig, blockchain.CurrentBlock(), 5, ethash.NewFaker(), genDb, forkSeed)[1:] + chain := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 5, ethash.NewFaker(), genDb, forkSeed)[1:] if err := testBlockChainImport(chain, blockchain); err == nil { t.Errorf("broken block chain not reported") } @@ -527,10 +529,10 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) { defer blockchain.Stop() // Insert an easy and a difficult chain afterwards - easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), genDb, len(first), func(i int, b *BlockGen) { + easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), genDb, len(first), func(i int, b *BlockGen) { b.OffsetTime(first[i]) }) - diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), genDb, len(second), func(i int, b *BlockGen) { + diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), genDb, len(second), func(i int, b *BlockGen) { b.OffsetTime(second[i]) }) if full { @@ -559,9 +561,9 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) { // Check that the chain is valid number and link wise if full { prev := blockchain.CurrentBlock() - for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { - if prev.ParentHash() != block.Hash() { - t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) + for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().Number.Uint64() - 1); block.NumberU64() != 0; prev, block = block.Header(), blockchain.GetBlockByNumber(block.NumberU64()-1) { + if prev.ParentHash != block.Hash() { + t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash, block.Hash()) } } } else { @@ -576,7 +578,7 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) { want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) if full { cur := blockchain.CurrentBlock() - if have := blockchain.GetTd(cur.Hash(), cur.NumberU64()); have.Cmp(want) != 0 { + if have := blockchain.GetTd(cur.Hash(), cur.Number.Uint64()); have.Cmp(want) != 0 { t.Errorf("total difficulty mismatch: have %v, want %v", have, want) } } else { @@ -601,7 +603,7 @@ func testBadHashes(t *testing.T, full bool) { // Create a chain, ban a hash and try to import if full { - blocks := makeBlockChain(blockchain.chainConfig, blockchain.CurrentBlock(), 3, ethash.NewFaker(), genDb, 10) + blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 3, ethash.NewFaker(), genDb, 10) BadHashes[blocks[2].Header().Hash()] = true defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() @@ -633,7 +635,7 @@ func testReorgBadHashes(t *testing.T, full bool) { } // Create a chain, import and ban afterwards headers := makeHeaderChain(blockchain.chainConfig, blockchain.CurrentHeader(), 4, ethash.NewFaker(), genDb, 10) - blocks := makeBlockChain(blockchain.chainConfig, blockchain.CurrentBlock(), 4, ethash.NewFaker(), genDb, 10) + blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 4, ethash.NewFaker(), genDb, 10) if full { if _, err = blockchain.InsertChain(blocks); err != nil { @@ -696,7 +698,7 @@ func testInsertNonceError(t *testing.T, full bool) { failNum uint64 ) if full { - blocks := makeBlockChain(blockchain.chainConfig, blockchain.CurrentBlock(), i, ethash.NewFaker(), genDb, 0) + blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), i, ethash.NewFaker(), genDb, 0) failAt = rand.Int() % len(blocks) failNum = blocks[failAt].NumberU64() @@ -894,11 +896,11 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { t.Helper() - if num := chain.CurrentBlock().NumberU64(); num != block { + if num := chain.CurrentBlock().Number.Uint64(); num != block { t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) } - if num := chain.CurrentFastBlock().NumberU64(); num != fast { - t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) + if num := chain.CurrentSnapBlock().Number.Uint64(); num != fast { + t.Errorf("%s head snap-block mismatch: have #%v, want #%v", kind, num, fast) } if num := chain.CurrentHeader().Number.Uint64(); num != header { t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) @@ -1649,13 +1651,13 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { t.Fatalf("block %d: failed to insert into chain: %v", i, err) } if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { - t.Errorf("block %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) + t.Errorf("block %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number, chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) } if _, err := chain.InsertChain(forks[i : i+1]); err != nil { t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) } if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { - t.Errorf(" fork %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) + t.Errorf(" fork %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number, chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) } } } @@ -1797,11 +1799,11 @@ func TestBlockchainRecovery(t *testing.T) { // Reopen broken blockchain again ancient, _ = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer ancient.Stop() - if num := ancient.CurrentBlock().NumberU64(); num != 0 { + if num := ancient.CurrentBlock().Number.Uint64(); num != 0 { t.Errorf("head block mismatch: have #%v, want #%v", num, 0) } - if num := ancient.CurrentFastBlock().NumberU64(); num != midBlock.NumberU64() { - t.Errorf("head fast-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) + if num := ancient.CurrentSnapBlock().Number.Uint64(); num != midBlock.NumberU64() { + t.Errorf("head snap-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) } if num := ancient.CurrentHeader().Number.Uint64(); num != midBlock.NumberU64() { t.Errorf("head header mismatch: have #%v, want #%v", num, midBlock.NumberU64()) @@ -1820,7 +1822,7 @@ func TestInsertReceiptChainRollback(t *testing.T) { if _, err := tmpChain.InsertChain(sideblocks); err != nil { t.Fatal("processing side chain failed:", err) } - t.Log("sidechain head:", tmpChain.CurrentBlock().Number(), tmpChain.CurrentBlock().Hash()) + t.Log("sidechain head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash()) sidechainReceipts := make([]types.Receipts, len(sideblocks)) for i, block := range sideblocks { sidechainReceipts[i] = tmpChain.GetReceiptsByHash(block.Hash()) @@ -1829,7 +1831,7 @@ func TestInsertReceiptChainRollback(t *testing.T) { if _, err := tmpChain.InsertChain(canonblocks); err != nil { t.Fatal("processing canon chain failed:", err) } - t.Log("canon head:", tmpChain.CurrentBlock().Number(), tmpChain.CurrentBlock().Hash()) + t.Log("canon head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash()) canonReceipts := make([]types.Receipts, len(canonblocks)) for i, block := range canonblocks { canonReceipts[i] = tmpChain.GetReceiptsByHash(block.Hash()) @@ -1859,8 +1861,8 @@ func TestInsertReceiptChainRollback(t *testing.T) { if err == nil { t.Fatal("expected error from InsertReceiptChain.") } - if ancientChain.CurrentFastBlock().NumberU64() != 0 { - t.Fatalf("failed to rollback ancient data, want %d, have %d", 0, ancientChain.CurrentFastBlock().NumberU64()) + if ancientChain.CurrentSnapBlock().Number.Uint64() != 0 { + t.Fatalf("failed to rollback ancient data, want %d, have %d", 0, ancientChain.CurrentSnapBlock().Number) } if frozen, err := ancientChain.db.Ancients(); err != nil || frozen != 1 { t.Fatalf("failed to truncate ancient data, frozen index is %d", frozen) @@ -1871,7 +1873,7 @@ func TestInsertReceiptChainRollback(t *testing.T) { if err != nil { t.Fatalf("can't import canon chain receipts: %v", err) } - if ancientChain.CurrentFastBlock().NumberU64() != canonblocks[len(canonblocks)-1].NumberU64() { + if ancientChain.CurrentSnapBlock().Number.Uint64() != canonblocks[len(canonblocks)-1].NumberU64() { t.Fatalf("failed to insert ancient recept chain after rollback") } if frozen, _ := ancientChain.db.Ancients(); frozen != uint64(len(canonblocks))+1 { @@ -1926,7 +1928,7 @@ func TestLowDiffLongChain(t *testing.T) { } // Sanity check that all the canonical numbers are present header := chain.CurrentHeader() - for number := head.NumberU64(); number > 0; number-- { + for number := head.Number.Uint64(); number > 0; number-- { if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) } @@ -2150,8 +2152,8 @@ func testInsertKnownChainData(t *testing.T, typ string) { return err } asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentFastBlock().Hash() != block.Hash() { - t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentFastBlock().Hash().Hex(), block.Hash().Hex()) + if chain.CurrentSnapBlock().Hash() != block.Hash() { + t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentSnapBlock().Hash().Hex(), block.Hash().Hex()) } } } else { @@ -2324,8 +2326,8 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i return err } asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentFastBlock().Hash() != block.Hash() { - t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentFastBlock().Hash().Hex(), block.Hash().Hex()) + if chain.CurrentSnapBlock().Hash() != block.Hash() { + t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentSnapBlock().Hash().Hex(), block.Hash().Hex()) } } } else { @@ -2452,7 +2454,7 @@ func TestReorgToShorterRemovesCanonMapping(t *testing.T) { if n, err := chain.InsertChain(canonblocks); err != nil { t.Fatalf("block %d: failed to insert into chain: %v", n, err) } - canonNum := chain.CurrentBlock().NumberU64() + canonNum := chain.CurrentBlock().Number.Uint64() canonHash := chain.CurrentBlock().Hash() _, err = chain.InsertChain(sideblocks) if err != nil { @@ -2467,7 +2469,7 @@ func TestReorgToShorterRemovesCanonMapping(t *testing.T) { t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) } if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { - t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) + t.Errorf("expected header to be gone: %v", headerByNum.Number) } if blockByHash := chain.GetBlockByHash(canonHash); blockByHash == nil { t.Errorf("expected block to be present: %x", blockByHash.Hash()) @@ -2553,7 +2555,7 @@ func TestTransactionIndices(t *testing.T) { t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored) } if tail != nil { - for i := *tail; i <= chain.CurrentBlock().NumberU64(); i++ { + for i := *tail; i <= chain.CurrentBlock().Number.Uint64(); i++ { block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) if block.Transactions().Len() == 0 { continue @@ -2649,7 +2651,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) { t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored) } if tail != nil { - for i := *tail; i <= chain.CurrentBlock().NumberU64(); i++ { + for i := *tail; i <= chain.CurrentBlock().Number.Uint64(); i++ { block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) if block.Transactions().Len() == 0 { continue @@ -2752,7 +2754,8 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in b.Fatalf("failed to insert shared chain: %v", err) } b.StopTimer() - if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { + block := chain.GetBlockByHash(chain.CurrentBlock().Hash()) + if got := block.Transactions().Len(); got != numTxs*numBlocks { b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) } } @@ -3715,8 +3718,8 @@ func TestSetCanonical(t *testing.T) { if chain.CurrentBlock().Hash() != head.Hash() { t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash()) } - if chain.CurrentFastBlock().Hash() != head.Hash() { - t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentFastBlock().Hash()) + if chain.CurrentSnapBlock().Hash() != head.Hash() { + t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash()) } if chain.CurrentHeader().Hash() != head.Hash() { t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash()) @@ -3799,8 +3802,8 @@ func TestCanonicalHashMarker(t *testing.T) { if chain.CurrentBlock().Hash() != head.Hash() { t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash()) } - if chain.CurrentFastBlock().Hash() != head.Hash() { - t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentFastBlock().Hash()) + if chain.CurrentSnapBlock().Hash() != head.Hash() { + t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash()) } if chain.CurrentHeader().Hash() != head.Hash() { t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash()) @@ -4138,6 +4141,102 @@ func testCreateThenDelete(t *testing.T, config *params.ChainConfig) { } } +// TestDataBlobTxs tests the following: +// +// 1. Writes data hash from transaction to storage. +func TestDataBlobTxs(t *testing.T) { + var ( + one = common.Hash{1} + two = common.Hash{2} + aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") + + // Generate a canonical chain to act as the main dataset + engine = beacon.NewFaker() + + // A sender who makes transactions, has some funds + key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + addr1 = crypto.PubkeyToAddress(key1.PublicKey) + funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether)) + gspec = &Genesis{ + Config: params.AllEthashProtocolChanges, + Alloc: GenesisAlloc{ + addr1: {Balance: funds}, + // The address 0xAAAA writes dataHashes[1] to storage slot 0x0. + aa: { + Code: []byte{ + byte(vm.PUSH1), + byte(0x1), + byte(vm.DATAHASH), + byte(vm.PUSH1), + byte(0x0), + byte(vm.SSTORE), + }, + Nonce: 0, + Balance: big.NewInt(0), + }, + }, + } + ) + + // We test the transition from non-cancun to cancun + // Genesis (block 0): AllEthhashProtocolChanges + // Block 1 : "" + // Block 2 : Cancun + var time uint64 = 2 * 10 // block time is 10 seconds, so this corresponds to second block. + gspec.Config.BerlinBlock = common.Big0 + gspec.Config.LondonBlock = common.Big0 + gspec.Config.ShanghaiTime = &time + gspec.Config.CancunTime = &time + gspec.Config.TerminalTotalDifficulty = common.Big0 + gspec.Config.TerminalTotalDifficultyPassed = true + signer := types.LatestSigner(gspec.Config) + + _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2, func(i int, b *BlockGen) { + if i == 0 { + // i==0 is a non-cancun block + return + } + b.SetCoinbase(common.Address{1}) + msg := types.BlobTxMessage{ + Nonce: 0, + Gas: 500000, + } + msg.To.Address = (*types.AddressSSZ)(&aa) + msg.ChainID.SetFromBig((*big.Int)(gspec.Config.ChainID)) + msg.Nonce = view.Uint64View(0) + msg.GasFeeCap.SetFromBig(newGwei(5)) + msg.GasTipCap.SetFromBig(big.NewInt(2)) + msg.MaxFeePerDataGas.SetFromBig(big.NewInt(params.MinDataGasPrice)) + // TODO(eip-4844): Add test case for max data fee too low + msg.BlobVersionedHashes = []common.Hash{one, two} + txdata := &types.SignedBlobTx{Message: msg} + + tx := types.NewTx(txdata) + tx, _ = types.SignTx(tx, signer, key1) + + b.AddTx(tx) + }) + + diskdb := rawdb.NewMemoryDatabase() + gspec.MustCommit(diskdb) + + chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } + if n, err := chain.InsertChain(blocks); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", n, err) + } + + state, _ := chain.State() + + // 1. Check that the storage slot is set to dataHashes[1]. + actual := state.GetState(aa, common.Hash{0}) + if actual != two { + t.Fatalf("incorrect data hash written to state (want: %s, got: %s)", two, actual) + } +} + // TestTransientStorageReset ensures the transient storage is wiped correctly // between transactions. func TestTransientStorageReset(t *testing.T) { diff --git a/core/bloombits/generator_test.go b/core/bloombits/generator_test.go index 883948d12bb..ac1aee0b252 100644 --- a/core/bloombits/generator_test.go +++ b/core/bloombits/generator_test.go @@ -18,6 +18,7 @@ package bloombits import ( "bytes" + crand "crypto/rand" "math/rand" "testing" @@ -78,7 +79,7 @@ func BenchmarkGenerator(b *testing.B) { } }) for i := 0; i < types.BloomBitLength; i++ { - rand.Read(input[i][:]) + crand.Read(input[i][:]) } b.Run("random", func(b *testing.B) { b.ReportAllocs() diff --git a/core/chain_makers.go b/core/chain_makers.go index 3518929f8e7..b70ead7e03c 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -61,7 +61,7 @@ func (b *BlockGen) SetCoinbase(addr common.Address) { panic("coinbase can only be set once") } b.header.Coinbase = addr - b.gasPool = new(GasPool).AddGas(b.header.GasLimit) + b.gasPool = new(GasPool).AddGas(b.header.GasLimit).AddDataGas(params.MaxDataGasPerBlock) } // SetExtra sets the extra data field of the generated block. @@ -98,7 +98,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti b.SetCoinbase(common.Address{}) } b.statedb.SetTxContext(tx.Hash(), len(b.txs)) - receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig) + receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, b.parent.Header().ExcessDataGas, tx, &b.header.GasUsed, vmConfig) if err != nil { panic(err) } @@ -156,6 +156,16 @@ func (b *BlockGen) Number() *big.Int { return new(big.Int).Set(b.header.Number) } +// Timestamp returns the timestamp of the block being generated. +func (b *BlockGen) Timestamp() uint64 { + return b.header.Time +} + +// ExcessDataGas returns the excessDataGas of the block being generated. +func (b *BlockGen) ExcessDataGas() *big.Int { + return b.header.ExcessDataGas +} + // BaseFee returns the EIP-1559 base fee of the block being generated. func (b *BlockGen) BaseFee() *big.Int { return new(big.Int).Set(b.header.BaseFee) @@ -207,23 +217,31 @@ func (b *BlockGen) AddUncle(h *types.Header) { } // AddWithdrawal adds a withdrawal to the generated block. -func (b *BlockGen) AddWithdrawal(w *types.Withdrawal) { - // The withdrawal will be assigned the next valid index. - var idx uint64 +// It returns the withdrawal index. +func (b *BlockGen) AddWithdrawal(w *types.Withdrawal) uint64 { + cpy := *w + cpy.Index = b.nextWithdrawalIndex() + b.withdrawals = append(b.withdrawals, &cpy) + return cpy.Index +} + +// nextWithdrawalIndex computes the index of the next withdrawal. +func (b *BlockGen) nextWithdrawalIndex() uint64 { + if len(b.withdrawals) != 0 { + return b.withdrawals[len(b.withdrawals)-1].Index + 1 + } for i := b.i - 1; i >= 0; i-- { if wd := b.chain[i].Withdrawals(); len(wd) != 0 { - idx = wd[len(wd)-1].Index + 1 - break + return wd[len(wd)-1].Index + 1 } if i == 0 { - // Correctly set the index if no parent had withdrawals + // Correctly set the index if no parent had withdrawals. if wd := b.parent.Withdrawals(); len(wd) != 0 { - idx = wd[len(wd)-1].Index + 1 + return wd[len(wd)-1].Index + 1 } } } - w.Index = idx - b.withdrawals = append(b.withdrawals, w) + return 0 } // PrevBlock returns a previously generated block by number. It panics if @@ -426,4 +444,9 @@ func (cr *fakeChainReader) GetHeaderByNumber(number uint64) *types.Header func (cr *fakeChainReader) GetHeaderByHash(hash common.Hash) *types.Header { return nil } func (cr *fakeChainReader) GetHeader(hash common.Hash, number uint64) *types.Header { return nil } func (cr *fakeChainReader) GetBlock(hash common.Hash, number uint64) *types.Block { return nil } -func (cr *fakeChainReader) GetTd(hash common.Hash, number uint64) *big.Int { return nil } +func (cr *fakeChainReader) GetTd(hash common.Hash, number uint64) *big.Int { + if cr.config.TerminalTotalDifficultyPassed { + return cr.config.TerminalTotalDifficulty + } + return nil +} diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index 166ac3f227f..4f735552755 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -19,7 +19,10 @@ package core import ( "fmt" "math/big" + "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/types" @@ -28,6 +31,112 @@ import ( "github.com/ethereum/go-ethereum/params" ) +func TestGenerateWithdrawalChain(t *testing.T) { + var ( + keyHex = "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c" + key, _ = crypto.HexToECDSA(keyHex) + address = crypto.PubkeyToAddress(key.PublicKey) // 658bdf435d810c91414ec09147daa6db62406379 + aa = common.Address{0xaa} + bb = common.Address{0xbb} + funds = big.NewInt(0).Mul(big.NewInt(1337), big.NewInt(params.Ether)) + config = *params.AllEthashProtocolChanges + gspec = &Genesis{ + Config: &config, + Alloc: GenesisAlloc{address: {Balance: funds}}, + BaseFee: big.NewInt(params.InitialBaseFee), + Difficulty: common.Big1, + GasLimit: 5_000_000, + } + gendb = rawdb.NewMemoryDatabase() + signer = types.LatestSigner(gspec.Config) + db = rawdb.NewMemoryDatabase() + ) + + config.TerminalTotalDifficultyPassed = true + config.TerminalTotalDifficulty = common.Big0 + config.ShanghaiTime = u64(0) + + // init 0xaa with some storage elements + storage := make(map[common.Hash]common.Hash) + storage[common.Hash{0x00}] = common.Hash{0x00} + storage[common.Hash{0x01}] = common.Hash{0x01} + storage[common.Hash{0x02}] = common.Hash{0x02} + storage[common.Hash{0x03}] = common.HexToHash("0303") + gspec.Alloc[aa] = GenesisAccount{ + Balance: common.Big1, + Nonce: 1, + Storage: storage, + Code: common.Hex2Bytes("6042"), + } + gspec.Alloc[bb] = GenesisAccount{ + Balance: common.Big2, + Nonce: 1, + Storage: storage, + Code: common.Hex2Bytes("600154600354"), + } + + genesis := gspec.MustCommit(gendb) + + chain, _ := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) { + tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(address), address, big.NewInt(1000), params.TxGas, new(big.Int).Add(gen.BaseFee(), common.Big1), nil), signer, key) + gen.AddTx(tx) + if i == 1 { + gen.AddWithdrawal(&types.Withdrawal{ + Validator: 42, + Address: common.Address{0xee}, + Amount: 1337, + }) + gen.AddWithdrawal(&types.Withdrawal{ + Validator: 13, + Address: common.Address{0xee}, + Amount: 1, + }) + } + if i == 3 { + gen.AddWithdrawal(&types.Withdrawal{ + Validator: 42, + Address: common.Address{0xee}, + Amount: 1337, + }) + gen.AddWithdrawal(&types.Withdrawal{ + Validator: 13, + Address: common.Address{0xee}, + Amount: 1, + }) + } + }) + + // Import the chain. This runs all block validation rules. + blockchain, _ := NewBlockChain(db, nil, gspec, nil, beacon.NewFaker(), vm.Config{}, nil, nil) + defer blockchain.Stop() + + if i, err := blockchain.InsertChain(chain); err != nil { + fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err) + return + } + + // enforce that withdrawal indexes are monotonically increasing from 0 + var ( + withdrawalIndex uint64 + head = blockchain.CurrentBlock().Number.Uint64() + ) + for i := 0; i < int(head); i++ { + block := blockchain.GetBlockByNumber(uint64(i)) + if block == nil { + t.Fatalf("block %d not found", i) + } + if len(block.Withdrawals()) == 0 { + continue + } + for j := 0; j < len(block.Withdrawals()); j++ { + if block.Withdrawals()[j].Index != withdrawalIndex { + t.Fatalf("withdrawal index %d does not equal expected index %d", block.Withdrawals()[j].Index, withdrawalIndex) + } + withdrawalIndex += 1 + } + } +} + func ExampleGenerateChain() { var ( key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -88,7 +197,7 @@ func ExampleGenerateChain() { } state, _ := blockchain.State() - fmt.Printf("last block: #%d\n", blockchain.CurrentBlock().Number()) + fmt.Printf("last block: #%d\n", blockchain.CurrentBlock().Number) fmt.Println("balance of addr1:", state.GetBalance(addr1)) fmt.Println("balance of addr2:", state.GetBalance(addr2)) fmt.Println("balance of addr3:", state.GetBalance(addr3)) diff --git a/core/dao_test.go b/core/dao_test.go index 4ae86b50ff1..f2e8dfe8f9a 100644 --- a/core/dao_test.go +++ b/core/dao_test.go @@ -76,7 +76,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { // Create a pro-fork block, and try to feed into the no-fork chain bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) + blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64())) for j := 0; j < len(blocks)/2; j++ { blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] } @@ -87,19 +87,19 @@ func TestDAOForkRangeExtradata(t *testing.T) { t.Fatalf("failed to commit contra-fork head for expansion: %v", err) } bc.Stop() - blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) if _, err := conBc.InsertChain(blocks); err == nil { t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0]) } // Create a proper no-fork block for the contra-forker - blocks, _ = GenerateChain(&conConf, conBc.CurrentBlock(), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(&conConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) if _, err := conBc.InsertChain(blocks); err != nil { t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err) } // Create a no-fork block, and try to feed into the pro-fork chain bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) + blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) for j := 0; j < len(blocks)/2; j++ { blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] } @@ -110,12 +110,12 @@ func TestDAOForkRangeExtradata(t *testing.T) { t.Fatalf("failed to commit pro-fork head for expansion: %v", err) } bc.Stop() - blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) if _, err := proBc.InsertChain(blocks); err == nil { t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0]) } // Create a proper pro-fork block for the pro-forker - blocks, _ = GenerateChain(&proConf, proBc.CurrentBlock(), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(&proConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) if _, err := proBc.InsertChain(blocks); err != nil { t.Fatalf("pro-fork chain didn't accepted pro-fork block: %v", err) } @@ -124,7 +124,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer bc.Stop() - blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) + blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64())) for j := 0; j < len(blocks)/2; j++ { blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] } @@ -134,7 +134,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { t.Fatalf("failed to commit contra-fork head for expansion: %v", err) } - blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) if _, err := conBc.InsertChain(blocks); err != nil { t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) } @@ -142,7 +142,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer bc.Stop() - blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) + blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) for j := 0; j < len(blocks)/2; j++ { blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] } @@ -152,7 +152,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { t.Fatalf("failed to commit pro-fork head for expansion: %v", err) } - blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) if _, err := proBc.InsertChain(blocks); err != nil { t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err) } diff --git a/core/error.go b/core/error.go index 872ba8d365d..6782e370937 100644 --- a/core/error.go +++ b/core/error.go @@ -59,6 +59,10 @@ var ( // by a transaction is higher than what's left in the block. ErrGasLimitReached = errors.New("gas limit reached") + // ErrDataGasLimitReached is returned by the gas pool if the amount of data gas required by a + // transaction is higher than what's left in the block. + ErrDataGasLimitReached = errors.New("data gas limit reached") + // ErrInsufficientFundsForTransfer is returned if the transaction sender doesn't // have enough funds for transfer(topmost call only). ErrInsufficientFundsForTransfer = errors.New("insufficient funds for transfer") @@ -86,6 +90,10 @@ var ( // transaction with a tip higher than the total fee cap. ErrTipAboveFeeCap = errors.New("max priority fee per gas higher than max fee per gas") + // ErrMaxFeePerDataGas is returned if the transaction specified a + // max_fee_per_data_gas that is below the current data gas price. + ErrMaxFeePerDataGas = errors.New("max fee per data gas too low") + // ErrTipVeryHigh is a sanity error to avoid extremely big numbers specified // in the tip field. ErrTipVeryHigh = errors.New("max priority fee per gas higher than 2^256-1") @@ -100,4 +108,8 @@ var ( // ErrSenderNoEOA is returned if the sender of a transaction is a contract. ErrSenderNoEOA = errors.New("sender not an eoa") + + // ErrInternalFailure is returned when an unexpected internal error condition + // prevents execution. + ErrInternalFailure = errors.New("internal failure") ) diff --git a/core/evm.go b/core/evm.go index 35e12338ef0..05927afb78e 100644 --- a/core/evm.go +++ b/core/evm.go @@ -36,7 +36,10 @@ type ChainContext interface { } // NewEVMBlockContext creates a new context for use in the EVM. -func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext { +// +// excessDataGas must be set to the excessDataGas value from the *parent* block header, and can be +// nil if the parent block is not of EIP-4844 type. It is read only. +func NewEVMBlockContext(header *types.Header, excessDataGas *big.Int, chain ChainContext, author *common.Address) vm.BlockContext { var ( beneficiary common.Address baseFee *big.Int @@ -55,25 +58,33 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common if header.Difficulty.Cmp(common.Big0) == 0 { random = &header.MixDigest } + // In the event excessDataGas is nil (which happens if the parent block is pre-cancun), + // we bootstrap BlockContext.ExcessDataGas with the zero value. + edg := new(big.Int) + if excessDataGas != nil { + edg.Set(excessDataGas) + } return vm.BlockContext{ - CanTransfer: CanTransfer, - Transfer: Transfer, - GetHash: GetHashFn(header, chain), - Coinbase: beneficiary, - BlockNumber: new(big.Int).Set(header.Number), - Time: header.Time, - Difficulty: new(big.Int).Set(header.Difficulty), - BaseFee: baseFee, - GasLimit: header.GasLimit, - Random: random, + CanTransfer: CanTransfer, + Transfer: Transfer, + GetHash: GetHashFn(header, chain), + Coinbase: beneficiary, + BlockNumber: new(big.Int).Set(header.Number), + Time: header.Time, + Difficulty: new(big.Int).Set(header.Difficulty), + BaseFee: baseFee, + GasLimit: header.GasLimit, + Random: random, + ExcessDataGas: edg, } } // NewEVMTxContext creates a new transaction context for a single transaction. -func NewEVMTxContext(msg Message) vm.TxContext { +func NewEVMTxContext(msg *Message) vm.TxContext { return vm.TxContext{ - Origin: msg.From(), - GasPrice: new(big.Int).Set(msg.GasPrice()), + Origin: msg.From, + GasPrice: new(big.Int).Set(msg.GasPrice), + DataHashes: msg.DataHashes, } } diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 08a1da706d5..4dda280e715 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -107,14 +107,16 @@ func TestCreation(t *testing.T) { params.GoerliChainConfig, params.GoerliGenesisHash, []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block - {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block - {1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block - {4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block - {4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block - {5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block - {5062605, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 0}}, // First London block - {6000000, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 0}}, // Future London block + {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block + {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block + {1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block + {4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block + {4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block + {5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block + {5062605, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // First London block + {6000000, 1678832735, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // Last London block + {6000001, 1678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 0}}, // First Shanghai block + {6500000, 2678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 0}}, // Future Shanghai block }, }, // Sepolia test cases @@ -306,7 +308,7 @@ func TestValidation(t *testing.T) { // Local is mainnet Gray Glacier, and isn't aware of more forks. Remote announces Gray Glacier + // 0xffffffff. Local needs software update, reject. - {×tampedConfig, 15050000, 0, ID{Hash: checksumToBytes(checksumUpdate(0xf0afd0e3, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, + {params.MainnetChainConfig, 15050000, 0, ID{Hash: checksumToBytes(checksumUpdate(0xf0afd0e3, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, // Local is mainnet Gray Glacier, and is aware of Shanghai. Remote announces Shanghai + // 0xffffffff. Local needs software update, reject. diff --git a/core/gaspool.go b/core/gaspool.go index e3795c1ee9e..df9b782d4ca 100644 --- a/core/gaspool.go +++ b/core/gaspool.go @@ -23,32 +23,68 @@ import ( // GasPool tracks the amount of gas available during execution of the transactions // in a block. The zero value is a pool with zero gas available. -type GasPool uint64 +type GasPool struct { + gas, dataGas uint64 +} // AddGas makes gas available for execution. func (gp *GasPool) AddGas(amount uint64) *GasPool { - if uint64(*gp) > math.MaxUint64-amount { + if gp.gas > math.MaxUint64-amount { panic("gas pool pushed above uint64") } - *(*uint64)(gp) += amount + gp.gas += amount return gp } // SubGas deducts the given amount from the pool if enough gas is // available and returns an error otherwise. func (gp *GasPool) SubGas(amount uint64) error { - if uint64(*gp) < amount { + if gp.gas < amount { return ErrGasLimitReached } - *(*uint64)(gp) -= amount + gp.gas -= amount return nil } // Gas returns the amount of gas remaining in the pool. func (gp *GasPool) Gas() uint64 { - return uint64(*gp) + return gp.gas +} + +// AddDataGas makes data gas available for execution. +func (gp *GasPool) AddDataGas(amount uint64) *GasPool { + if gp.dataGas > math.MaxUint64-amount { + panic("data gas pool pushed above uint64") + } + gp.dataGas += amount + return gp +} + +// SubDataGas deducts the given amount from the pool if enough data gas is available and returns an +// error otherwise. +func (gp *GasPool) SubDataGas(amount uint64) error { + if gp.dataGas < amount { + return ErrDataGasLimitReached + } + gp.dataGas -= amount + return nil +} + +// DataGas returns the amount of data gas remaining in the pool. +func (gp *GasPool) DataGas() uint64 { + return gp.dataGas +} + +// SetGas sets the amount of gas with the provided number. +func (gp *GasPool) SetGas(gas uint64) { + gp.gas = gas +} + +// SetDataGas sets the amount of data gas with the provided number. +func (gp *GasPool) SetDataGas(dataGas uint64) { + gp.dataGas = dataGas } func (gp *GasPool) String() string { - return fmt.Sprintf("%d", *gp) + return fmt.Sprintf("gas: %d, data_gas: %d", gp.gas, gp.dataGas) } diff --git a/core/gen_genesis.go b/core/gen_genesis.go index 4e0844e889a..b799e87d74b 100644 --- a/core/gen_genesis.go +++ b/core/gen_genesis.go @@ -18,19 +18,20 @@ var _ = (*genesisSpecMarshaling)(nil) // MarshalJSON marshals as JSON. func (g Genesis) MarshalJSON() ([]byte, error) { type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce math.HexOrDecimal64 `json:"nonce"` - Timestamp math.HexOrDecimal64 `json:"timestamp"` - ExtraData hexutil.Bytes `json:"extraData"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash common.Hash `json:"mixHash"` - Coinbase common.Address `json:"coinbase"` - Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` - Number math.HexOrDecimal64 `json:"number"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + Config *params.ChainConfig `json:"config"` + Nonce math.HexOrDecimal64 `json:"nonce"` + Timestamp math.HexOrDecimal64 `json:"timestamp"` + ExtraData hexutil.Bytes `json:"extraData"` + GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + Mixhash common.Hash `json:"mixHash"` + Coinbase common.Address `json:"coinbase"` + Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` + Number math.HexOrDecimal64 `json:"number"` + GasUsed math.HexOrDecimal64 `json:"gasUsed"` + ParentHash common.Hash `json:"parentHash"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + ExcessDataGas *math.HexOrDecimal256 `json:"excessDataGas"` } var enc Genesis enc.Config = g.Config @@ -51,25 +52,27 @@ func (g Genesis) MarshalJSON() ([]byte, error) { enc.GasUsed = math.HexOrDecimal64(g.GasUsed) enc.ParentHash = g.ParentHash enc.BaseFee = (*math.HexOrDecimal256)(g.BaseFee) + enc.ExcessDataGas = (*math.HexOrDecimal256)(g.ExcessDataGas) return json.Marshal(&enc) } // UnmarshalJSON unmarshals from JSON. func (g *Genesis) UnmarshalJSON(input []byte) error { type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce *math.HexOrDecimal64 `json:"nonce"` - Timestamp *math.HexOrDecimal64 `json:"timestamp"` - ExtraData *hexutil.Bytes `json:"extraData"` - GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash *common.Hash `json:"mixHash"` - Coinbase *common.Address `json:"coinbase"` - Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` - Number *math.HexOrDecimal64 `json:"number"` - GasUsed *math.HexOrDecimal64 `json:"gasUsed"` - ParentHash *common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + Config *params.ChainConfig `json:"config"` + Nonce *math.HexOrDecimal64 `json:"nonce"` + Timestamp *math.HexOrDecimal64 `json:"timestamp"` + ExtraData *hexutil.Bytes `json:"extraData"` + GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + Mixhash *common.Hash `json:"mixHash"` + Coinbase *common.Address `json:"coinbase"` + Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` + Number *math.HexOrDecimal64 `json:"number"` + GasUsed *math.HexOrDecimal64 `json:"gasUsed"` + ParentHash *common.Hash `json:"parentHash"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + ExcessDataGas *math.HexOrDecimal256 `json:"excessDataGas"` } var dec Genesis if err := json.Unmarshal(input, &dec); err != nil { @@ -120,5 +123,8 @@ func (g *Genesis) UnmarshalJSON(input []byte) error { if dec.BaseFee != nil { g.BaseFee = (*big.Int)(dec.BaseFee) } + if dec.ExcessDataGas != nil { + g.ExcessDataGas = (*big.Int)(dec.ExcessDataGas) + } return nil } diff --git a/core/genesis.go b/core/genesis.go index 1120be015f7..def7afa86aa 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -59,10 +59,11 @@ type Genesis struct { // These fields are used for consensus tests. Please don't use them // in actual genesis blocks. - Number uint64 `json:"number"` - GasUsed uint64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *big.Int `json:"baseFeePerGas"` + Number uint64 `json:"number"` + GasUsed uint64 `json:"gasUsed"` + ParentHash common.Hash `json:"parentHash"` + BaseFee *big.Int `json:"baseFeePerGas"` + ExcessDataGas *big.Int `json:"excessDataGas"` } func ReadGenesis(db ethdb.Database) (*Genesis, error) { @@ -138,7 +139,7 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) { // flush is very similar with deriveHash, but the main difference is // all the generated states will be persisted into the given database. // Also, the genesis state specification will be flushed as well. -func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database) error { +func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error { statedb, err := state.New(common.Hash{}, state.NewDatabaseWithNodeDB(db, triedb), nil) if err != nil { return err @@ -166,15 +167,15 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database) error { if err != nil { return err } - rawdb.WriteGenesisStateSpec(db, root, blob) + rawdb.WriteGenesisStateSpec(db, blockhash, blob) return nil } // CommitGenesisState loads the stored genesis state with the given block // hash and commits it into the provided trie database. -func CommitGenesisState(db ethdb.Database, triedb *trie.Database, hash common.Hash) error { +func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error { var alloc GenesisAlloc - blob := rawdb.ReadGenesisStateSpec(db, hash) + blob := rawdb.ReadGenesisStateSpec(db, blockhash) if len(blob) != 0 { if err := alloc.UnmarshalJSON(blob); err != nil { return err @@ -186,7 +187,7 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, hash common.Ha // - supported networks(mainnet, testnets), recover with defined allocations // - private network, can't recover var genesis *Genesis - switch hash { + switch blockhash { case params.MainnetGenesisHash: genesis = DefaultGenesisBlock() case params.RinkebyGenesisHash: @@ -202,7 +203,7 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, hash common.Ha return errors.New("not found") } } - return alloc.flush(db, triedb) + return alloc.flush(db, triedb, blockhash) } // GenesisAccount is an account in the state of the genesis block. @@ -216,15 +217,16 @@ type GenesisAccount struct { // field type overrides for gencodec type genesisSpecMarshaling struct { - Nonce math.HexOrDecimal64 - Timestamp math.HexOrDecimal64 - ExtraData hexutil.Bytes - GasLimit math.HexOrDecimal64 - GasUsed math.HexOrDecimal64 - Number math.HexOrDecimal64 - Difficulty *math.HexOrDecimal256 - BaseFee *math.HexOrDecimal256 - Alloc map[common.UnprefixedAddress]GenesisAccount + Nonce math.HexOrDecimal64 + Timestamp math.HexOrDecimal64 + ExtraData hexutil.Bytes + GasLimit math.HexOrDecimal64 + GasUsed math.HexOrDecimal64 + Number math.HexOrDecimal64 + Difficulty *math.HexOrDecimal256 + BaseFee *math.HexOrDecimal256 + ExcessDataGas *math.HexOrDecimal256 + Alloc map[common.UnprefixedAddress]GenesisAccount } type genesisAccountMarshaling struct { @@ -317,7 +319,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen // We have the genesis block in database(perhaps in ancient database) // but the corresponding state is missing. header := rawdb.ReadHeader(db, stored, 0) - if _, err := state.New(header.Root, state.NewDatabaseWithNodeDB(db, triedb), nil); err != nil { + if header.Root != types.EmptyRootHash && !rawdb.HasLegacyTrieNode(db, header.Root) { if genesis == nil { genesis = DefaultGenesisBlock() } @@ -458,16 +460,24 @@ func (g *Genesis) ToBlock() *types.Block { if g.Difficulty == nil && g.Mixhash == (common.Hash{}) { head.Difficulty = params.GenesisDifficulty } - if g.Config != nil && g.Config.IsLondon(common.Big0) { - if g.BaseFee != nil { - head.BaseFee = g.BaseFee - } else { - head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) + if g.Config != nil { + if g.Config.IsLondon(common.Big0) { + if g.BaseFee != nil { + head.BaseFee = g.BaseFee + } else { + head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) + } + } + if g.Config.IsShanghai(g.Timestamp) { + head.WithdrawalsHash = &types.EmptyRootHash + } + if g.Config.IsCancun(g.Timestamp) { + head.SetExcessDataGas(g.ExcessDataGas) } } var withdrawals []*types.Withdrawal if g.Config != nil && g.Config.IsShanghai(g.Timestamp) { - head.WithdrawalsHash = &types.EmptyRootHash + head.WithdrawalsHash = &types.EmptyWithdrawalsHash withdrawals = make([]*types.Withdrawal, 0) } return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals) @@ -493,7 +503,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *trie.Database) (*types.Block // All the checks has passed, flush the states derived from the genesis // specification as well as the specification itself into the provided // database. - if err := g.Alloc.flush(db, triedb); err != nil { + if err := g.Alloc.flush(db, triedb, block.Hash()); err != nil { return nil, err } rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) @@ -568,6 +578,16 @@ func DefaultSepoliaGenesisBlock() *Genesis { } } +// DefaultSepoliaGenesisBlock returns the Sepolia network genesis block. +func DefaultEIP4844GenesisBlock() *Genesis { + g := new(Genesis) + reader := strings.NewReader(eip4844AllocData) + if err := json.NewDecoder(reader).Decode(g); err != nil { + panic(err) + } + return g +} + // DeveloperGenesisBlock returns the 'geth --dev' genesis block. func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis { // Override the default period to the user requested one diff --git a/core/genesis_alloc.go b/core/genesis_alloc.go index 542dcc4120c..006a3f1ef5f 100644 --- a/core/genesis_alloc.go +++ b/core/genesis_alloc.go @@ -890,3 +890,57 @@ const KilnAllocData = `{ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0" }` + +const eip4844AllocData = `{ + "config": { + "chainId": 1331, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "shardingForkBlock": 0, + "clique": { + "period": 14, + "epoch": 30000 + }, + "terminalTotalDifficulty": 40 + }, + "nonce": "0x42", + "timestamp": "1660631592", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000BB427322C6C4Ed83cDCA287337AeF5bA734D01100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1C9C380", + "difficulty": "0x0", + "coinbase": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x7", + "alloc": { + "0x8A04d14125D0FDCDc742F4A05C051De07232EDa4": { + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a7146100445780632289511814610079578063621fd1301461008e578063c5f2892f146100b0575b600080fd5b34801561005057600080fd5b5061006461005f366004610cdd565b6100d3565b60405190151581526020015b60405180910390f35b61008c610087366004610d57565b61010a565b005b34801561009a57600080fd5b506100a3610942565b6040516100709190610e56565b3480156100bc57600080fd5b506100c5610954565b604051908152602001610070565b60006001600160e01b031982166301ffc9a760e01b148061010457506001600160e01b03198216638564090760e01b145b92915050565b6030861461016e5760405162461bcd60e51b815260206004820152602660248201527f4465706f736974436f6e74726163743a20696e76616c6964207075626b6579206044820152650d8cadccee8d60d31b60648201526084015b60405180910390fd5b602084146101dd5760405162461bcd60e51b815260206004820152603660248201527f4465706f736974436f6e74726163743a20696e76616c696420776974686472616044820152750eec2d8bec6e4cac8cadce8d2c2d8e640d8cadccee8d60531b6064820152608401610165565b6060821461023f5760405162461bcd60e51b815260206004820152602960248201527f4465706f736974436f6e74726163743a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b6064820152608401610165565b670de0b6b3a76400003410156102a65760405162461bcd60e51b815260206004820152602660248201527f4465706f736974436f6e74726163743a206465706f7369742076616c756520746044820152656f6f206c6f7760d01b6064820152608401610165565b6102b4633b9aca0034610e7f565b1561031d5760405162461bcd60e51b815260206004820152603360248201527f4465706f736974436f6e74726163743a206465706f7369742076616c7565206e6044820152726f74206d756c7469706c65206f66206777656960681b6064820152608401610165565b600061032d633b9aca0034610ea9565b905067ffffffffffffffff8111156103975760405162461bcd60e51b815260206004820152602760248201527f4465706f736974436f6e74726163743a206465706f7369742076616c756520746044820152660dede40d0d2ced60cb1b6064820152608401610165565b60006103a282610b29565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6103d7602054610b29565b6040516103eb989796959493929190610ee6565b60405180910390a1600060028a8a600060801b60405160200161041093929190610f59565b60408051601f198184030181529082905261042a91610f80565b602060405180830381855afa158015610447573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061046a9190610f9c565b9050600060028061047e6040848a8c610fb5565b60405160200161048f929190610fdf565b60408051601f19818403018152908290526104a991610f80565b602060405180830381855afa1580156104c6573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104e99190610f9c565b60026104f8896040818d610fb5565b60405161050c929190600090602001610fef565b60408051601f198184030181529082905261052691610f80565b602060405180830381855afa158015610543573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105669190610f9c565b60408051602081019390935282015260600160408051601f198184030181529082905261059291610f80565b602060405180830381855afa1580156105af573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105d29190610f9c565b90506000600280848c8c6040516020016105ee93929190611001565b60408051601f198184030181529082905261060891610f80565b602060405180830381855afa158015610625573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106489190610f9c565b604051600290610661908890600090889060200161101b565b60408051601f198184030181529082905261067b91610f80565b602060405180830381855afa158015610698573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106bb9190610f9c565b60408051602081019390935282015260600160408051601f19818403018152908290526106e791610f80565b602060405180830381855afa158015610704573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107279190610f9c565b90508581146107bb5760405162461bcd60e51b815260206004820152605460248201527f4465706f736974436f6e74726163743a207265636f6e7374727563746564204460448201527f65706f7369744461746120646f6573206e6f74206d6174636820737570706c6960648201527319590819195c1bdcda5d17d9185d1857dc9bdbdd60621b608482015260a401610165565b60016107c960206002611137565b6107d39190611143565b6020541061082d5760405162461bcd60e51b815260206004820152602160248201527f4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6044820152601b60fa1b6064820152608401610165565b600160206000828254610840919061115a565b909155505060205460005b602081101561092957816001166001141561088357826000826020811061087457610874611172565b01555061093995505050505050565b60026000826020811061089857610898611172565b0154604080516020810192909252810185905260600160408051601f19818403018152908290526108c891610f80565b602060405180830381855afa1580156108e5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109089190610f9c565b9250610915600283610ea9565b91508061092181611188565b91505061084b565b506109326111a3565b5050505050505b50505050505050565b606061094f602054610b29565b905090565b6020546000908190815b6020811015610aa55781600116600114156109ff5760026000826020811061098857610988611172565b0154604080516020810192909252810185905260600160408051601f19818403018152908290526109b891610f80565b602060405180830381855afa1580156109d5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109f89190610f9c565b9250610a86565b60028360218360208110610a1557610a15611172565b015460408051602081019390935282015260600160408051601f1981840301815290829052610a4391610f80565b602060405180830381855afa158015610a60573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610a839190610f9c565b92505b610a91600283610ea9565b915080610a9d81611188565b91505061095e565b50600282610ab4602054610b29565b604051610ac89291906000906020016111b9565b60408051601f1981840301815290829052610ae291610f80565b602060405180830381855afa158015610aff573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610b229190610f9c565b9250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b82600081518110610b6957610b69611172565b60200101906001600160f81b031916908160001a9053508060061a60f81b82600181518110610b9a57610b9a611172565b60200101906001600160f81b031916908160001a9053508060051a60f81b82600281518110610bcb57610bcb611172565b60200101906001600160f81b031916908160001a9053508060041a60f81b82600381518110610bfc57610bfc611172565b60200101906001600160f81b031916908160001a9053508060031a60f81b82600481518110610c2d57610c2d611172565b60200101906001600160f81b031916908160001a9053508060021a60f81b82600581518110610c5e57610c5e611172565b60200101906001600160f81b031916908160001a9053508060011a60f81b82600681518110610c8f57610c8f611172565b60200101906001600160f81b031916908160001a9053508060001a60f81b82600781518110610cc057610cc0611172565b60200101906001600160f81b031916908160001a90535050919050565b600060208284031215610cef57600080fd5b81356001600160e01b031981168114610d0757600080fd5b9392505050565b60008083601f840112610d2057600080fd5b50813567ffffffffffffffff811115610d3857600080fd5b602083019150836020828501011115610d5057600080fd5b9250929050565b60008060008060008060006080888a031215610d7257600080fd5b873567ffffffffffffffff80821115610d8a57600080fd5b610d968b838c01610d0e565b909950975060208a0135915080821115610daf57600080fd5b610dbb8b838c01610d0e565b909750955060408a0135915080821115610dd457600080fd5b50610de18a828b01610d0e565b989b979a50959894979596606090950135949350505050565b60005b83811015610e15578181015183820152602001610dfd565b83811115610e24576000848401525b50505050565b60008151808452610e42816020860160208601610dfa565b601f01601f19169290920160200192915050565b602081526000610d076020830184610e2a565b634e487b7160e01b600052601260045260246000fd5b600082610e8e57610e8e610e69565b500690565b634e487b7160e01b600052601160045260246000fd5b600082610eb857610eb8610e69565b500490565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60a081526000610efa60a083018a8c610ebd565b8281036020840152610f0d81898b610ebd565b90508281036040840152610f218188610e2a565b90508281036060840152610f36818688610ebd565b90508281036080840152610f4a8185610e2a565b9b9a5050505050505050505050565b828482376fffffffffffffffffffffffffffffffff19919091169101908152601001919050565b60008251610f92818460208701610dfa565b9190910192915050565b600060208284031215610fae57600080fd5b5051919050565b60008085851115610fc557600080fd5b83861115610fd257600080fd5b5050820193919092039150565b8183823760009101908152919050565b82848237909101908152602001919050565b838152818360208301376000910160200190815292915050565b6000845161102d818460208901610dfa565b67ffffffffffffffff199490941691909301908152601881019190915260380192915050565b600181815b8085111561108e57816000190482111561107457611074610e93565b8085161561108157918102915b93841c9390800290611058565b509250929050565b6000826110a557506001610104565b816110b257506000610104565b81600181146110c857600281146110d2576110ee565b6001915050610104565b60ff8411156110e3576110e3610e93565b50506001821b610104565b5060208310610133831016604e8410600b8410161715611111575081810a610104565b61111b8383611053565b806000190482111561112f5761112f610e93565b029392505050565b6000610d078383611096565b60008282101561115557611155610e93565b500390565b6000821982111561116d5761116d610e93565b500190565b634e487b7160e01b600052603260045260246000fd5b600060001982141561119c5761119c610e93565b5060010190565b634e487b7160e01b600052600160045260246000fd5b838152600083516111d1816020850160208801610dfa565b67ffffffffffffffff1993909316919092016020810191909152603801939250505056fea26469706673582212203a996a47fa4d82c10ba56e7ae9395436827d01429310fe088a93150149dcb3cd64736f6c63430008090033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x3294cf82a58a8ccea2ab14768c45bd3a3d16ca02685fe619f46b5e8964722e1a", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0xd32fd9eded28310711155ca8b78b29373d35511905e063f90585f97a372a8f29", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0xa02f79d5a09a5d0964d5b2befb082d3528d28407da1da541e199f742ed477d68", + "0x0000000000000000000000000000000000000000000000000000000000000020": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + "balance": "0x3782dace9d9000000" + }, + "0xBB427322C6C4Ed83cDCA287337AeF5bA734D0110": { + "balance": "0x152d02c7e14af6800000" + }, + "0x10F5d45854e038071485AC9e402308cF80D2d2fE": { + "balance": "0x152d02c7e14af6800000" + }, + "0x60E61a5b5787aCBDAB431Ac7cAFEB1eFbF9b4d9e": { + "balance": "0x152d02c7e14af6800000" + } + } +}` diff --git a/core/headerchain.go b/core/headerchain.go index d40d26f72bf..aed3c720c63 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -389,7 +389,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time, if res.ignored > 0 { context = append(context, []interface{}{"ignored", res.ignored}...) } - log.Info("Imported new block headers", context...) + log.Debug("Imported new block headers", context...) return res.status, err } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 9b90d8f20cc..fa788fd0061 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -37,7 +37,7 @@ import ( func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { var data []byte db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - data, _ = reader.Ancient(chainFreezerHashTable, number) + data, _ = reader.Ancient(ChainFreezerHashTable, number) if len(data) == 0 { // Get it by hash from leveldb data, _ = db.Get(headerHashKey(number)) @@ -334,7 +334,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu } // read remaining from ancients max := count * 700 - data, err := db.AncientRange(chainFreezerHeaderTable, i+1-count, count, max) + data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, max) if err == nil && uint64(len(data)) == count { // the data is on the order [h, h+1, .., n] -- reordering needed for i := range data { @@ -351,7 +351,7 @@ func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValu // First try to look up the data in ancient database. Extra hash // comparison is necessary since ancient database only maintains // the canonical data. - data, _ = reader.Ancient(chainFreezerHeaderTable, number) + data, _ = reader.Ancient(ChainFreezerHeaderTable, number) if len(data) > 0 && crypto.Keccak256Hash(data) == hash { return nil } @@ -427,7 +427,7 @@ func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number // isCanon is an internal utility method, to check whether the given number/hash // is part of the ancient (canon) set. func isCanon(reader ethdb.AncientReaderOp, number uint64, hash common.Hash) bool { - h, err := reader.Ancient(chainFreezerHashTable, number) + h, err := reader.Ancient(ChainFreezerHashTable, number) if err != nil { return false } @@ -443,7 +443,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue db.ReadAncients(func(reader ethdb.AncientReaderOp) error { // Check if the data is in ancients if isCanon(reader, number, hash) { - data, _ = reader.Ancient(chainFreezerBodiesTable, number) + data, _ = reader.Ancient(ChainFreezerBodiesTable, number) return nil } // If not, try reading from leveldb @@ -458,7 +458,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { var data []byte db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - data, _ = reader.Ancient(chainFreezerBodiesTable, number) + data, _ = reader.Ancient(ChainFreezerBodiesTable, number) if len(data) > 0 { return nil } @@ -526,7 +526,7 @@ func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { db.ReadAncients(func(reader ethdb.AncientReaderOp) error { // Check if the data is in ancients if isCanon(reader, number, hash) { - data, _ = reader.Ancient(chainFreezerDifficultyTable, number) + data, _ = reader.Ancient(ChainFreezerDifficultyTable, number) return nil } // If not, try reading from leveldb @@ -586,7 +586,7 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa db.ReadAncients(func(reader ethdb.AncientReaderOp) error { // Check if the data is in ancients if isCanon(reader, number, hash) { - data, _ = reader.Ancient(chainFreezerReceiptTable, number) + data, _ = reader.Ancient(ChainFreezerReceiptTable, number) return nil } // If not, try reading from leveldb @@ -636,7 +636,19 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para log.Error("Missing body but have receipt", "hash", hash, "number", number) return nil } - if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil { + header := ReadHeader(db, hash, number) + var baseFee *big.Int + var parentExcessDataGas *big.Int + if header == nil { + baseFee = big.NewInt(0) + } else { + baseFee = header.BaseFee + parentHeader := ReadHeader(db, header.ParentHash, number-1) + if parentHeader != nil { + parentExcessDataGas = parentHeader.ExcessDataGas + } + } + if err := receipts.DeriveFields(config, hash, number, header.Time, baseFee, parentExcessDataGas, body.Transactions); err != nil { log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) return nil } @@ -787,19 +799,19 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage, td *big.Int) error { num := block.NumberU64() - if err := op.AppendRaw(chainFreezerHashTable, num, block.Hash().Bytes()); err != nil { + if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil { return fmt.Errorf("can't add block %d hash: %v", num, err) } - if err := op.Append(chainFreezerHeaderTable, num, header); err != nil { + if err := op.Append(ChainFreezerHeaderTable, num, header); err != nil { return fmt.Errorf("can't append block header %d: %v", num, err) } - if err := op.Append(chainFreezerBodiesTable, num, block.Body()); err != nil { + if err := op.Append(ChainFreezerBodiesTable, num, block.Body()); err != nil { return fmt.Errorf("can't append block body %d: %v", num, err) } - if err := op.Append(chainFreezerReceiptTable, num, receipts); err != nil { + if err := op.Append(ChainFreezerReceiptTable, num, receipts); err != nil { return fmt.Errorf("can't append block %d receipts: %v", num, err) } - if err := op.Append(chainFreezerDifficultyTable, num, td); err != nil { + if err := op.Append(ChainFreezerDifficultyTable, num, td); err != nil { return fmt.Errorf("can't append block %d total difficulty: %v", num, err) } return nil diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index f7f8d0b086d..e4a7a6f4fcd 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -113,8 +113,8 @@ func TestBlockStorage(t *testing.T) { block := types.NewBlockWithHeader(&types.Header{ Extra: []byte("test block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { t.Fatalf("Non existent block returned: %v", entry) @@ -161,8 +161,8 @@ func TestPartialBlockStorage(t *testing.T) { block := types.NewBlockWithHeader(&types.Header{ Extra: []byte("test block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) // Store a header and check that it's not recognized as a block WriteHeader(db, block.Header()) @@ -198,8 +198,8 @@ func TestBadBlockStorage(t *testing.T) { Number: big.NewInt(1), Extra: []byte("bad block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) if entry := ReadBadBlock(db, block.Hash()); entry != nil { t.Fatalf("Non existent block returned: %v", entry) @@ -216,8 +216,8 @@ func TestBadBlockStorage(t *testing.T) { Number: big.NewInt(2), Extra: []byte("bad block two"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) WriteBadBlock(db, blockTwo) @@ -235,8 +235,8 @@ func TestBadBlockStorage(t *testing.T) { Number: big.NewInt(int64(n)), Extra: []byte("bad block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) WriteBadBlock(db, block) } @@ -377,13 +377,20 @@ func TestBlockReceiptStorage(t *testing.T) { receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) receipts := []*types.Receipt{receipt1, receipt2} + header := types.Header{ + Number: big.NewInt(0), + Time: 0, + Extra: []byte("test read receipts"), + } + hash := header.Hash() + // Check that no receipt entries are in a pristine database - hash := common.BytesToHash([]byte{0x03, 0x14}) if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 { t.Fatalf("non existent receipts returned: %v", rs) } - // Insert the body that corresponds to the receipts + // Insert the body & header that corresponds to the receipts WriteBody(db, hash, 0, body) + WriteHeader(db, &header) // Insert the receipt slice into the database and check presence WriteReceipts(db, hash, 0, receipts) @@ -446,8 +453,8 @@ func TestAncientStorage(t *testing.T) { Number: big.NewInt(0), Extra: []byte("test block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) // Ensure nothing non-existent will be read hash, number := block.Hash(), block.NumberU64() @@ -889,8 +896,8 @@ func TestHeadersRLPStorage(t *testing.T) { Number: big.NewInt(int64(i)), Extra: []byte("test block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, ParentHash: pHash, }) chain = append(chain, block) diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go index 7a9e6442f01..2ff29d1add9 100644 --- a/core/rawdb/accessors_metadata.go +++ b/core/rawdb/accessors_metadata.go @@ -82,15 +82,15 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha } // ReadGenesisStateSpec retrieves the genesis state specification based on the -// given genesis hash. -func ReadGenesisStateSpec(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, _ := db.Get(genesisStateSpecKey(hash)) +// given genesis (block-)hash. +func ReadGenesisStateSpec(db ethdb.KeyValueReader, blockhash common.Hash) []byte { + data, _ := db.Get(genesisStateSpecKey(blockhash)) return data } // WriteGenesisStateSpec writes the genesis state specification into the disk. -func WriteGenesisStateSpec(db ethdb.KeyValueWriter, hash common.Hash, data []byte) { - if err := db.Put(genesisStateSpecKey(hash), data); err != nil { +func WriteGenesisStateSpec(db ethdb.KeyValueWriter, blockhash common.Hash, data []byte) { + if err := db.Put(genesisStateSpecKey(blockhash), data); err != nil { log.Crit("Failed to store genesis state", "err", err) } } diff --git a/core/rawdb/ancient_scheme.go b/core/rawdb/ancient_scheme.go index 047b504a24b..b0428c5f5bd 100644 --- a/core/rawdb/ancient_scheme.go +++ b/core/rawdb/ancient_scheme.go @@ -18,30 +18,30 @@ package rawdb // The list of table names of chain freezer. const ( - // chainFreezerHeaderTable indicates the name of the freezer header table. - chainFreezerHeaderTable = "headers" + // ChainFreezerHeaderTable indicates the name of the freezer header table. + ChainFreezerHeaderTable = "headers" - // chainFreezerHashTable indicates the name of the freezer canonical hash table. - chainFreezerHashTable = "hashes" + // ChainFreezerHashTable indicates the name of the freezer canonical hash table. + ChainFreezerHashTable = "hashes" - // chainFreezerBodiesTable indicates the name of the freezer block body table. - chainFreezerBodiesTable = "bodies" + // ChainFreezerBodiesTable indicates the name of the freezer block body table. + ChainFreezerBodiesTable = "bodies" - // chainFreezerReceiptTable indicates the name of the freezer receipts table. - chainFreezerReceiptTable = "receipts" + // ChainFreezerReceiptTable indicates the name of the freezer receipts table. + ChainFreezerReceiptTable = "receipts" - // chainFreezerDifficultyTable indicates the name of the freezer total difficulty table. - chainFreezerDifficultyTable = "diffs" + // ChainFreezerDifficultyTable indicates the name of the freezer total difficulty table. + ChainFreezerDifficultyTable = "diffs" ) // chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables. // Hashes and difficulties don't compress well. var chainFreezerNoSnappy = map[string]bool{ - chainFreezerHeaderTable: false, - chainFreezerHashTable: true, - chainFreezerBodiesTable: false, - chainFreezerReceiptTable: false, - chainFreezerDifficultyTable: true, + ChainFreezerHeaderTable: false, + ChainFreezerHashTable: true, + ChainFreezerBodiesTable: false, + ChainFreezerReceiptTable: false, + ChainFreezerDifficultyTable: true, } // The list of identifiers of ancient stores. diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go index 738295cfb70..167afc38894 100644 --- a/core/rawdb/chain_freezer.go +++ b/core/rawdb/chain_freezer.go @@ -55,8 +55,8 @@ type chainFreezer struct { } // newChainFreezer initializes the freezer for ancient chain data. -func newChainFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*chainFreezer, error) { - freezer, err := NewFreezer(datadir, namespace, readonly, maxTableSize, tables) +func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFreezer, error) { + freezer, err := NewChainFreezer(datadir, namespace, readonly) if err != nil { return nil, err } @@ -280,19 +280,19 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash } // Write to the batch. - if err := op.AppendRaw(chainFreezerHashTable, number, hash[:]); err != nil { + if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil { return fmt.Errorf("can't write hash to Freezer: %v", err) } - if err := op.AppendRaw(chainFreezerHeaderTable, number, header); err != nil { + if err := op.AppendRaw(ChainFreezerHeaderTable, number, header); err != nil { return fmt.Errorf("can't write header to Freezer: %v", err) } - if err := op.AppendRaw(chainFreezerBodiesTable, number, body); err != nil { + if err := op.AppendRaw(ChainFreezerBodiesTable, number, body); err != nil { return fmt.Errorf("can't write body to Freezer: %v", err) } - if err := op.AppendRaw(chainFreezerReceiptTable, number, receipts); err != nil { + if err := op.AppendRaw(ChainFreezerReceiptTable, number, receipts); err != nil { return fmt.Errorf("can't write receipts to Freezer: %v", err) } - if err := op.AppendRaw(chainFreezerDifficultyTable, number, td); err != nil { + if err := op.AppendRaw(ChainFreezerDifficultyTable, number, td); err != nil { return fmt.Errorf("can't write td to Freezer: %v", err) } diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go index 85ad88e2917..102943516ef 100644 --- a/core/rawdb/chain_iterator.go +++ b/core/rawdb/chain_iterator.go @@ -50,7 +50,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) { if i+count > frozen { count = frozen - i } - data, err := db.AncientRange(chainFreezerHashTable, i, count, 32*count) + data, err := db.AncientRange(ChainFreezerHashTable, i, count, 32*count) if err != nil { log.Crit("Failed to init database from freezer", "err", err) } diff --git a/core/rawdb/database.go b/core/rawdb/database.go index ef80c251a45..6c545032f96 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -200,8 +200,9 @@ func resolveChainFreezerDir(ancient string) string { // where the chain freezer can be opened. func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly bool) (ethdb.Database, error) { // Create the idle freezer instance - frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, freezerTableSize, chainFreezerNoSnappy) + frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly) if err != nil { + printChainMetadata(db) return nil, err } // Since the freezer can be stored separately from the user's key-value database, @@ -231,10 +232,12 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st // If the freezer already contains something, ensure that the genesis blocks // match, otherwise we might mix up freezers across chains and destroy both // the freezer and the key-value store. - frgenesis, err := frdb.Ancient(chainFreezerHashTable, 0) + frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0) if err != nil { + printChainMetadata(db) return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err) } else if !bytes.Equal(kvgenesis, frgenesis) { + printChainMetadata(db) return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis) } // Key-value store and freezer belong to the same network. Ensure that they @@ -242,8 +245,19 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 { // Subsequent header after the freezer limit is missing from the database. // Reject startup if the database has a more recent head. - if ldbNum := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); ldbNum > frozen-1 { - return nil, fmt.Errorf("gap in the chain between ancients (#%d) and leveldb (#%d) ", frozen, ldbNum) + if head := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 { + // Find the smallest block stored in the key-value store + // in range of [frozen, head] + var number uint64 + for number = frozen; number <= head; number++ { + if present, _ := db.Has(headerHashKey(number)); present { + break + } + } + // We are about to exit on error. Print database metdata beore exiting + printChainMetadata(db) + return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ", + frozen-1, number, head) } // Database contains only older data than the freezer, this happens if the // state was wiped and reinited from an existing freezer. @@ -260,6 +274,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st // Key-value store contains more data than the genesis block, make sure we // didn't freeze anything yet. if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 { + printChainMetadata(db) return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path") } // Block #1 is still in the database, we're allowed to init a new freezer @@ -581,3 +596,42 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { } return nil } + +// printChainMetadata prints out chain metadata to stderr. +func printChainMetadata(db ethdb.KeyValueStore) { + fmt.Fprintf(os.Stderr, "Chain metadata\n") + for _, v := range ReadChainMetadata(db) { + fmt.Fprintf(os.Stderr, " %s\n", strings.Join(v, ": ")) + } + fmt.Fprintf(os.Stderr, "\n\n") +} + +// ReadChainMetadata returns a set of key/value pairs that contains informatin +// about the database chain status. This can be used for diagnostic purposes +// when investigating the state of the node. +func ReadChainMetadata(db ethdb.KeyValueStore) [][]string { + pp := func(val *uint64) string { + if val == nil { + return "" + } + return fmt.Sprintf("%d (%#x)", *val, *val) + } + data := [][]string{ + {"databaseVersion", pp(ReadDatabaseVersion(db))}, + {"headBlockHash", fmt.Sprintf("%v", ReadHeadBlockHash(db))}, + {"headFastBlockHash", fmt.Sprintf("%v", ReadHeadFastBlockHash(db))}, + {"headHeaderHash", fmt.Sprintf("%v", ReadHeadHeaderHash(db))}, + {"lastPivotNumber", pp(ReadLastPivotNumber(db))}, + {"len(snapshotSyncStatus)", fmt.Sprintf("%d bytes", len(ReadSnapshotSyncStatus(db)))}, + {"snapshotDisabled", fmt.Sprintf("%v", ReadSnapshotDisabled(db))}, + {"snapshotJournal", fmt.Sprintf("%d bytes", len(ReadSnapshotJournal(db)))}, + {"snapshotRecoveryNumber", pp(ReadSnapshotRecoveryNumber(db))}, + {"snapshotRoot", fmt.Sprintf("%v", ReadSnapshotRoot(db))}, + {"txIndexTail", pp(ReadTxIndexTail(db))}, + {"fastTxLookupLimit", pp(ReadFastTxLookupLimit(db))}, + } + if b := ReadSkeletonSyncStatus(db); b != nil { + data = append(data, []string{"SkeletonSyncStatus", string(b)}) + } + return data +} diff --git a/core/rawdb/databases_64bit.go b/core/rawdb/databases_64bit.go index 139ce7d3477..73bfeb20838 100644 --- a/core/rawdb/databases_64bit.go +++ b/core/rawdb/databases_64bit.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 -//go:build arm64 || amd64 +//go:build (arm64 || amd64) && !openbsd package rawdb diff --git a/core/rawdb/databases_non64bit.go b/core/rawdb/databases_non64bit.go index b8ab2ecada2..1f10c2f52bd 100644 --- a/core/rawdb/databases_non64bit.go +++ b/core/rawdb/databases_non64bit.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 . -//go:build !(arm64 || amd64) +//go:build !((arm64 || amd64) && !openbsd) package rawdb diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 7bae0a2ea0d..60e2c56e0ff 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -30,7 +30,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" - "github.com/prometheus/tsdb/fileutil" + "github.com/gofrs/flock" ) var ( @@ -75,10 +75,16 @@ type Freezer struct { readonly bool tables map[string]*freezerTable // Data tables for storing everything - instanceLock fileutil.Releaser // File-system lock to prevent double opens + instanceLock *flock.Flock // File-system lock to prevent double opens closeOnce sync.Once } +// NewChainFreezer is a small utility method around NewFreezer that sets the +// default parameters for the chain storage. +func NewChainFreezer(datadir string, namespace string, readonly bool) (*Freezer, error) { + return NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerNoSnappy) +} + // NewFreezer creates a freezer instance for maintaining immutable ordered // data according to the given parameters. // @@ -98,11 +104,17 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui return nil, errSymlinkDatadir } } + flockFile := filepath.Join(datadir, "FLOCK") + if err := os.MkdirAll(filepath.Dir(flockFile), 0755); err != nil { + return nil, err + } // Leveldb uses LOCK as the filelock filename. To prevent the // name collision, we use FLOCK as the lock name. - lock, _, err := fileutil.Flock(filepath.Join(datadir, "FLOCK")) - if err != nil { + lock := flock.New(flockFile) + if locked, err := lock.TryLock(); err != nil { return nil, err + } else if !locked { + return nil, errors.New("locking failed") } // Open all the supported data tables freezer := &Freezer{ @@ -118,12 +130,12 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui for _, table := range freezer.tables { table.Close() } - lock.Release() + lock.Unlock() return nil, err } freezer.tables[name] = table } - + var err error if freezer.readonly { // In readonly mode only validate, don't truncate. // validate also sets `freezer.frozen`. @@ -136,7 +148,7 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui for _, table := range freezer.tables { table.Close() } - lock.Release() + lock.Unlock() return nil, err } @@ -159,7 +171,7 @@ func (f *Freezer) Close() error { errs = append(errs, err) } } - if err := f.instanceLock.Release(); err != nil { + if err := f.instanceLock.Unlock(); err != nil { errs = append(errs, err) } }) diff --git a/core/rawdb/freezer_table_test.go b/core/rawdb/freezer_table_test.go index ea28e71756d..6181d4d72ca 100644 --- a/core/rawdb/freezer_table_test.go +++ b/core/rawdb/freezer_table_test.go @@ -27,17 +27,12 @@ import ( "sync/atomic" "testing" "testing/quick" - "time" "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/metrics" "github.com/stretchr/testify/require" ) -func init() { - rand.Seed(time.Now().Unix()) -} - // TestFreezerBasics test initializing a freezertable from scratch, writing to the table, // and reading it back. func TestFreezerBasics(t *testing.T) { diff --git a/core/state/iterator.go b/core/state/iterator.go index ba7efd4653b..29c4abfc217 100644 --- a/core/state/iterator.go +++ b/core/state/iterator.go @@ -117,7 +117,7 @@ func (it *NodeIterator) step() error { if !it.dataIt.Next(true) { it.dataIt = nil } - if !bytes.Equal(account.CodeHash, emptyCodeHash) { + if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { it.codeHash = common.BytesToHash(account.CodeHash) addrHash := common.BytesToHash(it.stateIt.LeafKey()) it.code, err = it.state.db.ContractCode(addrHash, common.BytesToHash(account.CodeHash)) diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index d1ffc4f9448..2bd5658e0a4 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -31,7 +31,6 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "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/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -55,14 +54,6 @@ const ( rangeCompactionThreshold = 100000 ) -var ( - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // emptyCode is the known hash of the empty EVM bytecode. - emptyCode = crypto.Keccak256(nil) -) - // Config includes all the configurations for pruning. type Config struct { Datadir string // The directory of the state database @@ -446,7 +437,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error { if err := rlp.DecodeBytes(accIter.LeafBlob(), &acc); err != nil { return err } - if acc.Root != emptyRoot { + if acc.Root != types.EmptyRootHash { id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root) storageTrie, err := trie.NewStateTrie(id, trie.NewDatabase(db)) if err != nil { @@ -463,7 +454,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error { return storageIter.Error() } } - if !bytes.Equal(acc.CodeHash, emptyCode) { + if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { stateBloom.Put(acc.CodeHash, nil) } } diff --git a/core/state/snapshot/account.go b/core/state/snapshot/account.go index b92e9429501..b5634972ad6 100644 --- a/core/state/snapshot/account.go +++ b/core/state/snapshot/account.go @@ -21,6 +21,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" ) @@ -41,10 +42,10 @@ func SlimAccount(nonce uint64, balance *big.Int, root common.Hash, codehash []by Nonce: nonce, Balance: balance, } - if root != emptyRoot { + if root != types.EmptyRootHash { slim.Root = root[:] } - if !bytes.Equal(codehash, emptyCode[:]) { + if !bytes.Equal(codehash, types.EmptyCodeHash[:]) { slim.CodeHash = codehash } return slim @@ -68,10 +69,10 @@ func FullAccount(data []byte) (Account, error) { return Account{}, err } if len(account.Root) == 0 { - account.Root = emptyRoot[:] + account.Root = types.EmptyRootHash[:] } if len(account.CodeHash) == 0 { - account.CodeHash = emptyCode[:] + account.CodeHash = types.EmptyCodeHash[:] } return account, nil } diff --git a/core/state/snapshot/conversion.go b/core/state/snapshot/conversion.go index ebad28fc736..ed7cb963ad0 100644 --- a/core/state/snapshot/conversion.go +++ b/core/state/snapshot/conversion.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/common" "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/log" "github.com/ethereum/go-ethereum/rlp" @@ -74,7 +75,7 @@ func GenerateTrie(snaptree *Tree, root common.Hash, src ethdb.Database, dst ethd scheme := snaptree.triedb.Scheme() got, err := generateTrieRoot(dst, scheme, acctIt, common.Hash{}, stackTrieGenerate, func(dst ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { // Migrate the code first, commit the contract code into the tmp db. - if codeHash != emptyCode { + if codeHash != types.EmptyCodeHash { code := rawdb.ReadCode(src, codeHash) if len(code) == 0 { return common.Hash{}, errors.New("failed to read contract code") diff --git a/core/state/snapshot/difflayer_test.go b/core/state/snapshot/difflayer_test.go index 59db920481b..674a031b160 100644 --- a/core/state/snapshot/difflayer_test.go +++ b/core/state/snapshot/difflayer_test.go @@ -18,6 +18,7 @@ package snapshot import ( "bytes" + crand "crypto/rand" "math/rand" "testing" @@ -73,7 +74,7 @@ func TestMergeBasics(t *testing.T) { if rand.Intn(2) == 0 { accStorage := make(map[common.Hash][]byte) value := make([]byte, 32) - rand.Read(value) + crand.Read(value) accStorage[randomHash()] = value storage[h] = accStorage } @@ -294,7 +295,7 @@ func BenchmarkSearchSlot(b *testing.B) { accStorage := make(map[common.Hash][]byte) for i := 0; i < 5; i++ { value := make([]byte, 32) - rand.Read(value) + crand.Read(value) accStorage[randomHash()] = value storage[accountKey] = accStorage } @@ -330,7 +331,7 @@ func BenchmarkFlatten(b *testing.B) { accStorage := make(map[common.Hash][]byte) for i := 0; i < 20; i++ { value := make([]byte, 32) - rand.Read(value) + crand.Read(value) accStorage[randomHash()] = value } storage[accountKey] = accStorage @@ -379,7 +380,7 @@ func BenchmarkJournal(b *testing.B) { accStorage := make(map[common.Hash][]byte) for i := 0; i < 200; i++ { value := make([]byte, 32) - rand.Read(value) + crand.Read(value) accStorage[randomHash()] = value } storage[accountKey] = accStorage diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 46f41cdbeed..d46705d31e3 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -27,7 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -35,12 +35,6 @@ import ( ) var ( - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // emptyCode is the known hash of the empty EVM bytecode. - emptyCode = crypto.Keccak256Hash(nil) - // accountCheckRange is the upper limit of the number of accounts involved in // each range check. This is a value estimated based on experience. If this // range is too large, the failure rate of range proof will increase. Otherwise, @@ -591,10 +585,10 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er if accMarker == nil || !bytes.Equal(account[:], accMarker) { dataLen := len(val) // Approximate size, saves us a round of RLP-encoding if !write { - if bytes.Equal(acc.CodeHash, emptyCode[:]) { + if bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) { dataLen -= 32 } - if acc.Root == emptyRoot { + if acc.Root == types.EmptyRootHash { dataLen -= 32 } snapRecoveredAccountMeter.Mark(1) @@ -621,7 +615,7 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er // If the iterated account is the contract, create a further loop to // verify or regenerate the contract storage. - if acc.Root == emptyRoot { + if acc.Root == types.EmptyRootHash { ctx.removeStorageAt(account) } else { var storeMarker []byte diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go index 1bc3421e99b..1bac4fd5604 100644 --- a/core/state/snapshot/generate_test.go +++ b/core/state/snapshot/generate_test.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/common" "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/log" "github.com/ethereum/go-ethereum/rlp" @@ -49,9 +50,9 @@ func TestGeneration(t *testing.T) { var helper = newHelper() stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false) - helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) - helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) - helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) @@ -83,16 +84,16 @@ func TestGenerateExistentState(t *testing.T) { var helper = newHelper() stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) - helper.addSnapAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) - helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) - helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) root, snap := helper.CommitAndGenerate() @@ -235,28 +236,28 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) { helper := newHelper() // Account one, empty root but non-empty database - helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) // Account two, non empty root but empty database stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Miss slots { // Account three, non empty root but misses slots in the beginning helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) // Account four, non empty root but misses slots in the middle helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) // Account five, non empty root but misses slots in the end helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) } @@ -264,22 +265,22 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) { { // Account six, non empty root but wrong slots in the beginning helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) // Account seven, non empty root but wrong slots in the middle helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) // Account eight, non empty root but wrong slots in the end helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) // Account 9, non empty root but rotated slots helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) } @@ -287,17 +288,17 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) { { // Account 10, non empty root but extra slots in the beginning helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) // Account 11, non empty root but extra slots in the middle helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) // Account 12, non empty root but extra slots in the end helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) } @@ -337,25 +338,25 @@ func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { // Missing accounts, only in the trie { - helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning - helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle - helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End + helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning + helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle + helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End } // Wrong accounts { - helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) - helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) - helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) } // Extra accounts, only in the snap { - helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyRoot.Bytes()}) // before the beginning - helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle - helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()}) // after the end + helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning + helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle + helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // after the end } root, snap := helper.CommitAndGenerate() @@ -384,9 +385,9 @@ func TestGenerateCorruptAccountTrie(t *testing.T) { // without any storage slots to keep the test smaller. helper := newHelper() - helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 - helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 - helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 + helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 + helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 @@ -419,10 +420,10 @@ func TestGenerateMissingStorageTrie(t *testing.T) { helper := newHelper() stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 - helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 + helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 root := helper.Commit() @@ -453,10 +454,10 @@ func TestGenerateCorruptStorageTrie(t *testing.T) { helper := newHelper() stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 - helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 + helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 root := helper.Commit() @@ -488,7 +489,7 @@ func TestGenerateWithExtraAccounts(t *testing.T) { []string{"val-1", "val-2", "val-3", "val-4", "val-5"}, true, ) - acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} + acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e @@ -508,7 +509,7 @@ func TestGenerateWithExtraAccounts(t *testing.T) { []string{"val-1", "val-2", "val-3", "val-4", "val-5"}, true, ) - acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} + acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) key := hashData([]byte("acc-2")) rawdb.WriteAccountSnapshot(helper.diskdb, key, val) @@ -559,7 +560,7 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) { []string{"val-1", "val-2", "val-3"}, true, ) - acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} + acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e @@ -573,8 +574,7 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) { { // 100 accounts exist only in snapshot for i := 0; i < 1000; i++ { - //acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} - acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} + acc := &Account{Balance: big.NewInt(int64(i)), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) key := hashData([]byte(fmt.Sprintf("acc-%d", i))) rawdb.WriteAccountSnapshot(helper.diskdb, key, val) @@ -611,7 +611,7 @@ func TestGenerateWithExtraBeforeAndAfter(t *testing.T) { } helper := newHelper() { - acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} + acc := &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val) helper.accTrie.Update(common.HexToHash("0x07").Bytes(), val) @@ -648,7 +648,7 @@ func TestGenerateWithMalformedSnapdata(t *testing.T) { } helper := newHelper() { - acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} + acc := &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val) @@ -687,7 +687,7 @@ func TestGenerateFromEmptySnap(t *testing.T) { for i := 0; i < 400; i++ { stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount(fmt.Sprintf("acc-%d", i), - &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) } root, snap := helper.CommitAndGenerate() t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4 @@ -724,7 +724,7 @@ func TestGenerateWithIncompleteStorage(t *testing.T) { for i := 0; i < 8; i++ { accKey := fmt.Sprintf("acc-%d", i) stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(accKey)), stKeys, stVals, true) - helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) var moddedKeys []string var moddedVals []string for ii := 0; ii < 8; ii++ { @@ -816,11 +816,11 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { var helper = newHelper() stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) - helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) @@ -851,11 +851,11 @@ func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { var helper = newHelper() stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) - helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) + helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) populateDangling(helper.diskdb) diff --git a/core/state/snapshot/iterator_test.go b/core/state/snapshot/iterator_test.go index 7420a2dc22e..54614427a5c 100644 --- a/core/state/snapshot/iterator_test.go +++ b/core/state/snapshot/iterator_test.go @@ -18,6 +18,7 @@ package snapshot import ( "bytes" + crand "crypto/rand" "encoding/binary" "fmt" "math/rand" @@ -47,7 +48,7 @@ func TestAccountIteratorBasics(t *testing.T) { if rand.Intn(2) == 0 { accStorage := make(map[common.Hash][]byte) value := make([]byte, 32) - rand.Read(value) + crand.Read(value) accStorage[randomHash()] = value storage[h] = accStorage } @@ -79,7 +80,7 @@ func TestStorageIteratorBasics(t *testing.T) { var nilstorage int for i := 0; i < 100; i++ { - rand.Read(value) + crand.Read(value) if rand.Intn(2) == 0 { accStorage[randomHash()] = common.CopyBytes(value) } else { diff --git a/core/state/snapshot/snapshot_test.go b/core/state/snapshot/snapshot_test.go index bbb2650aafc..6893f6001e3 100644 --- a/core/state/snapshot/snapshot_test.go +++ b/core/state/snapshot/snapshot_test.go @@ -17,6 +17,7 @@ package snapshot import ( + crand "crypto/rand" "encoding/binary" "fmt" "math/big" @@ -27,13 +28,14 @@ import ( "github.com/VictoriaMetrics/fastcache" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" ) // randomHash generates a random blob of data and returns it as a hash. func randomHash() common.Hash { var hash common.Hash - if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { + if n, err := crand.Read(hash[:]); n != common.HashLength || err != nil { panic(err) } return hash @@ -46,7 +48,7 @@ func randomAccount() []byte { Balance: big.NewInt(rand.Int63()), Nonce: rand.Uint64(), Root: root[:], - CodeHash: emptyCode[:], + CodeHash: types.EmptyCodeHash[:], } data, _ := rlp.EncodeToBytes(a) return data diff --git a/core/state/state_object.go b/core/state/state_object.go index 1550926d3a6..5dfd3c1b648 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -31,8 +31,6 @@ import ( "github.com/ethereum/go-ethereum/trie" ) -var emptyCodeHash = crypto.Keccak256(nil) - type Code []byte func (c Code) String() string { @@ -95,7 +93,7 @@ type stateObject struct { // empty returns whether the account is considered empty. func (s *stateObject) empty() bool { - return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) + return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes()) } // newObject creates a state object. @@ -104,10 +102,10 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st data.Balance = new(big.Int) } if data.CodeHash == nil { - data.CodeHash = emptyCodeHash + data.CodeHash = types.EmptyCodeHash.Bytes() } if data.Root == (common.Hash{}) { - data.Root = emptyRoot + data.Root = types.EmptyRootHash } return &stateObject{ db: db, @@ -154,7 +152,7 @@ func (s *stateObject) getTrie(db Database) (Trie, error) { if s.trie == nil { // Try fetching from prefetcher first // We don't prefetch empty tries - if s.data.Root != emptyRoot && s.db.prefetcher != nil { + if s.data.Root != types.EmptyRootHash && s.db.prefetcher != nil { // When the miner is creating the pending state, there is no // prefetcher s.trie = s.db.prefetcher.trie(s.addrHash, s.data.Root) @@ -270,7 +268,7 @@ func (s *stateObject) finalise(prefetch bool) { slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure } } - if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != emptyRoot { + if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash { s.db.prefetcher.prefetch(s.addrHash, s.data.Root, slotsToPrefetch) } if len(s.dirtyStorage) > 0 { @@ -454,7 +452,7 @@ func (s *stateObject) Code(db Database) []byte { if s.code != nil { return s.code } - if bytes.Equal(s.CodeHash(), emptyCodeHash) { + if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { return nil } code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash())) @@ -472,7 +470,7 @@ func (s *stateObject) CodeSize(db Database) int { if s.code != nil { return len(s.code) } - if bytes.Equal(s.CodeHash(), emptyCodeHash) { + if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { return 0 } size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash())) diff --git a/core/state/statedb.go b/core/state/statedb.go index 3f4bec2392d..247aef8b239 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -41,11 +41,6 @@ type revision struct { journalIndex int } -var ( - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") -) - type proofList [][]byte func (n *proofList) Put(key []byte, value []byte) error { @@ -580,10 +575,10 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { Root: common.BytesToHash(acc.Root), } if len(data.CodeHash) == 0 { - data.CodeHash = emptyCodeHash + data.CodeHash = types.EmptyCodeHash.Bytes() } if data.Root == (common.Hash{}) { - data.Root = emptyRoot + data.Root = types.EmptyRootHash } } } @@ -975,8 +970,8 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { storageTrieNodesUpdated int storageTrieNodesDeleted int nodes = trie.NewMergedNodeSet() + codeWriter = s.db.DiskDB().NewBatch() ) - codeWriter := s.db.DiskDB().NewBatch() for addr := range s.stateObjectsDirty { if obj := s.stateObjects[addr]; !obj.deleted { // Write any contract code associated with the state object @@ -1066,11 +1061,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { s.stateObjectsDestruct = make(map[common.Address]struct{}) } if root == (common.Hash{}) { - root = emptyRoot + root = types.EmptyRootHash } origin := s.originalRoot if origin == (common.Hash{}) { - origin = emptyRoot + origin = types.EmptyRootHash } if root != origin { start := time.Now() diff --git a/core/state/sync_test.go b/core/state/sync_test.go index 84b7bf84e02..aff91268aaf 100644 --- a/core/state/sync_test.go +++ b/core/state/sync_test.go @@ -134,8 +134,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error { // Tests that an empty state is not scheduled for syncing. func TestEmptyStateSync(t *testing.T) { db := trie.NewDatabase(rawdb.NewMemoryDatabase()) - empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - sync := NewStateSync(empty, rawdb.NewMemoryDatabase(), nil, db.Scheme()) + sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, db.Scheme()) if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) } @@ -555,7 +554,7 @@ func TestIncompleteStateSync(t *testing.T) { isCode[crypto.Keccak256Hash(acc.code)] = struct{}{} } } - isCode[common.BytesToHash(emptyCodeHash)] = struct{}{} + isCode[types.EmptyCodeHash] = struct{}{} checkTrieConsistency(db, srcRoot) // Create a destination state and sync with the scheduler diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 867b47db531..3e8111e5b47 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -17,6 +17,7 @@ package core import ( + "math/big" "sync/atomic" "github.com/ethereum/go-ethereum/consensus" @@ -47,13 +48,13 @@ func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine conse // Prefetch processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb, but any changes are discarded. The // only goal is to pre-cache transaction signatures and state trie nodes. -func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) { +func (p *statePrefetcher) Prefetch(block *types.Block, excessDataGas *big.Int, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) { var ( header = block.Header() - gaspool = new(GasPool).AddGas(block.GasLimit()) - blockContext = NewEVMBlockContext(header, p.bc, nil) + gaspool = new(GasPool).AddGas(block.GasLimit()).AddDataGas(params.MaxDataGasPerBlock) + blockContext = NewEVMBlockContext(header, excessDataGas, p.bc, nil) evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) - signer = types.MakeSigner(p.config, header.Number) + signer = types.MakeSigner(p.config, header.Number, header.Time) ) // Iterate over and process the individual transactions byzantium := p.config.IsByzantium(block.Number()) @@ -63,7 +64,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c return } // Convert the transaction into an executable message and pre-cache its sender - msg, err := tx.AsMessage(signer, header.BaseFee) + msg, err := TransactionToMessage(tx, signer, header.BaseFee) if err != nil { return // Also invalid block, bail out } @@ -85,7 +86,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c // precacheTransaction attempts to apply a transaction to the given state database // and uses the input parameters for its environment. The goal is not to execute // the transaction successfully, rather to warm up touched data slots. -func precacheTransaction(msg types.Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { +func precacheTransaction(msg *Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { // Update the evm with the new transaction context. evm.Reset(NewEVMTxContext(msg), statedb) // Add addresses to access list if applicable diff --git a/core/state_processor.go b/core/state_processor.go index 163ea0a0200..0e48156e8ab 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -56,30 +56,32 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen // Process returns the receipts and logs accumulated during the process and // returns the amount of gas that was used in the process. If any of the // transactions failed to execute due to insufficient gas it will return an error. -func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { +func (p *StateProcessor) Process(block *types.Block, excessDataGas *big.Int, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { var ( receipts types.Receipts usedGas = new(uint64) header = block.Header() blockHash = block.Hash() blockNumber = block.Number() + blockTime = block.Time() allLogs []*types.Log - gp = new(GasPool).AddGas(block.GasLimit()) + gp = new(GasPool).AddGas(block.GasLimit()).AddDataGas(params.MaxDataGasPerBlock) ) // Mutate the block and state according to any hard-fork specs if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } - blockContext := NewEVMBlockContext(header, p.bc, nil) + blockContext := NewEVMBlockContext(header, excessDataGas, p.bc, nil) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) // Iterate over and process the individual transactions + signer := types.MakeSigner(p.config, header.Number, header.Time) for i, tx := range block.Transactions() { - msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number), header.BaseFee) + msg, err := TransactionToMessage(tx, signer, header.BaseFee) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.SetTxContext(tx.Hash(), i) - receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) + receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockTime, blockHash, tx, usedGas, vmenv) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -97,7 +99,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return receipts, allLogs, *usedGas, nil } -func applyTransaction(msg types.Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { +func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockTime uint64, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -129,7 +131,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, gp *GasPool receipt.GasUsed = result.UsedGas // If the transaction created a contract, store the creation address in the receipt. - if msg.To() == nil { + if msg.To == nil { receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce()) } @@ -146,13 +148,14 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, gp *GasPool // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { - msg, err := tx.AsMessage(types.MakeSigner(config, header.Number), header.BaseFee) +func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, excessDataGas *big.Int, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { + signer := types.MakeSigner(config, header.Number, header.Time) + msg, err := TransactionToMessage(tx, signer, header.BaseFee) if err != nil { return nil, err } // Create a new context to be used in the EVM environment - blockContext := NewEVMBlockContext(header, bc, author) + blockContext := NewEVMBlockContext(header, excessDataGas, bc, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) - return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) + return applyTransaction(msg, config, gp, statedb, header.Number, header.Time, header.Hash(), tx, usedGas, vmenv) } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 821b85e9bcd..59391fa8619 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -404,7 +404,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr header.BaseFee = misc.CalcBaseFee(config, parent.Header()) } if config.IsShanghai(header.Time) { - header.WithdrawalsHash = &types.EmptyRootHash + header.WithdrawalsHash = &types.EmptyWithdrawalsHash } var receipts []*types.Receipt // The post-state result doesn't need to be correct (this is a bad block), but we do need something there diff --git a/core/state_transition.go b/core/state_transition.go index 653c6b18361..81eb5221162 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -25,65 +25,9 @@ import ( cmath "github.com/ethereum/go-ethereum/common/math" "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" ) -var emptyCodeHash = crypto.Keccak256Hash(nil) - -// StateTransition represents a state transition. -// -// == The State Transitioning Model -// -// A state transition is a change made when a transaction is applied to the current world -// state. The state transitioning model does all the necessary work to work out a valid new -// state root. -// -// 1. Nonce handling -// 2. Pre pay gas -// 3. Create a new state object if the recipient is nil -// 4. Value transfer -// -// == If contract creation == -// -// 4a. Attempt to run transaction data -// 4b. If valid, use result as code for the new state object -// -// == end == -// -// 5. Run Script section -// 6. Derive new state root -type StateTransition struct { - gp *GasPool - msg Message - gas uint64 - gasPrice *big.Int - gasFeeCap *big.Int - gasTipCap *big.Int - initialGas uint64 - value *big.Int - data []byte - state vm.StateDB - evm *vm.EVM -} - -// Message represents a message sent to a contract. -type Message interface { - From() common.Address - To() *common.Address - - GasPrice() *big.Int - GasFeeCap() *big.Int - GasTipCap() *big.Int - Gas() uint64 - Value() *big.Int - - Nonce() uint64 - IsFake() bool - Data() []byte - AccessList() types.AccessList -} - // ExecutionResult includes all output after executing given evm // message no matter the execution itself is successful or not. type ExecutionResult struct { @@ -178,19 +122,51 @@ func toWordSize(size uint64) uint64 { return (size + 31) / 32 } -// NewStateTransition initialises and returns a new state transition object. -func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition { - return &StateTransition{ - gp: gp, - evm: evm, - msg: msg, - gasPrice: msg.GasPrice(), - gasFeeCap: msg.GasFeeCap(), - gasTipCap: msg.GasTipCap(), - value: msg.Value(), - data: msg.Data(), - state: evm.StateDB, +// A Message contains the data derived from a single transaction that is relevant to state +// processing. +type Message struct { + To *common.Address + From common.Address + Nonce uint64 + Value *big.Int + GasLimit uint64 + GasPrice *big.Int + GasFeeCap *big.Int + GasTipCap *big.Int + MaxFeePerDataGas *big.Int + Data []byte + AccessList types.AccessList + DataHashes []common.Hash + + // When SkipAccountCheckss is true, the message nonce is not checked against the + // account nonce in state. It also disables checking that the sender is an EOA. + // This field will be set to true for operations like RPC eth_call. + SkipAccountChecks bool +} + +// TransactionToMessage converts a transaction into a Message. +func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) { + msg := &Message{ + Nonce: tx.Nonce(), + GasLimit: tx.Gas(), + GasPrice: new(big.Int).Set(tx.GasPrice()), + GasFeeCap: new(big.Int).Set(tx.GasFeeCap()), + GasTipCap: new(big.Int).Set(tx.GasTipCap()), + MaxFeePerDataGas: new(big.Int).Set(tx.MaxFeePerDataGas()), + To: tx.To(), + Value: tx.Value(), + Data: tx.Data(), + AccessList: tx.AccessList(), + DataHashes: tx.DataHashes(), + SkipAccountChecks: false, } + // If baseFee provided, set gasPrice to effectiveGasPrice. + if baseFee != nil { + msg.GasPrice = cmath.BigMin(msg.GasPrice.Add(msg.GasTipCap, baseFee), msg.GasFeeCap) + } + var err error + msg.From, err = types.Sender(s, tx) + return msg, err } // ApplyMessage computes the new state by applying the given message @@ -200,85 +176,160 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition // the gas used (which includes gas refunds) and an error if it failed. An error always // indicates a core error meaning that the message would always fail for that particular // state and would never be accepted within a block. -func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) (*ExecutionResult, error) { +func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) { return NewStateTransition(evm, msg, gp).TransitionDb() } +// StateTransition represents a state transition. +// +// == The State Transitioning Model +// +// A state transition is a change made when a transaction is applied to the current world +// state. The state transitioning model does all the necessary work to work out a valid new +// state root. +// +// 1. Nonce handling +// 2. Pre pay gas +// 3. Create a new state object if the recipient is nil +// 4. Value transfer +// +// == If contract creation == +// +// 4a. Attempt to run transaction data +// 4b. If valid, use result as code for the new state object +// +// == end == +// +// 5. Run Script section +// 6. Derive new state root +type StateTransition struct { + gp *GasPool + msg *Message + gasRemaining uint64 + state vm.StateDB + evm *vm.EVM +} + +// NewStateTransition initialises and returns a new state transition object. +func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *StateTransition { + return &StateTransition{ + gp: gp, + evm: evm, + msg: msg, + state: evm.StateDB, + } +} + // to returns the recipient of the message. func (st *StateTransition) to() common.Address { - if st.msg == nil || st.msg.To() == nil /* contract creation */ { + if st.msg == nil || st.msg.To == nil /* contract creation */ { return common.Address{} } - return *st.msg.To() + return *st.msg.To } func (st *StateTransition) buyGas() error { - mgval := new(big.Int).SetUint64(st.msg.Gas()) - mgval = mgval.Mul(mgval, st.gasPrice) - balanceCheck := mgval - if st.gasFeeCap != nil { - balanceCheck = new(big.Int).SetUint64(st.msg.Gas()) - balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap) - balanceCheck.Add(balanceCheck, st.value) + mgval := new(big.Int).SetUint64(st.msg.GasLimit) + mgval = mgval.Mul(mgval, st.msg.GasPrice) + + // compute data fee for eip-4844 data blobs if any + dgval := new(big.Int) + var dataGasUsed uint64 + if st.evm.ChainConfig().IsCancun(st.evm.Context.Time) { + dataGasUsed = st.dataGasUsed() + if st.evm.Context.ExcessDataGas == nil { + return fmt.Errorf("%w: cancun is active but ExcessDataGas is nil. Time: %v", ErrInternalFailure, st.evm.Context.Time) + } + dgval.Mul(types.GetDataGasPrice(st.evm.Context.ExcessDataGas), new(big.Int).SetUint64(dataGasUsed)) + } + + // perform the required user balance checks + balanceRequired := new(big.Int) + if st.msg.GasFeeCap == nil { + balanceRequired.Set(mgval) + } else { + balanceRequired.Add(st.msg.Value, dgval) + // EIP-1559 mandates that the sender has enough balance to cover not just actual fee but + // the max gas fee, so we compute this upper bound rather than use mgval here. + maxGasFee := new(big.Int).SetUint64(st.msg.GasLimit) + maxGasFee.Mul(maxGasFee, st.msg.GasFeeCap) + balanceRequired.Add(balanceRequired, maxGasFee) } - if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 { - return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want) + if have, want := st.state.GetBalance(st.msg.From), balanceRequired; have.Cmp(want) < 0 { + return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) } - if err := st.gp.SubGas(st.msg.Gas()); err != nil { + + // perform gas pool accounting + if err := st.gp.SubGas(st.msg.GasLimit); err != nil { + return err + } + st.gasRemaining += st.msg.GasLimit + if err := st.gp.SubDataGas(dataGasUsed); err != nil { return err } - st.gas += st.msg.Gas() - st.initialGas = st.msg.Gas() - st.state.SubBalance(st.msg.From(), mgval) + // deduct the total gas fee (regular + data) from the sender's balance + mgval.Add(mgval, dgval) + st.state.SubBalance(st.msg.From, mgval) return nil } func (st *StateTransition) preCheck() error { // Only check transactions that are not fake - if !st.msg.IsFake() { + msg := st.msg + if !msg.SkipAccountChecks { // Make sure this transaction's nonce is correct. - stNonce := st.state.GetNonce(st.msg.From()) - if msgNonce := st.msg.Nonce(); stNonce < msgNonce { + stNonce := st.state.GetNonce(msg.From) + if msgNonce := msg.Nonce; stNonce < msgNonce { return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh, - st.msg.From().Hex(), msgNonce, stNonce) + msg.From.Hex(), msgNonce, stNonce) } else if stNonce > msgNonce { return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow, - st.msg.From().Hex(), msgNonce, stNonce) + msg.From.Hex(), msgNonce, stNonce) } else if stNonce+1 < stNonce { return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax, - st.msg.From().Hex(), stNonce) + msg.From.Hex(), stNonce) } // Make sure the sender is an EOA - if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) { + codeHash := st.state.GetCodeHash(msg.From) + if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash { return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA, - st.msg.From().Hex(), codeHash) + msg.From.Hex(), codeHash) } } + // Make sure that transaction gasFeeCap is greater than the baseFee (post london) if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { // Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) - if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 { - if l := st.gasFeeCap.BitLen(); l > 256 { + if !st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0 { + if l := msg.GasFeeCap.BitLen(); l > 256 { return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh, - st.msg.From().Hex(), l) + msg.From.Hex(), l) } - if l := st.gasTipCap.BitLen(); l > 256 { + if l := msg.GasTipCap.BitLen(); l > 256 { return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh, - st.msg.From().Hex(), l) + msg.From.Hex(), l) } - if st.gasFeeCap.Cmp(st.gasTipCap) < 0 { + if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 { return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap, - st.msg.From().Hex(), st.gasTipCap, st.gasFeeCap) + msg.From.Hex(), msg.GasTipCap, msg.GasFeeCap) } // This will panic if baseFee is nil, but basefee presence is verified // as part of header validation. - if st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { + if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow, - st.msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee) + msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee) } } } + if st.dataGasUsed() > 0 && st.evm.ChainConfig().IsCancun(st.evm.Context.Time) { + dataGasPrice := types.GetDataGasPrice(st.evm.Context.ExcessDataGas) + if dataGasPrice.Cmp(st.msg.MaxFeePerDataGas) > 0 { + return fmt.Errorf("%w: address %v, maxFeePerDataGas: %v dataGasPrice: %v, excessDataGas: %v", + ErrMaxFeePerDataGas, + st.msg.From.Hex(), st.msg.MaxFeePerDataGas, dataGasPrice, st.evm.Context.ExcessDataGas) + } + } return st.buyGas() } @@ -297,7 +348,9 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { // applying the message. The rules include these clauses // // 1. the nonce of the message caller is correct - // 2. caller has enough balance to cover transaction fee(gaslimit * gasprice) + // 2. caller has enough balance to cover: + // Legacy tx: fee(gaslimit * gasprice) + // EIP-1559 tx: tx.value + max-fee(gaslimit * gascap + datagas * datagasprice) // 3. the amount of gas required is available in the block // 4. the purchased gas is enough to cover intrinsic usage // 5. there is no overflow when calculating intrinsic gas @@ -309,54 +362,54 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { } if st.evm.Config.Debug { - st.evm.Config.Tracer.CaptureTxStart(st.initialGas) + st.evm.Config.Tracer.CaptureTxStart(st.msg.GasLimit) defer func() { - st.evm.Config.Tracer.CaptureTxEnd(st.gas) + st.evm.Config.Tracer.CaptureTxEnd(st.gasRemaining) }() } var ( msg = st.msg - sender = vm.AccountRef(msg.From()) + sender = vm.AccountRef(msg.From) rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time) - contractCreation = msg.To() == nil + contractCreation = msg.To == nil ) // Check clauses 4-5, subtract intrinsic gas if everything is correct - gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) + gas, err := IntrinsicGas(msg.Data, msg.AccessList, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) if err != nil { return nil, err } - if st.gas < gas { - return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gas, gas) + if st.gasRemaining < gas { + return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas) } - st.gas -= gas + st.gasRemaining -= gas // Check clause 6 - if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) { - return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex()) + if msg.Value.Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From, msg.Value) { + return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex()) } // Check whether the init code size has been exceeded. - if rules.IsShanghai && contractCreation && len(st.data) > params.MaxInitCodeSize { - return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(st.data), params.MaxInitCodeSize) + if rules.IsShanghai && contractCreation && len(msg.Data) > params.MaxInitCodeSize { + return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) } // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) // - reset transient storage(eip 1153) - st.state.Prepare(rules, msg.From(), st.evm.Context.Coinbase, msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) + st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList) var ( ret []byte vmerr error // vm errors do not effect consensus and are therefore not assigned to err ) if contractCreation { - ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value) + ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, msg.Value) } else { // Increment the nonce for the next transaction - st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1) - ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value) + st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1) + ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value) } if !rules.IsLondon { @@ -366,12 +419,12 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { // After EIP-3529: refunds are capped to gasUsed / 5 st.refundGas(params.RefundQuotientEIP3529) } - effectiveTip := st.gasPrice + effectiveTip := msg.GasPrice if rules.IsLondon { - effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee)) + effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)) } - if st.evm.Config.NoBaseFee && st.gasFeeCap.Sign() == 0 && st.gasTipCap.Sign() == 0 { + if st.evm.Config.NoBaseFee && msg.GasFeeCap.Sign() == 0 && msg.GasTipCap.Sign() == 0 { // Skip fee payment when NoBaseFee is set and the fee fields // are 0. This avoids a negative effectiveTip being applied to // the coinbase when simulating calls. @@ -394,18 +447,22 @@ func (st *StateTransition) refundGas(refundQuotient uint64) { if refund > st.state.GetRefund() { refund = st.state.GetRefund() } - st.gas += refund + st.gasRemaining += refund // Return ETH for remaining gas, exchanged at the original rate. - remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) - st.state.AddBalance(st.msg.From(), remaining) + remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gasRemaining), st.msg.GasPrice) + st.state.AddBalance(st.msg.From, remaining) // Also return remaining gas to the block gas counter so it is // available for the next transaction. - st.gp.AddGas(st.gas) + st.gp.AddGas(st.gasRemaining) } // gasUsed returns the amount of gas used up by the state transition. func (st *StateTransition) gasUsed() uint64 { - return st.initialGas - st.gas + return st.msg.GasLimit - st.gasRemaining +} + +func (st *StateTransition) dataGasUsed() uint64 { + return types.GetDataGasUsed(len(st.msg.DataHashes)) } diff --git a/core/txpool/list.go b/core/txpool/list.go index 062cbbf63e6..940b536f269 100644 --- a/core/txpool/list.go +++ b/core/txpool/list.go @@ -254,17 +254,19 @@ type list struct { strict bool // Whether nonces are strictly continuous or not txs *sortedMap // Heap indexed sorted hash map of the transactions - costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance) - gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit) + costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance) + gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit) + totalcost *big.Int // Total cost of all transactions in the list } // newList create a new transaction list for maintaining nonce-indexable fast, // gapped, sortable transaction lists. func newList(strict bool) *list { return &list{ - strict: strict, - txs: newSortedMap(), - costcap: new(big.Int), + strict: strict, + txs: newSortedMap(), + costcap: new(big.Int), + totalcost: new(big.Int), } } @@ -302,7 +304,23 @@ func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transa if tx.GasFeeCapIntCmp(thresholdFeeCap) < 0 || tx.GasTipCapIntCmp(thresholdTip) < 0 { return false, nil } + + // If the old tx consumes data gas, ensure data gas is bumped by 1.1 in the + // new one as recommended by EIP-4844 + if old.MaxFeePerDataGas().Sign() == 1 { + mul := big.NewInt(110) + dataFeeMin := new(big.Int).Mul(mul, old.MaxFeePerDataGas()) + dataFeeMin.Div(dataFeeMin, b) + if dataFeeMin.Cmp(tx.MaxFeePerDataGas()) == 1 { + return false, nil + } + } + + // Old is being replaced, subtract old cost + l.subTotalCost([]*types.Transaction{old}) } + // Add new tx cost to totalcost + l.totalcost.Add(l.totalcost, tx.Cost()) // Otherwise overwrite the old transaction with the current one l.txs.Put(tx) if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 { @@ -318,7 +336,9 @@ func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transa // provided threshold. Every removed transaction is returned for any post-removal // maintenance. func (l *list) Forward(threshold uint64) types.Transactions { - return l.txs.Forward(threshold) + txs := l.txs.Forward(threshold) + l.subTotalCost(txs) + return txs } // Filter removes all transactions from the list with a cost or gas limit higher @@ -357,6 +377,9 @@ func (l *list) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, } invalids = l.txs.filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest }) } + // Reset total cost + l.subTotalCost(removed) + l.subTotalCost(invalids) l.txs.reheap() return removed, invalids } @@ -364,7 +387,9 @@ func (l *list) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, // Cap places a hard limit on the number of items, returning all transactions // exceeding that limit. func (l *list) Cap(threshold int) types.Transactions { - return l.txs.Cap(threshold) + txs := l.txs.Cap(threshold) + l.subTotalCost(txs) + return txs } // Remove deletes a transaction from the maintained list, returning whether the @@ -376,9 +401,12 @@ func (l *list) Remove(tx *types.Transaction) (bool, types.Transactions) { if removed := l.txs.Remove(nonce); !removed { return false, nil } + l.subTotalCost([]*types.Transaction{tx}) // In strict mode, filter out non-executable transactions if l.strict { - return true, l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce }) + txs := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce }) + l.subTotalCost(txs) + return true, txs } return true, nil } @@ -391,7 +419,9 @@ func (l *list) Remove(tx *types.Transaction) (bool, types.Transactions) { // prevent getting into and invalid state. This is not something that should ever // happen but better to be self correcting than failing! func (l *list) Ready(start uint64) types.Transactions { - return l.txs.Ready(start) + txs := l.txs.Ready(start) + l.subTotalCost(txs) + return txs } // Len returns the length of the transaction list. @@ -417,6 +447,14 @@ func (l *list) LastElement() *types.Transaction { return l.txs.LastElement() } +// subTotalCost subtracts the cost of the given transactions from the +// total cost of all transactions. +func (l *list) subTotalCost(txs []*types.Transaction) { + for _, tx := range txs { + l.totalcost.Sub(l.totalcost, tx.Cost()) + } +} + // priceHeap is a heap.Interface implementation over transactions for retrieving // price-sorted transactions to discard when the pool fills up. If baseFee is set // then the heap is sorted based on the effective tip based on the given base fee. @@ -561,6 +599,7 @@ func (l *pricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool { // Discard finds a number of most underpriced transactions, removes them from the // priced list and returns them for further removal from the entire pool. +// If noPending is set to true, we will only consider the floating list // // Note local transaction won't be considered for eviction. func (l *pricedList) Discard(slots int, force bool) (types.Transactions, bool) { diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index c8052018662..0519f0e5fd3 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -53,6 +53,10 @@ const ( // more expensive to propagate; larger transactions also take more resources // to validate whether they fit into the pool or not. txMaxSize = 4 * txSlotSize // 128KB + + // txWrapDataMax is the maximum size of an ssz encoded BlobTxWrapData (3 4-byte offsets + the + // raw data for each blob, each commitment, and each proof) + txWrapDataMax = 4 + 4 + 4 + params.MaxBlobsPerBlock*(params.FieldElementsPerBlob*32+48+48) ) var ( @@ -87,6 +91,20 @@ var ( // than some meaningful limit a user might use. This is not a consensus error // making the transaction invalid, rather a DOS protection. ErrOversizedData = errors.New("oversized data") + + // ErrBadWrapData is returned if wrap data is not valid for the transaction + ErrBadWrapData = errors.New("bad wrap data") + + // ErrMissingWrapData is returned if wrap data is missing for the transaction + ErrMissingWrapData = errors.New("missing wrap data") + + // ErrFutureReplacePending is returned if a future transaction replaces a pending + // transaction. Future transactions should only be able to replace other future transactions. + ErrFutureReplacePending = errors.New("future transaction tries to replace pending") + + // ErrOverdraft is returned if a transaction would cause the senders balance to go negative + // thus invalidating a potential large number of transactions. + ErrOverdraft = errors.New("transaction would cause overdraft") ) var ( @@ -145,7 +163,7 @@ const ( // blockChain provides the state of blockchain and current gas limit to do // some pre checks in tx pool and event subscribers. type blockChain interface { - CurrentBlock() *types.Block + CurrentBlock() *types.Header GetBlock(hash common.Hash, number uint64) *types.Block StateAt(root common.Hash) (*state.StateDB, error) @@ -247,10 +265,12 @@ type TxPool struct { eip2718 bool // Fork indicator whether we are using EIP-2718 type transactions. eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions. shanghai bool // Fork indicator whether we are in the Shanghai stage. + eip4844 bool // Fork indicator whether we are using EIP-4844 type transactions. - currentState *state.StateDB // Current state in the blockchain head - pendingNonces *noncer // Pending state tracking virtual nonces - currentMaxGas uint64 // Current gas limit for transaction caps + currentState *state.StateDB // Current state in the blockchain head + pendingNonces *noncer // Pending state tracking virtual nonces + currentMaxGas uint64 // Current gas limit for transaction caps + currentExcessDataGas *big.Int // Current block excess_data_gas locals *accountSet // Set of local transaction to exempt from eviction rules journal *journal // Journal of local transaction to back up to disk @@ -286,22 +306,23 @@ func NewTxPool(config Config, chainconfig *params.ChainConfig, chain blockChain) // Create the transaction pool with its initial settings pool := &TxPool{ - config: config, - chainconfig: chainconfig, - chain: chain, - signer: types.LatestSigner(chainconfig), - pending: make(map[common.Address]*list), - queue: make(map[common.Address]*list), - beats: make(map[common.Address]time.Time), - all: newLookup(), - chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), - reqResetCh: make(chan *txpoolResetRequest), - reqPromoteCh: make(chan *accountSet), - queueTxEventCh: make(chan *types.Transaction), - reorgDoneCh: make(chan chan struct{}), - reorgShutdownCh: make(chan struct{}), - initDoneCh: make(chan struct{}), - gasPrice: new(big.Int).SetUint64(config.PriceLimit), + config: config, + chainconfig: chainconfig, + chain: chain, + signer: types.LatestSigner(chainconfig), + pending: make(map[common.Address]*list), + queue: make(map[common.Address]*list), + beats: make(map[common.Address]time.Time), + all: newLookup(), + chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), + reqResetCh: make(chan *txpoolResetRequest), + reqPromoteCh: make(chan *accountSet), + queueTxEventCh: make(chan *types.Transaction), + reorgDoneCh: make(chan chan struct{}), + reorgShutdownCh: make(chan struct{}), + initDoneCh: make(chan struct{}), + gasPrice: new(big.Int).SetUint64(config.PriceLimit), + currentExcessDataGas: new(big.Int), } pool.locals = newAccountSet(pool.signer) for _, addr := range config.Locals { @@ -309,7 +330,7 @@ func NewTxPool(config Config, chainconfig *params.ChainConfig, chain blockChain) pool.locals.add(addr) } pool.priced = newPricedList(pool.all) - pool.reset(nil, chain.CurrentBlock().Header()) + pool.reset(nil, chain.CurrentBlock()) // Start the reorg loop early so it can handle requests generated during journal loading. pool.wg.Add(1) @@ -361,8 +382,8 @@ func (pool *TxPool) loop() { // Handle ChainHeadEvent case ev := <-pool.chainHeadCh: if ev.Block != nil { - pool.requestReset(head.Header(), ev.Block.Header()) - head = ev.Block + pool.requestReset(head, ev.Block.Header()) + head = ev.Block.Header() } // System shutdown. @@ -587,6 +608,9 @@ func (pool *TxPool) local() map[common.Address]types.Transactions { // validateTx checks whether a transaction is valid according to the consensus // rules and adheres to some heuristic limits of the local node (price and size). +// +// This does NOT validate wrap-data of the transaction, other than ensuring the +// tx completeness and limited size checks. func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { // Accept only legacy transactions until EIP-2718/2930 activates. if !pool.eip2718 && tx.Type() != types.LegacyTxType { @@ -596,10 +620,18 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType { return core.ErrTxTypeNotSupported } + // Reject data blob transactions until data blob EIP activates. + if !pool.eip4844 && tx.Type() == types.BlobTxType { + return core.ErrTxTypeNotSupported + } // Reject transactions over defined size to prevent DOS attacks if tx.Size() > txMaxSize { return ErrOversizedData } + // Reject transactions that have too much wrap data to prevent DOS attacks. + if uint64(tx.WrapDataSize()) > txWrapDataMax { + return ErrOversizedData + } // Check whether the init code size has been exceeded. if pool.shanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { return fmt.Errorf("%w: code size %v limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) @@ -639,9 +671,25 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { } // Transactor should have enough funds to cover the costs // cost == V + GP * GL - if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { + balance := pool.currentState.GetBalance(from) + if balance.Cmp(tx.Cost()) < 0 { return core.ErrInsufficientFunds } + + // Verify that replacing transactions will not result in overdraft + list := pool.pending[from] + if list != nil { // Sender already has pending txs + sum := new(big.Int).Add(tx.Cost(), list.totalcost) + if repl := list.txs.Get(tx.Nonce()); repl != nil { + // Deduct the cost of a transaction replaced by this + sum.Sub(sum, repl.Cost()) + } + if balance.Cmp(sum) < 0 { + log.Trace("Replacing transactions would overdraft", "sender", from, "balance", pool.currentState.GetBalance(from), "required", sum) + return ErrOverdraft + } + } + // Ensure the transaction has more gas than the basic tx fee. intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, pool.istanbul, pool.shanghai) if err != nil { @@ -650,27 +698,31 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if tx.Gas() < intrGas { return core.ErrIntrinsicGas } + // TODO: Handle & Check DataGas limits + if tx.IsIncomplete() { + return ErrMissingWrapData + } return nil } -// add validates a transaction and inserts it into the non-executable queue for later -// pending promotion and execution. If the transaction is a replacement for an already -// pending or queued one, it overwrites the previous transaction if its price is higher. -// -// If a newly added transaction is marked as local, its sending account will be -// be added to the allowlist, preventing any associated transaction from being dropped -// out of the pool due to pricing constraints. +// deprecated: use addTxsLocked to add multiple txs at once, batching is encouraged to improve performance. func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err error) { - // If the transaction is already known, discard it - hash := tx.Hash() - if pool.all.Get(hash) != nil { - log.Trace("Discarding already known transaction", "hash", hash) - knownTxMeter.Mark(1) - return false, ErrAlreadyKnown + // reuse the addTxsLocked staged validation system + txs := []*types.Transaction{tx} + errs := []error{nil} + pool.filterKnownTxsLocked(txs, errs) + pool.filterInvalidTxsLocked(txs, errs, local) + pool.filterInvalidBlobTxsLocked(txs, errs) + if errs[0] == nil { + return pool.addValidTx(tx, local) } - // Make the local flag. If it's from local source or it's from the network but - // the sender is marked as local previously, treat it as the local transaction. - isLocal := local || pool.locals.containsTx(tx) + return false, errs[0] +} + +func (pool *TxPool) addValidTx(tx *types.Transaction, local bool) (replaced bool, err error) { + inLocalPool := pool.locals.containsTx(tx) + isLocal := local || inLocalPool + hash := tx.Hash() // If the transaction fails basic validation, discard it if err := pool.validateTx(tx, isLocal); err != nil { @@ -678,6 +730,10 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e invalidTxMeter.Mark(1) return false, err } + + // already validated by this point + from, _ := types.Sender(pool.signer, tx) + // If the transaction pool is full, discard underpriced transactions if uint64(pool.all.Slots()+numSlots(tx)) > pool.config.GlobalSlots+pool.config.GlobalQueue { // If the new transaction is underpriced, don't accept it @@ -686,6 +742,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e underpricedTxMeter.Mark(1) return false, ErrUnderpriced } + // We're about to replace a transaction. The reorg does a more thorough // analysis of what to remove and how, but it runs async. We don't want to // do too many replacements between reorg-runs, so we cap the number of @@ -706,17 +763,37 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e overflowedTxMeter.Mark(1) return false, ErrTxPoolOverflow } - // Bump the counter of rejections-since-reorg - pool.changesSinceReorg += len(drop) + + // If the new transaction is a future transaction it should never churn pending transactions + if pool.isFuture(from, tx) { + var replacesPending bool + for _, dropTx := range drop { + dropSender, _ := types.Sender(pool.signer, dropTx) + if list := pool.pending[dropSender]; list != nil && list.Overlaps(dropTx) { + replacesPending = true + break + } + } + // Add all transactions back to the priced queue + if replacesPending { + for _, dropTx := range drop { + pool.priced.Put(dropTx, false) + } + log.Trace("Discarding future transaction replacing pending tx", "hash", hash) + return false, ErrFutureReplacePending + } + } + // Kick out the underpriced remote transactions. for _, tx := range drop { log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) underpricedTxMeter.Mark(1) - pool.removeTx(tx.Hash(), false) + dropped := pool.removeTx(tx.Hash(), false) + pool.changesSinceReorg += dropped } } + // Try to replace an existing transaction in the pending pool - from, _ := types.Sender(pool.signer, tx) // already validated if list := pool.pending[from]; list != nil && list.Overlaps(tx) { // Nonce already pending, check if required price bump is met inserted, old := list.Add(tx, pool.config.PriceBump) @@ -746,7 +823,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e return false, err } // Mark local addresses and journal local transactions - if local && !pool.locals.contains(from) { + if local && !inLocalPool { log.Info("Setting new local account", "address", from) pool.locals.add(from) pool.priced.Removed(pool.all.RemoteToLocals(pool.locals)) // Migrate the remotes if it's marked as local first time. @@ -760,6 +837,20 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e return replaced, nil } +// isFuture reports whether the given transaction is immediately executable. +func (pool *TxPool) isFuture(from common.Address, tx *types.Transaction) bool { + list := pool.pending[from] + if list == nil { + return pool.pendingNonces.get(from) != tx.Nonce() + } + // Sender has pending transactions. + if old := list.txs.Get(tx.Nonce()); old != nil { + return false // It replaces a pending transaction. + } + // Not replacing, check if parent nonce exists in pending. + return list.txs.Get(tx.Nonce()-1) == nil +} + // enqueueTx inserts a new transaction into the non-executable transaction queue. // // Note, this method assumes the pool lock is held! @@ -946,18 +1037,88 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error { // addTxsLocked attempts to queue a batch of transactions if they are valid. // The transaction pool lock must be held. +// +// It first validates the txs in stages, and then inserts the valid txs into +// the non-executable queue for later pending promotion and execution. +// +// If a transaction is a replacement for an already pending or queued one, +// it overwrites the previous transaction if its price is higher. +// +// If a newly added transaction is marked as local, its sending account will +// be added to the allowlist, preventing any associated transaction from +// being dropped out of the pool due to pricing constraints. func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error, *accountSet) { - dirty := newAccountSet(pool.signer) + // note: the transaction validation and adding happens in stages, so expensive work can be batched. errs := make([]error, len(txs)) + pool.filterKnownTxsLocked(txs, errs) + pool.filterInvalidTxsLocked(txs, errs, local) + pool.filterInvalidBlobTxsLocked(txs, errs) + dirty := pool.addValidTxsLocked(txs, errs, local) + return errs, dirty +} + +// filterKnownTxsLocked marks all known transactions with ErrAlreadyKnown +func (pool *TxPool) filterKnownTxsLocked(txs []*types.Transaction, errs []error) { + for i, tx := range txs { + if pool.Has(tx.Hash()) { + log.Trace("Discarding already known transaction", "hash", tx.Hash()) + knownTxMeter.Mark(1) + errs[i] = ErrAlreadyKnown + } + } +} + +// filterInvalidTxsLocked marks all invalid txs with respective error, this excludes blob validation +func (pool *TxPool) filterInvalidTxsLocked(txs []*types.Transaction, errs []error, local bool) { + for i, tx := range txs { + if errs[i] != nil { + continue + } + + // Make the local flag. If it's from local source or it's from the network but + // the sender is marked as local previously, treat it as the local transaction. + inLocalPool := pool.locals.containsTx(tx) + isLocal := local || inLocalPool + err := pool.validateTx(tx, isLocal) + if err != nil { + log.Trace("Discarding invalid transaction", "hash", tx.Hash(), "err", err) + invalidTxMeter.Mark(1) + errs[i] = err + } + } +} + +// filterInvalidBlobTxsLocked marks all blob txs (if any) with an error if the blobs or kzg commitments are invalid +func (pool *TxPool) filterInvalidBlobTxsLocked(txs []*types.Transaction, errs []error) { + for i, tx := range txs { + if errs[i] != nil { + continue + } + // all blobs within the tx can still be batched together + err := tx.VerifyBlobs() + if err != nil { + log.Trace("Discarding blob transaction", "hash", tx.Hash(), "err", err) + invalidTxMeter.Mark(1) + errs[i] = err + } + } +} + +// addValidTxsLocked adds all transactions to the pool that are not marked with an error. +func (pool *TxPool) addValidTxsLocked(txs []*types.Transaction, errs []error, local bool) *accountSet { + dirty := newAccountSet(pool.signer) for i, tx := range txs { - replaced, err := pool.add(tx, local) + if errs[i] != nil { + continue + } + replaced, err := pool.addValidTx(tx, local) errs[i] = err if err == nil && !replaced { dirty.addTx(tx) } } validTxMeter.Mark(int64(len(dirty.accounts))) - return errs, dirty + return dirty } // Status returns the status (unknown/pending/queued) of a batch of transactions @@ -996,11 +1157,12 @@ func (pool *TxPool) Has(hash common.Hash) bool { // removeTx removes a single transaction from the queue, moving all subsequent // transactions back to the future queue. -func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { +// Returns the number of transactions removed from the pending queue. +func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) int { // Fetch the transaction we wish to delete tx := pool.all.Get(hash) if tx == nil { - return + return 0 } addr, _ := types.Sender(pool.signer, tx) // already validated during insertion @@ -1028,7 +1190,7 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { pool.pendingNonces.setIfLower(addr, tx.Nonce()) // Reduce the pending counter pendingGauge.Dec(int64(1 + len(invalids))) - return + return 1 + len(invalids) } } // Transaction is in the future queue @@ -1042,6 +1204,7 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { delete(pool.beats, addr) } } + return 0 } // requestReset requests a pool reset to the new head block. @@ -1279,6 +1442,16 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) return } + // transactions that contained blobs might not have the wrapData anymore + // if not retrieved from block cache since wrap data is not persisted. Discord those. + j := 0 + for _, tx := range discarded { + if !tx.IsIncomplete() { + discarded[j] = tx + j++ + } + } + discarded = discarded[:j] included = append(included, add.Transactions()...) if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) @@ -1291,7 +1464,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { } // Initialize the internal state to the current head if newHead == nil { - newHead = pool.chain.CurrentBlock().Header() // Special case during testing + newHead = pool.chain.CurrentBlock() // Special case during testing } statedb, err := pool.chain.StateAt(newHead.Root) if err != nil { @@ -1301,6 +1474,9 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.currentState = statedb pool.pendingNonces = newNoncer(statedb) pool.currentMaxGas = newHead.GasLimit + if newHead.ExcessDataGas != nil { + pool.currentExcessDataGas.Set(newHead.ExcessDataGas) + } // Inject any transactions discarded due to reorgs log.Debug("Reinjecting stale transactions", "count", len(reinject)) @@ -1312,7 +1488,9 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.istanbul = pool.chainconfig.IsIstanbul(next) pool.eip2718 = pool.chainconfig.IsBerlin(next) pool.eip1559 = pool.chainconfig.IsLondon(next) - pool.shanghai = pool.chainconfig.IsShanghai(uint64(time.Now().Unix())) + now := uint64(time.Now().Unix()) + pool.shanghai = pool.chainconfig.IsShanghai(now) + pool.eip4844 = pool.chainconfig.IsCancun(now) } // promoteExecutables moves transactions that have become processable from the diff --git a/core/txpool/txpool2_test.go b/core/txpool/txpool2_test.go new file mode 100644 index 00000000000..20d6dd713a9 --- /dev/null +++ b/core/txpool/txpool2_test.go @@ -0,0 +1,212 @@ +// Copyright 2023 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 txpool + +import ( + "crypto/ecdsa" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/event" +) + +func pricedValuedTransaction(nonce uint64, value int64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { + tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(value), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) + return tx +} + +func count(t *testing.T, pool *TxPool) (pending int, queued int) { + t.Helper() + pending, queued = pool.stats() + if err := validatePoolInternals(pool); err != nil { + t.Fatalf("pool internal state corrupted: %v", err) + } + return pending, queued +} + +func fillPool(t *testing.T, pool *TxPool) { + t.Helper() + // Create a number of test accounts, fund them and make transactions + executableTxs := types.Transactions{} + nonExecutableTxs := types.Transactions{} + for i := 0; i < 384; i++ { + key, _ := crypto.GenerateKey() + pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) + // Add executable ones + for j := 0; j < int(pool.config.AccountSlots); j++ { + executableTxs = append(executableTxs, pricedTransaction(uint64(j), 100000, big.NewInt(300), key)) + } + } + // Import the batch and verify that limits have been enforced + pool.AddRemotesSync(executableTxs) + pool.AddRemotesSync(nonExecutableTxs) + pending, queued := pool.Stats() + slots := pool.all.Slots() + // sanity-check that the test prerequisites are ok (pending full) + if have, want := pending, slots; have != want { + t.Fatalf("have %d, want %d", have, want) + } + if have, want := queued, 0; have != want { + t.Fatalf("have %d, want %d", have, want) + } + + t.Logf("pool.config: GlobalSlots=%d, GlobalQueue=%d\n", pool.config.GlobalSlots, pool.config.GlobalQueue) + t.Logf("pending: %d queued: %d, all: %d\n", pending, queued, slots) +} + +// Tests that if a batch high-priced of non-executables arrive, they do not kick out +// executable transactions +func TestTransactionFutureAttack(t *testing.T) { + t.Parallel() + + // Create the pool to test the limit enforcement with + statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + blockchain := &testBlockChain{1000000, statedb, new(event.Feed)} + config := testTxPoolConfig + config.GlobalQueue = 100 + config.GlobalSlots = 100 + pool := NewTxPool(config, eip1559Config, blockchain) + defer pool.Stop() + fillPool(t, pool) + pending, _ := pool.Stats() + // Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops + { + key, _ := crypto.GenerateKey() + pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000)) + futureTxs := types.Transactions{} + for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ { + futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 100000, big.NewInt(500), key)) + } + for i := 0; i < 5; i++ { + pool.AddRemotesSync(futureTxs) + newPending, newQueued := count(t, pool) + t.Logf("pending: %d queued: %d, all: %d\n", newPending, newQueued, pool.all.Slots()) + } + } + newPending, _ := pool.Stats() + // Pending should not have been touched + if have, want := newPending, pending; have < want { + t.Errorf("wrong pending-count, have %d, want %d (GlobalSlots: %d)", + have, want, pool.config.GlobalSlots) + } +} + +// Tests that if a batch high-priced of non-executables arrive, they do not kick out +// executable transactions +func TestTransactionFuture1559(t *testing.T) { + t.Parallel() + // Create the pool to test the pricing enforcement with + statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + blockchain := &testBlockChain{1000000, statedb, new(event.Feed)} + pool := NewTxPool(testTxPoolConfig, eip1559Config, blockchain) + defer pool.Stop() + + // Create a number of test accounts, fund them and make transactions + fillPool(t, pool) + pending, _ := pool.Stats() + + // Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops + { + key, _ := crypto.GenerateKey() + pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000)) + futureTxs := types.Transactions{} + for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ { + futureTxs = append(futureTxs, dynamicFeeTx(1000+uint64(j), 100000, big.NewInt(200), big.NewInt(101), key)) + } + pool.AddRemotesSync(futureTxs) + } + newPending, _ := pool.Stats() + // Pending should not have been touched + if have, want := newPending, pending; have != want { + t.Errorf("Wrong pending-count, have %d, want %d (GlobalSlots: %d)", + have, want, pool.config.GlobalSlots) + } +} + +// Tests that if a batch of balance-overdraft txs arrive, they do not kick out +// executable transactions +func TestTransactionZAttack(t *testing.T) { + t.Parallel() + // Create the pool to test the pricing enforcement with + statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + blockchain := &testBlockChain{1000000, statedb, new(event.Feed)} + pool := NewTxPool(testTxPoolConfig, eip1559Config, blockchain) + defer pool.Stop() + // Create a number of test accounts, fund them and make transactions + fillPool(t, pool) + + countInvalidPending := func() int { + t.Helper() + var ivpendingNum int + pendingtxs, _ := pool.Content() + for account, txs := range pendingtxs { + cur_balance := new(big.Int).Set(pool.currentState.GetBalance(account)) + for _, tx := range txs { + if cur_balance.Cmp(tx.Value()) <= 0 { + ivpendingNum++ + } else { + cur_balance.Sub(cur_balance, tx.Value()) + } + } + } + if err := validatePoolInternals(pool); err != nil { + t.Fatalf("pool internal state corrupted: %v", err) + } + return ivpendingNum + } + ivPending := countInvalidPending() + t.Logf("invalid pending: %d\n", ivPending) + + // Now, DETER-Z attack starts, let's add a bunch of expensive non-executables (from N accounts) along with balance-overdraft txs (from one account), and see if the pending-count drops + for j := 0; j < int(pool.config.GlobalQueue); j++ { + futureTxs := types.Transactions{} + key, _ := crypto.GenerateKey() + pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000)) + futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 21000, big.NewInt(500), key)) + pool.AddRemotesSync(futureTxs) + } + + overDraftTxs := types.Transactions{} + { + key, _ := crypto.GenerateKey() + pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000)) + for j := 0; j < int(pool.config.GlobalSlots); j++ { + overDraftTxs = append(overDraftTxs, pricedValuedTransaction(uint64(j), 60000000000, 21000, big.NewInt(500), key)) + } + } + pool.AddRemotesSync(overDraftTxs) + pool.AddRemotesSync(overDraftTxs) + pool.AddRemotesSync(overDraftTxs) + pool.AddRemotesSync(overDraftTxs) + pool.AddRemotesSync(overDraftTxs) + + newPending, newQueued := count(t, pool) + newIvPending := countInvalidPending() + t.Logf("pool.all.Slots(): %d\n", pool.all.Slots()) + t.Logf("pending: %d queued: %d, all: %d\n", newPending, newQueued, pool.all.Slots()) + t.Logf("invalid pending: %d\n", newIvPending) + + // Pending should not have been touched + if newIvPending != ivPending { + t.Errorf("Wrong invalid pending-count, have %d, want %d (GlobalSlots: %d, queued: %d)", + newIvPending, ivPending, pool.config.GlobalSlots, newQueued) + } +} diff --git a/core/txpool/txpool_test.go b/core/txpool/txpool_test.go index 7aa016ab419..100ba36db3f 100644 --- a/core/txpool/txpool_test.go +++ b/core/txpool/txpool_test.go @@ -18,6 +18,7 @@ package txpool import ( "crypto/ecdsa" + crand "crypto/rand" "errors" "fmt" "math/big" @@ -27,6 +28,9 @@ import ( "testing" "time" + "github.com/holiman/uint256" + "github.com/protolambda/ztyp/view" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" @@ -55,6 +59,8 @@ func init() { eip1559Config = &cpy eip1559Config.BerlinBlock = common.Big0 eip1559Config.LondonBlock = common.Big0 + var zeroTime uint64 + eip1559Config.CancunTime = &zeroTime // for blob tx tests } type testBlockChain struct { @@ -63,14 +69,15 @@ type testBlockChain struct { chainHeadFeed *event.Feed } -func (bc *testBlockChain) CurrentBlock() *types.Block { - return types.NewBlock(&types.Header{ +func (bc *testBlockChain) CurrentBlock() *types.Header { + return &types.Header{ + Number: new(big.Int), GasLimit: atomic.LoadUint64(&bc.gasLimit), - }, nil, nil, nil, trie.NewStackTrie(nil)) + } } func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { - return bc.CurrentBlock() + return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil)) } func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { @@ -92,7 +99,7 @@ func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ec func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, bytes uint64) *types.Transaction { data := make([]byte, bytes) - rand.Read(data) + crand.Read(data) tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data), types.HomesteadSigner{}, key) return tx @@ -113,6 +120,42 @@ func dynamicFeeTx(nonce uint64, gaslimit uint64, gasFee *big.Int, tip *big.Int, return tx } +func blobTx(nonce uint64, gaslimit uint64, gasFee uint64, tip uint64, dataGasFee uint64, numBlobs int, key *ecdsa.PrivateKey) *types.Transaction { + // Need tx wrap data that will pass blob verification + blobData := &types.BlobTxWrapData{ + Blobs: make([]types.Blob, numBlobs), + } + commitments, hashes, proofs, err := blobData.Blobs.ComputeCommitmentsAndProofs() + if err != nil { + panic(err) + } + blobData.BlobKzgs = commitments + blobData.Proofs = proofs + + address := types.AddressSSZ(common.Address{}) + sbtx := &types.SignedBlobTx{ + Message: types.BlobTxMessage{ + Nonce: view.Uint64View(nonce), + GasTipCap: view.Uint256View(*uint256.NewInt(tip)), + GasFeeCap: view.Uint256View(*uint256.NewInt(gasFee)), + Gas: view.Uint64View(gaslimit), + To: types.AddressOptionalSSZ{&address}, + Value: view.Uint256View(*uint256.NewInt(100)), + Data: nil, + AccessList: nil, + MaxFeePerDataGas: view.Uint256View(*uint256.NewInt(dataGasFee)), + BlobVersionedHashes: hashes, + }, + } + sbtx.Message.ChainID.SetFromBig(params.TestChainConfig.ChainID) + + tx, err := types.SignNewTx(key, types.LatestSignerForChainID(params.TestChainConfig.ChainID), sbtx, types.WithTxWrapData(blobData)) + if err != nil { + panic(err) + } + return tx +} + func setupPool() (*TxPool, *ecdsa.PrivateKey) { return setupPoolWithConfig(params.TestChainConfig) } @@ -156,6 +199,9 @@ func validatePoolInternals(pool *TxPool) error { if nonce := pool.pendingNonces.get(addr); nonce != last+1 { return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1) } + if txs.totalcost.Cmp(common.Big0) < 0 { + return fmt.Errorf("totalcost went negative: %v", txs.totalcost) + } } return nil } @@ -1103,7 +1149,7 @@ func TestPendingLimiting(t *testing.T) { defer pool.Stop() account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000)) + testAddBalance(pool, account, big.NewInt(1000000000000)) // Keep track of transaction events to ensure all executables get announced events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5) @@ -1582,7 +1628,7 @@ func TestRepricingKeepsLocals(t *testing.T) { keys := make([]*ecdsa.PrivateKey, 3) for i := 0; i < len(keys); i++ { keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000*1000000)) + testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(100000*1000000)) } // Create transaction (both pending and queued) with a linearly growing gasprice for i := uint64(0); i < 500; i++ { @@ -1661,7 +1707,7 @@ func TestUnderpricing(t *testing.T) { defer sub.Unsubscribe() // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 4) + keys := make([]*ecdsa.PrivateKey, 5) for i := 0; i < len(keys); i++ { keys[i], _ = crypto.GenerateKey() testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) @@ -1697,6 +1743,10 @@ func TestUnderpricing(t *testing.T) { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) } + // Replace a future transaction with a future transaction + if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[1])); err != nil { // +K1:1 => -K1:1 => Pend K0:0, K0:1, K2:0; Que K1:1 + t.Fatalf("failed to add well priced transaction: %v", err) + } // Ensure that adding high priced transactions drops cheap ones, but not own if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil { // +K1:0 => -K1:1 => Pend K0:0, K0:1, K1:0, K2:0; Que - t.Fatalf("failed to add well priced transaction: %v", err) @@ -1707,6 +1757,10 @@ func TestUnderpricing(t *testing.T) { if err := pool.AddRemote(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil { // +K1:3 => -K0:1 => Pend K1:0, K2:0; Que K1:2 K1:3 t.Fatalf("failed to add well priced transaction: %v", err) } + // Ensure that replacing a pending transaction with a future transaction fails + if err := pool.AddRemote(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != ErrFutureReplacePending { + t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, ErrFutureReplacePending) + } pending, queued = pool.Stats() if pending != 2 { t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) @@ -1714,7 +1768,7 @@ func TestUnderpricing(t *testing.T) { if queued != 2 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) } - if err := validateEvents(events, 1); err != nil { + if err := validateEvents(events, 2); err != nil { t.Fatalf("additional event firing failed: %v", err) } if err := validatePoolInternals(pool); err != nil { @@ -1876,11 +1930,11 @@ func TestUnderpricingDynamicFee(t *testing.T) { t.Fatalf("failed to add well priced transaction: %v", err) } - tx = pricedTransaction(2, 100000, big.NewInt(3), keys[1]) + tx = pricedTransaction(1, 100000, big.NewInt(3), keys[1]) if err := pool.AddRemote(tx); err != nil { // +K1:2, -K0:1 => Pend K0:0 K1:0, K2:0; Que K1:2 t.Fatalf("failed to add well priced transaction: %v", err) } - tx = dynamicFeeTx(3, 100000, big.NewInt(4), big.NewInt(1), keys[1]) + tx = dynamicFeeTx(2, 100000, big.NewInt(4), big.NewInt(1), keys[1]) if err := pool.AddRemote(tx); err != nil { // +K1:3, -K1:0 => Pend K0:0 K2:0; Que K1:2 K1:3 t.Fatalf("failed to add well priced transaction: %v", err) } @@ -1891,7 +1945,7 @@ func TestUnderpricingDynamicFee(t *testing.T) { if queued != 2 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) } - if err := validateEvents(events, 1); err != nil { + if err := validateEvents(events, 2); err != nil { t.Fatalf("additional event firing failed: %v", err) } if err := validatePoolInternals(pool); err != nil { @@ -2133,6 +2187,9 @@ func TestReplacementDynamicFee(t *testing.T) { defer pool.Stop() testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) + key2, _ := crypto.GenerateKey() // separate key for our blob tx tests + testAddBalance(pool, crypto.PubkeyToAddress(key2.PublicKey), big.NewInt(1000000000)) + // Keep track of transaction events to ensure all executables get announced events := make(chan core.NewTxsEvent, 32) sub := pool.txFeed.Subscribe(events) @@ -2145,17 +2202,22 @@ func TestReplacementDynamicFee(t *testing.T) { tipThreshold := (gasTipCap * (100 + int64(testTxPoolConfig.PriceBump))) / 100 // Run the following identical checks for both the pending and queue pools: - // 1. Send initial tx => accept - // 2. Don't bump tip or fee cap => discard - // 3. Bump both more than min => accept - // 4. Check events match expected (2 new executable txs during pending, 0 during queue) - // 5. Send new tx with larger tip and gasFeeCap => accept - // 6. Bump tip max allowed so it's still underpriced => discard - // 7. Bump fee cap max allowed so it's still underpriced => discard - // 8. Bump tip min for acceptance => discard - // 9. Bump feecap min for acceptance => discard - // 10. Bump feecap and tip min for acceptance => accept - // 11. Check events match expected (2 new executable txs during pending, 0 during queue) + // 1. Send initial tx => accept + // 2. Don't bump tip or fee cap => discard + // 3. Bump both more than min => accept + // 4. Check events match expected (2 new executable txs during pending, 0 during queue) + // 5. Send new tx with larger tip and gasFeeCap => accept + // 6. Bump tip max allowed so it's still underpriced => discard + // 7. Bump fee cap max allowed so it's still underpriced => discard + // 8. Bump tip min for acceptance => discard + // 9. Bump feecap min for acceptance => discard + // 10. Bump feecap and tip min for acceptance => accept + // 11. Check events match expected (2 new executable txs during pending, 0 during queue) + // 12. Send initial blob tx => accept + // 13. bump tip/fee, but don't bump data gas fee => discard + // 14. bump tip/fee, insufficiently bump data gas fee => discard + // 15. bump tip/fee/datagasfee => accept + // 16. Check events match expected (2 new executable txs during pending, 0 during queue) stages := []string{"pending", "queued"} for _, stage := range stages { // Since state is empty, 0 nonce txs are "executable" and can go @@ -2226,6 +2288,34 @@ func TestReplacementDynamicFee(t *testing.T) { if err := validateEvents(events, count); err != nil { t.Fatalf("replacement %s event firing failed: %v", stage, err) } + // 12. Send initial tx => accept + tx = blobTx(nonce, 100000, uint64(2), uint64(1), uint64(100), 1, key2) + if err := pool.addRemoteSync(tx); err != nil { + t.Fatalf("failed to add original cheap %s transaction: %v", stage, err) + } + // 13. Bump cap & tip, but don't bump datagasfee => discard + tx = blobTx(nonce, 100000, uint64(3), uint64(2), uint64(100), 1, key2) + if err := pool.AddRemote(tx); err != ErrReplaceUnderpriced { + t.Fatalf("original cheap %s transaction replacement error mismatch: have %v, want %v", stage, err, ErrReplaceUnderpriced) + } + // 14. Bump cap, tip, & insufficiently bump datagasfee => discard + tx = blobTx(nonce, 100000, uint64(3), uint64(2), uint64(109), 1, key2) + if err := pool.AddRemote(tx); err != ErrReplaceUnderpriced { + t.Fatalf("original cheap %s transaction replacement error mismatch: have %v, want %v", stage, err, ErrReplaceUnderpriced) + } + // 15. Bump cap, tip, & datagasfee => accept + tx = blobTx(nonce, 100000, uint64(3), uint64(2), uint64(110), 1, key2) + if err := pool.AddRemote(tx); err != nil { + t.Fatalf("failed to replace cheap %s blob tx: %v", stage, err) + } + // 16. Check events match expected + count = 2 + if stage == "queued" { + count = 0 + } + if err := validateEvents(events, count); err != nil { + t.Fatalf("replacement %s event firing failed: %v", stage, err) + } } if err := validatePoolInternals(pool); err != nil { @@ -2420,6 +2510,23 @@ func TestSlotCount(t *testing.T) { } } +func TestBlobTransactionLimits(t *testing.T) { + t.Parallel() + + pool, key := setupPoolWithConfig(eip1559Config) + defer pool.Stop() + testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) + + tx := blobTx(0, 100000, uint64(2), uint64(1), uint64(100), 4, key) + if err := pool.addRemoteSync(tx); err != nil { + t.Fatalf("failed to add blob transaction with max blobs: %v", err) + } + tx = blobTx(1, 100000, uint64(2), uint64(1), uint64(100), 5, key) + if err := pool.addRemoteSync(tx); err == nil { + t.Fatalf("added blob transaction with too many blobs") + } +} + // Benchmarks the speed of validating the contents of the pending queue of the // transaction pool. func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } @@ -2485,7 +2592,7 @@ func benchmarkBatchInsert(b *testing.B, size int, local bool) { defer pool.Stop() account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000)) + testAddBalance(pool, account, big.NewInt(1000000000000000000)) batches := make([]types.Transactions, b.N) for i := 0; i < b.N; i++ { diff --git a/core/types.go b/core/types.go index 4c5b74a4986..09aac69f536 100644 --- a/core/types.go +++ b/core/types.go @@ -17,6 +17,8 @@ package core import ( + "math/big" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -39,7 +41,7 @@ type Prefetcher interface { // Prefetch processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb, but any changes are discarded. The // only goal is to pre-cache transaction signatures and state trie nodes. - Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) + Prefetch(block *types.Block, excessDataGas *big.Int, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) } // Processor is an interface for processing blocks using a given initial state. @@ -47,5 +49,5 @@ type Processor interface { // Process processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb and applying any rewards to both // the processor (coinbase) and any included uncles. - Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) + Process(block *types.Block, excessDataGas *big.Int, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) } diff --git a/core/types/block.go b/core/types/block.go index ac8c031acf1..3e46f85d65c 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -18,7 +18,9 @@ package types import ( + "bytes" "encoding/binary" + "errors" "fmt" "io" "math/big" @@ -31,11 +33,6 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -var ( - EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - EmptyUncleHash = rlpHash([]*Header(nil)) -) - // A BlockNonce is a 64-bit hash which proves (combined with the // mix-hash) that a sufficient amount of computation has been carried // out on a block. @@ -90,6 +87,9 @@ type Header struct { // WithdrawalsHash was added by EIP-4895 and is ignored in legacy headers. WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + // ExcessDataGas was added by EIP-4844 and is ignored in legacy headers. + ExcessDataGas *big.Int `json:"excessDataGas" rlp:"optional"` + /* TODO (MariusVanDerWijden) Add this field once needed // Random was added during the merge and contains the BeaconState randomness @@ -99,14 +99,32 @@ type Header struct { // field type overrides for gencodec type headerMarshaling struct { - Difficulty *hexutil.Big - Number *hexutil.Big - GasLimit hexutil.Uint64 - GasUsed hexutil.Uint64 - Time hexutil.Uint64 - Extra hexutil.Bytes - BaseFee *hexutil.Big - Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON + Difficulty *hexutil.Big + Number *hexutil.Big + GasLimit hexutil.Uint64 + GasUsed hexutil.Uint64 + Time hexutil.Uint64 + Extra hexutil.Bytes + BaseFee *hexutil.Big + ExcessDataGas *hexutil.Big + Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON +} + +// TimeBig returns the header's time field as a big int. +func (h *Header) TimeBig() *big.Int { + return new(big.Int).SetUint64(h.Time) +} + +// SetExcessDataGas sets the excess_data_gas field in the header +func (h *Header) SetExcessDataGas(v *big.Int) { + h.ExcessDataGas = new(big.Int) + if v != nil { + h.ExcessDataGas.Set(v) + } + if h.WithdrawalsHash == nil { + // leaving this nil would result in a buggy encoding + h.WithdrawalsHash = &EmptyRootHash + } } // Hash returns the block hash of the header, which is simply the keccak256 hash of its @@ -120,11 +138,18 @@ var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size()) // Size returns the approximate memory used by all internal contents. It is used // to approximate and limit the memory consumption of various caches. func (h *Header) Size() common.StorageSize { - var baseFeeBits int + var feeBits int if h.BaseFee != nil { - baseFeeBits = h.BaseFee.BitLen() + feeBits = h.BaseFee.BitLen() } - return headerSize + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen()+baseFeeBits)/8) + if h.ExcessDataGas != nil { + feeBits += h.ExcessDataGas.BitLen() + } + var withdrawalBytes int + if h.WithdrawalsHash != nil { + withdrawalBytes = common.HashLength + } + return headerSize + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen()+feeBits)/8+withdrawalBytes) } // SanityCheck checks a few basic things -- these checks are way beyond what @@ -148,6 +173,11 @@ func (h *Header) SanityCheck() error { return fmt.Errorf("too large base fee: bitlen %d", bfLen) } } + if h.ExcessDataGas != nil { + if bfLen := h.ExcessDataGas.BitLen(); bfLen > 256 { + return fmt.Errorf("too large excess data gas: bitlen %d", bfLen) + } + } return nil } @@ -155,14 +185,14 @@ func (h *Header) SanityCheck() error { // that is: no transactions, no uncles and no withdrawals. func (h *Header) EmptyBody() bool { if h.WithdrawalsHash == nil { - return h.TxHash == EmptyRootHash && h.UncleHash == EmptyUncleHash + return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash } - return h.TxHash == EmptyRootHash && h.UncleHash == EmptyUncleHash && *h.WithdrawalsHash == EmptyRootHash + return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash && *h.WithdrawalsHash == EmptyWithdrawalsHash } // EmptyReceipts returns true if there are no receipts for this header/block. func (h *Header) EmptyReceipts() bool { - return h.ReceiptHash == EmptyRootHash + return h.ReceiptHash == EmptyReceiptsHash } // Body is a simple (mutable, non-safe) data container for storing and moving @@ -190,10 +220,84 @@ type Block struct { ReceivedFrom interface{} } +// a view over a transaction to RLP encode/decode it the minimal way +type minimalTx Transaction + +func (tx *minimalTx) DecodeRLP(s *rlp.Stream) error { + kind, size, err := s.Kind() + switch { + case err != nil: + return err + case kind == rlp.List: + // It's a legacy transaction. + var inner LegacyTx + err := s.Decode(&inner) + if err == nil { + (*Transaction)(tx).setDecoded(&inner, rlp.ListSize(size)) + } + return err + case kind == rlp.String: + // It's an EIP-2718 typed TX envelope. + var b []byte + if b, err = s.Bytes(); err != nil { + return err + } + inner, err := (*Transaction)(tx).decodeTypedMinimal(b) + if err == nil { + (*Transaction)(tx).setDecoded(inner, uint64(len(b))) + } + return err + default: + return rlp.ErrExpectedList + } +} + +func (tx *minimalTx) EncodeRLP(w io.Writer) error { + if (*Transaction)(tx).Type() == LegacyTxType { + return rlp.Encode(w, tx.inner) + } + // It's an EIP-2718 typed TX envelope. + buf := encodeBufferPool.Get().(*bytes.Buffer) + defer encodeBufferPool.Put(buf) + buf.Reset() + if err := (*Transaction)(tx).encodeTypedMinimal(buf); err != nil { + return err + } + return rlp.Encode(w, buf.Bytes()) +} + +// a view over a regular transactions slice, to RLP decode/encode the transactions all the minimal way +type extBlockTxs []*Transaction + +func (txs *extBlockTxs) DecodeRLP(s *rlp.Stream) error { + // we need generics to do this nicely... + var out []*minimalTx + for i, tx := range *txs { + out[i] = (*minimalTx)(tx) + } + if err := s.Decode(&out); err != nil { + return fmt.Errorf("failed to decode list of minimal txs: %v", err) + } + rawtxs := make([]*Transaction, len(out)) + for i, tx := range out { + rawtxs[i] = (*Transaction)(tx) + } + *txs = rawtxs + return nil +} + +func (txs *extBlockTxs) EncodeRLP(w io.Writer) error { + out := make([]*minimalTx, len(*txs)) + for i, tx := range *txs { + out[i] = (*minimalTx)(tx) + } + return rlp.Encode(w, &out) +} + // "external" block encoding. used for eth protocol, etc. type extblock struct { Header *Header - Txs []*Transaction + Txs *extBlockTxs Uncles []*Header Withdrawals []*Withdrawal `rlp:"optional"` } @@ -210,7 +314,7 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []* // TODO: panic if len(txs) != len(receipts) if len(txs) == 0 { - b.header.TxHash = EmptyRootHash + b.header.TxHash = EmptyTxsHash } else { b.header.TxHash = DeriveSha(Transactions(txs), hasher) b.transactions = make(Transactions, len(txs)) @@ -218,7 +322,7 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []* } if len(receipts) == 0 { - b.header.ReceiptHash = EmptyRootHash + b.header.ReceiptHash = EmptyReceiptsHash } else { b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher) b.header.Bloom = CreateBloom(receipts) @@ -250,7 +354,7 @@ func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Heade if withdrawals == nil { b.header.WithdrawalsHash = nil } else if len(withdrawals) == 0 { - b.header.WithdrawalsHash = &EmptyRootHash + b.header.WithdrawalsHash = &EmptyWithdrawalsHash } else { h := DeriveSha(Withdrawals(withdrawals), hasher) b.header.WithdrawalsHash = &h @@ -279,11 +383,15 @@ func CopyHeader(h *Header) *Header { if h.BaseFee != nil { cpy.BaseFee = new(big.Int).Set(h.BaseFee) } + if h.ExcessDataGas != nil { + cpy.SetExcessDataGas(h.ExcessDataGas) + } if len(h.Extra) > 0 { cpy.Extra = make([]byte, len(h.Extra)) copy(cpy.Extra, h.Extra) } if h.WithdrawalsHash != nil { + cpy.WithdrawalsHash = new(common.Hash) *cpy.WithdrawalsHash = *h.WithdrawalsHash } return &cpy @@ -291,21 +399,32 @@ func CopyHeader(h *Header) *Header { // DecodeRLP decodes the Ethereum func (b *Block) DecodeRLP(s *rlp.Stream) error { - var eb extblock + eb := extblock{Txs: new(extBlockTxs)} _, size, _ := s.Kind() if err := s.Decode(&eb); err != nil { return err } - b.header, b.uncles, b.transactions, b.withdrawals = eb.Header, eb.Uncles, eb.Txs, eb.Withdrawals + for i, tx := range *eb.Txs { + if tx.wrapData != nil { + return fmt.Errorf("transactions in blocks must not contain wrap-data, tx %d is bad", i) + } + } + b.header, b.uncles, b.transactions, b.withdrawals = eb.Header, eb.Uncles, []*Transaction(*eb.Txs), eb.Withdrawals b.size.Store(rlp.ListSize(size)) return nil } // EncodeRLP serializes b into the Ethereum RLP block format. func (b *Block) EncodeRLP(w io.Writer) error { + if b.header.ExcessDataGas != nil && b.header.WithdrawalsHash == nil { + // This situation should not arise, but if it does (due to a bug) you'd silently produce an + // encoding that would fail to decode. ref: + // https://github.com/ethereum/go-ethereum/pull/26077 + return errors.New("nil WithdrawalsHash in header with non-nil ExcessDataGas") + } return rlp.Encode(w, extblock{ Header: b.header, - Txs: b.transactions, + Txs: (*extBlockTxs)(&b.transactions), Uncles: b.uncles, Withdrawals: b.withdrawals, }) @@ -354,6 +473,13 @@ func (b *Block) Withdrawals() Withdrawals { return b.withdrawals } +func (b *Block) ExcessDataGas() *big.Int { + if b.header.ExcessDataGas == nil { + return nil + } + return new(big.Int).Set(b.header.ExcessDataGas) +} + func (b *Block) Header() *Header { return CopyHeader(b.header) } // Body returns the non-header content of the block. diff --git a/core/types/data_blob.go b/core/types/data_blob.go new file mode 100644 index 00000000000..9daf1cf4b7a --- /dev/null +++ b/core/types/data_blob.go @@ -0,0 +1,416 @@ +package types + +import ( + "encoding/hex" + "errors" + "fmt" + "io" + + gokzg4844 "github.com/crate-crypto/go-kzg-4844" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto/kzg" + "github.com/ethereum/go-ethereum/params" + + "github.com/protolambda/ztyp/codec" +) + +// Compressed BLS12-381 G1 element +type KZGCommitment [48]byte + +func (p *KZGCommitment) Deserialize(dr *codec.DecodingReader) error { + if p == nil { + return errors.New("nil pubkey") + } + _, err := dr.Read(p[:]) + return err +} + +func (p *KZGCommitment) Serialize(w *codec.EncodingWriter) error { + return w.Write(p[:]) +} + +func (KZGCommitment) ByteLength() uint64 { + return 48 +} + +func (KZGCommitment) FixedLength() uint64 { + return 48 +} + +func (p KZGCommitment) MarshalText() ([]byte, error) { + return []byte("0x" + hex.EncodeToString(p[:])), nil +} + +func (p KZGCommitment) String() string { + return "0x" + hex.EncodeToString(p[:]) +} + +func (p *KZGCommitment) UnmarshalText(text []byte) error { + return hexutil.UnmarshalFixedText("KZGCommitment", text, p[:]) +} + +func (c KZGCommitment) ComputeVersionedHash() common.Hash { + return common.Hash(kzg.KZGToVersionedHash(gokzg4844.KZGCommitment(c))) +} + +// Compressed BLS12-381 G1 element +type KZGProof [48]byte + +func (p *KZGProof) Deserialize(dr *codec.DecodingReader) error { + if p == nil { + return errors.New("nil pubkey") + } + _, err := dr.Read(p[:]) + return err +} + +func (p *KZGProof) Serialize(w *codec.EncodingWriter) error { + return w.Write(p[:]) +} + +func (KZGProof) ByteLength() uint64 { + return 48 +} + +func (KZGProof) FixedLength() uint64 { + return 48 +} + +func (p KZGProof) MarshalText() ([]byte, error) { + return []byte("0x" + hex.EncodeToString(p[:])), nil +} + +func (p KZGProof) String() string { + return "0x" + hex.EncodeToString(p[:]) +} + +func (p *KZGProof) UnmarshalText(text []byte) error { + return hexutil.UnmarshalFixedText("KZGProof", text, p[:]) +} + +// BLSFieldElement is the raw bytes representation of a field element +type BLSFieldElement [32]byte + +func (p BLSFieldElement) MarshalText() ([]byte, error) { + return []byte("0x" + hex.EncodeToString(p[:])), nil +} + +func (p BLSFieldElement) String() string { + return "0x" + hex.EncodeToString(p[:]) +} + +func (p *BLSFieldElement) UnmarshalText(text []byte) error { + return hexutil.UnmarshalFixedText("BLSFieldElement", text, p[:]) +} + +// Blob data +type Blob [params.FieldElementsPerBlob * 32]byte + +func (blob *Blob) Deserialize(dr *codec.DecodingReader) error { + if blob == nil { + return errors.New("cannot decode ssz into nil Blob") + } + + // We treat the blob as an opaque sequence of bytes + // and therefore we do not do any validation related to field + // elements + if _, err := dr.Read(blob[:]); err != nil { + return err + } + + return nil +} + +func (blob *Blob) Serialize(w *codec.EncodingWriter) error { + return w.Write(blob[:]) + +} + +func (blob *Blob) ByteLength() (out uint64) { + return params.FieldElementsPerBlob * 32 +} + +func (blob *Blob) FixedLength() uint64 { + return params.FieldElementsPerBlob * 32 +} + +func (blob *Blob) MarshalText() ([]byte, error) { + out := make([]byte, 2+params.FieldElementsPerBlob*32*2) + copy(out[:2], "0x") + hex.Encode(out[2:], blob[:]) + + return out, nil +} + +func (blob *Blob) String() string { + v, err := blob.MarshalText() + if err != nil { + return "" + } + return string(v) +} + +func (blob *Blob) UnmarshalText(text []byte) error { + if blob == nil { + return errors.New("cannot decode text into nil Blob") + } + l := 2 + params.FieldElementsPerBlob*32*2 + if len(text) != l { + return fmt.Errorf("expected %d characters but got %d", l, len(text)) + } + if !(text[0] == '0' && text[1] == 'x') { + return fmt.Errorf("expected '0x' prefix in Blob string") + } + if _, err := hex.Decode(blob[:], text[2:]); err != nil { + return fmt.Errorf("blob is not formatted correctly: %v", err) + } + + return nil +} + +type BlobKzgs []KZGCommitment + +func (li *BlobKzgs) Deserialize(dr *codec.DecodingReader) error { + return dr.List(func() codec.Deserializable { + i := len(*li) + *li = append(*li, KZGCommitment{}) + return &(*li)[i] + }, 48, params.MaxBlobsPerBlock) +} + +func (li BlobKzgs) Serialize(w *codec.EncodingWriter) error { + return w.List(func(i uint64) codec.Serializable { + return &li[i] + }, 48, uint64(len(li))) +} + +func (li BlobKzgs) ByteLength() uint64 { + return uint64(len(li)) * 48 +} + +func (li BlobKzgs) FixedLength() uint64 { + return 0 +} + +func (li BlobKzgs) copy() BlobKzgs { + cpy := make(BlobKzgs, len(li)) + copy(cpy, li) + return cpy +} + +type KZGProofs []KZGProof + +func (li *KZGProofs) Deserialize(dr *codec.DecodingReader) error { + return dr.List(func() codec.Deserializable { + i := len(*li) + *li = append(*li, KZGProof{}) + return &(*li)[i] + }, 48, params.MaxBlobsPerBlock) +} + +func (li KZGProofs) Serialize(w *codec.EncodingWriter) error { + return w.List(func(i uint64) codec.Serializable { + return &li[i] + }, 48, uint64(len(li))) +} + +func (li KZGProofs) ByteLength() uint64 { + return uint64(len(li)) * 48 +} + +func (li KZGProofs) FixedLength() uint64 { + return 0 +} + +func (li KZGProofs) copy() KZGProofs { + cpy := make(KZGProofs, len(li)) + copy(cpy, li) + return cpy +} + +type Blobs []Blob + +func (a *Blobs) Deserialize(dr *codec.DecodingReader) error { + return dr.List(func() codec.Deserializable { + i := len(*a) + *a = append(*a, Blob{}) + return &(*a)[i] + }, params.FieldElementsPerBlob*32, params.FieldElementsPerBlob) +} + +func (a Blobs) Serialize(w *codec.EncodingWriter) error { + return w.List(func(i uint64) codec.Serializable { + return &a[i] + }, params.FieldElementsPerBlob*32, uint64(len(a))) +} + +func (a Blobs) ByteLength() (out uint64) { + return uint64(len(a)) * params.FieldElementsPerBlob * 32 +} + +func (a *Blobs) FixedLength() uint64 { + return 0 // it's a list, no fixed length +} + +func (blobs Blobs) copy() Blobs { + cpy := make(Blobs, len(blobs)) + copy(cpy, blobs) // each blob element is an array and gets deep-copied + return cpy +} + +// Return KZG commitments, versioned hashes and the proofs that correspond to these blobs +func (blobs Blobs) ComputeCommitmentsAndProofs() (commitments []KZGCommitment, versionedHashes []common.Hash, proofs []KZGProof, err error) { + commitments = make([]KZGCommitment, len(blobs)) + proofs = make([]KZGProof, len(blobs)) + versionedHashes = make([]common.Hash, len(blobs)) + + cryptoCtx := kzg.CrpytoCtx() + for i, blob := range blobs { + commitment, err := cryptoCtx.BlobToKZGCommitment(gokzg4844.Blob(blob)) + if err != nil { + return nil, nil, nil, fmt.Errorf("could not convert blob to commitment: %v", err) + } + + proof, err := cryptoCtx.ComputeBlobKZGProof(gokzg4844.Blob(blob), commitment) + if err != nil { + return nil, nil, nil, fmt.Errorf("could not compute proof for blob: %v", err) + } + commitments[i] = KZGCommitment(commitment) + proofs[i] = KZGProof(proof) + versionedHashes[i] = common.Hash(kzg.KZGToVersionedHash(gokzg4844.KZGCommitment(commitment))) + } + + return commitments, versionedHashes, proofs, nil +} + +func toBlobs(_blobs Blobs) []gokzg4844.Blob { + blobs := make([]gokzg4844.Blob, len(_blobs)) + for i, _blob := range _blobs { + blobs[i] = gokzg4844.Blob(_blob) + } + return blobs +} +func toComms(_comms BlobKzgs) []gokzg4844.KZGCommitment { + comms := make([]gokzg4844.KZGCommitment, len(_comms)) + for i, _comm := range _comms { + comms[i] = gokzg4844.KZGCommitment(_comm) + } + return comms +} +func toProofs(_proofs KZGProofs) []gokzg4844.KZGProof { + proofs := make([]gokzg4844.KZGProof, len(_proofs)) + for i, _proof := range _proofs { + proofs[i] = gokzg4844.KZGProof(_proof) + } + return proofs +} + +type BlobTxWrapper struct { + Tx SignedBlobTx + BlobKzgs BlobKzgs + Blobs Blobs + Proofs KZGProofs +} + +func (txw *BlobTxWrapper) Deserialize(dr *codec.DecodingReader) error { + return dr.Container(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.Proofs) +} + +func (txw *BlobTxWrapper) Serialize(w *codec.EncodingWriter) error { + return w.Container(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.Proofs) +} + +func (txw *BlobTxWrapper) ByteLength() uint64 { + return codec.ContainerLength(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.Proofs) +} + +func (txw *BlobTxWrapper) FixedLength() uint64 { + return 0 +} + +type BlobTxWrapData struct { + BlobKzgs BlobKzgs + Blobs Blobs + Proofs KZGProofs +} + +// sizeWrapData returns the size in bytes of the ssz-encoded BlobTxWrapData +func (b *BlobTxWrapData) sizeWrapData() common.StorageSize { + return common.StorageSize(codec.ContainerLength(&b.BlobKzgs, &b.Blobs, &b.Proofs)) +} + +// validateBlobTransactionWrapper implements validate_blob_transaction_wrapper from EIP-4844 +func (b *BlobTxWrapData) validateBlobTransactionWrapper(inner TxData) error { + blobTx, ok := inner.(*SignedBlobTx) + if !ok { + return fmt.Errorf("expected signed blob tx, got %T", inner) + } + l1 := len(blobTx.Message.BlobVersionedHashes) + if l1 == 0 { + return errors.New("blob transactions must have at least one blob") + } + l2 := len(b.BlobKzgs) + l3 := len(b.Blobs) + l4 := len(b.Proofs) + if l1 != l2 || l1 != l3 || l1 != l4 { + return fmt.Errorf("lengths don't match %v %v %v %v", l1, l2, l3, l4) + } + // the following check isn't strictly necessary as it would be caught by data gas processing + // (and hence it is not explicitly in the spec for this function), but it doesn't hurt to fail + // early in case we are getting spammed with too many blobs or there is a bug somewhere: + if l1 > params.MaxBlobsPerBlock { + return fmt.Errorf("number of blobs exceeds max: %v", l1) + } + cryptoCtx := kzg.CrpytoCtx() + err := cryptoCtx.VerifyBlobKZGProofBatch(toBlobs(b.Blobs), toComms(b.BlobKzgs), toProofs(b.Proofs)) + if err != nil { + return fmt.Errorf("error during proof verification: %v", err) + } + if !ok { + return errors.New("failed to verify kzg") + } + for i, h := range blobTx.Message.BlobVersionedHashes { + if computed := b.BlobKzgs[i].ComputeVersionedHash(); computed != h { + return fmt.Errorf("versioned hash %d supposedly %s but does not match computed %s", i, h, computed) + } + } + return nil +} + +func (b *BlobTxWrapData) copy() TxWrapData { + return &BlobTxWrapData{ + BlobKzgs: b.BlobKzgs.copy(), + Blobs: b.Blobs.copy(), + Proofs: b.Proofs.copy(), + } +} + +func (b *BlobTxWrapData) kzgs() BlobKzgs { + return b.BlobKzgs +} + +func (b *BlobTxWrapData) blobs() Blobs { + return b.Blobs +} + +func (b *BlobTxWrapData) proofs() KZGProofs { + return b.Proofs +} + +func (b *BlobTxWrapData) encodeTyped(w io.Writer, txdata TxData) error { + if _, err := w.Write([]byte{BlobTxType}); err != nil { + return err + } + blobTx, ok := txdata.(*SignedBlobTx) + if !ok { + return fmt.Errorf("expected signed blob tx, got %T", txdata) + } + wrapped := BlobTxWrapper{ + Tx: *blobTx, + BlobKzgs: b.BlobKzgs, + Blobs: b.Blobs, + Proofs: b.Proofs, + } + return EncodeSSZ(w, &wrapped) +} diff --git a/core/types/data_blob_tx.go b/core/types/data_blob_tx.go new file mode 100644 index 00000000000..a35fa981aba --- /dev/null +++ b/core/types/data_blob_tx.go @@ -0,0 +1,430 @@ +package types + +import ( + "encoding/hex" + "errors" + "fmt" + "math/big" + + "github.com/holiman/uint256" + "github.com/protolambda/ztyp/codec" + "github.com/protolambda/ztyp/conv" + . "github.com/protolambda/ztyp/view" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" +) + +type ECDSASignature struct { + V Uint8View + R Uint256View + S Uint256View +} + +func (sig *ECDSASignature) Deserialize(dr *codec.DecodingReader) error { + return dr.FixedLenContainer(&sig.V, &sig.R, &sig.S) +} + +func (sig *ECDSASignature) Serialize(w *codec.EncodingWriter) error { + return w.FixedLenContainer(&sig.V, &sig.R, &sig.S) +} + +func (*ECDSASignature) ByteLength() uint64 { + return 1 + 32 + 32 +} + +func (*ECDSASignature) FixedLength() uint64 { + return 1 + 32 + 32 +} + +type AddressSSZ common.Address + +func (addr *AddressSSZ) Deserialize(dr *codec.DecodingReader) error { + if addr == nil { + return errors.New("cannot deserialize into nil Address") + } + _, err := dr.Read(addr[:]) + return err +} + +func (addr *AddressSSZ) Serialize(w *codec.EncodingWriter) error { + return w.Write(addr[:]) +} + +func (*AddressSSZ) ByteLength() uint64 { + return 20 +} + +func (*AddressSSZ) FixedLength() uint64 { + return 20 +} + +// AddressOptionalSSZ implements Union[None, Address] +type AddressOptionalSSZ struct { + Address *AddressSSZ +} + +func (ao *AddressOptionalSSZ) Deserialize(dr *codec.DecodingReader) error { + if ao == nil { + return errors.New("cannot deserialize into nil Address") + } + if v, err := dr.ReadByte(); err != nil { + return err + } else if v == 0 { + ao.Address = nil + return nil + } else if v == 1 { + ao.Address = new(AddressSSZ) + if err := ao.Address.Deserialize(dr); err != nil { + return err + } + return nil + } else { + return fmt.Errorf("invalid union selector for Union[None, Address]: %d", v) + } +} + +func (ao *AddressOptionalSSZ) Serialize(w *codec.EncodingWriter) error { + if ao.Address == nil { + return w.WriteByte(0) + } else { + if err := w.WriteByte(1); err != nil { + return err + } + return ao.Address.Serialize(w) + } +} + +func (ao *AddressOptionalSSZ) ByteLength() uint64 { + if ao.Address == nil { + return 1 + } else { + return 1 + 20 + } +} + +func (*AddressOptionalSSZ) FixedLength() uint64 { + return 0 +} + +type TxDataView []byte + +func (tdv *TxDataView) Deserialize(dr *codec.DecodingReader) error { + return dr.ByteList((*[]byte)(tdv), MAX_CALLDATA_SIZE) +} + +func (tdv TxDataView) Serialize(w *codec.EncodingWriter) error { + return w.Write(tdv) +} + +func (tdv TxDataView) ByteLength() (out uint64) { + return uint64(len(tdv)) +} + +func (tdv *TxDataView) FixedLength() uint64 { + return 0 +} + +func (tdv TxDataView) MarshalText() ([]byte, error) { + return conv.BytesMarshalText(tdv[:]) +} + +func (tdv TxDataView) String() string { + return "0x" + hex.EncodeToString(tdv[:]) +} + +func (tdv *TxDataView) UnmarshalText(text []byte) error { + if tdv == nil { + return errors.New("cannot decode into nil blob data") + } + return conv.DynamicBytesUnmarshalText((*[]byte)(tdv), text[:]) +} + +// ReadHashes reads length hashes from dr and returns them through hashes, reusing existing capacity if possible. Hashes will always be +// non-nil on return. +func ReadHashes(dr *codec.DecodingReader, hashes *[]common.Hash, length uint64) error { + if uint64(len(*hashes)) != length { + // re-use space if available (for recycling old state objects) + if uint64(cap(*hashes)) >= length { + *hashes = (*hashes)[:length] + } else { + *hashes = make([]common.Hash, length) + } + } else if *hashes == nil { + // make sure the output is never nil + *hashes = []common.Hash{} + } + dst := *hashes + for i := uint64(0); i < length; i++ { + if _, err := dr.Read(dst[i][:]); err != nil { + return err + } + } + return nil +} + +func ReadHashesLimited(dr *codec.DecodingReader, hashes *[]common.Hash, limit uint64) error { + scope := dr.Scope() + if scope%32 != 0 { + return fmt.Errorf("bad deserialization scope, cannot decode hashes list") + } + length := scope / 32 + if length > limit { + return fmt.Errorf("too many hashes: %d > %d", length, limit) + } + return ReadHashes(dr, hashes, length) +} + +func WriteHashes(ew *codec.EncodingWriter, hashes []common.Hash) error { + for i := range hashes { + if err := ew.Write(hashes[i][:]); err != nil { + return err + } + } + return nil +} + +type VersionedHashesView []common.Hash + +func (vhv *VersionedHashesView) Deserialize(dr *codec.DecodingReader) error { + return ReadHashesLimited(dr, (*[]common.Hash)(vhv), MAX_VERSIONED_HASHES_LIST_SIZE) +} + +func (vhv VersionedHashesView) Serialize(w *codec.EncodingWriter) error { + return WriteHashes(w, vhv) +} + +func (vhv VersionedHashesView) ByteLength() (out uint64) { + return uint64(len(vhv)) * 32 +} + +func (vhv *VersionedHashesView) FixedLength() uint64 { + return 0 // it's a list, no fixed length +} + +type StorageKeysView []common.Hash + +func (skv *StorageKeysView) Deserialize(dr *codec.DecodingReader) error { + return ReadHashesLimited(dr, (*[]common.Hash)(skv), MAX_ACCESS_LIST_STORAGE_KEYS) +} + +func (skv StorageKeysView) Serialize(w *codec.EncodingWriter) error { + return WriteHashes(w, skv) +} + +func (skv StorageKeysView) ByteLength() (out uint64) { + return uint64(len(skv)) * 32 +} + +func (skv *StorageKeysView) FixedLength() uint64 { + return 0 // it's a list, no fixed length +} + +type AccessTupleView AccessTuple + +func (atv *AccessTupleView) Deserialize(dr *codec.DecodingReader) error { + return dr.Container((*AddressSSZ)(&atv.Address), (*StorageKeysView)(&atv.StorageKeys)) +} + +func (atv *AccessTupleView) Serialize(w *codec.EncodingWriter) error { + return w.Container((*AddressSSZ)(&atv.Address), (*StorageKeysView)(&atv.StorageKeys)) +} + +func (atv *AccessTupleView) ByteLength() uint64 { + return codec.ContainerLength((*AddressSSZ)(&atv.Address), (*StorageKeysView)(&atv.StorageKeys)) +} + +func (atv *AccessTupleView) FixedLength() uint64 { + return 0 +} + +type AccessListView AccessList + +func (alv *AccessListView) Deserialize(dr *codec.DecodingReader) error { + *alv = AccessListView([]AccessTuple{}) + return dr.List(func() codec.Deserializable { + i := len(*alv) + *alv = append(*alv, AccessTuple{}) + return (*AccessTupleView)(&((*alv)[i])) + }, 0, MAX_ACCESS_LIST_SIZE) +} + +func (alv AccessListView) Serialize(w *codec.EncodingWriter) error { + return w.List(func(i uint64) codec.Serializable { + return (*AccessTupleView)(&alv[i]) + }, 0, uint64(len(alv))) +} + +func (alv AccessListView) ByteLength() (out uint64) { + for _, v := range alv { + out += (*AccessTupleView)(&v).ByteLength() + codec.OFFSET_SIZE + } + return +} + +func (alv *AccessListView) FixedLength() uint64 { + return 0 +} + +type BlobTxMessage struct { + ChainID Uint256View + Nonce Uint64View + GasTipCap Uint256View // a.k.a. maxPriorityFeePerGas + GasFeeCap Uint256View // a.k.a. maxFeePerGas + Gas Uint64View + To AddressOptionalSSZ // nil means contract creation + Value Uint256View + Data TxDataView + AccessList AccessListView + MaxFeePerDataGas Uint256View + + BlobVersionedHashes VersionedHashesView +} + +func (tx *BlobTxMessage) Deserialize(dr *codec.DecodingReader) error { + return dr.Container(&tx.ChainID, &tx.Nonce, &tx.GasTipCap, &tx.GasFeeCap, &tx.Gas, &tx.To, &tx.Value, &tx.Data, &tx.AccessList, &tx.MaxFeePerDataGas, &tx.BlobVersionedHashes) +} + +func (tx *BlobTxMessage) Serialize(w *codec.EncodingWriter) error { + return w.Container(&tx.ChainID, &tx.Nonce, &tx.GasTipCap, &tx.GasFeeCap, &tx.Gas, &tx.To, &tx.Value, &tx.Data, &tx.AccessList, &tx.MaxFeePerDataGas, &tx.BlobVersionedHashes) +} + +func (tx *BlobTxMessage) ByteLength() uint64 { + return codec.ContainerLength(&tx.ChainID, &tx.Nonce, &tx.GasTipCap, &tx.GasFeeCap, &tx.Gas, &tx.To, &tx.Value, &tx.Data, &tx.AccessList, &tx.MaxFeePerDataGas, &tx.BlobVersionedHashes) +} + +func (tx *BlobTxMessage) FixedLength() uint64 { + return 0 +} + +func (tx *BlobTxMessage) setChainID(chainID *big.Int) { + (*uint256.Int)(&tx.ChainID).SetFromBig(chainID) +} + +func (stx *SignedBlobTx) ByteLength() uint64 { + return codec.ContainerLength(&stx.Message, &stx.Signature) +} + +func (stx *SignedBlobTx) FixedLength() uint64 { + return 0 +} + +// copy creates a deep copy of the transaction data and initializes all fields. +func (tx *BlobTxMessage) copy() *BlobTxMessage { + cpy := &BlobTxMessage{ + ChainID: tx.ChainID, + Nonce: tx.Nonce, + GasTipCap: tx.GasTipCap, + GasFeeCap: tx.GasFeeCap, + Gas: tx.Gas, + To: AddressOptionalSSZ{Address: (*AddressSSZ)(copyAddressPtr((*common.Address)(tx.To.Address)))}, + Value: tx.Value, + Data: common.CopyBytes(tx.Data), + AccessList: make([]AccessTuple, len(tx.AccessList)), + MaxFeePerDataGas: tx.MaxFeePerDataGas, + BlobVersionedHashes: make([]common.Hash, len(tx.BlobVersionedHashes)), + } + copy(cpy.AccessList, tx.AccessList) + copy(cpy.BlobVersionedHashes, tx.BlobVersionedHashes) + + return cpy +} + +type SignedBlobTx struct { + Message BlobTxMessage + Signature ECDSASignature +} + +const ( + MAX_CALLDATA_SIZE = 1 << 24 + MAX_ACCESS_LIST_SIZE = 1 << 24 + MAX_ACCESS_LIST_STORAGE_KEYS = 1 << 24 + MAX_VERSIONED_HASHES_LIST_SIZE = 1 << 24 +) + +func (stx *SignedBlobTx) Deserialize(dr *codec.DecodingReader) error { + return dr.Container(&stx.Message, &stx.Signature) +} + +func (stx *SignedBlobTx) Serialize(w *codec.EncodingWriter) error { + return w.Container(&stx.Message, &stx.Signature) +} + +// copy creates a deep copy of the transaction data and initializes all fields. +func (stx *SignedBlobTx) copy() TxData { + cpy := &SignedBlobTx{ + Message: *stx.Message.copy(), + Signature: stx.Signature, + } + + return cpy +} + +func u256ToBig(v *Uint256View) *big.Int { + return (*uint256.Int)(v).ToBig() +} + +// accessors for innerTx. +func (stx *SignedBlobTx) txType() byte { return BlobTxType } +func (stx *SignedBlobTx) chainID() *big.Int { return u256ToBig(&stx.Message.ChainID) } +func (stx *SignedBlobTx) accessList() AccessList { return AccessList(stx.Message.AccessList) } +func (stx *SignedBlobTx) dataHashes() []common.Hash { return stx.Message.BlobVersionedHashes } +func (stx *SignedBlobTx) data() []byte { return stx.Message.Data } +func (stx *SignedBlobTx) gas() uint64 { return uint64(stx.Message.Gas) } +func (stx *SignedBlobTx) gasFeeCap() *big.Int { return u256ToBig(&stx.Message.GasFeeCap) } +func (stx *SignedBlobTx) gasTipCap() *big.Int { return u256ToBig(&stx.Message.GasTipCap) } +func (stx *SignedBlobTx) maxFeePerDataGas() *big.Int { return u256ToBig(&stx.Message.MaxFeePerDataGas) } +func (stx *SignedBlobTx) gasPrice() *big.Int { return u256ToBig(&stx.Message.GasFeeCap) } +func (stx *SignedBlobTx) value() *big.Int { return u256ToBig(&stx.Message.Value) } +func (stx *SignedBlobTx) nonce() uint64 { return uint64(stx.Message.Nonce) } +func (stx *SignedBlobTx) to() *common.Address { return (*common.Address)(stx.Message.To.Address) } + +func (stx *SignedBlobTx) rawSignatureValues() (v, r, s *big.Int) { + return big.NewInt(int64(stx.Signature.V)), u256ToBig(&stx.Signature.R), u256ToBig(&stx.Signature.S) +} + +func (stx *SignedBlobTx) setSignatureValues(chainID, v, r, s *big.Int) { + stx.Message.setChainID(chainID) + stx.Signature.V = Uint8View(v.Uint64()) + (*uint256.Int)(&stx.Signature.R).SetFromBig(r) + (*uint256.Int)(&stx.Signature.S).SetFromBig(s) +} + +func (tx *SignedBlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { + if baseFee == nil { + return dst.Set(tx.gasFeeCap()) + } + tip := dst.Sub(tx.gasFeeCap(), baseFee) + if tip.Cmp(tx.gasTipCap()) > 0 { + tip.Set(tx.gasTipCap()) + } + return tip.Add(tip, baseFee) +} + +// fakeExponential approximates factor * e ** (num / denom) using a taylor expansion +// as described in the EIP-4844 spec. +func fakeExponential(factor, num, denom *big.Int) *big.Int { + output := new(big.Int) + numAccum := new(big.Int).Mul(factor, denom) + for i := 1; numAccum.Sign() > 0; i++ { + output.Add(output, numAccum) + numAccum.Mul(numAccum, num) + iBig := big.NewInt(int64(i)) + numAccum.Div(numAccum, iBig.Mul(iBig, denom)) + } + return output.Div(output, denom) +} + +// GetDataGasPrice implements get_data_gas_price from EIP-4844 +func GetDataGasPrice(excessDataGas *big.Int) *big.Int { + if excessDataGas == nil { + return nil + } + return fakeExponential(big.NewInt(params.MinDataGasPrice), excessDataGas, big.NewInt(params.DataGasPriceUpdateFraction)) +} + +// GetDataGasUsed returns the amount of datagas consumed by a transaction with the specified number +// of blobs +func GetDataGasUsed(blobs int) uint64 { + return uint64(blobs) * params.DataGasPerBlob +} diff --git a/core/types/data_blob_tx_test.go b/core/types/data_blob_tx_test.go new file mode 100644 index 00000000000..a98322b9ff7 --- /dev/null +++ b/core/types/data_blob_tx_test.go @@ -0,0 +1,40 @@ +package types + +import ( + "math/big" + "testing" +) + +func TestFakeExponential(t *testing.T) { + var tests = []struct { + factor, num, denom int64 + want int64 + }{ + // When num==0 the return value should always equal the value of factor + {1, 0, 1, 1}, + {38493, 0, 1000, 38493}, + {0, 1234, 2345, 0}, // should be 0 + {1, 2, 1, 6}, // approximate 7.389 + {1, 4, 2, 6}, + {1, 3, 1, 16}, // approximate 20.09 + {1, 6, 2, 18}, + {1, 4, 1, 49}, // approximate 54.60 + {1, 8, 2, 50}, + {10, 8, 2, 542}, // approximate 540.598 + {11, 8, 2, 596}, // approximate 600.58 + {1, 5, 1, 136}, // approximate 148.4 + {1, 5, 2, 11}, // approximate 12.18 + {2, 5, 2, 23}, // approximate 24.36 + } + + for _, tt := range tests { + factor := big.NewInt(tt.factor) + num := big.NewInt(tt.num) + denom := big.NewInt(tt.denom) + result := fakeExponential(factor, num, denom) + //t.Logf("%v*e^(%v/%v): %v", factor, num, denom, result) + if tt.want != result.Int64() { + t.Errorf("got %v want %v", result, tt.want) + } + } +} diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go index 5c8b81652d2..06916042c4b 100644 --- a/core/types/gen_header_json.go +++ b/core/types/gen_header_json.go @@ -33,6 +33,7 @@ func (h Header) MarshalJSON() ([]byte, error) { Nonce BlockNonce `json:"nonce"` BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ExcessDataGas *hexutil.Big `json:"excessDataGas" rlp:"optional"` Hash common.Hash `json:"hash"` } var enc Header @@ -53,6 +54,7 @@ func (h Header) MarshalJSON() ([]byte, error) { enc.Nonce = h.Nonce enc.BaseFee = (*hexutil.Big)(h.BaseFee) enc.WithdrawalsHash = h.WithdrawalsHash + enc.ExcessDataGas = (*hexutil.Big)(h.ExcessDataGas) enc.Hash = h.Hash() return json.Marshal(&enc) } @@ -77,6 +79,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { Nonce *BlockNonce `json:"nonce"` BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ExcessDataGas *hexutil.Big `json:"excessDataGas" rlp:"optional"` } var dec Header if err := json.Unmarshal(input, &dec); err != nil { @@ -145,5 +148,8 @@ func (h *Header) UnmarshalJSON(input []byte) error { if dec.WithdrawalsHash != nil { h.WithdrawalsHash = dec.WithdrawalsHash } + if dec.ExcessDataGas != nil { + h.ExcessDataGas = (*big.Int)(dec.ExcessDataGas) + } return nil } diff --git a/core/types/gen_header_rlp.go b/core/types/gen_header_rlp.go index 7fd2cf8f2d3..005f6c2ad45 100644 --- a/core/types/gen_header_rlp.go +++ b/core/types/gen_header_rlp.go @@ -42,7 +42,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { w.WriteBytes(obj.Nonce[:]) _tmp1 := obj.BaseFee != nil _tmp2 := obj.WithdrawalsHash != nil - if _tmp1 || _tmp2 { + _tmp3 := obj.ExcessDataGas != nil + if _tmp1 || _tmp2 || _tmp3 { if obj.BaseFee == nil { w.Write(rlp.EmptyString) } else { @@ -52,13 +53,23 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { w.WriteBigInt(obj.BaseFee) } } - if _tmp2 { + if _tmp2 || _tmp3 { if obj.WithdrawalsHash == nil { w.Write([]byte{0x80}) } else { w.WriteBytes(obj.WithdrawalsHash[:]) } } + if _tmp3 { + if obj.ExcessDataGas == nil { + w.Write(rlp.EmptyString) + } else { + if obj.ExcessDataGas.Sign() == -1 { + return rlp.ErrNegativeBigInt + } + w.WriteBigInt(obj.ExcessDataGas) + } + } w.ListEnd(_tmp0) return w.Flush() } diff --git a/core/types/gen_receipt_json.go b/core/types/gen_receipt_json.go index bb892f85bec..83133c8d13b 100644 --- a/core/types/gen_receipt_json.go +++ b/core/types/gen_receipt_json.go @@ -25,6 +25,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + EffectiveGasPrice *big.Int `json:"effectiveGasPrice,omitempty"` + DataGasUsed uint64 `json:"dataGasUsed,omitempty"` + DataGasPrice *big.Int `json:"dataGasPrice,omitempty"` BlockHash common.Hash `json:"blockHash,omitempty"` BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` TransactionIndex hexutil.Uint `json:"transactionIndex"` @@ -39,6 +42,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { enc.TxHash = r.TxHash enc.ContractAddress = r.ContractAddress enc.GasUsed = hexutil.Uint64(r.GasUsed) + enc.EffectiveGasPrice = r.EffectiveGasPrice + enc.DataGasUsed = r.DataGasUsed + enc.DataGasPrice = r.DataGasPrice enc.BlockHash = r.BlockHash enc.BlockNumber = (*hexutil.Big)(r.BlockNumber) enc.TransactionIndex = hexutil.Uint(r.TransactionIndex) @@ -57,6 +63,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { TxHash *common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress *common.Address `json:"contractAddress"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + EffectiveGasPrice *big.Int `json:"effectiveGasPrice,omitempty"` + DataGasUsed *uint64 `json:"dataGasUsed,omitempty"` + DataGasPrice *big.Int `json:"dataGasPrice,omitempty"` BlockHash *common.Hash `json:"blockHash,omitempty"` BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` TransactionIndex *hexutil.Uint `json:"transactionIndex"` @@ -97,6 +106,15 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'gasUsed' for Receipt") } r.GasUsed = uint64(*dec.GasUsed) + if dec.EffectiveGasPrice != nil { + r.EffectiveGasPrice = dec.EffectiveGasPrice + } + if dec.DataGasUsed != nil { + r.DataGasUsed = *dec.DataGasUsed + } + if dec.DataGasPrice != nil { + r.DataGasPrice = dec.DataGasPrice + } if dec.BlockHash != nil { r.BlockHash = *dec.BlockHash } diff --git a/core/types/hashes.go b/core/types/hashes.go new file mode 100644 index 00000000000..3bad430be57 --- /dev/null +++ b/core/types/hashes.go @@ -0,0 +1,42 @@ +// Copyright 2023 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 types + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +var ( + // EmptyRootHash is the known root hash of an empty trie. + EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + + // EmptyUncleHash is the known hash of the empty uncle set. + EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 + + // EmptyCodeHash is the known hash of the empty EVM bytecode. + EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 + + // EmptyTxsHash is the known hash of the empty transaction set. + EmptyTxsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + + // EmptyReceiptsHash is the known hash of the empty receipt set. + EmptyReceiptsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + + // EmptyWithdrawalsHash is the known hash of the empty withdrawal set. + EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") +) diff --git a/core/types/hashing.go b/core/types/hashing.go index 3df75432a4b..0bc049206dc 100644 --- a/core/types/hashing.go +++ b/core/types/hashing.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" + "github.com/protolambda/ztyp/codec" "golang.org/x/crypto/sha3" ) @@ -58,6 +59,18 @@ func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) { return h } +// prefixedSSZHash writes the prefix into the hasher before SSZ encoding x. It's used for +// computing the tx id & signing hashes of signed blob transactions. +func prefixedSSZHash(prefix byte, obj codec.Serializable) (h common.Hash) { + sha := hasherPool.Get().(crypto.KeccakState) + defer hasherPool.Put(sha) + sha.Reset() + sha.Write([]byte{prefix}) + EncodeSSZ(sha, obj) + sha.Read(h[:]) + return h +} + // TrieHasher is the tool used to calculate the hash of derivable list. // This is internal, do not use. type TrieHasher interface { diff --git a/core/types/receipt.go b/core/types/receipt.go index 4404b278891..8c51bb4678b 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -59,10 +59,15 @@ type Receipt struct { Logs []*Log `json:"logs" gencodec:"required"` // Implementation fields: These fields are added by geth when processing a transaction. - // They are stored in the chain database. TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` + // TODO: EffectiveGasPrice should be a required field: + // https://github.com/ethereum/execution-apis/blob/af82a989bead35e2325ecc49a9023df39c548756/src/schemas/receipt.yaml#L49 + // Changing it to required is currently breaking cmd/evm/t8n_test.go, so leaving as omitempty for now. + EffectiveGasPrice *big.Int `json:"effectiveGasPrice,omitempty"` + DataGasUsed uint64 `json:"dataGasUsed,omitempty"` + DataGasPrice *big.Int `json:"dataGasPrice,omitempty"` // Inclusion information: These fields provide information about the inclusion of the // transaction corresponding to this receipt. @@ -193,7 +198,7 @@ func (r *Receipt) decodeTyped(b []byte) error { return errShortTypedReceipt } switch b[0] { - case DynamicFeeTxType, AccessListTxType: + case BlobTxType, DynamicFeeTxType, AccessListTxType: var data receiptRLP err := rlp.DecodeBytes(b[1:], &data) if err != nil { @@ -268,6 +273,8 @@ func (r *ReceiptForStorage) EncodeRLP(_w io.Writer) error { return w.Flush() } +// TODO: might need additional decoding for SSZ receipt? + // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation // fields of a receipt from an RLP stream. func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { @@ -304,6 +311,9 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) { case DynamicFeeTxType: w.WriteByte(DynamicFeeTxType) rlp.Encode(w, data) + case BlobTxType: + w.WriteByte(BlobTxType) + rlp.Encode(w, data) default: // For unsupported types, write nothing. Since this is for // DeriveSha, the error will be caught matching the derived hash @@ -313,10 +323,9 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) { // DeriveFields fills the receipts with their computed fields based on consensus // data and contextual infos like containing block and transactions. -func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, txs Transactions) error { - signer := MakeSigner(config, new(big.Int).SetUint64(number)) +func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, parentExcessDataGas *big.Int, txs []*Transaction) error { + signer := MakeSigner(config, new(big.Int).SetUint64(number), time) - logIndex := uint(0) if len(txs) != len(rs) { return errors.New("transaction and receipt count mismatch") } @@ -325,6 +334,8 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu rs[i].Type = txs[i].Type() rs[i].TxHash = txs[i].Hash() + rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee) + // block location fields rs[i].BlockHash = hash rs[i].BlockNumber = new(big.Int).SetUint64(number) @@ -335,20 +346,41 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu // Deriving the signer is expensive, only do if it's actually needed from, _ := Sender(signer, txs[i]) rs[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce()) + } else { + rs[i].ContractAddress = common.Address{} } + // The used gas can be calculated based on previous r if i == 0 { rs[i].GasUsed = rs[i].CumulativeGasUsed } else { rs[i].GasUsed = rs[i].CumulativeGasUsed - rs[i-1].CumulativeGasUsed } + + // Set data gas fields for blob-containing txs + if len(txs[i].DataHashes()) > 0 { + rs[i].DataGasUsed = GetDataGasUsed(len(txs[i].DataHashes())) + rs[i].DataGasPrice = GetDataGasPrice(parentExcessDataGas) + } + } + return rs.DeriveLogFields(hash, number, txs) +} + +// DeriveLogFields fills the receipt logs with their computed fields based on consensus data and +// contextual infos like containing block and transactions. +func (rs Receipts) DeriveLogFields(hash common.Hash, number uint64, txs []*Transaction) error { + if len(txs) != len(rs) { + return errors.New("transaction and receipt count mismatch") + } + logIndex := uint(0) + for i, r := range rs { // The derived log fields can simply be set from the block and transaction - for j := 0; j < len(rs[i].Logs); j++ { - rs[i].Logs[j].BlockNumber = number - rs[i].Logs[j].BlockHash = hash - rs[i].Logs[j].TxHash = rs[i].TxHash - rs[i].Logs[j].TxIndex = uint(i) - rs[i].Logs[j].Index = logIndex + for _, l := range r.Logs { + l.BlockNumber = number + l.BlockHash = hash + l.TxHash = txs[i].Hash() + l.TxIndex = uint(i) + l.Index = logIndex logIndex++ } } diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index f44bb80b04b..15a8c2ea9c1 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -18,15 +18,19 @@ package types import ( "bytes" + "encoding/json" "math" "math/big" "reflect" "testing" + "github.com/holiman/uint256" + "github.com/protolambda/ztyp/view" + "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/kylelemons/godebug/diff" ) var ( @@ -96,122 +100,208 @@ func TestDeriveFields(t *testing.T) { // Create a few transactions to have receipts for to2 := common.HexToAddress("0x2") to3 := common.HexToAddress("0x3") + to4 := common.HexToAddress("0x4") + to5 := common.HexToAddress("0x5") + to6 := common.HexToAddress("0x6") + + blobTx := &SignedBlobTx{ + Message: BlobTxMessage{ + To: AddressOptionalSSZ{Address: (*AddressSSZ)(&to6)}, + Nonce: view.Uint64View(6), + Value: view.Uint256View(*uint256.NewInt(6)), + Gas: view.Uint64View(6), + GasTipCap: view.Uint256View(*uint256.NewInt(66)), + GasFeeCap: view.Uint256View(*uint256.NewInt(1066)), + }, + } + _, blobTx.Message.BlobVersionedHashes = oneEmptyBlobWrapData() + txs := Transactions{ NewTx(&LegacyTx{ Nonce: 1, Value: big.NewInt(1), Gas: 1, - GasPrice: big.NewInt(1), + GasPrice: big.NewInt(11), }), NewTx(&LegacyTx{ To: &to2, Nonce: 2, Value: big.NewInt(2), Gas: 2, - GasPrice: big.NewInt(2), + GasPrice: big.NewInt(22), }), NewTx(&AccessListTx{ To: &to3, Nonce: 3, Value: big.NewInt(3), Gas: 3, - GasPrice: big.NewInt(3), + GasPrice: big.NewInt(33), + }), + // EIP-1559 transactions. + NewTx(&DynamicFeeTx{ + To: &to4, + Nonce: 4, + Value: big.NewInt(4), + Gas: 4, + GasTipCap: big.NewInt(44), + GasFeeCap: big.NewInt(1045), }), + NewTx(&DynamicFeeTx{ + To: &to5, + Nonce: 5, + Value: big.NewInt(5), + Gas: 5, + GasTipCap: big.NewInt(55), + GasFeeCap: big.NewInt(1055), + }), + NewTx(blobTx), } + + blockNumber := big.NewInt(1) + blockHash := common.BytesToHash([]byte{0x03, 0x14}) + // Create the corresponding receipts receipts := Receipts{ &Receipt{ Status: ReceiptStatusFailed, CumulativeGasUsed: 1, Logs: []*Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, + { + Address: common.BytesToAddress([]byte{0x11}), + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + Index: 0, + }, + { + Address: common.BytesToAddress([]byte{0x01, 0x11}), + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + Index: 1, + }, }, - TxHash: txs[0].Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 1, + // derived fields: + TxHash: txs[0].Hash(), + ContractAddress: common.HexToAddress("0x5a443704dd4b594b382c22a083e2bd3090a6fef3"), + GasUsed: 1, + EffectiveGasPrice: big.NewInt(11), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 0, }, &Receipt{ PostState: common.Hash{2}.Bytes(), CumulativeGasUsed: 3, Logs: []*Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, + { + Address: common.BytesToAddress([]byte{0x22}), + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + Index: 2, + }, + { + Address: common.BytesToAddress([]byte{0x02, 0x22}), + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + Index: 3, + }, }, - TxHash: txs[1].Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 2, + // derived fields: + TxHash: txs[1].Hash(), + GasUsed: 2, + EffectiveGasPrice: big.NewInt(22), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 1, }, &Receipt{ Type: AccessListTxType, PostState: common.Hash{3}.Bytes(), CumulativeGasUsed: 6, - Logs: []*Log{ - {Address: common.BytesToAddress([]byte{0x33})}, - {Address: common.BytesToAddress([]byte{0x03, 0x33})}, - }, - TxHash: txs[2].Hash(), - ContractAddress: common.BytesToAddress([]byte{0x03, 0x33, 0x33}), - GasUsed: 3, + Logs: []*Log{}, + // derived fields: + TxHash: txs[2].Hash(), + GasUsed: 3, + EffectiveGasPrice: big.NewInt(33), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 2, + }, + &Receipt{ + Type: DynamicFeeTxType, + PostState: common.Hash{4}.Bytes(), + CumulativeGasUsed: 10, + Logs: []*Log{}, + // derived fields: + TxHash: txs[3].Hash(), + GasUsed: 4, + EffectiveGasPrice: big.NewInt(1044), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 3, + }, + &Receipt{ + Type: DynamicFeeTxType, + PostState: common.Hash{5}.Bytes(), + CumulativeGasUsed: 15, + Logs: []*Log{}, + // derived fields: + TxHash: txs[4].Hash(), + GasUsed: 5, + EffectiveGasPrice: big.NewInt(1055), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 4, + }, + &Receipt{ + Type: BlobTxType, + PostState: common.Hash{6}.Bytes(), + CumulativeGasUsed: 21, + Logs: []*Log{}, + // derived fields: + TxHash: txs[5].Hash(), + GasUsed: 6, + DataGasUsed: 131072, + EffectiveGasPrice: big.NewInt(1066), + DataGasPrice: big.NewInt(1), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 5, }, } - // Clear all the computed fields and re-derive them - number := big.NewInt(1) - hash := common.BytesToHash([]byte{0x03, 0x14}) - clearComputedFieldsOnReceipts(t, receipts) - if err := receipts.DeriveFields(params.TestChainConfig, hash, number.Uint64(), txs); err != nil { + // Re-derive receipts. + basefee := big.NewInt(1000) + derivedReceipts := clearComputedFieldsOnReceipts(receipts) + excessDataGas := new(big.Int) + err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), 0, basefee, excessDataGas, txs) + if err != nil { t.Fatalf("DeriveFields(...) = %v, want ", err) } - // Iterate over all the computed fields and check that they're correct - signer := MakeSigner(params.TestChainConfig, number) - logIndex := uint(0) - for i := range receipts { - if receipts[i].Type != txs[i].Type() { - t.Errorf("receipts[%d].Type = %d, want %d", i, receipts[i].Type, txs[i].Type()) - } - if receipts[i].TxHash != txs[i].Hash() { - t.Errorf("receipts[%d].TxHash = %s, want %s", i, receipts[i].TxHash.String(), txs[i].Hash().String()) - } - if receipts[i].BlockHash != hash { - t.Errorf("receipts[%d].BlockHash = %s, want %s", i, receipts[i].BlockHash.String(), hash.String()) - } - if receipts[i].BlockNumber.Cmp(number) != 0 { - t.Errorf("receipts[%c].BlockNumber = %s, want %s", i, receipts[i].BlockNumber.String(), number.String()) - } - if receipts[i].TransactionIndex != uint(i) { - t.Errorf("receipts[%d].TransactionIndex = %d, want %d", i, receipts[i].TransactionIndex, i) - } - if receipts[i].GasUsed != txs[i].Gas() { - t.Errorf("receipts[%d].GasUsed = %d, want %d", i, receipts[i].GasUsed, txs[i].Gas()) - } - if txs[i].To() != nil && receipts[i].ContractAddress != (common.Address{}) { - t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress.String(), (common.Address{}).String()) - } - from, _ := Sender(signer, txs[i]) - contractAddress := crypto.CreateAddress(from, txs[i].Nonce()) - if txs[i].To() == nil && receipts[i].ContractAddress != contractAddress { - t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress.String(), contractAddress.String()) - } - for j := range receipts[i].Logs { - if receipts[i].Logs[j].BlockNumber != number.Uint64() { - t.Errorf("receipts[%d].Logs[%d].BlockNumber = %d, want %d", i, j, receipts[i].Logs[j].BlockNumber, number.Uint64()) - } - if receipts[i].Logs[j].BlockHash != hash { - t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), hash.String()) - } - if receipts[i].Logs[j].TxHash != txs[i].Hash() { - t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String()) - } - if receipts[i].Logs[j].TxIndex != uint(i) { - t.Errorf("receipts[%d].Logs[%d].TransactionIndex = %d, want %d", i, j, receipts[i].Logs[j].TxIndex, i) - } - if receipts[i].Logs[j].Index != logIndex { - t.Errorf("receipts[%d].Logs[%d].Index = %d, want %d", i, j, receipts[i].Logs[j].Index, logIndex) - } - logIndex++ - } + // Check diff of receipts against derivedReceipts. + r1, err := json.MarshalIndent(receipts, "", " ") + if err != nil { + t.Fatal("error marshaling input receipts:", err) + } + r2, err := json.MarshalIndent(derivedReceipts, "", " ") + if err != nil { + t.Fatal("error marshaling derived receipts:", err) + } + d := diff.Diff(string(r1), string(r2)) + if d != "" { + t.Fatal("receipts differ:", d) } } @@ -342,41 +432,36 @@ func TestReceiptUnmarshalBinary(t *testing.T) { } } -func clearComputedFieldsOnReceipts(t *testing.T, receipts Receipts) { - t.Helper() - - for _, receipt := range receipts { - clearComputedFieldsOnReceipt(t, receipt) +func clearComputedFieldsOnReceipts(receipts []*Receipt) []*Receipt { + r := make([]*Receipt, len(receipts)) + for i, receipt := range receipts { + r[i] = clearComputedFieldsOnReceipt(receipt) } + return r } -func clearComputedFieldsOnReceipt(t *testing.T, receipt *Receipt) { - t.Helper() - - receipt.TxHash = common.Hash{} - receipt.BlockHash = common.Hash{} - receipt.BlockNumber = big.NewInt(math.MaxUint32) - receipt.TransactionIndex = math.MaxUint32 - receipt.ContractAddress = common.Address{} - receipt.GasUsed = 0 - - clearComputedFieldsOnLogs(t, receipt.Logs) +func clearComputedFieldsOnReceipt(receipt *Receipt) *Receipt { + cpy := *receipt + cpy.TxHash = common.Hash{0xff, 0xff, 0x11} + cpy.BlockHash = common.Hash{0xff, 0xff, 0x22} + cpy.BlockNumber = big.NewInt(math.MaxUint32) + cpy.TransactionIndex = math.MaxUint32 + cpy.ContractAddress = common.Address{0xff, 0xff, 0x33} + cpy.GasUsed = 0xffffffff + cpy.Logs = clearComputedFieldsOnLogs(receipt.Logs) + return &cpy } -func clearComputedFieldsOnLogs(t *testing.T, logs []*Log) { - t.Helper() - - for _, log := range logs { - clearComputedFieldsOnLog(t, log) +func clearComputedFieldsOnLogs(logs []*Log) []*Log { + l := make([]*Log, len(logs)) + for i, log := range logs { + cpy := *log + cpy.BlockNumber = math.MaxUint32 + cpy.BlockHash = common.Hash{} + cpy.TxHash = common.Hash{} + cpy.TxIndex = math.MaxUint32 + cpy.Index = math.MaxUint32 + l[i] = &cpy } -} - -func clearComputedFieldsOnLog(t *testing.T, log *Log) { - t.Helper() - - log.BlockNumber = math.MaxUint32 - log.BlockHash = common.Hash{} - log.TxHash = common.Hash{} - log.TxIndex = math.MaxUint32 - log.Index = math.MaxUint32 + return l } diff --git a/core/types/transaction.go b/core/types/transaction.go index 353e0e599c6..5c13cec634b 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -25,9 +25,12 @@ import ( "sync/atomic" "time" + "github.com/protolambda/ztyp/codec" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) @@ -45,6 +48,7 @@ const ( LegacyTxType = iota AccessListTxType DynamicFeeTxType + BlobTxType ) // Transaction is an Ethereum transaction. @@ -56,35 +60,76 @@ type Transaction struct { hash atomic.Value size atomic.Value from atomic.Value + + // sizeWrapData, 0 if there is no wrapData + sizeWrapData atomic.Value + + // For network propagation and disk, not embedded in the execution payload + wrapData TxWrapData } +type TxOption func(tx *Transaction) + // NewTx creates a new transaction. -func NewTx(inner TxData) *Transaction { +func NewTx(inner TxData, options ...TxOption) *Transaction { tx := new(Transaction) tx.setDecoded(inner.copy(), 0) + for _, txOpt := range options { + txOpt(tx) + } return tx } +// WithTxWrapData is a TxOption to add additional data to a transaction. +// wrapData may be nil to downgrade a transaction to a minimal tx. +func WithTxWrapData(wrapData TxWrapData) TxOption { + return func(tx *Transaction) { + if wrapData != nil { + tx.wrapData = wrapData.copy() + } + } +} + +type TxWrapData interface { + copy() TxWrapData + kzgs() BlobKzgs + blobs() Blobs + proofs() KZGProofs + encodeTyped(w io.Writer, txdata TxData) error + sizeWrapData() common.StorageSize + validateBlobTransactionWrapper(inner TxData) error +} + // TxData is the underlying data of a transaction. // -// This is implemented by DynamicFeeTx, LegacyTx and AccessListTx. +// This is implemented by DynamicFeeTx, LegacyTx, AccessListTx & SignedBlobTx. type TxData interface { txType() byte // returns the type ID copy() TxData // creates a deep copy and initializes all fields chainID() *big.Int accessList() AccessList + dataHashes() []common.Hash data() []byte gas() uint64 gasPrice() *big.Int gasTipCap() *big.Int gasFeeCap() *big.Int + maxFeePerDataGas() *big.Int value() *big.Int nonce() uint64 to() *common.Address rawSignatureValues() (v, r, s *big.Int) setSignatureValues(chainID, v, r, s *big.Int) + + // effectiveGasPrice computes the gas price paid by the transaction, given + // the inclusion block baseFee. + // + // Unlike other TxData methods, the returned *big.Int should be an independent + // copy of the computed value, i.e. callers are allowed to mutate the result. + // Method implementations can use 'dst' to store the result. + effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int } // EncodeRLP implements rlp.Encoder @@ -96,16 +141,34 @@ func (tx *Transaction) EncodeRLP(w io.Writer) error { buf := encodeBufferPool.Get().(*bytes.Buffer) defer encodeBufferPool.Put(buf) buf.Reset() - if err := tx.encodeTyped(buf); err != nil { + if err := tx.encodeTypedMinimal(buf); err != nil { return err } return rlp.Encode(w, buf.Bytes()) } -// encodeTyped writes the canonical encoding of a typed transaction to w. -func (tx *Transaction) encodeTyped(w *bytes.Buffer) error { - w.WriteByte(tx.Type()) - return rlp.Encode(w, tx.inner) +// encodeTyped writes the canonical encoding of a typed transaction to w, including wrapper data. +func (tx *Transaction) encodeTyped(w io.Writer) error { + if tx.wrapData != nil { + return tx.wrapData.encodeTyped(w, tx.inner) + } else { + return tx.encodeTypedMinimal(w) + } +} + +func (tx *Transaction) encodeTypedMinimal(w io.Writer) error { + if _, err := w.Write([]byte{tx.Type()}); err != nil { + return err + } + if tx.Type() == BlobTxType { + blobTx, ok := tx.inner.(*SignedBlobTx) + if !ok { + return ErrInvalidTxType + } + return EncodeSSZ(w, blobTx) + } else { + return rlp.Encode(w, tx.inner) + } } // MarshalBinary returns the canonical encoding of the transaction. @@ -120,6 +183,16 @@ func (tx *Transaction) MarshalBinary() ([]byte, error) { return buf.Bytes(), err } +// MarshalMinimal returns the minimal unwrapped encoding of the transaction. +func (tx *Transaction) MarshalMinimal() ([]byte, error) { + if tx.Type() == LegacyTxType { + return rlp.EncodeToBytes(tx.inner) + } + var buf bytes.Buffer + err := tx.encodeTypedMinimal(&buf) + return buf.Bytes(), err +} + // DecodeRLP implements rlp.Decoder func (tx *Transaction) DecodeRLP(s *rlp.Stream) error { kind, size, err := s.Kind() @@ -140,7 +213,7 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error { if b, err = s.Bytes(); err != nil { return err } - inner, err := tx.decodeTyped(b) + inner, err := tx.decodeTypedMinimal(b) if err == nil { tx.setDecoded(inner, uint64(len(b))) } @@ -162,16 +235,57 @@ func (tx *Transaction) UnmarshalBinary(b []byte) error { return nil } // It's an EIP2718 typed transaction envelope. - inner, err := tx.decodeTyped(b) + inner, wrapData, err := tx.decodeTyped(b) + if err != nil { + return err + } + tx.setDecoded(inner, 0) + tx.wrapData = wrapData + return nil +} + +// UnmarshalMinimal decodes the minimal encoding of transactions. +// It supports legacy RLP transactions and EIP2718 typed transactions. +func (tx *Transaction) UnmarshalMinimal(b []byte) error { + if len(b) > 0 && b[0] > 0x7f { + return tx.UnmarshalBinary(b) + } + // It's an EIP2718 typed transaction envelope. + inner, err := tx.decodeTypedMinimal(b) if err != nil { return err } tx.setDecoded(inner, uint64(len(b))) + tx.wrapData = nil return nil } +func DecodeSSZ(data []byte, dest codec.Deserializable) error { + return dest.Deserialize(codec.NewDecodingReader(bytes.NewReader(data), uint64(len(data)))) +} + +func EncodeSSZ(w io.Writer, obj codec.Serializable) error { + return obj.Serialize(codec.NewEncodingWriter(w)) +} + // decodeTyped decodes a typed transaction from the canonical format. -func (tx *Transaction) decodeTyped(b []byte) (TxData, error) { +func (tx *Transaction) decodeTyped(b []byte) (TxData, TxWrapData, error) { + if len(b) == 0 { + return nil, nil, errShortTypedTx + } + switch b[0] { + case BlobTxType: + var wrapped BlobTxWrapper + err := DecodeSSZ(b[1:], &wrapped) + return &wrapped.Tx, &BlobTxWrapData{BlobKzgs: wrapped.BlobKzgs, Blobs: wrapped.Blobs, Proofs: wrapped.Proofs}, err + default: + minimal, err := tx.decodeTypedMinimal(b) + return minimal, nil, err + } +} + +// decodeTyped decodes a typed transaction from the canonical format. +func (tx *Transaction) decodeTypedMinimal(b []byte) (TxData, error) { if len(b) <= 1 { return nil, errShortTypedTx } @@ -184,6 +298,10 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) { var inner DynamicFeeTx err := rlp.DecodeBytes(b[1:], &inner) return &inner, err + case BlobTxType: + var inner SignedBlobTx + err := DecodeSSZ(b[1:], &inner) + return &inner, err default: return nil, ErrTxTypeNotSupported } @@ -261,6 +379,9 @@ func (tx *Transaction) Data() []byte { return tx.inner.data() } // AccessList returns the access list of the transaction. func (tx *Transaction) AccessList() AccessList { return tx.inner.accessList() } +// DataHashes returns the blob versioned hashes of the transaction. +func (tx *Transaction) DataHashes() []common.Hash { return tx.inner.dataHashes() } + // Gas returns the gas limit of the transaction. func (tx *Transaction) Gas() uint64 { return tx.inner.gas() } @@ -273,6 +394,11 @@ func (tx *Transaction) GasTipCap() *big.Int { return new(big.Int).Set(tx.inner.g // GasFeeCap returns the fee cap per gas of the transaction. func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) } +// MaxFeePerDataGas returns the max_fee_per_data_gas value for the transaction +func (tx *Transaction) MaxFeePerDataGas() *big.Int { + return new(big.Int).Set(tx.inner.maxFeePerDataGas()) +} + // Value returns the ether amount of the transaction. func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) } @@ -285,13 +411,28 @@ func (tx *Transaction) To() *common.Address { return copyAddressPtr(tx.inner.to()) } -// Cost returns gas * gasPrice + value. +// Cost returns (gas * gasPrice) + (DataGas() * maxDataFeePerGas) + value. func (tx *Transaction) Cost() *big.Int { total := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())) total.Add(total, tx.Value()) + dataGasFee := tx.DataGas() + dataGasFee.Mul(dataGasFee, tx.MaxFeePerDataGas()) + total.Add(total, dataGasFee) return total } +// DataGas implements get_total_data_gas from EIP-4844. While this returns a big.Int for +// convenience, it should never exceed math.MaxUint64. +func (tx *Transaction) DataGas() *big.Int { + r := new(big.Int) + l := int64(len(tx.DataHashes())) + if l != 0 { + r.SetInt64(l) + r.Mul(r, big.NewInt(params.DataGasPerBlob)) + } + return r +} + // RawSignatureValues returns the V, R, S signature values of the transaction. // The return values should not be modified by the caller. func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) { @@ -363,9 +504,14 @@ func (tx *Transaction) Hash() common.Hash { } var h common.Hash - if tx.Type() == LegacyTxType { + switch tx.Type() { + case LegacyTxType: h = rlpHash(tx.inner) - } else { + case BlobTxType: + // TODO(eip-4844): We should remove this ugly switch by making hash() + // a part of the TxData interface + h = prefixedSSZHash(tx.Type(), tx.inner.(*SignedBlobTx)) + default: h = prefixedRlpHash(tx.Type(), tx.inner) } tx.hash.Store(h) @@ -389,6 +535,42 @@ func (tx *Transaction) Size() uint64 { return size } +func (tx *Transaction) WrapDataSize() common.StorageSize { + if size := tx.sizeWrapData.Load(); size != nil { + return size.(common.StorageSize) + } + var size common.StorageSize + if tx.wrapData != nil { + size = tx.wrapData.sizeWrapData() + } + tx.sizeWrapData.Store(size) + return size +} + +// IsIncomplete returns true if the transaction can be wrapped but is not. +func (tx *Transaction) IsIncomplete() bool { + return tx.Type() == BlobTxType && tx.wrapData == nil +} + +// VerifyBlobs verifies the blob transaction +func (tx *Transaction) VerifyBlobs() error { + if tx.wrapData != nil { + return tx.wrapData.validateBlobTransactionWrapper(tx.inner) + } + return nil +} + +// BlobWrapData returns the blob and kzg data, if any. +// kzgs and blobs may be empty if the transaction is not wrapped. +func (tx *Transaction) BlobWrapData() (versionedHashes []common.Hash, kzgs BlobKzgs, blobs Blobs, proofs KZGProofs) { + if blobWrap, ok := tx.wrapData.(*BlobTxWrapData); ok { + if signedBlobTx, ok := tx.inner.(*SignedBlobTx); ok { + return signedBlobTx.Message.BlobVersionedHashes, blobWrap.BlobKzgs, blobWrap.Blobs, blobWrap.Proofs + } + } + return nil, nil, nil, nil +} + // WithSignature returns a new transaction with the given signature. // This signature needs to be in the [R || S || V] format where V is 0 or 1. func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) { @@ -398,7 +580,11 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e } cpy := tx.inner.copy() cpy.setSignatureValues(signer.ChainID(), v, r, s) - return &Transaction{inner: cpy, time: tx.time}, nil + out := &Transaction{inner: cpy, time: tx.time} + if tx.wrapData != nil { + out.wrapData = tx.wrapData.copy() + } + return out, nil } // Transactions implements DerivableList for transactions. @@ -415,7 +601,7 @@ func (s Transactions) EncodeIndex(i int, w *bytes.Buffer) { if tx.Type() == LegacyTxType { rlp.Encode(w, tx.inner) } else { - tx.encodeTyped(w) + tx.encodeTypedMinimal(w) } } @@ -581,74 +767,6 @@ func (t *TransactionsByPriceAndNonce) Pop() { heap.Pop(&t.heads) } -// Message is a fully derived transaction and implements core.Message -// -// NOTE: In a future PR this will be removed. -type Message struct { - to *common.Address - from common.Address - nonce uint64 - amount *big.Int - gasLimit uint64 - gasPrice *big.Int - gasFeeCap *big.Int - gasTipCap *big.Int - data []byte - accessList AccessList - isFake bool -} - -func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, accessList AccessList, isFake bool) Message { - return Message{ - from: from, - to: to, - nonce: nonce, - amount: amount, - gasLimit: gasLimit, - gasPrice: gasPrice, - gasFeeCap: gasFeeCap, - gasTipCap: gasTipCap, - data: data, - accessList: accessList, - isFake: isFake, - } -} - -// AsMessage returns the transaction as a core.Message. -func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) { - msg := Message{ - nonce: tx.Nonce(), - gasLimit: tx.Gas(), - gasPrice: new(big.Int).Set(tx.GasPrice()), - gasFeeCap: new(big.Int).Set(tx.GasFeeCap()), - gasTipCap: new(big.Int).Set(tx.GasTipCap()), - to: tx.To(), - amount: tx.Value(), - data: tx.Data(), - accessList: tx.AccessList(), - isFake: false, - } - // If baseFee provided, set gasPrice to effectiveGasPrice. - if baseFee != nil { - msg.gasPrice = math.BigMin(msg.gasPrice.Add(msg.gasTipCap, baseFee), msg.gasFeeCap) - } - var err error - msg.from, err = Sender(s, tx) - return msg, err -} - -func (m Message) From() common.Address { return m.from } -func (m Message) To() *common.Address { return m.to } -func (m Message) GasPrice() *big.Int { return m.gasPrice } -func (m Message) GasFeeCap() *big.Int { return m.gasFeeCap } -func (m Message) GasTipCap() *big.Int { return m.gasTipCap } -func (m Message) Value() *big.Int { return m.amount } -func (m Message) Gas() uint64 { return m.gasLimit } -func (m Message) Nonce() uint64 { return m.nonce } -func (m Message) Data() []byte { return m.data } -func (m Message) AccessList() AccessList { return m.accessList } -func (m Message) IsFake() bool { return m.isFake } - // copyAddressPtr copies an address. func copyAddressPtr(a *common.Address) *common.Address { if a == nil { @@ -657,3 +775,65 @@ func copyAddressPtr(a *common.Address) *common.Address { cpy := *a return &cpy } + +// NetworkTransaction is a Transaction wrapper that encodes its maximal representation +type NetworkTransaction struct { + Tx *Transaction +} + +func NewNetworkTransaction(tx *Transaction) *NetworkTransaction { + return &NetworkTransaction{Tx: tx} +} + +// EncodeRLP implements rlp.Encoder +func (tx *NetworkTransaction) EncodeRLP(w io.Writer) error { + if tx.Tx.Type() == LegacyTxType { + return rlp.Encode(w, tx.Tx) + } + // It's an EIP-2718 typed TX envelope. + buf := encodeBufferPool.Get().(*bytes.Buffer) + defer encodeBufferPool.Put(buf) + buf.Reset() + if err := tx.Tx.encodeTyped(buf); err != nil { + return err + } + return rlp.Encode(w, buf.Bytes()) +} + +// DecodeRLP implements rlp.Decoder +func (tx *NetworkTransaction) DecodeRLP(s *rlp.Stream) error { + kind, size, err := s.Kind() + switch { + case err != nil: + return err + case kind == rlp.List: + // It's a legacy transaction. + var inner LegacyTx + err := s.Decode(&inner) + if err == nil { + tx.Tx = new(Transaction) + tx.Tx.setDecoded(&inner, rlp.ListSize(size)) + } + return err + default: + // It's an EIP-2718 typed TX envelope. + var b []byte + if b, err = s.Bytes(); err != nil { + return err + } + inner, wrapData, err := tx.Tx.decodeTyped(b) + if err == nil { + tx.Tx = new(Transaction) + tx.Tx.setDecoded(inner, 0) + tx.Tx.wrapData = wrapData + } + return err + } +} + +// Hash returns the transaction hash. +func (tx *NetworkTransaction) Hash() common.Hash { + return tx.Tx.Hash() +} + +type NetworkTransactions []*NetworkTransaction diff --git a/core/types/transaction_marshalling.go b/core/types/transaction_marshalling.go index 2566d0b8d65..ae5b356352f 100644 --- a/core/types/transaction_marshalling.go +++ b/core/types/transaction_marshalling.go @@ -19,8 +19,11 @@ package types import ( "encoding/json" "errors" + "fmt" "math/big" + "github.com/protolambda/ztyp/view" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -46,6 +49,13 @@ type txJSON struct { ChainID *hexutil.Big `json:"chainId,omitempty"` AccessList *AccessList `json:"accessList,omitempty"` + // Blob transaction fields: + MaxFeePerDataGas *hexutil.Big `json:"maxFeePerDataGas,omitempty"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + Blobs Blobs `json:"blobs,omitempty"` + BlobKzgs BlobKzgs `json:"blobKzgs,omitempty"` + Proofs KZGProofs `json:"proofs,omitempty"` + // Only used for encoding: Hash common.Hash `json:"hash"` } @@ -94,6 +104,27 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) { enc.V = (*hexutil.Big)(itx.V) enc.R = (*hexutil.Big)(itx.R) enc.S = (*hexutil.Big)(itx.S) + case *SignedBlobTx: + enc.ChainID = (*hexutil.Big)(u256ToBig(&itx.Message.ChainID)) + enc.AccessList = (*AccessList)(&itx.Message.AccessList) + enc.Nonce = (*hexutil.Uint64)(&itx.Message.Nonce) + enc.Gas = (*hexutil.Uint64)(&itx.Message.Gas) + enc.MaxFeePerGas = (*hexutil.Big)(u256ToBig(&itx.Message.GasFeeCap)) + enc.MaxPriorityFeePerGas = (*hexutil.Big)(u256ToBig(&itx.Message.GasTipCap)) + enc.Value = (*hexutil.Big)(u256ToBig(&itx.Message.Value)) + enc.Data = (*hexutil.Bytes)(&itx.Message.Data) + enc.To = tx.To() + v, r, s := tx.RawSignatureValues() + enc.V = (*hexutil.Big)(v) + enc.R = (*hexutil.Big)(r) + enc.S = (*hexutil.Big)(s) + enc.MaxFeePerDataGas = (*hexutil.Big)(u256ToBig(&itx.Message.MaxFeePerDataGas)) + enc.BlobVersionedHashes = itx.Message.BlobVersionedHashes + if tx.wrapData != nil { + enc.Blobs = tx.wrapData.blobs() + enc.BlobKzgs = tx.wrapData.kzgs() + enc.Proofs = tx.wrapData.proofs() + } } return json.Marshal(&enc) } @@ -262,7 +293,84 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { return err } } - + case BlobTxType: + var itx SignedBlobTx + inner = &itx + // Access list is optional for now + if dec.AccessList != nil { + itx.Message.AccessList = AccessListView(*dec.AccessList) + } else { + itx.Message.AccessList = AccessListView(AccessList{}) + } + if dec.ChainID == nil { + return errors.New("missing required field 'chainId' in transaction") + } + itx.Message.ChainID.SetFromBig((*big.Int)(dec.ChainID)) + if dec.To != nil { + itx.Message.To.Address = (*AddressSSZ)(dec.To) + } + if dec.Nonce == nil { + return errors.New("missing required field 'nonce' in transaction") + } + itx.Message.Nonce = view.Uint64View(*dec.Nonce) + if dec.MaxPriorityFeePerGas == nil { + return errors.New("missing required field 'maxPriorityFeePerGas' for txdata") + } + itx.Message.GasTipCap.SetFromBig((*big.Int)(dec.MaxPriorityFeePerGas)) + if dec.MaxFeePerGas == nil { + return errors.New("missing required field 'maxFeePerGas' for txdata") + } + itx.Message.GasFeeCap.SetFromBig((*big.Int)(dec.MaxFeePerGas)) + if dec.Gas == nil { + return errors.New("missing required field 'gas' for txdata") + } + itx.Message.Gas = view.Uint64View(*dec.Gas) + if dec.Value == nil { + return errors.New("missing required field 'value' in transaction") + } + itx.Message.Value.SetFromBig((*big.Int)(dec.Value)) + if dec.Data == nil { + return errors.New("missing required field 'input' in transaction") + } + itx.Message.Data = TxDataView(*dec.Data) + if dec.V == nil { + return errors.New("missing required field 'v' in transaction") + } + itx.Signature.V = view.Uint8View((*big.Int)(dec.V).Uint64()) + if dec.R == nil { + return errors.New("missing required field 'r' in transaction") + } + itx.Signature.R.SetFromBig((*big.Int)(dec.R)) + if dec.S == nil { + return errors.New("missing required field 's' in transaction") + } + itx.Signature.S.SetFromBig((*big.Int)(dec.S)) + withSignature := (*big.Int)(dec.V).Sign() != 0 || (*big.Int)(dec.R).Sign() != 0 || (*big.Int)(dec.S).Sign() != 0 + if withSignature { + if err := sanityCheckSignature(big.NewInt(int64(itx.Signature.V)), u256ToBig(&itx.Signature.R), u256ToBig(&itx.Signature.S), false); err != nil { + return err + } + } + if dec.MaxFeePerDataGas == nil { + return errors.New("missing required field 'maxFeePerDataGas' for txdata") + } + itx.Message.MaxFeePerDataGas.SetFromBig((*big.Int)(dec.MaxFeePerDataGas)) + if dec.BlobVersionedHashes == nil { + return errors.New("missing required field 'blobVersionedHashes' in transaction") + } + itx.Message.BlobVersionedHashes = dec.BlobVersionedHashes + // A BlobTx may not contain data + if len(dec.Blobs) != 0 || len(dec.BlobKzgs) != 0 { + tx.wrapData = &BlobTxWrapData{ + BlobKzgs: dec.BlobKzgs, + Blobs: dec.Blobs, + Proofs: dec.Proofs, + } + // Verify that versioned hashes match kzgs, and kzgs match blobs. + if err := tx.wrapData.validateBlobTransactionWrapper(&itx); err != nil { + return fmt.Errorf("blob wrapping data is invalid: %v", err) + } + } default: return ErrTxTypeNotSupported } diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 87f0390a6f9..c03f56bea40 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -36,10 +36,12 @@ type sigCache struct { from common.Address } -// MakeSigner returns a Signer based on the given chain config and block number. -func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer { +// MakeSigner returns a Signer based on the given chain config, block number and time. +func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, time uint64) Signer { var signer Signer switch { + case config.IsCancun(time): + signer = NewDankSigner(config.ChainID) case config.IsLondon(blockNumber): signer = NewLondonSigner(config.ChainID) case config.IsBerlin(blockNumber): @@ -63,6 +65,9 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer { // have the current block number available, use MakeSigner instead. func LatestSigner(config *params.ChainConfig) Signer { if config.ChainID != nil { + if config.CancunTime != nil { + return NewDankSigner(config.ChainID) + } if config.LondonBlock != nil { return NewLondonSigner(config.ChainID) } @@ -87,7 +92,8 @@ func LatestSignerForChainID(chainID *big.Int) Signer { if chainID == nil { return HomesteadSigner{} } - return NewLondonSigner(chainID) + return NewDankSigner(chainID) + } // SignTx signs the transaction using the given signer and private key. @@ -101,8 +107,8 @@ func SignTx(tx *Transaction, s Signer, prv *ecdsa.PrivateKey) (*Transaction, err } // SignNewTx creates a transaction and signs it. -func SignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) (*Transaction, error) { - tx := NewTx(txdata) +func SignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData, options ...TxOption) (*Transaction, error) { + tx := NewTx(txdata, options...) h := s.Hash(tx) sig, err := crypto.Sign(h[:], prv) if err != nil { @@ -113,8 +119,8 @@ func SignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) (*Transaction, er // MustSignNewTx creates a transaction and signs it. // This panics if the transaction cannot be signed. -func MustSignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) *Transaction { - tx, err := SignNewTx(prv, s, txdata) +func MustSignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData, options ...TxOption) *Transaction { + tx, err := SignNewTx(prv, s, txdata, options...) if err != nil { panic(err) } @@ -170,6 +176,64 @@ type Signer interface { Equal(Signer) bool } +type dankSigner struct{ londonSigner } + +// NewDankSigner returns a signer that accepts +// - (Mini) DankSharding transactions +// - EIP-1559 dynamic fee transactions +// - EIP-2930 access list transactions, +// - EIP-155 replay protected transactions, and +// - legacy Homestead transactions. +func NewDankSigner(chainId *big.Int) Signer { + return dankSigner{londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}} +} + +func (s dankSigner) Sender(tx *Transaction) (common.Address, error) { + if tx.Type() != BlobTxType { + return s.londonSigner.Sender(tx) + } + V, R, S := tx.RawSignatureValues() + // DynamicFee txs are defined to use 0 and 1 as their recovery + // id, add 27 to become equivalent to unprotected Homestead signatures. + V = new(big.Int).Add(V, big.NewInt(27)) + if tx.ChainId().Cmp(s.chainId) != 0 { + return common.Address{}, ErrInvalidChainId + } + return recoverPlain(s.Hash(tx), R, S, V, true) +} + +func (s dankSigner) Equal(s2 Signer) bool { + x, ok := s2.(dankSigner) + return ok && x.chainId.Cmp(s.chainId) == 0 +} + +func (s dankSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { + txdata, ok := tx.inner.(*SignedBlobTx) + if !ok { + return s.londonSigner.SignatureValues(tx, sig) + } + id := u256ToBig(&txdata.Message.ChainID) + // Check that chain ID of tx matches the signer. We also accept ID zero here, + // because it indicates that the chain ID was not specified in the tx. + if id.Sign() != 0 && id.Cmp(s.chainId) != 0 { + return nil, nil, nil, ErrInvalidChainId + } + R, S, _ = decodeSignature(sig) + V = big.NewInt(int64(sig[64])) + return R, S, V, nil +} + +// Hash returns the hash to be signed by the sender. +// It does not uniquely identify the transaction. +func (s dankSigner) Hash(tx *Transaction) common.Hash { + if tx.Type() != BlobTxType { + return s.londonSigner.Hash(tx) + } + messageSigning := tx.inner.(*SignedBlobTx).Message + messageSigning.setChainID(s.chainId) + return prefixedSSZHash(BlobTxType, &messageSigning) +} + type londonSigner struct{ eip2930Signer } // NewLondonSigner returns a signer that accepts diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go index 2a9ceb09529..701261c631d 100644 --- a/core/types/transaction_signing_test.go +++ b/core/types/transaction_signing_test.go @@ -24,6 +24,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" + "github.com/protolambda/ztyp/view" ) func TestEIP155Signing(t *testing.T) { @@ -77,6 +79,44 @@ func TestEIP155ChainId(t *testing.T) { } } +func TestEIP4844Signing(t *testing.T) { + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + + signer := NewDankSigner(big.NewInt(18)) + msg := BlobTxMessage{ + Nonce: view.Uint64View(0), + Gas: view.Uint64View(123457), + To: AddressOptionalSSZ{Address: (*AddressSSZ)(&addr)}, + GasTipCap: view.Uint256View(*uint256.NewInt(42)), + GasFeeCap: view.Uint256View(*uint256.NewInt(10)), + MaxFeePerDataGas: view.Uint256View(*uint256.NewInt(10)), + Value: view.Uint256View(*uint256.NewInt(10)), + } + var wrapData TxWrapData + wrapData, msg.BlobVersionedHashes = oneEmptyBlobWrapData() + txdata := &SignedBlobTx{Message: msg} + tx := NewTx(txdata, WithTxWrapData(wrapData)) + tx, err := SignTx(tx, signer, key) + if err != nil { + t.Fatal(err) + } + if !tx.Protected() { + t.Fatal("expected tx to be protected") + } + + if tx.ChainId().Cmp(signer.ChainID()) != 0 { + t.Error("expected chainId to be", signer.ChainID(), "got", tx.ChainId()) + } + sender, err := Sender(signer, tx) + if err != nil { + t.Fatal(err) + } + if sender != addr { + t.Error("expected sender to be", addr, "got", sender) + } +} + func TestEIP155SigningVitalik(t *testing.T) { // Test vectors come from http://vitalik.ca/files/eip155_testvec.txt for i, test := range []struct { diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 4b96c6b91a0..39af48fd23e 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -28,8 +28,13 @@ import ( "testing" "time" + gokzg4844 "github.com/crate-crypto/go-kzg-4844" + "github.com/holiman/uint256" + "github.com/protolambda/ztyp/view" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg" "github.com/ethereum/go-ethereum/rlp" ) @@ -73,6 +78,21 @@ var ( ) ) +// Returns a wrapper consisting of a single blob of all zeros that passes validation along with its +// versioned hash. +func oneEmptyBlobWrapData() (wrap *BlobTxWrapData, versionedHashes VersionedHashesView) { + cryptoCtx := kzg.CrpytoCtx() + blob := Blob{} + commitment, _ := cryptoCtx.BlobToKZGCommitment(gokzg4844.Blob(blob)) + proof, _ := cryptoCtx.ComputeBlobKZGProof(gokzg4844.Blob(blob), commitment) + wrapData := &BlobTxWrapData{ + BlobKzgs: BlobKzgs{KZGCommitment(commitment)}, + Blobs: Blobs{Blob(blob)}, + Proofs: KZGProofs{KZGProof(proof)}, + } + return wrapData, VersionedHashesView{common.Hash(kzg.KZGToVersionedHash(gokzg4844.KZGCommitment(wrapData.BlobKzgs[0])))} +} + func TestDecodeEmptyTypedTx(t *testing.T) { input := []byte{0x80} var tx Transaction @@ -412,14 +432,15 @@ func TestTransactionCoding(t *testing.T) { t.Fatalf("could not generate key: %v", err) } var ( - signer = NewEIP2930Signer(common.Big1) + signer = NewDankSigner(common.Big1) addr = common.HexToAddress("0x0000000000000000000000000000000000000001") recipient = common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") accesses = AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}} ) - for i := uint64(0); i < 500; i++ { + for i := uint64(0); i < 700; i++ { var txdata TxData - switch i % 5 { + var wrapData TxWrapData + switch i % 7 { case 0: // Legacy tx. txdata = &LegacyTx{ @@ -467,8 +488,28 @@ func TestTransactionCoding(t *testing.T) { GasPrice: big.NewInt(10), AccessList: accesses, } + case 5: + txdata = &DynamicFeeTx{ + ChainID: big.NewInt(1), + Nonce: i, + Gas: 123457, + GasTipCap: big.NewInt(42), + GasFeeCap: big.NewInt(10), + AccessList: accesses, + } + case 6: + msg := BlobTxMessage{ + ChainID: view.Uint256View(*uint256.NewInt(1)), + Nonce: view.Uint64View(i), + Gas: view.Uint64View(123457), + GasTipCap: view.Uint256View(*uint256.NewInt(42)), + GasFeeCap: view.Uint256View(*uint256.NewInt(10)), + AccessList: AccessListView(accesses), + } + wrapData, msg.BlobVersionedHashes = oneEmptyBlobWrapData() + txdata = &SignedBlobTx{Message: msg} } - tx, err := SignNewTx(key, signer, txdata) + tx, err := SignNewTx(key, signer, txdata, WithTxWrapData(wrapData)) if err != nil { t.Fatalf("could not sign transaction: %v", err) } @@ -492,6 +533,72 @@ func TestTransactionCoding(t *testing.T) { } } +// Make sure deserialized blob transactions never have nil access lists or versioned hash lists, +// even when empty. +func TestBlobTransactionEmptyLists(t *testing.T) { + txdata := &SignedBlobTx{ + Message: BlobTxMessage{ + ChainID: view.Uint256View(*uint256.NewInt(1)), + Nonce: view.Uint64View(1), + Gas: view.Uint64View(123457), + GasTipCap: view.Uint256View(*uint256.NewInt(42)), + GasFeeCap: view.Uint256View(*uint256.NewInt(10)), + MaxFeePerDataGas: view.Uint256View(*uint256.NewInt(10000000)), + }, + } + tx := NewTx(txdata) + data, err := tx.MarshalMinimal() + if err != nil { + t.Fatalf("ssz encoding failed: %v", err) + } + var parsedTx = &Transaction{} + if err := parsedTx.UnmarshalMinimal(data); err != nil { + t.Fatalf("ssz decoding failed: %v", err) + } + if parsedTx.AccessList() == nil { + t.Fatal("Deserialized blob txs should have non-nil access lists") + } + if parsedTx.DataHashes() == nil { + t.Fatal("Deserialized blob txs should have non-nil versioned hash lists") + } +} + +func TestBlobTransactionMinimalCodec(t *testing.T) { + key, err := crypto.GenerateKey() + if err != nil { + t.Fatalf("could not generate key: %v", err) + } + var ( + signer = NewDankSigner(common.Big1) + addr = common.HexToAddress("0x0000000000000000000000000000000000000001") + accesses = AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}} + ) + + txdata := &SignedBlobTx{ + Message: BlobTxMessage{ + ChainID: view.Uint256View(*uint256.NewInt(1)), + Nonce: view.Uint64View(1), + Gas: view.Uint64View(123457), + GasTipCap: view.Uint256View(*uint256.NewInt(42)), + GasFeeCap: view.Uint256View(*uint256.NewInt(10)), + AccessList: AccessListView(accesses), + BlobVersionedHashes: VersionedHashesView{common.HexToHash("0x01624652859a6e98ffc1608e2af0147ca4e86e1ce27672d8d3f3c9d4ffd6ef7e")}, + MaxFeePerDataGas: view.Uint256View(*uint256.NewInt(10000000)), + }, + } + tx, err := SignNewTx(key, signer, txdata) + if err != nil { + t.Fatalf("could not sign transaction: %v", err) + } + parsedTx, err := encodeDecodeJSON(tx) + if err != nil { + t.Fatal(err) + } + if err := assertEqual(parsedTx, tx); err != nil { + t.Fatal(err) + } +} + func encodeDecodeJSON(tx *Transaction) (*Transaction, error) { data, err := json.Marshal(tx) if err != nil { @@ -599,3 +706,27 @@ func TestTransactionSizes(t *testing.T) { } } } + +func TestVerifyBlobTransaction(t *testing.T) { + blobs := Blobs{Blob{}} + blobs[0][0] = 0xa + commitments, hashes, proofs, err := blobs.ComputeCommitmentsAndProofs() + if err != nil { + t.Fatalf("failed to compute commitments: %v", err) + } + + txData := SignedBlobTx{ + Message: BlobTxMessage{ + BlobVersionedHashes: hashes, + }, + } + wrapData := BlobTxWrapData{ + BlobKzgs: commitments, + Blobs: blobs, + Proofs: proofs, + } + tx := NewTx(&txData, WithTxWrapData(&wrapData)) + if err := tx.VerifyBlobs(); err != nil { + t.Fatalf("failed to verify blobs: %v", err) + } +} diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go index 620848fe624..68bc1ab3215 100644 --- a/core/types/tx_access_list.go +++ b/core/types/tx_access_list.go @@ -94,17 +94,23 @@ func (tx *AccessListTx) copy() TxData { } // accessors for innerTx. -func (tx *AccessListTx) txType() byte { return AccessListTxType } -func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID } -func (tx *AccessListTx) accessList() AccessList { return tx.AccessList } -func (tx *AccessListTx) data() []byte { return tx.Data } -func (tx *AccessListTx) gas() uint64 { return tx.Gas } -func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) value() *big.Int { return tx.Value } -func (tx *AccessListTx) nonce() uint64 { return tx.Nonce } -func (tx *AccessListTx) to() *common.Address { return tx.To } +func (tx *AccessListTx) txType() byte { return AccessListTxType } +func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID } +func (tx *AccessListTx) accessList() AccessList { return tx.AccessList } +func (tx *AccessListTx) dataHashes() []common.Hash { return nil } +func (tx *AccessListTx) data() []byte { return tx.Data } +func (tx *AccessListTx) gas() uint64 { return tx.Gas } +func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice } +func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice } +func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice } +func (tx *AccessListTx) maxFeePerDataGas() *big.Int { return new(big.Int) } +func (tx *AccessListTx) value() *big.Int { return tx.Value } +func (tx *AccessListTx) nonce() uint64 { return tx.Nonce } +func (tx *AccessListTx) to() *common.Address { return tx.To } + +func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { + return dst.Set(tx.GasPrice) +} func (tx *AccessListTx) rawSignatureValues() (v, r, s *big.Int) { return tx.V, tx.R, tx.S diff --git a/core/types/tx_dynamic_fee.go b/core/types/tx_dynamic_fee.go index 53f246ea1fa..f43598130a0 100644 --- a/core/types/tx_dynamic_fee.go +++ b/core/types/tx_dynamic_fee.go @@ -82,17 +82,30 @@ func (tx *DynamicFeeTx) copy() TxData { } // accessors for innerTx. -func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType } -func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID } -func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList } -func (tx *DynamicFeeTx) data() []byte { return tx.Data } -func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas } -func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap } -func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap } -func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap } -func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } -func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } -func (tx *DynamicFeeTx) to() *common.Address { return tx.To } +func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType } +func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID } +func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList } +func (tx *DynamicFeeTx) dataHashes() []common.Hash { return nil } +func (tx *DynamicFeeTx) data() []byte { return tx.Data } +func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas } +func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap } +func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap } +func (tx *DynamicFeeTx) maxFeePerDataGas() *big.Int { return new(big.Int) } +func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap } +func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } +func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } +func (tx *DynamicFeeTx) to() *common.Address { return tx.To } + +func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { + if baseFee == nil { + return dst.Set(tx.GasFeeCap) + } + tip := dst.Sub(tx.GasFeeCap, baseFee) + if tip.Cmp(tx.GasTipCap) > 0 { + tip.Set(tx.GasTipCap) + } + return tip.Add(tip, baseFee) +} func (tx *DynamicFeeTx) rawSignatureValues() (v, r, s *big.Int) { return tx.V, tx.R, tx.S diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go index 14d307829cc..22077ca0af9 100644 --- a/core/types/tx_legacy.go +++ b/core/types/tx_legacy.go @@ -91,17 +91,23 @@ func (tx *LegacyTx) copy() TxData { } // accessors for innerTx. -func (tx *LegacyTx) txType() byte { return LegacyTxType } -func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) } -func (tx *LegacyTx) accessList() AccessList { return nil } -func (tx *LegacyTx) data() []byte { return tx.Data } -func (tx *LegacyTx) gas() uint64 { return tx.Gas } -func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) value() *big.Int { return tx.Value } -func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } -func (tx *LegacyTx) to() *common.Address { return tx.To } +func (tx *LegacyTx) txType() byte { return LegacyTxType } +func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) } +func (tx *LegacyTx) accessList() AccessList { return nil } +func (tx *LegacyTx) dataHashes() []common.Hash { return nil } +func (tx *LegacyTx) data() []byte { return tx.Data } +func (tx *LegacyTx) gas() uint64 { return tx.Gas } +func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) maxFeePerDataGas() *big.Int { return new(big.Int) } +func (tx *LegacyTx) value() *big.Int { return tx.Value } +func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } +func (tx *LegacyTx) to() *common.Address { return tx.To } + +func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { + return dst.Set(tx.GasPrice) +} func (tx *LegacyTx) rawSignatureValues() (v, r, s *big.Int) { return tx.V, tx.R, tx.S diff --git a/core/types/types_test.go b/core/types/types_test.go index 1fb386d5dee..c40212aca29 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" + "github.com/protolambda/ztyp/view" ) type devnull struct{ len int } @@ -43,7 +44,7 @@ func BenchmarkDecodeRLP(b *testing.B) { func benchRLP(b *testing.B, encode bool) { key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") to := common.HexToAddress("0x00000000000000000000000000000000deadbeef") - signer := NewLondonSigner(big.NewInt(1337)) + signer := NewDankSigner(big.NewInt(1337)) for _, tc := range []struct { name string obj interface{} @@ -71,6 +72,19 @@ func benchRLP(b *testing.B, encode bool) { BaseFee: big.NewInt(10000000000), }, }, + { + "protodanksharding-header", + &Header{ + Difficulty: big.NewInt(10000000000), + Number: big.NewInt(1000), + GasLimit: 8_000_000, + GasUsed: 8_000_000, + Time: 555, + Extra: make([]byte, 32), + BaseFee: big.NewInt(10000000000), + ExcessDataGas: big.NewInt(0), + }, + }, { "receipt-for-storage", &ReceiptForStorage{ @@ -121,6 +135,25 @@ func benchRLP(b *testing.B, encode bool) { GasFeeCap: big.NewInt(500), }), }, + { + "blob-transaction", + MustSignNewTx(key, signer, + &SignedBlobTx{ + Message: BlobTxMessage{ + Nonce: 1, + Gas: 1000000, + To: AddressOptionalSSZ{Address: (*AddressSSZ)(&to)}, + Value: view.MustUint256("1"), + GasTipCap: view.MustUint256("500"), + GasFeeCap: view.MustUint256("500"), + BlobVersionedHashes: VersionedHashesView{common.Hash{0xaa}}, + }, + }, WithTxWrapData(&BlobTxWrapData{ + BlobKzgs: BlobKzgs{KZGCommitment{0xbb}}, + Blobs: Blobs{Blob{}}, + Proofs: KZGProofs{KZGProof{0xbc}}, + })), + }, } { if encode { b.Run(tc.name, func(b *testing.B) { diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 9a52616657b..0a0d0f617c9 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -28,8 +28,8 @@ import ( "github.com/ethereum/go-ethereum/crypto/blake2b" "github.com/ethereum/go-ethereum/crypto/bls12381" "github.com/ethereum/go-ethereum/crypto/bn256" + "github.com/ethereum/go-ethereum/crypto/kzg" "github.com/ethereum/go-ethereum/params" - big2 "github.com/holiman/big" "golang.org/x/crypto/ripemd160" ) @@ -105,11 +105,25 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{18}): &bls12381MapG2{}, } +var PrecompiledContractsDanksharding = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, + common.BytesToAddress([]byte{20}): &pointEvaluation{}, +} + var ( - PrecompiledAddressesBerlin []common.Address - PrecompiledAddressesIstanbul []common.Address - PrecompiledAddressesByzantium []common.Address - PrecompiledAddressesHomestead []common.Address + PrecompiledAddressesDanksharding []common.Address + PrecompiledAddressesBerlin []common.Address + PrecompiledAddressesIstanbul []common.Address + PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address ) func init() { @@ -125,11 +139,16 @@ func init() { for k := range PrecompiledContractsBerlin { PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) } + for k := range PrecompiledContractsDanksharding { + PrecompiledAddressesDanksharding = append(PrecompiledAddressesDanksharding, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { + case rules.IsCancun: + return PrecompiledAddressesDanksharding case rules.IsBerlin: return PrecompiledAddressesBerlin case rules.IsIstanbul: @@ -378,9 +397,9 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) { } // Retrieve the operands and execute the exponentiation var ( - base = new(big2.Int).SetBytes(getData(input, 0, baseLen)) - exp = new(big2.Int).SetBytes(getData(input, baseLen, expLen)) - mod = new(big2.Int).SetBytes(getData(input, baseLen+expLen, modLen)) + base = new(big.Int).SetBytes(getData(input, 0, baseLen)) + exp = new(big.Int).SetBytes(getData(input, baseLen, expLen)) + mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen)) v []byte ) switch { @@ -1049,3 +1068,16 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) { // Encode the G2 point to 256 bytes return g.EncodePoint(r), nil } + +// pointEvaluation implements the EIP-4844 point evaluation precompile +// to check if a value is part of a blob at a specific point with a KZG proof. +type pointEvaluation struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *pointEvaluation) RequiredGas(input []byte) uint64 { + return params.PointEvaluationGas +} + +func (c *pointEvaluation) Run(input []byte) ([]byte, error) { + return kzg.PointEvaluationPrecompile(input) +} diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index b22d999e6cd..b87ba1ce33d 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -65,6 +65,8 @@ var allPrecompiles = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{16}): &bls12381Pairing{}, common.BytesToAddress([]byte{17}): &bls12381MapG1{}, common.BytesToAddress([]byte{18}): &bls12381MapG2{}, + // TODO: this might change to 19 later. Avoiding precompile address changes / EIP collisions for now by keeping 20 (0x14). + common.BytesToAddress([]byte{20}): &pointEvaluation{}, } // EIP-152 test vectors @@ -391,3 +393,5 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) { } benchmarkPrecompiled("0f", testcase, b) } + +func TestPrecompiledPointEvaluation(t *testing.T) { testJson("pointEvaluation", "14", t) } diff --git a/core/vm/eips.go b/core/vm/eips.go index 29ff27c5526..e4d29a2eb99 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -235,6 +235,29 @@ func opPush0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by return nil, nil } +// enableSharding applies mini-danksharding (DATAHASH Opcode) +// - Adds an opcode that returns the versioned data hash of the tx at a index. +func enableSharding(jt *JumpTable) { + jt[DATAHASH] = &operation{ + execute: opDataHash, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + } +} + +// opDataHash implements DATAHASH opcode +func opDataHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + idx := scope.Stack.peek() + if idx.LtUint64(uint64(len(interpreter.evm.TxContext.DataHashes))) { + hash := interpreter.evm.TxContext.DataHashes[idx.Uint64()] + idx.SetBytes(hash.Bytes()) + } else { + idx.Clear() + } + return nil, nil +} + // ebnable3860 enables "EIP-3860: Limit and meter initcode" // https://eips.ethereum.org/EIPS/eip-3860 func enable3860(jt *JumpTable) { diff --git a/core/vm/evm.go b/core/vm/evm.go index d78ea079266..85d5a79acfc 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -43,6 +43,8 @@ type ( func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { var precompiles map[common.Address]PrecompiledContract switch { + case evm.chainRules.IsCancun: + precompiles = PrecompiledContractsDanksharding case evm.chainRules.IsBerlin: precompiles = PrecompiledContractsBerlin case evm.chainRules.IsIstanbul: @@ -68,21 +70,23 @@ type BlockContext struct { GetHash GetHashFunc // Block information - Coinbase common.Address // Provides information for COINBASE - GasLimit uint64 // Provides information for GASLIMIT - BlockNumber *big.Int // Provides information for NUMBER - Time uint64 // Provides information for TIME - Difficulty *big.Int // Provides information for DIFFICULTY - BaseFee *big.Int // Provides information for BASEFEE - Random *common.Hash // Provides information for PREVRANDAO + Coinbase common.Address // Provides information for COINBASE + GasLimit uint64 // Provides information for GASLIMIT + BlockNumber *big.Int // Provides information for NUMBER + Time uint64 // Provides information for TIME + Difficulty *big.Int // Provides information for DIFFICULTY + BaseFee *big.Int // Provides information for BASEFEE + Random *common.Hash // Provides information for PREVRANDAO + ExcessDataGas *big.Int // Provides information for EIP-4844 fee calculation } // TxContext provides the EVM with information about a transaction. // All fields can change between transactions. type TxContext struct { // Message information - Origin common.Address // Provides information for ORIGIN - GasPrice *big.Int // Provides information for GASPRICE + Origin common.Address // Provides information for ORIGIN + GasPrice *big.Int // Provides information for GASPRICE + DataHashes []common.Hash // Provides versioned data hashes for DATAHASH } // EVM is the Ethereum Virtual Machine base object and provides diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 65d46b3436d..4f961ef4db3 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -163,7 +163,7 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi return params.NetSstoreDirtyGas, nil } -// Here come the EIP220 rules: +// Here come the EIP2200 rules: // // (0.) If *gasleft* is less than or equal to 2300, fail the current call. // (1.) If current value equals new value (this is a no-op), SLOAD_GAS is deducted. diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index c3d06e515b1..6bb383e6316 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -90,6 +90,7 @@ func TestEIP2200(t *testing.T) { statedb.Finalise(true) // Push the state into the "original" slot vmctx := BlockContext{ + Time: 0, CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true }, Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, } diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 61f001a692c..e41a6982ef1 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -46,6 +46,9 @@ type twoOperandParams struct { var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" var commonParams []*twoOperandParams var twoOpMethods map[string]executionFunc +var emptyContext BlockContext = BlockContext{ + Time: 0, +} type contractRef struct { addr common.Address @@ -102,7 +105,7 @@ func init() { func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) evmInterpreter = env.interpreter @@ -201,7 +204,7 @@ func TestSAR(t *testing.T) { func TestAddMod(t *testing.T) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() evmInterpreter = NewEVMInterpreter(env) pc = uint64(0) @@ -245,7 +248,7 @@ func TestWriteExpectedValues(t *testing.T) { // getResult is a convenience function to generate the expected values getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) interpreter = env.interpreter @@ -290,7 +293,7 @@ func TestJsonTestcases(t *testing.T) { func opBenchmark(bench *testing.B, op executionFunc, args ...string) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() scope = &ScopeContext{nil, stack, nil} evmInterpreter = NewEVMInterpreter(env) @@ -531,7 +534,7 @@ func BenchmarkOpIsZero(b *testing.B) { func TestOpMstore(t *testing.T) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env) @@ -557,7 +560,7 @@ func TestOpMstore(t *testing.T) { func BenchmarkOpMstore(bench *testing.B) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env) @@ -580,7 +583,7 @@ func BenchmarkOpMstore(bench *testing.B) { func TestOpTstore(t *testing.T) { var ( statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, statedb, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env) @@ -622,7 +625,7 @@ func TestOpTstore(t *testing.T) { func BenchmarkOpKeccak256(bench *testing.B) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env) @@ -726,7 +729,7 @@ func TestRandom(t *testing.T) { {name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})}, } { var ( - env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(BlockContext{Random: &tt.random, Time: 0}, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) evmInterpreter = env.interpreter @@ -745,3 +748,44 @@ func TestRandom(t *testing.T) { } } } + +func TestDataHash(t *testing.T) { + type testcase struct { + name string + idx uint64 + expect common.Hash + hashes []common.Hash + } + var ( + zero = common.Hash{0} + one = common.Hash{1} + two = common.Hash{2} + three = common.Hash{3} + ) + for _, tt := range []testcase{ + {name: "[{1}]", idx: 0, expect: one, hashes: []common.Hash{one}}, + {name: "[1,{2},3]", idx: 2, expect: three, hashes: []common.Hash{one, two, three}}, + {name: "out-of-bounds (empty)", idx: 10, expect: zero, hashes: []common.Hash{}}, + {name: "out-of-bounds", idx: 25, expect: zero, hashes: []common.Hash{one, two, three}}, + } { + var ( + env = NewEVM(emptyContext, TxContext{DataHashes: tt.hashes}, nil, params.TestChainConfig, Config{}) + stack = newstack() + pc = uint64(0) + evmInterpreter = env.interpreter + ) + stack.push(uint256.NewInt(tt.idx)) + opDataHash(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) + if len(stack.data) != 1 { + t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data)) + } + actual := stack.pop() + expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes())) + if overflow { + t.Errorf("Testcase %v: invalid overflow", tt.name) + } + if actual.Cmp(expected) != 0 { + t.Errorf("Testcase %v: expected %x, got %x", tt.name, expected, actual) + } + } +} diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 0ab520b90f0..415a044f1af 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -57,6 +57,8 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { // If jump table was not initialised we set the default one. var table *JumpTable switch { + case evm.chainRules.IsCancun: + table = &shardingInstructionSet case evm.chainRules.IsShanghai: table = &shanghaiInstructionSet case evm.chainRules.IsMerge: diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index 31ee9922dba..70051af537b 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -38,6 +38,7 @@ var loopInterruptTests = []string{ func TestLoopInterrupt(t *testing.T) { address := common.BytesToAddress([]byte("contract")) vmctx := BlockContext{ + Time: 0, Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, } diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 91f1be669a4..ec8d04f0ce5 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -56,6 +56,7 @@ var ( londonInstructionSet = newLondonInstructionSet() mergeInstructionSet = newMergeInstructionSet() shanghaiInstructionSet = newShanghaiInstructionSet() + shardingInstructionSet = newShardingInstructionSet() ) // JumpTable contains the EVM opcodes supported at a given fork. @@ -79,6 +80,12 @@ func validate(jt JumpTable) JumpTable { return jt } +func newShardingInstructionSet() JumpTable { + instructionSet := newShanghaiInstructionSet() + enableSharding(&instructionSet) + return validate(instructionSet) +} + func newShanghaiInstructionSet() JumpTable { instructionSet := newMergeInstructionSet() enable3855(&instructionSet) // PUSH0 instruction @@ -98,7 +105,7 @@ func newMergeInstructionSet() JumpTable { } // newLondonInstructionSet returns the frontier, homestead, byzantium, -// contantinople, istanbul, petersburg, berlin and london instructions. +// constantinople, istanbul, petersburg, berlin and london instructions. func newLondonInstructionSet() JumpTable { instructionSet := newBerlinInstructionSet() enable3529(&instructionSet) // EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529 @@ -107,7 +114,7 @@ func newLondonInstructionSet() JumpTable { } // newBerlinInstructionSet returns the frontier, homestead, byzantium, -// contantinople, istanbul, petersburg and berlin instructions. +// constantinople, istanbul, petersburg and berlin instructions. func newBerlinInstructionSet() JumpTable { instructionSet := newIstanbulInstructionSet() enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929 @@ -115,7 +122,7 @@ func newBerlinInstructionSet() JumpTable { } // newIstanbulInstructionSet returns the frontier, homestead, byzantium, -// contantinople, istanbul and petersburg instructions. +// constantinople, istanbul and petersburg instructions. func newIstanbulInstructionSet() JumpTable { instructionSet := newConstantinopleInstructionSet() @@ -127,7 +134,7 @@ func newIstanbulInstructionSet() JumpTable { } // newConstantinopleInstructionSet returns the frontier, homestead, -// byzantium and contantinople instructions. +// byzantium and constantinople instructions. func newConstantinopleInstructionSet() JumpTable { instructionSet := newByzantiumInstructionSet() instructionSet[SHL] = &operation{ diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 9f199eb8f60..923b2d9e013 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -100,6 +100,7 @@ const ( CHAINID OpCode = 0x46 SELFBALANCE OpCode = 0x47 BASEFEE OpCode = 0x48 + DATAHASH OpCode = 0x49 ) // 0x50 range - 'storage' and execution. @@ -288,6 +289,7 @@ var opCodeToString = map[OpCode]string{ CHAINID: "CHAINID", SELFBALANCE: "SELFBALANCE", BASEFEE: "BASEFEE", + DATAHASH: "DATAHASH", // 0x50 range - 'storage' and execution. POP: "POP", @@ -443,6 +445,7 @@ var stringToOp = map[string]OpCode{ "CALLDATACOPY": CALLDATACOPY, "CHAINID": CHAINID, "BASEFEE": BASEFEE, + "DATAHASH": DATAHASH, "DELEGATECALL": DELEGATECALL, "STATICCALL": STATICCALL, "CODESIZE": CODESIZE, diff --git a/core/vm/testdata/precompiles/modexp.json b/core/vm/testdata/precompiles/modexp.json index 4550eb9138e..bfcb594609a 100644 --- a/core/vm/testdata/precompiles/modexp.json +++ b/core/vm/testdata/precompiles/modexp.json @@ -118,4 +118,4 @@ "Gas": 285900, "NoBenchmark": false } -] \ No newline at end of file +] diff --git a/core/vm/testdata/precompiles/pointEvaluation.json b/core/vm/testdata/precompiles/pointEvaluation.json new file mode 100644 index 00000000000..7215fde781d --- /dev/null +++ b/core/vm/testdata/precompiles/pointEvaluation.json @@ -0,0 +1,9 @@ +[ + { + "Input": "013c03613f6fc558fb7e61e75602241ed9a2f04e36d8670aadd286e71b5ca9cc420000000000000000000000000000000000000000000000000000000000000031e5a2356cbc2ef6a733eae8d54bf48719ae3d990017ca787c419c7d369f8e3c83fac17c3f237fc51f90e2c660eb202a438bc2025baded5cd193c1a018c5885bc9281ba704d5566082e851235c7be763b2a99adff965e0a121ee972ebc472d02944a74f5c6243e14052e105124b70bf65faf85ad3a494325e269fad097842cba", + "Expected": "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", + "Name": "pointEvaluation1", + "Gas": 50000, + "NoBenchmark": false + } +] diff --git a/crypto/kzg/kzg.go b/crypto/kzg/kzg.go new file mode 100644 index 00000000000..d5a97078264 --- /dev/null +++ b/crypto/kzg/kzg.go @@ -0,0 +1,111 @@ +package kzg + +import ( + "crypto/sha256" + "errors" + "fmt" + "math/big" + "sync" + + gokzg4844 "github.com/crate-crypto/go-kzg-4844" +) + +const ( + BlobCommitmentVersionKZG uint8 = 0x01 + FieldElementsPerBlob int = 4096 +) + +type VersionedHash [32]byte +type Root [32]byte +type Slot uint64 + +type BlobsSidecar struct { + BeaconBlockRoot Root + BeaconBlockSlot Slot + Blobs []gokzg4844.Blob + Proofs []gokzg4844.KZGProof +} + +const ( + PrecompileInputLength = 192 +) + +var ( + errInvalidInputLength = errors.New("invalid input length") +) + +// The value that gets returned when the `verify_kzg_proof“ precompile is called +var precompileReturnValue [64]byte + +var gCryptoCtx gokzg4844.Context +var initCryptoCtx sync.Once + +// InitializeCryptoCtx initializes the global context object returned via CryptoCtx +func InitializeCryptoCtx() { + initCryptoCtx.Do(func() { + // Initialize context to match the configurations that the + // specs are using. + ctx, err := gokzg4844.NewContext4096Insecure1337() + if err != nil { + panic(fmt.Sprintf("could not create context, err : %v", err)) + } + gCryptoCtx = *ctx + // Initialize the precompile return value + new(big.Int).SetUint64(gokzg4844.ScalarsPerBlob).FillBytes(precompileReturnValue[:32]) + copy(precompileReturnValue[32:], gokzg4844.BlsModulus[:]) + }) +} + +// CryptoCtx returns a context object stores all of the necessary configurations +// to allow one to create and verify blob proofs. +// This function is expensive to run if the crypto context isn't initialized, so it is recommended to +// pre-initialize by calling InitializeCryptoCtx +func CrpytoCtx() gokzg4844.Context { + InitializeCryptoCtx() + return gCryptoCtx +} + +// PointEvaluationPrecompile implements point_evaluation_precompile from EIP-4844 +func PointEvaluationPrecompile(input []byte) ([]byte, error) { + if len(input) != PrecompileInputLength { + return nil, errInvalidInputLength + } + // versioned hash: first 32 bytes + var versionedHash [32]byte + copy(versionedHash[:], input[:32]) + + var x, y gokzg4844.Scalar + // Evaluation point: next 32 bytes + copy(x[:], input[32:64]) + // Expected output: next 32 bytes + copy(y[:], input[64:96]) + + // input kzg point: next 48 bytes + var dataKZG [48]byte + copy(dataKZG[:], input[96:144]) + if KZGToVersionedHash(gokzg4844.KZGCommitment(dataKZG)) != VersionedHash(versionedHash) { + return nil, errors.New("mismatched versioned hash") + } + + // Quotient kzg: next 48 bytes + var quotientKZG gokzg4844.KZGProof + copy(quotientKZG[:], input[144:PrecompileInputLength]) + + cryptoCtx := CrpytoCtx() + err := cryptoCtx.VerifyKZGProof(dataKZG, x, y, quotientKZG) + if err != nil { + return nil, fmt.Errorf("verify_kzg_proof error: %v", err) + } + + result := precompileReturnValue // copy the value + + return result[:], nil +} + +// KZGToVersionedHash implements kzg_to_versioned_hash from EIP-4844 +func KZGToVersionedHash(kzg gokzg4844.KZGCommitment) VersionedHash { + h := sha256.Sum256(kzg[:]) + h[0] = BlobCommitmentVersionKZG + + return VersionedHash(h) +} diff --git a/crypto/signify/signify_test.go b/crypto/signify/signify_test.go index ba85d2fc433..9bac2c825f2 100644 --- a/crypto/signify/signify_test.go +++ b/crypto/signify/signify_test.go @@ -20,10 +20,9 @@ package signify import ( - "math/rand" + "crypto/rand" "os" "testing" - "time" "github.com/jedisct1/go-minisign" ) @@ -41,8 +40,6 @@ func TestSignify(t *testing.T) { defer os.Remove(tmpFile.Name()) defer tmpFile.Close() - rand.Seed(time.Now().UnixNano()) - data := make([]byte, 1024) rand.Read(data) tmpFile.Write(data) @@ -85,8 +82,6 @@ func TestSignifyTrustedCommentTooManyLines(t *testing.T) { defer os.Remove(tmpFile.Name()) defer tmpFile.Close() - rand.Seed(time.Now().UnixNano()) - data := make([]byte, 1024) rand.Read(data) tmpFile.Write(data) @@ -110,8 +105,6 @@ func TestSignifyTrustedCommentTooManyLinesLF(t *testing.T) { defer os.Remove(tmpFile.Name()) defer tmpFile.Close() - rand.Seed(time.Now().UnixNano()) - data := make([]byte, 1024) rand.Read(data) tmpFile.Write(data) @@ -135,8 +128,6 @@ func TestSignifyTrustedCommentEmpty(t *testing.T) { defer os.Remove(tmpFile.Name()) defer tmpFile.Close() - rand.Seed(time.Now().UnixNano()) - data := make([]byte, 1024) rand.Read(data) tmpFile.Write(data) diff --git a/eth/api.go b/eth/api.go index ceed85ef576..cd6510ccf9a 100644 --- a/eth/api.go +++ b/eth/api.go @@ -267,20 +267,24 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) { _, stateDb := api.eth.miner.Pending() return stateDb.RawDump(opts), nil } - var block *types.Block + var header *types.Header if blockNr == rpc.LatestBlockNumber { - block = api.eth.blockchain.CurrentBlock() + header = api.eth.blockchain.CurrentBlock() } else if blockNr == rpc.FinalizedBlockNumber { - block = api.eth.blockchain.CurrentFinalizedBlock() + header = api.eth.blockchain.CurrentFinalBlock() } else if blockNr == rpc.SafeBlockNumber { - block = api.eth.blockchain.CurrentSafeBlock() + header = api.eth.blockchain.CurrentSafeBlock() } else { - block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) + block := api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) + if block == nil { + return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) + } + header = block.Header() } - if block == nil { + if header == nil { return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) } - stateDb, err := api.eth.BlockChain().StateAt(block.Root()) + stateDb, err := api.eth.BlockChain().StateAt(header.Root) if err != nil { return state.Dump{}, err } @@ -347,20 +351,24 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex // the miner and operate on those _, stateDb = api.eth.miner.Pending() } else { - var block *types.Block + var header *types.Header if number == rpc.LatestBlockNumber { - block = api.eth.blockchain.CurrentBlock() + header = api.eth.blockchain.CurrentBlock() } else if number == rpc.FinalizedBlockNumber { - block = api.eth.blockchain.CurrentFinalizedBlock() + header = api.eth.blockchain.CurrentFinalBlock() } else if number == rpc.SafeBlockNumber { - block = api.eth.blockchain.CurrentSafeBlock() + header = api.eth.blockchain.CurrentSafeBlock() } else { - block = api.eth.blockchain.GetBlockByNumber(uint64(number)) + block := api.eth.blockchain.GetBlockByNumber(uint64(number)) + if block == nil { + return state.IteratorDump{}, fmt.Errorf("block #%d not found", number) + } + header = block.Header() } - if block == nil { + if header == nil { return state.IteratorDump{}, fmt.Errorf("block #%d not found", number) } - stateDb, err = api.eth.BlockChain().StateAt(block.Root()) + stateDb, err = api.eth.BlockChain().StateAt(header.Root) if err != nil { return state.IteratorDump{}, err } @@ -552,7 +560,7 @@ func (api *DebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error if block == nil { return 0, fmt.Errorf("current block missing") } - return block.NumberU64(), nil + return block.Number.Uint64(), nil } return uint64(num.Int64()), nil } diff --git a/eth/api_backend.go b/eth/api_backend.go index 8fd3e43300d..fd8a3334942 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -55,7 +55,7 @@ func (b *EthAPIBackend) ChainConfig() *params.ChainConfig { return b.eth.blockchain.Config() } -func (b *EthAPIBackend) CurrentBlock() *types.Block { +func (b *EthAPIBackend) CurrentBlock() *types.Header { return b.eth.blockchain.CurrentBlock() } @@ -72,19 +72,25 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb } // Otherwise resolve and return the block if number == rpc.LatestBlockNumber { - return b.eth.blockchain.CurrentBlock().Header(), nil + return b.eth.blockchain.CurrentBlock(), nil } if number == rpc.FinalizedBlockNumber { - block := b.eth.blockchain.CurrentFinalizedBlock() + if !b.eth.Merger().TDDReached() { + return nil, errors.New("'finalized' tag not supported on pre-merge network") + } + block := b.eth.blockchain.CurrentFinalBlock() if block != nil { - return block.Header(), nil + return block, nil } return nil, errors.New("finalized block not found") } if number == rpc.SafeBlockNumber { + if !b.eth.Merger().TDDReached() { + return nil, errors.New("'safe' tag not supported on pre-merge network") + } block := b.eth.blockchain.CurrentSafeBlock() if block != nil { - return block.Header(), nil + return block, nil } return nil, errors.New("safe block not found") } @@ -120,13 +126,22 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe } // Otherwise resolve and return the block if number == rpc.LatestBlockNumber { - return b.eth.blockchain.CurrentBlock(), nil + header := b.eth.blockchain.CurrentBlock() + return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil } if number == rpc.FinalizedBlockNumber { - return b.eth.blockchain.CurrentFinalizedBlock(), nil + if !b.eth.Merger().TDDReached() { + return nil, errors.New("'finalized' tag not supported on pre-merge network") + } + header := b.eth.blockchain.CurrentFinalBlock() + return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil } if number == rpc.SafeBlockNumber { - return b.eth.blockchain.CurrentSafeBlock(), nil + if !b.eth.Merger().TDDReached() { + return nil, errors.New("'safe' tag not supported on pre-merge network") + } + header := b.eth.blockchain.CurrentSafeBlock() + return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil } return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil } @@ -225,12 +240,20 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { if vmConfig == nil { vmConfig = b.eth.blockchain.GetVMConfig() } txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil) + var excessDataGas *big.Int + ph, err := b.HeaderByHash(ctx, header.ParentHash) + if err != nil { + return nil, state.Error, err + } + if ph != nil { + excessDataGas = ph.ExcessDataGas + } + context := core.NewEVMBlockContext(header, excessDataGas, b.eth.BlockChain(), nil) return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error, nil } @@ -379,6 +402,6 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re return b.eth.StateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) } -func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 00c4772185b..a67ad75ca7c 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -86,8 +86,10 @@ var caps = []string{ "engine_exchangeTransitionConfigurationV1", "engine_getPayloadV1", "engine_getPayloadV2", + "engine_getPayloadV3", "engine_newPayloadV1", "engine_newPayloadV2", + "engine_newPayloadV3", "engine_getPayloadBodiesByHashV1", "engine_getPayloadBodiesByRangeV1", } @@ -237,6 +239,10 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl log.Warn("Forkchoice requested unknown head", "hash", update.HeadBlockHash) return engine.STATUS_SYNCING, nil } + // If the finalized hash is known, we can direct the downloader to move + // potentially more data to the freezer from the get go. + finalized := api.remoteBlocks.get(update.FinalizedBlockHash) + // Header advertised via a past newPayload request. Start syncing to it. // Before we do however, make sure any legacy sync in switched off so we // don't accidentally have 2 cycles running. @@ -244,8 +250,16 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl merger.ReachTTD() api.eth.Downloader().Cancel() } - log.Info("Forkchoice requested sync to new head", "number", header.Number, "hash", header.Hash()) - if err := api.eth.Downloader().BeaconSync(api.eth.SyncMode(), header); err != nil { + context := []interface{}{"number", header.Number, "hash", header.Hash()} + if update.FinalizedBlockHash != (common.Hash{}) { + if finalized == nil { + context = append(context, []interface{}{"finalized", "unknown"}...) + } else { + context = append(context, []interface{}{"finalized", finalized.Number}...) + } + } + log.Info("Forkchoice requested sync to new head", context...) + if err := api.eth.Downloader().BeaconSync(api.eth.SyncMode(), header, finalized); err != nil { return engine.STATUS_SYNCING, err } return engine.STATUS_SYNCING, nil @@ -289,7 +303,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl } else { // If the head block is already in our canonical chain, the beacon client is // probably resyncing. Ignore the update. - log.Info("Ignoring beacon update to old head", "number", block.NumberU64(), "hash", update.HeadBlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)), "have", api.eth.BlockChain().CurrentBlock().NumberU64()) + log.Info("Ignoring beacon update to old head", "number", block.NumberU64(), "hash", update.HeadBlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)), "have", api.eth.BlockChain().CurrentBlock().Number) return valid(nil), nil } api.eth.SetSynced() @@ -310,7 +324,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not in canonical chain")) } // Set the finalized block - api.eth.BlockChain().SetFinalized(finalBlock) + api.eth.BlockChain().SetFinalized(finalBlock.Header()) } // Check if the safe block hash is in our canonical tree, if not somethings wrong if update.SafeBlockHash != (common.Hash{}) { @@ -324,7 +338,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain")) } // Set the safe block - api.eth.BlockChain().SetSafe(safeBlock) + api.eth.BlockChain().SetSafe(safeBlock.Header()) } // If payload generation was requested, create a new block to be potentially // sealed by the beacon client. The payload will be requested later, and we @@ -407,16 +421,34 @@ func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID) (*engine.Executi return data, nil } +// GetPayloadV3 returns a cached payload by id. +func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { + pl, err := api.localBlocks.getPayloadWithBlobsBundle(payloadID) + if err != nil { + return nil, err + } + if pl == nil { + return nil, engine.UnknownPayload + } + return pl, nil +} + // NewPayloadV1 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) { if params.Withdrawals != nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1")) } + if params.ExcessDataGas != nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("excessDataGas not supported in V1")) + } return api.newPayload(params) } // NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { + if params.ExcessDataGas != nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("excessDataGas not supported in V2")) + } if api.eth.BlockChain().Config().IsShanghai(params.Timestamp) { if params.Withdrawals == nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("nil withdrawals post-shanghai")) @@ -424,6 +456,20 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl } else if params.Withdrawals != nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("non-nil withdrawals pre-shanghai")) } + + return api.newPayload(params) +} + +// NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. +func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData) (engine.PayloadStatusV1, error) { + if api.eth.BlockChain().Config().IsCancun(params.Timestamp) { + if params.ExcessDataGas == nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("nil excessDataGas post-cancun")) + } + } else if params.ExcessDataGas != nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("non-nil excessDataGas pre-cancun")) + } + return api.newPayload(params) } @@ -448,7 +494,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa block, err := engine.ExecutableDataToBlock(params) if err != nil { log.Debug("Invalid NewPayload params", "params", params, "error", err) - return engine.PayloadStatusV1{Status: engine.INVALIDBLOCKHASH}, nil + return engine.PayloadStatusV1{Status: engine.INVALID}, nil } // Stash away the last update to warn the user if the beacon client goes offline api.lastNewPayloadLock.Lock() @@ -696,6 +742,8 @@ func (api *ConsensusAPI) heartbeat() { offlineLogged = time.Now() } continue + } else { + offlineLogged = time.Time{} } if time.Since(offlineLogged) > beaconUpdateWarnFrequency { if lastForkchoiceUpdate.IsZero() && lastNewPayloadUpdate.IsZero() { @@ -785,11 +833,14 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin // GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range // of block bodies by the engine api. func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV1, error) { - if start == 0 || count == 0 || count > 1024 { + if start == 0 || count == 0 { return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count)) } + if count > 1024 { + return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count)) + } // limit count up until current - current := api.eth.BlockChain().CurrentBlock().NumberU64() + current := api.eth.BlockChain().CurrentBlock().Number.Uint64() last := uint64(start) + uint64(count) - 1 if last > current { last = current diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index f7881415a43..8aa7406d85f 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -19,8 +19,11 @@ package catalyst import ( "bytes" "context" + crand "crypto/rand" "fmt" "math/big" + "math/rand" + "reflect" "sync" "testing" "time" @@ -41,9 +44,10 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" + "github.com/holiman/uint256" + "github.com/protolambda/ztyp/view" ) var ( @@ -89,7 +93,6 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) { } config.TerminalTotalDifficulty = totalDifficulty } - return genesis, blocks } @@ -248,8 +251,8 @@ func TestInvalidPayloadTimestamp(t *testing.T) { shouldErr bool }{ {0, true}, - {parent.Time(), true}, - {parent.Time() - 1, true}, + {parent.Time, true}, + {parent.Time - 1, true}, // TODO (MariusVanDerWijden) following tests are currently broken, // fixed in upcoming merge-kiln-v2 pr @@ -262,7 +265,7 @@ func TestInvalidPayloadTimestamp(t *testing.T) { params := engine.PayloadAttributes{ Timestamp: test.time, Random: crypto.Keccak256Hash([]byte{byte(123)}), - SuggestedFeeRecipient: parent.Coinbase(), + SuggestedFeeRecipient: parent.Coinbase, } fcState := engine.ForkchoiceStateV1{ HeadBlockHash: parent.Hash(), @@ -319,7 +322,7 @@ func TestEth2NewBlock(t *testing.T) { t.Fatalf("Failed to insert block: %v", err) case newResp.Status != "VALID": t.Fatalf("Failed to insert block: %v", newResp.Status) - case ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64()-1: + case ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64()-1: t.Fatalf("Chain head shouldn't be updated") } checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) @@ -331,7 +334,7 @@ func TestEth2NewBlock(t *testing.T) { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { t.Fatalf("Failed to insert block: %v", err) } - if have, want := ethservice.BlockChain().CurrentBlock().NumberU64(), block.NumberU64(); have != want { + if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want { t.Fatalf("Chain head should be updated, have %d want %d", have, want) } checkLogEvents(t, newLogCh, rmLogsCh, 1, 0) @@ -341,7 +344,7 @@ func TestEth2NewBlock(t *testing.T) { // Introduce fork chain var ( - head = ethservice.BlockChain().CurrentBlock().NumberU64() + head = ethservice.BlockChain().CurrentBlock().Number.Uint64() ) parent = preMergeBlocks[len(preMergeBlocks)-1] for i := 0; i < 10; i++ { @@ -359,7 +362,7 @@ func TestEth2NewBlock(t *testing.T) { if err != nil || newResp.Status != "VALID" { t.Fatalf("Failed to insert block: %v", err) } - if ethservice.BlockChain().CurrentBlock().NumberU64() != head { + if ethservice.BlockChain().CurrentBlock().Number.Uint64() != head { t.Fatalf("Chain head shouldn't be updated") } @@ -371,7 +374,7 @@ func TestEth2NewBlock(t *testing.T) { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { t.Fatalf("Failed to insert block: %v", err) } - if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64() { + if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64() { t.Fatalf("Chain head should be updated") } parent, head = block, block.NumberU64() @@ -389,7 +392,7 @@ func TestEth2DeepReorg(t *testing.T) { var ( api = NewConsensusAPI(ethservice, nil) parent = preMergeBlocks[len(preMergeBlocks)-core.TriesInMemory-1] - head = ethservice.BlockChain().CurrentBlock().NumberU64() + head = ethservice.BlockChain().CurrentBlock().Number.Uint64()() ) if ethservice.BlockChain().HasBlockAndState(parent.Hash(), parent.NumberU64()) { t.Errorf("Block %d not pruned", parent.NumberU64()) @@ -410,13 +413,13 @@ func TestEth2DeepReorg(t *testing.T) { if err != nil || newResp.Status != "VALID" { t.Fatalf("Failed to insert block: %v", err) } - if ethservice.BlockChain().CurrentBlock().NumberU64() != head { + if ethservice.BlockChain().CurrentBlock().Number.Uint64()() != head { t.Fatalf("Chain head shouldn't be updated") } if err := api.setHead(block.Hash()); err != nil { t.Fatalf("Failed to set head: %v", err) } - if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64() { + if ethservice.BlockChain().CurrentBlock().Number.Uint64()() != block.NumberU64() { t.Fatalf("Chain head should be updated") } parent, head = block, block.NumberU64() @@ -466,25 +469,28 @@ func TestFullAPI(t *testing.T) { logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") ) - callback := func(parent *types.Block) { - statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) + callback := func(parent *types.Header) { + statedb, _ := ethservice.BlockChain().StateAt(parent.Root) nonce := statedb.GetNonce(testAddr) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) ethservice.TxPool().AddLocal(tx) } - setupBlocks(t, ethservice, 10, parent, callback) + setupBlocks(t, ethservice, 10, parent, callback, nil) } -func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Block, callback func(parent *types.Block)) []*types.Block { +func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Header, callback func(parent *types.Header), withdrawals [][]*types.Withdrawal) []*types.Header { api := NewConsensusAPI(ethservice) - var blocks []*types.Block + var blocks []*types.Header for i := 0; i < n; i++ { callback(parent) + var w []*types.Withdrawal + if withdrawals != nil { + w = withdrawals[i] + } - payload := getNewPayload(t, api, parent) - - execResp, err := api.NewPayloadV1(*payload) + payload := getNewPayload(t, api, parent, w) + execResp, err := api.NewPayloadV2(*payload) if err != nil { t.Fatalf("can't execute payload: %v", err) } @@ -499,10 +505,10 @@ func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Bl if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { t.Fatalf("Failed to insert block: %v", err) } - if ethservice.BlockChain().CurrentBlock().NumberU64() != payload.Number { + if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { t.Fatal("Chain head should be updated") } - if ethservice.BlockChain().CurrentFinalizedBlock().NumberU64() != payload.Number-1 { + if ethservice.BlockChain().CurrentFinalBlock().Number.Uint64() != payload.Number-1 { t.Fatal("Finalized block should be updated") } parent = ethservice.BlockChain().CurrentBlock() @@ -557,8 +563,8 @@ func TestExchangeTransitionConfig(t *testing.T) { /* TestNewPayloadOnInvalidChain sets up a valid chain and tries to feed blocks -from an invalid chain to test if latestValidHash (LVH) works correctly. - +from an invalid chain to test if latestValidHash (LVH) works correctly +. We set up the following chain where P1 ... Pn and P1” are valid while P1' is invalid. We expect @@ -585,7 +591,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") ) for i := 0; i < 10; i++ { - statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) + statedb, _ := ethservice.BlockChain().StateAt(parent.Root) tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{ Nonce: statedb.GetNonce(testAddr), Value: new(big.Int), @@ -596,9 +602,9 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { ethservice.TxPool().AddRemotesSync([]*types.Transaction{tx}) var ( params = engine.PayloadAttributes{ - Timestamp: parent.Time() + 1, + Timestamp: parent.Time + 1, Random: crypto.Keccak256Hash([]byte{byte(i)}), - SuggestedFeeRecipient: parent.Coinbase(), + SuggestedFeeRecipient: parent.Coinbase, } fcState = engine.ForkchoiceStateV1{ HeadBlockHash: parent.Hash(), @@ -645,7 +651,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { t.Fatalf("Failed to insert block: %v", err) } - if ethservice.BlockChain().CurrentBlock().NumberU64() != payload.Number { + if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { t.Fatalf("Chain head should be updated") } parent = ethservice.BlockChain().CurrentBlock() @@ -676,10 +682,10 @@ func TestEmptyBlocks(t *testing.T) { api := NewConsensusAPI(ethservice) // Setup 10 blocks on the canonical chain - setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Block) {}) + setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil) // (1) check LatestValidHash by sending a normal payload (P1'') - payload := getNewPayload(t, api, commonAncestor) + payload := getNewPayload(t, api, commonAncestor, nil) status, err := api.NewPayloadV1(*payload) if err != nil { @@ -693,7 +699,7 @@ func TestEmptyBlocks(t *testing.T) { } // (2) Now send P1' which is invalid - payload = getNewPayload(t, api, commonAncestor) + payload = getNewPayload(t, api, commonAncestor, nil) payload.GasUsed += 1 payload = setBlockhash(payload) // Now latestValidHash should be the common ancestor @@ -711,7 +717,7 @@ func TestEmptyBlocks(t *testing.T) { } // (3) Now send a payload with unknown parent - payload = getNewPayload(t, api, commonAncestor) + payload = getNewPayload(t, api, commonAncestor, nil) payload.ParentHash = common.Hash{1} payload = setBlockhash(payload) // Now latestValidHash should be the common ancestor @@ -727,11 +733,12 @@ func TestEmptyBlocks(t *testing.T) { } } -func getNewPayload(t *testing.T, api *ConsensusAPI, parent *types.Block) *engine.ExecutableData { +func getNewPayload(t *testing.T, api *ConsensusAPI, parent *types.Header, withdrawals []*types.Withdrawal) *engine.ExecutableData { params := engine.PayloadAttributes{ - Timestamp: parent.Time() + 1, + Timestamp: parent.Time + 1, Random: crypto.Keccak256Hash([]byte{byte(1)}), - SuggestedFeeRecipient: parent.Coinbase(), + SuggestedFeeRecipient: parent.Coinbase, + Withdrawals: withdrawals, } payload, err := assembleBlock(api, parent.Hash(), ¶ms) @@ -748,21 +755,22 @@ func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData { number := big.NewInt(0) number.SetUint64(data.Number) header := &types.Header{ - ParentHash: data.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: data.FeeRecipient, - Root: data.StateRoot, - TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), - ReceiptHash: data.ReceiptsRoot, - Bloom: types.BytesToBloom(data.LogsBloom), - Difficulty: common.Big0, - Number: number, - GasLimit: data.GasLimit, - GasUsed: data.GasUsed, - Time: data.Timestamp, - BaseFee: data.BaseFeePerGas, - Extra: data.ExtraData, - MixDigest: data.Random, + ParentHash: data.ParentHash, + UncleHash: types.EmptyUncleHash, + Coinbase: data.FeeRecipient, + Root: data.StateRoot, + TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), + ReceiptHash: data.ReceiptsRoot, + Bloom: types.BytesToBloom(data.LogsBloom), + Difficulty: common.Big0, + Number: number, + GasLimit: data.GasLimit, + GasUsed: data.GasUsed, + Time: data.Timestamp, + BaseFee: data.BaseFeePerGas, + ExcessDataGas: data.ExcessDataGas, + Extra: data.ExtraData, + MixDigest: data.Random, } block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */) data.BlockHash = block.Hash() @@ -799,7 +807,7 @@ func TestTrickRemoteBlockCache(t *testing.T) { commonAncestor := ethserviceA.BlockChain().CurrentBlock() // Setup 10 blocks on the canonical chain - setupBlocks(t, ethserviceA, 10, commonAncestor, func(parent *types.Block) {}) + setupBlocks(t, ethserviceA, 10, commonAncestor, func(parent *types.Header) {}, nil) commonAncestor = ethserviceA.BlockChain().CurrentBlock() var invalidChain []*engine.ExecutableData @@ -808,7 +816,7 @@ func TestTrickRemoteBlockCache(t *testing.T) { //invalidChain = append(invalidChain, payload1) // create an invalid payload2 (P2) - payload2 := getNewPayload(t, apiA, commonAncestor) + payload2 := getNewPayload(t, apiA, commonAncestor, nil) //payload2.ParentHash = payload1.BlockHash payload2.GasUsed += 1 payload2 = setBlockhash(payload2) @@ -817,7 +825,7 @@ func TestTrickRemoteBlockCache(t *testing.T) { head := payload2 // create some valid payloads on top for i := 0; i < 10; i++ { - payload := getNewPayload(t, apiA, commonAncestor) + payload := getNewPayload(t, apiA, commonAncestor, nil) payload.ParentHash = head.BlockHash payload = setBlockhash(payload) invalidChain = append(invalidChain, payload) @@ -855,17 +863,17 @@ func TestInvalidBloom(t *testing.T) { api := NewConsensusAPI(ethservice) // Setup 10 blocks on the canonical chain - setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Block) {}) + setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil) // (1) check LatestValidHash by sending a normal payload (P1'') - payload := getNewPayload(t, api, commonAncestor) + payload := getNewPayload(t, api, commonAncestor, nil) payload.LogsBloom = append(payload.LogsBloom, byte(1)) status, err := api.NewPayloadV1(*payload) if err != nil { t.Fatal(err) } - if status.Status != engine.INVALIDBLOCKHASH { - t.Errorf("invalid status: expected VALID got: %v", status.Status) + if status.Status != engine.INVALID { + t.Errorf("invalid status: expected INVALID got: %v", status.Status) } } @@ -874,7 +882,7 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) { n, ethservice := startEthService(t, genesis, preMergeBlocks) defer n.Close() - genesis.Config.TerminalTotalDifficulty = preMergeBlocks[0].Difficulty() //.Sub(genesis.Config.TerminalTotalDifficulty, preMergeBlocks[len(preMergeBlocks)-1].Difficulty()) + ethservice.BlockChain().Config().TerminalTotalDifficulty = preMergeBlocks[0].Difficulty() //.Sub(genesis.Config.TerminalTotalDifficulty, preMergeBlocks[len(preMergeBlocks)-1].Difficulty()) var ( api = NewConsensusAPI(ethservice) @@ -966,7 +974,7 @@ func TestSimultaneousNewBlock(t *testing.T) { if err != nil { t.Fatalf("Failed to convert executable data to block %v", err) } - if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64()-1 { + if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64()-1 { t.Fatalf("Chain head shouldn't be updated") } fcState := engine.ForkchoiceStateV1{ @@ -997,7 +1005,7 @@ func TestSimultaneousNewBlock(t *testing.T) { t.Fatal(testErr) } } - if have, want := ethservice.BlockChain().CurrentBlock().NumberU64(), block.NumberU64(); have != want { + if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want { t.Fatalf("Chain head should be updated, have %d want %d", have, want) } parent = block @@ -1233,8 +1241,10 @@ func TestNilWithdrawals(t *testing.T) { } func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) + genesis, blocks := generateMergeChain(10, true) + n, ethservice := startEthService(t, genesis, blocks) + // enable shanghai on the last block + ethservice.BlockChain().Config().ShanghaiTime = &blocks[len(blocks)-1].Header().Time var ( parent = ethservice.BlockChain().CurrentBlock() @@ -1242,15 +1252,45 @@ func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) { logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") ) - callback := func(parent *types.Block) { - statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) + callback := func(parent *types.Header) { + statedb, _ := ethservice.BlockChain().StateAt(parent.Root) nonce := statedb.GetNonce(testAddr) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) ethservice.TxPool().AddLocal(tx) } - postMergeBlocks := setupBlocks(t, ethservice, 10, parent, callback) - return n, ethservice, append(preMergeBlocks, postMergeBlocks...) + withdrawals := make([][]*types.Withdrawal, 10) + withdrawals[0] = nil // should be filtered out by miner + withdrawals[1] = make([]*types.Withdrawal, 0) + for i := 2; i < len(withdrawals); i++ { + addr := make([]byte, 20) + crand.Read(addr) + withdrawals[i] = []*types.Withdrawal{ + {Index: rand.Uint64(), Validator: rand.Uint64(), Amount: rand.Uint64(), Address: common.BytesToAddress(addr)}, + } + } + + postShanghaiHeaders := setupBlocks(t, ethservice, 10, parent, callback, withdrawals) + postShanghaiBlocks := make([]*types.Block, len(postShanghaiHeaders)) + for i, header := range postShanghaiHeaders { + postShanghaiBlocks[i] = ethservice.BlockChain().GetBlock(header.Hash(), header.Number.Uint64()) + } + return n, ethservice, append(blocks, postShanghaiBlocks...) +} + +func allHashes(blocks []*types.Block) []common.Hash { + var hashes []common.Hash + for _, b := range blocks { + hashes = append(hashes, b.Hash()) + } + return hashes +} +func allBodies(blocks []*types.Block) []*types.Body { + var bodies []*types.Body + for _, b := range blocks { + bodies = append(bodies, b.Body()) + } + return bodies } func TestGetBlockBodiesByHash(t *testing.T) { @@ -1292,6 +1332,11 @@ func TestGetBlockBodiesByHash(t *testing.T) { results: []*types.Body{blocks[0].Body(), nil, blocks[0].Body(), blocks[0].Body()}, hashes: []common.Hash{blocks[0].Hash(), {1, 2}, blocks[0].Hash(), blocks[0].Hash()}, }, + // all blocks + { + results: allBodies(blocks), + hashes: allHashes(blocks), + }, } for k, test := range tests { @@ -1360,6 +1405,12 @@ func TestGetBlockBodiesByRange(t *testing.T) { start: 22, count: 2, }, + // allBlocks + { + results: allBodies(blocks), + start: 1, + count: hexutil.Uint64(len(blocks)), + }, } for k, test := range tests { @@ -1383,39 +1434,216 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) { node, eth, _ := setupBodies(t) api := NewConsensusAPI(eth) defer node.Close() - tests := []struct { start hexutil.Uint64 count hexutil.Uint64 + want *engine.EngineAPIError }{ // Genesis { start: 0, count: 1, + want: engine.InvalidParams, }, // No block requested { start: 1, count: 0, + want: engine.InvalidParams, }, // Genesis & no block { start: 0, count: 0, + want: engine.InvalidParams, }, // More than 1024 blocks { start: 1, count: 1025, + want: engine.TooLargeRequest, }, } - - for _, test := range tests { - result, err := api.GetPayloadBodiesByRangeV1(test.start, test.count) + for i, tc := range tests { + result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count) if err == nil { - t.Fatalf("expected error, got %v", result) + t.Fatalf("test %d: expected error, got %v", i, result) + } + if have, want := err.Error(), tc.want.Error(); have != want { + t.Fatalf("test %d: have %s, want %s", i, have, want) + } + } +} + +func TestEIP4844(t *testing.T) { + genesis, blocks := generateMergeChain(10, true) + lastBlockTime := blocks[len(blocks)-1].Time() + nextBlockTime := lastBlockTime + 10 // chainmakers block time is fixed at 10 seconds + genesis.Config.ShanghaiTime = &nextBlockTime + genesis.Config.CancunTime = &nextBlockTime + genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[0].Difficulty()) + + n, ethservice := startEthService(t, genesis, blocks) + ethservice.Merger().ReachTTD() + defer n.Close() + + api := NewConsensusAPI(ethservice) + + parent := ethservice.BlockChain().CurrentHeader() + params := engine.PayloadAttributes{ + Timestamp: parent.Time + 10, + Withdrawals: make([]*types.Withdrawal, 0), + } + fcState := engine.ForkchoiceStateV1{ + HeadBlockHash: parent.Hash(), + } + resp, err := api.ForkchoiceUpdatedV2(fcState, ¶ms) + if err != nil { + t.Fatalf("error preparing payload, err=%v", err) + } + if resp.PayloadStatus.Status != engine.VALID { + t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) + } + + execData, err := api.GetPayloadV3(*resp.PayloadID) + if err != nil { + t.Fatalf("error getting payload, err=%v", err) + } + ep := execData.ExecutionPayload + if ep.ExcessDataGas == nil { + t.Fatal("got nil ExcessDataGas") + } + if len(ep.Transactions) != 0 { + t.Fatal("expected zero transactions") + } + + if status, err := api.NewPayloadV3(*ep); err != nil { + t.Fatalf("error validating payload: %v", err) + } else if status.Status != engine.VALID { + t.Fatalf("invalid payload") + } + + fcState.HeadBlockHash = ep.BlockHash + _, err = api.ForkchoiceUpdatedV2(fcState, nil) + if err != nil { + t.Fatalf("error preparing payload, err=%v", err) + } + + block := ethservice.APIBackend.CurrentBlock() + if block.ExcessDataGas == nil { + t.Fatal("latest block is missing excessDataGas") + } +} + +func TestEIP4844WithBlobTransactions(t *testing.T) { + genesis, blocks := generateMergeChain(10, true) + lastBlockTime := blocks[len(blocks)-1].Time() + nextBlockTime := lastBlockTime + 10 // chainmakers block time is fixed at 10 seconds + genesis.Config.ShanghaiTime = &nextBlockTime + genesis.Config.CancunTime = &nextBlockTime + genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[0].Difficulty()) + + n, ethservice := startEthService(t, genesis, blocks) + ethservice.Merger().ReachTTD() + defer n.Close() + + api := NewConsensusAPI(ethservice) + + for i := 0; i < params.MaxBlobsPerBlock+5; i++ { + tx := newRandomBlobTx(t, ethservice.BlockChain(), 10+uint64(i)) + err := ethservice.TxPool().AddLocal(tx) + if err != nil { + t.Fatal(err) } } + + parent := ethservice.BlockChain().CurrentHeader() + params := engine.PayloadAttributes{ + Timestamp: parent.Time + 10, + Withdrawals: make([]*types.Withdrawal, 0), + } + fcState := engine.ForkchoiceStateV1{ + HeadBlockHash: parent.Hash(), + } + resp, err := api.ForkchoiceUpdatedV2(fcState, ¶ms) + if err != nil { + t.Fatalf("error preparing payload, err=%v", err) + } + if resp.PayloadStatus.Status != engine.VALID { + t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) + } + + ep, err := assembleWithTransactions(api, parent.Hash(), ¶ms, 4) + + if err != nil { + t.Fatalf("error getting payload, err=%v", err) + } + if ep.ExcessDataGas == nil { + t.Fatal("got nil ExcessDataGas") + } + if len(ep.Transactions) != 4 { + t.Fatalf("unexpected transactions. got %d", len(ep.Transactions)) + } + + if status, err := api.NewPayloadV3(*ep); err != nil { + t.Fatalf("error validating payload: %v", err) + } else if status.Status != engine.VALID { + t.Fatalf("invalid payload") + } + + fcState.HeadBlockHash = ep.BlockHash + _, err = api.ForkchoiceUpdatedV2(fcState, nil) + if err != nil { + t.Fatalf("error preparing payload, err=%v", err) + } + + block := ethservice.APIBackend.CurrentBlock() + if block.ExcessDataGas == nil { + t.Fatal("latest block is missing excessDataGas") + } +} + +func TestEIP4844Withdrawals(t *testing.T) { + genesis, blocks := generateMergeChain(10, true) + lastBlockTime := blocks[len(blocks)-1].Time() + nextBlockTime := lastBlockTime + 10 // chainmakers block time is fixed at 10 seconds + genesis.Config.ShanghaiTime = &nextBlockTime + genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[0].Difficulty()) + + n, ethservice := startEthService(t, genesis, blocks) + ethservice.Merger().ReachTTD() + defer n.Close() + + api := NewConsensusAPI(ethservice) + + // 10: Build Shanghai block with no withdrawals. + parent := ethservice.BlockChain().CurrentHeader() + params := engine.PayloadAttributes{ + Timestamp: parent.Time + 10, + Withdrawals: make([]*types.Withdrawal, 0), + } + fcState := engine.ForkchoiceStateV1{ + HeadBlockHash: parent.Hash(), + } + resp, err := api.ForkchoiceUpdatedV2(fcState, ¶ms) + if err != nil { + t.Fatalf("error preparing payload, err=%v", err) + } + if resp.PayloadStatus.Status != engine.VALID { + t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) + } + + execData, err := api.GetPayloadV2(*resp.PayloadID) + if err != nil { + t.Fatalf("error getting payload, err=%v", err) + } + ep := execData.ExecutionPayload + if ep.StateRoot != parent.Root { + t.Fatalf("mismatch state roots (got: %s, want: %s)", ep.StateRoot, blocks[8].Root()) + } + if ep.Withdrawals == nil || len(ep.Withdrawals) != 0 { + t.Fatalf("expected empty withdrawals list. got %#v", ep.Withdrawals) + } } func equalBody(a *types.Body, b *engine.ExecutionPayloadBodyV1) bool { @@ -1424,15 +1652,56 @@ func equalBody(a *types.Body, b *engine.ExecutionPayloadBodyV1) bool { } else if a == nil || b == nil { return false } - var want []hexutil.Bytes - for _, tx := range a.Transactions { + if len(a.Transactions) != len(b.TransactionData) { + return false + } + for i, tx := range a.Transactions { data, _ := tx.MarshalBinary() - want = append(want, hexutil.Bytes(data)) + if !bytes.Equal(data, b.TransactionData[i]) { + return false + } } - aBytes, errA := rlp.EncodeToBytes(want) - bBytes, errB := rlp.EncodeToBytes(b.TransactionData) - if errA != errB { - return false + return reflect.DeepEqual(a.Withdrawals, b.Withdrawals) +} + +func newRandomBlobTx(t *testing.T, chain *core.BlockChain, nonce uint64) *types.Transaction { + var blobs types.Blobs + blobs = append(blobs, types.Blob{}) + + commitments, versionedHashes, proofs, err := blobs.ComputeCommitmentsAndProofs() + if err != nil { + t.Fatal(err) + } + + chainID := chain.Config().ChainID + + recipient := common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a") + gasPrice := big.NewInt(1 * params.InitialBaseFee).Uint64() + txData := &types.SignedBlobTx{ + Message: types.BlobTxMessage{ + ChainID: view.Uint256View(*uint256.NewInt(chainID.Uint64())), + Nonce: view.Uint64View(nonce), + Gas: view.Uint64View(210000), + GasFeeCap: view.Uint256View(*uint256.NewInt(gasPrice)), + // fee per data gas needs to be higher than the minimum because this test produces more than one + // block and the latter one has non-zero excessDataGas + MaxFeePerDataGas: view.Uint256View(*uint256.NewInt(params.MinDataGasPrice * 2)), + GasTipCap: view.Uint256View(*uint256.NewInt(gasPrice)), + Value: view.Uint256View(*uint256.NewInt(1000)), + To: types.AddressOptionalSSZ{Address: (*types.AddressSSZ)(&recipient)}, + BlobVersionedHashes: versionedHashes, + }, + } + wrapData := &types.BlobTxWrapData{ + BlobKzgs: commitments, + Blobs: blobs, + Proofs: proofs, + } + tx := types.NewTx(txData, types.WithTxWrapData(wrapData)) + signer := types.NewDankSigner(chainID) + tx, err = types.SignTx(tx, signer, testKey) + if err != nil { + t.Fatal(err) } - return bytes.Equal(aBytes, bBytes) + return tx } diff --git a/eth/catalyst/queue.go b/eth/catalyst/queue.go index b7213dd591a..db55c500510 100644 --- a/eth/catalyst/queue.go +++ b/eth/catalyst/queue.go @@ -31,9 +31,12 @@ import ( const maxTrackedPayloads = 10 // maxTrackedHeaders is the maximum number of executed payloads the execution -// engine tracks before evicting old ones. Ideally we should only ever track the -// latest one; but have a slight wiggle room for non-ideal conditions. -const maxTrackedHeaders = 10 +// engine tracks before evicting old ones. These are tracked outside the chain +// during initial sync to allow ForkchoiceUpdate to reference past blocks via +// hashes only. For the sync target it would be enough to track only the latest +// header, but snap sync also needs the latest finalized height for the ancient +// limit. +const maxTrackedHeaders = 96 // payloadQueueItem represents an id->payload tuple to store until it's retrieved // or evicted. @@ -85,6 +88,23 @@ func (q *payloadQueue) get(id engine.PayloadID) *engine.ExecutionPayloadEnvelope return nil } +// get retrieves a previously stored payload along with its blobs bundle, or nil if it does not +// exist. +func (q *payloadQueue) getPayloadWithBlobsBundle(id engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { + q.lock.RLock() + defer q.lock.RUnlock() + + for _, item := range q.payloads { + if item == nil { + return nil, nil // no more items + } + if item.id == id { + return item.payload.ResolveWithBlobsBundle() + } + } + return nil, nil +} + // has checks if a particular payload is already tracked. func (q *payloadQueue) has(id engine.PayloadID) bool { q.lock.RLock() diff --git a/eth/catalyst/tester.go b/eth/catalyst/tester.go index 05511eaf7a2..c4eafd30d91 100644 --- a/eth/catalyst/tester.go +++ b/eth/catalyst/tester.go @@ -75,7 +75,7 @@ func (tester *FullSyncTester) Start() error { } // Trigger beacon sync with the provided block header as // trusted chain head. - err := tester.api.eth.Downloader().BeaconSync(downloader.FullSync, tester.block.Header()) + err := tester.api.eth.Downloader().BeaconSync(downloader.FullSync, tester.block.Header(), nil) if err != nil { log.Info("Failed to beacon sync", "err", err) } diff --git a/eth/downloader/beaconsync.go b/eth/downloader/beaconsync.go index 65d9225f8b5..ff985e6b035 100644 --- a/eth/downloader/beaconsync.go +++ b/eth/downloader/beaconsync.go @@ -76,7 +76,7 @@ func (b *beaconBackfiller) suspend() *types.Header { // Sync cycle was just terminated, retrieve and return the last filled header. // Can't use `filled` as that contains a stale value from before cancellation. - return b.downloader.blockchain.CurrentFastBlock().Header() + return b.downloader.blockchain.CurrentSnapBlock() } // resume starts the downloader threads for backfilling state and chain data. @@ -101,7 +101,7 @@ func (b *beaconBackfiller) resume() { defer func() { b.lock.Lock() b.filling = false - b.filled = b.downloader.blockchain.CurrentFastBlock().Header() + b.filled = b.downloader.blockchain.CurrentSnapBlock() b.lock.Unlock() }() // If the downloader fails, report an error as in beacon chain mode there @@ -151,8 +151,8 @@ func (d *Downloader) SetBadBlockCallback(onBadBlock badBlockFn) { // // Internally backfilling and state sync is done the same way, but the header // retrieval and scheduling is replaced. -func (d *Downloader) BeaconSync(mode SyncMode, head *types.Header) error { - return d.beaconSync(mode, head, true) +func (d *Downloader) BeaconSync(mode SyncMode, head *types.Header, final *types.Header) error { + return d.beaconSync(mode, head, final, true) } // BeaconExtend is an optimistic version of BeaconSync, where an attempt is made @@ -162,7 +162,7 @@ func (d *Downloader) BeaconSync(mode SyncMode, head *types.Header) error { // This is useful if a beacon client is feeding us large chunks of payloads to run, // but is not setting the head after each. func (d *Downloader) BeaconExtend(mode SyncMode, head *types.Header) error { - return d.beaconSync(mode, head, false) + return d.beaconSync(mode, head, nil, false) } // beaconSync is the post-merge version of the chain synchronization, where the @@ -171,7 +171,7 @@ func (d *Downloader) BeaconExtend(mode SyncMode, head *types.Header) error { // // Internally backfilling and state sync is done the same way, but the header // retrieval and scheduling is replaced. -func (d *Downloader) beaconSync(mode SyncMode, head *types.Header, force bool) error { +func (d *Downloader) beaconSync(mode SyncMode, head *types.Header, final *types.Header, force bool) error { // When the downloader starts a sync cycle, it needs to be aware of the sync // mode to use (full, snap). To keep the skeleton chain oblivious, inject the // mode into the backfiller directly. @@ -181,7 +181,7 @@ func (d *Downloader) beaconSync(mode SyncMode, head *types.Header, force bool) e d.skeleton.filler.(*beaconBackfiller).setMode(mode) // Signal the skeleton sync to switch to a new head, however it wants - if err := d.skeleton.Sync(head, force); err != nil { + if err := d.skeleton.Sync(head, final, force); err != nil { return err } return nil @@ -198,16 +198,16 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) { switch d.getMode() { case FullSync: - chainHead = d.blockchain.CurrentBlock().Header() + chainHead = d.blockchain.CurrentBlock() case SnapSync: - chainHead = d.blockchain.CurrentFastBlock().Header() + chainHead = d.blockchain.CurrentSnapBlock() default: chainHead = d.lightchain.CurrentHeader() } number := chainHead.Number.Uint64() // Retrieve the skeleton bounds and ensure they are linked to the local chain - beaconHead, beaconTail, err := d.skeleton.Bounds() + beaconHead, beaconTail, _, err := d.skeleton.Bounds() if err != nil { // This is a programming error. The chain backfiller was called with an // invalid beacon sync state. Ideally we would panic here, but erroring @@ -272,7 +272,7 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) { // until sync errors or is finished. func (d *Downloader) fetchBeaconHeaders(from uint64) error { var head *types.Header - _, tail, err := d.skeleton.Bounds() + _, tail, _, err := d.skeleton.Bounds() if err != nil { return err } @@ -292,7 +292,7 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error { for { // Some beacon headers might have appeared since the last cycle, make // sure we're always syncing to all available ones - head, _, err = d.skeleton.Bounds() + head, _, _, err = d.skeleton.Bounds() if err != nil { return err } diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index f7790b2d80f..fb9de79912e 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -154,6 +154,11 @@ type Downloader struct { bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations) + + // Progress reporting metrics + syncStartBlock uint64 // Head snap block when Geth was started + syncStartTime time.Time // Time instance when chain sync started + syncLogTime time.Time // Time instance when status was last reported } // LightChain encapsulates functions required to synchronise a light chain. @@ -191,10 +196,10 @@ type BlockChain interface { GetBlockByHash(common.Hash) *types.Block // CurrentBlock retrieves the head block from the local chain. - CurrentBlock() *types.Block + CurrentBlock() *types.Header - // CurrentFastBlock retrieves the head snap block from the local chain. - CurrentFastBlock() *types.Block + // CurrentSnapBlock retrieves the head snap block from the local chain. + CurrentSnapBlock() *types.Header // SnapSyncCommitHead directly commits the head block to a certain entity. SnapSyncCommitHead(common.Hash) error @@ -231,7 +236,9 @@ func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain Bl quitCh: make(chan struct{}), SnapSyncer: snap.NewSyncer(stateDb, chain.TrieDB().Scheme()), stateSyncStart: make(chan *stateSync), + syncStartBlock: chain.CurrentSnapBlock().Number.Uint64(), } + // Create the post-merge skeleton syncer and start the process dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success)) go dl.stateFetcher() @@ -254,9 +261,9 @@ func (d *Downloader) Progress() ethereum.SyncProgress { mode := d.getMode() switch { case d.blockchain != nil && mode == FullSync: - current = d.blockchain.CurrentBlock().NumberU64() + current = d.blockchain.CurrentBlock().Number.Uint64() case d.blockchain != nil && mode == SnapSync: - current = d.blockchain.CurrentFastBlock().NumberU64() + current = d.blockchain.CurrentSnapBlock().Number.Uint64() case d.lightchain != nil: current = d.lightchain.CurrentHeader().Number.Uint64() default: @@ -473,7 +480,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * }(time.Now()) // Look up the sync boundaries: the common ancestor and the target block - var latest, pivot *types.Header + var latest, pivot, final *types.Header if !beaconMode { // In legacy mode, use the master peer to retrieve the headers from latest, pivot, err = d.fetchHead(p) @@ -482,7 +489,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * } } else { // In beacon mode, use the skeleton chain to retrieve the headers from - latest, _, err = d.skeleton.Bounds() + latest, _, final, err = d.skeleton.Bounds() if err != nil { return err } @@ -492,7 +499,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * // Retrieve the pivot header from the skeleton chain segment but // fallback to local chain if it's not found in skeleton space. if pivot = d.skeleton.Header(number); pivot == nil { - _, oldest, _ := d.skeleton.Bounds() // error is already checked + _, oldest, _, _ := d.skeleton.Bounds() // error is already checked if number < oldest.Number.Uint64() { count := int(oldest.Number.Uint64() - number) // it's capped by fsMinFullBlocks headers := d.readHeaderRange(oldest, count) @@ -516,7 +523,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * // anyway, but still need a valid pivot block to avoid some code hitting // nil panics on access. if mode == SnapSync && pivot == nil { - pivot = d.blockchain.CurrentBlock().Header() + pivot = d.blockchain.CurrentBlock() } height := latest.Number.Uint64() @@ -560,26 +567,41 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * d.committed = 0 } if mode == SnapSync { - // Set the ancient data limitation. - // If we are running snap sync, all block data older than ancientLimit will be - // written to the ancient store. More recent data will be written to the active - // database and will wait for the freezer to migrate. + // Set the ancient data limitation. If we are running snap sync, all block + // data older than ancientLimit will be written to the ancient store. More + // recent data will be written to the active database and will wait for the + // freezer to migrate. // - // If there is a checkpoint available, then calculate the ancientLimit through - // that. Otherwise calculate the ancient limit through the advertised height - // of the remote peer. + // If the network is post-merge, use either the last announced finalized + // block as the ancient limit, or if we haven't yet received one, the head- + // a max fork ancestry limit. One quirky case if we've already passed the + // finalized block, in which case the skeleton.Bounds will return nil and + // we'll revert to head - 90K. That's fine, we're finishing sync anyway. // - // The reason for picking checkpoint first is that a malicious peer can give us - // a fake (very high) height, forcing the ancient limit to also be very high. - // The peer would start to feed us valid blocks until head, resulting in all of - // the blocks might be written into the ancient store. A following mini-reorg - // could cause issues. - if d.checkpoint != 0 && d.checkpoint > fullMaxForkAncestry+1 { - d.ancientLimit = d.checkpoint - } else if height > fullMaxForkAncestry+1 { - d.ancientLimit = height - fullMaxForkAncestry - 1 + // For non-merged networks, if there is a checkpoint available, then calculate + // the ancientLimit through that. Otherwise calculate the ancient limit through + // the advertised height of the remote peer. This most is mostly a fallback for + // legacy networks, but should eventually be droppped. TODO(karalabe). + if beaconMode { + // Beacon sync, use the latest finalized block as the ancient limit + // or a reasonable height if no finalized block is yet announced. + if final != nil { + d.ancientLimit = final.Number.Uint64() + } else if height > fullMaxForkAncestry+1 { + d.ancientLimit = height - fullMaxForkAncestry - 1 + } else { + d.ancientLimit = 0 + } } else { - d.ancientLimit = 0 + // Legacy sync, use any hardcoded checkpoints or the best announcement + // we have from the remote peer. TODO(karalabe): Drop this pathway. + if d.checkpoint != 0 && d.checkpoint > fullMaxForkAncestry+1 { + d.ancientLimit = d.checkpoint + } else if height > fullMaxForkAncestry+1 { + d.ancientLimit = height - fullMaxForkAncestry - 1 + } else { + d.ancientLimit = 0 + } } frozen, _ := d.stateDB.Ancients() // Ignore the error here since light client can also hit here. @@ -812,9 +834,9 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) mode := d.getMode() switch mode { case FullSync: - localHeight = d.blockchain.CurrentBlock().NumberU64() + localHeight = d.blockchain.CurrentBlock().Number.Uint64() case SnapSync: - localHeight = d.blockchain.CurrentFastBlock().NumberU64() + localHeight = d.blockchain.CurrentSnapBlock().Number.Uint64() default: localHeight = d.lightchain.CurrentHeader().Number.Uint64() } @@ -1152,8 +1174,8 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) e if mode == LightSync { head = d.lightchain.CurrentHeader().Number.Uint64() } else { - head = d.blockchain.CurrentFastBlock().NumberU64() - if full := d.blockchain.CurrentBlock().NumberU64(); head < full { + head = d.blockchain.CurrentSnapBlock().Number.Uint64() + if full := d.blockchain.CurrentBlock().Number.Uint64(); head < full { head = full } } @@ -1267,8 +1289,8 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode if rollback > 0 { lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0 if mode != LightSync { - lastFastBlock = d.blockchain.CurrentFastBlock().Number() - lastBlock = d.blockchain.CurrentBlock().Number() + lastFastBlock = d.blockchain.CurrentSnapBlock().Number + lastBlock = d.blockchain.CurrentBlock().Number } if err := d.lightchain.SetHead(rollback - 1); err != nil { // -1 to target the parent of the first uncertain block // We're already unwinding the stack, only print the error to make it more visible @@ -1276,8 +1298,8 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode } curFastBlock, curBlock := common.Big0, common.Big0 if mode != LightSync { - curFastBlock = d.blockchain.CurrentFastBlock().Number() - curBlock = d.blockchain.CurrentBlock().Number() + curFastBlock = d.blockchain.CurrentSnapBlock().Number + curBlock = d.blockchain.CurrentBlock().Number } log.Warn("Rolled back chain segment", "header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number), @@ -1322,7 +1344,7 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode // R: Nothing to give if mode != LightSync { head := d.blockchain.CurrentBlock() - if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 { + if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 { return errStallingPeer } } @@ -1559,7 +1581,7 @@ func (d *Downloader) importBlockResults(results []*fetchResult) error { // In post-merge, notify the engine API of encountered bad chains if d.badBlock != nil { - head, _, err := d.skeleton.Bounds() + head, _, _, err := d.skeleton.Bounds() if err != nil { log.Error("Failed to retrieve beacon bounds for bad block reporting", "err", err) } else { @@ -1614,6 +1636,7 @@ func (d *Downloader) processSnapSyncContent() error { if len(results) == 0 { // If pivot sync is done, stop if oldPivot == nil { + d.reportSnapSyncProgress(true) return sync.Cancel() } // If sync failed, stop @@ -1627,6 +1650,8 @@ func (d *Downloader) processSnapSyncContent() error { if d.chainInsertHook != nil { d.chainInsertHook(results) } + d.reportSnapSyncProgress(false) + // If we haven't downloaded the pivot block yet, check pivot staleness // notifications from the header downloader d.pivotLock.RLock() @@ -1739,7 +1764,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state } default: } - // Retrieve the a batch of results to import + // Retrieve the batch of results to import first, last := results[0].Header, results[len(results)-1].Header log.Debug("Inserting snap-sync blocks", "items", len(results), "firstnum", first.Number, "firsthash", first.Hash(), @@ -1820,3 +1845,56 @@ func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Hea } return headers } + +// reportSnapSyncProgress calculates various status reports and provides it to the user. +func (d *Downloader) reportSnapSyncProgress(force bool) { + // Initialize the sync start time if it's the first time we're reporting + if d.syncStartTime.IsZero() { + d.syncStartTime = time.Now().Add(-time.Millisecond) // -1ms offset to avoid division by zero + } + // Don't report all the events, just occasionally + if !force && time.Since(d.syncLogTime) < 8*time.Second { + return + } + // Don't report anything until we have a meaningful progress + var ( + headerBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerHeaderTable) + bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable) + receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable) + ) + syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes) + if syncedBytes == 0 { + return + } + var ( + header = d.blockchain.CurrentHeader() + block = d.blockchain.CurrentSnapBlock() + ) + syncedBlocks := block.Number.Uint64() - d.syncStartBlock + if syncedBlocks == 0 { + return + } + // Retrieve the current chain head and calculate the ETA + latest, _, _, err := d.skeleton.Bounds() + if err != nil { + // We're going to cheat for non-merged networks, but that's fine + latest = d.pivotHeader + } + if latest == nil { + // This should really never happen, but add some defensive code for now. + // TODO(karalabe): Remove it eventually if we don't see it blow. + log.Error("Nil latest block in sync progress report") + return + } + var ( + left = latest.Number.Uint64() - block.Number.Uint64() + eta = time.Since(d.syncStartTime) / time.Duration(syncedBlocks) * time.Duration(left) + + progress = fmt.Sprintf("%.2f%%", float64(block.Number.Uint64())*100/float64(latest.Number.Uint64())) + headers = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(header.Number.Uint64()), common.StorageSize(headerBytes).TerminalString()) + bodies = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(bodyBytes).TerminalString()) + receipts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(receiptBytes).TerminalString()) + ) + log.Info("Syncing: chain download in progress", "synced", progress, "chain", syncedBytes, "headers", headers, "bodies", bodies, "receipts", receipts, "eta", common.PrettyDuration(eta)) + d.syncLogTime = time.Now() +} diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 2f0c4acf788..a884c1e950b 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -100,7 +100,7 @@ func (dl *downloadTester) sync(id string, td *big.Int, mode SyncMode) error { head := dl.peers[id].chain.CurrentBlock() if td == nil { // If no particular TD was requested, load from the peer's blockchain - td = dl.peers[id].chain.GetTd(head.Hash(), head.NumberU64()) + td = dl.peers[id].chain.GetTd(head.Hash(), head.Number.Uint64()) } // Synchronise with the chosen peer and ensure proper cleanup afterwards err := dl.downloader.synchronise(id, head.Hash(), td, nil, mode, false, nil) @@ -158,7 +158,7 @@ type downloadTesterPeer struct { // and total difficulty. func (dlp *downloadTesterPeer) Head() (common.Hash, *big.Int) { head := dlp.chain.CurrentBlock() - return head.Hash(), dlp.chain.GetTd(head.Hash(), head.NumberU64()) + return head.Hash(), dlp.chain.GetTd(head.Hash(), head.Number.Uint64()) } func unmarshalRlpHeaders(rlpdata []rlp.RawValue) []*types.Header { @@ -430,10 +430,10 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) { if hs := int(tester.chain.CurrentHeader().Number.Uint64()) + 1; hs != headers { t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers) } - if bs := int(tester.chain.CurrentBlock().NumberU64()) + 1; bs != blocks { + if bs := int(tester.chain.CurrentBlock().Number.Uint64()) + 1; bs != blocks { t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, blocks) } - if rs := int(tester.chain.CurrentFastBlock().NumberU64()) + 1; rs != receipts { + if rs := int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1; rs != receipts { t.Fatalf("synchronised receipts mismatch: have %v, want %v", rs, receipts) } } @@ -490,7 +490,7 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) { for { // Check the retrieval count synchronously (! reason for this ugly block) tester.lock.RLock() - retrieved := int(tester.chain.CurrentFastBlock().Number().Uint64()) + 1 + retrieved := int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1 tester.lock.RUnlock() if retrieved >= targetBlocks+1 { break @@ -506,7 +506,7 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) { { cached = tester.downloader.queue.resultCache.countCompleted() frozen = int(atomic.LoadUint32(&blocked)) - retrieved = int(tester.chain.CurrentFastBlock().Number().Uint64()) + 1 + retrieved = int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1 } tester.downloader.queue.resultCache.lock.Unlock() tester.downloader.queue.lock.Unlock() @@ -522,7 +522,7 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) { // Make sure we filled up the cache, then exhaust it time.Sleep(25 * time.Millisecond) // give it a chance to screw up tester.lock.RLock() - retrieved = int(tester.chain.CurrentFastBlock().Number().Uint64()) + 1 + retrieved = int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1 tester.lock.RUnlock() if cached != blockCacheMaxItems && cached != blockCacheMaxItems-reorgProtHeaderDelay && retrieved+cached+frozen != targetBlocks+1 && retrieved+cached+frozen != targetBlocks+1-reorgProtHeaderDelay { t.Fatalf("block count mismatch: have %v, want %v (owned %v, blocked %v, target %v)", cached, blockCacheMaxItems, retrieved, frozen, targetBlocks+1) @@ -921,7 +921,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol uint, mode SyncMode) { t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch) } if mode == SnapSync { - if head := tester.chain.CurrentBlock().NumberU64(); head != 0 { + if head := tester.chain.CurrentBlock().Number.Uint64(); head != 0 { t.Errorf("fast sync pivot block #%d not rolled back", head) } } @@ -943,7 +943,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol uint, mode SyncMode) { t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch) } if mode == SnapSync { - if head := tester.chain.CurrentBlock().NumberU64(); head != 0 { + if head := tester.chain.CurrentBlock().Number.Uint64(); head != 0 { t.Errorf("fast sync pivot block #%d not rolled back", head) } } @@ -1478,13 +1478,13 @@ func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) { if c.local > 0 { tester.chain.InsertChain(chain.blocks[1 : c.local+1]) } - if err := tester.downloader.BeaconSync(mode, chain.blocks[len(chain.blocks)-1].Header()); err != nil { + if err := tester.downloader.BeaconSync(mode, chain.blocks[len(chain.blocks)-1].Header(), nil); err != nil { t.Fatalf("Failed to beacon sync chain %v %v", c.name, err) } select { case <-success: // Ok, downloader fully cancelled after sync cycle - if bs := int(tester.chain.CurrentBlock().NumberU64()) + 1; bs != len(chain.blocks) { + if bs := int(tester.chain.CurrentBlock().Number.Uint64()) + 1; bs != len(chain.blocks) { t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, len(chain.blocks)) } case <-time.NewTimer(time.Second * 3).C: diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go index b90f417ea44..5af5068c98c 100644 --- a/eth/downloader/queue.go +++ b/eth/downloader/queue.go @@ -76,6 +76,8 @@ func newFetchResult(header *types.Header, fastSync bool) *fetchResult { } if !header.EmptyBody() { item.pending |= (1 << bodyType) + } else if header.WithdrawalsHash != nil { + item.Withdrawals = make(types.Withdrawals, 0) } if fastSync && !header.EmptyReceipts() { item.pending |= (1 << receiptType) @@ -142,7 +144,7 @@ type queue struct { active *sync.Cond closed bool - lastStatLog time.Time + logTime time.Time // Time instance when status was last reported } // newQueue creates a new download queue for scheduling block retrieval. @@ -388,11 +390,12 @@ func (q *queue) Results(block bool) []*fetchResult { } } // Log some info at certain times - if time.Since(q.lastStatLog) > 60*time.Second { - q.lastStatLog = time.Now() + if time.Since(q.logTime) >= 60*time.Second { + q.logTime = time.Now() + info := q.Stats() info = append(info, "throttle", throttleThreshold) - log.Info("Downloader queue stats", info...) + log.Debug("Downloader queue stats", info...) } return results } @@ -781,14 +784,17 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH return errInvalidBody } if header.WithdrawalsHash == nil { - // discard any withdrawals if we don't have a withdrawal hash set - withdrawalLists[index] = nil - } else if *header.WithdrawalsHash == types.EmptyRootHash && withdrawalLists[index] == nil { - // if the withdrawal hash is the emptyRootHash, - // we expect withdrawals to be [] instead of nil - withdrawalLists[index] = make([]*types.Withdrawal, 0) - } else if withdrawalListHashes[index] != *header.WithdrawalsHash { - return errInvalidBody + // nil hash means that withdrawals should not be present in body + if withdrawalLists[index] != nil { + return errInvalidBody + } + } else { // non-nil hash: body must have withdrawals + if withdrawalLists[index] == nil { + return errInvalidBody + } + if withdrawalListHashes[index] != *header.WithdrawalsHash { + return errInvalidBody + } } return nil } diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go index 6babf944086..a8b1b45e006 100644 --- a/eth/downloader/queue_test.go +++ b/eth/downloader/queue_test.go @@ -42,7 +42,7 @@ func makeChain(n int, seed byte, parent *types.Block, empty bool) ([]*types.Bloc block.SetCoinbase(common.Address{seed}) // Add one tx to every secondblock if !empty && i%2 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/eth/downloader/skeleton.go b/eth/downloader/skeleton.go index 142e9e5e6bc..12eb5700f8d 100644 --- a/eth/downloader/skeleton.go +++ b/eth/downloader/skeleton.go @@ -102,6 +102,7 @@ type subchain struct { // suspended skeleton sync without prior knowledge of all prior suspension points. type skeletonProgress struct { Subchains []*subchain // Disjoint subchains downloaded until now + Finalized *uint64 // Last known finalized block number } // headUpdate is a notification that the beacon sync should switch to a new target. @@ -109,6 +110,7 @@ type skeletonProgress struct { // extend it and fail if it's not possible. type headUpdate struct { header *types.Header // Header to update the sync target to + final *types.Header // Finalized header to use as thresholds force bool // Whether to force the update or only extend if possible errc chan error // Channel to signal acceptance of the new head } @@ -321,12 +323,12 @@ func (s *skeleton) Terminate() error { // // This method does not block, rather it just waits until the syncer receives the // fed header. What the syncer does with it is the syncer's problem. -func (s *skeleton) Sync(head *types.Header, force bool) error { +func (s *skeleton) Sync(head *types.Header, final *types.Header, force bool) error { log.Trace("New skeleton head announced", "number", head.Number, "hash", head.Hash(), "force", force) errc := make(chan error) select { - case s.headEvents <- &headUpdate{header: head, force: force, errc: errc}: + case s.headEvents <- &headUpdate{header: head, final: final, force: force, errc: errc}: return <-errc case <-s.terminated: return errTerminated @@ -437,7 +439,7 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) { // we don't seamlessly integrate reorgs to keep things simple. If the // network starts doing many mini reorgs, it might be worthwhile handling // a limited depth without an error. - if reorged := s.processNewHead(event.header, event.force); reorged { + if reorged := s.processNewHead(event.header, event.final, event.force); reorged { // If a reorg is needed, and we're forcing the new head, signal // the syncer to tear down and start over. Otherwise, drop the // non-force reorg. @@ -590,7 +592,17 @@ func (s *skeleton) saveSyncStatus(db ethdb.KeyValueWriter) { // accepts and integrates it into the skeleton or requests a reorg. Upon reorg, // the syncer will tear itself down and restart with a fresh head. It is simpler // to reconstruct the sync state than to mutate it and hope for the best. -func (s *skeleton) processNewHead(head *types.Header, force bool) bool { +func (s *skeleton) processNewHead(head *types.Header, final *types.Header, force bool) bool { + // If a new finalized block was announced, update the sync process independent + // of what happens with the sync head below + if final != nil { + if number := final.Number.Uint64(); s.progress.Finalized == nil || *s.progress.Finalized != number { + s.progress.Finalized = new(uint64) + *s.progress.Finalized = final.Number.Uint64() + + s.saveSyncStatus(s.db) + } + } // If the header cannot be inserted without interruption, return an error for // the outer loop to tear down the skeleton sync and restart it number := head.Number.Uint64() @@ -1150,9 +1162,10 @@ func (s *skeleton) cleanStales(filled *types.Header) error { return nil } -// Bounds retrieves the current head and tail tracked by the skeleton syncer. -// This method is used by the backfiller, whose life cycle is controlled by the -// skeleton syncer. +// Bounds retrieves the current head and tail tracked by the skeleton syncer +// and optionally the last known finalized header if any was announced and if +// it is still in the sync range. This method is used by the backfiller, whose +// life cycle is controlled by the skeleton syncer. // // Note, the method will not use the internal state of the skeleton, but will // rather blindly pull stuff from the database. This is fine, because the back- @@ -1160,28 +1173,34 @@ func (s *skeleton) cleanStales(filled *types.Header) error { // There might be new heads appended, but those are atomic from the perspective // of this method. Any head reorg will first tear down the backfiller and only // then make the modification. -func (s *skeleton) Bounds() (head *types.Header, tail *types.Header, err error) { +func (s *skeleton) Bounds() (head *types.Header, tail *types.Header, final *types.Header, err error) { // Read the current sync progress from disk and figure out the current head. // Although there's a lot of error handling here, these are mostly as sanity // checks to avoid crashing if a programming error happens. These should not // happen in live code. status := rawdb.ReadSkeletonSyncStatus(s.db) if len(status) == 0 { - return nil, nil, errors.New("beacon sync not yet started") + return nil, nil, nil, errors.New("beacon sync not yet started") } progress := new(skeletonProgress) if err := json.Unmarshal(status, progress); err != nil { - return nil, nil, err + return nil, nil, nil, err } head = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Head) if head == nil { - return nil, nil, fmt.Errorf("head skeleton header %d is missing", progress.Subchains[0].Head) + return nil, nil, nil, fmt.Errorf("head skeleton header %d is missing", progress.Subchains[0].Head) } tail = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Tail) if tail == nil { - return nil, nil, fmt.Errorf("tail skeleton header %d is missing", progress.Subchains[0].Tail) + return nil, nil, nil, fmt.Errorf("tail skeleton header %d is missing", progress.Subchains[0].Tail) + } + if progress.Finalized != nil && tail.Number.Uint64() <= *progress.Finalized && *progress.Finalized <= head.Number.Uint64() { + final = rawdb.ReadSkeletonHeader(s.db, *progress.Finalized) + if final == nil { + return nil, nil, nil, fmt.Errorf("finalized skeleton header %d is missing", *progress.Finalized) + } } - return head, tail, nil + return head, tail, final, nil } // Header retrieves a specific header tracked by the skeleton syncer. This method diff --git a/eth/downloader/skeleton_test.go b/eth/downloader/skeleton_test.go index 3b8e627cba8..b19494a7b06 100644 --- a/eth/downloader/skeleton_test.go +++ b/eth/downloader/skeleton_test.go @@ -370,7 +370,7 @@ func TestSkeletonSyncInit(t *testing.T) { skeleton := newSkeleton(db, newPeerSet(), nil, newHookedBackfiller()) skeleton.syncStarting = func() { close(wait) } - skeleton.Sync(tt.head, true) + skeleton.Sync(tt.head, nil, true) <-wait skeleton.Terminate() @@ -484,10 +484,10 @@ func TestSkeletonSyncExtend(t *testing.T) { skeleton := newSkeleton(db, newPeerSet(), nil, newHookedBackfiller()) skeleton.syncStarting = func() { close(wait) } - skeleton.Sync(tt.head, true) + skeleton.Sync(tt.head, nil, true) <-wait - if err := skeleton.Sync(tt.extend, false); err != tt.err { + if err := skeleton.Sync(tt.extend, nil, false); err != tt.err { t.Errorf("test %d: extension failure mismatch: have %v, want %v", i, err, tt.err) } skeleton.Terminate() @@ -859,7 +859,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) { } // Create a skeleton sync and run a cycle skeleton := newSkeleton(db, peerset, drop, filler) - skeleton.Sync(tt.head, true) + skeleton.Sync(tt.head, nil, true) var progress skeletonProgress // Wait a bit (bleah) for the initial sync loop to go to idle. This might @@ -910,7 +910,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) { } // Apply the post-init events if there's any if tt.newHead != nil { - skeleton.Sync(tt.newHead, true) + skeleton.Sync(tt.newHead, nil, true) } if tt.newPeer != nil { if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH66, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil { diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go index 01f81a7b1cd..d791723b05b 100644 --- a/eth/downloader/testchain_test.go +++ b/eth/downloader/testchain_test.go @@ -168,7 +168,7 @@ func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool) } // Include transactions to the miner to make blocks more interesting. if parent == tc.blocks[0] && i%22 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go index 50081d2e542..35608031d97 100644 --- a/eth/fetcher/block_fetcher.go +++ b/eth/fetcher/block_fetcher.go @@ -599,7 +599,7 @@ func (f *BlockFetcher) loop() { announce.time = task.time // If the block is empty (header only), short circuit into the final import queue - if header.TxHash == types.EmptyRootHash && header.UncleHash == types.EmptyUncleHash { + if header.TxHash == types.EmptyTxsHash && header.UncleHash == types.EmptyUncleHash { log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash()) block := types.NewBlockWithHeader(header) diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go index 9e5693c02e5..0553add4f19 100644 --- a/eth/fetcher/block_fetcher_test.go +++ b/eth/fetcher/block_fetcher_test.go @@ -58,7 +58,7 @@ func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common // If the block number is multiple of 3, send a bonus transaction to the miner if parent == genesis && i%3 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/eth/filters/api.go b/eth/filters/api.go index a30eb28befd..f9ae70eba79 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -39,6 +39,7 @@ type filter struct { typ Type deadline *time.Timer // filter is inactive when deadline triggers hashes []common.Hash + fullTx bool txs []*types.Transaction crit FilterCriteria logs []*types.Log @@ -103,14 +104,14 @@ func (api *FilterAPI) timeoutLoop(timeout time.Duration) { // // It is part of the filter package because this filter can be used through the // `eth_getFilterChanges` polling method that is also used for log filters. -func (api *FilterAPI) NewPendingTransactionFilter() rpc.ID { +func (api *FilterAPI) NewPendingTransactionFilter(fullTx *bool) rpc.ID { var ( pendingTxs = make(chan []*types.Transaction) pendingTxSub = api.events.SubscribePendingTxs(pendingTxs) ) api.filtersMu.Lock() - api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, deadline: time.NewTimer(api.timeout), txs: make([]*types.Transaction, 0), s: pendingTxSub} + api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, fullTx: fullTx != nil && *fullTx, deadline: time.NewTimer(api.timeout), txs: make([]*types.Transaction, 0), s: pendingTxSub} api.filtersMu.Unlock() go func() { @@ -412,6 +413,9 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { api.filtersMu.Lock() defer api.filtersMu.Unlock() + chainConfig := api.sys.backend.ChainConfig() + latest := api.sys.backend.CurrentHeader() + if f, found := api.filters[id]; found { if !f.deadline.Stop() { // timer expired but filter is not yet removed in timeout loop @@ -426,9 +430,21 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { f.hashes = nil return returnHashes(hashes), nil case PendingTransactionsSubscription: - txs := f.txs - f.txs = nil - return txs, nil + if f.fullTx { + txs := make([]*ethapi.RPCTransaction, 0, len(f.txs)) + for _, tx := range f.txs { + txs = append(txs, ethapi.NewRPCPendingTransaction(tx, latest, chainConfig)) + } + f.txs = nil + return txs, nil + } else { + hashes := make([]common.Hash, 0, len(f.txs)) + for _, tx := range f.txs { + hashes = append(hashes, tx.Hash()) + } + f.txs = nil + return hashes, nil + } case LogsSubscription, MinedAndPendingLogsSubscription: logs := f.logs f.logs = nil diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index 974483b68fd..b70b0158ad0 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -37,6 +37,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) @@ -52,11 +53,12 @@ type testBackend struct { } func (b *testBackend) ChainConfig() *params.ChainConfig { - panic("implement me") + return params.TestChainConfig } func (b *testBackend) CurrentHeader() *types.Header { - panic("implement me") + hdr, _ := b.HeaderByNumber(context.TODO(), rpc.LatestBlockNumber) + return hdr } func (b *testBackend) ChainDb() ethdb.Database { @@ -256,10 +258,10 @@ func TestPendingTxFilter(t *testing.T) { types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), } - txs []*types.Transaction + hashes []common.Hash ) - fid0 := api.NewPendingTransactionFilter() + fid0 := api.NewPendingTransactionFilter(nil) time.Sleep(1 * time.Second) backend.txFeed.Send(core.NewTxsEvent{Txs: transactions}) @@ -271,7 +273,64 @@ func TestPendingTxFilter(t *testing.T) { t.Fatalf("Unable to retrieve logs: %v", err) } - tx := results.([]*types.Transaction) + h := results.([]common.Hash) + hashes = append(hashes, h...) + if len(hashes) >= len(transactions) { + break + } + // check timeout + if time.Now().After(timeout) { + break + } + + time.Sleep(100 * time.Millisecond) + } + + if len(hashes) != len(transactions) { + t.Errorf("invalid number of transactions, want %d transactions(s), got %d", len(transactions), len(hashes)) + return + } + for i := range hashes { + if hashes[i] != transactions[i].Hash() { + t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), hashes[i]) + } + } +} + +// TestPendingTxFilterFullTx tests whether pending tx filters retrieve all pending transactions that are posted to the event mux. +func TestPendingTxFilterFullTx(t *testing.T) { + t.Parallel() + + var ( + db = rawdb.NewMemoryDatabase() + backend, sys = newTestFilterSystem(t, db, Config{}) + api = NewFilterAPI(sys, false) + + transactions = []*types.Transaction{ + types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), + types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), + types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), + types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), + types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), + } + + txs []*ethapi.RPCTransaction + ) + + fullTx := true + fid0 := api.NewPendingTransactionFilter(&fullTx) + + time.Sleep(1 * time.Second) + backend.txFeed.Send(core.NewTxsEvent{Txs: transactions}) + + timeout := time.Now().Add(1 * time.Second) + for { + results, err := api.GetFilterChanges(fid0) + if err != nil { + t.Fatalf("Unable to retrieve logs: %v", err) + } + + tx := results.([]*ethapi.RPCTransaction) txs = append(txs, tx...) if len(txs) >= len(transactions) { break @@ -289,8 +348,8 @@ func TestPendingTxFilter(t *testing.T) { return } for i := range txs { - if txs[i].Hash() != transactions[i].Hash() { - t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[i].Hash()) + if txs[i].Hash != transactions[i].Hash() { + t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[i].Hash) } } } @@ -854,15 +913,15 @@ func TestPendingTxFilterDeadlock(t *testing.T) { // timeout either in 100ms or 200ms fids := make([]rpc.ID, 20) for i := 0; i < len(fids); i++ { - fid := api.NewPendingTransactionFilter() + fid := api.NewPendingTransactionFilter(nil) fids[i] = fid // Wait for at least one tx to arrive in filter for { - txs, err := api.GetFilterChanges(fid) + hashes, err := api.GetFilterChanges(fid) if err != nil { t.Fatalf("Filter should exist: %v\n", err) } - if len(txs.([]*types.Transaction)) > 0 { + if len(hashes.([]common.Hash)) > 0 { break } runtime.Gosched() diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 604ad5e1043..817ae4fc1d1 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -176,7 +176,8 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { results []*big.Int ) for sent < oracle.checkBlocks && number > 0 { - go oracle.getBlockValues(ctx, types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number))), number, sampleNumber, oracle.ignorePrice, result, quit) + signer := types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number)), head.Time) + go oracle.getBlockValues(ctx, signer, number, sampleNumber, oracle.ignorePrice, result, quit) sent++ exp++ number-- @@ -199,7 +200,7 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { // meaningful returned, try to query more blocks. But the maximum // is 2*checkBlocks. if len(res.values) == 1 && len(results)+1+exp < oracle.checkBlocks*2 && number > 0 { - go oracle.getBlockValues(ctx, types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number))), number, sampleNumber, oracle.ignorePrice, result, quit) + go oracle.getBlockValues(ctx, types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number)), head.Time), number, sampleNumber, oracle.ignorePrice, result, quit) sent++ exp++ number-- diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index a987d46458e..4ee5a0d1b28 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -49,10 +49,10 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber number = 0 } if number == rpc.FinalizedBlockNumber { - return b.chain.CurrentFinalizedBlock().Header(), nil + return b.chain.CurrentFinalBlock(), nil } if number == rpc.SafeBlockNumber { - return b.chain.CurrentSafeBlock().Header(), nil + return b.chain.CurrentSafeBlock(), nil } if number == rpc.LatestBlockNumber { number = testHead @@ -75,10 +75,10 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) number = 0 } if number == rpc.FinalizedBlockNumber { - return b.chain.CurrentFinalizedBlock(), nil + number = rpc.BlockNumber(b.chain.CurrentFinalBlock().Number.Uint64()) } if number == rpc.SafeBlockNumber { - return b.chain.CurrentSafeBlock(), nil + number = rpc.BlockNumber(b.chain.CurrentSafeBlock().Number.Uint64()) } if number == rpc.LatestBlockNumber { number = testHead @@ -169,8 +169,8 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke t.Fatalf("Failed to create local chain, %v", err) } chain.InsertChain(blocks) - chain.SetFinalized(chain.GetBlockByNumber(25)) - chain.SetSafe(chain.GetBlockByNumber(25)) + chain.SetFinalized(chain.GetBlockByNumber(25).Header()) + chain.SetSafe(chain.GetBlockByNumber(25).Header()) return &testBackend{chain: chain, pending: pending} } diff --git a/eth/handler.go b/eth/handler.go index 078133f059f..ed4ea16ade8 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -152,13 +152,13 @@ func newHandler(config *handlerConfig) (*handler, error) { // * the last snap sync is not finished while user specifies a full sync this // time. But we don't have any recent state for full sync. // In these cases however it's safe to reenable snap sync. - fullBlock, fastBlock := h.chain.CurrentBlock(), h.chain.CurrentFastBlock() - if fullBlock.NumberU64() == 0 && fastBlock.NumberU64() > 0 { + fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock() + if fullBlock.Number.Uint64() == 0 && snapBlock.Number.Uint64() > 0 { h.snapSync = uint32(1) log.Warn("Switch sync mode from full sync to snap sync") } } else { - if h.chain.CurrentBlock().NumberU64() > 0 { + if h.chain.CurrentBlock().Number.Uint64() > 0 { // Print warning log if database is not empty to run snap sync. log.Warn("Switch sync mode from snap sync to full sync") } else { @@ -183,10 +183,10 @@ func newHandler(config *handlerConfig) (*handler, error) { // If we've successfully finished a sync cycle and passed any required // checkpoint, enable accepting transactions from the network head := h.chain.CurrentBlock() - if head.NumberU64() >= h.checkpointNumber { + if head.Number.Uint64() >= h.checkpointNumber { // Checkpoint passed, sanity check the timestamp to have a fallback mechanism // for non-checkpointed (number = 0) private networks. - if head.Time() >= uint64(time.Now().AddDate(0, -1, 0).Unix()) { + if head.Time >= uint64(time.Now().AddDate(0, -1, 0).Unix()) { atomic.StoreUint32(&h.acceptTxs, 1) } } @@ -198,7 +198,7 @@ func newHandler(config *handlerConfig) (*handler, error) { log.Info("Chain post-merge, sync via beacon client") } else { head := h.chain.CurrentBlock() - if td := h.chain.GetTd(head.Hash(), head.NumberU64()); td.Cmp(ttd) >= 0 { + if td := h.chain.GetTd(head.Hash(), head.Number.Uint64()); td.Cmp(ttd) >= 0 { log.Info("Chain post-TTD, sync via beacon client") } else { log.Warn("Chain pre-merge, sync via PoW (ensure beacon client is ready)") @@ -227,7 +227,7 @@ func newHandler(config *handlerConfig) (*handler, error) { return h.chain.Engine().VerifyHeader(h.chain, header, true) } heighter := func() uint64 { - return h.chain.CurrentBlock().NumberU64() + return h.chain.CurrentBlock().Number.Uint64() } inserter := func(blocks types.Blocks) (int, error) { // All the block fetcher activities should be disabled @@ -250,7 +250,7 @@ func newHandler(config *handlerConfig) (*handler, error) { // the propagated block if the head is too old. Unfortunately there is a corner // case when starting new networks, where the genesis might be ancient (0 unix) // which would prevent full nodes from accepting it. - if h.chain.CurrentBlock().NumberU64() < h.checkpointNumber { + if h.chain.CurrentBlock().Number.Uint64() < h.checkpointNumber { log.Warn("Unsynced yet, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) return 0, nil } @@ -636,13 +636,17 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) { annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce ) - // Broadcast transactions to a batch of peers not knowing about it + // Broadcast transactions to a batch of peers not knowing about it, exluding + // only blob transactions which are never to be broadcast per EIP-4844 for _, tx := range txs { peers := h.peers.peersWithoutTransaction(tx.Hash()) - // Send the tx unconditionally to a subset of our peers - numDirect := int(math.Sqrt(float64(len(peers)))) - for _, peer := range peers[:numDirect] { - txset[peer] = append(txset[peer], tx.Hash()) + var numDirect int + if tx.Type() != types.BlobTxType { + // Send the tx unconditionally to a subset of our peers + numDirect = int(math.Sqrt(float64(len(peers)))) + for _, peer := range peers[:numDirect] { + txset[peer] = append(txset[peer], tx.Hash()) + } } // For the remaining peers, send announcement only for _, peer := range peers[numDirect:] { diff --git a/eth/handler_eth.go b/eth/handler_eth.go index 4ed6335769c..3bd36044c44 100644 --- a/eth/handler_eth.go +++ b/eth/handler_eth.go @@ -74,10 +74,12 @@ func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error { return h.txFetcher.Notify(peer.ID(), packet.Hashes) case *eth.TransactionsPacket: - return h.txFetcher.Enqueue(peer.ID(), *packet, false) + txs := packet.Unwrap() + return h.txFetcher.Enqueue(peer.ID(), txs, false) case *eth.PooledTransactionsPacket: - return h.txFetcher.Enqueue(peer.ID(), *packet, true) + txs := packet.Unwrap() + return h.txFetcher.Enqueue(peer.ID(), txs, true) default: return fmt.Errorf("unexpected eth packet type: %T", packet) diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index 502cc8e6a9f..1a469b28db2 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -39,6 +39,8 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" + "github.com/protolambda/ztyp/view" ) // testEthHandler is a mock event handler to listen for inbound network requests @@ -70,11 +72,18 @@ func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error { return nil case *eth.TransactionsPacket: - h.txBroadcasts.Send(([]*types.Transaction)(*packet)) + txs := packet.Unwrap() + for i, tx := range txs { + if tx.Type() == types.BlobTxType { + // blob txs should never be broadcast + return fmt.Errorf("transaction %v is a blob tx", i) + } + } + h.txBroadcasts.Send(packet.Unwrap()) return nil case *eth.PooledTransactionsPacket: - h.txBroadcasts.Send(([]*types.Transaction)(*packet)) + h.txBroadcasts.Send(packet.Unwrap()) return nil default: @@ -274,7 +283,7 @@ func testRecvTransactions(t *testing.T, protocol uint) { var ( genesis = handler.chain.Genesis() head = handler.chain.CurrentBlock() - td = handler.chain.GetTd(head.Hash(), head.NumberU64()) + td = handler.chain.GetTd(head.Hash(), head.Number.Uint64()) ) if err := src.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { t.Fatalf("failed to run protocol handshake") @@ -283,7 +292,8 @@ func testRecvTransactions(t *testing.T, protocol uint) { tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil) tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) - if err := src.SendTransactions([]*types.Transaction{tx}); err != nil { + ntx := types.NewNetworkTransaction(tx) + if err := src.SendTransactions([]*types.NetworkTransaction{ntx}); err != nil { t.Fatalf("failed to send transaction: %v", err) } select { @@ -337,7 +347,7 @@ func testSendTransactions(t *testing.T, protocol uint) { var ( genesis = handler.chain.Genesis() head = handler.chain.CurrentBlock() - td = handler.chain.GetTd(head.Hash(), head.NumberU64()) + td = handler.chain.GetTd(head.Hash(), head.Number.Uint64()) ) if err := sink.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { t.Fatalf("failed to run protocol handshake") @@ -436,13 +446,32 @@ func testTransactionPropagation(t *testing.T, protocol uint) { defer sub.Unsubscribe() } // Fill the source pool with transactions and wait for them at the sinks - txs := make([]*types.Transaction, 1024) + txs := make([]*types.Transaction, 1023) for nonce := range txs { tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil) tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) txs[nonce] = tx } + txdata := &types.SignedBlobTx{ + Message: types.BlobTxMessage{ + ChainID: view.Uint256View(*uint256.NewInt(1)), + Nonce: view.Uint64View(len(txs)), + Gas: view.Uint64View(123457), + BlobVersionedHashes: types.VersionedHashesView{common.HexToHash("0x01624652859a6e98ffc1608e2af0147ca4e86e1ce27672d8d3f3c9d4ffd6ef7e")}, + }, + } + wrapData := &types.BlobTxWrapData{ + BlobKzgs: types.BlobKzgs{types.KZGCommitment{0: 0xc0}}, + Blobs: types.Blobs{types.Blob{}}, + Proofs: types.KZGProofs{types.KZGProof{0: 0xd0}}, + } + blobTx, err := types.SignNewTx(testKey, types.NewDankSigner(common.Big1), txdata, types.WithTxWrapData(wrapData)) + if err != nil { + t.Fatal(err) + } + txs = append(txs, blobTx) + source.txpool.AddRemotes(txs) // Iterate through all the sinks and ensure they all got the transactions @@ -545,7 +574,7 @@ func testCheckpointChallenge(t *testing.T, syncmode downloader.SyncMode, checkpo var ( genesis = handler.chain.Genesis() head = handler.chain.CurrentBlock() - td = handler.chain.GetTd(head.Hash(), head.NumberU64()) + td = handler.chain.GetTd(head.Hash(), head.Number.Uint64()) ) if err := remote.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { t.Fatalf("failed to run protocol handshake") @@ -661,7 +690,8 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) { } // Initiate a block propagation across the peers time.Sleep(100 * time.Millisecond) - source.handler.BroadcastBlock(source.chain.CurrentBlock(), true) + header := source.chain.CurrentBlock() + source.handler.BroadcastBlock(source.chain.GetBlock(header.Hash(), header.Number.Uint64()), true) // Iterate through all the sinks and ensure the correct number got the block done := make(chan struct{}, peers) @@ -734,18 +764,19 @@ func testBroadcastMalformedBlock(t *testing.T, protocol uint) { // Create various combinations of malformed blocks head := source.chain.CurrentBlock() + block := source.chain.GetBlock(head.Hash(), head.Number.Uint64()) - malformedUncles := head.Header() + malformedUncles := head malformedUncles.UncleHash[0]++ - malformedTransactions := head.Header() + malformedTransactions := head malformedTransactions.TxHash[0]++ - malformedEverything := head.Header() + malformedEverything := head malformedEverything.UncleHash[0]++ malformedEverything.TxHash[0]++ // Try to broadcast all malformations and ensure they all get discarded for _, header := range []*types.Header{malformedUncles, malformedTransactions, malformedEverything} { - block := types.NewBlockWithHeader(header).WithBody(head.Transactions(), head.Uncles()) + block := types.NewBlockWithHeader(header).WithBody(block.Transactions(), block.Uncles()) if err := src.SendNewBlock(block, big.NewInt(131136)); err != nil { t.Fatalf("failed to broadcast block: %v", err) } diff --git a/eth/peer.go b/eth/peer.go index 55e5f004620..76187777166 100644 --- a/eth/peer.go +++ b/eth/peer.go @@ -17,8 +17,6 @@ package eth import ( - "math/big" - "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" ) @@ -26,9 +24,7 @@ import ( // ethPeerInfo represents a short summary of the `eth` sub-protocol metadata known // about a connected peer. type ethPeerInfo struct { - Version uint `json:"version"` // Ethereum protocol version negotiated - Difficulty *big.Int `json:"difficulty"` // Total difficulty of the peer's blockchain - Head string `json:"head"` // Hex hash of the peer's best owned block + Version uint `json:"version"` // Ethereum protocol version negotiated } // ethPeer is a wrapper around eth.Peer to maintain a few extra metadata. @@ -39,12 +35,8 @@ type ethPeer struct { // info gathers and returns some `eth` protocol metadata known about a peer. func (p *ethPeer) info() *ethPeerInfo { - hash, td := p.Head() - return ðPeerInfo{ - Version: p.Version(), - Difficulty: td, - Head: hash.Hex(), + Version: p.Version(), } } diff --git a/eth/protocols/eth/broadcast.go b/eth/protocols/eth/broadcast.go index 3045303f222..5216ffb7b52 100644 --- a/eth/protocols/eth/broadcast.go +++ b/eth/protocols/eth/broadcast.go @@ -76,12 +76,12 @@ func (p *Peer) broadcastTransactions() { // Pile transaction until we reach our allowed network limit var ( hashesCount uint64 - txs []*types.Transaction + txs []*types.NetworkTransaction size common.StorageSize ) for i := 0; i < len(queue) && size < maxTxPacketSize; i++ { if tx := p.txpool.Get(queue[i]); tx != nil { - txs = append(txs, tx) + txs = append(txs, types.NewNetworkTransaction(tx)) size += common.StorageSize(tx.Size()) } hashesCount++ diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go index ae4ec9142e8..2f2dd1cf6ae 100644 --- a/eth/protocols/eth/handler.go +++ b/eth/protocols/eth/handler.go @@ -137,12 +137,14 @@ type NodeInfo struct { // nodeInfo retrieves some `eth` protocol metadata about the running host node. func nodeInfo(chain *core.BlockChain, network uint64) *NodeInfo { head := chain.CurrentBlock() + hash := head.Hash() + return &NodeInfo{ Network: network, - Difficulty: chain.GetTd(head.Hash(), head.NumberU64()), + Difficulty: chain.GetTd(hash, head.Number.Uint64()), Genesis: chain.Genesis().Hash(), Config: chain.Config(), - Head: head.Hash(), + Head: hash, } } diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index 76505ab8d32..bbb9866bd3d 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -225,24 +225,24 @@ func testGetBlockHeaders(t *testing.T, protocol uint) { []common.Hash{backend.chain.GetBlockByNumber(0).Hash()}, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().NumberU64()}, Amount: 1}, + &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 1}, []common.Hash{backend.chain.CurrentBlock().Hash()}, }, { // If the peer requests a bit into the future, we deliver what we have - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().NumberU64()}, Amount: 10}, + &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 10}, []common.Hash{backend.chain.CurrentBlock().Hash()}, }, // Ensure protocol limits are honored { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, - getHashes(backend.chain.CurrentBlock().NumberU64(), limit), + &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 1}, Amount: limit + 10, Reverse: true}, + getHashes(backend.chain.CurrentBlock().Number.Uint64(), limit), }, // Check that requesting more than available is handled gracefully { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, + &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3}, []common.Hash{ - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().NumberU64() - 4).Hash(), - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().NumberU64()).Hash(), + backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(), + backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64()).Hash(), }, }, { &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, @@ -253,10 +253,10 @@ func testGetBlockHeaders(t *testing.T, protocol uint) { }, // Check that requesting more than available is handled gracefully, even if mid skip { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, + &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3}, []common.Hash{ - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().NumberU64() - 4).Hash(), - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().NumberU64() - 1).Hash(), + backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(), + backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 1).Hash(), }, }, { &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, @@ -293,7 +293,7 @@ func testGetBlockHeaders(t *testing.T, protocol uint) { &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: unknown}, Amount: 1}, []common.Hash{}, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().NumberU64() + 1}, Amount: 1}, + &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() + 1}, Amount: 1}, []common.Hash{}, }, } @@ -394,7 +394,7 @@ func testGetBlockBodies(t *testing.T, protocol uint) { ) for j := 0; j < tt.random; j++ { for { - num := rand.Int63n(int64(backend.chain.CurrentBlock().NumberU64())) + num := rand.Int63n(int64(backend.chain.CurrentBlock().Number.Uint64())) if !seen[num] { seen[num] = true @@ -529,7 +529,7 @@ func testGetNodeData(t *testing.T, protocol uint, drop bool) { // Sanity check whether all state matches. accounts := []common.Address{testAddr, acc1Addr, acc2Addr} - for i := uint64(0); i <= backend.chain.CurrentBlock().NumberU64(); i++ { + for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { root := backend.chain.GetBlockByNumber(i).Root() reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil) for j, acc := range accounts { @@ -602,7 +602,7 @@ func testGetBlockReceipts(t *testing.T, protocol uint) { hashes []common.Hash receipts [][]*types.Receipt ) - for i := uint64(0); i <= backend.chain.CurrentBlock().NumberU64(); i++ { + for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { block := backend.chain.GetBlockByNumber(i) hashes = append(hashes, block.Hash()) diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index 74e514b863a..ea272877f20 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -498,7 +498,7 @@ func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsPac continue } // If known, encode and queue for response packet - if encoded, err := rlp.EncodeToBytes(tx); err != nil { + if encoded, err := rlp.EncodeToBytes(types.NewNetworkTransaction(tx)); err != nil { log.Error("Failed to encode transaction", "err", err) } else { hashes = append(hashes, hash) @@ -524,6 +524,13 @@ func handleTransactions(backend Backend, msg Decoder, peer *Peer) error { if tx == nil { return fmt.Errorf("%w: transaction %d is nil", errDecode, i) } + // TODO(eip-4844): implement penalizing of clients who send unrequested + // blob transactions. While we're interop testing we'll go ahead and + // accept any that happen to come our way. + /*if tx.Tx.Type() == types.BlobTxType { + // blob txs should never be broadcast + return fmt.Errorf("transaction %v is a blob tx", i) + }*/ peer.markTransaction(tx.Hash()) } return backend.Handle(peer, &txs) diff --git a/eth/protocols/eth/handshake_test.go b/eth/protocols/eth/handshake_test.go index c768edaeac0..5c6727d91cc 100644 --- a/eth/protocols/eth/handshake_test.go +++ b/eth/protocols/eth/handshake_test.go @@ -39,7 +39,7 @@ func testHandshake(t *testing.T, protocol uint) { var ( genesis = backend.chain.Genesis() head = backend.chain.CurrentBlock() - td = backend.chain.GetTd(head.Hash(), head.NumberU64()) + td = backend.chain.GetTd(head.Hash(), head.Number.Uint64()) forkID = forkid.NewID(backend.chain.Config(), backend.chain.Genesis().Hash(), backend.chain.CurrentHeader().Number.Uint64(), backend.chain.CurrentHeader().Time) ) tests := []struct { diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index 219f486c8e6..1af5ccb7ee3 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -189,7 +189,7 @@ func (p *Peer) markTransaction(hash common.Hash) { // // The reasons this is public is to allow packages using this protocol to write // tests that directly send messages without having to do the async queueing. -func (p *Peer) SendTransactions(txs types.Transactions) error { +func (p *Peer) SendTransactions(txs types.NetworkTransactions) error { // Mark all the transactions as known, but ensure we don't overflow our limits for _, tx := range txs { p.knownTxs.Add(tx.Hash()) diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index 0d4b368988f..c69e71e7f8a 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -116,7 +116,16 @@ func (p *NewBlockHashesPacket) Unpack() ([]common.Hash, []uint64) { } // TransactionsPacket is the network packet for broadcasting new transactions. -type TransactionsPacket []*types.Transaction +type TransactionsPacket []*types.NetworkTransaction + +// Unwrap returns the wrapped Transactions +func (p *TransactionsPacket) Unwrap() []*types.Transaction { + txs := make([]*types.Transaction, len(*p)) + for i := range *p { + txs[i] = (*p)[i].Tx + } + return txs +} // GetBlockHeadersPacket represents a block header query. type GetBlockHeadersPacket struct { @@ -321,7 +330,7 @@ type GetPooledTransactionsPacket66 struct { } // PooledTransactionsPacket is the network packet for transaction distribution. -type PooledTransactionsPacket []*types.Transaction +type PooledTransactionsPacket []*types.NetworkTransaction // PooledTransactionsPacket66 is the network packet for transaction distribution over eth/66. type PooledTransactionsPacket66 struct { @@ -329,6 +338,15 @@ type PooledTransactionsPacket66 struct { PooledTransactionsPacket } +// Unwrap returns the wrapped transactions +func (p *PooledTransactionsPacket) Unwrap() []*types.Transaction { + txs := make([]*types.Transaction, len(*p)) + for i := range *p { + txs[i] = (*p)[i].Tx + } + return txs +} + // PooledTransactionsRLPPacket is the network packet for transaction distribution, used // in the cases we already have them in rlp-encoded form type PooledTransactionsRLPPacket []rlp.RawValue diff --git a/eth/protocols/eth/protocol_test.go b/eth/protocols/eth/protocol_test.go index a86fbb0a690..c919bf5df03 100644 --- a/eth/protocols/eth/protocol_test.go +++ b/eth/protocols/eth/protocol_test.go @@ -108,7 +108,7 @@ func TestEth66EmptyMessages(t *testing.T) { ReceiptsPacket66{1111, ReceiptsPacket([][]*types.Receipt{})}, // Transactions GetPooledTransactionsPacket66{1111, GetPooledTransactionsPacket([]common.Hash{})}, - PooledTransactionsPacket66{1111, PooledTransactionsPacket([]*types.Transaction{})}, + PooledTransactionsPacket66{1111, PooledTransactionsPacket([]*types.NetworkTransaction{})}, PooledTransactionsRLPPacket66{1111, PooledTransactionsRLPPacket([]rlp.RawValue{})}, } { if have, _ := rlp.EncodeToBytes(msg); !bytes.Equal(have, want) { @@ -125,6 +125,7 @@ func TestEth66Messages(t *testing.T) { blockBody *BlockBody blockBodyRlp rlp.RawValue txs []*types.Transaction + ntxs []*types.NetworkTransaction txRlps []rlp.RawValue hashes []common.Hash receipts []*types.Receipt @@ -152,6 +153,7 @@ func TestEth66Messages(t *testing.T) { t.Fatal(err) } txs = append(txs, tx) + ntxs = append(ntxs, types.NewNetworkTransaction(tx)) txRlps = append(txRlps, rlpdata) } } @@ -251,7 +253,7 @@ func TestEth66Messages(t *testing.T) { common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), }, { - PooledTransactionsPacket66{1111, PooledTransactionsPacket(txs)}, + PooledTransactionsPacket66{1111, PooledTransactionsPacket(ntxs)}, common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"), }, { diff --git a/eth/protocols/snap/handler.go b/eth/protocols/snap/handler.go index 6941d522aa2..d7c94004401 100644 --- a/eth/protocols/snap/handler.go +++ b/eth/protocols/snap/handler.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -464,7 +465,7 @@ func ServiceGetByteCodesQuery(chain *core.BlockChain, req *GetByteCodesPacket) [ bytes uint64 ) for _, hash := range req.Hashes { - if hash == emptyCode { + if hash == types.EmptyCodeHash { // Peers should not request the empty code, but if they do, at // least sent them back a correct response without db lookups codes = append(codes, []byte{}) diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 052d8eaca72..13279fd96c4 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -46,14 +46,6 @@ import ( "golang.org/x/crypto/sha3" ) -var ( - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // emptyCode is the known hash of the empty EVM bytecode. - emptyCode = crypto.Keccak256Hash(nil) -) - const ( // minRequestSize is the minimum number of bytes to request from a remote peer. // This number is used as the low cap for account and storage range requests. @@ -1833,7 +1825,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) { res.task.pend = 0 for i, account := range res.accounts { // Check if the account is a contract with an unknown code - if !bytes.Equal(account.CodeHash, emptyCode[:]) { + if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)) { res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{} res.task.needCode[i] = true @@ -1841,7 +1833,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) { } } // Check if the account is a contract with an unknown storage trie - if account.Root != emptyRoot { + if account.Root != types.EmptyRootHash { if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) { // If there was a previous large state retrieval in progress, // don't restart it from scratch. This happens if a sync cycle diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go index 971605d8c29..0a611797295 100644 --- a/eth/protocols/snap/sync_test.go +++ b/eth/protocols/snap/sync_test.go @@ -1354,7 +1354,7 @@ func getCodeHash(i uint64) []byte { // getCodeByHash convenience function to lookup the code from the code hash func getCodeByHash(hash common.Hash) []byte { - if hash == emptyCode { + if hash == types.EmptyCodeHash { return nil } for i, h := range codehashes { @@ -1376,7 +1376,7 @@ func makeAccountTrieNoStorage(n int) (string, *trie.Trie, entrySlice) { value, _ := rlp.EncodeToBytes(&types.StateAccount{ Nonce: i, Balance: big.NewInt(int64(i)), - Root: emptyRoot, + Root: types.EmptyRootHash, CodeHash: getCodeHash(i), }) key := key32(i) @@ -1427,7 +1427,7 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) { value, _ := rlp.EncodeToBytes(&types.StateAccount{ Nonce: uint64(0), Balance: big.NewInt(int64(i)), - Root: emptyRoot, + Root: types.EmptyRootHash, CodeHash: getCodeHash(uint64(i)), }) elem := &kv{boundaries[i].Bytes(), value} @@ -1439,7 +1439,7 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) { value, _ := rlp.EncodeToBytes(&types.StateAccount{ Nonce: i, Balance: big.NewInt(int64(i)), - Root: emptyRoot, + Root: types.EmptyRootHash, CodeHash: getCodeHash(i), }) elem := &kv{key32(i), value} @@ -1472,7 +1472,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool) // Create n accounts in the trie for i := uint64(1); i <= uint64(accounts); i++ { key := key32(i) - codehash := emptyCode[:] + codehash := types.EmptyCodeHash.Bytes() if code { codehash = getCodeHash(i) } @@ -1527,7 +1527,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin // Create n accounts in the trie for i := uint64(1); i <= uint64(accounts); i++ { key := key32(i) - codehash := emptyCode[:] + codehash := types.EmptyCodeHash.Bytes() if code { codehash = getCodeHash(i) } @@ -1678,7 +1678,7 @@ func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) { log.Crit("Invalid account encountered during snapshot creation", "err", err) } accounts++ - if acc.Root != emptyRoot { + if acc.Root != types.EmptyRootHash { id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root) storeTrie, err := trie.NewStateTrie(id, triedb) if err != nil { diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 3bb1464952a..9d95346d05b 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -155,11 +155,12 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe logged = time.Now() } // Retrieve the next block to regenerate and process it + excessDataGas := current.Header().ExcessDataGas next := current.NumberU64() + 1 if current = eth.blockchain.GetBlockByNumber(next); current == nil { return nil, nil, fmt.Errorf("block #%d not found", next) } - _, _, _, err := eth.blockchain.Processor().Process(current, statedb, vm.Config{}) + _, _, _, err := eth.blockchain.Processor().Process(current, excessDataGas, statedb, vm.Config{}) if err != nil { return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err) } @@ -189,7 +190,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe } // stateAtTransaction returns the execution environment of a certain transaction. -func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { // Short circuit if it's genesis block. if block.NumberU64() == 0 { return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") @@ -209,19 +210,19 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, return nil, vm.BlockContext{}, statedb, release, nil } // Recompute transactions up to the target index. - signer := types.MakeSigner(eth.blockchain.Config(), block.Number()) + signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time()) for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset - msg, _ := tx.AsMessage(signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) + context := core.NewEVMBlockContext(block.Header(), parent.Header().ExcessDataGas, eth.blockchain, nil) if idx == txIndex { return msg, context, statedb, release, nil } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) statedb.SetTxContext(tx.Hash(), idx) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { + if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()).AddDataGas(tx.DataGas().Uint64())); err != nil { return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } // Ensure any modifications are committed to the state diff --git a/eth/sync.go b/eth/sync.go index 8fd86b578cf..6d764ef4822 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -206,22 +206,22 @@ func peerToSyncOp(mode downloader.SyncMode, p *eth.Peer) *chainSyncOp { func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) { // If we're in snap sync mode, return that directly if atomic.LoadUint32(&cs.handler.snapSync) == 1 { - block := cs.handler.chain.CurrentFastBlock() - td := cs.handler.chain.GetTd(block.Hash(), block.NumberU64()) + block := cs.handler.chain.CurrentSnapBlock() + td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) return downloader.SnapSync, td } // We are probably in full sync, but we might have rewound to before the // snap sync pivot, check if we should reenable if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil { - if head := cs.handler.chain.CurrentBlock(); head.NumberU64() < *pivot { - block := cs.handler.chain.CurrentFastBlock() - td := cs.handler.chain.GetTd(block.Hash(), block.NumberU64()) + if head := cs.handler.chain.CurrentBlock(); head.Number.Uint64() < *pivot { + block := cs.handler.chain.CurrentSnapBlock() + td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) return downloader.SnapSync, td } } // Nope, we're really full syncing head := cs.handler.chain.CurrentBlock() - td := cs.handler.chain.GetTd(head.Hash(), head.NumberU64()) + td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64()) return downloader.FullSync, td } @@ -263,21 +263,23 @@ func (h *handler) doSync(op *chainSyncOp) error { // If we've successfully finished a sync cycle and passed any required checkpoint, // enable accepting transactions from the network. head := h.chain.CurrentBlock() - if head.NumberU64() >= h.checkpointNumber { + if head.Number.Uint64() >= h.checkpointNumber { // Checkpoint passed, sanity check the timestamp to have a fallback mechanism // for non-checkpointed (number = 0) private networks. - if head.Time() >= uint64(time.Now().AddDate(0, -1, 0).Unix()) { + if head.Time >= uint64(time.Now().AddDate(0, -1, 0).Unix()) { atomic.StoreUint32(&h.acceptTxs, 1) } } - if head.NumberU64() > 0 { + if head.Number.Uint64() > 0 { // We've completed a sync cycle, notify all peers of new state. This path is // essential in star-topology networks where a gateway node needs to notify // all its out-of-date peers of the availability of a new block. This failure // scenario will most often crop up in private and hackathon networks with // degenerate connectivity, but it should be healthy for the mainnet too to // more reliably update peers or the local TD state. - h.BroadcastBlock(head, false) + if block := h.chain.GetBlock(head.Hash(), head.Number.Uint64()); block != nil { + h.BroadcastBlock(block, false) + } } return nil } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 55c56b40c9f..55b1d41f0bf 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -23,6 +23,7 @@ import ( "encoding/json" "errors" "fmt" + "math/big" "os" "runtime" "sync" @@ -87,7 +88,7 @@ type Backend interface { Engine() consensus.Engine ChainDb() ethdb.Database StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) - StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) + StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) } // API is the collection of tracing APIs exposed over the private debugging endpoint. @@ -285,19 +286,27 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed go func() { defer pend.Done() - // Fetch and execute the block trace taskCh + // Fetch and execute the next block trace taskCh for task := range taskCh { - var ( - signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number()) - blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil) - ) + signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time()) + var excessDataGas *big.Int + parent, err := api.backend.BlockByHash(ctx, task.block.ParentHash()) + if err != nil { + log.Warn("Tracing failed, could not lookup parent for block", task.block.NumberU64(), "err", err) + break + } + if parent != nil { + excessDataGas = parent.Header().ExcessDataGas + } + blockCtx := core.NewEVMBlockContext(task.block.Header(), excessDataGas, api.chainContext(ctx), nil) // Trace all the transactions contained within for i, tx := range task.block.Transactions() { - msg, _ := tx.AsMessage(signer, task.block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee()) txctx := &Context{ - BlockHash: task.block.Hash(), - TxIndex: i, - TxHash: tx.Hash(), + BlockHash: task.block.Hash(), + BlockNumber: task.block.Number(), + TxIndex: i, + TxHash: tx.Hash(), } res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config) if err != nil { @@ -543,9 +552,9 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config var ( roots []common.Hash - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) chainConfig = api.backend.ChainConfig() - vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) + vmctx = core.NewEVMBlockContext(block.Header(), parent.Header().ExcessDataGas, api.chainContext(ctx), nil) deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) ) for i, tx := range block.Transactions() { @@ -553,12 +562,12 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config return nil, err } var ( - msg, _ = tx.AsMessage(signer, block.BaseFee()) + msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) txContext = core.NewEVMTxContext(msg) vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{}) ) statedb.SetTxContext(tx.Hash(), i) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { + if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit).AddDataGas(params.MaxDataGasPerBlock)); err != nil { log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err) // We intentionally don't return the error here: if we do, then the RPC server will not // return the roots. Most likely, the caller already knows that a certain transaction fails to @@ -598,6 +607,10 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac if err != nil { return nil, err } + var excessDataGas *big.Int + if parent != nil { + excessDataGas = parent.Header().ExcessDataGas + } reexec := defaultTraceReexec if config != nil && config.Reexec != nil { reexec = *config.Reexec @@ -613,7 +626,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac // in separate worker threads. if config != nil && config.Tracer != nil && *config.Tracer != "" { if isJS := DefaultDirectory.IsJS(*config.Tracer); isJS { - return api.traceBlockParallel(ctx, block, statedb, config) + return api.traceBlockParallel(ctx, block, excessDataGas, statedb, config) } } // Native tracers have low overhead @@ -621,17 +634,18 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac txs = block.Transactions() blockHash = block.Hash() is158 = api.backend.ChainConfig().IsEIP158(block.Number()) - blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + blockCtx = core.NewEVMBlockContext(block.Header(), excessDataGas, api.chainContext(ctx), nil) + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) results = make([]*txTraceResult, len(txs)) ) for i, tx := range txs { // Generate the next state snapshot fast without tracing - msg, _ := tx.AsMessage(signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) txctx := &Context{ - BlockHash: blockHash, - TxIndex: i, - TxHash: tx.Hash(), + BlockHash: blockHash, + BlockNumber: block.Number(), + TxIndex: i, + TxHash: tx.Hash(), } res, err := api.traceTx(ctx, msg, txctx, blockCtx, statedb, config) if err != nil { @@ -648,13 +662,13 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac // traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread // runs along and executes txes without tracing enabled to generate their prestate. // Worker threads take the tasks and the prestate and trace them. -func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) { +func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, excessDataGas *big.Int, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) { // Execute all the transaction contained within the block concurrently var ( txs = block.Transactions() blockHash = block.Hash() - blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + blockCtx = core.NewEVMBlockContext(block.Header(), excessDataGas, api.chainContext(ctx), nil) + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) results = make([]*txTraceResult, len(txs)) pend sync.WaitGroup ) @@ -669,11 +683,12 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat defer pend.Done() // Fetch and execute the next transaction trace tasks for task := range jobs { - msg, _ := txs[task.index].AsMessage(signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee()) txctx := &Context{ - BlockHash: blockHash, - TxIndex: task.index, - TxHash: txs[task.index].Hash(), + BlockHash: blockHash, + BlockNumber: block.Number(), + TxIndex: task.index, + TxHash: txs[task.index].Hash(), } res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config) if err != nil { @@ -699,10 +714,10 @@ txloop: } // Generate the next state snapshot fast without tracing - msg, _ := tx.AsMessage(signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { + if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit).AddDataGas(params.MaxDataGasPerBlock)); err != nil { failed = err break txloop } @@ -738,6 +753,10 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block if err != nil { return nil, err } + var excessDataGas *big.Int + if parent != nil { + excessDataGas = parent.ExcessDataGas() + } reexec := defaultTraceReexec if config != nil && config.Reexec != nil { reexec = *config.Reexec @@ -762,9 +781,9 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute transaction, either tracing all or just the requested one var ( dumps []string - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) chainConfig = api.backend.ChainConfig() - vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) + vmctx = core.NewEVMBlockContext(block.Header(), excessDataGas, api.chainContext(ctx), nil) canon = true ) // Check if there are any overrides: the caller may wish to enable a future @@ -779,7 +798,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block for i, tx := range block.Transactions() { // Prepare the transaction for un-traced execution var ( - msg, _ = tx.AsMessage(signer, block.BaseFee()) + msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) txContext = core.NewEVMTxContext(msg) vmConf vm.Config dump *os.File @@ -810,7 +829,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute the transaction and flush any traces to disk vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) statedb.SetTxContext(tx.Hash(), i) - _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit).AddDataGas(params.MaxDataGasPerBlock)) if writer != nil { writer.Flush() } @@ -874,9 +893,10 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config * defer release() txctx := &Context{ - BlockHash: blockHash, - TxIndex: int(index), - TxHash: hash, + BlockHash: blockHash, + BlockNumber: block.Number(), + TxIndex: int(index), + TxHash: hash, } return api.traceTx(ctx, msg, txctx, vmctx, statedb, config) } @@ -917,9 +937,17 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc if err != nil { return nil, err } + var excessDataGas *big.Int + parent, err := api.backend.BlockByHash(ctx, block.ParentHash()) + if err != nil { + return nil, err + } + if parent != nil { + excessDataGas = parent.Header().ExcessDataGas + } defer release() - vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) + vmctx := core.NewEVMBlockContext(block.Header(), excessDataGas, api.chainContext(ctx), nil) // Apply the customization rules if required. if config != nil { if err := config.StateOverrides.Apply(statedb); err != nil { @@ -943,7 +971,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer dependent. -func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { +func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { var ( tracer Tracer err error @@ -982,7 +1010,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex // Call Prepare to clear out the statedb access list statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) - if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())); err != nil { + if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit).AddDataGas(params.MaxDataGasPerBlock)); err != nil { return nil, fmt.Errorf("tracing failed: %w", err) } return tracer.GetResult() diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 29ec8086857..8fb56a6dd9d 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -109,7 +109,7 @@ func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber { - return b.chain.CurrentBlock(), nil + return b.chain.GetBlockByNumber(b.chain.CurrentBlock().Number.Uint64()), nil } return b.chain.GetBlockByNumber(uint64(number)), nil } @@ -156,7 +156,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex return statedb, release, nil } -func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) { +func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) { parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { return nil, vm.BlockContext{}, nil, nil, errBlockNotFound @@ -169,11 +169,11 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block return nil, vm.BlockContext{}, statedb, release, nil } // Recompute transactions up to the target index. - signer := types.MakeSigner(b.chainConfig, block.Number()) + signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time()) for idx, tx := range block.Transactions() { - msg, _ := tx.AsMessage(signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(block.Header(), b.chain, nil) + context := core.NewEVMBlockContext(block.Header(), parent.Header().ExcessDataGas, b.chain, nil) if idx == txIndex { return msg, context, statedb, release, nil } diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 808841ade11..1266d52b6dc 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -58,7 +58,7 @@ type callTrace struct { From common.Address `json:"from"` Gas *hexutil.Uint64 `json:"gas"` GasUsed *hexutil.Uint64 `json:"gasUsed"` - To common.Address `json:"to,omitempty"` + To *common.Address `json:"to,omitempty"` Input hexutil.Bytes `json:"input"` Output hexutil.Bytes `json:"output,omitempty"` Error string `json:"error,omitempty"` @@ -122,7 +122,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { } // Configure a blockchain with the given prestate var ( - signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) + signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) origin, _ = signer.Sender(tx) txContext = vm.TxContext{ Origin: origin, @@ -145,7 +145,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil) + msg, err := core.TransactionToMessage(tx, signer, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } @@ -219,8 +219,8 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); 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))) - msg, err := tx.AsMessage(signer, nil) + signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) + msg, err := core.TransactionToMessage(tx, signer, nil) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } @@ -314,7 +314,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil) + msg, err := core.TransactionToMessage(tx, signer, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go new file mode 100644 index 00000000000..feab911194b --- /dev/null +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -0,0 +1,213 @@ +package tracetest + +import ( + "encoding/json" + "fmt" + "math/big" + "os" + "path/filepath" + "reflect" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "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/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/tests" + + // Force-load the native, to trigger registration + "github.com/ethereum/go-ethereum/eth/tracers" +) + +// flatCallTrace is the result of a callTracerParity run. +type flatCallTrace struct { + Action flatCallTraceAction `json:"action"` + BlockHash common.Hash `json:"-"` + BlockNumber uint64 `json:"-"` + Error string `json:"error,omitempty"` + Result flatCallTraceResult `json:"result,omitempty"` + Subtraces int `json:"subtraces"` + TraceAddress []int `json:"traceAddress"` + TransactionHash common.Hash `json:"-"` + TransactionPosition uint64 `json:"-"` + Type string `json:"type"` + Time string `json:"-"` +} + +type flatCallTraceAction struct { + Author common.Address `json:"author,omitempty"` + RewardType string `json:"rewardType,omitempty"` + SelfDestructed common.Address `json:"address,omitempty"` + Balance hexutil.Big `json:"balance,omitempty"` + CallType string `json:"callType,omitempty"` + CreationMethod string `json:"creationMethod,omitempty"` + From common.Address `json:"from,omitempty"` + Gas hexutil.Uint64 `json:"gas,omitempty"` + Init hexutil.Bytes `json:"init,omitempty"` + Input hexutil.Bytes `json:"input,omitempty"` + RefundAddress common.Address `json:"refundAddress,omitempty"` + To common.Address `json:"to,omitempty"` + Value hexutil.Big `json:"value,omitempty"` +} + +type flatCallTraceResult struct { + Address common.Address `json:"address,omitempty"` + Code hexutil.Bytes `json:"code,omitempty"` + GasUsed hexutil.Uint64 `json:"gasUsed,omitempty"` + Output hexutil.Bytes `json:"output,omitempty"` +} + +// flatCallTracerTest defines a single test to check the call tracer against. +type flatCallTracerTest struct { + Genesis core.Genesis `json:"genesis"` + Context callContext `json:"context"` + Input string `json:"input"` + TracerConfig json.RawMessage `json:"tracerConfig"` + Result []flatCallTrace `json:"result"` +} + +func flatCallTracerTestRunner(tracerName string, filename string, dirPath string, t testing.TB) error { + // Call tracer test found, read if from disk + blob, err := os.ReadFile(filepath.Join("testdata", dirPath, filename)) + if err != nil { + return fmt.Errorf("failed to read testcase: %v", err) + } + test := new(flatCallTracerTest) + if err := json.Unmarshal(blob, test); err != nil { + return fmt.Errorf("failed to parse testcase: %v", err) + } + // Configure a blockchain with the given prestate + tx := new(types.Transaction) + if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { + return fmt.Errorf("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)) + origin, _ := signer.Sender(tx) + txContext := vm.TxContext{ + 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), + } + _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false) + + // Create the tracer, the EVM environment and run it + tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) + if err != nil { + return fmt.Errorf("failed to create call tracer: %v", err) + } + evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) + + msg, err := core.TransactionToMessage(tx, signer, nil) + if err != nil { + return fmt.Errorf("failed to prepare transaction for tracing: %v", err) + } + st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) + + if _, err = st.TransitionDb(); err != nil { + return fmt.Errorf("failed to execute transaction: %v", err) + } + + // Retrieve the trace result and compare against the etalon + res, err := tracer.GetResult() + if err != nil { + return fmt.Errorf("failed to retrieve trace result: %v", err) + } + ret := new([]flatCallTrace) + if err := json.Unmarshal(res, ret); err != nil { + return fmt.Errorf("failed to unmarshal trace result: %v", err) + } + if !jsonEqualFlat(ret, test.Result) { + t.Logf("tracer name: %s", tracerName) + + // uncomment this for easier debugging + // have, _ := json.MarshalIndent(ret, "", " ") + // want, _ := json.MarshalIndent(test.Result, "", " ") + // t.Logf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want)) + + // uncomment this for harder debugging <3 meowsbits + // lines := deep.Equal(ret, test.Result) + // for _, l := range lines { + // t.Logf("%s", l) + // t.FailNow() + // } + + t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result) + } + return nil +} + +// Iterates over all the input-output datasets in the tracer parity test harness and +// runs the Native tracer against them. +func TestFlatCallTracerNative(t *testing.T) { + testFlatCallTracer("flatCallTracer", "call_tracer_flat", t) +} + +func testFlatCallTracer(tracerName string, dirPath string, t *testing.T) { + files, err := os.ReadDir(filepath.Join("testdata", dirPath)) + if err != nil { + t.Fatalf("failed to retrieve tracer test suite: %v", err) + } + for _, file := range files { + if !strings.HasSuffix(file.Name(), ".json") { + continue + } + file := file // capture range variable + t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) { + t.Parallel() + + err := flatCallTracerTestRunner(tracerName, file.Name(), dirPath, t) + if err != nil { + t.Fatal(err) + } + }) + } +} + +// jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to +// comparison +func jsonEqualFlat(x, y interface{}) bool { + xTrace := new([]flatCallTrace) + yTrace := new([]flatCallTrace) + if xj, err := json.Marshal(x); err == nil { + json.Unmarshal(xj, xTrace) + } else { + return false + } + if yj, err := json.Marshal(y); err == nil { + json.Unmarshal(yj, yTrace) + } else { + return false + } + return reflect.DeepEqual(xTrace, yTrace) +} + +func BenchmarkFlatCallTracer(b *testing.B) { + files, err := filepath.Glob("testdata/call_tracer_flat/*.json") + if err != nil { + b.Fatalf("failed to read testdata: %v", err) + } + + for _, file := range files { + filename := strings.TrimPrefix(file, "testdata/call_tracer_flat/") + b.Run(camel(strings.TrimSuffix(filename, ".json")), func(b *testing.B) { + for n := 0; n < b.N; n++ { + err := flatCallTracerTestRunner("flatCallTracer", filename, "call_tracer_flat", b) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 03f06311a3b..082e45457b3 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -92,7 +92,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { } // Configure a blockchain with the given prestate var ( - signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) + signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) origin, _ = signer.Sender(tx) txContext = vm.TxContext{ Origin: origin, @@ -115,7 +115,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil) + msg, err := core.TransactionToMessage(tx, signer, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json index 40d240e4b82..95c5889269f 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json @@ -58,7 +58,6 @@ { "error": "contract creation code storage out of gas", "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", - "to": "0x0000000000000000000000000000000000000000", "gas": "0x39ff0", "gasUsed": "0x39ff0", "input": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182", diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json index ec10902b284..b5355f65fe9 100644 --- a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json +++ b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json @@ -50,7 +50,6 @@ "input": "0x02f9029d82053980849502f90085010c388d00832dc6c08080b90241608060405234801561001057600080fd5b50600060405161001f906100a2565b604051809103906000f08015801561003b573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c04062266040518163ffffffff1660e01b815260040160006040518083038186803b15801561008457600080fd5b505afa158015610098573d6000803e3d6000fd5b50505050506100af565b610145806100fc83390190565b603f806100bd6000396000f3fe6080604052600080fdfea264697066735822122077f7dbd3450d6e817079cf3fe27107de5768bb3163a402b94e2206b468eb025664736f6c63430008070033608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c040622614602d575b600080fd5b60336035565b005b60036002116076576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401606d906097565b60405180910390fd5b565b6000608360128360b5565b9150608c8260c6565b602082019050919050565b6000602082019050818103600083015260ae816078565b9050919050565b600082825260208201905092915050565b7f546869732063616c6c6564206661696c6564000000000000000000000000000060008201525056fea264697066735822122033f8d92e29d467e5ea08d0024eab0b36b86b8cdb3542c6e89dbaabeb8ffaa42064736f6c63430008070033c001a07566181071cabaf58b70fc41557eb813bfc7a24f5c58554e7fed0bf7c031f169a0420af50b5fe791a4d839e181a676db5250b415dfb35cb85d544db7a1475ae2cc", "result": { "from": "0x3623191d4ccfbbdf09e8ebf6382a1f8257417bc1", - "to": "0x0000000000000000000000000000000000000000", "gas": "0x2cd774", "gasUsed": "0x25590", "input": "0x608060405234801561001057600080fd5b50600060405161001f906100a2565b604051809103906000f08015801561003b573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c04062266040518163ffffffff1660e01b815260040160006040518083038186803b15801561008457600080fd5b505afa158015610098573d6000803e3d6000fd5b50505050506100af565b610145806100fc83390190565b603f806100bd6000396000f3fe6080604052600080fdfea264697066735822122077f7dbd3450d6e817079cf3fe27107de5768bb3163a402b94e2206b468eb025664736f6c63430008070033608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c040622614602d575b600080fd5b60336035565b005b60036002116076576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401606d906097565b60405180910390fd5b565b6000608360128360b5565b9150608c8260c6565b602082019050919050565b6000602082019050818103600083015260ae816078565b9050919050565b600082825260208201905092915050565b7f546869732063616c6c6564206661696c6564000000000000000000000000000060008201525056fea264697066735822122033f8d92e29d467e5ea08d0024eab0b36b86b8cdb3542c6e89dbaabeb8ffaa42064736f6c63430008070033", 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 new file mode 100644 index 00000000000..e54ede92b02 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json @@ -0,0 +1,64 @@ +{ + "genesis": { + "difficulty": "50486697699375", + "extraData": "0xd783010406844765746887676f312e362e32856c696e7578", + "gasLimit": "4788482", + "hash": "0xf6bbc5bbe34d5c93fd5b4712cd498d1026b8b0f586efefe7fe30231ed6b8a1a5", + "miner": "0xbcdfc35b86bedf72f0cda046a3c16829a2ef41d1", + "mixHash": "0xabca93555584c0463ee5c212251dd002bb3a93a157e06614276f93de53d4fdb8", + "nonce": "0xa64136fcb9c2d4ca", + "number": "1719576", + "stateRoot": "0xab5eec2177a92d633e282936af66c46e24cfa8f2fdc2b8155f33885f483d06f3", + "timestamp": "1466150166", + "totalDifficulty": "28295412423546970038", + "alloc": { + "0xf8bda96b67036ee48107f2a0695ea673479dda56": { + "balance": "0x1529e844f9ecdeec", + "nonce": "33", + "code": "0x", + "storage": {} + } + }, + "config": { + "chainId": 1, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 3000000, + "eip158Block": 0, + "ethash": {}, + "homesteadBlock": 1150000, + "byzantiumBlock": 8772000, + "constantinopleBlock": 9573000, + "petersburgBlock": 10500839, + "istanbulBlock": 10500839 + } + }, + "context": { + "number": "1719577", + "difficulty": "50486697732143", + "timestamp": "1466150178", + "gasLimit": "4788484", + "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" + }, + "input": "0xf874218504a817c800832318608080a35b620186a05a131560135760016020526000565b600080601f600039601f565b6000f31ba0575fa000a1f06659a7b6d3c7877601519a4997f04293f0dfa0eee6d8cd840c77a04c52ce50719ee2ff7a0c5753f4ee69c0340666f582dbb5148845a354ca726e4a", + "result": [ + { + "action": { + "from": "0xf8bda96b67036ee48107f2a0695ea673479dda56", + "gas": "0x22410c", + "init": "0x5b620186a05a131560135760016020526000565b600080601f600039601f565b6000f3", + "value": "0x0" + }, + "blockNumber": 1719577, + "result": { + "address": "0xb2e6a2546c45889427757171ab05b8b438525b42", + "code": "0x", + "gasUsed": "0x219202" + }, + "subtraces": 0, + "traceAddress": [], + "type": "create" + } + ] +} 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 new file mode 100644 index 00000000000..be198885cbc --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json @@ -0,0 +1,74 @@ +{ + "genesis": { + "difficulty": "4671584", + "extraData": "0xd683010b05846765746886676f312e3133856c696e7578", + "gasLimit": "9435026", + "hash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "mixHash": "0x3a44525624571c31344ba57780f7664098fe7cbeafe532bcdee76a23fc474ba0", + "nonce": "0x6dca647c00c72bbf", + "number": "1555278", + "stateRoot": "0x5f56d8323ee384b0c8d1de49d63e150e17283eea813483698362bc0ec9e0242a", + "timestamp": "1590795319", + "totalDifficulty": "2242614315030", + "alloc": { + "0x0000000000000000000000000000000000000004": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x62436e941792f02a5fb1", + "nonce": "265356", + "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": "1555279", + "difficulty": "4669303", + "timestamp": "1590795340", + "gasLimit": "9444238", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf86f83040c8c843b9aca0083019f7880809b60206000600060006013600462030d40f26002556000516000550081a2a086ad228c89ad9664287b12a5602a635a803506904f4ce39795990ac4f945cd57a025b30ea8042d773f6c5b13d7cc1b3979f9f10ee674410b6a2112ce840d0302dc", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xcf08", + "init": "0x60206000600060006013600462030d40f260025560005160005500" + }, + "result": { + "gasUsed": "0xf3bc", + "code": "0x", + "address": "0x5f8a7e007172ba80afbff1b15f800eb0b260f224" + }, + "traceAddress": [], + "subtraces": 0, + "transactionPosition": 74, + "transactionHash": "0x5ef60b27ac971c22a7d484e546e50093ca62300c8986d165154e47773764b6a4", + "blockNumber": 1555279, + "blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46", + "time": "209.346µs" + } + ] +} 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 new file mode 100644 index 00000000000..94b864ff497 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json @@ -0,0 +1,94 @@ +{ + "genesis": { + "difficulty": "4671584", + "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578", + "gasLimit": "9425823", + "hash": "0x27dd7d052dbc8a29cc5b9487e1e41d842e7a643fcaea4964caa22b834964acaf", + "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3", + "mixHash": "0xb4a050624f5d147fdf02857cbfd55da3ddc1451743acc5c163861584589c3034", + "nonce": "0x3c255875b17e0573", + "number": "1555277", + "stateRoot": "0x6290d79215a2eebc25d5e456b35876c6d78ffc1ea47bdd70e375ebb3cf325620", + "timestamp": "1590795308", + "totalDifficulty": "2242609643446", + "alloc": { + "0x0000000000000000000000000000000000000001": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x624329308610ab365fb1", + "nonce": "265194", + "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": "1555278", + "difficulty": "4671584", + "timestamp": "1590795319", + "gasLimit": "9435026", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf8ee83040bea843b9aca008301a7588080b8997f18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c600052601c6020527f73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f6040527feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549606052602060806080600060006001610bb7f260025560a060020a6080510660005560005432146001550081a1a05b9a162d84bfe84faa7c176e21c26c0083645d4dd0d566547b7be2c2da0b4259a05b37ff12a4c27634cb0da6008d9b69726d415ff4694f9bc38c7806eb1fb60ae9", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xcf08", + "init": "0x7f18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c600052601c6020527f73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f6040527feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549606052602060806080600060006001610bb7f260025560a060020a60805106600055600054321460015500" + }, + "result": { + "gasUsed": "0xf3e9", + "code": "0x", + "address": "0x568c19ecb14b87e4aec29b4d2d700a3ad3fd0613" + }, + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 141, + "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", + "blockNumber": 1555278, + "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b", + "time": "300.9µs" + }, + { + "type": "call", + "action": { + "from": "0x568c19ecb14b87e4aec29b4d2d700a3ad3fd0613", + "to": "0x0000000000000000000000000000000000000001", + "value": "0x0", + "gas": "0xbb7", + "input": "0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", + "callType": "callcode" + }, + "error": "out of gas", + "traceAddress": [ + 0 + ], + "subtraces": 0, + "transactionPosition": 141, + "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", + "blockNumber": 1555278, + "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 new file mode 100644 index 00000000000..506dc5ff68e --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json @@ -0,0 +1,90 @@ +{ + "genesis": { + "difficulty": "4683014", + "extraData": "0x537465762d63676574682d76312e31312e34", + "gasLimit": "9435044", + "hash": "0x3452ca5005cb73cd60dfa488a7b124251168e564491f80eb66765e79d78cfd95", + "miner": "0x415aa6292d1db797a467b22139704956c030e62f", + "mixHash": "0x6037612618507ae70c74a72bc2580253662971db959cfbc06d3f8527d4d01575", + "nonce": "0x314fc90dee5e39a2", + "number": "1555274", + "stateRoot": "0x795751f3f96a5de1fd3944ddd78cbfe4ef10491e1086be47609869a30929d0e5", + "timestamp": "1590795228", + "totalDifficulty": "2242595605834", + "alloc": { + "0x0000000000000000000000000000000000000009": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x6242e3ccf48e66425fb1", + "nonce": "264981", + "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": "1555275", + "difficulty": "4683014", + "timestamp": "1590795244", + "gasLimit": "9444256", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf87a83040b15843b9aca008301a0348080a636600060003760406103e8366000600060095af26001556103e851600255610408516003550081a1a0dd883fbbb489b640dadc8c1bf151767155228d0a1321f687f070f35f14374b05a02dd0ccb16a8de39bc8ee61381bbbbb54f0ab18422afd7b03c6163da1f5023934", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xcf08", + "init": "0x36600060003760406103e8366000600060095af26001556103e8516002556104085160035500" + }, + "error": "out of gas", + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 117, + "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", + "blockNumber": 1555275, + "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", + "time": "332.877µs" + }, + { + "type": "call", + "action": { + "from": "0x8832ef498070145c3a5b30f47fbca71fd7b1de9f", + "to": "0x0000000000000000000000000000000000000009", + "value": "0x0", + "gas": "0xc897", + "input": "0x", + "callType": "callcode" + }, + "error": "invalid input length", + "traceAddress": [ + 0 + ], + "subtraces": 0, + "transactionPosition": 117, + "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", + "blockNumber": 1555275, + "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 new file mode 100644 index 00000000000..b83236690c2 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json @@ -0,0 +1,67 @@ +{ + "context": { + "difficulty": "3755480783", + "gasLimit": "5401723", + "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", + "number": "2294702", + "timestamp": "1513676146" + }, + "genesis": { + "alloc": { + "0x13e4acefe6a6700604929946e70e6443e4e73447": { + "balance": "0xcf3e0938579f000", + "code": "0x", + "nonce": "9", + "storage": {} + }, + "0x7dc9c9730689ff0b0fd506c67db815f12d90a448": { + "balance": "0x0", + "code": "0x", + "nonce": "0", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3757315409", + "extraData": "0x566961425443", + "gasLimit": "5406414", + "hash": "0xae107f592eebdd9ff8d6ba00363676096e6afb0e1007a7d3d0af88173077378d", + "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", + "mixHash": "0xc927aa05a38bc3de864e95c33b3ae559d3f39c4ccd51cef6f113f9c50ba0caf1", + "nonce": "0x93363bbd2c95f410", + "number": "2294701", + "stateRoot": "0x6b6737d5bde8058990483e915866bd1578014baeff57bd5e4ed228a2bfad635c", + "timestamp": "1513676127", + "totalDifficulty": "7160808139332585" + }, + "input": "0xf907ef098504e3b29200830897be8080b9079c606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a1129a01060f46676a5dff6f407f0f51eb6f37f5c8c54e238c70221e18e65fc29d3ea65a0557b01c50ff4ffaac8ed6e5d31237a4ecbac843ab1bfe8bb0165a0060df7c54f", + "result": [ + { + "action": { + "from": "0x13e4acefe6a6700604929946e70e6443e4e73447", + "gas": "0x5e106", + "init": "0x606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a11", + "value": "0x0" + }, + "blockNumber": 2294702, + "result": { + "address": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448", + "code": "0x606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029", + "gasUsed": "0x897be" + }, + "subtraces": 0, + "traceAddress": [], + "type": "create" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/deep_calls.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/deep_calls.json new file mode 100644 index 00000000000..5931b408092 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/deep_calls.json @@ -0,0 +1,635 @@ +{ + "context": { + "difficulty": "117066904", + "gasLimit": "4712384", + "miner": "0x1977c248e1014cc103929dd7f154199c916e39ec", + "number": "25001", + "timestamp": "1479891545" + }, + "genesis": { + "alloc": { + "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38": { + "balance": "0x0", + "code": "0x606060405236156100825760e060020a600035046302d05d3f811461008a5780630accce061461009c5780631ab9075a146100c757806331ed274614610102578063645a3b7214610133578063772fdae314610155578063a7f4377914610180578063ae5f80801461019e578063c9bded21146101ea578063f905c15a14610231575b61023a610002565b61023c600054600160a060020a031681565b61023a600435602435604435606435608435600254600160a060020a03166000141561024657610002565b61023a600435600254600160a060020a03166000148015906100f8575060025433600160a060020a03908116911614155b156102f457610002565b61023a60043560243560443560643560843560a43560c435600254600160a060020a03166000141561031657610002565b61023a600435602435600254600160a060020a0316600014156103d057610002565b61023a600435602435604435606435608435600254600160a060020a03166000141561046157610002565b61023a60025433600160a060020a0390811691161461051657610002565b61023a6004356024356044356060828152600160a060020a0382169060ff8516907fa6c2f0913db6f79ff0a4365762c61718973b3413d6e40382e704782a9a5099f690602090a3505050565b61023a600435602435600160a060020a038116606090815260ff8316907fee6348a7ec70f74e3d6cba55a53e9f9110d180d7698e9117fc466ae29a43e34790602090a25050565b61023c60035481565b005b6060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061029d57610002565b60408051858152602081018390528151600160a060020a03858116939087169260ff8a16927f5a690ecd0cb15c1c1fd6b6f8a32df0d4f56cb41a54fea7e94020f013595de796929181900390910190a45050505050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061036d57610002565b6040805186815260208101869052808201859052606081018490529051600160a060020a03831691889160ff8b16917fd65d9ddafbad8824e2bbd6f56cc9f4ac27ba60737035c10a321ea2f681c94d47919081900360800190a450505050505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061042757610002565b60408051828152905183917fa9c6cbc4bd352a6940479f6d802a1001550581858b310d7f68f7bea51218cda6919081900360200190a25050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104b857610002565b80600160a060020a031684600160a060020a03168660ff167f69bdaf789251e1d3a0151259c0c715315496a7404bce9fd0b714674685c2cab78686604051808381526020018281526020019250505060405180910390a45050505050565b600254600160a060020a0316ff", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" + } + }, + "0x2cccf5e0538493c235d1c5ef6580f77d99e91396": { + "balance": "0x0", + "code": "0x606060405236156100775760e060020a600035046302d05d3f811461007f57806313bc6d4b146100915780633688a877146100b95780635188f9961461012f5780637eadc976146101545780638ad79680146101d3578063a43e04d814610238578063a7f437791461025e578063e16c7d981461027c575b61029f610002565b6102a1600054600160a060020a031681565b6102be600435600160a060020a03811660009081526002602052604090205460ff165b919050565b6102d26004356040805160208181018352600080835284815260038252835190849020805460026001821615610100026000190190911604601f8101849004840283018401909552848252929390929183018282801561037d5780601f106103525761010080835404028352916020019161037d565b61029f6004356024356000805433600160a060020a039081169116146104a957610002565b61034060043560008181526001602090815260408083205481517ff905c15a0000000000000000000000000000000000000000000000000000000081529151600160a060020a03909116928392839263f905c15a92600483810193919291829003018189876161da5a03f1156100025750506040515195945050505050565b60408051602060248035600481810135601f810185900485028601850190965285855261029f9581359591946044949293909201918190840183828082843750949650505050505050600054600160a060020a0390811633909116146104f657610002565b61029f6004355b600080548190600160a060020a0390811633909116146105a457610002565b61029f60005433600160a060020a0390811691161461072957610002565b6102a1600435600081815260016020526040902054600160a060020a03166100b4565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b820191906000526020600020905b81548152906001019060200180831161036057829003601f168201915b505050505090506100b4565b506000828152600160208181526040808420805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a038581168086526002909352818520805460ff191690941790935580517f1ab9075a0000000000000000000000000000000000000000000000000000000081523090931660048401525184939192631ab9075a926024828101939192829003018183876161da5a03f11561000257505060408051602081018690528082019290925243606083015260808083526003908301527f414444000000000000000000000000000000000000000000000000000000000060a0830152517f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d39181900360c00190a15b505050565b600083815260016020526040902054600160a060020a03838116911614156104d0576104a4565b600083815260016020526040812054600160a060020a031614610389576103898361023f565b600082815260036020908152604082208054845182855293839020919360026001831615610100026000190190921691909104601f90810184900483019391929186019083901061056a57805160ff19168380011785555b5061059a9291505b808211156105a05760008155600101610556565b8280016001018555821561054e579182015b8281111561054e57825182600050559160200191906001019061057c565b50505050565b5090565b600083815260016020526040812054600160a060020a031614156105c757610002565b50506000818152600160205260408082205481517fa7f437790000000000000000000000000000000000000000000000000000000081529151600160a060020a0391909116928392839263a7f4377992600483810193919291829003018183876161da5a03f11561000257505050600160005060008460001916815260200190815260200160002060006101000a815490600160a060020a0302191690556002600050600083600160a060020a0316815260200190815260200160002060006101000a81549060ff02191690557f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d383834360405180806020018560001916815260200184600160a060020a03168152602001838152602001828103825260038152602001807f44454c000000000000000000000000000000000000000000000000000000000081526020015060200194505050505060405180910390a1505050565b600054600160a060020a0316ff", + "nonce": "1", + "storage": { + "0x0684ac65a9fa32414dda56996f4183597d695987fdb82b145d722743891a6fe8": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", + "0x1cd76f78169a420d99346e3501dd3e541622c38a226f9b63e01cfebc69879dc7": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", + "0x8e54a4494fe5da016bfc01363f4f6cdc91013bb5434bd2a4a3359f13a23afa2f": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", + "0x94edf7f600ba56655fd65fca1f1424334ce369326c1dc3e53151dcd1ad06bc13": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xbbee47108b275f55f98482c6800f6372165e88b0330d3f5dae6419df4734366c": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", + "0xd38c0c4e84de118cfdcc775130155d83b8bbaaf23dc7f3c83a626b10473213bd": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xfb3aa5c655c2ec9d40609401f88d505d1da61afaa550e36ef5da0509ada257ba": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113" + } + }, + "0x3e9286eafa2db8101246c2131c09b49080d00690": { + "balance": "0x0", + "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063056d4470146100e957806316c66cc61461010c5780631ab9075a146101935780633ae1005c146101ce57806358541662146101fe5780635ed61af014610231578063644e3b791461025457806384dbac3b146102db578063949ae479146102fd5780639859387b14610321578063a7f4377914610340578063ab03fc261461035e578063e8161b7814610385578063e964d4e114610395578063f905c15a146103a5578063f92eb774146103ae575b6103be610002565b6103c0600054600160a060020a031681565b6103be6004356002546000908190600160a060020a031681141561040357610002565b6103dd60043560006108365b6040805160025460e360020a631c2d8fb30282527f636f6e747261637464620000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435600254600160a060020a03166000148015906101c4575060025433600160a060020a03908116911614155b1561088d57610002565b6103be600435602435604435606435600254600090819081908190600160a060020a03168114156108af57610002565b6103c0600435602435604435606435608435600254600090819081908190600160a060020a03168114156110e857610002565b6103be6004356002546000908190600160a060020a03168114156115ec57610002565b6103c06004356000611b635b6040805160025460e360020a631c2d8fb30282527f6d61726b6574646200000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435602435600254600160a060020a031660001415611bb557610002565b6103be600435602435600254600090600160a060020a0316811415611d2e57610002565b6103be600435600254600160a060020a031660001415611fc657610002565b6103be60025433600160a060020a0390811691161461207e57610002565b6103be600435602435604435600254600090600160a060020a031681141561208c57610002565b6103dd60043560006124b8610260565b6103c0600435600061250a610118565b6103f160035481565b6103f16004356000612561610260565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061046557610002565b8291506104e55b6040805160025460e360020a631c2d8fb30282527f63706f6f6c00000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f115610002575050604051519150505b90565b600160a060020a031663b2206e6d83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fb2206e6d0000000000000000000000000000000000000000000000000000000082526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f11561000257505060405151915061059b90506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f115610002575050506107355b6040805160025460e360020a631c2d8fb30282527f6c6f676d6772000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b50826120ee5b6040805160025460e360020a631c2d8fb30282527f6163636f756e7463746c0000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316630accce06600684600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150866040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050505050565b600160a060020a03166316c66cc6836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051519150505b919050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061091157610002565b87935061091c610260565b600160a060020a031663bdbdb08685600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fbdbdb0860000000000000000000000000000000000000000000000000000000082526004820152602481018a905290516044808301935060209282900301816000876161da5a03f1156100025750506040515193506109ca90506106ba565b600160a060020a03166381982a7a8885876040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610a3661046c565b600160a060020a03166308636bdb85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517f08636bdb000000000000000000000000000000000000000000000000000000008252600482015260248101889052604481019290925251606482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919450600160a060020a03871692506314baa1b6916024828101926000929190829003018183876161da5a03f11561000257505050610b3561046c565b600160a060020a0316630a3b6ede85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038d16602482015290516044808301935060209282900301816000876161da5a03f115610002575050604051519150610bd590506106ba565b600160a060020a031663d5b205ce87838b6040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610c41610118565b600160a060020a031663988db79c888a6040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050610ca5610260565b600160a060020a031663f4f2821b896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610d6f5b6040805160025460e360020a631c2d8fb30282527f747261646564620000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316635f539d69896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610dc2610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928e9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610ec5610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928d9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610fc8610639565b600160a060020a031663645a3b7285600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151905061101e610260565b600160a060020a031663f92eb77488600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f115610002575050505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061114a57610002565b604051600254600160a060020a0316908a908a908a908a908a90611579806125b38339018087600160a060020a0316815260200186600160a060020a03168152602001856000191681526020018481526020018381526020018281526020019650505050505050604051809103906000f092506111c5610118565b600160a060020a031663b9858a288a856040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611229610260565b600160a060020a0316635188f99689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611288610260565b600160a060020a031663bdbdb08689896040518360e060020a0281526004018083600019168152602001828152602001925050506020604051808303816000876161da5a03f1156100025750506040515192506112e590506106ba565b600160a060020a03166346d88e7d8a858a6040518460e060020a0281526004018084600160a060020a0316815260200183600160a060020a0316815260200182815260200193505050506000604051808303816000876161da5a03f115610002575050506113516106ba565b600160a060020a03166381982a7a8a84866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050506113bd61046c565b600160a060020a0316632b58469689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f1156100025750505061141c61046c565b600160a060020a03166308636bdb8984866040518460e060020a028152600401808460001916815260200183815260200182600160a060020a0316815260200193505050506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919350600160a060020a03861692506314baa1b6916024828101926000929190829003018183876161da5a03f115610002575050506114d3610639565b6040805160e160020a630566670302815260016004820152602481018b9052600160a060020a0386811660448301528c811660648301526000608483018190529251931692630accce069260a480840193919291829003018183876161da5a03f11561000257505050611544610639565b600160a060020a031663645a3b728961155b610260565b600160a060020a031663f92eb7748c6040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448084019360009350829003018183876161da5a03f1156100025750939a9950505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061164e57610002565b82915061165961046c565b600160a060020a0316630a3b6ede83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f1156100025750506040515191506116f990506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f1156100025750505061179b6106ba565b600160a060020a031663d653078983600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517ff1ff78a0000000000000000000000000000000000000000000000000000000008252915191929163f1ff78a09160048181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f1156100025750505061189f610260565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506118f2610118565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050611945610639565b600160a060020a0316630accce06600484600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da44689181870191602091908190038801816000876161da5a03f115610002575050506040518051906020015060006040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050611a48610639565b600160a060020a031663645a3b7283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611a9e610260565b600160a060020a031663f92eb77486600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b600160a060020a03166381738c59836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611c1757610002565b611c1f610260565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060405151159050611c7457610002565b611c7c610260565b600160a060020a0316632243118a836040518260e060020a02815260040180826000191681526020019150506000604051808303816000876161da5a03f11561000257505050611cca610639565b600160a060020a031663ae5f8080600184846040518460e060020a028152600401808481526020018360001916815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611d9057610002565b5081611d9a610260565b600160a060020a031663581d5d6084846040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506000604051808303816000876161da5a03f11561000257505050611df5610639565b600160a060020a0316630accce06600283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630566670302825260048201949094526024810193909352600160a060020a038816604484015260006064840181905260848401819052905160a4808501949293509091829003018183876161da5a03f11561000257505050611eab610639565b600160a060020a031663645a3b7282600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611f01610260565b600160a060020a031663f92eb77485600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061202857610002565b612030610118565b600160a060020a0316639859387b826040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505050565b600254600160a060020a0316ff5b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f11561000257505060405151151590506106b457610002565b600160a060020a031663d65307898383600160a060020a031663f1ff78a06040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fd6530789000000000000000000000000000000000000000000000000000000008252600160a060020a039485166004830152602482015292891660448401525160648381019360009350829003018183876161da5a03f115610002575050506121a5610118565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506121f8610cf4565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505061224b610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d028252915191928a9290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f1156100025750505080600160a060020a031663ea71b02d6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151600160a060020a031660001490506124b25761239f610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fea71b02d000000000000000000000000000000000000000000000000000000008252915191928a92909163ea71b02d91600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f115610002575050505b50505050565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663213fe2b7836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663f92eb774836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f115610002575050604051519150610888905056606060405260405160c08061157983396101206040819052825160805160a051935160e0516101005160008054600160a060020a03199081163317909155600180546005805484168817905560048a90556006869055600b8590556008849055909116861760a060020a60ff02191690554360038190556002558686526101408390526101608190529396929594919390929091600160a060020a033016917f76885d242fb71c6f74a7e717416e42eff4d96faf54f6de75c6a0a6bbd8890c6b91a230600160a060020a03167fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff600b600050546040518082815260200191505060405180910390a250505050505061145e8061011b6000396000f3606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", + "nonce": "16", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" + } + }, + "0x70c9217d814985faef62b124420f8dfbddd96433": { + "balance": "0x4ef436dcbda6cd4a", + "code": "0x", + "nonce": "1634", + "storage": {} + }, + "0x7986bad81f4cbd9317f5a46861437dae58d69113": { + "balance": "0x0", + "code": "0x6060604052361561008d5760e060020a600035046302d05d3f811461009557806316c66cc6146100a75780631ab9075a146100d7578063213fe2b7146101125780639859387b1461013f578063988db79c1461015e578063a7f4377914610180578063b9858a281461019e578063c8e40fbf146101c0578063f4f2821b146101e8578063f905c15a14610209575b610212610002565b610214600054600160a060020a031681565b600160a060020a0360043581811660009081526005602052604081205461023193168114610257575060016101e3565b610212600435600254600160a060020a0316600014801590610108575060025433600160a060020a03908116911614155b1561025f57610002565b610214600435600160a060020a03811660009081526004602052604081205460ff16151561027557610002565b610212600435600254600160a060020a03166000141561029b57610002565b610212600435602435600254600160a060020a03166000141561050457610002565b61021260025433600160a060020a0390811691161461056757610002565b610212600435602435600254600160a060020a03166000141561057557610002565b610231600435600160a060020a03811660009081526004602052604090205460ff165b919050565b610212600435600254600090600160a060020a031681141561072057610002565b61024560035481565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060006101e3565b60028054600160a060020a031916821790555b50565b50600160a060020a038181166000908152600460205260409020546101009004166101e3565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506102fe57610002565b600160a060020a03811660009081526004602052604090205460ff161515610272576040516104028061092e833901809050604051809103906000f06004600050600083600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600083600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555050565b600160a060020a03821660009081526004602052604090205460ff1615156104725760405161040280610d30833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a03811660009081526006602052604090208054600160a060020a031916831790555b5050565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506103b957610002565b600254600160a060020a0316ff5b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506105d857610002565b600160a060020a03821660009081526004602052604090205460ff1615156106915760405161040280611132833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a031660009081526005602052604090208054600160a060020a0319169091179055565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f115610002575050604051511515905061078357610002565b50600160a060020a0381811660009081526005602090815260408083205490931680835260049091529190205460ff161561080f576040600081812054825160e260020a632e72bafd028152600160a060020a03868116600483015293516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260056020526040812054909116146108545760406000908120600160a060020a0384169091528054600160a060020a03191690555b50600160a060020a0381811660009081526006602090815260408083205490931680835260049091529190205460ff16156108e657600160a060020a038181166000908152604080518183205460e260020a632e72bafd028252868516600483015291516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260066020526040812054909116146105005760406000908120600160a060020a0384169091528054600160a060020a0319169055505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", + "nonce": "7", + "storage": { + "0xffc4df2d4f3d2cffad590bed6296406ab7926ca9e74784f74a95191fa069a174": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" + } + }, + "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f": { + "balance": "0x0", + "code": "0x606060405236156100ae5760e060020a600035046302d05d3f81146100b65780631ab9075a146100c85780632b68bb2d146101035780634cc927d7146101c557806351a34eb81461028e57806356ccb6f0146103545780635928d37f1461041d578063599efa6b146104e9578063759297bb146105b2578063771d50e11461067e578063a7f4377914610740578063f905c15a1461075e578063f92eb77414610767578063febf661214610836575b610902610002565b610904600054600160a060020a031681565b610902600435600254600160a060020a03166000148015906100f9575060025433600160a060020a03908116911614155b1561092057610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061094257610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610a0d57610002565b61090260043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ae957610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610bbc57610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610c9657610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610de057610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ebb57610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f9e57610002565b61090260025433600160a060020a0390811691161461106957610002565b61090e60035481565b61090e60043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750506040805180517ff92eb774000000000000000000000000000000000000000000000000000000008252600482018790529151919350600160a060020a038416925063f92eb774916024828101926020929190829003018188876161da5a03f11561000257505060405151949350505050565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061107757610002565b005b6060908152602090f35b60408051918252519081900360200190f35b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5ed61af000000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152925190959286169350635ed61af092602483810193919291829003018183876161da5a03f115610002575050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fab03fc2600000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015260248301899052808816604484015292519095928616935063ab03fc2692606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f949ae47900000000000000000000000000000000000000000000000000000000825233600160a060020a0390811660048401526024830188905292519095928616935063949ae47992604483810193919291829003018183876161da5a03f11561000257505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f46d88e7d000000000000000000000000000000000000000000000000000000008252600160a060020a0380891660048401523381166024840152604483018890529251909592861693506346d88e7d92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5315cdde00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a16602484015260448301889052925190959286169350635315cdde92606483810193919291829003018183876161da5a03f115610002575050604080517f5928d37f00000000000000000000000000000000000000000000000000000000815233600160a060020a03908116600483015287166024820152604481018690529051635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fe68e401c00000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015280891660248401526044830188905292519095928616935063e68e401c92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5152f381000000000000000000000000000000000000000000000000000000008252600160a060020a03808a1660048401528089166024840152604483018890523381166064840152925190959286169350635152f38192608483810193919291829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f056d447000000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015292519095928616935063056d447092602483810193919291829003018183876161da5a03f115610002575050505050565b600254600160a060020a0316ff5b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f3ae1005c00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a166024840152808916604484015260648301889052925190959286169350633ae1005c92608483810193919291829003018183876161da5a03f11561000257505050505050505056", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" + } + }, + "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { + "balance": "0x0", + "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000006195", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5842545553440000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000" + } + }, + "0xcf00ffd997ad14939736f026006498e3f099baaf": { + "balance": "0x0", + "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063031e7f5d146100e95780631ab9075a1461010b5780632243118a1461014657806327aad68a1461016557806338a699a4146101da5780635188f996146101f8578063581d5d601461021e57806381738c5914610246578063977da54014610269578063a07421ce14610288578063a7f43779146102be578063bdbdb086146102dc578063e1c7111914610303578063f4f2821b14610325578063f905c15a1461034a578063f92eb77414610353575b610387610002565b610389600054600160a060020a031681565b610387600435602435600254600160a060020a0316600014156103a857610002565b610387600435600254600160a060020a031660001480159061013c575060025433600160a060020a03908116911614155b1561042957610002565b610387600435600254600160a060020a03166000141561044b57610002565b6102ac60043560008181526004602081815260408320547f524d81d3000000000000000000000000000000000000000000000000000000006060908152610100909104600160a060020a031692839263524d81d3926064928188876161da5a03f1156100025750506040515192506103819050565b61039c60043560008181526004602052604090205460ff165b919050565b6103876004356024356002546000908190600160a060020a031681141561079457610002565b61038760043560243560025460009081908190600160a060020a031681141561080457610002565b61038960043560008181526004602052604081205460ff1615156109e357610002565b610387600435600254600160a060020a0316600014156109fb57610002565b600435600090815260096020526040902054670de0b6b3a764000090810360243502045b60408051918252519081900360200190f35b61038760025433600160a060020a03908116911614610a9257610002565b600435600090815260086020526040902054670de0b6b3a7640000602435909102046102ac565b610387600435602435600254600160a060020a031660001415610aa057610002565b61038760043560025460009081908190600160a060020a0316811415610b3657610002565b6102ac60035481565b6102ac600435600081815260076020908152604080832054600690925290912054670de0b6b3a76400000204805b50919050565b005b600160a060020a03166060908152602090f35b15156060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506103fe57610002565b60008281526004602052604090205460ff16151561041b57610002565b600860205260406000205550565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104a157610002565b604080516000838152600460205291909120805460ff1916600117905561040280610de2833901809050604051809103906000f0600460005060008360001916815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555066470de4df8200006008600050600083600019168152602001908152602001600020600050819055506703782dace9d9000060096000506000836000191681526020019081526020016000206000508190555050565b600460005060008560001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151821415905061060057838152600660209081526040808320839055600790915281208190555b81600160a060020a0316630a3b0a4f846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050600160a060020a038316808252600560209081526040808420879055805160e160020a6364a81ff102815290518694670de0b6b3a7640000949363c9503fe29360048181019492939183900301908290876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008660001916815260200190815260200160002060008282825054019250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000866000191681526020019081526020016000206000828282505401925050819055505b50505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f11561000257505060405151151590506107e957610002565b8381526004602052604081205460ff16151561056657610002565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f115610002575050604051511515905061085957610002565b849250670de0b6b3a764000083600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575060408051805160e160020a6364a81ff102825291519189028590049650600481810192602092909190829003018188876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b9391600481810192602092909190829003018189876161da5a03f115610002575050506040518051906020015002049050806006600050600085600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750604080518051855260208681528286208054989098039097557f2e94420f00000000000000000000000000000000000000000000000000000000815290518896600483810193919291829003018187876161da5a03f115610002575050604080515183526020939093525020805490910190555050505050565b60409020546101009004600160a060020a03166101f3565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610a5157610002565b60008181526004602052604090205460ff161515610a6e57610002565b6040600020805474ffffffffffffffffffffffffffffffffffffffffff1916905550565b600254600160a060020a0316ff5b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610af657610002565b60008281526004602052604090205460ff161515610b1357610002565b670de0b6b3a7640000811115610b2857610002565b600960205260406000205550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f1156100025750506040515115159050610b8b57610002565b600160a060020a038416815260056020908152604080832054808452600490925282205490935060ff161515610bc057610002565b600460005060008460001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663b9caebf4856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506005600050600085600160a060020a0316815260200190815260200160002060005060009055839050600082600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519190911115905061078e57670de0b6b3a764000081600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008560001916815260200190815260200160002060008282825054039250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000856000191681526020019081526020016000206000828282505403925050819055505050505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", + "nonce": "3", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", + "0x3571d73f14f31a1463bd0a2f92f7fde1653d4e1ead7aedf4b0a5df02f16092ab": "0x0000000000000000000000000000000000000000000007d634e4c55188be0000", + "0x4e64fe2d1b72d95a0a31945cc6e4f4e524ac5ad56d6bd44a85ec7bc9cc0462c0": "0x000000000000000000000000000000000000000000000002b5e3af16b1880000" + } + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "117124093", + "extraData": "0xd5830105008650617269747986312e31322e31826d61", + "gasLimit": "4707788", + "hash": "0xad325e4c49145fb7a4058a68ac741cc8607a71114e23fc88083c7e881dd653e7", + "miner": "0x00714b9ac97fd6bd9325a059a70c9b9fa94ce050", + "mixHash": "0x0af918f65cb4af04b608fc1f14a849707696986a0e7049e97ef3981808bcc65f", + "nonce": "0x38dee147326a8d40", + "number": "25000", + "stateRoot": "0xc5d6bbcd46236fcdcc80b332ffaaa5476b980b01608f9708408cfef01b58bd5b", + "timestamp": "1479891517", + "totalDifficulty": "1895410389427" + }, + "input": "0xf88b8206628504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb80000000000000000000000000000000000000000000000280faf689c35ac00002aa0a7ee5b7877811bf671d121b40569462e722657044808dc1d6c4f1e4233ec145ba0417e7543d52b65738d9df419cbe40a708424f4d54b0fc145c0a64545a2bb1065", + "result": [ + { + "action": { + "callType": "call", + "from": "0x70c9217d814985faef62b124420f8dfbddd96433", + "gas": "0x37b38", + "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 25001, + "result": { + "gasUsed": "0x1810b", + "output": "0x" + }, + "subtraces": 2, + "traceAddress": [], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "gas": "0x31217", + "input": "0xe16c7d98636f6e7472616374617069000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f" + }, + "subtraces": 0, + "traceAddress": [0], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "gas": "0x30b4a", + "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", + "to": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0xedb7", + "output": "0x" + }, + "subtraces": 4, + "traceAddress": [1], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", + "gas": "0x2a68d", + "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690" + }, + "subtraces": 0, + "traceAddress": [1, 0], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", + "gas": "0x29f35", + "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", + "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0xf8d", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 2, + "traceAddress": [1, 1], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x23ac9", + "input": "0xe16c7d98636f6e7472616374646200000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113" + }, + "subtraces": 0, + "traceAddress": [1, 1, 0], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x23366", + "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", + "to": "0x7986bad81f4cbd9317f5a46861437dae58d69113", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x273", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [1, 1, 1], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", + "gas": "0x28a9e", + "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690" + }, + "subtraces": 0, + "traceAddress": [1, 2], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", + "gas": "0x283b9", + "input": "0x949ae479000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", + "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0xc51c", + "output": "0x" + }, + "subtraces": 12, + "traceAddress": [1, 3], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x21d79", + "input": "0x13bc6d4b000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x24d", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [1, 3, 0], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x2165b", + "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf" + }, + "subtraces": 0, + "traceAddress": [1, 3, 1], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x20ee1", + "input": "0x581d5d60000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", + "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x5374", + "output": "0x" + }, + "subtraces": 6, + "traceAddress": [1, 3, 2], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "gas": "0x1a8e8", + "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x24d", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [1, 3, 2, 0], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "gas": "0x1a2c6", + "input": "0xc9503fe2", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x3cb", + "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 2, 1], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "gas": "0x19b72", + "input": "0xc9503fe2", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x3cb", + "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 2, 2], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "gas": "0x19428", + "input": "0x6f265b93", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x305", + "output": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 2, 3], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "gas": "0x18d45", + "input": "0x2e94420f", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x229", + "output": "0x5842545553440000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 2, 4], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "gas": "0x1734e", + "input": "0x2e94420f", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x229", + "output": "0x5842545553440000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 2, 5], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x1b6c1", + "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38" + }, + "subtraces": 0, + "traceAddress": [1, 3, 3], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x1af69", + "input": "0x2e94420f", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x229", + "output": "0x5842545553440000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 4], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x1a91d", + "input": "0x0accce0600000000000000000000000000000000000000000000000000000000000000025842545553440000000000000000000000000000000000000000000000000000000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x12fa", + "output": "0x" + }, + "subtraces": 1, + "traceAddress": [1, 3, 5], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", + "gas": "0x143a5", + "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x24d", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [1, 3, 5, 0], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x19177", + "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38" + }, + "subtraces": 0, + "traceAddress": [1, 3, 6], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x18a22", + "input": "0x2e94420f", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x229", + "output": "0x5842545553440000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 7], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x18341", + "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x334", + "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf" + }, + "subtraces": 0, + "traceAddress": [1, 3, 8], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x17bec", + "input": "0x2e94420f", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x229", + "output": "0x5842545553440000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 9], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x1764e", + "input": "0xf92eb7745842545553440000000000000000000000000000000000000000000000000000", + "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x45c", + "output": "0x00000000000000000000000000000000000000000000002816d180e30c390000" + }, + "subtraces": 0, + "traceAddress": [1, 3, 10], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", + "gas": "0x16e62", + "input": "0x645a3b72584254555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002816d180e30c390000", + "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0xebb", + "output": "0x" + }, + "subtraces": 1, + "traceAddress": [1, 3, 11], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", + "gas": "0x108ba", + "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", + "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x24d", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [1, 3, 11, 0], + "type": "call" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall.json new file mode 100644 index 00000000000..3a03ffc0fa9 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall.json @@ -0,0 +1,120 @@ +{ + "context": { + "difficulty": "31927752", + "gasLimit": "4707788", + "miner": "0x5659922ce141eedbc2733678f9806c77b4eebee8", + "number": "11495", + "timestamp": "1479735917" + }, + "genesis": { + "alloc": { + "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff": { + "balance": "0x0", + "code": "0x606060405236156100825760e060020a60003504630a0313a981146100875780630a3b0a4f146101095780630cd40fea1461021257806329092d0e1461021f5780634cd06a5f146103295780635dbe47e8146103395780637a9e5410146103d9578063825db5f7146103e6578063a820b44d146103f3578063efa52fb31461047a575b610002565b34610002576104fc600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a26333556e849091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f415610002575050604051519150505b919050565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f21ce24d4000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926321ce24d49260448082019391829003018186803b156100025760325a03f415610002575050505b50565b3461000257610512600181565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f89489a87000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926389489a879260448082019391829003018186803b156100025760325a03f4156100025750505061020f565b3461000257610528600435610403565b34610002576104fc600435604080516000602091820181905282517f7d65837a00000000000000000000000000000000000000000000000000000000815260048101829052600160a060020a0385166024820152925190927342b02b5deeb78f34cd5ac896473b63e6c99a71a292637d65837a92604480840193829003018186803b156100025760325a03f4156100025750506040515191506101049050565b3461000257610512600c81565b3461000257610512600081565b3461000257610528600061055660005b600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263685a1f3c9091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b346100025761053a600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263f775b6b59091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b604080519115158252519081900360200190f35b005b6040805160ff9092168252519081900360200190f35b60408051918252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b90509056", + "nonce": "1", + "storage": { + "0x4d140b25abf3c71052885c66f73ce07cff141c1afabffdaf5cba04d625b7ebcc": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + }, + "0x269296dddce321a6bcbaa2f0181127593d732cba": { + "balance": "0x0", + "code": "0x606060405236156101275760e060020a60003504630cd40fea811461012c578063173825d9146101395780631849cb5a146101c7578063285791371461030f5780632a58b3301461033f5780632cb0d48a146103565780632f54bf6e1461036a578063332b9f061461039d5780633ca8b002146103c55780633df4ddf4146103d557806341c0e1b5146103f457806347799da81461040557806362a51eee1461042457806366907d13146104575780637065cb48146104825780637a9e541014610496578063825db5f7146104a3578063949d225d146104b0578063a51687df146104c7578063b4da4e37146104e6578063b4e6850b146104ff578063bd7474ca14610541578063e75623d814610541578063e9938e1114610555578063f5d241d314610643575b610002565b3461000257610682600181565b34610002576106986004356106ff335b60006001600a9054906101000a9004600160a060020a0316600160a060020a0316635dbe47e8836000604051602001526040518260e060020a0281526004018082600160a060020a03168152602001915050602060405180830381600087803b156100025760325a03f1156100025750506040515191506103989050565b3461000257604080516101008082018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a0360043581168752600586529589902089519788018a528054808816808a52605060020a91829004600160a060020a0316978a01889052600183015463ffffffff8082169d8c018e905264010000000082048116988c01899052604060020a90910416958a018690526002830154948a01859052600390920154808916938a01849052049096169690970186905293969495949293604080516001605060020a03998a16815297891660208901529590971686860152600160a060020a03909316606086015263ffffffff9182166080860152811660a08501521660c083015260e08201929092529051908190036101000190f35b346100025761069a60043560018054600091829160ff60f060020a909104161515141561063d5761072833610376565b34610002576106ae6004546001605060020a031681565b34610002576106986004356108b333610149565b346100025761069a6004355b600160a060020a03811660009081526002602052604090205460ff1615156001145b919050565b34610002576106986001805460ff60f060020a9091041615151415610913576108ed33610376565b346100025761069a600435610149565b34610002576106ae6003546001605060020a03605060020a9091041681565b346100025761069861091533610149565b34610002576106ae6003546001605060020a0360a060020a9091041681565b346100025761069a60043560243560018054600091829160ff60f060020a909104161515141561095e5761092633610376565b34610002576106986004356001805460ff60f060020a909104161515141561072557610a8b33610376565b3461000257610698600435610aa533610149565b3461000257610682600c81565b3461000257610682600081565b34610002576106ae6003546001605060020a031681565b34610002576106ca600154600160a060020a03605060020a9091041681565b346100025761069a60015460ff60f060020a9091041681565b346100025761069a60043560243560443560643560843560a43560c43560018054600091829160ff60f060020a9091041615151415610b5857610ad233610376565b3461000257610698600435610bd633610149565b34610002576106e6600435604080516101008181018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a03808b168752600586529589902089519788018a5280548088168952600160a060020a03605060020a918290041696890196909652600181015463ffffffff8082169b8a019b909b5264010000000081048b1695890195909552604060020a90940490981691860182905260028301549086015260039091015480841696850196909652940416918101919091525b50919050565b346100025761069a60043560243560443560643560843560a43560018054600091829160ff60f060020a9091041615151415610c8e57610bfb33610376565b6040805160ff9092168252519081900360200190f35b005b604080519115158252519081900360200190f35b604080516001605060020a039092168252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b6040805163ffffffff9092168252519081900360200190f35b1561012757600160a060020a0381166000908152600260205260409020805460ff191690555b50565b1561063d57506001605060020a0380831660009081526005602052604090208054909116151561075b576000915061063d565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610817905b8051600354600090819060016001605060020a0390911611610c995760038054605060020a60f060020a0319169055610ddf565b600380546001605060020a031981166000196001605060020a03928316011782558416600090815260056020526040812080547fffff000000000000000000000000000000000000000000000000000000000000168155600181810180546bffffffffffffffffffffffff191690556002820192909255909101805473ffffffffffffffffffffffffffffffffffffffff19169055915061063d565b1561012757600180547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f060020a8302179055610725565b1561091357600480546001605060020a031981166001605060020a039091166001011790555b565b156101275733600160a060020a0316ff5b1561095e57506001605060020a03808416600090815260056020526040902080549091161515610965576000915061095e565b600191505b5092915050565b60038101546001605060020a0384811691161415610986576001915061095e565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610a12906107e3565b61095983825b80546003546001605060020a0391821691600091161515610de55760038054605060020a60a060020a031916605060020a84021760a060020a69ffffffffffffffffffff02191660a060020a84021781558301805473ffffffffffffffffffffffffffffffffffffffff19169055610ddf565b1561072557600480546001605060020a0319168217905550565b1561012757600160a060020a0381166000908152600260205260409020805460ff19166001179055610725565b15610b5857506001605060020a038088166000908152600560205260409020805490911615610b645760009150610b58565b6004546001605060020a0390811690891610610b3057600480546001605060020a03191660018a011790555b6003805460016001605060020a03821681016001605060020a03199092169190911790915591505b50979650505050505050565b80546001605060020a0319168817605060020a60f060020a031916605060020a880217815560018101805463ffffffff1916871767ffffffff0000000019166401000000008702176bffffffff00000000000000001916604060020a860217905560028101839055610b048982610a18565b156101275760018054605060020a60f060020a031916605060020a8302179055610725565b15610c8e57506001605060020a03808816600090815260056020526040902080549091161515610c2e5760009150610c8e565b8054605060020a60f060020a031916605060020a88021781556001808201805463ffffffff1916881767ffffffff0000000019166401000000008802176bffffffff00000000000000001916604060020a87021790556002820184905591505b509695505050505050565b6003546001605060020a03848116605060020a909204161415610d095760e084015160038054605060020a928302605060020a60a060020a031990911617808255919091046001605060020a031660009081526005602052604090200180546001605060020a0319169055610ddf565b6003546001605060020a0384811660a060020a909204161415610d825760c08401516003805460a060020a92830260a060020a69ffffffffffffffffffff021990911617808255919091046001605060020a03166000908152600560205260409020018054605060020a60a060020a0319169055610ddf565b505060c082015160e08301516001605060020a0380831660009081526005602052604080822060039081018054605060020a60a060020a031916605060020a8702179055928416825290200180546001605060020a031916831790555b50505050565b6001605060020a0384161515610e6457600380546001605060020a03605060020a9182900481166000908152600560205260409020830180546001605060020a0319908116871790915583548785018054918590049093168402605060020a60a060020a03199182161790911690915582549185029116179055610ddf565b506001605060020a038381166000908152600560205260409020600390810180549185018054605060020a60a060020a0319908116605060020a94859004909516808502959095176001605060020a0319168817909155815416918402919091179055801515610ef4576003805460a060020a69ffffffffffffffffffff02191660a060020a8402179055610ddf565b6003808401546001605060020a03605060020a9091041660009081526005602052604090200180546001605060020a031916831790555050505056", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000113204f5d64c28326fd7bd05fd4ea855302d7f2ff00000000000000000000" + } + }, + "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2": { + "balance": "0x0", + "code": "0x6504032353da7150606060405236156100695760e060020a60003504631bf7509d811461006e57806321ce24d41461008157806333556e84146100ec578063685a1f3c146101035780637d65837a1461011757806389489a8714610140578063f775b6b5146101fc575b610007565b61023460043560006100fd82600061010d565b610246600435602435600160a060020a03811660009081526020839052604081205415156102cb57826001016000508054806001018281815481835581811511610278576000838152602090206102789181019083015b808211156102d057600081556001016100d8565b610248600435602435600182015481105b92915050565b6102346004356024355b60018101906100fd565b610248600435602435600160a060020a03811660009081526020839052604090205415156100fd565b61024660043560243580600160a060020a031632600160a060020a03161415156101f857600160a060020a038116600090815260208390526040902054156101f857600160a060020a038116600090815260208390526040902054600183018054909160001901908110156100075760009182526020808320909101805473ffffffffffffffffffffffffffffffffffffffff19169055600160a060020a038316825283905260408120556002820180546000190190555b5050565b61025c60043560243560008260010160005082815481101561000757600091825260209091200154600160a060020a03169392505050565b60408051918252519081900360200190f35b005b604080519115158252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b50505060009283526020808420909201805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a0385168352908590526040909120819055600284018054600101905590505b505050565b509056", + "nonce": "1", + "storage": {} + }, + "0xa529806c67cc6486d4d62024471772f47f6fd672": { + "balance": "0x67820e39ac8fe9800", + "code": "0x", + "nonce": "68", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "31912170", + "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", + "gasLimit": "4712388", + "hash": "0x0855914bdc581bccdc62591fd438498386ffb59ea4d5361ed5c3702e26e2c72f", + "miner": "0x334391aa808257952a462d1475562ee2106a6c90", + "mixHash": "0x64bb70b8ca883cadb8fbbda2c70a861612407864089ed87b98e5de20acceada6", + "nonce": "0x684129f283aaef18", + "number": "11494", + "stateRoot": "0x7057f31fe3dab1d620771adad35224aae43eb70e94861208bc84c557ff5b9d10", + "timestamp": "1479735912", + "totalDifficulty": "90744064339" + }, + "input": "0xf889448504a817c800832dc6c094269296dddce321a6bcbaa2f0181127593d732cba80a47065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e29a080ed81e4c5e9971a730efab4885566e2c868cd80bd4166d0ed8c287fdf181650a069d7c49215e3d4416ad239cd09dbb71b9f04c16b33b385d14f40b618a7a65115", + "result": [ + { + "action": { + "callType": "call", + "from": "0xa529806c67cc6486d4d62024471772f47f6fd672", + "gas": "0x2d6e28", + "input": "0x7065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e", + "to": "0x269296dddce321a6bcbaa2f0181127593d732cba", + "value": "0x0" + }, + "blockNumber": 11495, + "result": { + "gasUsed": "0xbd55", + "output": "0x" + }, + "subtraces": 1, + "traceAddress": [], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x269296dddce321a6bcbaa2f0181127593d732cba", + "gas": "0x2cae73", + "input": "0x5dbe47e8000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", + "to": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0xa9d", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 1, + "traceAddress": [0], + "type": "call" + }, + { + "action": { + "callType": "delegatecall", + "from": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", + "gas": "0x2bf459", + "input": "0x7d65837a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", + "to": "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2", + "value": "0x0" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x2aa", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [0, 0], + "type": "call" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall_parent_value.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall_parent_value.json new file mode 100644 index 00000000000..800a6a4288d --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall_parent_value.json @@ -0,0 +1,103 @@ +{ + "genesis": { + "number": "566098", + "hash": "0xba134562590a59291892395a29c5088899c2c64d720135dad88f7f076cf55f5f", + "nonce": "0x4b281be9594e3eb3", + "mixHash": "0xdb4ec386166d9c0dc9ba147755ecbb87af9f0a22563cbda02c799efa4e29db6e", + "stateRoot": "0xfc01993ad96a8fb8790a093cea4f505f8db1b0e1143c5f57bb1d173db0baa9e3", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "difficulty": "1926740", + "totalDifficulty": "482216286599", + "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", + "gasLimit": "19388354", + "timestamp": "1577558314", + "alloc": { + "0x6ab9dd83108698b9ca8d03af3c7eb91c0e54c3fc": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0xcbd5b9b25d1c38c2aad", + "nonce": "134969", + "code": "0x", + "storage": {} + }, + "0x91765918420bcb5ad22ee0997abed04056705798": { + "balance": "0x0", + "nonce": "1", + "code": "0x366000803760206000366000736ab9dd83108698b9ca8d03af3c7eb91c0e54c3fc60325a03f41560015760206000f3", + "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": "566099", + "difficulty": "1927680", + "timestamp": "1577558317", + "gasLimit": "19369422", + "miner": "0x774c398d763161f55b66a646f17edda4addad2ca" + }, + "input": "0xf87983020f3985746a52880083015f909491765918420bcb5ad22ee0997abed04056705798888ac7230489e80000884e45375a4741394181a1a04b7260723fd02830754916b3bdf1537b6a851a7ae27c7e9296cfe1fc8275ec08a049d32158988eb717d61b4503b27c7583037c067daba1eb56f4bdfafc1b0045f6", + "result": [ + { + "action": { + "callType": "call", + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "gas": "0x10b68", + "input": "0x4e45375a47413941", + "to": "0x91765918420bcb5ad22ee0997abed04056705798", + "value": "0x8ac7230489e80000" + }, + "blockHash": "0xb05cc5c8f11df2b5d53ced342ee79e2805785f04c2f40add4539f27bd349f74e", + "blockNumber": 566099, + "result": { + "gasUsed": "0x5721", + "output": "0x4e45375a47413941000000000000000000000000000000000000000000000000" + }, + "subtraces": 1, + "traceAddress": [], + "transactionHash": "0x6e26dffe2f66186f03a2c36a16a4cd9724d07622c83746f1e35f988515713d4b", + "transactionPosition": 10, + "type": "call" + }, + { + "action": { + "callType": "delegatecall", + "from": "0x91765918420bcb5ad22ee0997abed04056705798", + "gas": "0x10463", + "input": "0x4e45375a47413941", + "to": "0x6ab9dd83108698b9ca8d03af3c7eb91c0e54c3fc", + "value": "0x8ac7230489e80000" + }, + "blockHash": "0xb05cc5c8f11df2b5d53ced342ee79e2805785f04c2f40add4539f27bd349f74e", + "blockNumber": 566099, + "result": { + "gasUsed": "0x0", + "output": "0x" + }, + "subtraces": 0, + "traceAddress": [ + 0 + ], + "transactionHash": "0x6e26dffe2f66186f03a2c36a16a4cd9724d07622c83746f1e35f988515713d4b", + "transactionPosition": 10, + "type": "call" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json new file mode 100644 index 00000000000..3b44a5e2cd9 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json @@ -0,0 +1,95 @@ +{ + "genesis": { + "difficulty": "4683014", + "extraData": "0x537465762d63676574682d76312e31312e34", + "gasLimit": "9435044", + "hash": "0x3452ca5005cb73cd60dfa488a7b124251168e564491f80eb66765e79d78cfd95", + "miner": "0x415aa6292d1db797a467b22139704956c030e62f", + "mixHash": "0x6037612618507ae70c74a72bc2580253662971db959cfbc06d3f8527d4d01575", + "nonce": "0x314fc90dee5e39a2", + "number": "1555274", + "stateRoot": "0x795751f3f96a5de1fd3944ddd78cbfe4ef10491e1086be47609869a30929d0e5", + "timestamp": "1590795228", + "totalDifficulty": "2242595605834", + "alloc": { + "0x0000000000000000000000000000000000000001": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x6242e3ccf48e66425fb1", + "nonce": "264882", + "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": "1555275", + "difficulty": "4683014", + "timestamp": "1590795244", + "gasLimit": "9444256", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf9011583040ab2843b9aca008301a9c88080b8c0601b565b6000555b005b630badf00d6003565b63c001f00d6003565b7319e7e376e7c213b7e7e7e46cc70a5dd086daff2a7f22ae6da6b482f9b1b19b0b897c3fd43884180a1c5ee361e1107a1bc635649dda600052601b603f537f16433dce375ce6dc8151d3f0a22728bc4a1d9fd6ed39dfd18b4609331937367f6040527f306964c0cf5d74f04129fdc60b54d35b596dde1bf89ad92cb4123318f4c0e40060605260206080607f60006000600161fffff2156007576080511460125760095681a1a07682fc43dbe1fb13c6474f5e70e121c826dd996168d8bb1d8ca7a63470127b46a00a25b308ba417b7770899e8f98a3f0c14aa9bf7db0edacfe4e78d00dbbd3c31e", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xcf08", + "init": "0x601b565b6000555b005b630badf00d6003565b63c001f00d6003565b7319e7e376e7c213b7e7e7e46cc70a5dd086daff2a7f22ae6da6b482f9b1b19b0b897c3fd43884180a1c5ee361e1107a1bc635649dda600052601b603f537f16433dce375ce6dc8151d3f0a22728bc4a1d9fd6ed39dfd18b4609331937367f6040527f306964c0cf5d74f04129fdc60b54d35b596dde1bf89ad92cb4123318f4c0e40060605260206080607f60006000600161fffff21560075760805114601257600956" + }, + "result": { + "gasUsed": "0x137e5", + "code": "0x", + "address": "0x1a05d76017ca02010533a470e05e8925a0380d8f" + }, + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 18, + "transactionHash": "0xc1c42a325856d513523aec464811923b2e2926f54015c7ba37877064cf889803", + "blockNumber": 1555275, + "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", + "time": "453.925µs" + }, + { + "type": "call", + "action": { + "from": "0x1a05d76017ca02010533a470e05e8925a0380d8f", + "to": "0x0000000000000000000000000000000000000001", + "value": "0x0", + "gas": "0xc8c6", + "input": "0x22ae6da6b482f9b1b19b0b897c3fd43884180a1c5ee361e1107a1bc635649dda000000000000000000000000000000000000000000000000000000000000001b16433dce375ce6dc8151d3f0a22728bc4a1d9fd6ed39dfd18b4609331937367f306964c0cf5d74f04129fdc60b54d35b596dde1bf89ad92cb4123318f4c0e4", + "callType": "callcode" + }, + "result": { + "gasUsed": "0xbb8", + "output": "0x00000000000000000000000019e7e376e7c213b7e7e7e46cc70a5dd086daff2a" + }, + "traceAddress": [0], + "subtraces": 0, + "transactionPosition": 18, + "transactionHash": "0xc1c42a325856d513523aec464811923b2e2926f54015c7ba37877064cf889803", + "blockNumber": 1555275, + "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/include_precompiled.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/include_precompiled.json new file mode 100644 index 00000000000..d33375bfd22 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/include_precompiled.json @@ -0,0 +1,832 @@ +{ + "genesis": { + "number": "559197", + "hash": "0x0742a2bfab0452e2c634f3685b7e49ceb065c7000609b2b73f086e01fd1dfb58", + "nonce": "0x3060ad521440e1c2", + "mixHash": "0x59e7d4ae6cc3c38d23dac3f869b21984c7ba8f38070f4116a4941d9c403b6299", + "stateRoot": "0x68418fb5cf4afa9b807dc079e8cdde0e148ac2c8afb378e675465b5bed1fbd02", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "difficulty": "1813945", + "totalDifficulty": "469107641961", + "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", + "gasLimit": "6321166", + "timestamp": "1577471202", + "alloc": { + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0xc5e6fdae52af83f7e28", + "nonce": "77947", + "code": "0x", + "storage": {} + }, + "0x774c398d763161f55b66a646f17edda4addad2ca": { + "balance": "0xf09ef316eff819ee488", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc": { + "balance": "0x0", + "nonce": "1", + "code": "0x60006121df537c01000000000000000000000000000000000000000000000000000000006000350463b041b2858114156100d257600435604052780100000000000000000000000000000000000000000000000060606060599059016000905260038152604051816020015260008160400152809050205404606052606051151561008f57600060a052602060a0f35b604051601c604459905901600090520163e0e9a17b601c82035260605160048201526020610100602483600030602d5a03f1506101005190501460c052602060c0f35b632cce81aa81141561019957600435610120526001610120511280156100f85780610143565b78010000000000000000000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540461012051135b905015610157576000610180526020610180f35b601c604459905901600090520163e0e9a17b601c82035261012051600482015260206101c0602483600030602d5a03f1506101c05190506101a05260206101a0f35b63e0e9a17b8114156102e957600435610120526604000000000002546101e0526007610200525b610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540413156102da575b6102005160050a610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e051816020015260008160400152809050205404031215610269576000610200511361026c565b60005b1561028157600161020051036102005261020b565b7c01000000000000000000000000000000000000000000000000000000006102005160200260020a606060605990590160009052600381526101e05181602001526001816040015280905020540204546101e0526101c0565b6101e051610280526020610280f35b63cef887b08114156103e757365990590160009052366004823760043560208201016102c0526024356102e052506060601c61014c5990590160009052016390fa337d601c8203526102c0516020601f602083035101046020026020018360048401526020820360648401528060c8840152808401935050506102e051602482015233604482015281600401599059016000905260648160648460006004601cf161039057fe5b60648101925060c882015180808582606487015160006004600a8705601201f16103b657fe5b5080840193505080830360206103a08284600030602d5a03f1506103a0519050905090509050610300526020610300f35b6390fa337d81141561065f57365990590160009052366004823760043560208201016102c0526024356102e0526044356103e052505a610400526020601c608c599059016000905201632b861629601c8203526102c0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161048a57fe5b602481019250604882015180808582602487015160006004600a8705601201f16104b057fe5b5080840193505080830360206104408284600030602d5a03f15061044051905090509050905061042052610420511561065e576102c05160208103516020599059016000905260208183856000600287604801f150805190509050905061046052602059905901600090526020816020610460600060026068f1508051905060005b6020811215610552578181601f031a816105400153600181019050610532565b5050610540516101e0526102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020555a61058052700100000000000000000000000000000000660400000000000154046105a0526104006105a0516103ff02056105c0526104006105a05161040102056105e0526105c0513a12156105f6576105c05161060052610615565b6105e0513a131561060e576105e05161060052610614565b3a610600525b5b6105805161040051036106005160020202610620526106205170010000000000000000000000000000000061060051021766040000000000015561042051610640526020610640f35b5b63d467ae0381141561073257600435604052602435610660526106605134121515610725576000341315610718576c01000000000000000000000000606060605990590160009052600381526040518160200152600381604001528090502054046103e0526000600060006000346103e051611388f115156106dd57fe5b601c60405990590160009052013481526103e0517f15e746bf513b8a58e4265cc1162d7fc445da5c9b1928d7cfcde2582735d4677f602083a2505b60016106a05260206106a0f35b60006106c05260206106c0f35b63ea4971ee811415610851576004356101e0526024356102e0526044356103e052601c606459905901600090520163d467ae03601c8203526101e05160048201526604000000000001546fffffffffffffffffffffffffffffffff16602482015260206106e060448334306123555a03f1506106e051905015156107bd576000610700526020610700f35b606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166102e0511215610844576102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020556001610760526020610760f35b6000610780526020610780f35b6387def0818114156108a3576004356101e0526c01000000000000000000000000606060605990590160009052600381526101e0518160200152600381604001528090502054046107a05260206107a0f35b630aece23c8114156108f4576004356101e052606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166107e05260206107e0f35b63fa14df6b811415610926576604000000000001546fffffffffffffffffffffffffffffffff16610820526020610820f35b63b8c48f8c811415610b1b576004356101e0526024356108405260443561086052600066040000000000035414151561096a576000610880526020610880f3610976565b60016604000000000003555b6101e051660400000000000255606060605990590160009052600381526101e05181602001526000816040015280905020546108a0526108a0610840518060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a600783015350506108a051606060605990590160009052600381526101e0518160200152600081604001528090502055606060605990590160009052600381526101e051816020015260008160400152809050205461094052601061094001610860518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061094051606060605990590160009052600381526101e051816020015260008160400152809050205560016109e05260206109e0f35b632b86162981141561179457365990590160009052366004823760043560208201016102c0525060483560005b6020811215610b68578181601f031a81610a600153600181019050610b48565b5050610a6051610a00526102c05160208103516020599059016000905260208183856000600287604801f1508051905090509050610a8052602059905901600090526020816020610a80600060026068f1508051905060005b6020811215610be1578181601f031a81610b600153600181019050610bc1565b5050610b60516101e05270010000000000000000000000000000000070010000000000000000000000000000000060606060599059016000905260038152610a005181602001526000816040015280905020540204610b8052610b80511515610c8b57601c602059905901600090520161272e6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610bc0526020610bc0f35b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204610be0526000610be051141515610d2e57601c60205990590160009052016127386101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610c20526020610c20f35b608c35610c40526301000000610c405160031a0262010000610c405160021a02610100610c405160011a02610c405160001a010101610c60526301000000610c605104610ca05262ffffff610c605116610cc0526003610ca051036101000a610cc05102610c805260006101e0511315610db057610c80516101e05112610db3565b60005b1561174d57780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a00518160200152600081604001528090502054046001016101205260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610d405250610d405160081a610d405160091a61010002610d4051600a1a6201000002610d4051600b1a630100000002010101610d005260006107e0610120510614158015610e7e5780610e8b565b6001660400000000000054145b905015610f0257610d0051610c6051141515610eae576000610d00511415610eb1565b60005b15610efd57601c602059905901600090520161271a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610da0526020610da0f35b6111b4565b6301000000610d005104610de05262ffffff610d005116610e00526003610de051036101000a610e005102610dc05260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610e605250610e605160041a610e605160051a61010002610e605160061a6201000002610e605160071a630100000002010101610e2052601c604459905901600090520163e0e9a17b601c8203526107e0610120510360048201526020610ec0602483600030602d5a03f150610ec0519050610ea05260806080599059016000905260038152610ea05181602001526002816040015260008160600152809050206002810154610f205250610f205160041a610f205160051a61010002610f205160061a6201000002610f205160071a630100000002010101610ee052610ee051610e20510362049d408112156110595762049d4090505b6249d40081131561106b576249d40090505b62127500610dc0518202047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156110ba577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505b600860076000835b80156110d9576002810490506001820191506110c2565b5080905001046000600382131515611103578160030360080260020a62ffffff841602905061111a565b6003820360080260020a8304905062ffffff811690505b6280000081161561113357610100810490506001820191505b6301000000820281179050905090509050610f6052610f6051610c6051141515611164576000610f60511415611167565b60005b156111b357601c60205990590160009052016127246101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000611040526020611040f35b5b6101e0516101e0516101e05166040000000000005455606060605990590160009052600381526101e0518160200152600081604001528090502054611060526008611060016604000000000000548060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061106051606060605990590160009052600381526101e0518160200152600081604001528090502055600166040000000000005401660400000000000055606060605990590160009052600381526101e0518160200152600081604001528090502054611100526111006001780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205404018060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061110051606060605990590160009052600381526101e051816020015260008160400152809050205560006111c05278010000000000000000000000000000000000000000000000006801000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205402046111e0526111c06111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350506001611260525b6008611260511215611515576112605160050a611280526001611280517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540407141561148757611260516004026111c0016111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a60038301535050611505565b611260516004026111c0017c01000000000000000000000000000000000000000000000000000000006112605160200260020a60606060599059016000905260038152610a00518160200152600181604001528090502054020480601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350505b60016112605101611260526113ec565b6111c051606060605990590160009052600381526101e05181602001526001816040015280905020555050608060805990590160009052600381526101e051816020015260028160400152600081606001528090502060005b600281121561159057806020026102c05101518282015560018101905061156e565b700100000000000000000000000000000000600003816020026102c051015116828201555050610c80517bffff0000000000000000000000000000000000000000000000000000056113e0526113e051610b805101610be052606060605990590160009052600381526101e051816020015260008160400152809050205461140052601061140001610be0518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061140051606060605990590160009052600381526101e0518160200152600081604001528090502055660400000000000354610be051121515611703576101e051660400000000000255610be0516604000000000003555b601c6020599059016000905201610120516101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a350610120516114a05260206114a0f35b601c602059905901600090520161276a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a35060006114c05260206114c0f35b630f5995ce8114156119a157365990590160009052366004823760043560208201016114e05260243561150052604435602082010161152052606435604052506114e05160208103516020599059016000905260208183856000600287604801f150805190509050905061156052602059905901600090526020816020611560600060026068f1508051905060005b6020811215611843578181601f031a816116400153600181019050611823565b50506116405161154052604060206114e051035114156118a457601c6020599059016000905201614e52611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a3506000611660526020611660f35b6080601c6101ac59905901600090520163bd136cb3601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff161192357fe5b6084810192506101488201518080858260c487015160006004600a8705601201f161194a57fe5b508084019350508083036020611680828434306123555a03f15061168051905090509050905061042052600161042051141561199357611540516116a05260206116a0f36119a0565b60006116c05260206116c0f35b5b63bd136cb3811415611d8c573659905901600090523660048237600435611540526024356115005260443560208201016115205260643560405250601c606459905901600090520163d467ae03601c82035260405160048201526060606059905901600090526003815260405181602001526003816040015280905020546bffffffffffffffffffffffff166024820152602061170060448334306123555a03f1506117005190501515611a9757601c6020599059016000905201614e2a611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e2a611720526020611720f35b601c6044599059016000905201633d73b705601c82035260405160048201526020611740602483600030602d5a03f15061174051905015611b1a57601c6020599059016000905201614e34611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e34611760526020611760f35b601c604459905901600090520163b041b285601c82035260405160048201526020611780602483600030602d5a03f1506117805190501515611b9e57601c6020599059016000905201614e3e611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e3e6117a05260206117a0f35b6060601c61014c59905901600090520163b7129afb601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360a4840152806101088401528084019350505081600401599059016000905260648160648460006004601cf1611c1557fe5b6064810192506101088201518080858260a487015160006004600a8705601201f1611c3c57fe5b5080840193505080830360206117e08284600030602d5a03f1506117e05190509050905090506117c0526080608059905901600090526003815260405181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006002820154046401000000006001830154020160005b6020811215611ce4578181601f031a816118a00153600181019050611cc4565b50506118a051905061180052611800516117c0511415611d4457601c60205990590160009052016001611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a35060016118c05260206118c0f35b601c6020599059016000905201614e48611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e486118e05260206118e0f35b63318a3fee81141561205657365990590160009052366004823760043560208201016114e0526024356115005260443560208201016115205260643560405260843561190052506080601c6101ac599059016000905201630f5995ce601c8203526114e0516020601f6020830351010460200260200183600484015260208203608484015280610108840152808401935050506115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff1611e7b57fe5b60848101925061010882015180808582608487015160006004600a8705601201f1611ea257fe5b508084019350506101488201518080858260c487015160006004600a8705601201f1611eca57fe5b508084019350508083036020611920828434306123555a03f15061192051905090509050905061154052600061154051141515612010576040601c60ec599059016000905201631c0b6367601c8203526114e0516020601f6020830351010460200260200183600484015260208203604484015280608884015280840193505050611540516024820152816004015990590160009052604481604484600060046018f1611f7357fe5b604481019250608882015180808582604487015160006004600a8705601201f1611f9957fe5b5080840193505080830360206119608284600061190051602d5a03f15061196051905090509050905061194052601c602059905901600090520161194051611540517f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061194051611980526020611980f35b601c602059905901600090520161753a60007f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061753a6119a05260206119a0f35b6309dd0e81811415612076576604000000000002546119c05260206119c0f35b63023948728114156120d2577801000000000000000000000000000000000000000000000000606060605990590160009052600381526604000000000002548160200152600081604001528090502054046119e05260206119e0f35b632c181929811415612139577001000000000000000000000000000000007001000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540204611a20526020611a20f35b637ca823d58114156122af576604000000000002546101e052700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611a60526000611260525b600a61126051121561224c57608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612230578181601f031a81611b200153600181019050612210565b5050611b205190506101e05260016112605101611260526121a8565b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611b4052611b4051611a605103611b80526020611b80f35b63b7129afb81141561246a57365990590160009052366004823760043561154052602435611500526044356020820101611520525061154051611ba0526020611520510351611bc0526000611260525b611bc05161126051121561245b5761126051602002611520510151611be05260026115005107611c00526001611c0051141561234a57611be051611c2052611ba051611c4052612368565b6000611c0051141561236757611ba051611c2052611be051611c40525b5b60405990590160009052611c205160005b6020811215612399578181601f031a81611ca00153600181019050612379565b5050611ca0518152611c405160005b60208112156123c8578181601f031a81611d2001536001810190506123a8565b5050611d2051602082015260205990590160009052602081604084600060026088f15080519050611d4052602059905901600090526020816020611d40600060026068f1508051905060005b6020811215612434578181601f031a81611de00153600181019050612414565b5050611de0519050611ba052600261150051056115005260016112605101611260526122ff565b611ba051611e00526020611e00f35b633d73b70581141561255b576004356040526604000000000002546101e0526000611260525b600661126051121561254e576101e05160405114156124b6576001611e20526020611e20f35b608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612532578181601f031a81611ec00153600181019050612512565b5050611ec05190506101e0526001611260510161126052612490565b6000611ee0526020611ee0f35b631f794436811415612737576004356101e052601c606459905901600090520163d467ae03601c8203526101e0516004820152606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff1660248201526020611f2060448334306123555a03f150611f20519050151561265657601c602059905901600090520160006101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350602159905901600090526001815260006020820152602081019050602060408203526020601f6020830351604001010460200260408203f3505b601c602059905901600090520160016101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350608060805990590160009052600381526101e0518160200152600281604001526000816060015280905020607059905901600090526050815260208101905060005b60028112156126f05780830154816020028301526001810190506126d1565b70010000000000000000000000000000000060000381840154168160200283015281905090509050602060408203526020601f6020830351604001010460200260408203f3505b6313f955e18114156128ca573659905901600090523660048237600435602082010161204052602435612060525060506120805260006120a052612080516120c0526000611260525b612060516112605112156128bb576120a051806120c051038080602001599059016000905281815260208101905090508180828286612040510160006004600a8705601201f16127cc57fe5b50809050905090506120e0526020601c608c599059016000905201632b861629601c8203526120e0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161284157fe5b602481019250604882015180808582602487015160006004600a8705601201f161286757fe5b5080840193505080830360206121a08284600030602d5a03f1506121a051905090509050905061042052612080516120a051016120a052612080516120c051016120c0526001611260510161126052612780565b610420516121c05260206121c0f35b50", + "storage": { + "0x292b7a8d467a95cffd303c7edd99875892cdb3eaee87e5ca29057dc88a09ffbd": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x4d2fcf8ac901ad7dcf5b1c3979801430d9979c87157230ae066a0276984c6ac7": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xdf951a5d1d9283b06d4f1de58542f1e1e310d8d17aada46586ddb9598bc42894": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x9c8d09d387f3ba5dd4733e24c63e4d549864a7cd57a1bdf1fdd831a2a0184815": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x4ab3b783bb170e11b0932a5ce8f5f343f67058b3925da271001a75ae498bd655": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x0", + "nonce": "0", + "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": "559198", + "difficulty": "1814830", + "timestamp": "1577471205", + "gasLimit": "6327338", + "miner": "0x774c398d763161f55b66a646f17edda4addad2ca" + }, + "tracerConfig": { + "includePrecompiles": true + }, + "input": "0xf9026f8301307b85746a52880083124f80946cc68eb482a757c690dd151d2bd5e774ada38bdc80b9020413f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e00000000000000000000000000000000081a1a01c9e9d742c8e69daba2a026ccafdde618f2e44c96db281c2209c22f183ad03a2a049a61d267d22226896d4c065525819c238784c439dc2afa7d17fce76595730d1", + "result": [ + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "gas": "0x119d28", + "input": "0x13f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1c6ff", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 20, + "traceAddress": [], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1a", + "input": "0x04000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x18", + "output": "0x04000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67" + }, + "subtraces": 0, + "traceAddress": [ + 0 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x15", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x15", + "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" + }, + "subtraces": 0, + "traceAddress": [ + 1 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1e", + "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1b", + "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 2 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x114243", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 2, + "traceAddress": [ + 3 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x98", + "input": "0x04000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x60", + "output": "0xb099ea4048830027371dc31039920ae4fd19a641a7cbe57c198edd19d60f158a" + }, + "subtraces": 0, + "traceAddress": [ + 3, + 0 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x68", + "input": "0xb099ea4048830027371dc31039920ae4fd19a641a7cbe57c198edd19d60f158a", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x48", + "output": "0x5b53875b0f1381589859adcf938980f4a8fb0af4c88450070000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 3, + 1 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1a", + "input": "0x040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae7", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x18", + "output": "0x040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae7" + }, + "subtraces": 0, + "traceAddress": [ + 4 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x15", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x15", + "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" + }, + "subtraces": 0, + "traceAddress": [ + 5 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1e", + "input": "0x0000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1b", + "output": "0x0000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 6 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x110d3b", + "input": "0x2b86162900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 2, + "traceAddress": [ + 7 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x98", + "input": "0x040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae7", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x60", + "output": "0xa0c6939b58a99b0d940f4435ab7db7d54d6b7786e68e00d9ff3890d69f95565d" + }, + "subtraces": 0, + "traceAddress": [ + 7, + 0 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x68", + "input": "0xa0c6939b58a99b0d940f4435ab7db7d54d6b7786e68e00d9ff3890d69f95565d", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x48", + "output": "0xabbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 7, + 1 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1a", + "input": "0x04000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc303", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x18", + "output": "0x04000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc303" + }, + "subtraces": 0, + "traceAddress": [ + 8 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x15", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x15", + "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" + }, + "subtraces": 0, + "traceAddress": [ + 9 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1e", + "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1b", + "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 10 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x10d833", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 2, + "traceAddress": [ + 11 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x98", + "input": "0x04000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc303", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x60", + "output": "0x6defff59ba277fa4511f8675ca98ca7d9c237c7433684490cf1ce09a9249e32f" + }, + "subtraces": 0, + "traceAddress": [ + 11, + 0 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x68", + "input": "0x6defff59ba277fa4511f8675ca98ca7d9c237c7433684490cf1ce09a9249e32f", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x48", + "output": "0xe93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 11, + 1 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1a", + "input": "0x04000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x18", + "output": "0x04000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de" + }, + "subtraces": 0, + "traceAddress": [ + 12 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x15", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x15", + "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" + }, + "subtraces": 0, + "traceAddress": [ + 13 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1e", + "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1b", + "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 14 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x10a328", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 2, + "traceAddress": [ + 15 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x98", + "input": "0x04000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x60", + "output": "0x996652142ffecd9cc272f376ca0e8228871a903772996289f847a6dbe2ce2698" + }, + "subtraces": 0, + "traceAddress": [ + 15, + 0 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x68", + "input": "0x996652142ffecd9cc272f376ca0e8228871a903772996289f847a6dbe2ce2698", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x48", + "output": "0xf2e372a0b5b837116eee8f968840393d85975a15313468070000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 15, + 1 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1a", + "input": "0x04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e0", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x18", + "output": "0x04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e0" + }, + "subtraces": 0, + "traceAddress": [ + 16 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x15", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x15", + "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" + }, + "subtraces": 0, + "traceAddress": [ + 17 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x1e", + "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000004", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1b", + "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 18 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x106e1d", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 2, + "traceAddress": [ + 19 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x98", + "input": "0x04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e0", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x60", + "output": "0xe57cf1c1d6132b9cfd9e90f54f907c038b47941b2a7f3800783af26e852ec116" + }, + "subtraces": 0, + "traceAddress": [ + 19, + 0 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x68", + "input": "0xe57cf1c1d6132b9cfd9e90f54f907c038b47941b2a7f3800783af26e852ec116", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x48", + "output": "0x8d5b6fafc6216500f9ef1ab16b30a59df9122d7de0f4910a0000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 19, + 1 + ], + "type": "call" + } + ] +} \ No newline at end of file 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 new file mode 100644 index 00000000000..170948e1566 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json @@ -0,0 +1,88 @@ +{ + "context": { + "difficulty": "3451177886", + "gasLimit": "4709286", + "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", + "number": "2290744", + "timestamp": "1513616439" + }, + "genesis": { + "alloc": { + "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a": { + "balance": "0x0", + "code": "0x606060405263ffffffff60e060020a6000350416633b91f50681146100505780635bb47808146100715780635f51fca01461008c578063bc7647a9146100ad578063f1bd0d7a146100c8575b610000565b346100005761006f600160a060020a03600435811690602435166100e9565b005b346100005761006f600160a060020a0360043516610152565b005b346100005761006f600160a060020a036004358116906024351661019c565b005b346100005761006f600160a060020a03600435166101fa565b005b346100005761006f600160a060020a0360043581169060243516610db8565b005b600160a060020a038083166000908152602081905260408120549091908116903316811461011657610000565b839150600160a060020a038316151561012d573392505b6101378284610e2e565b6101418284610db8565b61014a826101fa565b5b5b50505050565b600154600160a060020a03908116903316811461016e57610000565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790555b5b5050565b600254600160a060020a0390811690331681146101b857610000565b600160a060020a038381166000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19169184169190911790555b5b505050565b6040805160e260020a631a481fc102815260016024820181905260026044830152606482015262093a8060848201819052600060a4830181905260c06004840152601e60c48401527f736574456e7469747953746174757328616464726573732c75696e743829000060e484015292519091600160a060020a038516916369207f049161010480820192879290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526000602482018190526001604483015260606004830152602360648301527f626567696e506f6c6c28616464726573732c75696e7436342c626f6f6c2c626f60848301527f6f6c29000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f61646453746f636b28616464726573732c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f697373756553746f636b2875696e74382c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602160648301527f6772616e7453746f636b2875696e74382c75696e743235362c61646472657373608483015260f860020a60290260a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f115610000575050604080517f010555b8000000000000000000000000000000000000000000000000000000008152600160a060020a03338116602483015260006044830181905260606004840152603c60648401527f6772616e7456657374656453746f636b2875696e74382c75696e743235362c6160848401527f6464726573732c75696e7436342c75696e7436342c75696e743634290000000060a48401529251908716935063010555b89260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601260c48201527f626567696e53616c65286164647265737329000000000000000000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601a60648301527f7472616e7366657253616c6546756e64732875696e743235362900000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152602d60c48201527f7365744163636f756e74696e6753657474696e67732875696e743235362c756960e48201527f6e7436342c75696e7432353629000000000000000000000000000000000000006101048201529051600160a060020a03861692506369207f04916101248082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152603460648301527f637265617465526563757272696e6752657761726428616464726573732c756960848301527f6e743235362c75696e7436342c737472696e672900000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601b60648301527f72656d6f7665526563757272696e675265776172642875696e7429000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602360648301527f697373756552657761726428616464726573732c75696e743235362c7374726960848301527f6e6729000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f61737369676e53746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f72656d6f766553746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260026024808301919091526003604483015260006064830181905267ffffffffffffffff8616608484015260ff871660a484015260c0600484015260c48301919091527f7365744164647265737342796c617728737472696e672c616464726573732c6260e48301527f6f6f6c29000000000000000000000000000000000000000000000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152602160c48301527f73657453746174757342796c617728737472696e672c75696e74382c626f6f6c60e483015260f860020a6029026101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152603860c48301527f736574566f74696e6742796c617728737472696e672c75696e743235362c756960e48301527f6e743235362c626f6f6c2c75696e7436342c75696e74382900000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f115610000575050505b505050565b604080517f225553a4000000000000000000000000000000000000000000000000000000008152600160a060020a0383811660048301526002602483015291519184169163225553a49160448082019260009290919082900301818387803b156100005760325a03f115610000575050505b5050565b600082604051611fd280610f488339600160a060020a03909216910190815260405190819003602001906000f0801561000057905082600160a060020a03166308b027418260016040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b156100005760325a03f115610000575050604080517fa14e3ee300000000000000000000000000000000000000000000000000000000815260006004820181905260016024830152600160a060020a0386811660448401529251928716935063a14e3ee39260648084019382900301818387803b156100005760325a03f115610000575050505b5050505600606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029a165627a7a723058200e78a5f7e0f91739035d0fbf5eca02f79377210b722f63431f29a22e2880b3bd0029", + "nonce": "789", + "storage": { + "0xfe9ec0542a1c009be8b1f3acf43af97100ffff42eb736850fb038fa1151ad4d9": "0x000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8" + } + }, + "0x5cb4a6b902fcb21588c86c3517e797b07cdaadb9": { + "balance": "0x0", + "code": "0x", + "nonce": "0", + "storage": {} + }, + "0xe4a13bc304682a903e9472f469c33801dd18d9e8": { + "balance": "0x33c763c929f62c4f", + "code": "0x", + "nonce": "14", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3451177886", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "4713874", + "hash": "0x5d52a672417cd1269bf4f7095e25dcbf837747bba908cd5ef809dc1bd06144b5", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0x01a12845ed546b94a038a7a03e8df8d7952024ed41ccb3db7a7ade4abc290ce1", + "nonce": "0x28c446f1cb9748c1", + "number": "2290743", + "stateRoot": "0x4898aceede76739daef76448a367d10015a2c022c9e7909b99a10fbf6fb16708", + "timestamp": "1513616414", + "totalDifficulty": "7146523769022564" + }, + "input": "0xf8aa0e8509502f9000830493e0941d3ddf7caf024f253487e18bc4a15b1a360c170a80b8443b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e829a0524564944fa419f5c189b5074044f89210c6d6b2d77ee8f7f12a927d59b636dfa0015b28986807a424b18b186ee6642d76739df36cad802d20e8c00e79a61d7281", + "result": [ + { + "action": { + "callType": "call", + "from": "0xe4a13bc304682a903e9472f469c33801dd18d9e8", + "gas": "0x435c8", + "input": "0x3b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8", + "to": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", + "value": "0x0" + }, + "blockNumber": 2290744, + "error": "invalid jump destination", + "result": {}, + "subtraces": 1, + "traceAddress": [], + "type": "call" + }, + { + "action": { + "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", + "gas": "0x39ff0", + "init": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182", + "value": "0x0" + }, + "blockNumber": 0, + "error": "contract creation code storage out of gas", + "result": {}, + "subtraces": 0, + "traceAddress": [0], + "type": "create" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json new file mode 100644 index 00000000000..328b743270d --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json @@ -0,0 +1,72 @@ +{ + "genesis": { + "difficulty": "117067574", + "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", + "gasLimit": "4712380", + "hash": "0xe05db05eeb3f288041ecb10a787df121c0ed69499355716e17c307de313a4486", + "miner": "0x0c062b329265c965deef1eede55183b3acb8f611", + "mixHash": "0xb669ae39118a53d2c65fd3b1e1d3850dd3f8c6842030698ed846a2762d68b61d", + "nonce": "0x2b469722b8e28c45", + "number": "24973", + "stateRoot": "0x532a5c3f75453a696428db078e32ae283c85cb97e4d8560dbdf022adac6df369", + "timestamp": "1479891145", + "totalDifficulty": "1892250259406", + "alloc": { + "0x6c06b16512b332e6cd8293a2974872674716ce18": { + "balance": "0x0", + "nonce": "1", + "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d146036575b6000565b34600057604e60048080359060200190919050506050565b005b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f19350505050505b5056", + "storage": {} + }, + "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31": { + "balance": "0x229ebbb36c3e0f20", + "nonce": "3", + "code": "0x", + "storage": {} + } + }, + "config": { + "chainId": 3, + "homesteadBlock": 0, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "byzantiumBlock": 1700000, + "constantinopleBlock": 4230000, + "petersburgBlock": 4939394, + "istanbulBlock": 6485846, + "muirGlacierBlock": 7117117, + "ethash": {} + } + }, + "context": { + "number": "24974", + "difficulty": "117067574", + "timestamp": "1479891162", + "gasLimit": "4712388", + "miner": "0xc822ef32e6d26e170b70cf761e204c1806265914" + }, + "input": "0xf889038504a81557008301f97e946c06b16512b332e6cd8293a2974872674716ce1880a42e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b1600002aa0e2a6558040c5d72bc59f2fb62a38993a314c849cd22fb393018d2c5af3112095a01bdb6d7ba32263ccc2ecc880d38c49d9f0c5a72d8b7908e3122b31356d349745", + "result": [ + { + "action": { + "callType": "call", + "from": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31", + "gas": "0x1a466", + "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000", + "to": "0x6c06b16512b332e6cd8293a2974872674716ce18", + "value": "0x0" + }, + "blockNumber": 24974, + "result": { + "gasUsed": "0x72de", + "output": "0x" + }, + "subtraces": 0, + "traceAddress": [], + "type": "call" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_precompiled_wrong_gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_precompiled_wrong_gas.json new file mode 100644 index 00000000000..6b5738101c2 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_precompiled_wrong_gas.json @@ -0,0 +1,219 @@ +{ + "genesis": { + "number": "559197", + "hash": "0x0742a2bfab0452e2c634f3685b7e49ceb065c7000609b2b73f086e01fd1dfb58", + "nonce": "0x3060ad521440e1c2", + "mixHash": "0x59e7d4ae6cc3c38d23dac3f869b21984c7ba8f38070f4116a4941d9c403b6299", + "stateRoot": "0x68418fb5cf4afa9b807dc079e8cdde0e148ac2c8afb378e675465b5bed1fbd02", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "difficulty": "1813945", + "totalDifficulty": "469107641961", + "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", + "gasLimit": "6321166", + "timestamp": "1577471202", + "alloc": { + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0xc5e6fdae52af83f7e28", + "nonce": "77947", + "code": "0x", + "storage": {} + }, + "0x774c398d763161f55b66a646f17edda4addad2ca": { + "balance": "0xf09ef316eff819ee488", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc": { + "balance": "0x0", + "nonce": "1", + "code": "0x60006121df537c01000000000000000000000000000000000000000000000000000000006000350463b041b2858114156100d257600435604052780100000000000000000000000000000000000000000000000060606060599059016000905260038152604051816020015260008160400152809050205404606052606051151561008f57600060a052602060a0f35b604051601c604459905901600090520163e0e9a17b601c82035260605160048201526020610100602483600030602d5a03f1506101005190501460c052602060c0f35b632cce81aa81141561019957600435610120526001610120511280156100f85780610143565b78010000000000000000000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540461012051135b905015610157576000610180526020610180f35b601c604459905901600090520163e0e9a17b601c82035261012051600482015260206101c0602483600030602d5a03f1506101c05190506101a05260206101a0f35b63e0e9a17b8114156102e957600435610120526604000000000002546101e0526007610200525b610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540413156102da575b6102005160050a610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e051816020015260008160400152809050205404031215610269576000610200511361026c565b60005b1561028157600161020051036102005261020b565b7c01000000000000000000000000000000000000000000000000000000006102005160200260020a606060605990590160009052600381526101e05181602001526001816040015280905020540204546101e0526101c0565b6101e051610280526020610280f35b63cef887b08114156103e757365990590160009052366004823760043560208201016102c0526024356102e052506060601c61014c5990590160009052016390fa337d601c8203526102c0516020601f602083035101046020026020018360048401526020820360648401528060c8840152808401935050506102e051602482015233604482015281600401599059016000905260648160648460006004601cf161039057fe5b60648101925060c882015180808582606487015160006004600a8705601201f16103b657fe5b5080840193505080830360206103a08284600030602d5a03f1506103a0519050905090509050610300526020610300f35b6390fa337d81141561065f57365990590160009052366004823760043560208201016102c0526024356102e0526044356103e052505a610400526020601c608c599059016000905201632b861629601c8203526102c0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161048a57fe5b602481019250604882015180808582602487015160006004600a8705601201f16104b057fe5b5080840193505080830360206104408284600030602d5a03f15061044051905090509050905061042052610420511561065e576102c05160208103516020599059016000905260208183856000600287604801f150805190509050905061046052602059905901600090526020816020610460600060026068f1508051905060005b6020811215610552578181601f031a816105400153600181019050610532565b5050610540516101e0526102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020555a61058052700100000000000000000000000000000000660400000000000154046105a0526104006105a0516103ff02056105c0526104006105a05161040102056105e0526105c0513a12156105f6576105c05161060052610615565b6105e0513a131561060e576105e05161060052610614565b3a610600525b5b6105805161040051036106005160020202610620526106205170010000000000000000000000000000000061060051021766040000000000015561042051610640526020610640f35b5b63d467ae0381141561073257600435604052602435610660526106605134121515610725576000341315610718576c01000000000000000000000000606060605990590160009052600381526040518160200152600381604001528090502054046103e0526000600060006000346103e051611388f115156106dd57fe5b601c60405990590160009052013481526103e0517f15e746bf513b8a58e4265cc1162d7fc445da5c9b1928d7cfcde2582735d4677f602083a2505b60016106a05260206106a0f35b60006106c05260206106c0f35b63ea4971ee811415610851576004356101e0526024356102e0526044356103e052601c606459905901600090520163d467ae03601c8203526101e05160048201526604000000000001546fffffffffffffffffffffffffffffffff16602482015260206106e060448334306123555a03f1506106e051905015156107bd576000610700526020610700f35b606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166102e0511215610844576102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020556001610760526020610760f35b6000610780526020610780f35b6387def0818114156108a3576004356101e0526c01000000000000000000000000606060605990590160009052600381526101e0518160200152600381604001528090502054046107a05260206107a0f35b630aece23c8114156108f4576004356101e052606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166107e05260206107e0f35b63fa14df6b811415610926576604000000000001546fffffffffffffffffffffffffffffffff16610820526020610820f35b63b8c48f8c811415610b1b576004356101e0526024356108405260443561086052600066040000000000035414151561096a576000610880526020610880f3610976565b60016604000000000003555b6101e051660400000000000255606060605990590160009052600381526101e05181602001526000816040015280905020546108a0526108a0610840518060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a600783015350506108a051606060605990590160009052600381526101e0518160200152600081604001528090502055606060605990590160009052600381526101e051816020015260008160400152809050205461094052601061094001610860518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061094051606060605990590160009052600381526101e051816020015260008160400152809050205560016109e05260206109e0f35b632b86162981141561179457365990590160009052366004823760043560208201016102c0525060483560005b6020811215610b68578181601f031a81610a600153600181019050610b48565b5050610a6051610a00526102c05160208103516020599059016000905260208183856000600287604801f1508051905090509050610a8052602059905901600090526020816020610a80600060026068f1508051905060005b6020811215610be1578181601f031a81610b600153600181019050610bc1565b5050610b60516101e05270010000000000000000000000000000000070010000000000000000000000000000000060606060599059016000905260038152610a005181602001526000816040015280905020540204610b8052610b80511515610c8b57601c602059905901600090520161272e6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610bc0526020610bc0f35b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204610be0526000610be051141515610d2e57601c60205990590160009052016127386101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610c20526020610c20f35b608c35610c40526301000000610c405160031a0262010000610c405160021a02610100610c405160011a02610c405160001a010101610c60526301000000610c605104610ca05262ffffff610c605116610cc0526003610ca051036101000a610cc05102610c805260006101e0511315610db057610c80516101e05112610db3565b60005b1561174d57780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a00518160200152600081604001528090502054046001016101205260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610d405250610d405160081a610d405160091a61010002610d4051600a1a6201000002610d4051600b1a630100000002010101610d005260006107e0610120510614158015610e7e5780610e8b565b6001660400000000000054145b905015610f0257610d0051610c6051141515610eae576000610d00511415610eb1565b60005b15610efd57601c602059905901600090520161271a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610da0526020610da0f35b6111b4565b6301000000610d005104610de05262ffffff610d005116610e00526003610de051036101000a610e005102610dc05260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610e605250610e605160041a610e605160051a61010002610e605160061a6201000002610e605160071a630100000002010101610e2052601c604459905901600090520163e0e9a17b601c8203526107e0610120510360048201526020610ec0602483600030602d5a03f150610ec0519050610ea05260806080599059016000905260038152610ea05181602001526002816040015260008160600152809050206002810154610f205250610f205160041a610f205160051a61010002610f205160061a6201000002610f205160071a630100000002010101610ee052610ee051610e20510362049d408112156110595762049d4090505b6249d40081131561106b576249d40090505b62127500610dc0518202047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156110ba577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505b600860076000835b80156110d9576002810490506001820191506110c2565b5080905001046000600382131515611103578160030360080260020a62ffffff841602905061111a565b6003820360080260020a8304905062ffffff811690505b6280000081161561113357610100810490506001820191505b6301000000820281179050905090509050610f6052610f6051610c6051141515611164576000610f60511415611167565b60005b156111b357601c60205990590160009052016127246101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000611040526020611040f35b5b6101e0516101e0516101e05166040000000000005455606060605990590160009052600381526101e0518160200152600081604001528090502054611060526008611060016604000000000000548060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061106051606060605990590160009052600381526101e0518160200152600081604001528090502055600166040000000000005401660400000000000055606060605990590160009052600381526101e0518160200152600081604001528090502054611100526111006001780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205404018060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061110051606060605990590160009052600381526101e051816020015260008160400152809050205560006111c05278010000000000000000000000000000000000000000000000006801000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205402046111e0526111c06111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350506001611260525b6008611260511215611515576112605160050a611280526001611280517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540407141561148757611260516004026111c0016111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a60038301535050611505565b611260516004026111c0017c01000000000000000000000000000000000000000000000000000000006112605160200260020a60606060599059016000905260038152610a00518160200152600181604001528090502054020480601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350505b60016112605101611260526113ec565b6111c051606060605990590160009052600381526101e05181602001526001816040015280905020555050608060805990590160009052600381526101e051816020015260028160400152600081606001528090502060005b600281121561159057806020026102c05101518282015560018101905061156e565b700100000000000000000000000000000000600003816020026102c051015116828201555050610c80517bffff0000000000000000000000000000000000000000000000000000056113e0526113e051610b805101610be052606060605990590160009052600381526101e051816020015260008160400152809050205461140052601061140001610be0518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061140051606060605990590160009052600381526101e0518160200152600081604001528090502055660400000000000354610be051121515611703576101e051660400000000000255610be0516604000000000003555b601c6020599059016000905201610120516101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a350610120516114a05260206114a0f35b601c602059905901600090520161276a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a35060006114c05260206114c0f35b630f5995ce8114156119a157365990590160009052366004823760043560208201016114e05260243561150052604435602082010161152052606435604052506114e05160208103516020599059016000905260208183856000600287604801f150805190509050905061156052602059905901600090526020816020611560600060026068f1508051905060005b6020811215611843578181601f031a816116400153600181019050611823565b50506116405161154052604060206114e051035114156118a457601c6020599059016000905201614e52611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a3506000611660526020611660f35b6080601c6101ac59905901600090520163bd136cb3601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff161192357fe5b6084810192506101488201518080858260c487015160006004600a8705601201f161194a57fe5b508084019350508083036020611680828434306123555a03f15061168051905090509050905061042052600161042051141561199357611540516116a05260206116a0f36119a0565b60006116c05260206116c0f35b5b63bd136cb3811415611d8c573659905901600090523660048237600435611540526024356115005260443560208201016115205260643560405250601c606459905901600090520163d467ae03601c82035260405160048201526060606059905901600090526003815260405181602001526003816040015280905020546bffffffffffffffffffffffff166024820152602061170060448334306123555a03f1506117005190501515611a9757601c6020599059016000905201614e2a611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e2a611720526020611720f35b601c6044599059016000905201633d73b705601c82035260405160048201526020611740602483600030602d5a03f15061174051905015611b1a57601c6020599059016000905201614e34611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e34611760526020611760f35b601c604459905901600090520163b041b285601c82035260405160048201526020611780602483600030602d5a03f1506117805190501515611b9e57601c6020599059016000905201614e3e611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e3e6117a05260206117a0f35b6060601c61014c59905901600090520163b7129afb601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360a4840152806101088401528084019350505081600401599059016000905260648160648460006004601cf1611c1557fe5b6064810192506101088201518080858260a487015160006004600a8705601201f1611c3c57fe5b5080840193505080830360206117e08284600030602d5a03f1506117e05190509050905090506117c0526080608059905901600090526003815260405181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006002820154046401000000006001830154020160005b6020811215611ce4578181601f031a816118a00153600181019050611cc4565b50506118a051905061180052611800516117c0511415611d4457601c60205990590160009052016001611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a35060016118c05260206118c0f35b601c6020599059016000905201614e48611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e486118e05260206118e0f35b63318a3fee81141561205657365990590160009052366004823760043560208201016114e0526024356115005260443560208201016115205260643560405260843561190052506080601c6101ac599059016000905201630f5995ce601c8203526114e0516020601f6020830351010460200260200183600484015260208203608484015280610108840152808401935050506115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff1611e7b57fe5b60848101925061010882015180808582608487015160006004600a8705601201f1611ea257fe5b508084019350506101488201518080858260c487015160006004600a8705601201f1611eca57fe5b508084019350508083036020611920828434306123555a03f15061192051905090509050905061154052600061154051141515612010576040601c60ec599059016000905201631c0b6367601c8203526114e0516020601f6020830351010460200260200183600484015260208203604484015280608884015280840193505050611540516024820152816004015990590160009052604481604484600060046018f1611f7357fe5b604481019250608882015180808582604487015160006004600a8705601201f1611f9957fe5b5080840193505080830360206119608284600061190051602d5a03f15061196051905090509050905061194052601c602059905901600090520161194051611540517f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061194051611980526020611980f35b601c602059905901600090520161753a60007f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061753a6119a05260206119a0f35b6309dd0e81811415612076576604000000000002546119c05260206119c0f35b63023948728114156120d2577801000000000000000000000000000000000000000000000000606060605990590160009052600381526604000000000002548160200152600081604001528090502054046119e05260206119e0f35b632c181929811415612139577001000000000000000000000000000000007001000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540204611a20526020611a20f35b637ca823d58114156122af576604000000000002546101e052700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611a60526000611260525b600a61126051121561224c57608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612230578181601f031a81611b200153600181019050612210565b5050611b205190506101e05260016112605101611260526121a8565b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611b4052611b4051611a605103611b80526020611b80f35b63b7129afb81141561246a57365990590160009052366004823760043561154052602435611500526044356020820101611520525061154051611ba0526020611520510351611bc0526000611260525b611bc05161126051121561245b5761126051602002611520510151611be05260026115005107611c00526001611c0051141561234a57611be051611c2052611ba051611c4052612368565b6000611c0051141561236757611ba051611c2052611be051611c40525b5b60405990590160009052611c205160005b6020811215612399578181601f031a81611ca00153600181019050612379565b5050611ca0518152611c405160005b60208112156123c8578181601f031a81611d2001536001810190506123a8565b5050611d2051602082015260205990590160009052602081604084600060026088f15080519050611d4052602059905901600090526020816020611d40600060026068f1508051905060005b6020811215612434578181601f031a81611de00153600181019050612414565b5050611de0519050611ba052600261150051056115005260016112605101611260526122ff565b611ba051611e00526020611e00f35b633d73b70581141561255b576004356040526604000000000002546101e0526000611260525b600661126051121561254e576101e05160405114156124b6576001611e20526020611e20f35b608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612532578181601f031a81611ec00153600181019050612512565b5050611ec05190506101e0526001611260510161126052612490565b6000611ee0526020611ee0f35b631f794436811415612737576004356101e052601c606459905901600090520163d467ae03601c8203526101e0516004820152606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff1660248201526020611f2060448334306123555a03f150611f20519050151561265657601c602059905901600090520160006101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350602159905901600090526001815260006020820152602081019050602060408203526020601f6020830351604001010460200260408203f3505b601c602059905901600090520160016101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350608060805990590160009052600381526101e0518160200152600281604001526000816060015280905020607059905901600090526050815260208101905060005b60028112156126f05780830154816020028301526001810190506126d1565b70010000000000000000000000000000000060000381840154168160200283015281905090509050602060408203526020601f6020830351604001010460200260408203f3505b6313f955e18114156128ca573659905901600090523660048237600435602082010161204052602435612060525060506120805260006120a052612080516120c0526000611260525b612060516112605112156128bb576120a051806120c051038080602001599059016000905281815260208101905090508180828286612040510160006004600a8705601201f16127cc57fe5b50809050905090506120e0526020601c608c599059016000905201632b861629601c8203526120e0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161284157fe5b602481019250604882015180808582602487015160006004600a8705601201f161286757fe5b5080840193505080830360206121a08284600030602d5a03f1506121a051905090509050905061042052612080516120a051016120a052612080516120c051016120c0526001611260510161126052612780565b610420516121c05260206121c0f35b50", + "storage": { + "0x292b7a8d467a95cffd303c7edd99875892cdb3eaee87e5ca29057dc88a09ffbd": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x4d2fcf8ac901ad7dcf5b1c3979801430d9979c87157230ae066a0276984c6ac7": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xdf951a5d1d9283b06d4f1de58542f1e1e310d8d17aada46586ddb9598bc42894": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x9c8d09d387f3ba5dd4733e24c63e4d549864a7cd57a1bdf1fdd831a2a0184815": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x4ab3b783bb170e11b0932a5ce8f5f343f67058b3925da271001a75ae498bd655": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x0", + "nonce": "0", + "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": "559198", + "difficulty": "1814830", + "timestamp": "1577471205", + "gasLimit": "6327338", + "miner": "0x774c398d763161f55b66a646f17edda4addad2ca" + }, + "input": "0xf9026f8301307b85746a52880083124f80946cc68eb482a757c690dd151d2bd5e774ada38bdc80b9020413f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e00000000000000000000000000000000081a1a01c9e9d742c8e69daba2a026ccafdde618f2e44c96db281c2209c22f183ad03a2a049a61d267d22226896d4c065525819c238784c439dc2afa7d17fce76595730d1", + "result": [ + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "gas": "0x119d28", + "input": "0x13f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1c6ff", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 5, + "traceAddress": [], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x114243", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 0 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x110d3b", + "input": "0x2b86162900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 1 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x10d833", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 2 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x10a328", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 3 + ], + "type": "call" + }, + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "gas": "0x106e1d", + "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", + "value": "0x0" + }, + "result": { + "address": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x27c3", + "output": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "subtraces": 0, + "traceAddress": [ + 4 + ], + "type": "call" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_throw_outer_revert.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_throw_outer_revert.json new file mode 100644 index 00000000000..b11b8e040dd --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_throw_outer_revert.json @@ -0,0 +1,95 @@ +{ + "context": { + "difficulty": "3956606365", + "gasLimit": "5413248", + "miner": "0x00d8ae40d9a06d0e7a2877b62e32eb959afbe16d", + "number": "2295104", + "timestamp": "1513681256" + }, + "genesis": { + "alloc": { + "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76": { + "balance": "0x0", + "code": "0x60606040526004361061015e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680625b4487146101a257806311df9995146101cb578063278ecde11461022057806330adce0e146102435780633197cbb61461026c5780634bb278f3146102955780636103d70b146102aa57806363a599a4146102bf5780636a2d1cb8146102d457806375f12b21146102fd57806378e979251461032a578063801db9cc1461035357806386d1a69f1461037c5780638da5cb5b146103915780638ef26a71146103e65780639890220b1461040f5780639b39caef14610424578063b85dfb801461044d578063be9a6555146104a1578063ccb07cef146104b6578063d06c91e4146104e3578063d669e1d414610538578063df40503c14610561578063e2982c2114610576578063f02e030d146105c3578063f2fde38b146105d8578063f3283fba14610611575b600060149054906101000a900460ff1615151561017a57600080fd5b60075442108061018b575060085442115b15151561019757600080fd5b6101a03361064a565b005b34156101ad57600080fd5b6101b5610925565b6040518082815260200191505060405180910390f35b34156101d657600080fd5b6101de61092b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561022b57600080fd5b6102416004808035906020019091905050610951565b005b341561024e57600080fd5b610256610c48565b6040518082815260200191505060405180910390f35b341561027757600080fd5b61027f610c4e565b6040518082815260200191505060405180910390f35b34156102a057600080fd5b6102a8610c54565b005b34156102b557600080fd5b6102bd610f3e565b005b34156102ca57600080fd5b6102d261105d565b005b34156102df57600080fd5b6102e76110d5565b6040518082815260200191505060405180910390f35b341561030857600080fd5b6103106110e1565b604051808215151515815260200191505060405180910390f35b341561033557600080fd5b61033d6110f4565b6040518082815260200191505060405180910390f35b341561035e57600080fd5b6103666110fa565b6040518082815260200191505060405180910390f35b341561038757600080fd5b61038f611104565b005b341561039c57600080fd5b6103a4611196565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103f157600080fd5b6103f96111bb565b6040518082815260200191505060405180910390f35b341561041a57600080fd5b6104226111c1565b005b341561042f57600080fd5b610437611296565b6040518082815260200191505060405180910390f35b341561045857600080fd5b610484600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061129c565b604051808381526020018281526020019250505060405180910390f35b34156104ac57600080fd5b6104b46112c0565b005b34156104c157600080fd5b6104c9611341565b604051808215151515815260200191505060405180910390f35b34156104ee57600080fd5b6104f6611354565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561054357600080fd5b61054b61137a565b6040518082815260200191505060405180910390f35b341561056c57600080fd5b610574611385565b005b341561058157600080fd5b6105ad600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506116c3565b6040518082815260200191505060405180910390f35b34156105ce57600080fd5b6105d66116db565b005b34156105e357600080fd5b61060f600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611829565b005b341561061c57600080fd5b610648600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506118fe565b005b600080670de0b6b3a7640000341015151561066457600080fd5b61069b610696670de0b6b3a7640000610688610258346119d990919063ffffffff16565b611a0c90919063ffffffff16565b611a27565b9150660221b262dd80006106ba60065484611a7e90919063ffffffff16565b111515156106c757600080fd5b600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15156107d557600080fd5b6102c65a03f115156107e657600080fd5b5050506040518051905050610808828260010154611a7e90919063ffffffff16565b8160010181905550610827348260000154611a7e90919063ffffffff16565b816000018190555061084434600554611a7e90919063ffffffff16565b60058190555061085f82600654611a7e90919063ffffffff16565b6006819055503373ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c836040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e8583600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60025481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060085442108061096b5750651b48eb57e00060065410155b15151561097757600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154821415156109c757600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856000604051602001526040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1515610ac857600080fd5b6102c65a03f11515610ad957600080fd5b5050506040518051905050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68836000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610b7d57600080fd5b6102c65a03f11515610b8e57600080fd5b505050604051805190501515610ba357600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055506000811115610c4457610c433382611a9c565b5b5050565b60055481565b60085481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610cb157600080fd5b600854421015610cd357660221b262dd8000600654141515610cd257600080fd5b5b651b48eb57e000600654108015610cf057506213c6806008540142105b151515610cfc57600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501515610d7557600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b1515610e3a57600080fd5b6102c65a03f11515610e4b57600080fd5b5050506040518051905090506000811115610f2057600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68826000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610ef957600080fd5b6102c65a03f11515610f0a57600080fd5b505050604051805190501515610f1f57600080fd5b5b6001600960006101000a81548160ff02191690831515021790555050565b600080339150600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114151515610f9657600080fd5b803073ffffffffffffffffffffffffffffffffffffffff163110151515610fbc57600080fd5b610fd181600254611b5090919063ffffffff16565b6002819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561105957fe5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156110b857600080fd5b6001600060146101000a81548160ff021916908315150217905550565b670de0b6b3a764000081565b600060149054906101000a900460ff1681565b60075481565b651b48eb57e00081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561115f57600080fd5b600060149054906101000a900460ff16151561117a57600080fd5b60008060146101000a81548160ff021916908315150217905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561121c57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050151561129457600080fd5b565b61025881565b600a6020528060005260406000206000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561131b57600080fd5b600060075414151561132c57600080fd5b4260078190555062278d004201600881905550565b600960009054906101000a900460ff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b660221b262dd800081565b60008060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113e557600080fd5b600654660221b262dd800003925061142b670de0b6b3a764000061141c610258670de0b6b3a76400006119d990919063ffffffff16565b81151561142557fe5b04611a27565b915081831115151561143c57600080fd5b600a60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b151561158c57600080fd5b6102c65a03f1151561159d57600080fd5b50505060405180519050506115bf838260010154611a7e90919063ffffffff16565b81600101819055506115dc83600654611a7e90919063ffffffff16565b6006819055503073ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c846040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e856000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60016020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561173657600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2fde38b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b151561181357600080fd5b6102c65a03f1151561182457600080fd5b505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561188457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156118fb57806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561195957600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561199557600080fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080828402905060008414806119fa57508284828115156119f757fe5b04145b1515611a0257fe5b8091505092915050565b6000808284811515611a1a57fe5b0490508091505092915050565b6000611a416202a300600754611a7e90919063ffffffff16565b421015611a7557611a6e611a5f600584611a0c90919063ffffffff16565b83611a7e90919063ffffffff16565b9050611a79565b8190505b919050565b6000808284019050838110151515611a9257fe5b8091505092915050565b611aee81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611a7e90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611b4681600254611a7e90919063ffffffff16565b6002819055505050565b6000828211151515611b5e57fe5b8183039050929150505600a165627a7a72305820ec0d82a406896ccf20989b3d6e650abe4dc104e400837f1f58e67ef499493ae90029", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000008d69d00910d0b2afb2a99ed6c16c8129fa8e1751", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000e819f024b41358d2c08e3a868a5c5dd0566078d4", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000005a388981", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000005a3b38e6" + } + }, + "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826": { + "balance": "0x2a2dd979a35cf000", + "code": "0x", + "nonce": "0", + "storage": {} + }, + "0xe819f024b41358d2c08e3a868a5c5dd0566078d4": { + "balance": "0x0", + "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c681461027257806370a08231146102ad5780638da5cb5b146102fa57806395d89b411461034f578063a9059cbb146103dd578063dd62ed3e14610437578063f2fde38b146104a3575b600080fd5b34156100ca57600080fd5b6100d26104dc565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610515565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba61069c565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506106a2565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610952565b6040518082815260200191505060405180910390f35b341561027d57600080fd5b6102936004808035906020019091905050610957565b604051808215151515815260200191505060405180910390f35b34156102b857600080fd5b6102e4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610abe565b6040518082815260200191505060405180910390f35b341561030557600080fd5b61030d610b07565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561035a57600080fd5b610362610b2d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103a2578082015181840152602081019050610387565b50505050905090810190601f1680156103cf5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103e857600080fd5b61041d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b66565b604051808215151515815260200191505060405180910390f35b341561044257600080fd5b61048d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d01565b6040518082815260200191505060405180910390f35b34156104ae57600080fd5b6104da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d88565b005b6040805190810160405280600b81526020017f416c6c436f6465436f696e00000000000000000000000000000000000000000081525081565b6000808214806105a157506000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054145b15156105ac57600080fd5b81600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905061077683600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061080b83600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108618382610e7d90919063ffffffff16565b600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b600681565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156109b557600080fd5b610a0782600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610a5f82600054610e7d90919063ffffffff16565b60008190555060003373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040805190810160405280600481526020017f414c4c430000000000000000000000000000000000000000000000000000000081525081565b6000610bba82600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610c4f82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610de457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515610e5c5780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000808284019050838110151515610e7357fe5b8091505092915050565b6000828211151515610e8b57fe5b8183039050929150505600a165627a7a7230582059f3ea3df0b054e9ab711f37969684ba83fe38f255ffe2c8d850d951121c51100029", + "nonce": "1", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3956606365", + "extraData": "0x566961425443", + "gasLimit": "5418523", + "hash": "0x6f37eb930a25da673ea1bb80fd9e32ddac19cdf7cd4bb2eac62cc13598624077", + "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", + "mixHash": "0x10971cde68c587c750c23b8589ae868ce82c2c646636b97e7d9856470c5297c7", + "nonce": "0x810f923ff4b450a1", + "number": "2295103", + "stateRoot": "0xff403612573d76dfdaf4fea2429b77dbe9764021ae0e38dc8ac79a3cf551179e", + "timestamp": "1513681246", + "totalDifficulty": "7162347056825919" + }, + "input": "0xf86d808504e3b292008307dfa69433056b5dcac09a9b4becad0e1dcf92c19bd0af76880e92596fd62900008029a0e5f27bb66431f7081bb7f1f242003056d7f3f35414c352cd3d1848b52716dac2a07d0be78980edb0bd2a0678fc53aa90ea9558ce346b0d947967216918ac74ccea", + "result": [ + { + "action": { + "callType": "call", + "from": "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826", + "gas": "0x78d9e", + "input": "0x", + "to": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", + "value": "0xe92596fd6290000" + }, + "blockNumber": 2295104, + "error": "execution reverted", + "result": { + "gasUsed": "0x7c1c8" + }, + "subtraces": 1, + "traceAddress": [], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", + "gas": "0x75fe3", + "input": "0xa9059cbb000000000000000000000000d4fcab9f0a6dc0493af47c864f6f17a8a5e2e82600000000000000000000000000000000000000000000000000000000000002f4", + "to": "0xe819f024b41358d2c08e3a868a5c5dd0566078d4", + "value": "0x0" + }, + "blockNumber": 0, + "error": "invalid opcode: INVALID", + "result": {}, + "subtraces": 0, + "traceAddress": [0], + "type": "call" + } + ] +} 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 new file mode 100644 index 00000000000..64425dbadda --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json @@ -0,0 +1,94 @@ +{ + "genesis": { + "difficulty": "1808543", + "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", + "gasLimit": "4875092", + "hash": "0x3851fdc18bd5f2314cf0c90439356f9a1fe157d7fb06c20e20b77954da903671", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "mixHash": "0x3d4e702d6058acf94c9547560f05536d45d515bd4f9014564ec41b5b4ff9578b", + "nonce": "0x1695153e7b16c1e7", + "number": "555461", + "stateRoot": "0xba8272acd0dfeb5f04376328e8bfc5b276b177697000c204a060f6f7b629ae32", + "timestamp": "1577423350", + "totalDifficulty": "462222992438", + "alloc": { + "0xcf5b3467dfa45cdc8e5358a7a1ba4deb02e5faed": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x16c102a3b09c02abdace", + "nonce": "19049", + "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": "555462", + "difficulty": "1808543", + "timestamp": "1577423360", + "gasLimit": "4873701", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf90451824a6985746a52880083053e908080b903fb60606040525b60405161015b806102a0833901809050604051809103906000f0600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b610247806100596000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900480632ef9db1314610044578063e37678761461007157610042565b005b61005b6004803590602001803590602001506100ad565b6040518082815260200191505060405180910390f35b61008860048035906020018035906020015061008a565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000600060008484604051808381526020018281526020019250505060405180910390209150610120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f6164640000000000000000000000000000000000000000000000000000000000846101e3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681868660405180807f616464000000000000000000000000000000000000000000000000000000000081526020015060200184815260200183815260200182815260200193505050506000604051808303816000866161da5a03f191505050600060005060008281526020019081526020016000206000505492506101db565b505092915050565b60004340848484604051808581526020018473ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140183815260200182815260200194505050505060405180910390209050610240565b9392505050566060604052610148806100136000396000f30060606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b50505681a1a0b9a85df655d3b6aa081e52d8c3db52c50c2bf97d9d993a980113b2262649c125a00d51e63880ca8ef4705914a71e7ff906834a9cdcff0cbd063ff4e43a5905890d", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0x3951c", + "init": "0x60606040525b60405161015b806102a0833901809050604051809103906000f0600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b610247806100596000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900480632ef9db1314610044578063e37678761461007157610042565b005b61005b6004803590602001803590602001506100ad565b6040518082815260200191505060405180910390f35b61008860048035906020018035906020015061008a565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000600060008484604051808381526020018281526020019250505060405180910390209150610120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f6164640000000000000000000000000000000000000000000000000000000000846101e3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681868660405180807f616464000000000000000000000000000000000000000000000000000000000081526020015060200184815260200183815260200182815260200193505050506000604051808303816000866161da5a03f191505050600060005060008281526020019081526020016000206000505492506101db565b505092915050565b60004340848484604051808581526020018473ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140183815260200182815260200194505050505060405180910390209050610240565b9392505050566060604052610148806100136000396000f30060606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b505056" + }, + "result": { + "gasUsed": "0x53e90", + "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632ef9db1314610044578063e37678761461007157610042565b005b61005b6004803590602001803590602001506100ad565b6040518082815260200191505060405180910390f35b61008860048035906020018035906020015061008a565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000600060008484604051808381526020018281526020019250505060405180910390209150610120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f6164640000000000000000000000000000000000000000000000000000000000846101e3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681868660405180807f616464000000000000000000000000000000000000000000000000000000000081526020015060200184815260200183815260200182815260200193505050506000604051808303816000866161da5a03f191505050600060005060008281526020019081526020016000206000505492506101db565b505092915050565b60004340848484604051808581526020018473ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140183815260200182815260200194505050505060405180910390209050610240565b939250505056", + "address": "0x9db7a1baf185a865ffee3824946ccd8958191e5e" + }, + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 23, + "transactionHash": "0xe267552ce8437a5bc7081385c99f912de5723ad34b958db215dbc41abd5f6c03", + "blockNumber": 555462, + "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1", + "time": "1.147715ms" + }, + { + "type": "create", + "action": { + "from": "0x9db7a1baf185a865ffee3824946ccd8958191e5e", + "value": "0x0", + "gas": "0x30b34", + "init": "0x6060604052610148806100136000396000f30060606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b505056" + }, + "result": { + "gasUsed": "0x1009d", + "code": "0x60606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b505056", + "address": "0xcf5b3467dfa45cdc8e5358a7a1ba4deb02e5faed" + }, + "traceAddress": [0], + "subtraces": 0, + "transactionPosition": 23, + "transactionHash": "0xe267552ce8437a5bc7081385c99f912de5723ad34b958db215dbc41abd5f6c03", + "blockNumber": 555462, + "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1" + } + ] +} 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 new file mode 100644 index 00000000000..bbd9904d9c7 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json @@ -0,0 +1,94 @@ +{ + "genesis": { + "difficulty": "4635413", + "extraData": "0xd683010b05846765746886676f312e3133856c696e7578", + "gasLimit": "9289294", + "hash": "0x359775cf1a2ae2400e26ec68bf33bcfe38b7979c76b7e616f42c4ca7e7605e39", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "mixHash": "0x4b2a0ef121a9c7d732fa0fbd4166a0e1041d2da2b8cb677c61edabf8b7183b64", + "nonce": "0x2a8a64ad9757be55", + "number": "1555160", + "stateRoot": "0x95067c12148e2362fcd4a89df286ff0b1739ef097a40ca42ae7f698af9a9d913", + "timestamp": "1590793999", + "totalDifficulty": "2242063623471", + "alloc": { + "0x8785e369f0ef0a4e5c5a5f929680427dc75273a5": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x623145b285b3f551fa3f", + "nonce": "260617", + "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": "1555161", + "difficulty": "4633150", + "timestamp": "1590794020", + "gasLimit": "9298364", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf85e8303fa09843b9aca0083019ed880808a6000600060006000f50081a2a0485ea410e210740eef8e6f6de11c530f46f8da80eecb02afbb6c5f61749ac015a068d72f1b0f1d3cb4e214d5def79b49a73e6ee91db2df83499a54c656c144600f", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xcf6c", + "init": "0x6000600060006000f500" + }, + "result": { + "gasUsed": "0x14c78", + "code": "0x", + "address": "0x2e8eded627eead210cb6143eb39ef7a3e44e4f00" + }, + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 31, + "transactionHash": "0x1257b698c5833c54ce786734087002b097275abc3877af082b5c2a538e894a41", + "blockNumber": 1555161, + "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171", + "time": "889.048µs" + }, + { + "type": "create", + "action": { + "from": "0x2e8eded627eead210cb6143eb39ef7a3e44e4f00", + "value": "0x0", + "gas": "0x5117", + "init": "0x" + }, + "result": { + "gasUsed": "0x0", + "code": "0x", + "address": "0x8785e369f0ef0a4e5c5a5f929680427dc75273a5" + }, + "traceAddress": [0], + "subtraces": 0, + "transactionPosition": 31, + "transactionHash": "0x1257b698c5833c54ce786734087002b097275abc3877af082b5c2a538e894a41", + "blockNumber": 1555161, + "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171" + } + ] +} 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 new file mode 100644 index 00000000000..19ae5fc5d3f --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json @@ -0,0 +1,90 @@ +{ + "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", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xcf08", + "init": "0x5a600055600060006000f0505a60015500" + }, + "error": "out of gas", + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 63, + "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", + "blockNumber": 1555170, + "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e", + "time": "952.736µs" + }, + { + "type": "create", + "action": { + "from": "0x9c5cfe45b15eaff4ad617af4250189e26024a4f8", + "value": "0x0", + "gas": "0x3cb", + "init": "0x" + }, + "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/nested_create_inerror.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json new file mode 100644 index 00000000000..a62d4bb6452 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json @@ -0,0 +1,81 @@ +{ + "genesis": { + "difficulty": "3244991", + "extraData": "0x", + "gasLimit": "7968787", + "hash": "0x62bbf18c203068a8793af8d8360d054f95a63bc62b87ade550861ed490af3f15", + "miner": "0x9f2659ffe7b3b467e46dcec3623392cf51635079", + "mixHash": "0xc8dec711fd1e03972b6a279a09dc0cd29c5171b60f42c4ce37c7c51ff445f776", + "nonce": "0x40b1bbcc25ddb804", + "number": "839246", + "stateRoot": "0x4bb3b02ec70b837651233957fb61a6ea3fc6a4244c1f55df7a713c154829ec0a", + "timestamp": "1581179375", + "totalDifficulty": "1023985623933", + "alloc": { + "0x76554b33410b6d90b7dc889bfed0451ad195f27e": { + "balance": "0x0", + "nonce": "1", + "code": "0x6080604052348015600f57600080fd5b506004361060505760003560e01c8063391521f414605557806355313dea14605d5780636d3d14161460655780638da5cb5b14606d578063b9d1e5aa1460b5575b600080fd5b605b60bd565b005b606360c8565b005b606b60ca565b005b607360cf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60bb60f4565b005b6020610123600af050565b005b600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565bfefea165627a7a723058202094d5aa5dbbd493e9a2c64c50b62eba4b109b2a12d2bb73a5d0d54982651fc80029", + "storage": {} + }, + "0xed69ab7145a9bae7152406d062c077c6ecc6ae18": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0xa3b31cbd5168d3c99756660d4b7625d679e12573": { + "balance": "0x569bc6535d3083fce", + "nonce": "26", + "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": "839247", + "difficulty": "3213311", + "timestamp": "1581179571", + "gasLimit": "7961006", + "miner": "0x9f2659ffe7b3b467e46dcec3623392cf51635079" + }, + "input": "0xf86a1a8509502f9000830334509476554b33410b6d90b7dc889bfed0451ad195f27e8084391521f481a2a02e4ff0d171a860c8c7de2283978e2f225f9ba3ed4dec446b773c6b2d73ef22dea02a6a517528b491cb71b204f534db11a1c8059035f54d5bae347d1cab536bde2c", + "result": [ + { + "type": "call", + "action": { + "from": "0xa3b31cbd5168d3c99756660d4b7625d679e12573", + "to": "0x76554b33410b6d90b7dc889bfed0451ad195f27e", + "value": "0x0", + "gas": "0x2e138", + "input": "0x391521f4", + "callType": "call" + }, + "result": { + "gasUsed": "0xd0b5", + "output": "0x" + }, + "traceAddress": [], + "subtraces": 0, + "transactionPosition": 26, + "transactionHash": "0xcb1090fa85d2a3da8326b75333e92b3dca89963c895d9c981bfdaa64643135e4", + "blockNumber": 839247, + "blockHash": "0xce7ff7d84ca97f0f89d6065e2c12409a795c9f607cdb14aef0713cad5d7e311c", + "time": "182.267µs" + } + ] +} \ 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 new file mode 100644 index 00000000000..792845538f9 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json @@ -0,0 +1,189 @@ +{ + "genesis": { + "number": "13535", + "hash": "0x6f706fe8026edb51577b57685574dc152dba4e2ebfc8a50bb63a8c95a4f8818d", + "nonce": "0x0000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "stateRoot": "0x7f54db248a004ca182fe87fdfa6efda97163908b4f0cc84b36a6d60699d5d1be", + "miner": "0x0000000000000000000000000000000000000000", + "difficulty": "1", + "totalDifficulty": "24766", + "extraData": "0xf09f928e20407072796c616273206e6f64652d3020f09f928e000000000000001d32ac3baf238e163e18ed6d77b67b0b54b08ad9781dc4ffd93c5ede1ca12c5f21b36ac39c7ebb88dff65da91f5b9461f19873a02602230b931ba388a809119f00", + "gasLimit": "8000000", + "timestamp": "1549153003", + "alloc": { + "0x0b1ba0af832d7c05fd64161e0db78e85978e8082": { + "balance": "0x0", + "nonce": "1", + "code": "0x6080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b8578063095ea7b31461014257806318160ddd1461018757806323b872dd146101ae5780632e1a7d4d146101e5578063313ce567146101fd57806370a082311461022857806395d89b4114610256578063a9059cbb1461026b578063d0e30db0146100ae578063dd62ed3e1461029c575b6100b66102d0565b005b3480156100c457600080fd5b506100cd61031f565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101075781810151838201526020016100ef565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561014e57600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff600435166024356103cb565b604080519115158252519081900360200190f35b34801561019357600080fd5b5061019c61043e565b60408051918252519081900360200190f35b3480156101ba57600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610443565b3480156101f157600080fd5b506100b66004356105e3565b34801561020957600080fd5b50610212610678565b6040805160ff9092168252519081900360200190f35b34801561023457600080fd5b5061019c73ffffffffffffffffffffffffffffffffffffffff60043516610681565b34801561026257600080fd5b506100cd610693565b34801561027757600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff6004351660243561070b565b3480156102a857600080fd5b5061019c73ffffffffffffffffffffffffffffffffffffffff6004358116906024351661071f565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103c35780601f10610398576101008083540402835291602001916103c3565b820191906000526020600020905b8154815290600101906020018083116103a657829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b303190565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081205482111561047557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104eb575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105655773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561052d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b336000908152600360205260409020548111156105ff57600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f1935050505015801561063e573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103c35780601f10610398576101008083540402835291602001916103c3565b6000610718338484610443565b9392505050565b6004602090815260009283526040808420909152908252902054815600a165627a7a72305820228981f11f47ad9630080069b0a81423fcfba5aa8e0f478a579c4bc080ba7e820029", + "storage": { + "0xbe8a6e3827dad84a671edac41a02b0f5b47b9d0339adb1e9411b9ba4e2118738": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x48bacb9266a570d521063ef5dd96e61686dbe788": { + "balance": "0x0", + "nonce": "1", + "code": "0x6080604052600436106101b65763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663288cdc9181146101bb578063297bb70b146101f15780632ac126221461021e5780633683ef8e1461024b5780633c28d8611461026d5780633e228bae1461029a5780633fd3c997146102ba5780634ac14782146102e75780634d0ae546146103075780634f9559b11461032757806350dde190146103475780636070410814610367578063642f2eaf1461039457806364a3bc15146103b457806377fcce68146103d45780637b8e3514146103f45780637e1d9808146104145780637e9d74dc1461043457806382c174d0146104615780638da5cb5b146104815780639363470214610496578063a3e20380146104b6578063b4be83d5146104d6578063bfc8bfce146104f6578063c585bb9314610516578063c75e0a8114610536578063d46b02c314610563578063d9bfa73e14610583578063db123b1a146105a3578063dd1c7d18146105c5578063e306f779146105e5578063e5fa431b146105fa578063eea086ba1461061a578063f2fde38b1461062f578063ffa1ad741461064f575b600080fd5b3480156101c757600080fd5b506101db6101d63660046148ee565b610664565b6040516101e89190615513565b60405180910390f35b3480156101fd57600080fd5b5061021161020c366004614811565b610676565b6040516101e891906157ed565b34801561022a57600080fd5b5061023e6102393660046148ee565b6107a1565b6040516101e89190615505565b34801561025757600080fd5b5061026b61026636600461492b565b6107b6565b005b34801561027957600080fd5b5061028d610288366004614a5f565b6108a3565b6040516101e891906157fb565b3480156102a657600080fd5b506102116102b5366004614b1f565b610a3a565b3480156102c657600080fd5b506102da6102d53660046149ee565b610a90565b6040516101e891906155cf565b3480156102f357600080fd5b5061026b6103023660046147dc565b610ab8565b34801561031357600080fd5b50610211610322366004614811565b610b85565b34801561033357600080fd5b5061026b6103423660046148ee565b610c75565b34801561035357600080fd5b50610211610362366004614811565b610e2a565b34801561037357600080fd5b506103876103823660046149ee565b610ebe565b6040516101e89190615425565b3480156103a057600080fd5b5061023e6103af3660046148ee565b610f0c565b3480156103c057600080fd5b506102116103cf366004614b1f565b610f21565b3480156103e057600080fd5b5061026b6103ef3660046147ac565b610fcc565b34801561040057600080fd5b5061023e61040f366004614772565b611106565b34801561042057600080fd5b5061021161042f3660046148a5565b611126565b34801561044057600080fd5b5061045461044f3660046147dc565b61128a565b6040516101e891906154f4565b34801561046d57600080fd5b5061023e61047c36600461490c565b61131f565b34801561048d57600080fd5b5061038761133f565b3480156104a257600080fd5b5061023e6104b1366004614993565b61135b565b3480156104c257600080fd5b506102116104d13660046148a5565b6118de565b3480156104e257600080fd5b506102116104f1366004614b1f565b6119f1565b34801561050257600080fd5b5061026b610511366004614b68565b611a6c565b34801561052257600080fd5b5061026b610531366004614754565b611d05565b34801561054257600080fd5b50610556610551366004614a2a565b611f30565b6040516101e8919061580a565b34801561056f57600080fd5b5061026b61057e366004614a2a565b61202a565b34801561058f57600080fd5b506101db61059e366004614772565b6120c6565b3480156105af57600080fd5b506105b86120e3565b6040516101e891906155be565b3480156105d157600080fd5b506102116105e03660046148a5565b61218e565b3480156105f157600080fd5b506101db612263565b34801561060657600080fd5b506102116106153660046148a5565b612269565b34801561062657600080fd5b506103876123db565b34801561063b57600080fd5b5061026b61064a366004614754565b6123f7565b34801561065b57600080fd5b506105b86124a8565b60046020526000908152604090205481565b61067e614386565b600080610689614386565b60005460ff16156106cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558751935091505b81831461076f57610758878381518110151561071957fe5b90602001906020020151878481518110151561073157fe5b90602001906020020151878581518110151561074957fe5b906020019060200201516124df565b9050610764848261257d565b600190910190610701565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055509392505050565b60056020526000908152604090205460ff1681565b73ffffffffffffffffffffffffffffffffffffffff831633146108465761080e848484848080601f0160208091040260200160405190810160405280939291908181526020018383808284375061135b945050505050565b1515610846576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061569d565b5050600091825260076020908152604080842073ffffffffffffffffffffffffffffffffffffffff9093168452919052902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6108ab6143af565b6108b36143de565b6108bb6143de565b6000805460ff16156108f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561016080890151610140808a01919091528901519088015261094588611f30565b925061095087611f30565b915061095a6125df565b905061096888848389612611565b61097487838388612611565b61097e88886127a9565b610992888885604001518560400151612809565b8051602081015190519195506109ad918a9186918190612990565b6020808501519081015190516109c99189918591908190612990565b6109e28882856020015186604001518860000151612aa9565b6109fb8782846020015185604001518860200151612aa9565b610a0788888387612b55565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550949350505050565b610a42614386565b6060610a4f858585612d2d565b9050608081825160208401305af48015610a8657815183526020820151602084015260408201516040840152606082015160608401525b505b509392505050565b600b6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60008054819060ff1615610af8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558151905b808214610b5857610b508382815181101515610b4157fe5b90602001906020020151612eff565b600101610b29565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550565b610b8d614386565b600080610b98614386565b60005460ff1615610bd5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558751935091505b81831461076f57610c5e8783815181101515610c1f57fe5b906020019060200201518784815181101515610c3757fe5b906020019060200201518785815181101515610c4f57fe5b90602001906020020151612f2a565b9050610c6a848261257d565b600190910190610c07565b6000805481908190819060ff1615610cb9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610cec6125df565b935073ffffffffffffffffffffffffffffffffffffffff84163314610d115733610d14565b60005b73ffffffffffffffffffffffffffffffffffffffff8086166000908152600660209081526040808320938516835292905220549093506001860192509050808211610d8b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061572d565b73ffffffffffffffffffffffffffffffffffffffff80851660008181526006602090815260408083209488168084529490915290819020859055517f82af639571738f4ebd4268fb0363d8957ebe1bbb9e78dba5ebd69eed39b154f090610df3908690615513565b60405180910390a35050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055505050565b610e32614386565b600080610e3d614386565b86519250600091505b818314610eb457610e9d8783815181101515610e5e57fe5b906020019060200201518784815181101515610e7657fe5b906020019060200201518785815181101515610e8e57fe5b90602001906020020151610a3a565b9050610ea9848261257d565b600190910190610e46565b5050509392505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff165b919050565b60096020526000908152604090205460ff1681565b610f29614386565b60005460ff1615610f66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610f9c848484612f2a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055949350505050565b6000805460ff161561100a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561103d6125df565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152600860209081526040808320948916808452949091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168715151790555192935090917fa8656e308026eeabce8f0bc18048433252318ab80ac79da0b3d3d8697dfba891906110d1908690615505565b60405180910390a35050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550565b600860209081526000928352604080842090915290825290205460ff1681565b61112e614386565b6060600080600061113d614386565b60005460ff161561117a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117815589518a919081106111b257fe5b906020019060200201516101600151945088519350600092505b828414611255578489848151811015156111e257fe5b906020019060200201516101600181905250611202888760200151612f7d565b915061122e898481518110151561121557fe5b9060200190602002015183898681518110151561074957fe5b905061123a868261257d565b6020860151881161124a57611255565b6001909201916111cc565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055509195945050505050565b606060006060600084519250826040519080825280602002602001820160405280156112d057816020015b6112bd6143de565b8152602001906001900390816112b55790505b509150600090505b808314610a88576112ff85828151811015156112f057fe5b90602001906020020151611f30565b828281518110151561130d57fe5b602090810290910101526001016112d8565b600760209081526000928352604080842090915290825290205460ff1681565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b600080600080600080600080600089511115156113a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061571d565b6113ad89612fc4565b7f010000000000000000000000000000000000000000000000000000000000000090049650600760ff88161061140f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061563d565b8660ff16600781111561141e57fe5b9550600086600781111561142e57fe5b1415611466576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061570d565b600186600781111561147457fe5b14156114bc578851156114b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157dd565b600097506118d0565b60028660078111156114ca57fe5b141561160557885160411461150b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155dd565b88600081518110151561151a57fe5b01602001517f010000000000000000000000000000000000000000000000000000000000000090819004810204945061155a89600163ffffffff61308816565b935061156d89602163ffffffff61308816565b925060018b86868660405160008152602001604052604051611592949392919061556e565b60206040516020810390808403906000865af11580156115b6573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8c811690821614995092506118d09050565b600386600781111561161357fe5b14156117b9578851604114611654576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155dd565b88600081518110151561166357fe5b01602001517f01000000000000000000000000000000000000000000000000000000000000009081900481020494506116a389600163ffffffff61308816565b93506116b689602163ffffffff61308816565b925060018b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061175757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161171a565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040805192909401829003822060008352910192839052611592945092508991899150889061556e565b60048660078111156117c757fe5b14156117df576117d88b8b8b6130d3565b97506118d0565b60058660078111156117ed57fe5b1415611850576117fc89613228565b73ffffffffffffffffffffffffffffffffffffffff808c1660009081526008602090815260408083209385168352929052205490915060ff16151561184457600097506118d0565b6117d8818c8c8c6132a1565b600686600781111561185e57fe5b141561189e5760008b815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290205460ff1697506118d0565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061563d565b505050505050509392505050565b6118e6614386565b60606000806000806118f6614386565b89600081518110151561190557fe5b906020019060200201516101400151955089519450600093505b8385146119e457858a8581518110151561193557fe5b6020908102909101015161014001528651611951908a90612f7d565b92506119948a8581518110151561196457fe5b9060200190602002015160a001518b8681518110151561198057fe5b9060200190602002015160800151856133fd565b91506119c08a858151811015156119a757fe5b90602001906020020151838a87815181101515610e8e57fe5b90506119cc878261257d565b865189116119d9576119e4565b60019093019261191f565b5050505050509392505050565b6119f9614386565b60005460ff1615611a36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610f9c8484846124df565b600a5460009073ffffffffffffffffffffffffffffffffffffffff1615611abf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b611b02611afd888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843750613453945050505050565b613694565b60008181526009602052604090205490915060ff1615611b4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061568d565b73ffffffffffffffffffffffffffffffffffffffff86163314611c1f57611ba6818785858080601f0160208091040260200160405190810160405280939291908181526020018383808284375061135b945050505050565b1515611bde576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157cd565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88161790555b6000818152600960205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555130908690869080838380828437820191505092505050600060405180830381855af49150501515611cb6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156bd565b73ffffffffffffffffffffffffffffffffffffffff86163314611cfc57600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b50505050505050565b6003546000908190819073ffffffffffffffffffffffffffffffffffffffff163314611d5d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061577d565b8392508273ffffffffffffffffffffffffffffffffffffffff1663ae25532e6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611dc457600080fd5b505af1158015611dd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611dfc9190810190614a0c565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152600b602052604090205490925073ffffffffffffffffffffffffffffffffffffffff1690508015611e81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061561d565b7fffffffff0000000000000000000000000000000000000000000000000000000082166000908152600b60205260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616179055517fd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c0319490611f2290849087906155a3565b60405180910390a150505050565b611f386143de565b611f41826136d1565b6020808301829052600091825260049052604090819020549082015260808201511515611f755760015b60ff168152610f07565b60a08201511515611f87576002611f6b565b60a0820151604082015110611f9d576005611f6b565b6101008201514210611fb0576004611f6b565b60208082015160009081526005909152604090205460ff1615611fd4576006611f6b565b610120820151825173ffffffffffffffffffffffffffffffffffffffff90811660009081526006602090815260408083206060880151909416835292905220541115612021576006611f6b565b60038152919050565b60005460ff1615612067576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561209b81612eff565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b600660209081526000928352604080842090915290825290205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156121865780601f1061215b57610100808354040283529160200191612186565b820191906000526020600020905b81548152906001019060200180831161216957829003601f168201915b505050505081565b612196614386565b606060008060006121a5614386565b8860008151811015156121b457fe5b906020019060200201516101600151945088519350600092505b828414612257578489848151811015156121e457fe5b906020019060200201516101600181905250612204888760200151612f7d565b9150612230898481518110151561221757fe5b90602001906020020151838986815181101515610e8e57fe5b905061223c868261257d565b6020860151881161224c57612257565b6001909201916121ce565b50505050509392505050565b60025481565b612271614386565b6060600080600080612281614386565b60005460ff16156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558a518b919081106122f657fe5b906020019060200201516101400151955089519450600093505b8385146123a557858a8581518110151561232657fe5b6020908102909101015161014001528651612342908a90612f7d565b92506123558a8581518110151561196457fe5b91506123818a8581518110151561236857fe5b90602001906020020151838a8781518110151561074957fe5b905061238d878261257d565b8651891161239a576123a5565b600190930192612310565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550929695505050505050565b600a5473ffffffffffffffffffffffffffffffffffffffff1681565b60035473ffffffffffffffffffffffffffffffffffffffff163314612448576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061577d565b73ffffffffffffffffffffffffffffffffffffffff8116156124a557600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b60408051808201909152600581527f322e302e30000000000000000000000000000000000000000000000000000000602082015281565b6124e7614386565b6124ef6143de565b60008060006124fd88611f30565b93506125076125df565b925061251588858589612611565b6125278860a001518560400151612f7d565b915061253387836136df565b9050612546888589848960000151612990565b61255088826136f5565b945061256788848660200151876040015189612aa9565b612572888487613756565b505050509392505050565b8151815161258b9190613864565b8252602080830151908201516125a19190613864565b6020830152604080830151908201516125ba9190613864565b6040830152606080830151908201516125d39190613864565b60609092019190915250565b600a5460009073ffffffffffffffffffffffffffffffffffffffff16818115612608578161260a565b335b9392505050565b825160ff1660031461264f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061579d565b606084015173ffffffffffffffffffffffffffffffffffffffff16156126c257606084015173ffffffffffffffffffffffffffffffffffffffff1633146126c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157ad565b602084015173ffffffffffffffffffffffffffffffffffffffff161561274d578173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff1614151561274d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155ed565b604083015115156127a35761276b836020015185600001518361135b565b15156127a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061565d565b50505050565b6127bb8260a001518260a001516138ae565b6127cd836080015183608001516138ae565b1015612805576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157bd565b5050565b6128116143af565b6000806000806128258960a0015188612f7d565b935061283a89608001518a60a0015186613909565b925061284a8860a0015187612f7d565b915061285f88608001518960a0015184613909565b90508084106128a25760208086018051839052805182018490525151865182015260808a015160a08b015187519092015161289a9290613909565b8551526128df565b845183905284516020908101859052855181015190860180519190915260a089015160808a01519151516128d69290613986565b60208087015101525b84515160208087015101516128f49190612f7d565b604086015284515160808a015160c08b0151612911929190613909565b85516040015284516020015160a08a015160e08b0151612932929190613909565b855160600152602085015151608089015160c08a0151612953929190613909565b8560200151604001818152505061297b8560200151602001518960a001518a60e00151613909565b60208601516060015250505050949350505050565b8215156129c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156dd565b82821115612a03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156cd565b8460a00151612a16856040015184613864565b1115612a4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155fd565b612a5c8560800151836138ae565b612a6a828760a001516138ae565b1115612aa2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061575d565b5050505050565b612ab7828260200151613864565b600084815260046020908152604091829020929092558681015187518451938501518584015160608701516101408c01516101608d015196518b9873ffffffffffffffffffffffffffffffffffffffff9788169897909616967f0bcc4c97732e47d9946f229edb95f5b6323f601300e4690de719993f3c37112996612b46968f96339692959194909390615433565b60405180910390a45050505050565b60018054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101008789161502019095169490940493840181900481028201810190925282815260609390929091830182828015612bfe5780601f10612bd357610100808354040283529160200191612bfe565b820191906000526020600020905b815481529060010190602001808311612be157829003601f168201915b50505050509050612c2685610140015186600001518660000151856020015160200151613a23565b61014084015184518651845160200151612c4293929190613a23565b612c5b8561014001518660000151858560400151613a23565b612c778186600001518760400151856000015160400151613a23565b612c938185600001518660400151856020015160400151613a23565b836040015173ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff161415612cfd57612cf881848760400151612cf3866000015160600151876020015160600151613864565b613a23565b612aa2565b612d1581848760400151856000015160600151613a23565b612aa281848660400151856020015160600151613a23565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b81811015612e34578351855260209485019490930192600101612e16565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b81811015612e7d578351855260209485019490930192600101612e5f565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b81811015612ec5578351855260209485019490930192600101612ea7565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b612f076143de565b612f1082611f30565b9050612f1c8282613bed565b612805828260200151613d04565b612f32614386565b612f3d8484846124df565b6020810151909150831461260a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061574d565b600082821115612fb9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061560d565b508082035b92915050565b6000808251111515613002576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156fd565b815182907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061303257fe5b016020015182517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01909252507f0100000000000000000000000000000000000000000000000000000000000000908190040290565b6000816020018351101515156130ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061562d565b50016020015190565b6040516000906060907f1626ba7e000000000000000000000000000000000000000000000000000000009061310e908790869060240161554e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093178352815191935090829081885afa8080156131ab576001811461321c57612572565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0c57414c4c45545f4552524f5200000000000000000000000000000000604052600060605260646000fd5b50505195945050505050565b60006014825110151515613268576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061578d565b613276826014845103613dab565b82517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec019092525090565b6040516000906060907f9363470200000000000000000000000000000000000000000000000000000000906132de90879087908790602401615521565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783528151919350908290818a5afa80801561337b57600181146133ec576133f1565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0f56414c494441544f525f4552524f5200000000000000000000000000604052600060605260646000fd5b825194505b50505050949350505050565b6000808311613438576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b61344b61344585846138ae565b84613e0c565b949350505050565b604080517f5a65726f45785472616e73616374696f6e2800000000000000000000000000006020808301919091527f75696e743235362073616c742c0000000000000000000000000000000000000060328301527f61646472657373207369676e6572416464726573732c00000000000000000000603f8301527f627974657320646174610000000000000000000000000000000000000000000060558301527f2900000000000000000000000000000000000000000000000000000000000000605f830152825180830384018152606090920192839052815160009384938493909282918401908083835b6020831061357c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161353f565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018019909216911617905260405191909301819003812089519097508995509093508392850191508083835b6020831061361257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016135d5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040805192909401829003822097825281019a909a525073ffffffffffffffffffffffffffffffffffffffff97909716968801969096525050606085015250506080909120919050565b600280546040517f190100000000000000000000000000000000000000000000000000000000000081529182015260228101919091526042902090565b6000612fbe611afd83613e23565b60008183106136ee578161260a565b5090919050565b6136fd614386565b6020810182905260a08301516080840151613719918491613909565b808252608084015160c0850151613731929190613909565b604082015260a083015160e084015161374b918491613909565b606082015292915050565b60018054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010087891615020190951694909404938401819004810282018101909252828152606093909290918301828280156137ff5780601f106137d4576101008083540402835291602001916137ff565b820191906000526020600020905b8154815290600101906020018083116137e257829003601f168201915b5050505050905061381f8461014001518560000151858560000151613a23565b6138388461016001518486600001518560200151613a23565b61385081856000015186604001518560400151613a23565b6127a3818486604001518560600151613a23565b6000828201838110156138a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061567d565b8091505b5092915050565b6000808315156138c157600091506138a7565b508282028284828115156138d157fe5b04146138a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061567d565b6000808311613944576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b61394f84848461427c565b15613438576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156ad565b60008083116139c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b6139cc848484614301565b15613a03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156ad565b61344b613445613a1386856138ae565b613a1e866001612f7d565b613864565b600080600083118015613a6257508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15613be5578551600310613aa2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061573d565b50506020848101517fffffffff00000000000000000000000000000000000000000000000000000000166000818152600b90925260409091205473ffffffffffffffffffffffffffffffffffffffff16801515613b2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156ed565b604051660fffffffffffe0603f885101168060840182017fa85e59e40000000000000000000000000000000000000000000000000000000083526080600484015273ffffffffffffffffffffffffffffffffffffffff8816602484015273ffffffffffffffffffffffffffffffffffffffff87166044840152856064840152608483015b81811015613bc757895181526020998a019901613baf565b61020084858403866000895af1801515613bdf573d85fd5b50505050505b505050505050565b805160009060ff16600314613c2e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061579d565b606083015173ffffffffffffffffffffffffffffffffffffffff1615613ca157606083015173ffffffffffffffffffffffffffffffffffffffff163314613ca1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157ad565b613ca96125df565b835190915073ffffffffffffffffffffffffffffffffffffffff808316911614613cff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061566d565b505050565b6000818152600560205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558281015183516101408501516101608601519351859473ffffffffffffffffffffffffffffffffffffffff9485169493909316927fdc47b3613d9fe400085f6dbdc99453462279057e6207385042827ed6b1a62cf792613d9f923392906154b7565b60405180910390a45050565b600081601401835110151515613ded576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061578d565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000808284811515613e1a57fe5b04949350505050565b604080517f4f726465722800000000000000000000000000000000000000000000000000006020808301919091527f61646472657373206d616b6572416464726573732c000000000000000000000060268301527f616464726573732074616b6572416464726573732c0000000000000000000000603b8301527f6164647265737320666565526563697069656e74416464726573732c0000000060508301527f616464726573732073656e646572416464726573732c00000000000000000000606c8301527f75696e74323536206d616b65724173736574416d6f756e742c0000000000000060828301527f75696e743235362074616b65724173736574416d6f756e742c00000000000000609b8301527f75696e74323536206d616b65724665652c00000000000000000000000000000060b48301527f75696e743235362074616b65724665652c00000000000000000000000000000060c58301527f75696e743235362065787069726174696f6e54696d655365636f6e64732c000060d68301527f75696e743235362073616c742c0000000000000000000000000000000000000060f48301527f6279746573206d616b65724173736574446174612c00000000000000000000006101018301527f62797465732074616b65724173736574446174610000000000000000000000006101168301527f290000000000000000000000000000000000000000000000000000000000000061012a830152825161010b81840301815261012b90920192839052815160009384938493849391929182918401908083835b602083106140ab57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161406e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930181900381206101408b0151805191995095509093508392850191508083835b6020831061414657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614109565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930181900381206101608b0151805191985095509093508392850191508083835b602083106141e157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016141a4565b5181516020939093036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018019909116921691909117905260405192018290039091207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0890180516101408b018051610160909c0180519a84529881529288526101a0822091529890525050509190525090919050565b6000808084116142b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b8215806142c3575084155b156142d15760009150610a88565b838015156142db57fe5b85840990506142ea85846138ae565b6142f66103e8836138ae565b101595945050505050565b60008080841161433d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b821580614348575084155b156143565760009150610a88565b8380151561436057fe5b8584099050836143708583612f7d565b81151561437957fe5b0690506142ea85846138ae565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b610120604051908101604052806143c4614386565b81526020016143d1614386565b8152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b600061260a82356158b0565b6000601f8201831361441b57600080fd5b813561442e6144298261583f565b615818565b81815260209384019390925082018360005b8381101561446c578135860161445688826145bc565b8452506020928301929190910190600101614440565b5050505092915050565b6000601f8201831361448757600080fd5b81356144956144298261583f565b81815260209384019390925082018360005b8381101561446c57813586016144bd888261460b565b84525060209283019291909101906001016144a7565b6000601f820183136144e457600080fd5b81356144f26144298261583f565b9150818183526020840193506020810190508385602084028201111561451757600080fd5b60005b8381101561446c578161452d888261454f565b845250602092830192919091019060010161451a565b600061260a82356158c9565b600061260a82356158ce565b600061260a82356158d1565b600061260a82516158d1565b600080601f8301841361458557600080fd5b50813567ffffffffffffffff81111561459d57600080fd5b6020830191508360018202830111156145b557600080fd5b9250929050565b6000601f820183136145cd57600080fd5b81356145db61442982615860565b915080825260208301602083018583830111156145f757600080fd5b614602838284615907565b50505092915050565b6000610180828403121561461e57600080fd5b614629610180615818565b9050600061463784846143fe565b8252506020614648848483016143fe565b602083015250604061465c848285016143fe565b6040830152506060614670848285016143fe565b60608301525060806146848482850161454f565b60808301525060a06146988482850161454f565b60a08301525060c06146ac8482850161454f565b60c08301525060e06146c08482850161454f565b60e0830152506101006146d58482850161454f565b610100830152506101206146eb8482850161454f565b6101208301525061014082013567ffffffffffffffff81111561470d57600080fd5b614719848285016145bc565b6101408301525061016082013567ffffffffffffffff81111561473b57600080fd5b614747848285016145bc565b6101608301525092915050565b60006020828403121561476657600080fd5b600061344b84846143fe565b6000806040838503121561478557600080fd5b600061479185856143fe565b92505060206147a2858286016143fe565b9150509250929050565b600080604083850312156147bf57600080fd5b60006147cb85856143fe565b92505060206147a285828601614543565b6000602082840312156147ee57600080fd5b813567ffffffffffffffff81111561480557600080fd5b61344b84828501614476565b60008060006060848603121561482657600080fd5b833567ffffffffffffffff81111561483d57600080fd5b61484986828701614476565b935050602084013567ffffffffffffffff81111561486657600080fd5b614872868287016144d3565b925050604084013567ffffffffffffffff81111561488f57600080fd5b61489b8682870161440a565b9150509250925092565b6000806000606084860312156148ba57600080fd5b833567ffffffffffffffff8111156148d157600080fd5b6148dd86828701614476565b93505060206148728682870161454f565b60006020828403121561490057600080fd5b600061344b848461454f565b6000806040838503121561491f57600080fd5b6000614791858561454f565b6000806000806060858703121561494157600080fd5b600061494d878761454f565b945050602061495e878288016143fe565b935050604085013567ffffffffffffffff81111561497b57600080fd5b61498787828801614573565b95989497509550505050565b6000806000606084860312156149a857600080fd5b60006149b4868661454f565b93505060206149c5868287016143fe565b925050604084013567ffffffffffffffff8111156149e257600080fd5b61489b868287016145bc565b600060208284031215614a0057600080fd5b600061344b848461455b565b600060208284031215614a1e57600080fd5b600061344b8484614567565b600060208284031215614a3c57600080fd5b813567ffffffffffffffff811115614a5357600080fd5b61344b8482850161460b565b60008060008060808587031215614a7557600080fd5b843567ffffffffffffffff811115614a8c57600080fd5b614a988782880161460b565b945050602085013567ffffffffffffffff811115614ab557600080fd5b614ac18782880161460b565b935050604085013567ffffffffffffffff811115614ade57600080fd5b614aea878288016145bc565b925050606085013567ffffffffffffffff811115614b0757600080fd5b614b13878288016145bc565b91505092959194509250565b600080600060608486031215614b3457600080fd5b833567ffffffffffffffff811115614b4b57600080fd5b614b578682870161460b565b93505060206149c58682870161454f565b60008060008060008060808789031215614b8157600080fd5b6000614b8d898961454f565b9650506020614b9e89828a016143fe565b955050604087013567ffffffffffffffff811115614bbb57600080fd5b614bc789828a01614573565b9450945050606087013567ffffffffffffffff811115614be657600080fd5b614bf289828a01614573565b92509250509295509295509295565b614c0a816158b0565b82525050565b6000614c1b826158ac565b808452602084019350614c2d836158a6565b60005b82811015614c5d57614c438683516153e5565b614c4c826158a6565b606096909601959150600101614c30565b5093949350505050565b614c0a816158c9565b614c0a816158ce565b614c0a816158d1565b6000614c8d826158ac565b808452614ca1816020860160208601615913565b614caa8161593f565b9093016020019392505050565b614c0a816158fc565b601281527f4c454e4754485f36355f52455155495245440000000000000000000000000000602082015260400190565b600d81527f494e56414c49445f54414b455200000000000000000000000000000000000000602082015260400190565b600e81527f4f524445525f4f56455246494c4c000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b601a81527f41535345545f50524f58595f414c52454144595f455849535453000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601581527f5349474e41545552455f554e535550504f525445440000000000000000000000602082015260400190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601781527f494e56414c49445f4f524445525f5349474e4154555245000000000000000000602082015260400190565b600d81527f494e56414c49445f4d414b455200000000000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b600f81527f494e56414c49445f54585f484153480000000000000000000000000000000000602082015260400190565b601181527f494e56414c49445f5349474e4154555245000000000000000000000000000000602082015260400190565b600e81527f524f554e44494e475f4552524f52000000000000000000000000000000000000602082015260400190565b601081527f4641494c45445f455845435554494f4e00000000000000000000000000000000602082015260400190565b600d81527f54414b45525f4f56455250415900000000000000000000000000000000000000602082015260400190565b601481527f494e56414c49445f54414b45525f414d4f554e54000000000000000000000000602082015260400190565b601a81527f41535345545f50524f58595f444f45535f4e4f545f4558495354000000000000602082015260400190565b602181527f475245415445525f5448414e5f5a45524f5f4c454e4754485f5245515549524560208201527f4400000000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f5349474e41545552455f494c4c4547414c000000000000000000000000000000602082015260400190565b601e81527f4c454e4754485f475245415445525f5448414e5f305f52455155495245440000602082015260400190565b601781527f494e56414c49445f4e45575f4f524445525f45504f4348000000000000000000602082015260400190565b601e81527f4c454e4754485f475245415445525f5448414e5f335f52455155495245440000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601281527f494e56414c49445f46494c4c5f50524943450000000000000000000000000000602082015260400190565b601281527f5245454e5452414e43595f494c4c4547414c0000000000000000000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4f524445525f554e46494c4c41424c4500000000000000000000000000000000602082015260400190565b600e81527f494e56414c49445f53454e444552000000000000000000000000000000000000602082015260400190565b601881527f4e454741544956455f5350524541445f52455155495245440000000000000000602082015260400190565b601481527f494e56414c49445f54585f5349474e4154555245000000000000000000000000602082015260400190565b601181527f4c454e4754485f305f5245515549524544000000000000000000000000000000602082015260400190565b805160808301906153738482614c70565b5060208201516153866020850182614c70565b5060408201516153996040850182614c70565b5060608201516127a36060850182614c70565b80516101208301906153be8482615362565b5060208201516153d16080850182615362565b5060408201516127a3610100850182614c70565b805160608301906153f6848261541c565b5060208201516154096020850182614c70565b5060408201516127a36040850182614c70565b614c0a816158f6565b60208101612fbe8284614c01565b6101008101615442828b614c01565b61544f602083018a614c01565b61545c6040830189614c70565b6154696060830188614c70565b6154766080830187614c70565b61548360a0830186614c70565b81810360c08301526154958185614c82565b905081810360e08301526154a98184614c82565b9a9950505050505050505050565b606081016154c58286614c01565b81810360208301526154d78185614c82565b905081810360408301526154eb8184614c82565b95945050505050565b6020808252810161260a8184614c10565b60208101612fbe8284614c67565b60208101612fbe8284614c70565b6060810161552f8286614c70565b61553c6020830185614c01565b81810360408301526154eb8184614c82565b6040810161555c8285614c70565b818103602083015261344b8184614c82565b6080810161557c8287614c70565b615589602083018661541c565b6155966040830185614c70565b6154eb6060830184614c70565b604081016155b18285614c79565b61260a6020830184614c01565b6020808252810161260a8184614c82565b60208101612fbe8284614cb7565b60208082528101612fbe81614cc0565b60208082528101612fbe81614cf0565b60208082528101612fbe81614d20565b60208082528101612fbe81614d50565b60208082528101612fbe81614d80565b60208082528101612fbe81614db0565b60208082528101612fbe81614e06565b60208082528101612fbe81614e36565b60208082528101612fbe81614e66565b60208082528101612fbe81614e96565b60208082528101612fbe81614ec6565b60208082528101612fbe81614ef6565b60208082528101612fbe81614f26565b60208082528101612fbe81614f56565b60208082528101612fbe81614f86565b60208082528101612fbe81614fb6565b60208082528101612fbe81614fe6565b60208082528101612fbe81615016565b60208082528101612fbe81615046565b60208082528101612fbe8161509c565b60208082528101612fbe816150cc565b60208082528101612fbe816150fc565b60208082528101612fbe8161512c565b60208082528101612fbe8161515c565b60208082528101612fbe8161518c565b60208082528101612fbe816151bc565b60208082528101612fbe816151ec565b60208082528101612fbe8161521c565b60208082528101612fbe81615272565b60208082528101612fbe816152a2565b60208082528101612fbe816152d2565b60208082528101612fbe81615302565b60208082528101612fbe81615332565b60808101612fbe8284615362565b6101208101612fbe82846153ac565b60608101612fbe82846153e5565b60405181810167ffffffffffffffff8111828210171561583757600080fd5b604052919050565b600067ffffffffffffffff82111561585657600080fd5b5060209081020190565b600067ffffffffffffffff82111561587757600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b60200190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b151590565b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b60ff1690565b6000612fbe826158b0565b82818337506000910152565b60005b8381101561592e578181015183820152602001615916565b838111156127a35750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a72305820d41ee66f45c4d1637cb6e5f109447c6d5d7fef3204a685dc442151c0f029b7da6c6578706572696d656e74616cf50037", + "storage": { + "0x1458d05345aa0372fb580f207529f32cbb6e9242890d36a93225785d4496083e": "0x0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48" + } + }, + "0x5409ed021d9299bf6814279a6a1411a7e866a631": { + "balance": "0xac6bd1cc338c2000", + "nonce": "22", + "code": "0x", + "storage": {} + }, + "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c": { + "balance": "0x0", + "nonce": "1", + "code": "0x606060405236156100965763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610098578063095ea7b31461014657806318160ddd1461018657806323b872dd146101a8578063313ce567146101ee57806370a082311461021457806395d89b411461024f578063a9059cbb146102fd578063dd62ed3e1461033d575bfe5b34156100a057fe5b6100a861037e565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014e57fe5b61017273ffffffffffffffffffffffffffffffffffffffff600435166024356103b5565b604080519115158252519081900360200190f35b341561018e57fe5b61019661042d565b60408051918252519081900360200190f35b34156101b057fe5b61017273ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610433565b604080519115158252519081900360200190f35b34156101f657fe5b6101fe6105d4565b6040805160ff9092168252519081900360200190f35b341561021c57fe5b61019673ffffffffffffffffffffffffffffffffffffffff600435166105d9565b60408051918252519081900360200190f35b341561025757fe5b6100a8610605565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561030557fe5b61017273ffffffffffffffffffffffffffffffffffffffff6004351660243561063c565b604080519115158252519081900360200190f35b341561034557fe5b61019673ffffffffffffffffffffffffffffffffffffffff60043581169060243516610727565b60408051918252519081900360200190f35b60408051808201909152601181527f30782050726f746f636f6c20546f6b656e000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60035481565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906104835750828110155b80156104b6575073ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090205483810110155b156105c65773ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220805487019055918716815220805484900390557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156105585773ffffffffffffffffffffffffffffffffffffffff808616600090815260016020908152604080832033909416835292905220805484900390555b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3600191506105cb565b600091505b5b509392505050565b601281565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff3316600090815260208190526040812054829010801590610699575073ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110155b156107185773ffffffffffffffffffffffffffffffffffffffff33811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610427565b506000610427565b5b92915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a723058201b5b70cf82a73dec658c2e60ab9a0f8e2ba01a74b66a6f5b0402f56d2ea0ffcf0029", + "storage": { + "0xd37b858806ebf992fe75c1dd1a61cc7625ea52328d19005ba6b8b62506ae5306": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "config": { + "chainId": 5, + "supportedProtocolVersions": [ + 67, + 66 + ], + "homesteadBlock": 0, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 1561651, + "berlinBlock": 4460644, + "londonBlock": 5062605, + "terminalTotalDifficulty": 10790000, + "terminalTotalDifficultyPassed": true, + "clique": { + "period": 15, + "epoch": 30000 + }, + "trustedCheckpoint": { + "sectionIndex": 210, + "sectionHead": "0xbb11eaf551a6c06f74a6c7bbfe1699cbf64b8f248b64691da916dd443176db2f", + "chtRoot": "0x9934ae326d00d9c7de2e074c0e51689efb7fa7fcba18929ff4279c27259c45e6", + "bloomRoot": "0x7fe3bd4fd45194aa8a5cfe5ac590edff1f870d3d98d3c310494e7f67613a87ff" + }, + "trustedCheckpointOracle": { + "address": "0x18ca0e045f0d772a851bc7e48357bcaab0a0795d", + "signers": [ + "0x4769bcad07e3b938b7f43eb7d278bc7cb9effb38", + "0x78d1ad571a1a09d60d9bbf25894b44e4c8859595", + "0x286834935f4a8cfb4ff4c77d5770c2775ae2b0e7", + "0xb86e2b0ab5a4b1373e40c51a7c712c70ba2f9f8e", + "0x0df8fa387c602ae62559cc4afa4972a7045d6707" + ], + "threshold": 2 + } + } + }, + "context": { + "number": "13536", + "difficulty": "1", + "timestamp": "1549153018", + "gasLimit": "8000000", + "miner": "0x0000000000000000000000000000000000000000", + "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e" + }, + "input": "0xf92e9e1684ee6b2800832c8c7f8080b92e4c60806040523480156200001157600080fd5b5060405162002d2c38038062002d2c83398101806040526200003791908101906200051d565b6000805433600160a060020a031991821617825560018054909116600160a060020a0386161790558251849084908490849081906200007e906004906020870190620003d0565b50825162000094906005906020860190620003d0565b50620000b0836010640100000000620019476200036f82021704565b9150620000cd846010640100000000620019476200036f82021704565b60028054600160a060020a03948516600160a060020a031991821617909155600380549285169290911691909117905550600154604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130181207f6070410800000000000000000000000000000000000000000000000000000000825291909216945063607041089350620001739250906004016200068e565b602060405180830381600087803b1580156200018e57600080fd5b505af1158015620001a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001c99190810190620004f4565b9050600160a060020a038116151562000219576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200021090620006b0565b60405180910390fd5b6002546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b39062000268908490600019906004016200066f565b602060405180830381600087803b1580156200028357600080fd5b505af115801562000298573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002be9190810190620005a1565b506003546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b3906200030e908490600019906004016200066f565b602060405180830381600087803b1580156200032957600080fd5b505af11580156200033e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620003649190810190620005a1565b50505050506200077a565b600081601401835110151515620003b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000210906200069e565b506014818301810151910190600160a060020a03165b92915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200041357805160ff191683800117855562000443565b8280016001018555821562000443579182015b828111156200044357825182559160200191906001019062000426565b506200045192915062000455565b5090565b6200047291905b808211156200045157600081556001016200045c565b90565b600062000483825162000711565b9392505050565b600062000483825162000742565b6000601f82018313620004aa57600080fd5b8151620004c1620004bb82620006e9565b620006c2565b91508082526020830160208301858383011115620004de57600080fd5b620004eb83828462000747565b50505092915050565b6000602082840312156200050757600080fd5b600062000515848462000475565b949350505050565b6000806000606084860312156200053357600080fd5b600062000541868662000475565b93505060208401516001604060020a038111156200055e57600080fd5b6200056c8682870162000498565b92505060408401516001604060020a038111156200058957600080fd5b620005978682870162000498565b9150509250925092565b600060208284031215620005b457600080fd5b60006200051584846200048a565b620005cd8162000711565b82525050565b620005cd816200071d565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601881527f554e524547495354455245445f41535345545f50524f58590000000000000000602082015260400190565b620005cd8162000472565b604081016200067f8285620005c2565b62000483602083018462000664565b60208101620003ca8284620005d3565b60208082528101620003ca81620005de565b60208082528101620003ca8162000634565b6040518181016001604060020a0381118282101715620006e157600080fd5b604052919050565b60006001604060020a038211156200070057600080fd5b506020601f91909101601f19160190565b600160a060020a031690565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b151590565b60005b83811015620007645781810151838201526020016200074a565b8381111562000774576000848401525b50505050565b6125a2806200078a6000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318978e8281146100c8578063630f1e6c146100f25780638da5cb5b146101125780639395525c14610134578063f2fde38b14610147575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612388565b60405180910390fd5b005b6100db6100d6366004611df1565b610167565b6040516100e9929190612488565b60405180910390f35b3480156100fe57600080fd5b506100c661010d366004611eec565b6102f7565b34801561011e57600080fd5b50610127610388565b6040516100e99190612337565b6100db610142366004611d0b565b6103a4565b34801561015357600080fd5b506100c6610162366004611ce5565b61050a565b61016f6119fa565b6101776119fa565b6000806101826105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815261025c939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b50505050508c600081518110151561024157fe5b6020908102909101015161014001519063ffffffff61069616565b156102875761026c8b8b8b6107c3565b935061028084600001518560600151610ac1565b90506102ae565b6102928b8b8b610b03565b9350836060015191506102a68883896107c3565b845190935090505b6102c2846020015184602001518888610d15565b6102e98b60008151811015156102d457fe5b90602001906020020151610140015182610f29565b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b61038383838080601f01602080910402602001604051908101604052809392919081815260200183838082843750879450610f299350505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6103ac6119fa565b6103b46119fa565b60008060006103c16105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152610441939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b156104925761046a670de0b6b3a7640000610464670de0b6b3a76400008a611045565b3461108f565b92506104778b848c6110e7565b945061048b85600001518660600151610ac1565b90506104d6565b6104ad670d2f13f7789f0000670de0b6b3a76400003461108f565b92506104ba8b848c6110e7565b9450846060015191506104ce89838a6107c3565b855190945090505b6104ea856020015185602001518989610d15565b6104fc8b60008151811015156102d457fe5b505050965096945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461055b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b73ffffffffffffffffffffffffffffffffffffffff8116156105b857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b600034116105f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612398565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b5050505050565b6000815183511480156107ba5750816040518082805190602001908083835b602083106106f257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106b5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052604051919093018190038120885190955088945090928392508401908083835b6020831061078757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161074a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b90505b92915050565b6107cb6119fa565b60608060008060008060006107de6119fa565b8a15156107ea57610ab2565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561088e5780601f106108635761010080835404028352916020019161088e565b820191906000526020600020905b81548152906001019060200180831161087157829003601f168201915b505060058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152969e509194509250840190508282801561093d5780601f106109125761010080835404028352916020019161093d565b820191906000526020600020905b81548152906001019060200180831161092057829003601f168201915b50505050509650600095508b519450600093505b838514610a7857878c8581518110151561096757fe5b6020908102909101015161014001528b5187908d908690811061098657fe5b60209081029091010151610160015261099f8b87610ac1565b9250610a068c858151811015156109b257fe5b9060200190602002015160a00151610a008e878151811015156109d157fe5b90602001906020020151608001518f888151811015156109ed57fe5b9060200190602002015160e00151610ac1565b8561128b565b9150610a418c85815181101515610a1957fe5b90602001906020020151838c87815181101515610a3257fe5b906020019060200201516112e6565b9050610a4d898261135e565b610a5f89600001518a60600151610ac1565b95508a8610610a6d57610a78565b600190930192610951565b8a861015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b50505050505050509392505050565b600082821115610afd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123b8565b50900390565b610b0b6119fa565b606080600080600080610b1c6119fa565b60008b6000815181101515610b2d57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929b5092909190830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505096508b519550600094505b848614610cdb57878c86815181101515610c0b57fe5b6020908102909101015161014001528b5187908d9087908110610c2a57fe5b6020908102909101015161016001528851610c46908c90610ac1565b9350610c898c86815181101515610c5957fe5b9060200190602002015160a001518d87815181101515610c7557fe5b90602001906020020151608001518661128b565b9250610cb58c86815181101515610c9c57fe5b90602001906020020151848c88815181101515610a3257fe5b9150610cc1898361135e565b5087518a8110610cd057610cdb565b600190940193610bf5565b8a811015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b600080808066b1a2bc2ec50000861115610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612448565b610d658888611045565b935034841115610da1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123a8565b610dab3485610ac1565b9250610dc086670de0b6b3a76400008a61108f565b915082821115610dfc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612428565b6000831115610f1f576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610e5b9086906004016124a4565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506000821115610edb5760405173ffffffffffffffffffffffffffffffffffffffff86169083156108fc029084906000818181858888f19350505050158015610ed9573d6000803e3d6000fd5b505b610ee58383610ac1565b90506000811115610f1f57604051339082156108fc029083906000818181858888f19350505050158015610f1d573d6000803e3d6000fd5b505b5050505050505050565b6000610f3b838263ffffffff6113c016565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161415610fab57610fa6838361142d565b610383565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116141561101357610fa6838361161b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123f8565b600082820183811015611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b8091505b5092915050565b60008083116110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d78584611703565b8461175e565b90505b9392505050565b6110ef6119fa565b60608060008060006110ff6119fa565b89600081518110151561110e57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929950929091908301828280156111c65780601f1061119b576101008083540402835291602001916111c6565b820191906000526020600020905b8154815290600101906020018083116111a957829003601f168201915b5050505050945089519350600092505b82841461127e57858a848151811015156111ec57fe5b602090810290910101516101400152895185908b908590811061120b57fe5b90602001906020020151610160018190525061122b898860200151610ac1565b91506112578a8481518110151561123e57fe5b90602001906020020151838a86815181101515610a3257fe5b9050611263878261135e565b602087015189116112735761127e565b6001909201916111d6565b5050505050509392505050565b60008083116112c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d76112d68685611703565b6112e1866001610ac1565b611045565b6112ee6119fa565b606060006112fd868686611775565b600154815191935073ffffffffffffffffffffffffffffffffffffffff1691506080908390602082016000855af1801561135457825184526020830151602085015260408301516040850152606083015160608501525b5050509392505050565b8151815161136c9190611045565b8252602080830151908201516113829190611045565b60208301526040808301519082015161139b9190611045565b6040830152606080830151908201516113b49190611045565b60609092019190915250565b600081600401835110151515611402576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612468565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b60008061144184601063ffffffff61194716565b604080517f7472616e7366657228616464726573732c75696e7432353629000000000000008152905190819003601901812091935073ffffffffffffffffffffffffffffffffffffffff8416919061149f903390879060240161236d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783525181519192909182919080838360005b8381101561154357818101518382015260200161152b565b50505050905090810190601f1680156115705780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1925050508015156115bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b3d156115dc575060003d602014156115dc5760206000803e506000515b801515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b50505050565b60008060018314611658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612478565b61166984601063ffffffff61194716565b915061167c84602463ffffffff6119a816565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd906116d590309033908690600401612345565b600060405180830381600087803b1580156116ef57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b6000808315156117165760009150611088565b5082820282848281151561172657fe5b0414611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b600080828481151561176c57fe5b04949350505050565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b8181101561187c57835185526020948501949093019260010161185e565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b818110156118c55783518552602094850194909301926001016118a7565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b8181101561190d5783518552602094850194909301926001016118ef565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b600081601401835110151515611989576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612458565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006107ba83836000816020018351101515156119f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123c8565b50016020015190565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b60006107ba8235612540565b6000601f82018313611a4057600080fd5b8135611a53611a4e826124d9565b6124b2565b81815260209384019390925082018360005b83811015611a915781358601611a7b8882611b41565b8452506020928301929190910190600101611a65565b5050505092915050565b6000601f82018313611aac57600080fd5b8135611aba611a4e826124d9565b81815260209384019390925082018360005b83811015611a915781358601611ae28882611b90565b8452506020928301929190910190600101611acc565b600080601f83018413611b0a57600080fd5b50813567ffffffffffffffff811115611b2257600080fd5b602083019150836001820283011115611b3a57600080fd5b9250929050565b6000601f82018313611b5257600080fd5b8135611b60611a4e826124fa565b91508082526020830160208301858383011115611b7c57600080fd5b611b8783828461255c565b50505092915050565b60006101808284031215611ba357600080fd5b611bae6101806124b2565b90506000611bbc8484611a23565b8252506020611bcd84848301611a23565b6020830152506040611be184828501611a23565b6040830152506060611bf584828501611a23565b6060830152506080611c0984828501611cd9565b60808301525060a0611c1d84828501611cd9565b60a08301525060c0611c3184828501611cd9565b60c08301525060e0611c4584828501611cd9565b60e083015250610100611c5a84828501611cd9565b61010083015250610120611c7084828501611cd9565b6101208301525061014082013567ffffffffffffffff811115611c9257600080fd5b611c9e84828501611b41565b6101408301525061016082013567ffffffffffffffff811115611cc057600080fd5b611ccc84828501611b41565b6101608301525092915050565b60006107ba8235612559565b600060208284031215611cf757600080fd5b6000611d038484611a23565b949350505050565b60008060008060008060c08789031215611d2457600080fd5b863567ffffffffffffffff811115611d3b57600080fd5b611d4789828a01611a9b565b965050602087013567ffffffffffffffff811115611d6457600080fd5b611d7089828a01611a2f565b955050604087013567ffffffffffffffff811115611d8d57600080fd5b611d9989828a01611a9b565b945050606087013567ffffffffffffffff811115611db657600080fd5b611dc289828a01611a2f565b9350506080611dd389828a01611cd9565b92505060a0611de489828a01611a23565b9150509295509295509295565b600080600080600080600060e0888a031215611e0c57600080fd5b873567ffffffffffffffff811115611e2357600080fd5b611e2f8a828b01611a9b565b9750506020611e408a828b01611cd9565b965050604088013567ffffffffffffffff811115611e5d57600080fd5b611e698a828b01611a2f565b955050606088013567ffffffffffffffff811115611e8657600080fd5b611e928a828b01611a9b565b945050608088013567ffffffffffffffff811115611eaf57600080fd5b611ebb8a828b01611a2f565b93505060a0611ecc8a828b01611cd9565b92505060c0611edd8a828b01611a23565b91505092959891949750929550565b600080600060408486031215611f0157600080fd5b833567ffffffffffffffff811115611f1857600080fd5b611f2486828701611af8565b93509350506020611f3786828701611cd9565b9150509250925092565b611f4a81612540565b82525050565b602381527f44454641554c545f46554e4354494f4e5f574554485f434f4e54524143545f4f60208201527f4e4c590000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f494e56414c49445f4d53475f56414c5545000000000000000000000000000000602082015260400190565b600d81527f4f564552534f4c445f5745544800000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b600f81527f5452414e534645525f4641494c45440000000000000000000000000000000000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601a81527f494e53554646494349454e545f4554485f52454d41494e494e47000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b601881527f4645455f50455243454e544147455f544f4f5f4c415247450000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160808301906122f9848261232e565b50602082015161230c602085018261232e565b50604082015161231f604085018261232e565b50606082015161161560608501825b611f4a81612559565b602081016107bd8284611f41565b606081016123538286611f41565b6123606020830185611f41565b611d03604083018461232e565b6040810161237b8285611f41565b6110e0602083018461232e565b602080825281016107bd81611f50565b602080825281016107bd81611fa6565b602080825281016107bd81611fd6565b602080825281016107bd81612006565b602080825281016107bd81612036565b602080825281016107bd8161208c565b602080825281016107bd816120bc565b602080825281016107bd816120ec565b602080825281016107bd8161211c565b602080825281016107bd8161214c565b602080825281016107bd8161217c565b602080825281016107bd816121ac565b602080825281016107bd816121dc565b602080825281016107bd8161220c565b602080825281016107bd81612262565b602080825281016107bd816122b8565b610100810161249782856122e8565b6110e060808301846122e8565b602081016107bd828461232e565b60405181810167ffffffffffffffff811182821017156124d157600080fd5b604052919050565b600067ffffffffffffffff8211156124f057600080fd5b5060209081020190565b600067ffffffffffffffff82111561251157600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b828183375060009101525600a265627a7a72305820d9f418f11e0f91f06f6f9d22924be0add925495eeb76a6388b5417adb505eeb36c6578706572696d656e74616cf5003700000000000000000000000048bacb9266a570d521063ef5dd96e61686dbe788000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082000000000000000000000000000000000000000000000000000000001ba0a7c6b0c9a5cb47eb4a8449556851a943353640d4fe93a64eb89eff56245c27f1a00e0d13877bfb8842dc394fd206d041b1f76be95a371eff128c8c34812a1b24c8", + "result": [ + { + "action": { + "from": "0x5409ed021d9299bf6814279a6a1411a7e866a631", + "gas": "0x215c47", + "init": "0x60806040523480156200001157600080fd5b5060405162002d2c38038062002d2c83398101806040526200003791908101906200051d565b6000805433600160a060020a031991821617825560018054909116600160a060020a0386161790558251849084908490849081906200007e906004906020870190620003d0565b50825162000094906005906020860190620003d0565b50620000b0836010640100000000620019476200036f82021704565b9150620000cd846010640100000000620019476200036f82021704565b60028054600160a060020a03948516600160a060020a031991821617909155600380549285169290911691909117905550600154604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130181207f6070410800000000000000000000000000000000000000000000000000000000825291909216945063607041089350620001739250906004016200068e565b602060405180830381600087803b1580156200018e57600080fd5b505af1158015620001a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001c99190810190620004f4565b9050600160a060020a038116151562000219576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200021090620006b0565b60405180910390fd5b6002546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b39062000268908490600019906004016200066f565b602060405180830381600087803b1580156200028357600080fd5b505af115801562000298573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002be9190810190620005a1565b506003546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b3906200030e908490600019906004016200066f565b602060405180830381600087803b1580156200032957600080fd5b505af11580156200033e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620003649190810190620005a1565b50505050506200077a565b600081601401835110151515620003b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000210906200069e565b506014818301810151910190600160a060020a03165b92915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200041357805160ff191683800117855562000443565b8280016001018555821562000443579182015b828111156200044357825182559160200191906001019062000426565b506200045192915062000455565b5090565b6200047291905b808211156200045157600081556001016200045c565b90565b600062000483825162000711565b9392505050565b600062000483825162000742565b6000601f82018313620004aa57600080fd5b8151620004c1620004bb82620006e9565b620006c2565b91508082526020830160208301858383011115620004de57600080fd5b620004eb83828462000747565b50505092915050565b6000602082840312156200050757600080fd5b600062000515848462000475565b949350505050565b6000806000606084860312156200053357600080fd5b600062000541868662000475565b93505060208401516001604060020a038111156200055e57600080fd5b6200056c8682870162000498565b92505060408401516001604060020a038111156200058957600080fd5b620005978682870162000498565b9150509250925092565b600060208284031215620005b457600080fd5b60006200051584846200048a565b620005cd8162000711565b82525050565b620005cd816200071d565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601881527f554e524547495354455245445f41535345545f50524f58590000000000000000602082015260400190565b620005cd8162000472565b604081016200067f8285620005c2565b62000483602083018462000664565b60208101620003ca8284620005d3565b60208082528101620003ca81620005de565b60208082528101620003ca8162000634565b6040518181016001604060020a0381118282101715620006e157600080fd5b604052919050565b60006001604060020a038211156200070057600080fd5b506020601f91909101601f19160190565b600160a060020a031690565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b151590565b60005b83811015620007645781810151838201526020016200074a565b8381111562000774576000848401525b50505050565b6125a2806200078a6000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318978e8281146100c8578063630f1e6c146100f25780638da5cb5b146101125780639395525c14610134578063f2fde38b14610147575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612388565b60405180910390fd5b005b6100db6100d6366004611df1565b610167565b6040516100e9929190612488565b60405180910390f35b3480156100fe57600080fd5b506100c661010d366004611eec565b6102f7565b34801561011e57600080fd5b50610127610388565b6040516100e99190612337565b6100db610142366004611d0b565b6103a4565b34801561015357600080fd5b506100c6610162366004611ce5565b61050a565b61016f6119fa565b6101776119fa565b6000806101826105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815261025c939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b50505050508c600081518110151561024157fe5b6020908102909101015161014001519063ffffffff61069616565b156102875761026c8b8b8b6107c3565b935061028084600001518560600151610ac1565b90506102ae565b6102928b8b8b610b03565b9350836060015191506102a68883896107c3565b845190935090505b6102c2846020015184602001518888610d15565b6102e98b60008151811015156102d457fe5b90602001906020020151610140015182610f29565b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b61038383838080601f01602080910402602001604051908101604052809392919081815260200183838082843750879450610f299350505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6103ac6119fa565b6103b46119fa565b60008060006103c16105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152610441939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b156104925761046a670de0b6b3a7640000610464670de0b6b3a76400008a611045565b3461108f565b92506104778b848c6110e7565b945061048b85600001518660600151610ac1565b90506104d6565b6104ad670d2f13f7789f0000670de0b6b3a76400003461108f565b92506104ba8b848c6110e7565b9450846060015191506104ce89838a6107c3565b855190945090505b6104ea856020015185602001518989610d15565b6104fc8b60008151811015156102d457fe5b505050965096945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461055b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b73ffffffffffffffffffffffffffffffffffffffff8116156105b857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b600034116105f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612398565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b5050505050565b6000815183511480156107ba5750816040518082805190602001908083835b602083106106f257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106b5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052604051919093018190038120885190955088945090928392508401908083835b6020831061078757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161074a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b90505b92915050565b6107cb6119fa565b60608060008060008060006107de6119fa565b8a15156107ea57610ab2565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561088e5780601f106108635761010080835404028352916020019161088e565b820191906000526020600020905b81548152906001019060200180831161087157829003601f168201915b505060058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152969e509194509250840190508282801561093d5780601f106109125761010080835404028352916020019161093d565b820191906000526020600020905b81548152906001019060200180831161092057829003601f168201915b50505050509650600095508b519450600093505b838514610a7857878c8581518110151561096757fe5b6020908102909101015161014001528b5187908d908690811061098657fe5b60209081029091010151610160015261099f8b87610ac1565b9250610a068c858151811015156109b257fe5b9060200190602002015160a00151610a008e878151811015156109d157fe5b90602001906020020151608001518f888151811015156109ed57fe5b9060200190602002015160e00151610ac1565b8561128b565b9150610a418c85815181101515610a1957fe5b90602001906020020151838c87815181101515610a3257fe5b906020019060200201516112e6565b9050610a4d898261135e565b610a5f89600001518a60600151610ac1565b95508a8610610a6d57610a78565b600190930192610951565b8a861015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b50505050505050509392505050565b600082821115610afd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123b8565b50900390565b610b0b6119fa565b606080600080600080610b1c6119fa565b60008b6000815181101515610b2d57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929b5092909190830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505096508b519550600094505b848614610cdb57878c86815181101515610c0b57fe5b6020908102909101015161014001528b5187908d9087908110610c2a57fe5b6020908102909101015161016001528851610c46908c90610ac1565b9350610c898c86815181101515610c5957fe5b9060200190602002015160a001518d87815181101515610c7557fe5b90602001906020020151608001518661128b565b9250610cb58c86815181101515610c9c57fe5b90602001906020020151848c88815181101515610a3257fe5b9150610cc1898361135e565b5087518a8110610cd057610cdb565b600190940193610bf5565b8a811015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b600080808066b1a2bc2ec50000861115610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612448565b610d658888611045565b935034841115610da1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123a8565b610dab3485610ac1565b9250610dc086670de0b6b3a76400008a61108f565b915082821115610dfc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612428565b6000831115610f1f576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610e5b9086906004016124a4565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506000821115610edb5760405173ffffffffffffffffffffffffffffffffffffffff86169083156108fc029084906000818181858888f19350505050158015610ed9573d6000803e3d6000fd5b505b610ee58383610ac1565b90506000811115610f1f57604051339082156108fc029083906000818181858888f19350505050158015610f1d573d6000803e3d6000fd5b505b5050505050505050565b6000610f3b838263ffffffff6113c016565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161415610fab57610fa6838361142d565b610383565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116141561101357610fa6838361161b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123f8565b600082820183811015611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b8091505b5092915050565b60008083116110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d78584611703565b8461175e565b90505b9392505050565b6110ef6119fa565b60608060008060006110ff6119fa565b89600081518110151561110e57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929950929091908301828280156111c65780601f1061119b576101008083540402835291602001916111c6565b820191906000526020600020905b8154815290600101906020018083116111a957829003601f168201915b5050505050945089519350600092505b82841461127e57858a848151811015156111ec57fe5b602090810290910101516101400152895185908b908590811061120b57fe5b90602001906020020151610160018190525061122b898860200151610ac1565b91506112578a8481518110151561123e57fe5b90602001906020020151838a86815181101515610a3257fe5b9050611263878261135e565b602087015189116112735761127e565b6001909201916111d6565b5050505050509392505050565b60008083116112c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d76112d68685611703565b6112e1866001610ac1565b611045565b6112ee6119fa565b606060006112fd868686611775565b600154815191935073ffffffffffffffffffffffffffffffffffffffff1691506080908390602082016000855af1801561135457825184526020830151602085015260408301516040850152606083015160608501525b5050509392505050565b8151815161136c9190611045565b8252602080830151908201516113829190611045565b60208301526040808301519082015161139b9190611045565b6040830152606080830151908201516113b49190611045565b60609092019190915250565b600081600401835110151515611402576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612468565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b60008061144184601063ffffffff61194716565b604080517f7472616e7366657228616464726573732c75696e7432353629000000000000008152905190819003601901812091935073ffffffffffffffffffffffffffffffffffffffff8416919061149f903390879060240161236d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783525181519192909182919080838360005b8381101561154357818101518382015260200161152b565b50505050905090810190601f1680156115705780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1925050508015156115bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b3d156115dc575060003d602014156115dc5760206000803e506000515b801515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b50505050565b60008060018314611658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612478565b61166984601063ffffffff61194716565b915061167c84602463ffffffff6119a816565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd906116d590309033908690600401612345565b600060405180830381600087803b1580156116ef57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b6000808315156117165760009150611088565b5082820282848281151561172657fe5b0414611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b600080828481151561176c57fe5b04949350505050565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b8181101561187c57835185526020948501949093019260010161185e565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b818110156118c55783518552602094850194909301926001016118a7565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b8181101561190d5783518552602094850194909301926001016118ef565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b600081601401835110151515611989576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612458565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006107ba83836000816020018351101515156119f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123c8565b50016020015190565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b60006107ba8235612540565b6000601f82018313611a4057600080fd5b8135611a53611a4e826124d9565b6124b2565b81815260209384019390925082018360005b83811015611a915781358601611a7b8882611b41565b8452506020928301929190910190600101611a65565b5050505092915050565b6000601f82018313611aac57600080fd5b8135611aba611a4e826124d9565b81815260209384019390925082018360005b83811015611a915781358601611ae28882611b90565b8452506020928301929190910190600101611acc565b600080601f83018413611b0a57600080fd5b50813567ffffffffffffffff811115611b2257600080fd5b602083019150836001820283011115611b3a57600080fd5b9250929050565b6000601f82018313611b5257600080fd5b8135611b60611a4e826124fa565b91508082526020830160208301858383011115611b7c57600080fd5b611b8783828461255c565b50505092915050565b60006101808284031215611ba357600080fd5b611bae6101806124b2565b90506000611bbc8484611a23565b8252506020611bcd84848301611a23565b6020830152506040611be184828501611a23565b6040830152506060611bf584828501611a23565b6060830152506080611c0984828501611cd9565b60808301525060a0611c1d84828501611cd9565b60a08301525060c0611c3184828501611cd9565b60c08301525060e0611c4584828501611cd9565b60e083015250610100611c5a84828501611cd9565b61010083015250610120611c7084828501611cd9565b6101208301525061014082013567ffffffffffffffff811115611c9257600080fd5b611c9e84828501611b41565b6101408301525061016082013567ffffffffffffffff811115611cc057600080fd5b611ccc84828501611b41565b6101608301525092915050565b60006107ba8235612559565b600060208284031215611cf757600080fd5b6000611d038484611a23565b949350505050565b60008060008060008060c08789031215611d2457600080fd5b863567ffffffffffffffff811115611d3b57600080fd5b611d4789828a01611a9b565b965050602087013567ffffffffffffffff811115611d6457600080fd5b611d7089828a01611a2f565b955050604087013567ffffffffffffffff811115611d8d57600080fd5b611d9989828a01611a9b565b945050606087013567ffffffffffffffff811115611db657600080fd5b611dc289828a01611a2f565b9350506080611dd389828a01611cd9565b92505060a0611de489828a01611a23565b9150509295509295509295565b600080600080600080600060e0888a031215611e0c57600080fd5b873567ffffffffffffffff811115611e2357600080fd5b611e2f8a828b01611a9b565b9750506020611e408a828b01611cd9565b965050604088013567ffffffffffffffff811115611e5d57600080fd5b611e698a828b01611a2f565b955050606088013567ffffffffffffffff811115611e8657600080fd5b611e928a828b01611a9b565b945050608088013567ffffffffffffffff811115611eaf57600080fd5b611ebb8a828b01611a2f565b93505060a0611ecc8a828b01611cd9565b92505060c0611edd8a828b01611a23565b91505092959891949750929550565b600080600060408486031215611f0157600080fd5b833567ffffffffffffffff811115611f1857600080fd5b611f2486828701611af8565b93509350506020611f3786828701611cd9565b9150509250925092565b611f4a81612540565b82525050565b602381527f44454641554c545f46554e4354494f4e5f574554485f434f4e54524143545f4f60208201527f4e4c590000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f494e56414c49445f4d53475f56414c5545000000000000000000000000000000602082015260400190565b600d81527f4f564552534f4c445f5745544800000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b600f81527f5452414e534645525f4641494c45440000000000000000000000000000000000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601a81527f494e53554646494349454e545f4554485f52454d41494e494e47000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b601881527f4645455f50455243454e544147455f544f4f5f4c415247450000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160808301906122f9848261232e565b50602082015161230c602085018261232e565b50604082015161231f604085018261232e565b50606082015161161560608501825b611f4a81612559565b602081016107bd8284611f41565b606081016123538286611f41565b6123606020830185611f41565b611d03604083018461232e565b6040810161237b8285611f41565b6110e0602083018461232e565b602080825281016107bd81611f50565b602080825281016107bd81611fa6565b602080825281016107bd81611fd6565b602080825281016107bd81612006565b602080825281016107bd81612036565b602080825281016107bd8161208c565b602080825281016107bd816120bc565b602080825281016107bd816120ec565b602080825281016107bd8161211c565b602080825281016107bd8161214c565b602080825281016107bd8161217c565b602080825281016107bd816121ac565b602080825281016107bd816121dc565b602080825281016107bd8161220c565b602080825281016107bd81612262565b602080825281016107bd816122b8565b610100810161249782856122e8565b6110e060808301846122e8565b602081016107bd828461232e565b60405181810167ffffffffffffffff811182821017156124d157600080fd5b604052919050565b600067ffffffffffffffff8211156124f057600080fd5b5060209081020190565b600067ffffffffffffffff82111561251157600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b828183375060009101525600a265627a7a72305820d9f418f11e0f91f06f6f9d22924be0add925495eeb76a6388b5417adb505eeb36c6578706572696d656e74616cf5003700000000000000000000000048bacb9266a570d521063ef5dd96e61686dbe788000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e808200000000000000000000000000000000000000000000000000000000", + "value": "0x0" + }, + "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", + "blockNumber": 13536, + "result": { + "address": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", + "code": "0x60806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318978e8281146100c8578063630f1e6c146100f25780638da5cb5b146101125780639395525c14610134578063f2fde38b14610147575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612388565b60405180910390fd5b005b6100db6100d6366004611df1565b610167565b6040516100e9929190612488565b60405180910390f35b3480156100fe57600080fd5b506100c661010d366004611eec565b6102f7565b34801561011e57600080fd5b50610127610388565b6040516100e99190612337565b6100db610142366004611d0b565b6103a4565b34801561015357600080fd5b506100c6610162366004611ce5565b61050a565b61016f6119fa565b6101776119fa565b6000806101826105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815261025c939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b50505050508c600081518110151561024157fe5b6020908102909101015161014001519063ffffffff61069616565b156102875761026c8b8b8b6107c3565b935061028084600001518560600151610ac1565b90506102ae565b6102928b8b8b610b03565b9350836060015191506102a68883896107c3565b845190935090505b6102c2846020015184602001518888610d15565b6102e98b60008151811015156102d457fe5b90602001906020020151610140015182610f29565b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b61038383838080601f01602080910402602001604051908101604052809392919081815260200183838082843750879450610f299350505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6103ac6119fa565b6103b46119fa565b60008060006103c16105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152610441939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b156104925761046a670de0b6b3a7640000610464670de0b6b3a76400008a611045565b3461108f565b92506104778b848c6110e7565b945061048b85600001518660600151610ac1565b90506104d6565b6104ad670d2f13f7789f0000670de0b6b3a76400003461108f565b92506104ba8b848c6110e7565b9450846060015191506104ce89838a6107c3565b855190945090505b6104ea856020015185602001518989610d15565b6104fc8b60008151811015156102d457fe5b505050965096945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461055b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b73ffffffffffffffffffffffffffffffffffffffff8116156105b857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b600034116105f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612398565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b5050505050565b6000815183511480156107ba5750816040518082805190602001908083835b602083106106f257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106b5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052604051919093018190038120885190955088945090928392508401908083835b6020831061078757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161074a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b90505b92915050565b6107cb6119fa565b60608060008060008060006107de6119fa565b8a15156107ea57610ab2565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561088e5780601f106108635761010080835404028352916020019161088e565b820191906000526020600020905b81548152906001019060200180831161087157829003601f168201915b505060058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152969e509194509250840190508282801561093d5780601f106109125761010080835404028352916020019161093d565b820191906000526020600020905b81548152906001019060200180831161092057829003601f168201915b50505050509650600095508b519450600093505b838514610a7857878c8581518110151561096757fe5b6020908102909101015161014001528b5187908d908690811061098657fe5b60209081029091010151610160015261099f8b87610ac1565b9250610a068c858151811015156109b257fe5b9060200190602002015160a00151610a008e878151811015156109d157fe5b90602001906020020151608001518f888151811015156109ed57fe5b9060200190602002015160e00151610ac1565b8561128b565b9150610a418c85815181101515610a1957fe5b90602001906020020151838c87815181101515610a3257fe5b906020019060200201516112e6565b9050610a4d898261135e565b610a5f89600001518a60600151610ac1565b95508a8610610a6d57610a78565b600190930192610951565b8a861015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b50505050505050509392505050565b600082821115610afd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123b8565b50900390565b610b0b6119fa565b606080600080600080610b1c6119fa565b60008b6000815181101515610b2d57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929b5092909190830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505096508b519550600094505b848614610cdb57878c86815181101515610c0b57fe5b6020908102909101015161014001528b5187908d9087908110610c2a57fe5b6020908102909101015161016001528851610c46908c90610ac1565b9350610c898c86815181101515610c5957fe5b9060200190602002015160a001518d87815181101515610c7557fe5b90602001906020020151608001518661128b565b9250610cb58c86815181101515610c9c57fe5b90602001906020020151848c88815181101515610a3257fe5b9150610cc1898361135e565b5087518a8110610cd057610cdb565b600190940193610bf5565b8a811015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b600080808066b1a2bc2ec50000861115610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612448565b610d658888611045565b935034841115610da1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123a8565b610dab3485610ac1565b9250610dc086670de0b6b3a76400008a61108f565b915082821115610dfc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612428565b6000831115610f1f576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610e5b9086906004016124a4565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506000821115610edb5760405173ffffffffffffffffffffffffffffffffffffffff86169083156108fc029084906000818181858888f19350505050158015610ed9573d6000803e3d6000fd5b505b610ee58383610ac1565b90506000811115610f1f57604051339082156108fc029083906000818181858888f19350505050158015610f1d573d6000803e3d6000fd5b505b5050505050505050565b6000610f3b838263ffffffff6113c016565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161415610fab57610fa6838361142d565b610383565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116141561101357610fa6838361161b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123f8565b600082820183811015611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b8091505b5092915050565b60008083116110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d78584611703565b8461175e565b90505b9392505050565b6110ef6119fa565b60608060008060006110ff6119fa565b89600081518110151561110e57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929950929091908301828280156111c65780601f1061119b576101008083540402835291602001916111c6565b820191906000526020600020905b8154815290600101906020018083116111a957829003601f168201915b5050505050945089519350600092505b82841461127e57858a848151811015156111ec57fe5b602090810290910101516101400152895185908b908590811061120b57fe5b90602001906020020151610160018190525061122b898860200151610ac1565b91506112578a8481518110151561123e57fe5b90602001906020020151838a86815181101515610a3257fe5b9050611263878261135e565b602087015189116112735761127e565b6001909201916111d6565b5050505050509392505050565b60008083116112c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d76112d68685611703565b6112e1866001610ac1565b611045565b6112ee6119fa565b606060006112fd868686611775565b600154815191935073ffffffffffffffffffffffffffffffffffffffff1691506080908390602082016000855af1801561135457825184526020830151602085015260408301516040850152606083015160608501525b5050509392505050565b8151815161136c9190611045565b8252602080830151908201516113829190611045565b60208301526040808301519082015161139b9190611045565b6040830152606080830151908201516113b49190611045565b60609092019190915250565b600081600401835110151515611402576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612468565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b60008061144184601063ffffffff61194716565b604080517f7472616e7366657228616464726573732c75696e7432353629000000000000008152905190819003601901812091935073ffffffffffffffffffffffffffffffffffffffff8416919061149f903390879060240161236d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783525181519192909182919080838360005b8381101561154357818101518382015260200161152b565b50505050905090810190601f1680156115705780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1925050508015156115bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b3d156115dc575060003d602014156115dc5760206000803e506000515b801515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b50505050565b60008060018314611658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612478565b61166984601063ffffffff61194716565b915061167c84602463ffffffff6119a816565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd906116d590309033908690600401612345565b600060405180830381600087803b1580156116ef57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b6000808315156117165760009150611088565b5082820282848281151561172657fe5b0414611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b600080828481151561176c57fe5b04949350505050565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b8181101561187c57835185526020948501949093019260010161185e565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b818110156118c55783518552602094850194909301926001016118a7565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b8181101561190d5783518552602094850194909301926001016118ef565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b600081601401835110151515611989576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612458565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006107ba83836000816020018351101515156119f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123c8565b50016020015190565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b60006107ba8235612540565b6000601f82018313611a4057600080fd5b8135611a53611a4e826124d9565b6124b2565b81815260209384019390925082018360005b83811015611a915781358601611a7b8882611b41565b8452506020928301929190910190600101611a65565b5050505092915050565b6000601f82018313611aac57600080fd5b8135611aba611a4e826124d9565b81815260209384019390925082018360005b83811015611a915781358601611ae28882611b90565b8452506020928301929190910190600101611acc565b600080601f83018413611b0a57600080fd5b50813567ffffffffffffffff811115611b2257600080fd5b602083019150836001820283011115611b3a57600080fd5b9250929050565b6000601f82018313611b5257600080fd5b8135611b60611a4e826124fa565b91508082526020830160208301858383011115611b7c57600080fd5b611b8783828461255c565b50505092915050565b60006101808284031215611ba357600080fd5b611bae6101806124b2565b90506000611bbc8484611a23565b8252506020611bcd84848301611a23565b6020830152506040611be184828501611a23565b6040830152506060611bf584828501611a23565b6060830152506080611c0984828501611cd9565b60808301525060a0611c1d84828501611cd9565b60a08301525060c0611c3184828501611cd9565b60c08301525060e0611c4584828501611cd9565b60e083015250610100611c5a84828501611cd9565b61010083015250610120611c7084828501611cd9565b6101208301525061014082013567ffffffffffffffff811115611c9257600080fd5b611c9e84828501611b41565b6101408301525061016082013567ffffffffffffffff811115611cc057600080fd5b611ccc84828501611b41565b6101608301525092915050565b60006107ba8235612559565b600060208284031215611cf757600080fd5b6000611d038484611a23565b949350505050565b60008060008060008060c08789031215611d2457600080fd5b863567ffffffffffffffff811115611d3b57600080fd5b611d4789828a01611a9b565b965050602087013567ffffffffffffffff811115611d6457600080fd5b611d7089828a01611a2f565b955050604087013567ffffffffffffffff811115611d8d57600080fd5b611d9989828a01611a9b565b945050606087013567ffffffffffffffff811115611db657600080fd5b611dc289828a01611a2f565b9350506080611dd389828a01611cd9565b92505060a0611de489828a01611a23565b9150509295509295509295565b600080600080600080600060e0888a031215611e0c57600080fd5b873567ffffffffffffffff811115611e2357600080fd5b611e2f8a828b01611a9b565b9750506020611e408a828b01611cd9565b965050604088013567ffffffffffffffff811115611e5d57600080fd5b611e698a828b01611a2f565b955050606088013567ffffffffffffffff811115611e8657600080fd5b611e928a828b01611a9b565b945050608088013567ffffffffffffffff811115611eaf57600080fd5b611ebb8a828b01611a2f565b93505060a0611ecc8a828b01611cd9565b92505060c0611edd8a828b01611a23565b91505092959891949750929550565b600080600060408486031215611f0157600080fd5b833567ffffffffffffffff811115611f1857600080fd5b611f2486828701611af8565b93509350506020611f3786828701611cd9565b9150509250925092565b611f4a81612540565b82525050565b602381527f44454641554c545f46554e4354494f4e5f574554485f434f4e54524143545f4f60208201527f4e4c590000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f494e56414c49445f4d53475f56414c5545000000000000000000000000000000602082015260400190565b600d81527f4f564552534f4c445f5745544800000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b600f81527f5452414e534645525f4641494c45440000000000000000000000000000000000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601a81527f494e53554646494349454e545f4554485f52454d41494e494e47000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b601881527f4645455f50455243454e544147455f544f4f5f4c415247450000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160808301906122f9848261232e565b50602082015161230c602085018261232e565b50604082015161231f604085018261232e565b50606082015161161560608501825b611f4a81612559565b602081016107bd8284611f41565b606081016123538286611f41565b6123606020830185611f41565b611d03604083018461232e565b6040810161237b8285611f41565b6110e0602083018461232e565b602080825281016107bd81611f50565b602080825281016107bd81611fa6565b602080825281016107bd81611fd6565b602080825281016107bd81612006565b602080825281016107bd81612036565b602080825281016107bd8161208c565b602080825281016107bd816120bc565b602080825281016107bd816120ec565b602080825281016107bd8161211c565b602080825281016107bd8161214c565b602080825281016107bd8161217c565b602080825281016107bd816121ac565b602080825281016107bd816121dc565b602080825281016107bd8161220c565b602080825281016107bd81612262565b602080825281016107bd816122b8565b610100810161249782856122e8565b6110e060808301846122e8565b602081016107bd828461232e565b60405181810167ffffffffffffffff811182821017156124d157600080fd5b604052919050565b600067ffffffffffffffff8211156124f057600080fd5b5060209081020190565b600067ffffffffffffffff82111561251157600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b828183375060009101525600a265627a7a72305820d9f418f11e0f91f06f6f9d22924be0add925495eeb76a6388b5417adb505eeb36c6578706572696d656e74616cf50037", + "gasUsed": "0x2c8c7f" + }, + "subtraces": 3, + "traceAddress": [], + "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", + "transactionPosition": 0, + "type": "create" + }, + { + "action": { + "callType": "call", + "from": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", + "gas": "0x1dba84", + "input": "0x60704108f47261b000000000000000000000000000000000000000000000000000000000", + "to": "0x48bacb9266a570d521063ef5dd96e61686dbe788", + "value": "0x0" + }, + "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", + "blockNumber": 13536, + "result": { + "gasUsed": "0x3d9", + "output": "0x0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48" + }, + "subtraces": 0, + "traceAddress": [ + 0 + ], + "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", + "transactionPosition": 0, + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", + "gas": "0x1dad2e", + "input": "0x095ea7b30000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "to": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082", + "value": "0x0" + }, + "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", + "blockNumber": 13536, + "result": { + "gasUsed": "0x56c8", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [ + 1 + ], + "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", + "transactionPosition": 0, + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", + "gas": "0x1d4ee1", + "input": "0x095ea7b30000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "to": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c", + "value": "0x0" + }, + "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", + "blockNumber": 13536, + "result": { + "gasUsed": "0x56ca", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 0, + "traceAddress": [ + 2 + ], + "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", + "transactionPosition": 0, + "type": "call" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/oog.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/oog.json new file mode 100644 index 00000000000..26ae2f0604b --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/oog.json @@ -0,0 +1,68 @@ +{ + "context": { + "difficulty": "3699098917", + "gasLimit": "5258985", + "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", + "number": "2294631", + "timestamp": "1513675366" + }, + "genesis": { + "alloc": { + "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62": { + "balance": "0x0", + "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c68146102785780635a3b7e42146102b357806370a082311461034157806379cc67901461038e57806395d89b41146103e8578063a9059cbb14610476578063dd62ed3e146104b8575b600080fd5b34156100ca57600080fd5b6100d2610524565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061055d565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba6105ea565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506105f0565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610910565b604051808260ff1660ff16815260200191505060405180910390f35b341561028357600080fd5b6102996004808035906020019091905050610915565b604051808215151515815260200191505060405180910390f35b34156102be57600080fd5b6102c6610a18565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103065780820151818401526020810190506102eb565b50505050905090810190601f1680156103335780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561034c57600080fd5b610378600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a51565b6040518082815260200191505060405180910390f35b341561039957600080fd5b6103ce600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a69565b604051808215151515815260200191505060405180910390f35b34156103f357600080fd5b6103fb610bf8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610c31565b005b34156104c357600080fd5b61050e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e34565b6040518082815260200191505060405180910390f35b6040805190810160405280600881526020017f446f70616d696e6500000000000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60005481565b6000808373ffffffffffffffffffffffffffffffffffffffff161415151561061757600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561066557600080fd5b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156106f157fe5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561077c57600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601281565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561096557600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b6040805190810160405280600981526020017f446f706d6e20302e32000000000000000000000000000000000000000000000081525081565b60016020528060005260406000206000915090505481565b600081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ab957600080fd5b600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610b4457600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b6040805190810160405280600581526020017f444f504d4e00000000000000000000000000000000000000000000000000000081525081565b60008273ffffffffffffffffffffffffffffffffffffffff1614151515610c5757600080fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ca557600080fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610d3157fe5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60026020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058206d93424f4e7b11929b8276a269038402c10c0ddf21800e999916ddd9dff4a7630029", + "nonce": "1", + "storage": { + "0x296b66049cc4f9c8bf3d4f14752add261d1a980b39bdd194a7897baf39ac7579": "0x0000000000000000000000000000000000000000033b2e3c9fc9653f9e72b1e0" + } + }, + "0x94194bc2aaf494501d7880b61274a169f6502a54": { + "balance": "0xea8c39a876d19888d", + "code": "0x", + "nonce": "265", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3699098917", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "5263953", + "hash": "0x03a0f62a8106793dafcfae7b75fd2654322062d585a19cea568314d7205790dc", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0x15482cc64b7c00a947f5bf015dfc010db1a6a668c74df61974d6a7848c174408", + "nonce": "0xd1bdb150f6fd170e", + "number": "2294630", + "stateRoot": "0x1ab1a534e84cc787cda1db21e0d5920ab06017948075b759166cfea7274657a1", + "timestamp": "1513675347", + "totalDifficulty": "7160543502214733" + }, + "input": "0xf8ab820109855d21dba00082ca1d9443064693d3d38ad6a7cb579e0d6d9718c8aa6b6280b844a9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f90001ba0ce3ad83f5530136467b7c2bb225f406bd170f4ad59c254e5103c34eeabb5bd69a0455154527224a42ab405cacf0fe92918a75641ce4152f8db292019a5527aa956", + "result": [ + { + "action": { + "callType": "call", + "from": "0x94194bc2aaf494501d7880b61274a169f6502a54", + "gas": "0x7045", + "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000", + "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62", + "value": "0x0" + }, + "blockNumber": 2294631, + "error": "out of gas", + "result": {}, + "subtraces": 0, + "traceAddress": [], + "type": "call" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/option_convert_parity_errors.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/option_convert_parity_errors.json new file mode 100644 index 00000000000..0216c318b55 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/option_convert_parity_errors.json @@ -0,0 +1,71 @@ +{ + "context": { + "difficulty": "3699098917", + "gasLimit": "5258985", + "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", + "number": "2294631", + "timestamp": "1513675366" + }, + "genesis": { + "alloc": { + "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62": { + "balance": "0x0", + "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c68146102785780635a3b7e42146102b357806370a082311461034157806379cc67901461038e57806395d89b41146103e8578063a9059cbb14610476578063dd62ed3e146104b8575b600080fd5b34156100ca57600080fd5b6100d2610524565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061055d565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba6105ea565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506105f0565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610910565b604051808260ff1660ff16815260200191505060405180910390f35b341561028357600080fd5b6102996004808035906020019091905050610915565b604051808215151515815260200191505060405180910390f35b34156102be57600080fd5b6102c6610a18565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103065780820151818401526020810190506102eb565b50505050905090810190601f1680156103335780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561034c57600080fd5b610378600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a51565b6040518082815260200191505060405180910390f35b341561039957600080fd5b6103ce600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a69565b604051808215151515815260200191505060405180910390f35b34156103f357600080fd5b6103fb610bf8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610c31565b005b34156104c357600080fd5b61050e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e34565b6040518082815260200191505060405180910390f35b6040805190810160405280600881526020017f446f70616d696e6500000000000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60005481565b6000808373ffffffffffffffffffffffffffffffffffffffff161415151561061757600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561066557600080fd5b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156106f157fe5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561077c57600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601281565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561096557600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b6040805190810160405280600981526020017f446f706d6e20302e32000000000000000000000000000000000000000000000081525081565b60016020528060005260406000206000915090505481565b600081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ab957600080fd5b600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610b4457600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b6040805190810160405280600581526020017f444f504d4e00000000000000000000000000000000000000000000000000000081525081565b60008273ffffffffffffffffffffffffffffffffffffffff1614151515610c5757600080fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ca557600080fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610d3157fe5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60026020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058206d93424f4e7b11929b8276a269038402c10c0ddf21800e999916ddd9dff4a7630029", + "nonce": "1", + "storage": { + "0x296b66049cc4f9c8bf3d4f14752add261d1a980b39bdd194a7897baf39ac7579": "0x0000000000000000000000000000000000000000033b2e3c9fc9653f9e72b1e0" + } + }, + "0x94194bc2aaf494501d7880b61274a169f6502a54": { + "balance": "0xea8c39a876d19888d", + "code": "0x", + "nonce": "265", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3699098917", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "5263953", + "hash": "0x03a0f62a8106793dafcfae7b75fd2654322062d585a19cea568314d7205790dc", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0x15482cc64b7c00a947f5bf015dfc010db1a6a668c74df61974d6a7848c174408", + "nonce": "0xd1bdb150f6fd170e", + "number": "2294630", + "stateRoot": "0x1ab1a534e84cc787cda1db21e0d5920ab06017948075b759166cfea7274657a1", + "timestamp": "1513675347", + "totalDifficulty": "7160543502214733" + }, + "tracerConfig": { + "convertParityErrors": true + }, + "input": "0xf8ab820109855d21dba00082ca1d9443064693d3d38ad6a7cb579e0d6d9718c8aa6b6280b844a9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f90001ba0ce3ad83f5530136467b7c2bb225f406bd170f4ad59c254e5103c34eeabb5bd69a0455154527224a42ab405cacf0fe92918a75641ce4152f8db292019a5527aa956", + "result": [ + { + "action": { + "callType": "call", + "from": "0x94194bc2aaf494501d7880b61274a169f6502a54", + "gas": "0x7045", + "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000", + "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62", + "value": "0x0" + }, + "blockNumber": 2294631, + "error": "Out of gas", + "result": {}, + "subtraces": 0, + "traceAddress": [], + "type": "call" + } + ] +} 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 new file mode 100644 index 00000000000..f58d20cd2b0 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json @@ -0,0 +1,111 @@ +{ + "genesis": { + "difficulty": "1911202", + "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", + "gasLimit": "7842876", + "hash": "0x4d7bc82e0d56307094378e1a8fbfa6260986f621de95b5fe68a95248b3ba8efe", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "mixHash": "0xc102ad52677c391edab82cc895ca7a7e9fff3eed4fa966ecf7fb61ec1e84bb6b", + "nonce": "0x39f5b074e3437f3f", + "number": "553415", + "stateRoot": "0x8f89e79109c19fa00e72b400502448540dc4773ad92dddd341dbba20c710a3b5", + "timestamp": "1577396195", + "totalDifficulty": "458361299240", + "alloc": { + "0x531f76bad925f6a925474996c7d738c1008045f6": { + "balance": "0x0", + "nonce": "1", + "code": "0x6060604052361561008a576000357c01000000000000000000000000000000000000000000000000000000009004806301cb3b20146102bf57806329dcb0cf146102cc57806338af3eed146102ed5780636e66f6e9146103245780637a3a0e841461035b5780637b3e5e7b1461037c578063a035b1fe1461039d578063dc0d3dff146103be5761008a565b6102bd5b60003490506040604051908101604052803381526020018281526020015060066000506006600050805480919060010190908154818355818115116101365760020281600202836000526020600020918201910161013591906100ec565b808211156101315760006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160005060009055506001016100ec565b5090565b5b505050815481101561000257906000526020600020906002020160005060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555060208201518160010160005055905050806002600082828250540192505081905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166390b98a11336004600050548404604051837c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506020604051808303816000876161da5a03f1156100025750505060405151507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf633826001604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15b50565b005b6102ca6004506104c8565b005b6102d760045061043a565b6040518082815260200191505060405180910390f35b6102f8600450610402565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61032f60045061044c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610366600450610428565b6040518082815260200191505060405180910390f35b610387600450610431565b6040518082815260200191505060405180910390f35b6103a8600450610443565b6040518082815260200191505060405180910390f35b6103cf600480359060200150610472565b604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016000505481565b60026000505481565b60036000505481565b60046000505481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60066000508181548110156100025790600052602060002090600202016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160005054905082565b6000600360005054421015156107d8576001600050546002600050541015156105cf57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166000600260005054604051809050600060405180830381858888f19350505050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf6600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002600050546000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a161079d565b7fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf66000600b600060405180848152602001838152602001828152602001935050505060405180910390a1600090505b60066000505481101561079c57600660005081815481101561000257906000526020600020906002020160005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166000600660005083815481101561000257906000526020600020906002020160005060010160005054604051809050600060405180830381858888f19350505050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf6600660005082815481101561000257906000526020600020906002020160005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600050838154811015610002579060005260206000209060020201600050600101600050546000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15b806001019050805061061e565b5b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b5056", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000b49180d443dc4ca6028de0031ac09337891fd8ce", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + } + }, + "0xb49180d443dc4ca6028de0031ac09337891fd8ce": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x193e9986e2e3f0c58988", + "nonce": "2585", + "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": "553416", + "difficulty": "1909336", + "timestamp": "1577396224", + "gasLimit": "7835218", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf870820a1985e8d4a5100083040b2894531f76bad925f6a925474996c7d738c1008045f6880de0b6b3a76400008081a2a08693170f040d9501b831b404d9e40fba040c5aef4b8974aedc20b3844aea7c32a0476861058ff9b8030c58bcba8be320acc855e4694a633c493fb50fbdb9455489", + "result": [ + { + "type": "call", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "to": "0x531f76bad925f6a925474996c7d738c1008045f6", + "value": "0xde0b6b3a7640000", + "gas": "0x3b920", + "input": "0x", + "callType": "call" + }, + "result": { + "gasUsed": "0x19c3e", + "output": "0x" + }, + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 5, + "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", + "blockNumber": 553416, + "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282", + "time": "617.42µs" + }, + { + "type": "call", + "action": { + "from": "0x531f76bad925f6a925474996c7d738c1008045f6", + "to": "0xb49180d443dc4ca6028de0031ac09337891fd8ce", + "value": "0x0", + "gas": "0x2164e", + "input": "0x90b98a11000000000000000000000000877bd459c9b7d8576b44e59e09d076c25946f4430000000000000000000000000000000000000000000000000000000000000001", + "callType": "call" + }, + "result": { + "gasUsed": "0x0", + "output": "0x" + }, + "traceAddress": [ + 0 + ], + "subtraces": 0, + "transactionPosition": 5, + "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", + "blockNumber": 553416, + "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert.json new file mode 100644 index 00000000000..897aebb0e05 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert.json @@ -0,0 +1,68 @@ +{ + "context": { + "difficulty": "3665057456", + "gasLimit": "5232723", + "miner": "0xf4d8e706cfb25c0decbbdd4d2e2cc10c66376a3f", + "number": "2294501", + "timestamp": "1513673601" + }, + "genesis": { + "alloc": { + "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9": { + "balance": "0x2a3fc32bcc019283", + "code": "0x", + "nonce": "10", + "storage": {} + }, + "0xabbcd5b340c80b5f1c0545c04c987b87310296ae": { + "balance": "0x0", + "code": "0x606060405236156100755763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632d0335ab811461007a578063548db174146100ab5780637f649783146100fc578063b092145e1461014d578063c3f44c0a14610186578063c47cf5de14610203575b600080fd5b341561008557600080fd5b610099600160a060020a0360043516610270565b60405190815260200160405180910390f35b34156100b657600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061028f95505050505050565b005b341561010757600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061029e95505050505050565b005b341561015857600080fd5b610172600160a060020a03600435811690602435166102ad565b604051901515815260200160405180910390f35b341561019157600080fd5b6100fa6004803560ff1690602480359160443591606435600160a060020a0316919060a49060843590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965050509235600160a060020a031692506102cd915050565b005b341561020e57600080fd5b61025460046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061056a95505050505050565b604051600160a060020a03909116815260200160405180910390f35b600160a060020a0381166000908152602081905260409020545b919050565b61029a816000610594565b5b50565b61029a816001610594565b5b50565b600160209081526000928352604080842090915290825290205460ff1681565b60008080600160a060020a038416158061030d5750600160a060020a038085166000908152600160209081526040808320339094168352929052205460ff165b151561031857600080fd5b6103218561056a565b600160a060020a038116600090815260208190526040808220549295507f19000000000000000000000000000000000000000000000000000000000000009230918891908b908b90517fff000000000000000000000000000000000000000000000000000000000000008089168252871660018201526c01000000000000000000000000600160a060020a038088168202600284015286811682026016840152602a8301869052841602604a820152605e810182805190602001908083835b6020831061040057805182525b601f1990920191602091820191016103e0565b6001836020036101000a0380198251168184511617909252505050919091019850604097505050505050505051809103902091506001828a8a8a6040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f1151561049957600080fd5b5050602060405103519050600160a060020a03838116908216146104bc57600080fd5b600160a060020a0380841660009081526020819052604090819020805460010190559087169086905180828051906020019080838360005b8381101561050d5780820151818401525b6020016104f4565b50505050905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008661646e5a03f1915050151561055e57600080fd5b5b505050505050505050565b600060248251101561057e5750600061028a565b600160a060020a0360248301511690505b919050565b60005b825181101561060157600160a060020a033316600090815260016020526040812083918584815181106105c657fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff19169115159190911790555b600101610597565b5b5050505600a165627a7a723058200027e8b695e9d2dea9f3629519022a69f3a1d23055ce86406e686ea54f31ee9c0029", + "nonce": "1", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3672229776", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "5227619", + "hash": "0xa07b3d6c6bf63f5f981016db9f2d1d93033833f2c17e8bf7209e85f1faf08076", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0x806e151ce2817be922e93e8d5921fa0f0d0fd213d6b2b9a3fa17458e74a163d0", + "nonce": "0xbc5d43adc2c30c7d", + "number": "2294500", + "stateRoot": "0xca645b335888352ef9d8b1ef083e9019648180b259026572e3139717270de97d", + "timestamp": "1513673552", + "totalDifficulty": "7160066586979149" + }, + "input": "0xf9018b0a8505d21dba00832dc6c094abbcd5b340c80b5f1c0545c04c987b87310296ae80b9012473b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988000000000000000000000000000000000000000000000000000000000000000000000000000000001ba0fd659d76a4edbd2a823e324c93f78ad6803b30ff4a9c8bce71ba82798975c70ca06571eecc0b765688ec6c78942c5ee8b585e00988c0141b518287e9be919bc48a", + "result": [ + { + "action": { + "callType": "call", + "from": "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9", + "gas": "0x2d55e8", + "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000", + "to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae", + "value": "0x0" + }, + "blockNumber": 2294501, + "error": "execution reverted", + "result": { + "gasUsed": "0x719b" + }, + "subtraces": 0, + "traceAddress": [], + "type": "call" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert_reason.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert_reason.json new file mode 100644 index 00000000000..62dbaf20dc9 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert_reason.json @@ -0,0 +1,74 @@ +{ + "context": { + "difficulty": "2", + "gasLimit": "8000000", + "miner": "0x0000000000000000000000000000000000000000", + "number": "3212651", + "timestamp": "1597246515" + }, + "genesis": { + "alloc": { + "0xf58833cf0c791881b494eb79d461e08a1f043f52": { + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063609ff1bd11610078578063609ff1bd146101af5780639e7b8d61146101cd578063a3ec138d14610211578063e2ba53f0146102ae576100a5565b80630121b93f146100aa578063013cf08b146100d85780632e4176cf146101215780635c19a95c1461016b575b600080fd5b6100d6600480360360208110156100c057600080fd5b81019080803590602001909291905050506102cc565b005b610104600480360360208110156100ee57600080fd5b8101908080359060200190929190505050610469565b604051808381526020018281526020019250505060405180910390f35b61012961049a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ad6004803603602081101561018157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bf565b005b6101b76108db565b6040518082815260200191505060405180910390f35b61020f600480360360208110156101e357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610952565b005b6102536004803603602081101561022757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b53565b60405180858152602001841515151581526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060405180910390f35b6102b6610bb0565b6040518082815260200191505060405180910390f35b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154141561038a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f486173206e6f20726967687420746f20766f746500000000000000000000000081525060200191505060405180910390fd5b8060010160009054906101000a900460ff161561040f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f416c726561647920766f7465642e00000000000000000000000000000000000081525060200191505060405180910390fd5b60018160010160006101000a81548160ff02191690831515021790555081816002018190555080600001546002838154811061044757fe5b9060005260206000209060020201600101600082825401925050819055505050565b6002818154811061047657fe5b90600052602060002090600202016000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff1615610587576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f596f7520616c726561647920766f7465642e000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610629576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e000081525060200191505060405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107cc57600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156107c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f466f756e64206c6f6f7020696e2064656c65676174696f6e2e0000000000000081525060200191505060405180910390fd5b61062a565b60018160010160006101000a81548160ff021916908315150217905550818160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff16156108bf578160000154600282600201548154811061089c57fe5b9060005260206000209060020201600101600082825401925050819055506108d6565b816000015481600001600082825401925050819055505b505050565b6000806000905060008090505b60028054905081101561094d57816002828154811061090357fe5b9060005260206000209060020201600101541115610940576002818154811061092857fe5b90600052602060002090600202016001015491508092505b80806001019150506108e8565b505090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180610bde6028913960400191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff1615610aba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f54686520766f74657220616c726561647920766f7465642e000000000000000081525060200191505060405180910390fd5b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414610b0957600080fd5b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555050565b60016020528060005260406000206000915090508060000154908060010160009054906101000a900460ff16908060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154905084565b60006002610bbc6108db565b81548110610bc657fe5b90600052602060002090600202016000015490509056fe4f6e6c79206368616972706572736f6e2063616e206769766520726967687420746f20766f74652ea26469706673582212201d282819f8f06fed792100d60a8b08809b081a34a1ecd225e83a4b41122165ed64736f6c63430006060033", + "nonce": "1", + "storage": { + "0x6200beec95762de01ce05f2a0e58ce3299dbb53c68c9f3254a242121223cdf58": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1": { + "balance": "0x57af9d6b3df812900", + "code": "0x", + "nonce": "6", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "IstanbulBlock": 1561651, + "chainId": 5, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "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": "0xf888068449504f80832dc6c094f58833cf0c791881b494eb79d461e08a1f043f5280a45c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf12da0264664db3e71fae1dbdaf2f53954be149ad3b7ba8a5054b4d89c70febfacc8b1a0212e8398757963f419681839ae8c5a54b411e252473c82d93dda68405ca63294", + "result": [ + { + "action": { + "callType": "call", + "from": "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", + "gas": "0x2d7308", + "input": "0x5c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", + "to": "0xf58833cf0c791881b494eb79d461e08a1f043f52", + "value": "0x0" + }, + "blockNumber": 3212651, + "error": "execution reverted", + "result": { + "gasUsed": "0x5940", + "output": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001e53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e0000" + }, + "subtraces": 0, + "traceAddress": [], + "type": "call" + } + ] +} diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json new file mode 100644 index 00000000000..cd34d0b6d06 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json @@ -0,0 +1,91 @@ +{ + "genesis": { + "difficulty": "4628640", + "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578", + "gasLimit": "9244120", + "hash": "0x5a1f551897cc91265225b0453136ad8c7eef1c1c8b06139da4f2e6e710c1f4df", + "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3", + "mixHash": "0xd6735e63f8937fe0c5491e0d5836ec28467363be7ada5a2f979f9d107e2c831e", + "nonce": "0x7c35e34d2e328d7d", + "number": "1555145", + "stateRoot": "0x565873b05f71b98595133e37a52d79c3476ce820c05ebedaddd35541b0e894a3", + "timestamp": "1590793819", + "totalDifficulty": "2241994078605", + "alloc": { + "0x119f569a45e9d0089d51d7f9529f5ea9bf5785e2": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x622e8fced69d43eb8d97", + "nonce": "260140", + "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": "1555146", + "difficulty": "4630900", + "timestamp": "1590793820", + "gasLimit": "9253146", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf8628303f82c843b9aca0083019ecc80808e605a600053600160006001f0ff0081a2a077f539ae2a58746bbfa6370fc423f946870efa32753d697d3729d361a428623aa0384ef9a5650d6630f5c1ddef616bffa5fc72a95a9314361d0918de066aa4475a", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xcf08", + "init": "0x605a600053600160006001f0ff00" + }, + "result": { + "gasUsed": "0x102a1", + "code": "0x", + "address": "0x1d99a1a3efa9181f540f9e24fa6e4e08eb7844ca" + }, + "traceAddress": [], + "subtraces": 1, + "transactionPosition": 14, + "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", + "blockNumber": 1555146, + "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e", + "time": "187.145µs" + }, + { + "type": "suicide", + "action": { + "address": "0x1d99a1a3efa9181f540f9e24fa6e4e08eb7844ca", + "refundAddress": "0x0000000000000000000000000000000000000000", + "balance": "0x0" + }, + "result": null, + "traceAddress": [ + 0 + ], + "subtraces": 0, + "transactionPosition": 14, + "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", + "blockNumber": 1555146, + "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple.json new file mode 100644 index 00000000000..6d084410a36 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple.json @@ -0,0 +1,97 @@ +{ + "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, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "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", + "result": [ + { + "action": { + "callType": "call", + "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", + "gas": "0x10738", + "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", + "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", + "value": "0x0" + }, + "blockNumber": 2289806, + "result": { + "gasUsed": "0x9751", + "output": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "subtraces": 1, + "traceAddress": [], + "type": "call" + }, + { + "action": { + "callType": "call", + "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", + "gas": "0x6d05", + "input": "0x", + "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", + "value": "0x6f05b59d3b20000" + }, + "blockNumber": 0, + "result": { + "gasUsed": "0x0", + "output": "0x" + }, + "subtraces": 0, + "traceAddress": [0], + "type": "call" + } + ] +} 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 new file mode 100644 index 00000000000..d530fe908b2 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json @@ -0,0 +1,70 @@ +{ + "genesis": { + "difficulty": "4673862", + "extraData": "0xd683010b05846765746886676f312e3133856c696e7578", + "gasLimit": "9471919", + "hash": "0x7f072150c5905c214966e3432d418910badcdbe510aceaac295b1d7059cc0ffc", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "mixHash": "0x113ced8fedb939fdc862008da7bdddde726f997c0e6dfba0e55613994757b489", + "nonce": "0x0f411a2e5552c5b7", + "number": "1555284", + "stateRoot": "0x9fe125b361b72d5479b24ad9be9964b74228c73a2dfb0065060a79b4a6dfaa1e", + "timestamp": "1590795374", + "totalDifficulty": "2242642335405", + "alloc": { + "0xe85df1413eebe1b191c26260e19783a274a6b041": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x6244c985ef1e48e84531", + "nonce": "265775", + "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": "1555285", + "difficulty": "4676144", + "timestamp": "1590795378", + "gasLimit": "9481167", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf9014083040e2f843b9aca008301aab08080b8eb7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5547f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000037f05581a2a09db45e7846f193471f6d897fb6ff58b7ec41a9c6f63d10aca47d821c365981cba052ec320875625e16141a1a9e8b7993de863698fb699f93ae2cab26149bbb144f", + "result": [ + { + "type": "create", + "action": { + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "value": "0x0", + "gas": "0xd550", + "init": "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5547f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000037f055" + }, + "error": "out of gas", + "traceAddress": [], + "subtraces": 0, + "transactionPosition": 16, + "transactionHash": "0x384487e5ae8d2997aece8e28403d393cb9752425e6de358891bed981c5af1c05", + "blockNumber": 1555285, + "blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f", + "time": "665.278µs" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/staticcall_precompiled.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/staticcall_precompiled.json new file mode 100644 index 00000000000..9291149bdb6 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/staticcall_precompiled.json @@ -0,0 +1,83 @@ +{ + "genesis": { + "difficulty": "2028219", + "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", + "gasLimit": "23481547", + "hash": "0x3c06114e88c26b52decfe4e5f6d4d51cfaaea0317b646017fac32fadbe7df9f5", + "miner": "0x2a1442b4fbabf7b5507c13ccf076a547abfaeb1b", + "mixHash": "0x46108f74220c5ab23651f93912b14fea37ed1380d22e10639a1f5651c98cb949", + "nonce": "0x426a5267e0b636fe", + "number": "567687", + "stateRoot": "0x7b4b193fe73ef87101c7c325954681861cc240c299d03459784b2b11c9c522ae", + "timestamp": "1577578008", + "totalDifficulty": "485254950048", + "alloc": { + "0x8521f13dd5e4bc3dab3cf0f01a195a5af899e851": { + "balance": "0x0", + "nonce": "1", + "code": "0x608060405260043610610251576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301ffc9a7146102565780630519ce79146102c857806306fdde031461031f578063095ea7b3146103af5780630a0f81681461040a5780631155dfe51461046157806318160ddd1461048c5780631b57cd44146104b7578063200b1e641461050657806327d7874c146105cb5780632ba73c151461061c5780633108e4d71461066d578063317676bf146106bc5780633f4ba83a1461071557806342842e0e1461072c57806346cb96fa146107a75780634e0a3379146107f65780635501d42d146108475780635c975abb146108a05780635fd8c710146108cf5780636352211e146108e65780636af04a571461096157806370a08231146109b85780637158798814610a1d5780637866928014610a6e5780638456cb5914610ae95780638462151c14610b0057806385ac788214610ba657806395787d2614610c2c57806395d89b4114610c6e57806396b5d99214610cfe578063990581b614610d795780639db797f014610e2d578063ab8f933a14610e80578063ad84202814610eab578063b047fb5014610ed6578063b355752214610f2d578063b9db15b414610f7c578063bc4006f514610fd2578063ca083be214611029578063cdd22c9314611082578063cec21acb146110d1578063e078d8b114611136578063e17b25af14611182578063e52ab74b146111d3578063f010432314611222578063fac9c51f1461129d578063fdb33429146112ec578063fffb147914611367575b600080fd5b34801561026257600080fd5b506102ae6004803603602081101561027957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506113e2565b604051808215151515815260200191505060405180910390f35b3480156102d457600080fd5b506102dd6116cb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561032b57600080fd5b506103346116f1565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610374578082015181840152602081019050610359565b50505050905090810190601f1680156103a15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103bb57600080fd5b50610408600480360360408110156103d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061172a565b005b34801561041657600080fd5b5061041f6117c4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561046d57600080fd5b506104766117e9565b6040518082815260200191505060405180910390f35b34801561049857600080fd5b506104a16117f6565b6040518082815260200191505060405180910390f35b3480156104c357600080fd5b506104f0600480360360208110156104da57600080fd5b8101908080359060200190929190505050611806565b6040518082815260200191505060405180910390f35b34801561051257600080fd5b506105b5600480360360a081101561052957600080fd5b81019080803590602001909291908035906020019064010000000081111561055057600080fd5b82018360208201111561056257600080fd5b8035906020019184600183028401116401000000008311171561058457600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919050505061181e565b6040518082815260200191505060405180910390f35b3480156105d757600080fd5b5061061a600480360360208110156105ee57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611cac565b005b34801561062857600080fd5b5061066b6004803603602081101561063f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d86565b005b34801561067957600080fd5b506106a66004803603602081101561069057600080fd5b8101908080359060200190929190505050611e61565b6040518082815260200191505060405180910390f35b3480156106c857600080fd5b506106ff600480360360408110156106df57600080fd5b810190808035906020019092919080359060200190929190505050611e79565b6040518082815260200191505060405180910390f35b34801561072157600080fd5b5061072a611ea9565b005b34801561073857600080fd5b506107a56004803603606081101561074f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611f86565b005b3480156107b357600080fd5b506107e0600480360360208110156107ca57600080fd5b8101908080359060200190929190505050612053565b6040518082815260200191505060405180910390f35b34801561080257600080fd5b506108456004803603602081101561081957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061206b565b005b34801561085357600080fd5b5061088a6004803603604081101561086a57600080fd5b810190808035906020019092919080359060200190929190505050612146565b6040518082815260200191505060405180910390f35b3480156108ac57600080fd5b506108b5612176565b604051808215151515815260200191505060405180910390f35b3480156108db57600080fd5b506108e4612189565b005b3480156108f257600080fd5b5061091f6004803603602081101561090957600080fd5b810190808035906020019092919050505061226d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561096d57600080fd5b506109766122e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156109c457600080fd5b50610a07600480360360208110156109db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061230c565b6040518082815260200191505060405180910390f35b348015610a2957600080fd5b50610a6c60048036036020811015610a4057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612355565b005b348015610a7a57600080fd5b50610aa760048036036020811015610a9157600080fd5b8101908080359060200190929190505050612472565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610af557600080fd5b50610afe6124a5565b005b348015610b0c57600080fd5b50610b4f60048036036020811015610b2357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506125e9565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610b92578082015181840152602081019050610b77565b505050509050019250505060405180910390f35b348015610bb257600080fd5b50610c16600480360360c0811015610bc957600080fd5b810190808035906020019092919080359060200190929190803515159060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612737565b6040518082815260200191505060405180910390f35b610c5860048036036020811015610c4257600080fd5b8101908080359060200190929190505050612c0c565b6040518082815260200191505060405180910390f35b348015610c7a57600080fd5b50610c8361304b565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610cc3578082015181840152602081019050610ca8565b50505050905090810190601f168015610cf05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610d0a57600080fd5b50610d3760048036036020811015610d2157600080fd5b8101908080359060200190929190505050613084565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610d8557600080fd5b50610db260048036036020811015610d9c57600080fd5b81019080803590602001909291905050506130b7565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610df2578082015181840152602081019050610dd7565b50505050905090810190601f168015610e1f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610e3957600080fd5b50610e6660048036036020811015610e5057600080fd5b810190808035906020019092919050505061317b565b604051808215151515815260200191505060405180910390f35b348015610e8c57600080fd5b50610e956131b3565b6040518082815260200191505060405180910390f35b348015610eb757600080fd5b50610ec06131b9565b6040518082815260200191505060405180910390f35b348015610ee257600080fd5b50610eeb6131bf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610f3957600080fd5b50610f6660048036036020811015610f5057600080fd5b81019080803590602001909291905050506131e5565b6040518082815260200191505060405180910390f35b348015610f8857600080fd5b50610fb560048036036020811015610f9f57600080fd5b81019080803590602001909291905050506131fd565b604051808381526020018281526020019250505060405180910390f35b348015610fde57600080fd5b50610fe7613235565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561103557600080fd5b5061106c6004803603604081101561104c57600080fd5b81019080803590602001909291908035906020019092919050505061325b565b6040518082815260200191505060405180910390f35b34801561108e57600080fd5b506110bb600480360360208110156110a557600080fd5b810190808035906020019092919050505061328b565b6040518082815260200191505060405180910390f35b3480156110dd57600080fd5b50611120600480360360208110156110f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506132ab565b6040518082815260200191505060405180910390f35b61116c6004803603604081101561114c57600080fd5b8101908080359060200190929190803590602001909291905050506132c3565b6040518082815260200191505060405180910390f35b34801561118e57600080fd5b506111d1600480360360208110156111a557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134ee565b005b3480156111df57600080fd5b5061120c600480360360208110156111f657600080fd5b810190808035906020019092919050505061358d565b6040518082815260200191505060405180910390f35b34801561122e57600080fd5b5061125b6004803603602081101561124557600080fd5b81019080803590602001909291905050506135ad565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156112a957600080fd5b506112d6600480360360208110156112c057600080fd5b81019080803590602001909291905050506135e0565b6040518082815260200191505060405180910390f35b3480156112f857600080fd5b506113256004803603602081101561130f57600080fd5b81019080803590602001909291905050506135f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561137357600080fd5b506113a06004803603602081101561138a57600080fd5b810190808035906020019092919050505061362b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060405180807f737570706f727473496e74657266616365286279746573342900000000000000815250601901905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611610575060405180807f746f6b656e734f664f776e6572286164647265737329000000000000000000008152506016019050604051809103902060405180807f736166655472616e7366657246726f6d28616464726573732c6164647265737381526020017f2c75696e743235362900000000000000000000000000000000000000000000008152506029019050604051809103902060405180807f617070726f766528616464726573732c75696e743235362900000000000000008152506018019050604051809103902060405180807f6f776e65724f662875696e7432353629000000000000000000000000000000008152506010019050604051809103902060405180807f62616c616e63654f6628616464726573732900000000000000000000000000008152506012019050604051809103902060405180807f746f74616c537570706c79282900000000000000000000000000000000000000815250600d019050604051809103902018181818187bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806116c4575060405180807f73796d626f6c28290000000000000000000000000000000000000000000000008152506008019050604051809103902060405180807f6e616d652829000000000000000000000000000000000000000000000000000081525060060190506040518091039020187bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040805190810160405280600781526020017f426974766965770000000000000000000000000000000000000000000000000081525081565b600260149054906101000a900460ff1615151561174657600080fd5b611750338261365e565b151561175b57600080fd5b61176581836136ca565b808273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600480549050905090565b6000600160048054905003905090565b60166020528060005260406000206000915090505481565b600085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506101006000825111801561187a575080825111155b151561188557600080fd5b33896005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156118f557600080fd5b6000878760405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506000600e6000838152602001908152602001600020541415156119b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f5369676e617475726520416c726561647920557365640000000000000000000081525060200191505060405180910390fd5b600560008d815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660018d60405160200180828152602001915050604051602081830303815290604052805190602001208b8b8b60405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611a80573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff16141515611aac57600080fd5b611ab4613a21565b6020604051908101604052808d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050815250905060006001600a839080600181540180825580915050906001820390600052602060002001600090919290919091506000820151816000019080519060200190611b54929190613a35565b5050500390508063ffffffff1681141515611b6e57600080fd5b7fe819187a0cf517f3c23c7bd6e6b11a3aec56ec3f2784dc69ac56ebac668748ee3382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a133600b600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508d600c600083815260200190815260200160002081905550600860008f81526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055508d600e600085815260200190815260200160002081905550809750505050505050509695505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611d0757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515611d4357600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611de157600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515611e1d57600080fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60116020528060005260406000206000915090505481565b600860205281600052604060002081815481101515611e9457fe5b90600052602060002001600091509150505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611f0457600080fd5b600260149054906101000a900460ff161515611f1f57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff16601860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515611f7c57600080fd5b611f84613720565b565b600260149054906101000a900460ff16151515611fa257600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611fde57600080fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415151561201957600080fd5b61202333826137b3565b151561202e57600080fd5b612038838261365e565b151561204357600080fd5b61204e83838361381f565b505050565b600e6020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156120c657600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561210257600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600d6020528160005260406000208181548110151561216157fe5b90600052602060002001600091509150505481565b600260149054906101000a900460ff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156121e557600080fd5b60003073ffffffffffffffffffffffffffffffffffffffff16319050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612269573d6000803e3d6000fd5b5050565b60006005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156122e157600080fd5b919050565b601860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156123b057600080fd5b600260149054906101000a900460ff1615156123cb57600080fd5b80601860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa44619930581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600b6020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061254d57506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b806125a55750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156125b057600080fd5b600260149054906101000a900460ff161515156125cc57600080fd5b6001600260146101000a81548160ff021916908315150217905550565b606060006125f68361230c565b9050600081141561263a5760006040519080825280602002602001820160405280156126315781602001602082028038833980820191505090505b50915050612732565b60608160405190808252806020026020018201604052801561266b5781602001602082028038833980820191505090505b50905060006126786117f6565b905060008090506000600190505b8281111515612729578673ffffffffffffffffffffffffffffffffffffffff166005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561271c5780848381518110151561270557fe5b906020019060200201818152505081806001019250505b8080600101915050612686565b83955050505050505b919050565b600033876005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156127a957600080fd5b60008585604051602001808381526020018281526020019250505060405160208183030381529060405280519060200120905060008911156128715788601260008381526020019081526020016000205414151515612870576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f5369676e617475726520416c726561647920557365640000000000000000000081525060200191505060405180910390fd5b5b600560008b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660018b604051602001808281526020019150506040516020818303038152906040528051906020012089898960405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561293e573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1614151561296a57600080fd5b6000339050600073ffffffffffffffffffffffffffffffffffffffff16600b60008c815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515156129de57600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600b60008c815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515612a4c57600080fd5b612a54613ab5565b6020604051908101604052808b1515815250905060006001600f8390806001815401808255809150509060018203906000526020600020016000909192909190915060008201518160000160006101000a81548160ff02191690831515021790555050500390508063ffffffff1681141515612acf57600080fd5b7fa10f25ef783c24056e27eb55eb6c0ac1c4863cd5eab7e657cd067926b3dce0648382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1826010600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600d60008d81526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055508b60116000838152602001908152602001600020819055508b60126000868152602001908152602001600020819055508096505050505050509695505050505050565b600034601354808210151515612c2157600080fd5b60003390506000600b600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612c9a57600080fd5b8173ffffffffffffffffffffffffffffffffffffffff16600b600088815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515612d0857600080fd5b612d10613acb565b602060405190810160405280348152509050600060016014839080600181540180825580915050906001820390600052602060002001600090919290919091506000820151816000015550500390508063ffffffff1681141515612d7357600080fd5b836015600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508760166000838152602001908152602001600020819055506000606434604602811515612dee57fe5b0490506000600d60008b815260200190815260200160002080549050823403811515612e1657fe5b049050600b60008b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612e92573d6000803e3d6000fd5b5060008090505b600d60008c815260200190815260200160002080549050811015612fcf5760106000600d60008e815260200190815260200160002083815481101515612edb57fe5b9060005260206000200154815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612f5a573d6000803e3d6000fd5b5060176000858152602001908152602001600020600d60008d815260200190815260200160002082815481101515612f8e57fe5b906000526020600020015490806001815401808255809150509060018203906000526020600020016000909192909190915055508080600101915050612e99565b507f6ea1e5e03071ff9bad53b614eafcc00d29db646e9c351fcc00d45a4118d7c51a8684604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a18298505050505050505050919050565b6040805190810160405280600281526020017f425600000000000000000000000000000000000000000000000000000000000081525081565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606000600a838154811015156130ca57fe5b906000526020600020019050806000018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561316e5780601f106131435761010080835404028352916020019161316e565b820191906000526020600020905b81548152906001019060200180831161315157829003601f168201915b5050505050915050919050565b600080600f8381548110151561318d57fe5b9060005260206000200190508060000160009054906101000a900460ff16915050919050565b60035481565b60135481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60126020528060005260406000206000915090505481565b600080600060048481548110151561321157fe5b90600052602060002090600202019050806000015492508060010154915050915091565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60176020528160005260406000208181548110151561327657fe5b90600052602060002001600091509150505481565b600060086000838152602001908152602001600020805490509050919050565b60066020528060005260406000206000915090505481565b6000346003548082101515156132d857600080fd5b8460007f01000000000000000000000000000000000000000000000000000000000000000281600060208110151561330c57fe5b1a7f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415151561335e57600080fd5b8460007f01000000000000000000000000000000000000000000000000000000000000000281600060208110151561339257fe5b1a7f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141515156133e457600080fd5b60003390506133f1613adf565b60408051908101604052808a81526020018981525090506000600160048390806001815401808255809150509060018203906000526020600020906002020160009091929091909150600082015181600001556020820151816001015550500390508063ffffffff168114151561346757600080fd5b7f982bb66d9aa60573bc0a2066122e1466ecbc4c179a5e7c1c5b589345008ce69a8382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a16134de6000848361381f565b8097505050505050505092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561354957600080fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600d6000838152602001908152602001600020805490509050919050565b60156020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c6020528060005260406000206000915090505481565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60106020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008273ffffffffffffffffffffffffffffffffffffffff166005600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b806007600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561377b57600080fd5b600260149054906101000a900460ff16151561379657600080fd5b6000600260146101000a81548160ff021916908315150217905550565b60008273ffffffffffffffffffffffffffffffffffffffff166007600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001019190505550816005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151561397d57600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001900391905055506007600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b7f70a295484349ac4c2073cdca8ba026869fff31e0d35e268f820e44c9d25f4a2e838383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b602060405190810160405280606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613a7657805160ff1916838001178555613aa4565b82800160010185558215613aa4579182015b82811115613aa3578251825591602001919060010190613a88565b5b509050613ab19190613aff565b5090565b6020604051908101604052806000151581525090565b602060405190810160405280600081525090565b604080519081016040528060008019168152602001600080191681525090565b613b2191905b80821115613b1d576000816000905550600101613b05565b5090565b9056fea165627a7a72305820b73bf81476c95567782e45ebae5220573d46c55a9004c11243c470bc91f2d26d0029", + "storage": { + "0x05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xa54c2b4154b4f221d71d6d5bc0ec905c931a021bb6fb138fc0495bb0373e2276": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x0000000000000000000000000000000000000001": { + "balance": "0x0", + "nonce": "0", + "code": "0x", + "storage": {} + }, + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0xcec3d4daf44926cc41e", + "nonce": "147795", + "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": "567688", + "difficulty": "2028219", + "timestamp": "1577578023", + "gasLimit": "23504477", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf9018f8302415385746a52880083048196948521f13dd5e4bc3dab3cf0f01a195a5af899e85180b90124200b1e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9af799918107e9a339eba0584b8b60b35aae6f087c74f6bfc00c9301849b204d094ed65e09c76c2597f5516f9440aad2921e50dde096e7caaa65a536d4d9265e00000000000000000000000000000000000000000000000000000000000000504269747669657720697320616e20616d617a696e6720776562736974652e20596f752073686f756c6420646566696e6974656c792061646420796f75722070726f6475637420746f2069742e20e282bf0000000000000000000000000000000081a2a0686e4a69e1fa6cac6b4f751a3935ca5a371d720c34d3a7136988aa017a528ed5a07d993e607b665c24557d0eae166c21fe744e618ed3430902ac6206c63a331dc0", + "result": [ + { + "action": { + "author": "0x0000000000000000000000000000000000000000", + "address": "0x0000000000000000000000000000000000000000", + "balance": "0x0", + "callType": "call", + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "gas": "0x4053e", + "input": "0x200b1e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9af799918107e9a339eba0584b8b60b35aae6f087c74f6bfc00c9301849b204d094ed65e09c76c2597f5516f9440aad2921e50dde096e7caaa65a536d4d9265e00000000000000000000000000000000000000000000000000000000000000504269747669657720697320616e20616d617a696e6720776562736974652e20596f752073686f756c6420646566696e6974656c792061646420796f75722070726f6475637420746f2069742e20e282bf00000000000000000000000000000000", + "refundAddress": "0x0000000000000000000000000000000000000000", + "to": "0x8521f13dd5e4bc3dab3cf0f01a195a5af899e851", + "value": "0x0" + }, + "error": "execution reverted", + "result": { + "gasUsed": "0x947c" + }, + "subtraces": 0, + "traceAddress": [], + "type": "call" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/suicide.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/suicide.json new file mode 100644 index 00000000000..bd9e057c022 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/suicide.json @@ -0,0 +1,92 @@ +{ + "genesis": { + "number": "553153", + "hash": "0x88bde20840880a1f3fba92121912a3cc0d3b26d76e4d914fbd85fc2e43da3b3f", + "nonce": "0x7be554ffe4b82fc2", + "mixHash": "0xf73d2ff3c16599c3b8a24b9ebde6c09583b5ee3f747d3cd37845d564f4c8d87a", + "stateRoot": "0x40b5f53d610108947688a04fb68838ff9c0aa0dd6e54156b682537192171ff5c", + "miner": "0x774c398d763161f55b66a646f17edda4addad2ca", + "difficulty": "1928226", + "totalDifficulty": "457857582215", + "extraData": "0xd983010907846765746888676f312e31332e358664617277696e", + "gasLimit": "7999473", + "timestamp": "1577392669", + "alloc": { + "0x877bd459c9b7d8576b44e59e09d076c25946f443": { + "balance": "0x19bb4ac611ca7a1fc881", + "nonce": "701", + "code": "0x", + "storage": {} + }, + "0x8ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91": { + "balance": "0x0", + "nonce": "1", + "code": "0x60606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610044578063cfae32171461005157610042565b005b61004f6004506100ca565b005b61005c60045061015e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561015b57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b60206040519081016040528060008152602001506001600050805480601f016020809104026020016040519081016040528092919081815260200182805480156101cd57820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505090506101d9565b9056", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000877bd459c9b7d8576b44e59e09d076c25946f443" + } + } + }, + "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": "553154", + "difficulty": "1929167", + "timestamp": "1577392670", + "gasLimit": "8000000", + "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "input": "0xf86c8202bd850ee6b280008344aa20948ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91808441c0e1b581a2a03f95ca5cdf7fd727630341c4c6aa1b64ccd9949bd9ecc72cfdd7ce17a2013a69a06d34795ef7fb0108a6dbee4ae0a1bdc48dcd2a4ee53bb6a33d45515af07bb9a8", + "result": [ + { + "action": { + "callType": "call", + "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", + "gas": "0x445708", + "input": "0x41c0e1b5", + "to": "0x8ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91", + "value": "0x0" + }, + "blockHash": "0xf641c3b0f82b07cd3a528adb9927dd83eeb4f1682e2bd523ed36888e0d82c9a9", + "blockNumber": 553154, + "result": { + "gasUsed": "0x347a", + "output": "0x" + }, + "subtraces": 1, + "traceAddress": [], + "transactionHash": "0x6af0a5c3188ffacae4d340d4a17e14fdb5a54187683a80ef241bde248189882b", + "transactionPosition": 15, + "type": "call" + }, + { + "action": { + "address": "0x8ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91", + "balance": "0x0", + "refundAddress": "0x877bd459c9b7d8576b44e59e09d076c25946f443" + }, + "blockHash": "0xf641c3b0f82b07cd3a528adb9927dd83eeb4f1682e2bd523ed36888e0d82c9a9", + "blockNumber": 553154, + "subtraces": 0, + "traceAddress": [ + 0 + ], + "transactionHash": "0x6af0a5c3188ffacae4d340d4a17e14fdb5a54187683a80ef241bde248189882b", + "transactionPosition": 15, + "type": "suicide" + } + ] +} \ No newline at end of file diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/throw.json new file mode 100644 index 00000000000..b119bed5289 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/throw.json @@ -0,0 +1,70 @@ +{ + "context": { + "difficulty": "117009631", + "gasLimit": "4712388", + "miner": "0x294e5d6c39a36ce38af1dca70c1060f78dee8070", + "number": "25009", + "timestamp": "1479891666" + }, + "genesis": { + "alloc": { + "0x70c9217d814985faef62b124420f8dfbddd96433": { + "balance": "0x4ecd70668f5d854a", + "code": "0x", + "nonce": "1638", + "storage": {} + }, + "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { + "balance": "0x0", + "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000061a9", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" + } + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "117066792", + "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", + "gasLimit": "4712388", + "hash": "0xe23e8d4562a1045b70cbc99fefb20c101a8f0fc8559a80d65fea8896e2f1d46e", + "miner": "0x71842f946b98800fe6feb49f0ae4e253259031c9", + "mixHash": "0x0aada9d6e93dd4db0d09c0488dc0a048fca2ccdc1f3fc7b83ba2a8d393a3a4ff", + "nonce": "0x70849d5838dee2e9", + "number": "25008", + "stateRoot": "0x1e01d2161794768c5b917069e73d86e8dca80cd7f3168c0597de420ab93a3b7b", + "timestamp": "1479891641", + "totalDifficulty": "1896347038589" + }, + "input": "0xf88b8206668504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb8000000000000000000000000000000000000000000000027fad02094277c000029a0692a3b4e7b2842f8dd7832e712c21e09f451f416c8976d5b8d02e8c0c2b4bea9a07645e90fc421b63dd755767fd93d3c03b4ec0c4d8fafa059558d08cf11d59750", + "result": [ + { + "action": { + "callType": "call", + "from": "0x70c9217d814985faef62b124420f8dfbddd96433", + "gas": "0x37b38", + "input": "0x51a34eb8000000000000000000000000000000000000000000000027fad02094277c0000", + "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", + "value": "0x0" + }, + "blockNumber": 25009, + "error": "invalid jump destination", + "result": {}, + "subtraces": 0, + "traceAddress": [], + "type": "call" + } + ] +} diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go index 524d1747493..1e2e46b55e1 100644 --- a/eth/tracers/js/tracer_test.go +++ b/eth/tracers/js/tracer_test.go @@ -57,7 +57,7 @@ type vmContext struct { } func testCtx() *vmContext { - return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}} + return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1), Time: 1}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}} } func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) { @@ -180,7 +180,7 @@ func TestHaltBetweenSteps(t *testing.T) { if err != nil { t.Fatal(err) } - env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) + env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: 1}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) scope := &vm.ScopeContext{ Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0), } @@ -204,7 +204,7 @@ func TestNoStepExec(t *testing.T) { if err != nil { t.Fatal(err) } - env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) + env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: 1}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0)) tracer.CaptureEnd(nil, 0, nil) ret, err := tracer.GetResult() @@ -239,7 +239,7 @@ func TestIsPrecompile(t *testing.T) { t.Fatal(err) } - blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150)} + blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150), Time: 150} res, err := runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil) if err != nil { t.Error(err) @@ -249,7 +249,7 @@ func TestIsPrecompile(t *testing.T) { } tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil) - blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)} + blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250), Time: 250} res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil) if err != nil { t.Error(err) diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index 1bc7456d31c..fb21294c82f 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -55,7 +55,7 @@ func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) {} func TestStoreCapture(t *testing.T) { var ( logger = NewStructLogger(nil) - env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: logger}) + env = vm.NewEVM(vm.BlockContext{Time: 0}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: logger}) contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000) ) contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)} diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index 75103f64cc8..02ee152a5aa 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -42,17 +42,17 @@ type callLog struct { } type callFrame struct { - Type vm.OpCode `json:"-"` - From common.Address `json:"from"` - Gas uint64 `json:"gas"` - GasUsed uint64 `json:"gasUsed"` - To common.Address `json:"to,omitempty" rlp:"optional"` - Input []byte `json:"input" rlp:"optional"` - Output []byte `json:"output,omitempty" rlp:"optional"` - Error string `json:"error,omitempty" rlp:"optional"` - RevertReason string `json:"revertReason,omitempty"` - Calls []callFrame `json:"calls,omitempty" rlp:"optional"` - Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Type vm.OpCode `json:"-"` + From common.Address `json:"from"` + Gas uint64 `json:"gas"` + GasUsed uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input []byte `json:"input" rlp:"optional"` + Output []byte `json:"output,omitempty" rlp:"optional"` + Error string `json:"error,omitempty" rlp:"optional"` + RevertReason string `json:"revertReason,omitempty"` + Calls []callFrame `json:"calls,omitempty" rlp:"optional"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` // Placed at end on purpose. The RLP will be decoded to 0 instead of // nil if there are non-empty elements after in the struct. Value *big.Int `json:"value,omitempty" rlp:"optional"` @@ -74,7 +74,7 @@ func (f *callFrame) processOutput(output []byte, err error) { } f.Error = err.Error() if f.Type == vm.CREATE || f.Type == vm.CREATE2 { - f.To = common.Address{} + f.To = nil } if !errors.Is(err, vm.ErrExecutionReverted) || len(output) == 0 { return @@ -127,10 +127,11 @@ func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, e // CaptureStart implements the EVMLogger interface to initialize the tracing operation. func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + toCopy := to t.callstack[0] = callFrame{ Type: vm.CALL, From: from, - To: to, + To: &toCopy, Input: common.CopyBytes(input), Gas: gas, Value: value, @@ -191,10 +192,11 @@ func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common. return } + toCopy := to call := callFrame{ Type: typ, From: from, - To: to, + To: &toCopy, Input: common.CopyBytes(input), Gas: gas, Value: value, @@ -240,6 +242,7 @@ func (t *callTracer) GetResult() (json.RawMessage, error) { if len(t.callstack) != 1 { return nil, errors.New("incorrect number of top-level calls") } + res, err := json.Marshal(t.callstack[0]) if err != nil { return nil, err diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go new file mode 100644 index 00000000000..5da60405062 --- /dev/null +++ b/eth/tracers/native/call_flat.go @@ -0,0 +1,379 @@ +// 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 native + +import ( + "encoding/json" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +//go:generate go run github.com/fjl/gencodec -type flatCallAction -field-override flatCallActionMarshaling -out gen_flatcallaction_json.go +//go:generate go run github.com/fjl/gencodec -type flatCallResult -field-override flatCallResultMarshaling -out gen_flatcallresult_json.go + +func init() { + tracers.DefaultDirectory.Register("flatCallTracer", newFlatCallTracer, false) +} + +var parityErrorMapping = map[string]string{ + "contract creation code storage out of gas": "Out of gas", + "out of gas": "Out of gas", + "gas uint64 overflow": "Out of gas", + "max code size exceeded": "Out of gas", + "invalid jump destination": "Bad jump destination", + "execution reverted": "Reverted", + "return data out of bounds": "Out of bounds", + "stack limit reached 1024 (1023)": "Out of stack", + "precompiled failed": "Built-in failed", + "invalid input length": "Built-in failed", +} + +var parityErrorMappingStartingWith = map[string]string{ + "invalid opcode:": "Bad instruction", + "stack underflow": "Stack underflow", +} + +// flatCallFrame is a standalone callframe. +type flatCallFrame struct { + Action flatCallAction `json:"action"` + BlockHash *common.Hash `json:"blockHash"` + BlockNumber uint64 `json:"blockNumber"` + Error string `json:"error,omitempty"` + Result *flatCallResult `json:"result,omitempty"` + Subtraces int `json:"subtraces"` + TraceAddress []int `json:"traceAddress"` + TransactionHash *common.Hash `json:"transactionHash"` + TransactionPosition uint64 `json:"transactionPosition"` + Type string `json:"type"` +} + +type flatCallAction struct { + Author *common.Address `json:"author,omitempty"` + RewardType string `json:"rewardType,omitempty"` + SelfDestructed *common.Address `json:"address,omitempty"` + Balance *big.Int `json:"balance,omitempty"` + CallType string `json:"callType,omitempty"` + CreationMethod string `json:"creationMethod,omitempty"` + From *common.Address `json:"from,omitempty"` + Gas *uint64 `json:"gas,omitempty"` + Init *[]byte `json:"init,omitempty"` + Input *[]byte `json:"input,omitempty"` + RefundAddress *common.Address `json:"refundAddress,omitempty"` + To *common.Address `json:"to,omitempty"` + Value *big.Int `json:"value,omitempty"` +} + +type flatCallActionMarshaling struct { + Balance *hexutil.Big + Gas *hexutil.Uint64 + Init *hexutil.Bytes + Input *hexutil.Bytes + Value *hexutil.Big +} + +type flatCallResult struct { + Address *common.Address `json:"address,omitempty"` + Code *[]byte `json:"code,omitempty"` + GasUsed *uint64 `json:"gasUsed,omitempty"` + Output *[]byte `json:"output,omitempty"` +} + +type flatCallResultMarshaling struct { + Code *hexutil.Bytes + GasUsed *hexutil.Uint64 + Output *hexutil.Bytes +} + +// flatCallTracer reports call frame information of a tx in a flat format, i.e. +// as opposed to the nested format of `callTracer`. +type flatCallTracer struct { + tracer *callTracer + config flatCallTracerConfig + ctx *tracers.Context // Holds tracer context data + reason error // Textual reason for the interruption + activePrecompiles []common.Address // Updated on CaptureStart based on given rules +} + +type flatCallTracerConfig struct { + ConvertParityErrors bool `json:"convertParityErrors"` // If true, call tracer converts errors to parity format + IncludePrecompiles bool `json:"includePrecompiles"` // If true, call tracer includes calls to precompiled contracts +} + +// newFlatCallTracer returns a new flatCallTracer. +func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + var config flatCallTracerConfig + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + + tracer, err := tracers.DefaultDirectory.New("callTracer", ctx, cfg) + if err != nil { + return nil, err + } + t, ok := tracer.(*callTracer) + if !ok { + return nil, errors.New("internal error: embedded tracer has wrong type") + } + + return &flatCallTracer{tracer: t, ctx: ctx, config: config}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *flatCallTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.tracer.CaptureStart(env, from, to, create, input, gas, value) + // Update list of precompiles based on current block + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + t.activePrecompiles = vm.ActivePrecompiles(rules) +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *flatCallTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { + t.tracer.CaptureEnd(output, gasUsed, err) +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *flatCallTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { + t.tracer.CaptureState(pc, op, gas, cost, scope, rData, depth, err) +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *flatCallTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { + t.tracer.CaptureFault(pc, op, gas, cost, scope, depth, err) +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *flatCallTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + t.tracer.CaptureEnter(typ, from, to, input, gas, value) + + // Child calls must have a value, even if it's zero. + // Practically speaking, only STATICCALL has nil value. Set it to zero. + if t.tracer.callstack[len(t.tracer.callstack)-1].Value == nil && value == nil { + t.tracer.callstack[len(t.tracer.callstack)-1].Value = big.NewInt(0) + } +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) { + t.tracer.CaptureExit(output, gasUsed, err) + + // Parity traces don't include CALL/STATICCALLs to precompiles. + // By default we remove them from the callstack. + if t.config.IncludePrecompiles { + return + } + var ( + // call has been nested in parent + parent = t.tracer.callstack[len(t.tracer.callstack)-1] + call = parent.Calls[len(parent.Calls)-1] + typ = call.Type + to = call.To + ) + if typ == vm.CALL || typ == vm.STATICCALL { + if t.isPrecompiled(*to) { + t.tracer.callstack[len(t.tracer.callstack)-1].Calls = parent.Calls[:len(parent.Calls)-1] + } + } +} + +func (t *flatCallTracer) CaptureTxStart(gasLimit uint64) { + t.tracer.CaptureTxStart(gasLimit) +} + +func (t *flatCallTracer) CaptureTxEnd(restGas uint64) { + t.tracer.CaptureTxEnd(restGas) +} + +// GetResult returns an empty json object. +func (t *flatCallTracer) GetResult() (json.RawMessage, error) { + if len(t.tracer.callstack) < 1 { + return nil, errors.New("invalid number of calls") + } + + flat, err := flatFromNested(&t.tracer.callstack[0], []int{}, t.config.ConvertParityErrors, t.ctx) + if err != nil { + return nil, err + } + + res, err := json.Marshal(flat) + if err != nil { + return nil, err + } + return res, t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *flatCallTracer) Stop(err error) { + t.tracer.Stop(err) +} + +// isPrecompiled returns whether the addr is a precompile. +func (t *flatCallTracer) isPrecompiled(addr common.Address) bool { + for _, p := range t.activePrecompiles { + if p == addr { + return true + } + } + return false +} + +func flatFromNested(input *callFrame, traceAddress []int, convertErrs bool, ctx *tracers.Context) (output []flatCallFrame, err error) { + var frame *flatCallFrame + switch input.Type { + case vm.CREATE, vm.CREATE2: + frame = newFlatCreate(input) + case vm.SELFDESTRUCT: + frame = newFlatSuicide(input) + case vm.CALL, vm.STATICCALL, vm.CALLCODE, vm.DELEGATECALL: + frame = newFlatCall(input) + default: + return nil, fmt.Errorf("unrecognized call frame type: %s", input.Type) + } + + frame.TraceAddress = traceAddress + frame.Error = input.Error + frame.Subtraces = len(input.Calls) + fillCallFrameFromContext(frame, ctx) + if convertErrs { + convertErrorToParity(frame) + } + + // Revert output contains useful information (revert reason). + // Otherwise discard result. + if input.Error != "" && input.Error != vm.ErrExecutionReverted.Error() { + frame.Result = nil + } + + output = append(output, *frame) + if len(input.Calls) > 0 { + for i, childCall := range input.Calls { + childAddr := childTraceAddress(traceAddress, i) + childCallCopy := childCall + flat, err := flatFromNested(&childCallCopy, childAddr, convertErrs, ctx) + if err != nil { + return nil, err + } + output = append(output, flat...) + } + } + + return output, nil +} + +func newFlatCreate(input *callFrame) *flatCallFrame { + var ( + actionInit = input.Input[:] + resultCode = input.Output[:] + ) + + return &flatCallFrame{ + Type: strings.ToLower(vm.CREATE.String()), + Action: flatCallAction{ + From: &input.From, + Gas: &input.Gas, + Value: input.Value, + Init: &actionInit, + }, + Result: &flatCallResult{ + GasUsed: &input.GasUsed, + Address: input.To, + Code: &resultCode, + }, + } +} + +func newFlatCall(input *callFrame) *flatCallFrame { + var ( + actionInput = input.Input[:] + resultOutput = input.Output[:] + ) + + return &flatCallFrame{ + Type: strings.ToLower(vm.CALL.String()), + Action: flatCallAction{ + From: &input.From, + To: input.To, + Gas: &input.Gas, + Value: input.Value, + CallType: strings.ToLower(input.Type.String()), + Input: &actionInput, + }, + Result: &flatCallResult{ + GasUsed: &input.GasUsed, + Output: &resultOutput, + }, + } +} + +func newFlatSuicide(input *callFrame) *flatCallFrame { + return &flatCallFrame{ + Type: "suicide", + Action: flatCallAction{ + SelfDestructed: &input.From, + Balance: input.Value, + RefundAddress: input.To, + }, + } +} + +func fillCallFrameFromContext(callFrame *flatCallFrame, ctx *tracers.Context) { + if ctx == nil { + return + } + if ctx.BlockHash != (common.Hash{}) { + callFrame.BlockHash = &ctx.BlockHash + } + if ctx.BlockNumber != nil { + callFrame.BlockNumber = ctx.BlockNumber.Uint64() + } + if ctx.TxHash != (common.Hash{}) { + callFrame.TransactionHash = &ctx.TxHash + } + callFrame.TransactionPosition = uint64(ctx.TxIndex) +} + +func convertErrorToParity(call *flatCallFrame) { + if call.Error == "" { + return + } + + if parityError, ok := parityErrorMapping[call.Error]; ok { + call.Error = parityError + } else { + for gethError, parityError := range parityErrorMappingStartingWith { + if strings.HasPrefix(call.Error, gethError) { + call.Error = parityError + } + } + } +} + +func childTraceAddress(a []int, i int) []int { + child := make([]int, 0, len(a)+1) + child = append(child, a...) + child = append(child, i) + return child +} diff --git a/eth/tracers/native/gen_callframe_json.go b/eth/tracers/native/gen_callframe_json.go index 21fc9e2b31a..c44f38390df 100644 --- a/eth/tracers/native/gen_callframe_json.go +++ b/eth/tracers/native/gen_callframe_json.go @@ -16,19 +16,19 @@ var _ = (*callFrameMarshaling)(nil) // MarshalJSON marshals as JSON. func (c callFrame) MarshalJSON() ([]byte, error) { type callFrame0 struct { - Type vm.OpCode `json:"-"` - From common.Address `json:"from"` - Gas hexutil.Uint64 `json:"gas"` - GasUsed hexutil.Uint64 `json:"gasUsed"` - To common.Address `json:"to,omitempty" rlp:"optional"` - Input hexutil.Bytes `json:"input" rlp:"optional"` - Output hexutil.Bytes `json:"output,omitempty" rlp:"optional"` - Error string `json:"error,omitempty" rlp:"optional"` - RevertReason string `json:"revertReason,omitempty"` - Calls []callFrame `json:"calls,omitempty" rlp:"optional"` - Logs []callLog `json:"logs,omitempty" rlp:"optional"` - Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` - TypeString string `json:"type"` + Type vm.OpCode `json:"-"` + From common.Address `json:"from"` + Gas hexutil.Uint64 `json:"gas"` + GasUsed hexutil.Uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input hexutil.Bytes `json:"input" rlp:"optional"` + Output hexutil.Bytes `json:"output,omitempty" rlp:"optional"` + Error string `json:"error,omitempty" rlp:"optional"` + RevertReason string `json:"revertReason,omitempty"` + Calls []callFrame `json:"calls,omitempty" rlp:"optional"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` + TypeString string `json:"type"` } var enc callFrame0 enc.Type = c.Type @@ -80,7 +80,7 @@ func (c *callFrame) UnmarshalJSON(input []byte) error { c.GasUsed = uint64(*dec.GasUsed) } if dec.To != nil { - c.To = *dec.To + c.To = dec.To } if dec.Input != nil { c.Input = *dec.Input diff --git a/eth/tracers/native/gen_flatcallaction_json.go b/eth/tracers/native/gen_flatcallaction_json.go new file mode 100644 index 00000000000..c0756069835 --- /dev/null +++ b/eth/tracers/native/gen_flatcallaction_json.go @@ -0,0 +1,110 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package native + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var _ = (*flatCallActionMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (f flatCallAction) MarshalJSON() ([]byte, error) { + type flatCallAction struct { + Author *common.Address `json:"author,omitempty"` + RewardType string `json:"rewardType,omitempty"` + SelfDestructed *common.Address `json:"address,omitempty"` + Balance *hexutil.Big `json:"balance,omitempty"` + CallType string `json:"callType,omitempty"` + CreationMethod string `json:"creationMethod,omitempty"` + From *common.Address `json:"from,omitempty"` + Gas *hexutil.Uint64 `json:"gas,omitempty"` + Init *hexutil.Bytes `json:"init,omitempty"` + Input *hexutil.Bytes `json:"input,omitempty"` + RefundAddress *common.Address `json:"refundAddress,omitempty"` + To *common.Address `json:"to,omitempty"` + Value *hexutil.Big `json:"value,omitempty"` + } + var enc flatCallAction + enc.Author = f.Author + enc.RewardType = f.RewardType + enc.SelfDestructed = f.SelfDestructed + enc.Balance = (*hexutil.Big)(f.Balance) + enc.CallType = f.CallType + enc.CreationMethod = f.CreationMethod + enc.From = f.From + enc.Gas = (*hexutil.Uint64)(f.Gas) + enc.Init = (*hexutil.Bytes)(f.Init) + enc.Input = (*hexutil.Bytes)(f.Input) + enc.RefundAddress = f.RefundAddress + enc.To = f.To + enc.Value = (*hexutil.Big)(f.Value) + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (f *flatCallAction) UnmarshalJSON(input []byte) error { + type flatCallAction struct { + Author *common.Address `json:"author,omitempty"` + RewardType *string `json:"rewardType,omitempty"` + SelfDestructed *common.Address `json:"address,omitempty"` + Balance *hexutil.Big `json:"balance,omitempty"` + CallType *string `json:"callType,omitempty"` + CreationMethod *string `json:"creationMethod,omitempty"` + From *common.Address `json:"from,omitempty"` + Gas *hexutil.Uint64 `json:"gas,omitempty"` + Init *hexutil.Bytes `json:"init,omitempty"` + Input *hexutil.Bytes `json:"input,omitempty"` + RefundAddress *common.Address `json:"refundAddress,omitempty"` + To *common.Address `json:"to,omitempty"` + Value *hexutil.Big `json:"value,omitempty"` + } + var dec flatCallAction + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Author != nil { + f.Author = dec.Author + } + if dec.RewardType != nil { + f.RewardType = *dec.RewardType + } + if dec.SelfDestructed != nil { + f.SelfDestructed = dec.SelfDestructed + } + if dec.Balance != nil { + f.Balance = (*big.Int)(dec.Balance) + } + if dec.CallType != nil { + f.CallType = *dec.CallType + } + if dec.CreationMethod != nil { + f.CreationMethod = *dec.CreationMethod + } + if dec.From != nil { + f.From = dec.From + } + if dec.Gas != nil { + f.Gas = (*uint64)(dec.Gas) + } + if dec.Init != nil { + f.Init = (*[]byte)(dec.Init) + } + if dec.Input != nil { + f.Input = (*[]byte)(dec.Input) + } + if dec.RefundAddress != nil { + f.RefundAddress = dec.RefundAddress + } + if dec.To != nil { + f.To = dec.To + } + if dec.Value != nil { + f.Value = (*big.Int)(dec.Value) + } + return nil +} diff --git a/eth/tracers/native/gen_flatcallresult_json.go b/eth/tracers/native/gen_flatcallresult_json.go new file mode 100644 index 00000000000..e9fa5e44da8 --- /dev/null +++ b/eth/tracers/native/gen_flatcallresult_json.go @@ -0,0 +1,55 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package native + +import ( + "encoding/json" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var _ = (*flatCallResultMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (f flatCallResult) MarshalJSON() ([]byte, error) { + type flatCallResult struct { + Address *common.Address `json:"address,omitempty"` + Code *hexutil.Bytes `json:"code,omitempty"` + GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` + Output *hexutil.Bytes `json:"output,omitempty"` + } + var enc flatCallResult + enc.Address = f.Address + enc.Code = (*hexutil.Bytes)(f.Code) + enc.GasUsed = (*hexutil.Uint64)(f.GasUsed) + enc.Output = (*hexutil.Bytes)(f.Output) + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (f *flatCallResult) UnmarshalJSON(input []byte) error { + type flatCallResult struct { + Address *common.Address `json:"address,omitempty"` + Code *hexutil.Bytes `json:"code,omitempty"` + GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` + Output *hexutil.Bytes `json:"output,omitempty"` + } + var dec flatCallResult + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Address != nil { + f.Address = dec.Address + } + if dec.Code != nil { + f.Code = (*[]byte)(dec.Code) + } + if dec.GasUsed != nil { + f.GasUsed = (*uint64)(dec.GasUsed) + } + if dec.Output != nil { + f.Output = (*[]byte)(dec.Output) + } + return nil +} diff --git a/eth/tracers/tracers.go b/eth/tracers/tracers.go index b93f7db6f57..856f52a10de 100644 --- a/eth/tracers/tracers.go +++ b/eth/tracers/tracers.go @@ -19,6 +19,7 @@ package tracers import ( "encoding/json" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" @@ -27,9 +28,10 @@ import ( // Context contains some contextual infos for a transaction execution that is not // available from within the EVM object. type Context struct { - BlockHash common.Hash // Hash of the block the tx is contained within (zero if dangling tx or call) - TxIndex int // Index of the transaction within a block (zero if dangling tx or call) - TxHash common.Hash // Hash of the transaction being traced (zero if dangling call) + BlockHash common.Hash // Hash of the block the tx is contained within (zero if dangling tx or call) + BlockNumber *big.Int // Number of the block the tx is contained within (zero if dangling tx or call) + TxIndex int // Index of the transaction within a block (zero if dangling tx or call) + TxHash common.Hash // Hash of the transaction being traced (zero if dangling call) } // Tracer interface extends vm.EVMLogger and additionally diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 6cd5a022b1a..7c5ec65650e 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -88,7 +88,7 @@ func BenchmarkTransactionTrace(b *testing.B) { //EnableReturnData: false, }) evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil) + msg, err := core.TransactionToMessage(tx, signer, nil) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 1d2df5466ed..c8353b25ae2 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -102,9 +102,10 @@ func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { } type rpcBlock struct { - Hash common.Hash `json:"hash"` - Transactions []rpcTransaction `json:"transactions"` - UncleHashes []common.Hash `json:"uncles"` + Hash common.Hash `json:"hash"` + Transactions []rpcTransaction `json:"transactions"` + UncleHashes []common.Hash `json:"uncles"` + Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` } func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) { @@ -112,15 +113,19 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface err := ec.c.CallContext(ctx, &raw, method, args...) if err != nil { return nil, err - } else if len(raw) == 0 { - return nil, ethereum.NotFound } + // Decode header and transactions. var head *types.Header - var body rpcBlock if err := json.Unmarshal(raw, &head); err != nil { return nil, err } + // When the block is not found, the API returns JSON null. + if head == nil { + return nil, ethereum.NotFound + } + + var body rpcBlock if err := json.Unmarshal(raw, &body); err != nil { return nil, err } @@ -131,10 +136,10 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles") } - if head.TxHash == types.EmptyRootHash && len(body.Transactions) > 0 { + if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 { return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions") } - if head.TxHash != types.EmptyRootHash && len(body.Transactions) == 0 { + if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 { return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions") } // Load uncles because they are not included in the block response. @@ -169,7 +174,7 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface } txs[i] = tx.tx } - return types.NewBlockWithHeader(head).WithBody(txs, uncles), nil + return types.NewBlockWithHeader(head).WithBody(txs, uncles).WithWithdrawals(body.Withdrawals), nil } // HeaderByHash returns the block header with the given hash. diff --git a/ethdb/dbtest/testsuite.go b/ethdb/dbtest/testsuite.go index 06a2d330db5..e455215cb0a 100644 --- a/ethdb/dbtest/testsuite.go +++ b/ethdb/dbtest/testsuite.go @@ -18,7 +18,7 @@ package dbtest import ( "bytes" - "math/rand" + "crypto/rand" "reflect" "sort" "testing" diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index fdad13b392e..4e374c9e283 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -14,12 +14,13 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -//go:build arm64 || amd64 +//go:build (arm64 || amd64) && !openbsd // Package pebble implements the key-value database layer based on pebble. package pebble import ( + "bytes" "fmt" "runtime" "sync" @@ -130,7 +131,7 @@ func New(file string, cache int, handles int, namespace string, readonly bool) ( // The max memtable size is limited by the uint32 offsets stored in // internal/arenaskl.node, DeferredBatchOp, and flushableBatchEntry. // Taken from https://github.com/cockroachdb/pebble/blob/master/open.go#L38 - maxMemTableSize := 4 << 30 // 4 GB + maxMemTableSize := 4<<30 - 1 // Capped by 4 GB // Two memory tables is configured which is identical to leveldb, // including a frozen memory table and another live one. @@ -361,6 +362,17 @@ func (d *Database) Stat(property string) (string, error) { // is treated as a key after all keys in the data store. If both is nil then it // will compact entire data store. func (d *Database) Compact(start []byte, limit []byte) error { + // There is no special flag to represent the end of key range + // in pebble(nil in leveldb). Use an ugly hack to construct a + // large key to represent it. + // Note any prefixed database entry will be smaller than this + // flag, as for trie nodes we need the 32 byte 0xff because + // there might be a shared prefix starting with a number of + // 0xff-s, so 32 ensures than only a hash collision could touch it. + // https://github.com/cockroachdb/pebble/issues/2359#issuecomment-1443995833 + if limit == nil { + limit = bytes.Repeat([]byte{0xff}, 32) + } return d.db.Compact(start, limit, true) // Parallelization is preferred } diff --git a/ethdb/pebble/pebble_test.go b/ethdb/pebble/pebble_test.go index c773967dc66..590d5bf0353 100644 --- a/ethdb/pebble/pebble_test.go +++ b/ethdb/pebble/pebble_test.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 . -//go:build arm64 || amd64 +//go:build (arm64 || amd64) && !openbsd package pebble diff --git a/event/event_test.go b/event/event_test.go index bdad11f13d6..84b37eca3ba 100644 --- a/event/event_test.go +++ b/event/event_test.go @@ -100,7 +100,6 @@ func TestSubscribeDuplicateType(t *testing.T) { } func TestMuxConcurrent(t *testing.T) { - rand.Seed(time.Now().Unix()) mux := new(TypeMux) defer mux.Stop() diff --git a/event/feedof.go b/event/feedof.go index 598038a19e2..4a24e37f125 100644 --- a/event/feedof.go +++ b/event/feedof.go @@ -14,9 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -//go:build go1.18 -// +build go1.18 - package event import ( diff --git a/event/feedof_test.go b/event/feedof_test.go index 8478eeffb1e..846afc9ee19 100644 --- a/event/feedof_test.go +++ b/event/feedof_test.go @@ -14,9 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -//go:build go1.18 -// +build go1.18 - package event import ( diff --git a/go.mod b/go.mod index fbac3e4d67a..d2d1c93a815 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum/go-ethereum -go 1.18 +go 1.19 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 @@ -13,7 +13,8 @@ require ( github.com/cespare/cp v0.1.0 github.com/cloudflare/cloudflare-go v0.14.0 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 - github.com/consensys/gnark-crypto v0.9.1-0.20230105202408-1a7a29904a7c + github.com/consensys/gnark-crypto v0.10.0 + github.com/crate-crypto/go-kzg-4844 v0.1.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 github.com/docker/docker v1.6.2 @@ -26,6 +27,7 @@ require ( github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff github.com/gballet/go-verkle v0.0.0-20220902153445-097bd83b7732 github.com/go-stack/stack v1.8.1 + github.com/gofrs/flock v0.8.1 github.com/golang-jwt/jwt/v4 v4.3.0 github.com/golang/protobuf v1.5.2 github.com/golang/snappy v0.0.4 @@ -34,9 +36,8 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/graph-gophers/graphql-go v1.3.0 github.com/hashicorp/go-bexpr v0.1.10 - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e github.com/holiman/bloomfilter/v2 v2.0.3 - github.com/holiman/uint256 v1.2.0 + github.com/holiman/uint256 v1.2.1 github.com/huin/goupnp v1.0.3 github.com/influxdata/influxdb v1.8.3 github.com/influxdata/influxdb-client-go/v2 v2.4.0 @@ -44,12 +45,13 @@ require ( github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e github.com/julienschmidt/httprouter v1.3.0 github.com/karalabe/usb v0.0.2 + github.com/kylelemons/godebug v1.1.0 github.com/mattn/go-colorable v0.1.13 github.com/mattn/go-isatty v0.0.16 github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 - github.com/prometheus/tsdb v0.7.1 + github.com/protolambda/ztyp v0.2.1 github.com/rs/cors v1.7.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/status-im/keycard-go v0.2.0 @@ -61,7 +63,7 @@ require ( golang.org/x/crypto v0.1.0 golang.org/x/exp v0.0.0-20230206171751-46f607a40771 golang.org/x/sync v0.1.0 - golang.org/x/sys v0.5.0 + golang.org/x/sys v0.6.0 golang.org/x/text v0.7.0 golang.org/x/time v0.0.0-20220922220347-f3bd1da661af golang.org/x/tools v0.2.0 @@ -79,6 +81,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect github.com/aws/smithy-go v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.5.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect @@ -98,7 +101,6 @@ require ( github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect diff --git a/go.sum b/go.sum index bf28cd2e24e..707f1162f02 100644 --- a/go.sum +++ b/go.sum @@ -71,6 +71,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8= +github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= @@ -105,8 +107,8 @@ github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.9.1-0.20230105202408-1a7a29904a7c h1:llSLg4o9EgH3SrXky+Q5BqEYqV76NGKo07K5Ps2pIKo= -github.com/consensys/gnark-crypto v0.9.1-0.20230105202408-1a7a29904a7c/go.mod h1:CkbdF9hbRidRJYMRzmfX8TMOr95I2pYXRHF18MzRrvA= +github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= +github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -116,6 +118,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7 h1:6IrxszG5G+O7zhtkWxq6+unVvnrm1fqV2Pe+T95DUzw= github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7/go.mod h1:gFnFS95y8HstDP6P9pPwzrxOOC5TRDkwbM+ao15ChAI= +github.com/crate-crypto/go-kzg-4844 v0.1.0 h1:2PXr2wKBNTmSsoYLCmaNg5Z6uQUf7LiUAsnDbTfq+0M= +github.com/crate-crypto/go-kzg-4844 v0.1.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= @@ -135,7 +139,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= @@ -195,11 +198,9 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= @@ -214,6 +215,8 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= @@ -294,12 +297,11 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/uint256 v1.2.1 h1:XRtyuda/zw2l+Bq/38n5XUoEF72aSOu/77Thd9pPp2o= +github.com/holiman/uint256 v1.2.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= @@ -440,7 +442,6 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -481,7 +482,6 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= @@ -490,8 +490,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/protolambda/ztyp v0.2.1 h1:+rfw75/Zh8EopNlG652TGDXlLgJflj6XWxJ9yCVpJws= +github.com/protolambda/ztyp v0.2.1/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -683,7 +683,6 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -727,8 +726,8 @@ golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/graphql/graphql.go b/graphql/graphql.go index 356ff669fb1..0c13cc80f55 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -1219,7 +1219,7 @@ func (r *Resolver) Blocks(ctx context.Context, args struct { if args.To != nil { to = rpc.BlockNumber(*args.To) } else { - to = rpc.BlockNumber(r.backend.CurrentBlock().Number().Int64()) + to = rpc.BlockNumber(r.backend.CurrentBlock().Number.Int64()) } if to < from { return []*Block{}, nil diff --git a/interfaces.go b/interfaces.go index eb9af60076e..0926016e921 100644 --- a/interfaces.go +++ b/interfaces.go @@ -132,16 +132,18 @@ type ChainSyncReader interface { // CallMsg contains parameters for contract calls. type CallMsg struct { - From common.Address // the sender of the 'transaction' - To *common.Address // the destination contract (nil for contract creation) - Gas uint64 // if 0, the call executes with near-infinite gas - GasPrice *big.Int // wei <-> gas exchange ratio - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - GasTipCap *big.Int // EIP-1559 tip per gas. - Value *big.Int // amount of wei sent along with the call - Data []byte // input data, usually an ABI-encoded contract method invocation + From common.Address // the sender of the 'transaction' + To *common.Address // the destination contract (nil for contract creation) + Gas uint64 // if 0, the call executes with near-infinite gas + GasPrice *big.Int // wei <-> gas exchange ratio + GasFeeCap *big.Int // EIP-1559 fee cap per gas. + GasTipCap *big.Int // EIP-1559 tip per gas. + MaxFeePerDataGas *big.Int // EIP-4844 max_fee_per_data_gas + Value *big.Int // amount of wei sent along with the call + Data []byte // input data, usually an ABI-encoded contract method invocation AccessList types.AccessList // EIP-2930 access list. + DataHashes []common.Hash // versioned data hashes for EIP-4844 } // A ContractCaller provides contract calls, essentially transactions that are executed by diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 58f65f86d79..c09e12316c8 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -229,6 +229,7 @@ func (s *TxPoolAPI) Inspect() map[string]map[string]map[string]string { // Define a formatter to flatten a transaction into a string var format = func(tx *types.Transaction) string { + // TODO: handle data gas for txs with blobs (EIP-4844) if to := tx.To(); to != nil { return fmt.Sprintf("%s: %v wei + %v gas × %v wei", tx.To().Hex(), tx.Value(), tx.Gas(), tx.GasPrice()) } @@ -918,13 +919,14 @@ func (diff *StateOverride) Apply(state *state.StateDB) error { // BlockOverrides is a set of header fields to override. type BlockOverrides struct { - Number *hexutil.Big - Difficulty *hexutil.Big - Time *hexutil.Uint64 - GasLimit *hexutil.Uint64 - Coinbase *common.Address - Random *common.Hash - BaseFee *hexutil.Big + Number *hexutil.Big + Difficulty *hexutil.Big + Time *hexutil.Uint64 + GasLimit *hexutil.Uint64 + Coinbase *common.Address + Random *common.Hash + BaseFee *hexutil.Big + ExcessDataGas *hexutil.Big } // Apply overrides the given header fields into the given block context. @@ -953,6 +955,9 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) { if diff.BaseFee != nil { blockCtx.BaseFee = diff.BaseFee.ToInt() } + if diff.ExcessDataGas != nil { + blockCtx.ExcessDataGas = diff.BaseFee.ToInt() + } } func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { @@ -994,7 +999,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash }() // Execute the message. - gp := new(core.GasPool).AddGas(math.MaxUint64) + gp := new(core.GasPool).AddGas(math.MaxUint64).AddDataGas(params.MaxDataGasPerBlock) result, err := core.ApplyMessage(evm, msg, gp) if err := vmError(); err != nil { return nil, err @@ -1005,7 +1010,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout) } if err != nil { - return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) + return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.GasLimit) } return result, nil } @@ -1213,6 +1218,12 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} { if head.BaseFee != nil { result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee) } + if head.WithdrawalsHash != nil { + result["withdrawalsRoot"] = *head.WithdrawalsHash + } + if head.ExcessDataGas != nil { + result["excessDataGas"] = (*hexutil.Big)(head.ExcessDataGas) + } if head.WithdrawalsHash != nil { result["withdrawalsRoot"] = head.WithdrawalsHash @@ -1246,6 +1257,9 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param } } fields["transactions"] = transactions + // inclTx also expands withdrawals + // TODO @MariusVanDerWijden: add a second flag similar to inclTx to enable withdrawals + fields["withdrawals"] = block.Withdrawals() } uncles := block.Uncles() uncleHashes := make([]common.Hash, len(uncles)) @@ -1282,46 +1296,49 @@ func (s *BlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inc // RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction type RPCTransaction struct { - BlockHash *common.Hash `json:"blockHash"` - BlockNumber *hexutil.Big `json:"blockNumber"` - From common.Address `json:"from"` - Gas hexutil.Uint64 `json:"gas"` - GasPrice *hexutil.Big `json:"gasPrice"` - GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` - GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` - Hash common.Hash `json:"hash"` - Input hexutil.Bytes `json:"input"` - Nonce hexutil.Uint64 `json:"nonce"` - To *common.Address `json:"to"` - TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` - Value *hexutil.Big `json:"value"` - Type hexutil.Uint64 `json:"type"` - Accesses *types.AccessList `json:"accessList,omitempty"` - ChainID *hexutil.Big `json:"chainId,omitempty"` - V *hexutil.Big `json:"v"` - R *hexutil.Big `json:"r"` - S *hexutil.Big `json:"s"` + BlockHash *common.Hash `json:"blockHash"` + BlockNumber *hexutil.Big `json:"blockNumber"` + From common.Address `json:"from"` + Gas hexutil.Uint64 `json:"gas"` + GasPrice *hexutil.Big `json:"gasPrice"` + GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` + GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` + Hash common.Hash `json:"hash"` + Input hexutil.Bytes `json:"input"` + Nonce hexutil.Uint64 `json:"nonce"` + To *common.Address `json:"to"` + TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` + Value *hexutil.Big `json:"value"` + Type hexutil.Uint64 `json:"type"` + Accesses *types.AccessList `json:"accessList,omitempty"` + MaxFeePerDataGas *hexutil.Big `json:"maxFeePerDataGas,omitempty"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + ChainID *hexutil.Big `json:"chainId,omitempty"` + V *hexutil.Big `json:"v"` + R *hexutil.Big `json:"r"` + S *hexutil.Big `json:"s"` } // newRPCTransaction returns a transaction that will serialize to the RPC // representation, with the given location metadata set (if available). -func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction { - signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber)) +func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction { + signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime) from, _ := types.Sender(signer, tx) v, r, s := tx.RawSignatureValues() result := &RPCTransaction{ - Type: hexutil.Uint64(tx.Type()), - From: from, - Gas: hexutil.Uint64(tx.Gas()), - GasPrice: (*hexutil.Big)(tx.GasPrice()), - Hash: tx.Hash(), - Input: hexutil.Bytes(tx.Data()), - Nonce: hexutil.Uint64(tx.Nonce()), - To: tx.To(), - Value: (*hexutil.Big)(tx.Value()), - V: (*hexutil.Big)(v), - R: (*hexutil.Big)(r), - S: (*hexutil.Big)(s), + Type: hexutil.Uint64(tx.Type()), + From: from, + Gas: hexutil.Uint64(tx.Gas()), + GasPrice: (*hexutil.Big)(tx.GasPrice()), + Hash: tx.Hash(), + Input: hexutil.Bytes(tx.Data()), + Nonce: hexutil.Uint64(tx.Nonce()), + To: tx.To(), + BlobVersionedHashes: tx.DataHashes(), + Value: (*hexutil.Big)(tx.Value()), + V: (*hexutil.Big)(v), + R: (*hexutil.Big)(r), + S: (*hexutil.Big)(s), } if blockHash != (common.Hash{}) { result.BlockHash = &blockHash @@ -1338,12 +1355,13 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber al := tx.AccessList() result.Accesses = &al result.ChainID = (*hexutil.Big)(tx.ChainId()) - case types.DynamicFeeTxType: + case types.DynamicFeeTxType, types.BlobTxType: al := tx.AccessList() result.Accesses = &al result.ChainID = (*hexutil.Big)(tx.ChainId()) result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap()) result.GasTipCap = (*hexutil.Big)(tx.GasTipCap()) + result.MaxFeePerDataGas = (*hexutil.Big)(tx.MaxFeePerDataGas()) // if the transaction has been mined, compute the effective gas price if baseFee != nil && blockHash != (common.Hash{}) { // price = min(tip, gasFeeCap - baseFee) + baseFee @@ -1360,11 +1378,13 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction { var baseFee *big.Int blockNumber := uint64(0) + var blockTime uint64 if current != nil { baseFee = misc.CalcBaseFee(config, current) blockNumber = current.Number.Uint64() + blockTime = current.Time } - return newRPCTransaction(tx, common.Hash{}, blockNumber, 0, baseFee, config) + return newRPCTransaction(tx, common.Hash{}, blockNumber, blockTime, 0, baseFee, config) } // newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation. @@ -1373,7 +1393,7 @@ func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *param if index >= uint64(len(txs)) { return nil } - return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee(), config) + return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config) } // newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index. @@ -1478,7 +1498,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH if err != nil { return nil, 0, nil, err } - res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit).AddDataGas(params.MaxDataGasPerBlock)) if err != nil { return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.toTransaction().Hash(), err) } @@ -1585,7 +1605,7 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H if err != nil { return nil, err } - return newRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee, s.b.ChainConfig()), nil + return newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, s.b.ChainConfig()), nil } // No finalized transaction, try to retrieve it from the pool if tx := s.b.GetPoolTransaction(hash); tx != nil { @@ -1621,6 +1641,7 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. // as per specification. return nil, nil } + receipts, err := s.b.GetReceipts(ctx, blockHash) if err != nil { return nil, err @@ -1629,10 +1650,13 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. return nil, nil } receipt := receipts[index] - + header, err := s.b.HeaderByHash(ctx, blockHash) + if err != nil { + return nil, err + } // Derive the sender. bigblock := new(big.Int).SetUint64(blockNumber) - signer := types.MakeSigner(s.b.ChainConfig(), bigblock) + signer := types.MakeSigner(s.b.ChainConfig(), bigblock, header.Time) from, _ := types.Sender(signer, tx) fields := map[string]interface{}{ @@ -1648,18 +1672,13 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. "logs": receipt.Logs, "logsBloom": receipt.Bloom, "type": hexutil.Uint(tx.Type()), + "effectiveGasPrice": (*hexutil.Big)(receipt.EffectiveGasPrice), } - // Assign the effective gas price paid - if !s.b.ChainConfig().IsLondon(bigblock) { - fields["effectiveGasPrice"] = hexutil.Uint64(tx.GasPrice().Uint64()) - } else { - header, err := s.b.HeaderByHash(ctx, blockHash) - if err != nil { - return nil, err - } - gasPrice := new(big.Int).Add(header.BaseFee, tx.EffectiveGasTipValue(header.BaseFee)) - fields["effectiveGasPrice"] = hexutil.Uint64(gasPrice.Uint64()) + if receipt.DataGasUsed > 0 { + fields["dataGasUsed"] = hexutil.Uint64(receipt.DataGasUsed) + fields["dataGasPrice"] = (*hexutil.Big)(receipt.DataGasPrice) } + // Assign receipt status or post state. if len(receipt.PostState) > 0 { fields["root"] = hexutil.Bytes(receipt.PostState) @@ -1669,6 +1688,7 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. if receipt.Logs == nil { fields["logs"] = []*types.Log{} } + // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation if receipt.ContractAddress != (common.Address{}) { fields["contractAddress"] = receipt.ContractAddress @@ -1704,7 +1724,7 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c return common.Hash{}, err } // Print a log with full tx details for manual investigations and interventions - signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number()) + signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number, b.CurrentBlock().Time) from, err := types.Sender(signer, tx) if err != nil { return common.Hash{}, err diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go new file mode 100644 index 00000000000..205e23e8474 --- /dev/null +++ b/internal/ethapi/api_test.go @@ -0,0 +1,159 @@ +// Copyright 2023 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 ethapi + +import ( + "encoding/json" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" +) + +func TestTransaction_RoundTripRpcJSON(t *testing.T) { + var ( + config = params.AllEthashProtocolChanges + signer = types.LatestSigner(config) + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + tests = allTransactionTypes(common.Address{0xde, 0xad}, config) + ) + t.Parallel() + for i, tt := range tests { + var tx2 types.Transaction + tx, err := types.SignNewTx(key, signer, tt) + if err != nil { + t.Fatalf("test %d: signing failed: %v", i, err) + } + // Regular transaction + if data, err := json.Marshal(tx); err != nil { + t.Fatalf("test %d: marshalling failed; %v", i, err) + } else if err = tx2.UnmarshalJSON(data); err != nil { + t.Fatalf("test %d: sunmarshal failed: %v", i, err) + } else if want, have := tx.Hash(), tx2.Hash(); want != have { + t.Fatalf("test %d: stx changed, want %x have %x", i, want, have) + } + + // rpcTransaction + rpcTx := newRPCTransaction(tx, common.Hash{}, 0, 0, 0, nil, config) + if data, err := json.Marshal(rpcTx); err != nil { + t.Fatalf("test %d: marshalling failed; %v", i, err) + } else if err = tx2.UnmarshalJSON(data); err != nil { + t.Fatalf("test %d: unmarshal failed: %v", i, err) + } else if want, have := tx.Hash(), tx2.Hash(); want != have { + t.Fatalf("test %d: tx changed, want %x have %x", i, want, have) + } + } +} + +func allTransactionTypes(addr common.Address, config *params.ChainConfig) []types.TxData { + return []types.TxData{ + &types.LegacyTx{ + Nonce: 5, + GasPrice: big.NewInt(6), + Gas: 7, + To: &addr, + Value: big.NewInt(8), + Data: []byte{0, 1, 2, 3, 4}, + V: big.NewInt(9), + R: big.NewInt(10), + S: big.NewInt(11), + }, + &types.LegacyTx{ + Nonce: 5, + GasPrice: big.NewInt(6), + Gas: 7, + To: nil, + Value: big.NewInt(8), + Data: []byte{0, 1, 2, 3, 4}, + V: big.NewInt(32), + R: big.NewInt(10), + S: big.NewInt(11), + }, + &types.AccessListTx{ + ChainID: config.ChainID, + Nonce: 5, + GasPrice: big.NewInt(6), + Gas: 7, + To: &addr, + Value: big.NewInt(8), + Data: []byte{0, 1, 2, 3, 4}, + AccessList: types.AccessList{ + types.AccessTuple{ + Address: common.Address{0x2}, + StorageKeys: []common.Hash{types.EmptyRootHash}, + }, + }, + V: big.NewInt(32), + R: big.NewInt(10), + S: big.NewInt(11), + }, + &types.AccessListTx{ + ChainID: config.ChainID, + Nonce: 5, + GasPrice: big.NewInt(6), + Gas: 7, + To: nil, + Value: big.NewInt(8), + Data: []byte{0, 1, 2, 3, 4}, + AccessList: types.AccessList{ + types.AccessTuple{ + Address: common.Address{0x2}, + StorageKeys: []common.Hash{types.EmptyRootHash}, + }, + }, + V: big.NewInt(32), + R: big.NewInt(10), + S: big.NewInt(11), + }, + &types.DynamicFeeTx{ + ChainID: config.ChainID, + Nonce: 5, + GasTipCap: big.NewInt(6), + GasFeeCap: big.NewInt(9), + Gas: 7, + To: &addr, + Value: big.NewInt(8), + Data: []byte{0, 1, 2, 3, 4}, + AccessList: types.AccessList{ + types.AccessTuple{ + Address: common.Address{0x2}, + StorageKeys: []common.Hash{types.EmptyRootHash}, + }, + }, + V: big.NewInt(32), + R: big.NewInt(10), + S: big.NewInt(11), + }, + &types.DynamicFeeTx{ + ChainID: config.ChainID, + Nonce: 5, + GasTipCap: big.NewInt(6), + GasFeeCap: big.NewInt(9), + Gas: 7, + To: nil, + Value: big.NewInt(8), + Data: []byte{0, 1, 2, 3, 4}, + AccessList: types.AccessList{}, + V: big.NewInt(32), + R: big.NewInt(10), + S: big.NewInt(11), + }, + } +} diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 0c1763472f2..98887afc803 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -59,7 +59,7 @@ type Backend interface { HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) CurrentHeader() *types.Header - CurrentBlock() *types.Block + CurrentBlock() *types.Header BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) @@ -68,7 +68,7 @@ type Backend interface { PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetTd(ctx context.Context, hash common.Hash) *big.Int - GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) + GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index e07248db5d6..ad0eab3c06b 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -23,9 +23,12 @@ import ( "fmt" "math/big" + "github.com/protolambda/ztyp/view" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" @@ -40,6 +43,7 @@ type TransactionArgs struct { GasPrice *hexutil.Big `json:"gasPrice"` MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"` MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"` + MaxFeePerDataGas *hexutil.Big `json:"maxFeePerDataGas"` Value *hexutil.Big `json:"value"` Nonce *hexutil.Uint64 `json:"nonce"` @@ -52,6 +56,8 @@ type TransactionArgs struct { // Introduced by AccessListTxType transaction. AccessList *types.AccessList `json:"accessList,omitempty"` ChainID *hexutil.Big `json:"chainId,omitempty"` + + Blobs []types.Blob `json:"blobs,omitempty"` } // from retrieves the transaction sender address. @@ -199,10 +205,10 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ // ToMessage converts the transaction arguments to the Message type used by the // core evm. This method is used in calls and traces that do not require a real // live transaction. -func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (types.Message, error) { +func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Message, error) { // Reject invalid combinations of pre- and post-1559 fee styles if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { - return types.Message{}, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } // Set sender address or use zero address if none specified. addr := args.from() @@ -220,9 +226,10 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t gas = globalGasCap } var ( - gasPrice *big.Int - gasFeeCap *big.Int - gasTipCap *big.Int + gasPrice *big.Int + gasFeeCap *big.Int + gasTipCap *big.Int + maxFeePerDataGas *big.Int ) if baseFee == nil { // If there's no basefee, then it must be a non-1559 execution @@ -253,6 +260,9 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap) } } + if args.MaxFeePerDataGas != nil { + maxFeePerDataGas = args.MaxFeePerDataGas.ToInt() + } } value := new(big.Int) if args.Value != nil { @@ -263,7 +273,25 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t if args.AccessList != nil { accessList = *args.AccessList } - msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true) + // The values don't matter. Only its cardinality is used for correct gas estimation + var fakeDataHashes []common.Hash + if args.Blobs != nil { + fakeDataHashes = make([]common.Hash, len(args.Blobs)) + } + msg := &core.Message{ + From: addr, + To: args.To, + Value: value, + GasLimit: gas, + GasPrice: gasPrice, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + MaxFeePerDataGas: maxFeePerDataGas, + Data: data, + AccessList: accessList, + DataHashes: fakeDataHashes, + SkipAccountChecks: true, + } return msg, nil } @@ -271,7 +299,35 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t // This assumes that setDefaults has been called. func (args *TransactionArgs) toTransaction() *types.Transaction { var data types.TxData + var opts []types.TxOption switch { + case args.Blobs != nil: + al := types.AccessList{} + if args.AccessList != nil { + al = *args.AccessList + } + msg := types.BlobTxMessage{} + msg.To.Address = (*types.AddressSSZ)(args.To) + msg.ChainID.SetFromBig((*big.Int)(args.ChainID)) + msg.Nonce = view.Uint64View(*args.Nonce) + msg.Gas = view.Uint64View(*args.Gas) + msg.GasFeeCap.SetFromBig((*big.Int)(args.MaxFeePerGas)) + msg.GasTipCap.SetFromBig((*big.Int)(args.MaxPriorityFeePerGas)) + msg.MaxFeePerDataGas.SetFromBig((*big.Int)(args.MaxFeePerDataGas)) + msg.Value.SetFromBig((*big.Int)(args.Value)) + msg.Data = args.data() + msg.AccessList = types.AccessListView(al) + commitments, versionedHashes, proofs, err := types.Blobs(args.Blobs).ComputeCommitmentsAndProofs() + // XXX if blobs are invalid we will omit the wrap-data (and an error will pop-up later) + if err == nil { + opts = append(opts, types.WithTxWrapData(&types.BlobTxWrapData{ + BlobKzgs: commitments, + Blobs: args.Blobs, + Proofs: proofs, + })) + msg.BlobVersionedHashes = versionedHashes + } + data = &types.SignedBlobTx{Message: msg} case args.MaxFeePerGas != nil: al := types.AccessList{} if args.AccessList != nil { @@ -309,7 +365,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction { Data: args.data(), } } - return types.NewTx(data) + return types.NewTx(data, opts...) } // ToTransaction converts the arguments to a transaction. diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index a8f2d521488..1b533861d5d 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -278,7 +278,7 @@ func (b *backendMock) HeaderByHash(ctx context.Context, hash common.Hash) (*type func (b *backendMock) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { return nil, nil } -func (b *backendMock) CurrentBlock() *types.Block { return nil } +func (b *backendMock) CurrentBlock() *types.Header { return nil } func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { return nil, nil } @@ -305,7 +305,7 @@ func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number return nil, nil } func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *backendMock) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { return nil, nil, nil } func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil } diff --git a/internal/version/vcs_go1.18.go b/internal/version/vcs.go similarity index 97% rename from internal/version/vcs_go1.18.go rename to internal/version/vcs.go index 53cd41fb309..21de8946e80 100644 --- a/internal/version/vcs_go1.18.go +++ b/internal/version/vcs.go @@ -14,9 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -//go:build go1.18 -// +build go1.18 - package version import ( diff --git a/internal/version/vcs_fallback.go b/internal/version/vcs_fallback.go deleted file mode 100644 index f792c68cdb4..00000000000 --- a/internal/version/vcs_fallback.go +++ /dev/null @@ -1,28 +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 . - -//go:build !go1.18 -// +build !go1.18 - -package version - -import "runtime/debug" - -// In Go versions before 1.18, VCS information is not available. - -func buildInfoVCS(info *debug.BuildInfo) (VCSInfo, bool) { - return VCSInfo{}, false -} diff --git a/les/api_backend.go b/les/api_backend.go index 422ac74b866..c9cfa8bcf51 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -52,8 +52,8 @@ func (b *LesApiBackend) ChainConfig() *params.ChainConfig { return b.eth.chainConfig } -func (b *LesApiBackend) CurrentBlock() *types.Block { - return types.NewBlockWithHeader(b.eth.BlockChain().CurrentHeader()) +func (b *LesApiBackend) CurrentBlock() *types.Header { + return b.eth.BlockChain().CurrentHeader() } func (b *LesApiBackend) SetHead(number uint64) { @@ -184,12 +184,20 @@ func (b *LesApiBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *LesApiBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { if vmConfig == nil { vmConfig = new(vm.Config) } txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(header, b.eth.blockchain, nil) + var excessDataGas *big.Int + ph, err := b.HeaderByHash(ctx, header.ParentHash) + if err != nil { + return nil, state.Error, err + } + if ph != nil { + excessDataGas = ph.ExcessDataGas + } + context := core.NewEVMBlockContext(header, excessDataGas, b.eth.blockchain, nil) return vm.NewEVM(context, txContext, state, b.eth.chainConfig, *vmConfig), state.Error, nil } @@ -330,6 +338,6 @@ func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, re return b.eth.stateAtBlock(ctx, block, reexec) } -func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } diff --git a/les/api_test.go b/les/api_test.go index 3db1c5fd5ec..db680da0bff 100644 --- a/les/api_test.go +++ b/les/api_test.go @@ -18,6 +18,7 @@ package les import ( "context" + crand "crypto/rand" "errors" "flag" "math/rand" @@ -326,7 +327,7 @@ func getHead(ctx context.Context, t *testing.T, client *rpc.Client) (uint64, com func testRequest(ctx context.Context, t *testing.T, client *rpc.Client) bool { var res string var addr common.Address - rand.Read(addr[:]) + crand.Read(addr[:]) c, cancel := context.WithTimeout(ctx, time.Second*12) defer cancel() err := client.CallContext(c, &res, "eth_getBalance", addr, "latest") diff --git a/les/benchmark.go b/les/benchmark.go index 757822a6b31..95563a21aaf 100644 --- a/les/benchmark.go +++ b/les/benchmark.go @@ -17,6 +17,7 @@ package les import ( + crand "crypto/rand" "encoding/binary" "fmt" "math/big" @@ -114,7 +115,7 @@ func (b *benchmarkProofsOrCode) init(h *serverHandler, count int) error { func (b *benchmarkProofsOrCode) request(peer *serverPeer, index int) error { key := make([]byte, 32) - rand.Read(key) + crand.Read(key) if b.code { return peer.requestCode(0, []CodeReq{{BHash: b.headHash, AccKey: key}}) } @@ -176,7 +177,7 @@ func (b *benchmarkTxSend) init(h *serverHandler, count int) error { for i := range b.txs { data := make([]byte, txSizeCostLimit) - rand.Read(data) + crand.Read(data) tx, err := types.SignTx(types.NewTransaction(0, addr, new(big.Int), 0, new(big.Int), data), signer, key) if err != nil { panic(err) @@ -200,7 +201,7 @@ func (b *benchmarkTxStatus) init(h *serverHandler, count int) error { func (b *benchmarkTxStatus) request(peer *serverPeer, index int) error { var hash common.Hash - rand.Read(hash[:]) + crand.Read(hash[:]) return peer.requestTxStatus(0, []common.Hash{hash}) } @@ -278,7 +279,7 @@ func (h *serverHandler) measure(setup *benchmarkSetup, count int) error { clientMeteredPipe := &meteredPipe{rw: clientPipe} serverMeteredPipe := &meteredPipe{rw: serverPipe} var id enode.ID - rand.Read(id[:]) + crand.Read(id[:]) peer1 := newServerPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "client", nil), clientMeteredPipe) peer2 := newClientPeer(lpv2, NetworkId, p2p.NewPeer(id, "server", nil), serverMeteredPipe) diff --git a/les/catalyst/api_test.go b/les/catalyst/api_test.go index 54757f61dae..36ececa5921 100644 --- a/les/catalyst/api_test.go +++ b/les/catalyst/api_test.go @@ -167,6 +167,81 @@ func TestExecutePayloadV1(t *testing.T) { } } +func TestShardingExecutePayloadV1(t *testing.T) { + genesis, headers, _, _, postBlocks := generatePreMergeChain(10, 2) + n, lesService := startLesService(t, genesis, headers) + lesService.Merger().ReachTTD() + defer n.Close() + + api := NewConsensusAPI(lesService) + fcState := engine.ForkchoiceStateV1{ + HeadBlockHash: postBlocks[0].Hash(), + SafeBlockHash: common.Hash{}, + FinalizedBlockHash: common.Hash{}, + } + if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { + t.Errorf("Failed to update head %v", err) + } + block := postBlocks[0] + + fakeBlock := types.NewBlock(&types.Header{ + ParentHash: block.ParentHash(), + UncleHash: crypto.Keccak256Hash(nil), + Coinbase: block.Coinbase(), + Root: block.Root(), + TxHash: crypto.Keccak256Hash(nil), + ReceiptHash: crypto.Keccak256Hash(nil), + Bloom: block.Bloom(), + Difficulty: big.NewInt(0), + Number: block.Number(), + GasLimit: block.GasLimit(), + GasUsed: block.GasUsed(), + Time: block.Time(), + Extra: block.Extra(), + MixDigest: block.MixDigest(), + Nonce: types.BlockNonce{}, + BaseFee: block.BaseFee(), + ExcessDataGas: block.ExcessDataGas(), + }, nil, nil, nil, trie.NewStackTrie(nil)) + + _, err := api.ExecutePayloadV1(engine.ExecutableData{ + ParentHash: fakeBlock.ParentHash(), + FeeRecipient: fakeBlock.Coinbase(), + StateRoot: fakeBlock.Root(), + ReceiptsRoot: fakeBlock.ReceiptHash(), + LogsBloom: fakeBlock.Bloom().Bytes(), + Random: fakeBlock.MixDigest(), + Number: fakeBlock.NumberU64(), + GasLimit: fakeBlock.GasLimit(), + GasUsed: fakeBlock.GasUsed(), + Timestamp: fakeBlock.Time(), + ExtraData: fakeBlock.Extra(), + BaseFeePerGas: fakeBlock.BaseFee(), + ExcessDataGas: fakeBlock.ExcessDataGas(), + BlockHash: fakeBlock.Hash(), + Transactions: encodeTransactions(fakeBlock.Transactions()), + }) + if err != nil { + t.Errorf("Failed to execute payload %v", err) + } + headHeader := api.les.BlockChain().CurrentHeader() + if headHeader.Number.Uint64() != fakeBlock.NumberU64()-1 { + t.Fatal("Unexpected chain head update") + } + fcState = engine.ForkchoiceStateV1{ + HeadBlockHash: fakeBlock.Hash(), + SafeBlockHash: common.Hash{}, + FinalizedBlockHash: common.Hash{}, + } + if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { + t.Fatal("Failed to update head") + } + headHeader = api.les.BlockChain().CurrentHeader() + if headHeader.Number.Uint64() != fakeBlock.NumberU64() { + t.Fatal("Failed to update chain head") + } +} + func TestEth2DeepReorg(t *testing.T) { // TODO (MariusVanDerWijden) TestEth2DeepReorg is currently broken, because it tries to reorg // before the totalTerminalDifficulty threshold diff --git a/les/downloader/queue_test.go b/les/downloader/queue_test.go index 44b2208595f..6bffa90219a 100644 --- a/les/downloader/queue_test.go +++ b/les/downloader/queue_test.go @@ -41,7 +41,7 @@ func makeChain(n int, seed byte, parent *types.Block, empty bool) ([]*types.Bloc block.SetCoinbase(common.Address{seed}) // Add one tx to every secondblock if !empty && i%2 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/les/downloader/testchain_test.go b/les/downloader/testchain_test.go index 400eec94e7c..dff0844cb89 100644 --- a/les/downloader/testchain_test.go +++ b/les/downloader/testchain_test.go @@ -131,7 +131,7 @@ func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool) } // Include transactions to the miner to make blocks more interesting. if parent == tc.genesis && i%22 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/les/fetcher/block_fetcher.go b/les/fetcher/block_fetcher.go index c76f20ced31..085ecb2d665 100644 --- a/les/fetcher/block_fetcher.go +++ b/les/fetcher/block_fetcher.go @@ -548,7 +548,7 @@ func (f *BlockFetcher) loop() { announce.time = task.time // If the block is empty (header only), short circuit into the final import queue - if header.TxHash == types.EmptyRootHash && header.UncleHash == types.EmptyUncleHash { + if header.TxHash == types.EmptyTxsHash && header.UncleHash == types.EmptyUncleHash { log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash()) block := types.NewBlockWithHeader(header) diff --git a/les/fetcher/block_fetcher_test.go b/les/fetcher/block_fetcher_test.go index caff7a3b355..95ca65916d0 100644 --- a/les/fetcher/block_fetcher_test.go +++ b/les/fetcher/block_fetcher_test.go @@ -57,7 +57,7 @@ func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common // If the block number is multiple of 3, send a bonus transaction to the miner if parent == genesis && i%3 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/les/handler_test.go b/les/handler_test.go index b7be29b862a..c3970925961 100644 --- a/les/handler_test.go +++ b/les/handler_test.go @@ -121,20 +121,20 @@ func testGetBlockHeaders(t *testing.T, protocol int) { &GetBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1}, []common.Hash{bc.GetBlockByNumber(0).Hash()}, }, { - &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64()}, Amount: 1}, + &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().Number.Uint64()}, Amount: 1}, []common.Hash{bc.CurrentBlock().Hash()}, }, // Ensure protocol limits are honored //{ - // &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, + // &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().Number.Uint64()() - 1}, Amount: limit + 10, Reverse: true}, // []common.Hash{}, //}, // Check that requesting more than available is handled gracefully { - &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, + &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3}, []common.Hash{ - bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(), - bc.GetBlockByNumber(bc.CurrentBlock().NumberU64()).Hash(), + bc.GetBlockByNumber(bc.CurrentBlock().Number.Uint64() - 4).Hash(), + bc.GetBlockByNumber(bc.CurrentBlock().Number.Uint64()).Hash(), }, }, { &GetBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, @@ -145,10 +145,10 @@ func testGetBlockHeaders(t *testing.T, protocol int) { }, // Check that requesting more than available is handled gracefully, even if mid skip { - &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, + &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3}, []common.Hash{ - bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(), - bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1).Hash(), + bc.GetBlockByNumber(bc.CurrentBlock().Number.Uint64() - 4).Hash(), + bc.GetBlockByNumber(bc.CurrentBlock().Number.Uint64() - 1).Hash(), }, }, { &GetBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, @@ -162,7 +162,7 @@ func testGetBlockHeaders(t *testing.T, protocol int) { &GetBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, []common.Hash{}, }, { - &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() + 1}, Amount: 1}, + &GetBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().Number.Uint64() + 1}, Amount: 1}, []common.Hash{}, }, } @@ -240,7 +240,7 @@ func testGetBlockBodies(t *testing.T, protocol int) { for j := 0; j < tt.random; j++ { for { - num := rand.Int63n(int64(bc.CurrentBlock().NumberU64())) + num := rand.Int63n(int64(bc.CurrentBlock().Number.Uint64())) if !seen[num] { seen[num] = true @@ -292,7 +292,7 @@ func testGetCode(t *testing.T, protocol int) { var codereqs []*CodeReq var codes [][]byte - for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { + for i := uint64(0); i <= bc.CurrentBlock().Number.Uint64(); i++ { header := bc.GetHeaderByNumber(i) req := &CodeReq{ BHash: header.Hash(), @@ -367,7 +367,7 @@ func testGetReceipt(t *testing.T, protocol int) { // Collect the hashes to request, and the response to expect var receipts []types.Receipts var hashes []common.Hash - for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { + for i := uint64(0); i <= bc.CurrentBlock().Number.Uint64(); i++ { block := bc.GetBlockByNumber(i) hashes = append(hashes, block.Hash()) @@ -404,7 +404,7 @@ func testGetProofs(t *testing.T, protocol int) { proofsV2 := light.NewNodeSet() accounts := []common.Address{bankAddr, userAddr1, userAddr2, signerAddr, {}} - for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { + for i := uint64(0); i <= bc.CurrentBlock().Number.Uint64(); i++ { header := bc.GetHeaderByNumber(i) trie, _ := trie.New(trie.StateTrieID(header.Root), trie.NewDatabase(server.db)) diff --git a/les/odr_test.go b/les/odr_test.go index e028d35e639..49c6868c647 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -116,12 +116,6 @@ func TestOdrContractCallLes2(t *testing.T) { testOdr(t, 2, 2, true, odrContractC func TestOdrContractCallLes3(t *testing.T) { testOdr(t, 3, 2, true, odrContractCall) } func TestOdrContractCallLes4(t *testing.T) { testOdr(t, 4, 2, true, odrContractCall) } -type callmsg struct { - types.Message -} - -func (callmsg) CheckNonce() bool { return false } - func odrContractCall(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000") @@ -136,14 +130,24 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai from := statedb.GetOrNewStateObject(bankAddr) from.SetBalance(math.MaxBig256) - msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)} + msg := &core.Message{ + From: from.Address(), + To: &testContractAddr, + Value: new(big.Int), + GasLimit: 100000, + GasPrice: big.NewInt(params.InitialBaseFee), + GasFeeCap: big.NewInt(params.InitialBaseFee), + GasTipCap: new(big.Int), + Data: data, + SkipAccountChecks: true, + } - context := core.NewEVMBlockContext(header, bc, nil) + context := core.NewEVMBlockContext(header, nil, bc, nil) txContext := core.NewEVMTxContext(msg) vmenv := vm.NewEVM(context, txContext, statedb, config, vm.Config{NoBaseFee: true}) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) - gp := new(core.GasPool).AddGas(math.MaxUint64) + gp := new(core.GasPool).AddGas(math.MaxUint64).AddDataGas(math.MaxUint64) result, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, result.Return()...) } @@ -151,11 +155,21 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai header := lc.GetHeaderByHash(bhash) state := light.NewState(ctx, header, lc.Odr()) state.SetBalance(bankAddr, math.MaxBig256) - msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)} - context := core.NewEVMBlockContext(header, lc, nil) + msg := &core.Message{ + From: bankAddr, + To: &testContractAddr, + Value: new(big.Int), + GasLimit: 100000, + GasPrice: big.NewInt(params.InitialBaseFee), + GasFeeCap: big.NewInt(params.InitialBaseFee), + GasTipCap: new(big.Int), + Data: data, + SkipAccountChecks: true, + } + context := core.NewEVMBlockContext(header, nil, lc, nil) txContext := core.NewEVMTxContext(msg) vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{NoBaseFee: true}) - gp := new(core.GasPool).AddGas(math.MaxUint64) + gp := new(core.GasPool).AddGas(math.MaxUint64).AddDataGas(math.MaxUint64) result, _ := core.ApplyMessage(vmenv, msg, gp) if state.Error() == nil { res = append(res, result.Return()...) @@ -281,7 +295,7 @@ func testGetTxStatusFromUnindexedPeers(t *testing.T, protocol int) { blockHashes = make(map[common.Hash]common.Hash) // Transaction hash to block hash mappings intraIndex = make(map[common.Hash]uint64) // Transaction intra-index in block ) - for number := uint64(1); number < server.backend.Blockchain().CurrentBlock().NumberU64(); number++ { + for number := uint64(1); number < server.backend.Blockchain().CurrentBlock().Number.Uint64(); number++ { block := server.backend.Blockchain().GetBlockByNumber(number) if block == nil { t.Fatalf("Failed to retrieve block %d", number) diff --git a/les/protocol.go b/les/protocol.go index dced7039e40..d686e6ceb96 100644 --- a/les/protocol.go +++ b/les/protocol.go @@ -131,7 +131,7 @@ type GetHelperTrieProofsPacket struct { // SendTxPacket represents a transaction propagation request type SendTxPacket struct { ReqID uint64 - Txs []*types.Transaction + Txs []*types.NetworkTransaction } // GetTxStatusPacket represents a transaction status query diff --git a/les/server_requests.go b/les/server_requests.go index 3563bf93c63..35d2aa47293 100644 --- a/les/server_requests.go +++ b/les/server_requests.go @@ -348,7 +348,7 @@ func handleGetReceipts(msg Decoder) (serveRequestFn, uint64, uint64, error) { // Retrieve the requested block's receipts, skipping if unknown to us results := bc.GetReceiptsByHash(hash) if results == nil { - if header := bc.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { + if header := bc.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyReceiptsHash { p.bumpInvalid() continue } @@ -523,7 +523,7 @@ func handleSendTx(msg Decoder) (serveRequestFn, uint64, uint64, error) { if backend.AddTxsSync() { addFn = backend.TxPool().AddRemotesSync } - if errs := addFn([]*types.Transaction{tx}); errs[0] != nil { + if errs := addFn([]*types.Transaction{tx.Tx}); errs[0] != nil { stats[i].Error = errs[0].Error() continue } diff --git a/les/state_accessor.go b/les/state_accessor.go index 091ec8871ee..cdf022c46df 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -39,7 +39,7 @@ func (leth *LightEthereum) stateAtBlock(ctx context.Context, block *types.Block, } // stateAtTransaction returns the execution environment of a certain transaction. -func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { // Short circuit if it's genesis block. if block.NumberU64() == 0 { return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") @@ -57,19 +57,19 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types. return nil, vm.BlockContext{}, statedb, release, nil } // Recompute transactions up to the target index. - signer := types.MakeSigner(leth.blockchain.Config(), block.Number()) + signer := types.MakeSigner(leth.blockchain.Config(), block.Number(), block.Time()) for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset - msg, _ := tx.AsMessage(signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(block.Header(), leth.blockchain, nil) + context := core.NewEVMBlockContext(block.Header(), parent.Header().ExcessDataGas, leth.blockchain, nil) statedb.SetTxContext(tx.Hash(), idx) if idx == txIndex { return msg, context, statedb, release, nil } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{}) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { + if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()).AddDataGas(tx.DataGas().Uint64())); err != nil { return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } // Ensure any modifications are committed to the state diff --git a/les/txrelay.go b/les/txrelay.go index 40a51fb76f8..4a4ec37dee9 100644 --- a/les/txrelay.go +++ b/les/txrelay.go @@ -114,8 +114,11 @@ func (ltrx *lesTxRelay) send(txs types.Transactions, count int) { } for p, list := range sendTo { + ll := make(types.NetworkTransactions, len(list)) + for i := range list { + ll[i] = types.NewNetworkTransaction(list[i]) + } pp := p - ll := list enc, _ := rlp.EncodeToBytes(ll) reqID := rand.Uint64() diff --git a/les/utils/limiter_test.go b/les/utils/limiter_test.go index 3fbdc60d7c5..c031b21de58 100644 --- a/les/utils/limiter_test.go +++ b/les/utils/limiter_test.go @@ -17,7 +17,7 @@ package utils import ( - "math/rand" + "crypto/rand" "testing" "github.com/ethereum/go-ethereum/p2p/enode" diff --git a/les/vflux/client/fillset_test.go b/les/vflux/client/fillset_test.go index ddb12a82f9b..652dcf9f62b 100644 --- a/les/vflux/client/fillset_test.go +++ b/les/vflux/client/fillset_test.go @@ -17,7 +17,7 @@ package client import ( - "math/rand" + "crypto/rand" "testing" "time" diff --git a/les/vflux/server/clientpool_test.go b/les/vflux/server/clientpool_test.go index 790ec513607..f75c70afcab 100644 --- a/les/vflux/server/clientpool_test.go +++ b/les/vflux/server/clientpool_test.go @@ -135,7 +135,6 @@ func alwaysTrueFn() bool { } func testClientPool(t *testing.T, activeLimit, clientCount, paidCount int, randomDisconnect bool) { - rand.Seed(time.Now().UnixNano()) var ( clock mclock.Simulated db = rawdb.NewMemoryDatabase() diff --git a/light/lightchain_test.go b/light/lightchain_test.go index 8600e56345f..d19713dc2f8 100644 --- a/light/lightchain_test.go +++ b/light/lightchain_test.go @@ -253,8 +253,8 @@ func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types. Number: big.NewInt(int64(i + 1)), Difficulty: big.NewInt(int64(difficulty)), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, } if i == 0 { header.ParentHash = genesis.Hash() diff --git a/light/odr_test.go b/light/odr_test.go index 903c7f6f90a..08e6da47c52 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -174,12 +174,6 @@ func odrAccounts(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc func TestOdrContractCallLes2(t *testing.T) { testChainOdr(t, 1, odrContractCall) } -type callmsg struct { - types.Message -} - -func (callmsg) CheckNonce() bool { return false } - func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc *LightChain, bhash common.Hash) ([]byte, error) { data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000") config := params.TestChainConfig @@ -205,11 +199,21 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain // Perform read-only call. st.SetBalance(testBankAddress, math.MaxBig256) - msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)} + msg := &core.Message{ + From: testBankAddress, + To: &testContractAddr, + Value: new(big.Int), + GasLimit: 1000000, + GasPrice: big.NewInt(params.InitialBaseFee), + GasFeeCap: big.NewInt(params.InitialBaseFee), + GasTipCap: new(big.Int), + Data: data, + SkipAccountChecks: true, + } txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(header, chain, nil) + context := core.NewEVMBlockContext(header, nil, chain, nil) vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{NoBaseFee: true}) - gp := new(core.GasPool).AddGas(math.MaxUint64) + gp := new(core.GasPool).AddGas(math.MaxUint64).AddDataGas(math.MaxUint64) result, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, result.Return()...) if st.Error() != nil { diff --git a/light/odr_util.go b/light/odr_util.go index c49af3a1fb7..1325beae31a 100644 --- a/light/odr_util.go +++ b/light/odr_util.go @@ -175,7 +175,15 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num genesis := rawdb.ReadCanonicalHash(odr.Database(), 0) config := rawdb.ReadChainConfig(odr.Database(), genesis) - if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Transactions()); err != nil { + var excessDataGas *big.Int + if number > 0 { + parentHeader, err := GetHeaderByNumber(ctx, odr, number-1) + if err != nil { + return nil, err + } + excessDataGas = parentHeader.ExcessDataGas + } + if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), excessDataGas, block.Transactions()); err != nil { return nil, err } rawdb.WriteReceipts(odr.Database(), hash, number, receipts) diff --git a/light/txpool.go b/light/txpool.go index e59dc3e7743..56e78b40f25 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -380,7 +380,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error } // Transactor should have enough funds to cover the costs - // cost == V + GP * GL + // cost == V + GP * GL + DGP * DG if b := currentState.GetBalance(from); b.Cmp(tx.Cost()) < 0 { return core.ErrInsufficientFunds } diff --git a/log/logger.go b/log/logger.go index 1549e328548..4e471a22da9 100644 --- a/log/logger.go +++ b/log/logger.go @@ -116,12 +116,58 @@ type Logger interface { // SetHandler updates the logger to write records to the specified handler. SetHandler(h Handler) - // Log a message at the given level with context key/value pairs + // Log a message at the trace level with context key/value pairs + // + // # Usage + // + // log.Trace("msg") + // log.Trace("msg", "key1", val1) + // log.Trace("msg", "key1", val1, "key2", val2) Trace(msg string, ctx ...interface{}) + + // Log a message at the debug level with context key/value pairs + // + // # Usage Examples + // + // log.Debug("msg") + // log.Debug("msg", "key1", val1) + // log.Debug("msg", "key1", val1, "key2", val2) Debug(msg string, ctx ...interface{}) + + // Log a message at the info level with context key/value pairs + // + // # Usage Examples + // + // log.Info("msg") + // log.Info("msg", "key1", val1) + // log.Info("msg", "key1", val1, "key2", val2) Info(msg string, ctx ...interface{}) + + // Log a message at the warn level with context key/value pairs + // + // # Usage Examples + // + // log.Warn("msg") + // log.Warn("msg", "key1", val1) + // log.Warn("msg", "key1", val1, "key2", val2) Warn(msg string, ctx ...interface{}) + + // Log a message at the error level with context key/value pairs + // + // # Usage Examples + // + // log.Error("msg") + // log.Error("msg", "key1", val1) + // log.Error("msg", "key1", val1, "key2", val2) Error(msg string, ctx ...interface{}) + + // Log a message at the crit level with context key/value pairs, and then exit. + // + // # Usage Examples + // + // log.Crit("msg") + // log.Crit("msg", "key1", val1) + // log.Crit("msg", "key1", val1, "key2", val2) Crit(msg string, ctx ...interface{}) } diff --git a/log/root.go b/log/root.go index 9fb4c5ae0b1..5a41723c3ee 100644 --- a/log/root.go +++ b/log/root.go @@ -30,31 +30,79 @@ func Root() Logger { // runtime.Caller(2) always refers to the call site in client code. // Trace is a convenient alias for Root().Trace +// +// Log a message at the trace level with context key/value pairs +// +// # Usage +// +// log.Trace("msg") +// log.Trace("msg", "key1", val1) +// log.Trace("msg", "key1", val1, "key2", val2) func Trace(msg string, ctx ...interface{}) { root.write(msg, LvlTrace, ctx, skipLevel) } // Debug is a convenient alias for Root().Debug +// +// Log a message at the debug level with context key/value pairs +// +// # Usage Examples +// +// log.Debug("msg") +// log.Debug("msg", "key1", val1) +// log.Debug("msg", "key1", val1, "key2", val2) func Debug(msg string, ctx ...interface{}) { root.write(msg, LvlDebug, ctx, skipLevel) } // Info is a convenient alias for Root().Info +// +// Log a message at the info level with context key/value pairs +// +// # Usage Examples +// +// log.Info("msg") +// log.Info("msg", "key1", val1) +// log.Info("msg", "key1", val1, "key2", val2) func Info(msg string, ctx ...interface{}) { root.write(msg, LvlInfo, ctx, skipLevel) } // Warn is a convenient alias for Root().Warn +// +// Log a message at the warn level with context key/value pairs +// +// # Usage Examples +// +// log.Warn("msg") +// log.Warn("msg", "key1", val1) +// log.Warn("msg", "key1", val1, "key2", val2) func Warn(msg string, ctx ...interface{}) { root.write(msg, LvlWarn, ctx, skipLevel) } // Error is a convenient alias for Root().Error +// +// Log a message at the error level with context key/value pairs +// +// # Usage Examples +// +// log.Error("msg") +// log.Error("msg", "key1", val1) +// log.Error("msg", "key1", val1, "key2", val2) func Error(msg string, ctx ...interface{}) { root.write(msg, LvlError, ctx, skipLevel) } // Crit is a convenient alias for Root().Crit +// +// Log a message at the crit level with context key/value pairs, and then exit. +// +// # Usage Examples +// +// log.Crit("msg") +// log.Crit("msg", "key1", val1) +// log.Crit("msg", "key1", val1, "key2", val2) func Crit(msg string, ctx ...interface{}) { root.write(msg, LvlCrit, ctx, skipLevel) os.Exit(1) diff --git a/metrics/cpu.go b/metrics/cpu.go index 72ece16e076..3a49cd42493 100644 --- a/metrics/cpu.go +++ b/metrics/cpu.go @@ -17,8 +17,9 @@ package metrics // CPUStats is the system and process CPU stats. +// All values are in seconds. type CPUStats struct { - GlobalTime int64 // Time spent by the CPU working on all processes - GlobalWait int64 // Time spent by waiting on disk for all processes - LocalTime int64 // Time spent by the CPU working on this process + GlobalTime float64 // Time spent by the CPU working on all processes + GlobalWait float64 // Time spent by waiting on disk for all processes + LocalTime float64 // Time spent by the CPU working on this process } diff --git a/metrics/cpu_enabled.go b/metrics/cpu_enabled.go index 533d40b85a5..2359028a212 100644 --- a/metrics/cpu_enabled.go +++ b/metrics/cpu_enabled.go @@ -38,7 +38,7 @@ func ReadCPUStats(stats *CPUStats) { } // requesting all cpu times will always return an array with only one time stats entry timeStat := timeStats[0] - stats.GlobalTime = int64((timeStat.User + timeStat.Nice + timeStat.System) * cpu.ClocksPerSec) - stats.GlobalWait = int64((timeStat.Iowait) * cpu.ClocksPerSec) + stats.GlobalTime = timeStat.User + timeStat.Nice + timeStat.System + stats.GlobalWait = timeStat.Iowait stats.LocalTime = getProcessCPUTime() } diff --git a/metrics/cputime_nop.go b/metrics/cputime_nop.go index 0188735a783..465d88c4d23 100644 --- a/metrics/cputime_nop.go +++ b/metrics/cputime_nop.go @@ -21,6 +21,6 @@ package metrics // getProcessCPUTime returns 0 on Windows as there is no system call to resolve // the actual process' CPU time. -func getProcessCPUTime() int64 { +func getProcessCPUTime() float64 { return 0 } diff --git a/metrics/cputime_unix.go b/metrics/cputime_unix.go index 3c56a75d007..ad4f812fd28 100644 --- a/metrics/cputime_unix.go +++ b/metrics/cputime_unix.go @@ -26,11 +26,11 @@ import ( ) // getProcessCPUTime retrieves the process' CPU time since program startup. -func getProcessCPUTime() int64 { +func getProcessCPUTime() float64 { var usage syscall.Rusage if err := syscall.Getrusage(syscall.RUSAGE_SELF, &usage); err != nil { log.Warn("Failed to retrieve CPU time", "err", err) return 0 } - return int64(usage.Utime.Sec+usage.Stime.Sec)*100 + int64(usage.Utime.Usec+usage.Stime.Usec)/10000 //nolint:unconvert + return float64(usage.Utime.Sec+usage.Stime.Sec) + float64(usage.Utime.Usec+usage.Stime.Usec)/1000000 //nolint:unconvert } diff --git a/metrics/metrics.go b/metrics/metrics.go index 2edf8e35f15..ff7196b5649 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -127,8 +127,6 @@ func CollectProcessMetrics(refresh time.Duration) { return } - refreshFreq := int64(refresh / time.Second) - // Create the various data collectors var ( cpustats = make([]CPUStats, 2) @@ -163,14 +161,25 @@ func CollectProcessMetrics(refresh time.Duration) { diskWriteBytesCounter = GetOrRegisterCounter("system/disk/writebytes", DefaultRegistry) ) + var lastCollectTime time.Time + // Iterate loading the different stats and updating the meters. now, prev := 0, 1 for ; ; now, prev = prev, now { - // CPU + // Gather CPU times. ReadCPUStats(&cpustats[now]) - cpuSysLoad.Update((cpustats[now].GlobalTime - cpustats[prev].GlobalTime) / refreshFreq) - cpuSysWait.Update((cpustats[now].GlobalWait - cpustats[prev].GlobalWait) / refreshFreq) - cpuProcLoad.Update((cpustats[now].LocalTime - cpustats[prev].LocalTime) / refreshFreq) + collectTime := time.Now() + secondsSinceLastCollect := collectTime.Sub(lastCollectTime).Seconds() + lastCollectTime = collectTime + if secondsSinceLastCollect > 0 { + sysLoad := (cpustats[now].GlobalTime - cpustats[prev].GlobalTime) / secondsSinceLastCollect + sysWait := (cpustats[now].GlobalWait - cpustats[prev].GlobalWait) / secondsSinceLastCollect + procLoad := (cpustats[now].LocalTime - cpustats[prev].LocalTime) / secondsSinceLastCollect + // Convert to integer percentage. + cpuSysLoad.Update(int64(sysLoad * 100)) + cpuSysWait.Update(int64(sysWait * 100)) + cpuProcLoad.Update(int64(procLoad * 100)) + } // Threads cpuThreads.Update(int64(threadCreateProfile.Count())) diff --git a/metrics/sample.go b/metrics/sample.go index fa2bfb274e3..afcaa211842 100644 --- a/metrics/sample.go +++ b/metrics/sample.go @@ -41,6 +41,7 @@ type ExpDecaySample struct { reservoirSize int t0, t1 time.Time values *expDecaySampleHeap + rand *rand.Rand } // NewExpDecaySample constructs a new exponentially-decaying sample with the @@ -59,6 +60,12 @@ func NewExpDecaySample(reservoirSize int, alpha float64) Sample { return s } +// SetRand sets the random source (useful in tests) +func (s *ExpDecaySample) SetRand(prng *rand.Rand) Sample { + s.rand = prng + return s +} + // Clear clears all samples. func (s *ExpDecaySample) Clear() { s.mutex.Lock() @@ -168,8 +175,14 @@ func (s *ExpDecaySample) update(t time.Time, v int64) { if s.values.Size() == s.reservoirSize { s.values.Pop() } + var f64 float64 + if s.rand != nil { + f64 = s.rand.Float64() + } else { + f64 = rand.Float64() + } s.values.Push(expDecaySample{ - k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(), + k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / f64, v: v, }) if t.After(s.t1) { @@ -402,6 +415,7 @@ type UniformSample struct { mutex sync.Mutex reservoirSize int values []int64 + rand *rand.Rand } // NewUniformSample constructs a new uniform sample with the given reservoir @@ -416,6 +430,12 @@ func NewUniformSample(reservoirSize int) Sample { } } +// SetRand sets the random source (useful in tests) +func (s *UniformSample) SetRand(prng *rand.Rand) Sample { + s.rand = prng + return s +} + // Clear clears all samples. func (s *UniformSample) Clear() { s.mutex.Lock() @@ -511,7 +531,12 @@ func (s *UniformSample) Update(v int64) { if len(s.values) < s.reservoirSize { s.values = append(s.values, v) } else { - r := rand.Int63n(s.count) + var r int64 + if s.rand != nil { + r = s.rand.Int63n(s.count) + } else { + r = rand.Int63n(s.count) + } if r < int64(len(s.values)) { s.values[int(r)] = v } diff --git a/metrics/sample_test.go b/metrics/sample_test.go index c9168d3e820..3ae128d56f6 100644 --- a/metrics/sample_test.go +++ b/metrics/sample_test.go @@ -80,7 +80,6 @@ func BenchmarkUniformSample1028(b *testing.B) { } func TestExpDecaySample10(t *testing.T) { - rand.Seed(1) s := NewExpDecaySample(100, 0.99) for i := 0; i < 10; i++ { s.Update(int64(i)) @@ -102,7 +101,6 @@ func TestExpDecaySample10(t *testing.T) { } func TestExpDecaySample100(t *testing.T) { - rand.Seed(1) s := NewExpDecaySample(1000, 0.01) for i := 0; i < 100; i++ { s.Update(int64(i)) @@ -124,7 +122,6 @@ func TestExpDecaySample100(t *testing.T) { } func TestExpDecaySample1000(t *testing.T) { - rand.Seed(1) s := NewExpDecaySample(100, 0.99) for i := 0; i < 1000; i++ { s.Update(int64(i)) @@ -150,7 +147,6 @@ func TestExpDecaySample1000(t *testing.T) { // The priority becomes +Inf quickly after starting if this is done, // effectively freezing the set of samples until a rescale step happens. func TestExpDecaySampleNanosecondRegression(t *testing.T) { - rand.Seed(1) s := NewExpDecaySample(100, 0.99) for i := 0; i < 100; i++ { s.Update(10) @@ -183,8 +179,7 @@ func TestExpDecaySampleRescale(t *testing.T) { func TestExpDecaySampleSnapshot(t *testing.T) { now := time.Now() - rand.Seed(1) - s := NewExpDecaySample(100, 0.99) + s := NewExpDecaySample(100, 0.99).(*ExpDecaySample).SetRand(rand.New(rand.NewSource(1))) for i := 1; i <= 10000; i++ { s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) } @@ -195,8 +190,7 @@ func TestExpDecaySampleSnapshot(t *testing.T) { func TestExpDecaySampleStatistics(t *testing.T) { now := time.Now() - rand.Seed(1) - s := NewExpDecaySample(100, 0.99) + s := NewExpDecaySample(100, 0.99).(*ExpDecaySample).SetRand(rand.New(rand.NewSource(1))) for i := 1; i <= 10000; i++ { s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) } @@ -204,7 +198,6 @@ func TestExpDecaySampleStatistics(t *testing.T) { } func TestUniformSample(t *testing.T) { - rand.Seed(1) s := NewUniformSample(100) for i := 0; i < 1000; i++ { s.Update(int64(i)) @@ -226,7 +219,6 @@ func TestUniformSample(t *testing.T) { } func TestUniformSampleIncludesTail(t *testing.T) { - rand.Seed(1) s := NewUniformSample(100) max := 100 for i := 0; i < max; i++ { @@ -244,7 +236,7 @@ func TestUniformSampleIncludesTail(t *testing.T) { } func TestUniformSampleSnapshot(t *testing.T) { - s := NewUniformSample(100) + s := NewUniformSample(100).(*UniformSample).SetRand(rand.New(rand.NewSource(1))) for i := 1; i <= 10000; i++ { s.Update(int64(i)) } @@ -254,8 +246,7 @@ func TestUniformSampleSnapshot(t *testing.T) { } func TestUniformSampleStatistics(t *testing.T) { - rand.Seed(1) - s := NewUniformSample(100) + s := NewUniformSample(100).(*UniformSample).SetRand(rand.New(rand.NewSource(1))) for i := 1; i <= 10000; i++ { s.Update(int64(i)) } diff --git a/miner/miner_test.go b/miner/miner_test.go index 2e7682acd33..6bf3edae5db 100644 --- a/miner/miner_test.go +++ b/miner/miner_test.go @@ -19,6 +19,7 @@ package miner import ( "errors" + "math/big" "testing" "time" @@ -65,14 +66,15 @@ type testBlockChain struct { chainHeadFeed *event.Feed } -func (bc *testBlockChain) CurrentBlock() *types.Block { - return types.NewBlock(&types.Header{ +func (bc *testBlockChain) CurrentBlock() *types.Header { + return &types.Header{ + Number: new(big.Int), GasLimit: bc.gasLimit, - }, nil, nil, nil, trie.NewStackTrie(nil)) + } } func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { - return bc.CurrentBlock() + return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil)) } func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { diff --git a/miner/payload_building.go b/miner/payload_building.go index f84d908e86d..c12a41aafd2 100644 --- a/miner/payload_building.go +++ b/miner/payload_building.go @@ -125,6 +125,31 @@ func (payload *Payload) Resolve() *engine.ExecutionPayloadEnvelope { return engine.BlockToExecutableData(payload.empty, big.NewInt(0)) } +// ResolveWithBlobsBundle returns the latest built payload, including its blobs bundle, and also +// terminates the background thread for updating payload. It's safe to be called multiple times. +func (payload *Payload) ResolveWithBlobsBundle() (*engine.ExecutionPayloadEnvelope, error) { + payload.lock.Lock() + defer payload.lock.Unlock() + + var err error + select { + case <-payload.stop: + default: + close(payload.stop) + } + if payload.full != nil { + pl := engine.BlockToExecutableData(payload.full, payload.fullFees) + pl.BlobsBundle, err = engine.BlockToBlobData(payload.full) + if err != nil { + return nil, err + } + return pl, nil + } + pl := engine.BlockToExecutableData(payload.empty, big.NewInt(0)) + pl.BlobsBundle, err = engine.BlockToBlobData(payload.empty) + return pl, err +} + // ResolveEmpty is basically identical to Resolve, but it expects empty block only. // It's only used in tests. func (payload *Payload) ResolveEmpty() *engine.ExecutionPayloadEnvelope { diff --git a/miner/stress/1559/main.go b/miner/stress/1559/main.go index abc24f4a369..c27875000d8 100644 --- a/miner/stress/1559/main.go +++ b/miner/stress/1559/main.go @@ -19,6 +19,7 @@ package main import ( "crypto/ecdsa" + crand "crypto/rand" "math/big" "math/rand" "os" @@ -162,7 +163,7 @@ func makeTransaction(nonce uint64, privKey *ecdsa.PrivateKey, signer types.Signe // Feecap and feetip are limited to 32 bytes. Offer a sightly // larger buffer for creating both valid and invalid transactions. var buf = make([]byte, 32+5) - rand.Read(buf) + crand.Read(buf) gasTipCap := new(big.Int).SetBytes(buf) // If the given base fee is nil(the 1559 is still not available), @@ -173,7 +174,7 @@ func makeTransaction(nonce uint64, privKey *ecdsa.PrivateKey, signer types.Signe // Generate the feecap, 75% valid feecap and 25% unguaranteed. var gasFeeCap *big.Int if rand.Intn(4) == 0 { - rand.Read(buf) + crand.Read(buf) gasFeeCap = new(big.Int).SetBytes(buf) } else { gasFeeCap = new(big.Int).Add(baseFee, gasTipCap) diff --git a/miner/worker.go b/miner/worker.go index 49204f71a07..9c7d030e71e 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -95,10 +95,11 @@ type environment struct { gasPool *core.GasPool // available gas used to pack transactions coinbase common.Address - header *types.Header - txs []*types.Transaction - receipts []*types.Receipt - uncles map[common.Hash]*types.Header + header *types.Header + excessDataGas *big.Int + txs []*types.Transaction + receipts []*types.Receipt + uncles map[common.Hash]*types.Header } // copy creates a deep copy of environment. @@ -494,7 +495,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) { for { select { case <-w.startCh: - clearPending(w.chain.CurrentBlock().NumberU64()) + clearPending(w.chain.CurrentBlock().Number.Uint64()) timestamp = time.Now().Unix() commit(false, commitInterruptNewHead) @@ -607,12 +608,12 @@ func (w *worker) mainLoop() { case <-cleanTicker.C: chainHead := w.chain.CurrentBlock() for hash, uncle := range w.localUncles { - if uncle.NumberU64()+staleThreshold <= chainHead.NumberU64() { + if uncle.NumberU64()+staleThreshold <= chainHead.Number.Uint64() { delete(w.localUncles, hash) } } for hash, uncle := range w.remoteUncles { - if uncle.NumberU64()+staleThreshold <= chainHead.NumberU64() { + if uncle.NumberU64()+staleThreshold <= chainHead.Number.Uint64() { delete(w.remoteUncles, hash) } } @@ -790,10 +791,10 @@ func (w *worker) resultLoop() { } // makeEnv creates a new environment for the sealing block. -func (w *worker) makeEnv(parent *types.Block, header *types.Header, coinbase common.Address) (*environment, error) { +func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address) (*environment, error) { // Retrieve the parent state to execute on top and start a prefetcher for // the miner to speed block sealing up a bit. - state, err := w.chain.StateAt(parent.Root()) + state, err := w.chain.StateAt(parent.Root) if err != nil { return nil, err } @@ -801,7 +802,7 @@ func (w *worker) makeEnv(parent *types.Block, header *types.Header, coinbase com // Note the passed coinbase may be different with header.Coinbase. env := &environment{ - signer: types.MakeSigner(w.chainConfig, header.Number), + signer: types.MakeSigner(w.chainConfig, header.Number, header.Time), state: state, coinbase: coinbase, ancestors: mapset.NewSet[common.Hash](), @@ -819,6 +820,15 @@ func (w *worker) makeEnv(parent *types.Block, header *types.Header, coinbase com } // Keep track of transactions which return errors so they can be removed env.tcount = 0 + + // Initialize the prestate excess_data_gas field used during state transition + if w.chainConfig.IsCancun(header.Time) { + // TODO(EIP-4844): Unit test this + env.excessDataGas = new(big.Int) + if parent.ExcessDataGas != nil { + env.excessDataGas.Set(parent.ExcessDataGas) + } + } return env, nil } @@ -861,11 +871,14 @@ func (w *worker) updateSnapshot(env *environment) { } func (w *worker) commitTransaction(env *environment, tx *types.Transaction) ([]*types.Log, error) { - snap := env.state.Snapshot() - - receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig()) + var ( + snap = env.state.Snapshot() + gp = env.gasPool.Gas() + ) + receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, env.excessDataGas, tx, &env.header.GasUsed, *w.chain.GetVMConfig()) if err != nil { env.state.RevertToSnapshot(snap) + env.gasPool.SetGas(gp) return nil, err } env.txs = append(env.txs, tx) @@ -877,7 +890,7 @@ func (w *worker) commitTransaction(env *environment, tx *types.Transaction) ([]* func (w *worker) commitTransactions(env *environment, txs *types.TransactionsByPriceAndNonce, interrupt *int32) error { gasLimit := env.header.GasLimit if env.gasPool == nil { - env.gasPool = new(core.GasPool).AddGas(gasLimit) + env.gasPool = new(core.GasPool).AddGas(gasLimit).AddDataGas(params.MaxDataGasPerBlock) } var coalescedLogs []*types.Log @@ -941,6 +954,11 @@ func (w *worker) commitTransactions(env *environment, txs *types.TransactionsByP log.Trace("Skipping unsupported transaction type", "sender", from, "type", tx.Type()) txs.Pop() + case errors.Is(err, core.ErrDataGasLimitReached): + // Shift, as the next tx from the account may not contain blobs + log.Trace("Skipping blob transaction. Reached max number of blobs in current context", "sender", from, "numBlobs", len(tx.DataHashes())) + txs.Shift() + default: // Strange error, discard the transaction and get the next in line (note, the // nonce-too-high clause will prevent us from executing in vain). @@ -988,25 +1006,26 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { // Find the parent block for sealing task parent := w.chain.CurrentBlock() if genParams.parentHash != (common.Hash{}) { - parent = w.chain.GetBlockByHash(genParams.parentHash) - } - if parent == nil { - return nil, fmt.Errorf("missing parent") + block := w.chain.GetBlockByHash(genParams.parentHash) + if block == nil { + return nil, fmt.Errorf("missing parent") + } + parent = block.Header() } // Sanity check the timestamp correctness, recap the timestamp // to parent+1 if the mutation is allowed. timestamp := genParams.timestamp - if parent.Time() >= timestamp { + if parent.Time >= timestamp { if genParams.forceTime { - return nil, fmt.Errorf("invalid timestamp, parent %d given %d", parent.Time(), timestamp) + return nil, fmt.Errorf("invalid timestamp, parent %d given %d", parent.Time, timestamp) } - timestamp = parent.Time() + 1 + timestamp = parent.Time + 1 } // Construct the sealing block header. header := &types.Header{ ParentHash: parent.Hash(), - Number: new(big.Int).Add(parent.Number(), common.Big1), - GasLimit: core.CalcGasLimit(parent.GasLimit(), w.config.GasCeil), + Number: new(big.Int).Add(parent.Number, common.Big1), + GasLimit: core.CalcGasLimit(parent.GasLimit, w.config.GasCeil), Time: timestamp, Coinbase: genParams.coinbase, } @@ -1020,9 +1039,9 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { } // Set baseFee and GasLimit if we are on an EIP-1559 chain if w.chainConfig.IsLondon(header.Number) { - header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent.Header()) - if !w.chainConfig.IsLondon(parent.Number()) { - parentGasLimit := parent.GasLimit() * w.chainConfig.ElasticityMultiplier() + header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent) + if !w.chainConfig.IsLondon(parent.Number) { + parentGasLimit := parent.GasLimit * w.chainConfig.ElasticityMultiplier() header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil) } } diff --git a/miner/worker_test.go b/miner/worker_test.go index a3f46db17cc..697ac50c92d 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -17,9 +17,9 @@ package miner import ( + "crypto/rand" "errors" "math/big" - "math/rand" "sync/atomic" "testing" "time" @@ -105,8 +105,6 @@ func init() { GasPrice: big.NewInt(params.InitialBaseFee), }) newTxs = append(newTxs, tx2) - - rand.Seed(time.Now().UnixNano()) } // testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing. @@ -131,6 +129,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine return crypto.Sign(crypto.Keccak256(data), testBankKey) }) case *ethash.Ethash: + case consensus.Engine: default: t.Fatalf("unexpected consensus engine type: %T", engine) } @@ -149,7 +148,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine if _, err := chain.InsertChain(blocks); err != nil { t.Fatalf("failed to insert origin chain: %v", err) } - parent := chain.GetBlockByHash(chain.CurrentBlock().ParentHash()) + parent := chain.GetBlockByHash(chain.CurrentBlock().ParentHash) blocks, _ = core.GenerateChain(chainConfig, parent, engine, genDb, 1, func(i int, gen *core.BlockGen) { gen.SetCoinbase(testUserAddress) }) @@ -178,10 +177,10 @@ func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base func (b *testWorkerBackend) newRandomUncle() *types.Block { var parent *types.Block cur := b.chain.CurrentBlock() - if cur.NumberU64() == 0 { + if cur.Number.Uint64() == 0 { parent = b.chain.Genesis() } else { - parent = b.chain.GetBlockByHash(b.chain.CurrentBlock().ParentHash()) + parent = b.chain.GetBlockByHash(b.chain.CurrentBlock().ParentHash) } blocks, _ := core.GenerateChain(b.chain.Config(), parent, b.chain.Engine(), b.db, 1, func(i int, gen *core.BlockGen) { var addr = make([]byte, common.AddressLength) @@ -609,21 +608,21 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co b.chain.CurrentBlock().Hash(), common.HexToAddress("0xdeadbeef"), common.HexToHash("0xcafebabe"), - b.chain.CurrentBlock().NumberU64() + 1, + b.chain.CurrentBlock().Number.Uint64() + 1, false, }, { b.chain.CurrentBlock().Hash(), common.Address{}, common.HexToHash("0xcafebabe"), - b.chain.CurrentBlock().NumberU64() + 1, + b.chain.CurrentBlock().Number.Uint64() + 1, false, }, { b.chain.CurrentBlock().Hash(), common.Address{}, common.Hash{}, - b.chain.CurrentBlock().NumberU64() + 1, + b.chain.CurrentBlock().Number.Uint64() + 1, false, }, { diff --git a/node/node.go b/node/node.go index 112a771ab09..2f89bc1ad27 100644 --- a/node/node.go +++ b/node/node.go @@ -37,7 +37,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rpc" - "github.com/prometheus/tsdb/fileutil" + "github.com/gofrs/flock" ) // Node is a container on which services can be registered. @@ -46,13 +46,13 @@ type Node struct { config *Config accman *accounts.Manager log log.Logger - keyDir string // key store directory - keyDirTemp bool // If true, key directory will be removed by Stop - dirLock fileutil.Releaser // prevents concurrent use of instance directory - stop chan struct{} // Channel to wait for termination notifications - server *p2p.Server // Currently running P2P networking layer - startStopLock sync.Mutex // Start/Stop are protected by an additional lock - state int // Tracks state of node lifecycle + keyDir string // key store directory + keyDirTemp bool // If true, key directory will be removed by Stop + dirLock *flock.Flock // prevents concurrent use of instance directory + stop chan struct{} // Channel to wait for termination notifications + server *p2p.Server // Currently running P2P networking layer + startStopLock sync.Mutex // Start/Stop are protected by an additional lock + state int // Tracks state of node lifecycle lock sync.Mutex lifecycles []Lifecycle // All registered backends, services, and auxiliary services that have a lifecycle @@ -320,20 +320,20 @@ func (n *Node) openDataDir() error { } // Lock the instance directory to prevent concurrent use by another instance as well as // accidental use of the instance directory as a database. - release, _, err := fileutil.Flock(filepath.Join(instdir, "LOCK")) - if err != nil { - return convertFileLockError(err) + n.dirLock = flock.New(filepath.Join(instdir, "LOCK")) + + if locked, err := n.dirLock.TryLock(); err != nil { + return err + } else if !locked { + return ErrDatadirUsed } - n.dirLock = release return nil } func (n *Node) closeDataDir() { // Release instance directory lock. - if n.dirLock != nil { - if err := n.dirLock.Release(); err != nil { - n.log.Error("Can't release datadir lock", "err", err) - } + if n.dirLock != nil && n.dirLock.Locked() { + n.dirLock.Unlock() n.dirLock = nil } } diff --git a/oss-fuzz.sh b/oss-fuzz.sh index 7f454ff307b..745a5ba7c7c 100644 --- a/oss-fuzz.sh +++ b/oss-fuzz.sh @@ -125,7 +125,5 @@ compile_fuzzer tests/fuzzers/snap FuzzSRange fuzz_storage_range compile_fuzzer tests/fuzzers/snap FuzzByteCodes fuzz_byte_codes compile_fuzzer tests/fuzzers/snap FuzzTrieNodes fuzz_trie_nodes -compile_fuzzer tests/fuzzers/modexp Fuzz fuzzModexp - #TODO: move this to tests/fuzzers, if possible compile_fuzzer crypto/blake2b Fuzz fuzzBlake2b diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go index f4fd9b246fd..21f0d75172c 100644 --- a/p2p/discover/v4_udp_test.go +++ b/p2p/discover/v4_udp_test.go @@ -165,7 +165,6 @@ func TestUDPv4_responseTimeouts(t *testing.T) { test := newUDPTest(t) defer test.close() - rand.Seed(time.Now().UnixNano()) randomDuration := func(max time.Duration) time.Duration { return time.Duration(rand.Int63n(int64(max))) } diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go index 53a1c6f7670..38f5b3b652c 100644 --- a/p2p/discover/v5_udp.go +++ b/p2p/discover/v5_udp.go @@ -83,6 +83,7 @@ type UDPv5 struct { callCh chan *callV5 callDoneCh chan *callV5 respTimeoutCh chan *callTimeout + unhandled chan<- ReadPacket // state of dispatch codec codecV5 @@ -156,6 +157,7 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) { callCh: make(chan *callV5), callDoneCh: make(chan *callV5), respTimeoutCh: make(chan *callTimeout), + unhandled: cfg.Unhandled, // state of dispatch codec: v5wire.NewCodec(ln, cfg.PrivateKey, cfg.Clock, cfg.V5ProtocolID), activeCallByNode: make(map[enode.ID]*callV5), @@ -657,6 +659,14 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error { addr := fromAddr.String() fromID, fromNode, packet, err := t.codec.Decode(rawpacket, addr) if err != nil { + if t.unhandled != nil && v5wire.IsInvalidHeader(err) { + // The packet seems unrelated to discv5, send it to the next protocol. + // t.log.Trace("Unhandled discv5 packet", "id", fromID, "addr", addr, "err", err) + up := ReadPacket{Data: make([]byte, len(rawpacket)), Addr: fromAddr} + copy(up.Data, rawpacket) + t.unhandled <- up + return nil + } t.log.Debug("Bad discv5 packet", "id", fromID, "addr", addr, "err", err) return err } diff --git a/p2p/discover/v5wire/encoding.go b/p2p/discover/v5wire/encoding.go index d979ab0f9cd..5108910620e 100644 --- a/p2p/discover/v5wire/encoding.go +++ b/p2p/discover/v5wire/encoding.go @@ -94,6 +94,8 @@ const ( // Should reject packets smaller than minPacketSize. minPacketSize = 63 + maxPacketSize = 1280 + minMessageSize = 48 // this refers to data after static headers randomPacketMsgSize = 20 ) @@ -122,6 +124,13 @@ var ( ErrInvalidReqID = errors.New("request ID larger than 8 bytes") ) +// IsInvalidHeader reports whether 'err' is related to an invalid packet header. When it +// returns false, it is pretty certain that the packet causing the error does not belong +// to discv5. +func IsInvalidHeader(err error) bool { + return err == errTooShort || err == errInvalidHeader || err == errMsgTooShort +} + // Packet sizes. var ( sizeofStaticHeader = binary.Size(StaticHeader{}) @@ -147,6 +156,7 @@ type Codec struct { msgctbuf []byte // message data ciphertext // decoder buffer + decbuf []byte reader bytes.Reader } @@ -158,6 +168,7 @@ func NewCodec(ln *enode.LocalNode, key *ecdsa.PrivateKey, clock mclock.Clock, pr privkey: key, sc: NewSessionCache(1024, clock), protocolID: DefaultProtocolID, + decbuf: make([]byte, maxPacketSize), } if protocolID != nil { c.protocolID = *protocolID @@ -424,10 +435,13 @@ func (c *Codec) encryptMessage(s *session, p Packet, head *Header, headerData [] } // Decode decodes a discovery packet. -func (c *Codec) Decode(input []byte, addr string) (src enode.ID, n *enode.Node, p Packet, err error) { - if len(input) < minPacketSize { +func (c *Codec) Decode(inputData []byte, addr string) (src enode.ID, n *enode.Node, p Packet, err error) { + if len(inputData) < minPacketSize { return enode.ID{}, nil, nil, errTooShort } + // Copy the packet to a tmp buffer to avoid modifying it. + c.decbuf = append(c.decbuf[:0], inputData...) + input := c.decbuf // Unmask the static header. var head Header copy(head.IV[:], input[:sizeofMaskingIV]) diff --git a/p2p/enode/localnode_test.go b/p2p/enode/localnode_test.go index 312df813bba..7f97ad392f2 100644 --- a/p2p/enode/localnode_test.go +++ b/p2p/enode/localnode_test.go @@ -17,7 +17,7 @@ package enode import ( - "math/rand" + "crypto/rand" "net" "testing" diff --git a/p2p/netutil/iptrack_test.go b/p2p/netutil/iptrack_test.go index a9a2998a652..ee3bba861e2 100644 --- a/p2p/netutil/iptrack_test.go +++ b/p2p/netutil/iptrack_test.go @@ -17,8 +17,8 @@ package netutil import ( + crand "crypto/rand" "fmt" - mrand "math/rand" "testing" "time" @@ -123,8 +123,8 @@ func TestIPTrackerForceGC(t *testing.T) { for i := 0; i < 5*max; i++ { e1 := make([]byte, 4) e2 := make([]byte, 4) - mrand.Read(e1) - mrand.Read(e2) + crand.Read(e1) + crand.Read(e2) it.AddStatement(string(e1), string(e2)) it.AddContact(string(e1)) clock.Run(rate) diff --git a/p2p/server.go b/p2p/server.go index 19f7935ffca..610b82d784f 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -1057,7 +1057,7 @@ func (srv *Server) runPeer(p *Peer) { // Broadcast peer drop to external subscribers. This needs to be // after the send to delpeer so subscribers have a consistent view of // the peer set (i.e. Server.Peers() doesn't include the peer when the - // event is received. + // event is received). srv.peerFeed.Send(&PeerEvent{ Type: PeerEventTypeDrop, Peer: p.ID(), diff --git a/params/bootnodes.go b/params/bootnodes.go index 0a995bc3c40..5a29582363e 100644 --- a/params/bootnodes.go +++ b/params/bootnodes.go @@ -22,14 +22,10 @@ import "github.com/ethereum/go-ethereum/common" // the main Ethereum network. var MainnetBootnodes = []string{ // Ethereum Foundation Go Bootnodes - "enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", // bootnode-aws-ap-southeast-1-001 - "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", // bootnode-aws-us-east-1-001 - "enode://8499da03c47d637b20eee24eec3c356c9a2e6148d6fe25ca195c7949ab8ec2c03e3556126b0d7ed644675e78c4318b08691b7b57de10e5f0d40d05b09238fa0a@52.187.207.27:30303", // bootnode-azure-australiaeast-001 - "enode://103858bdb88756c71f15e9b5e09b56dc1be52f0a5021d46301dbbfb7e130029cc9d0d6f73f693bc29b665770fff7da4d34f3c6379fe12721b5d7a0bcb5ca1fc1@191.234.162.198:30303", // bootnode-azure-brazilsouth-001 - "enode://715171f50508aba88aecd1250af392a45a330af91d7b90701c436b618c86aaa1589c9184561907bebbb56439b8f8787bc01f49a7c77276c58c1b09822d75e8e8@52.231.165.108:30303", // bootnode-azure-koreasouth-001 - "enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303", // bootnode-azure-westus-001 - "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", // bootnode-hetzner-hel - "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303", // bootnode-hetzner-fsn + "enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", // bootnode-aws-ap-southeast-1-001 + "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", // bootnode-aws-us-east-1-001 + "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", // bootnode-hetzner-hel + "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303", // bootnode-hetzner-fsn } // SepoliaBootnodes are the enode URLs of the P2P bootstrap nodes running on the @@ -65,6 +61,11 @@ var GoerliBootnodes = []string{ "enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303", } +var Eip4844Bootnodes = []string{ + "enode://3e5e464998b0ae5504fea271d9d6d51bf53918ca0f18359e5827761338478f5a03f70dc875fe9338006291bcd0de9ac2c54781d61f06f71b8678d37df5aab3c3@35.222.39.134:0?discport=30304", + "enode://98b3bd997b5da1d5ffbcf4b52baa937c604d90e457fa26077dcb02a895a53125f272add9355b6247f16231b1759ac1d1532e0781ec46137e0f7c39b6844525b8@34.170.3.3:0?discport=30304", +} + var V5Bootnodes = []string{ // Teku team's bootnode "enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA", diff --git a/params/config.go b/params/config.go index 816577a5479..e3d64547bac 100644 --- a/params/config.go +++ b/params/config.go @@ -31,6 +31,7 @@ var ( SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") + Eip4844GenesisHash = common.HexToHash("0x28389ca4b6b1a3e13068d70daf3dd23a6e4ded1056bb35014f0a2a2080c453a1") ) // TrustedCheckpoints associates each known checkpoint with the genesis hash of @@ -194,6 +195,7 @@ var ( ArrowGlacierBlock: nil, TerminalTotalDifficulty: big.NewInt(10_790_000), TerminalTotalDifficultyPassed: true, + ShanghaiTime: newUint64(1678832736), Clique: &CliqueConfig{ Period: 15, Epoch: 30000, @@ -954,7 +956,7 @@ type Rules struct { IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon bool - IsMerge, IsShanghai, isCancun, isPrague bool + IsMerge, IsShanghai, IsCancun, isPrague bool } // Rules ensures c's ChainID is not nil. @@ -977,7 +979,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsLondon: c.IsLondon(num), IsMerge: isMerge, IsShanghai: c.IsShanghai(timestamp), - isCancun: c.IsCancun(timestamp), + IsCancun: c.IsCancun(timestamp), isPrague: c.IsPrague(timestamp), } } diff --git a/params/protocol_params.go b/params/protocol_params.go index bb703d0b74d..76b9d5f01f0 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -159,6 +159,18 @@ const ( // up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529 RefundQuotient uint64 = 2 RefundQuotientEIP3529 uint64 = 5 + + // stuff from EIP-4844 + FieldElementsPerBlob = 4096 // each field element is 32 bytes + MaxDataGasPerBlock = 1 << 19 + DataGasPerBlob = 1 << 17 + TargetDataGasPerBlock = 1 << 18 + MinDataGasPrice = 1 + DataGasPriceUpdateFraction = 2225652 + MaxBlobsPerBlock = MaxDataGasPerBlock / DataGasPerBlob + + BlobCommitmentVersionKZG uint8 = 0x01 + PointEvaluationGas uint64 = 50000 ) // Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations diff --git a/params/version.go b/params/version.go index 2a55ad122a3..0cede57bbff 100644 --- a/params/version.go +++ b/params/version.go @@ -23,7 +23,7 @@ import ( const ( VersionMajor = 1 // Major version component of the current release VersionMinor = 11 // Minor version component of the current release - VersionPatch = 1 // Patch version component of the current release + VersionPatch = 5 // Patch version component of the current release VersionMeta = "unstable" // Version metadata to append to the version string ) diff --git a/rpc/client.go b/rpc/client.go index a509cb2e0fa..69ff4851e31 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -345,7 +345,10 @@ func (c *Client) CallContext(ctx context.Context, result interface{}, method str case len(resp.Result) == 0: return ErrNoResult default: - return json.Unmarshal(resp.Result, &result) + if result == nil { + return nil + } + return json.Unmarshal(resp.Result, result) } } diff --git a/rpc/client_test.go b/rpc/client_test.go index 0a88ce40b2a..a94a54929b3 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -69,6 +69,26 @@ func TestClientResponseType(t *testing.T) { } } +// This test checks calling a method that returns 'null'. +func TestClientNullResponse(t *testing.T) { + server := newTestServer() + defer server.Stop() + + client := DialInProc(server) + defer client.Close() + + var result json.RawMessage + if err := client.Call(&result, "test_null"); err != nil { + t.Fatal(err) + } + if result == nil { + t.Fatal("Expected non-nil result") + } + if !reflect.DeepEqual(result, json.RawMessage("null")) { + t.Errorf("Expected null, got %s", result) + } +} + // This test checks that server-returned errors with code and data come out of Client.Call. func TestClientErrorData(t *testing.T) { server := newTestServer() diff --git a/rpc/server_test.go b/rpc/server_test.go index c9abe53e521..f1a9b3d5cd4 100644 --- a/rpc/server_test.go +++ b/rpc/server_test.go @@ -45,7 +45,7 @@ func TestServerRegisterName(t *testing.T) { t.Fatalf("Expected service calc to be registered") } - wantCallbacks := 12 + wantCallbacks := 13 if len(svc.callbacks) != wantCallbacks { t.Errorf("Expected %d callbacks for service 'service', got %d", wantCallbacks, len(svc.callbacks)) } diff --git a/rpc/testservice_test.go b/rpc/testservice_test.go index 8454a401922..eab67f1dd5d 100644 --- a/rpc/testservice_test.go +++ b/rpc/testservice_test.go @@ -78,6 +78,10 @@ func (o *MarshalErrObj) MarshalText() ([]byte, error) { func (s *testService) NoArgsRets() {} +func (s *testService) Null() any { + return nil +} + func (s *testService) Echo(str string, i int, args *echoArgs) echoResult { return echoResult{str, i, args} } diff --git a/rpc/websocket.go b/rpc/websocket.go index 0ac2a2792d5..a6b95dd2acd 100644 --- a/rpc/websocket.go +++ b/rpc/websocket.go @@ -38,7 +38,7 @@ const ( wsPingInterval = 30 * time.Second wsPingWriteTimeout = 5 * time.Second wsPongTimeout = 30 * time.Second - wsMessageSizeLimit = 15 * 1024 * 1024 + wsMessageSizeLimit = 32 * 1024 * 1024 ) var wsBufferPool = new(sync.Pool) diff --git a/signer/core/api.go b/signer/core/api.go index 3c1c94801b1..05da1ff7878 100644 --- a/signer/core/api.go +++ b/signer/core/api.go @@ -589,7 +589,10 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args apitypes.SendTxA return nil, err } // Convert fields into a real transaction - var unsignedTx = result.Transaction.ToTransaction() + unsignedTx, err := result.Transaction.ToTransaction() + if err != nil { + return nil, err + } // Get the password for the transaction pw, err := api.lookupOrQueryPassword(acc.Address, "Account password", fmt.Sprintf("Please enter the password for account %s", acc.Address.String())) diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go index c72cad5939c..aa09680b7b2 100644 --- a/signer/core/apitypes/types.go +++ b/signer/core/apitypes/types.go @@ -28,6 +28,8 @@ import ( "strconv" "strings" + "github.com/protolambda/ztyp/view" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -98,6 +100,8 @@ type SendTxArgs struct { // For non-legacy transactions AccessList *types.AccessList `json:"accessList,omitempty"` ChainID *hexutil.Big `json:"chainId,omitempty"` + + Blobs []types.Blob `json:"blobs,omitempty"` } func (args SendTxArgs) String() string { @@ -109,7 +113,7 @@ func (args SendTxArgs) String() string { } // ToTransaction converts the arguments to a transaction. -func (args *SendTxArgs) ToTransaction() *types.Transaction { +func (args *SendTxArgs) ToTransaction() (*types.Transaction, error) { // Add the To-field, if specified var to *common.Address if args.To != nil { @@ -126,6 +130,33 @@ func (args *SendTxArgs) ToTransaction() *types.Transaction { var data types.TxData switch { + case args.Blobs != nil: + al := types.AccessList{} + if args.AccessList != nil { + al = *args.AccessList + } + msg := types.BlobTxMessage{} + msg.To.Address = (*types.AddressSSZ)(to) + msg.ChainID.SetFromBig((*big.Int)(args.ChainID)) + msg.Nonce = view.Uint64View(args.Nonce) + msg.Gas = view.Uint64View(args.Gas) + msg.GasFeeCap.SetFromBig((*big.Int)(args.MaxFeePerGas)) + msg.GasTipCap.SetFromBig((*big.Int)(args.MaxPriorityFeePerGas)) + msg.Value.SetFromBig((*big.Int)(&args.Value)) + msg.Data = input + msg.AccessList = types.AccessListView(al) + commitments, hashes, proofs, err := types.Blobs(args.Blobs).ComputeCommitmentsAndProofs() + if err != nil { + return nil, fmt.Errorf("invalid blobs: %v", err) + } + msg.BlobVersionedHashes = hashes + wrapData := types.BlobTxWrapData{ + Blobs: args.Blobs, + Proofs: proofs, + BlobKzgs: commitments, + } + data = &types.SignedBlobTx{Message: msg} + return types.NewTx(data, types.WithTxWrapData(&wrapData)), nil case args.MaxFeePerGas != nil: al := types.AccessList{} if args.AccessList != nil { @@ -163,7 +194,7 @@ func (args *SendTxArgs) ToTransaction() *types.Transaction { Data: input, } } - return types.NewTx(data) + return types.NewTx(data), nil } type SigFormat struct { @@ -742,112 +773,30 @@ func isPrimitiveTypeValid(primitiveType string) bool { primitiveType == "bool" || primitiveType == "bool[]" || primitiveType == "string" || - primitiveType == "string[]" { - return true - } - if primitiveType == "bytes" || + primitiveType == "string[]" || + primitiveType == "bytes" || primitiveType == "bytes[]" || - primitiveType == "bytes1" || - primitiveType == "bytes1[]" || - primitiveType == "bytes2" || - primitiveType == "bytes2[]" || - primitiveType == "bytes3" || - primitiveType == "bytes3[]" || - primitiveType == "bytes4" || - primitiveType == "bytes4[]" || - primitiveType == "bytes5" || - primitiveType == "bytes5[]" || - primitiveType == "bytes6" || - primitiveType == "bytes6[]" || - primitiveType == "bytes7" || - primitiveType == "bytes7[]" || - primitiveType == "bytes8" || - primitiveType == "bytes8[]" || - primitiveType == "bytes9" || - primitiveType == "bytes9[]" || - primitiveType == "bytes10" || - primitiveType == "bytes10[]" || - primitiveType == "bytes11" || - primitiveType == "bytes11[]" || - primitiveType == "bytes12" || - primitiveType == "bytes12[]" || - primitiveType == "bytes13" || - primitiveType == "bytes13[]" || - primitiveType == "bytes14" || - primitiveType == "bytes14[]" || - primitiveType == "bytes15" || - primitiveType == "bytes15[]" || - primitiveType == "bytes16" || - primitiveType == "bytes16[]" || - primitiveType == "bytes17" || - primitiveType == "bytes17[]" || - primitiveType == "bytes18" || - primitiveType == "bytes18[]" || - primitiveType == "bytes19" || - primitiveType == "bytes19[]" || - primitiveType == "bytes20" || - primitiveType == "bytes20[]" || - primitiveType == "bytes21" || - primitiveType == "bytes21[]" || - primitiveType == "bytes22" || - primitiveType == "bytes22[]" || - primitiveType == "bytes23" || - primitiveType == "bytes23[]" || - primitiveType == "bytes24" || - primitiveType == "bytes24[]" || - primitiveType == "bytes25" || - primitiveType == "bytes25[]" || - primitiveType == "bytes26" || - primitiveType == "bytes26[]" || - primitiveType == "bytes27" || - primitiveType == "bytes27[]" || - primitiveType == "bytes28" || - primitiveType == "bytes28[]" || - primitiveType == "bytes29" || - primitiveType == "bytes29[]" || - primitiveType == "bytes30" || - primitiveType == "bytes30[]" || - primitiveType == "bytes31" || - primitiveType == "bytes31[]" || - primitiveType == "bytes32" || - primitiveType == "bytes32[]" { - return true - } - if primitiveType == "int" || + primitiveType == "int" || primitiveType == "int[]" || - primitiveType == "int8" || - primitiveType == "int8[]" || - primitiveType == "int16" || - primitiveType == "int16[]" || - primitiveType == "int32" || - primitiveType == "int32[]" || - primitiveType == "int64" || - primitiveType == "int64[]" || - primitiveType == "int96" || - primitiveType == "int96[]" || - primitiveType == "int128" || - primitiveType == "int128[]" || - primitiveType == "int256" || - primitiveType == "int256[]" { + primitiveType == "uint" || + primitiveType == "uint[]" { return true } - if primitiveType == "uint" || - primitiveType == "uint[]" || - primitiveType == "uint8" || - primitiveType == "uint8[]" || - primitiveType == "uint16" || - primitiveType == "uint16[]" || - primitiveType == "uint32" || - primitiveType == "uint32[]" || - primitiveType == "uint64" || - primitiveType == "uint64[]" || - primitiveType == "uint96" || - primitiveType == "uint96[]" || - primitiveType == "uint128" || - primitiveType == "uint128[]" || - primitiveType == "uint256" || - primitiveType == "uint256[]" { - return true + // For 'bytesN', 'bytesN[]', we allow N from 1 to 32 + for n := 1; n <= 32; n++ { + // e.g. 'bytes28' or 'bytes28[]' + if primitiveType == fmt.Sprintf("bytes%d", n) || primitiveType == fmt.Sprintf("bytes%d[]", n) { + return true + } + } + // For 'intN','intN[]' and 'uintN','uintN[]' we allow N in increments of 8, from 8 up to 256 + for n := 8; n <= 256; n += 8 { + if primitiveType == fmt.Sprintf("int%d", n) || primitiveType == fmt.Sprintf("int%d[]", n) { + return true + } + if primitiveType == fmt.Sprintf("uint%d", n) || primitiveType == fmt.Sprintf("uint%d[]", n) { + return true + } } return false } diff --git a/tests/fuzzers/modexp/debug/main.go b/signer/core/apitypes/types_test.go similarity index 50% rename from tests/fuzzers/modexp/debug/main.go rename to signer/core/apitypes/types_test.go index 22002bd3f80..eef3cae00cc 100644 --- a/tests/fuzzers/modexp/debug/main.go +++ b/signer/core/apitypes/types_test.go @@ -1,4 +1,4 @@ -// Copyright 2020 The go-ethereum Authors +// Copyright 2023 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,27 +14,27 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package main +package apitypes -import ( - "fmt" - "os" +import "testing" - "github.com/ethereum/go-ethereum/tests/fuzzers/modexp" -) - -func main() { - if len(os.Args) != 2 { - fmt.Fprintf(os.Stderr, "Usage: debug \n") - fmt.Fprintf(os.Stderr, "Example\n") - fmt.Fprintf(os.Stderr, " $ debug ../crashers/4bbef6857c733a87ecf6fd8b9e7238f65eb9862a\n") - os.Exit(1) +func TestIsPrimitive(t *testing.T) { + // Expected positives + for i, tc := range []string{ + "int24", "int24[]", "uint88", "uint88[]", "uint", "uint[]", "int256", "int256[]", + "uint96", "uint96[]", "int96", "int96[]", "bytes17[]", "bytes17", + } { + if !isPrimitiveTypeValid(tc) { + t.Errorf("test %d: expected '%v' to be a valid primitive", i, tc) + } } - crasher := os.Args[1] - data, err := os.ReadFile(crasher) - if err != nil { - fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err) - os.Exit(1) + // Expected negatives + for i, tc := range []string{ + "int257", "int257[]", "uint88 ", "uint88 []", "uint257", "uint-1[]", + "uint0", "uint0[]", "int95", "int95[]", "uint1", "uint1[]", "bytes33[]", "bytess", + } { + if isPrimitiveTypeValid(tc) { + t.Errorf("test %d: expected '%v' to not be a valid primitive", i, tc) + } } - modexp.Fuzz(data) } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 8da95a640a1..8d63c9e6075 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -89,6 +89,7 @@ type btHeader struct { Timestamp uint64 BaseFeePerGas *big.Int WithdrawalsRoot *common.Hash + ExcessDataGas *big.Int } type btHeaderMarshaling struct { @@ -99,6 +100,7 @@ type btHeaderMarshaling struct { GasUsed math.HexOrDecimal64 Timestamp math.HexOrDecimal64 BaseFeePerGas *math.HexOrDecimal256 + ExcessDataGas *math.HexOrDecimal256 } func (t *BlockTest) Run(snapshotter bool) error { @@ -154,7 +156,7 @@ func (t *BlockTest) Run(snapshotter bool) error { } // Cross-check the snapshot-to-hash against the trie hash if snapshotter { - if err := chain.Snapshots().Verify(chain.CurrentBlock().Root()); err != nil { + if err := chain.Snapshots().Verify(chain.CurrentBlock().Root); err != nil { return err } } @@ -163,18 +165,19 @@ func (t *BlockTest) Run(snapshotter bool) error { func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis { return &core.Genesis{ - Config: config, - Nonce: t.json.Genesis.Nonce.Uint64(), - Timestamp: t.json.Genesis.Timestamp, - ParentHash: t.json.Genesis.ParentHash, - ExtraData: t.json.Genesis.ExtraData, - GasLimit: t.json.Genesis.GasLimit, - GasUsed: t.json.Genesis.GasUsed, - Difficulty: t.json.Genesis.Difficulty, - Mixhash: t.json.Genesis.MixHash, - Coinbase: t.json.Genesis.Coinbase, - Alloc: t.json.Pre, - BaseFee: t.json.Genesis.BaseFeePerGas, + Config: config, + Nonce: t.json.Genesis.Nonce.Uint64(), + Timestamp: t.json.Genesis.Timestamp, + ParentHash: t.json.Genesis.ParentHash, + ExtraData: t.json.Genesis.ExtraData, + GasLimit: t.json.Genesis.GasLimit, + GasUsed: t.json.Genesis.GasUsed, + Difficulty: t.json.Genesis.Difficulty, + Mixhash: t.json.Genesis.MixHash, + Coinbase: t.json.Genesis.Coinbase, + Alloc: t.json.Pre, + BaseFee: t.json.Genesis.BaseFeePerGas, + ExcessDataGas: t.json.Genesis.ExcessDataGas, } } @@ -283,6 +286,9 @@ func validateHeader(h *btHeader, h2 *types.Header) error { if !reflect.DeepEqual(h.WithdrawalsRoot, h2.WithdrawalsHash) { return fmt.Errorf("withdrawalsRoot: want: %v have: %v", h.WithdrawalsRoot, h2.WithdrawalsHash) } + if !reflect.DeepEqual(h.ExcessDataGas, h2.ExcessDataGas) { + return fmt.Errorf("excessDataGas: want: %v have: %v", h.ExcessDataGas, h2.ExcessDataGas) + } return nil } @@ -317,8 +323,8 @@ func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []b // block-by-block, so we can only validate imported headers after // all blocks have been processed by BlockChain, as they may not // be part of the longest chain until last block is imported. - for b := cm.CurrentBlock(); b != nil && b.NumberU64() != 0; b = cm.GetBlockByHash(b.Header().ParentHash) { - if err := validateHeader(bmap[b.Hash()].BlockHeader, b.Header()); err != nil { + for b := cm.CurrentBlock(); b != nil && b.Number.Uint64() != 0; b = cm.GetBlockByHash(b.ParentHash).Header() { + if err := validateHeader(bmap[b.Hash()].BlockHeader, b); err != nil { return fmt.Errorf("imported block header validation failed: %v", err) } } diff --git a/tests/fuzzers/les/les-fuzzer.go b/tests/fuzzers/les/les-fuzzer.go index 924a749e583..ae5e8d1b59e 100644 --- a/tests/fuzzers/les/les-fuzzer.go +++ b/tests/fuzzers/les/les-fuzzer.go @@ -380,7 +380,7 @@ func Fuzz(input []byte) int { f.doFuzz(l.GetHelperTrieProofsMsg, req) case 6: - req := &l.SendTxPacket{Txs: make([]*types.Transaction, f.randomInt(l.MaxTxSend+1))} + req := &l.SendTxPacket{Txs: make([]*types.NetworkTransaction, f.randomInt(l.MaxTxSend+1))} signer := types.HomesteadSigner{} for i := range req.Txs { var nonce uint64 @@ -390,7 +390,8 @@ func Fuzz(input []byte) int { nonce = f.nonce f.nonce += 1 } - req.Txs[i], _ = types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(10000), params.TxGas, big.NewInt(1000000000*int64(f.randomByte())), nil), signer, bankKey) + tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(10000), params.TxGas, big.NewInt(1000000000*int64(f.randomByte())), nil), signer, bankKey) + req.Txs[i] = types.NewNetworkTransaction(tx) } f.doFuzz(l.SendTxV2Msg, req) diff --git a/tests/fuzzers/modexp/modexp-fuzzer.go b/tests/fuzzers/modexp/modexp-fuzzer.go deleted file mode 100644 index 086d9e11531..00000000000 --- a/tests/fuzzers/modexp/modexp-fuzzer.go +++ /dev/null @@ -1,90 +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 modexp - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - big2 "github.com/holiman/big" -) - -// Fuzz is the fuzzing entry-point. -// The function must return -// -// - 1 if the fuzzer should increase priority of the -// given input during subsequent fuzzing (for example, the input is lexically -// correct and was parsed successfully); -// - -1 if the input must not be added to corpus even if gives new coverage; and -// - 0 otherwise -// -// other values are reserved for future use. -func Fuzz(input []byte) int { - if len(input) <= 96 { - return -1 - } - // Abort on too expensive inputs - precomp := vm.PrecompiledContractsBerlin[common.BytesToAddress([]byte{5})] - if gas := precomp.RequiredGas(input); gas > 40_000_000 { - return 0 - } - var ( - baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() - expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() - modLen = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64() - ) - // Handle a special case when both the base and mod length is zero - if baseLen == 0 && modLen == 0 { - return -1 - } - input = input[96:] - // Retrieve the operands and execute the exponentiation - var ( - base = new(big.Int).SetBytes(getData(input, 0, baseLen)) - exp = new(big.Int).SetBytes(getData(input, baseLen, expLen)) - mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen)) - base2 = new(big2.Int).SetBytes(getData(input, 0, baseLen)) - exp2 = new(big2.Int).SetBytes(getData(input, baseLen, expLen)) - mod2 = new(big2.Int).SetBytes(getData(input, baseLen+expLen, modLen)) - ) - if mod.BitLen() == 0 { - // Modulo 0 is undefined, return zero - return -1 - } - var a = new(big2.Int).Exp(base2, exp2, mod2).String() - var b = new(big.Int).Exp(base, exp, mod).String() - if a != b { - panic(fmt.Sprintf("Inequality %#x ^ %#x mod %#x \n have %s\n want %s", base, exp, mod, a, b)) - } - return 1 -} - -// getData returns a slice from the data based on the start and size and pads -// up to size with zero's. This function is overflow safe. -func getData(data []byte, start uint64, size uint64) []byte { - length := uint64(len(data)) - if start > length { - start = length - } - end := start + size - if end > length { - end = length - } - return common.RightPadBytes(data[start:end], int(size)) -} diff --git a/tests/gen_btheader.go b/tests/gen_btheader.go index 985ea692d75..339ae84bdae 100644 --- a/tests/gen_btheader.go +++ b/tests/gen_btheader.go @@ -35,6 +35,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) { Timestamp math.HexOrDecimal64 BaseFeePerGas *math.HexOrDecimal256 WithdrawalsRoot *common.Hash + ExcessDataGas *math.HexOrDecimal256 } var enc btHeader enc.Bloom = b.Bloom @@ -55,6 +56,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) { enc.Timestamp = math.HexOrDecimal64(b.Timestamp) enc.BaseFeePerGas = (*math.HexOrDecimal256)(b.BaseFeePerGas) enc.WithdrawalsRoot = b.WithdrawalsRoot + enc.ExcessDataGas = (*math.HexOrDecimal256)(b.ExcessDataGas) return json.Marshal(&enc) } @@ -79,6 +81,7 @@ func (b *btHeader) UnmarshalJSON(input []byte) error { Timestamp *math.HexOrDecimal64 BaseFeePerGas *math.HexOrDecimal256 WithdrawalsRoot *common.Hash + ExcessDataGas *math.HexOrDecimal256 } var dec btHeader if err := json.Unmarshal(input, &dec); err != nil { @@ -138,5 +141,8 @@ func (b *btHeader) UnmarshalJSON(input []byte) error { if dec.WithdrawalsRoot != nil { b.WithdrawalsRoot = dec.WithdrawalsRoot } + if dec.ExcessDataGas != nil { + b.ExcessDataGas = (*big.Int)(dec.ExcessDataGas) + } return nil } diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go index 7693a207a56..2444bac5cae 100644 --- a/tests/gen_sttransaction.go +++ b/tests/gen_sttransaction.go @@ -19,6 +19,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { GasPrice *math.HexOrDecimal256 `json:"gasPrice"` MaxFeePerGas *math.HexOrDecimal256 `json:"maxFeePerGas"` MaxPriorityFeePerGas *math.HexOrDecimal256 `json:"maxPriorityFeePerGas"` + MaxFeePerDataGas *big.Int `json:"maxFeePerDataGas"` Nonce math.HexOrDecimal64 `json:"nonce"` To string `json:"to"` Data []string `json:"data"` @@ -31,6 +32,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { enc.GasPrice = (*math.HexOrDecimal256)(s.GasPrice) enc.MaxFeePerGas = (*math.HexOrDecimal256)(s.MaxFeePerGas) enc.MaxPriorityFeePerGas = (*math.HexOrDecimal256)(s.MaxPriorityFeePerGas) + enc.MaxFeePerDataGas = s.MaxFeePerDataGas enc.Nonce = math.HexOrDecimal64(s.Nonce) enc.To = s.To enc.Data = s.Data @@ -52,6 +54,7 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { GasPrice *math.HexOrDecimal256 `json:"gasPrice"` MaxFeePerGas *math.HexOrDecimal256 `json:"maxFeePerGas"` MaxPriorityFeePerGas *math.HexOrDecimal256 `json:"maxPriorityFeePerGas"` + MaxFeePerDataGas *big.Int `json:"maxFeePerDataGas"` Nonce *math.HexOrDecimal64 `json:"nonce"` To *string `json:"to"` Data []string `json:"data"` @@ -73,6 +76,9 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { if dec.MaxPriorityFeePerGas != nil { s.MaxPriorityFeePerGas = (*big.Int)(dec.MaxPriorityFeePerGas) } + if dec.MaxFeePerDataGas != nil { + s.MaxFeePerDataGas = dec.MaxFeePerDataGas + } if dec.Nonce != nil { s.Nonce = uint64(*dec.Nonce) } diff --git a/tests/init.go b/tests/init.go index db037e3e1a0..99b7e4d3331 100644 --- a/tests/init.go +++ b/tests/init.go @@ -90,6 +90,19 @@ var Forks = map[string]*params.ChainConfig{ PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), }, + "MuirGlacier": { + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + DAOForkBlock: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + }, "FrontierToHomesteadAt5": { ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(5), @@ -286,6 +299,44 @@ var Forks = map[string]*params.ChainConfig{ TerminalTotalDifficulty: big.NewInt(0), ShanghaiTime: u64(15_000), }, + "Cancun": { + 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), + ArrowGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(0), + ShanghaiTime: u64(0), + CancunTime: u64(0), + }, + "ShanghaiToCancunAtTime15k": { + 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), + ArrowGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(0), + ShanghaiTime: u64(0), + CancunTime: u64(15_000), + }, } // AvailableForks returns the set of defined fork names diff --git a/tests/kzg_testdata/kzg_blobs.json b/tests/kzg_testdata/kzg_blobs.json new file mode 100644 index 00000000000..9b454db090e --- /dev/null +++ b/tests/kzg_testdata/kzg_blobs.json @@ -0,0 +1 @@ +{"KzgBlob1":"Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backyard, let me. Whiteboard polynomial tell me. Is it FFT, DTF or just COVID19? Help me! Help me! In your palo alto backy","KzgBlob2":"Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No special thing this time. No silly math for me or little little dumpling skin. Love me! Love me! No delivery tonight. No"} diff --git a/tests/state_test.go b/tests/state_test.go index 7dd2f678c68..c196a5744a1 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -222,13 +222,13 @@ func runBenchmark(b *testing.B, t *StateTest) { // Prepare the EVM. txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase) + context := core.NewEVMBlockContext(block.Header(), nil, nil, &t.json.Env.Coinbase) context.GetHash = vmTestBlockHash context.BaseFee = baseFee evm := vm.NewEVM(context, txContext, statedb, config, vmconfig) // Create "contract" for sender to cache code analysis. - sender := vm.NewContract(vm.AccountRef(msg.From()), vm.AccountRef(msg.From()), + sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From), nil, 0) var ( @@ -239,12 +239,12 @@ func runBenchmark(b *testing.B, t *StateTest) { b.ResetTimer() for n := 0; n < b.N; n++ { snapshot := statedb.Snapshot() - statedb.Prepare(rules, msg.From(), context.Coinbase, msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) + statedb.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList) b.StartTimer() start := time.Now() // Execute the message. - _, leftOverGas, err := evm.Call(sender, *msg.To(), msg.Data(), msg.Gas(), msg.Value()) + _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, msg.Value) if err != nil { b.Error(err) return @@ -253,7 +253,7 @@ func runBenchmark(b *testing.B, t *StateTest) { b.StopTimer() elapsed += uint64(time.Since(start)) refund += statedb.GetRefund() - gasUsed += msg.Gas() - leftOverGas + gasUsed += msg.GasLimit - leftOverGas statedb.RevertToSnapshot(snapshot) } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index b2e87fb004b..3b7fb418bed 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -104,6 +104,7 @@ type stTransaction struct { GasPrice *big.Int `json:"gasPrice"` MaxFeePerGas *big.Int `json:"maxFeePerGas"` MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas"` + MaxFeePerDataGas *big.Int `json:"maxFeePerDataGas"` Nonce uint64 `json:"nonce"` To string `json:"to"` Data []string `json:"data"` @@ -245,7 +246,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh // Prepare the EVM. txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase) + context := core.NewEVMBlockContext(block.Header(), nil, nil, &t.json.Env.Coinbase) context.GetHash = vmTestBlockHash context.BaseFee = baseFee context.Random = nil @@ -261,7 +262,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh // Execute the message. snapshot := statedb.Snapshot() gaspool := new(core.GasPool) - gaspool.AddGas(block.GasLimit()) + gaspool.AddGas(block.GasLimit()).AddDataGas(params.MaxDataGasPerBlock) _, err = core.ApplyMessage(evm, msg, gaspool) if err != nil { statedb.RevertToSnapshot(snapshot) @@ -329,7 +330,7 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis { return genesis } -func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Message, error) { +func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Message, error) { // Derive sender from private key if present. var from common.Address if len(tx.PrivateKey) > 0 { @@ -397,8 +398,18 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Messa return nil, fmt.Errorf("no gas price provided") } - msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, gasPrice, - tx.MaxFeePerGas, tx.MaxPriorityFeePerGas, data, accessList, false) + msg := &core.Message{ + From: from, + To: to, + Nonce: tx.Nonce, + Value: value, + GasLimit: gasLimit, + GasPrice: gasPrice, + GasFeeCap: tx.MaxFeePerGas, + GasTipCap: tx.MaxPriorityFeePerGas, + Data: data, + AccessList: accessList, + } return msg, nil } diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 391aa57584c..a0a7c61b493 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -37,6 +37,7 @@ type TransactionTest struct { EIP158 ttFork Frontier ttFork Homestead ttFork + Cancun ttFork } type ttFork struct { @@ -45,7 +46,7 @@ type ttFork struct { } func (tt *TransactionTest) Run(config *params.ChainConfig) error { - validateTx := func(rlpData hexutil.Bytes, signer types.Signer, isHomestead bool, isIstanbul bool) (*common.Address, *common.Hash, error) { + validateTx := func(rlpData hexutil.Bytes, signer types.Signer, isHomestead bool, isIstanbul bool, isCancun bool) (*common.Address, *common.Hash, error) { tx := new(types.Transaction) if err := rlp.DecodeBytes(rlpData, tx); err != nil { return nil, nil, err @@ -72,16 +73,18 @@ func (tt *TransactionTest) Run(config *params.ChainConfig) error { fork ttFork isHomestead bool isIstanbul bool + isCancun bool }{ - {"Frontier", types.FrontierSigner{}, tt.Frontier, false, false}, - {"Homestead", types.HomesteadSigner{}, tt.Homestead, true, false}, - {"EIP150", types.HomesteadSigner{}, tt.EIP150, true, false}, - {"EIP158", types.NewEIP155Signer(config.ChainID), tt.EIP158, true, false}, - {"Byzantium", types.NewEIP155Signer(config.ChainID), tt.Byzantium, true, false}, - {"Constantinople", types.NewEIP155Signer(config.ChainID), tt.Constantinople, true, false}, - {"Istanbul", types.NewEIP155Signer(config.ChainID), tt.Istanbul, true, true}, + {"Frontier", types.FrontierSigner{}, tt.Frontier, false, false, false}, + {"Homestead", types.HomesteadSigner{}, tt.Homestead, true, false, false}, + {"EIP150", types.HomesteadSigner{}, tt.EIP150, true, false, false}, + {"EIP158", types.NewEIP155Signer(config.ChainID), tt.EIP158, true, false, false}, + {"Byzantium", types.NewEIP155Signer(config.ChainID), tt.Byzantium, true, false, false}, + {"Constantinople", types.NewEIP155Signer(config.ChainID), tt.Constantinople, true, false, false}, + {"Istanbul", types.NewEIP155Signer(config.ChainID), tt.Istanbul, true, true, false}, + {"Cancun", types.NewEIP155Signer(config.ChainID), tt.Cancun, true, true, false}, } { - sender, txhash, err := validateTx(tt.RLP, testcase.signer, testcase.isHomestead, testcase.isIstanbul) + sender, txhash, err := validateTx(tt.RLP, testcase.signer, testcase.isHomestead, testcase.isIstanbul, testcase.isCancun) if testcase.fork.Sender == (common.UnprefixedAddress{}) { if err == nil { diff --git a/trie/committer.go b/trie/committer.go index c4957f3490e..9f978873a8d 100644 --- a/trie/committer.go +++ b/trie/committer.go @@ -33,29 +33,20 @@ type leaf struct { // insertion order. type committer struct { nodes *NodeSet - tracer *tracer collectLeaf bool } // newCommitter creates a new committer or picks one from the pool. -func newCommitter(owner common.Hash, tracer *tracer, collectLeaf bool) *committer { +func newCommitter(nodeset *NodeSet, collectLeaf bool) *committer { return &committer{ - nodes: NewNodeSet(owner), - tracer: tracer, + nodes: nodeset, collectLeaf: collectLeaf, } } -// Commit collapses a node down into a hash node and returns it along with -// the modified nodeset. -func (c *committer) Commit(n node) (hashNode, *NodeSet) { - h := c.commit(nil, n) - // Some nodes can be deleted from trie which can't be captured - // by committer itself. Iterate all deleted nodes tracked by - // tracer and marked them as deleted only if they are present - // in database previously. - c.tracer.markDeletions(c.nodes) - return h.(hashNode), c.nodes +// Commit collapses a node down into a hash node. +func (c *committer) Commit(n node) hashNode { + return c.commit(nil, n).(hashNode) } // commit collapses a node down into a hash node and returns it. @@ -74,9 +65,7 @@ func (c *committer) commit(path []byte, n node) node { // If the child is fullNode, recursively commit, // otherwise it can only be hashNode or valueNode. if _, ok := cn.Val.(*fullNode); ok { - childV := c.commit(append(path, cn.Key...), cn.Val) - - collapsed.Val = childV + collapsed.Val = c.commit(append(path, cn.Key...), cn.Val) } // The key needs to be copied, since we're adding it to the // modified nodeset. @@ -85,12 +74,6 @@ func (c *committer) commit(path []byte, n node) node { if hn, ok := hashedNode.(hashNode); ok { return hn } - // The short node now is embedded in its parent. Mark the node as - // deleted if it's present in database previously. It's equivalent - // as deletion from database's perspective. - if prev := c.tracer.getPrev(path); len(prev) != 0 { - c.nodes.markDeleted(path, prev) - } return collapsed case *fullNode: hashedKids := c.commitChildren(path, cn) @@ -101,12 +84,6 @@ func (c *committer) commit(path []byte, n node) node { if hn, ok := hashedNode.(hashNode); ok { return hn } - // The full node now is embedded in its parent. Mark the node as - // deleted if it's present in database previously. It's equivalent - // as deletion from database's perspective. - if prev := c.tracer.getPrev(path); len(prev) != 0 { - c.nodes.markDeleted(path, prev) - } return collapsed case hashNode: return cn @@ -134,8 +111,7 @@ func (c *committer) commitChildren(path []byte, n *fullNode) [17]node { // Commit the child recursively and store the "hashed" value. // Note the returned node can be some embedded nodes, so it's // possible the type is not hashNode. - hashed := c.commit(append(path, byte(i)), child) - children[i] = hashed + children[i] = c.commit(append(path, byte(i)), child) } // For the 17th child, it's possible the type is valuenode. if n.Children[16] != nil { @@ -155,6 +131,12 @@ func (c *committer) store(path []byte, n node) node { // usually is leaf node). But small value (less than 32bytes) is not // our target (leaves in account trie only). if hash == nil { + // The node is embedded in its parent, in other words, this node + // will not be stored in the database independently, mark it as + // deleted only if the node was existent in database before. + if _, ok := c.nodes.accessList[string(path)]; ok { + c.nodes.markDeleted(path) + } return n } // We have the hash already, estimate the RLP encoding-size of the node. @@ -169,7 +151,7 @@ func (c *committer) store(path []byte, n node) node { } ) // Collect the dirty node to nodeset for return. - c.nodes.markUpdated(path, mnode, c.tracer.getPrev(path)) + c.nodes.markUpdated(path, mnode) // Collect the corresponding leaf node if it's required. We don't check // full node since it's impossible to store value in fullNode. The key diff --git a/trie/database.go b/trie/database.go index 74247d59c4f..200ed3674bf 100644 --- a/trie/database.go +++ b/trie/database.go @@ -792,13 +792,12 @@ func (db *Database) Update(nodes *MergedNodeSet) error { } for _, owner := range order { subset := nodes.sets[owner] - for _, path := range subset.updates.order { - n, ok := subset.updates.nodes[path] - if !ok { - return fmt.Errorf("missing node %x %v", owner, path) + subset.forEachWithOrder(func(path string, n *memoryNode) { + if n.isDeleted() { + return // ignore deletion } db.insert(n.hash, int(n.size), n.node) - } + }) } // Link up the account trie and storage trie if the node points // to an account trie leaf. @@ -808,7 +807,7 @@ func (db *Database) Update(nodes *MergedNodeSet) error { if err := rlp.DecodeBytes(n.blob, &account); err != nil { return err } - if account.Root != emptyRoot { + if account.Root != types.EmptyRootHash { db.reference(account.Root, n.parent) } } diff --git a/trie/encoding_test.go b/trie/encoding_test.go index e8fe4f3c6bb..d16d25c359c 100644 --- a/trie/encoding_test.go +++ b/trie/encoding_test.go @@ -18,6 +18,7 @@ package trie import ( "bytes" + crand "crypto/rand" "encoding/hex" "math/rand" "testing" @@ -97,7 +98,7 @@ func TestHexToCompactInPlaceRandom(t *testing.T) { for i := 0; i < 10000; i++ { l := rand.Intn(128) key := make([]byte, l) - rand.Read(key) + crand.Read(key) hexBytes := keybytesToHex(key) hexOrig := []byte(string(hexBytes)) exp := hexToCompact(hexBytes) diff --git a/trie/iterator.go b/trie/iterator.go index aa621cd54a2..f42beec4abe 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -22,6 +22,7 @@ import ( "errors" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) // NodeResolver is used for looking up trie nodes before reaching into the real @@ -160,7 +161,7 @@ func (e seekError) Error() string { } func newNodeIterator(trie *Trie, start []byte) NodeIterator { - if trie.Hash() == emptyRoot { + if trie.Hash() == types.EmptyRootHash { return &nodeIterator{ trie: trie, err: errIteratorEnd, @@ -302,7 +303,7 @@ func (it *nodeIterator) seek(prefix []byte) error { func (it *nodeIterator) init() (*nodeIteratorState, error) { root := it.trie.Hash() state := &nodeIteratorState{node: it.trie.root, index: -1} - if root != emptyRoot { + if root != types.EmptyRootHash { state.hash = root } return state, state.resolve(it, nil) diff --git a/trie/nodeset.go b/trie/nodeset.go index 92817235017..99e4a80fa8a 100644 --- a/trie/nodeset.go +++ b/trie/nodeset.go @@ -19,6 +19,7 @@ package trie import ( "fmt" "reflect" + "sort" "strings" "github.com/ethereum/go-ethereum/common" @@ -40,8 +41,8 @@ var memoryNodeSize = int(reflect.TypeOf(memoryNode{}).Size()) // memorySize returns the total memory size used by this node. // nolint:unused -func (n *memoryNode) memorySize(key int) int { - return int(n.size) + memoryNodeSize + key +func (n *memoryNode) memorySize(pathlen int) int { + return int(n.size) + memoryNodeSize + pathlen } // rlp returns the raw rlp encoded blob of the cached trie node, either directly @@ -64,7 +65,13 @@ func (n *memoryNode) obj() node { return expandNode(n.hash[:], n.node) } +// isDeleted returns the indicator if the node is marked as deleted. +func (n *memoryNode) isDeleted() bool { + return n.hash == (common.Hash{}) +} + // nodeWithPrev wraps the memoryNode with the previous node value. +// nolint: unused type nodeWithPrev struct { *memoryNode prev []byte // RLP-encoded previous value, nil means it's non-existent @@ -79,64 +86,60 @@ func (n *nodeWithPrev) unwrap() *memoryNode { // memorySize returns the total memory size used by this node. It overloads // the function in memoryNode by counting the size of previous value as well. // nolint: unused -func (n *nodeWithPrev) memorySize(key int) int { - return n.memoryNode.memorySize(key) + len(n.prev) -} - -// nodesWithOrder represents a collection of dirty nodes which includes -// newly-inserted and updated nodes. The modification order of all nodes -// is represented by order list. -type nodesWithOrder struct { - order []string // the path list of dirty nodes, sort by insertion order - nodes map[string]*nodeWithPrev // the map of dirty nodes, keyed by node path +func (n *nodeWithPrev) memorySize(pathlen int) int { + return n.memoryNode.memorySize(pathlen) + len(n.prev) } // NodeSet contains all dirty nodes collected during the commit operation. // Each node is keyed by path. It's not thread-safe to use. type NodeSet struct { - owner common.Hash // the identifier of the trie - updates *nodesWithOrder // the set of updated nodes(newly inserted, updated) - deletes map[string][]byte // the map of deleted nodes, keyed by node - leaves []*leaf // the list of dirty leaves + owner common.Hash // the identifier of the trie + nodes map[string]*memoryNode // the set of dirty nodes(inserted, updated, deleted) + leaves []*leaf // the list of dirty leaves + updates int // the count of updated and inserted nodes + deletes int // the count of deleted nodes + + // The list of accessed nodes, which records the original node value. + // The origin value is expected to be nil for newly inserted node + // and is expected to be non-nil for other types(updated, deleted). + accessList map[string][]byte } // NewNodeSet initializes an empty node set to be used for tracking dirty nodes // from a specific account or storage trie. The owner is zero for the account // trie and the owning account address hash for storage tries. -func NewNodeSet(owner common.Hash) *NodeSet { +func NewNodeSet(owner common.Hash, accessList map[string][]byte) *NodeSet { return &NodeSet{ - owner: owner, - updates: &nodesWithOrder{ - nodes: make(map[string]*nodeWithPrev), - }, - deletes: make(map[string][]byte), + owner: owner, + nodes: make(map[string]*memoryNode), + accessList: accessList, } } -/* -// NewNodeSetWithDeletion initializes the nodeset with provided deletion set. -func NewNodeSetWithDeletion(owner common.Hash, paths [][]byte, prev [][]byte) *NodeSet { - set := NewNodeSet(owner) - for i, path := range paths { - set.markDeleted(path, prev[i]) +// forEachWithOrder iterates the dirty nodes with the order from bottom to top, +// right to left, nodes with the longest path will be iterated first. +func (set *NodeSet) forEachWithOrder(callback func(path string, n *memoryNode)) { + var paths sort.StringSlice + for path := range set.nodes { + paths = append(paths, path) + } + // Bottom-up, longest path first + sort.Sort(sort.Reverse(paths)) + for _, path := range paths { + callback(path, set.nodes[path]) } - return set } -*/ -// markUpdated marks the node as dirty(newly-inserted or updated) with provided -// node path, node object along with its previous value. -func (set *NodeSet) markUpdated(path []byte, node *memoryNode, prev []byte) { - set.updates.order = append(set.updates.order, string(path)) - set.updates.nodes[string(path)] = &nodeWithPrev{ - memoryNode: node, - prev: prev, - } +// markUpdated marks the node as dirty(newly-inserted or updated). +func (set *NodeSet) markUpdated(path []byte, node *memoryNode) { + set.nodes[string(path)] = node + set.updates += 1 } -// markDeleted marks the node as deleted with provided path and previous value. -func (set *NodeSet) markDeleted(path []byte, prev []byte) { - set.deletes[string(path)] = prev +// markDeleted marks the node as deleted. +func (set *NodeSet) markDeleted(path []byte) { + set.nodes[string(path)] = &memoryNode{} + set.deletes += 1 } // addLeaf collects the provided leaf node into set. @@ -144,16 +147,16 @@ func (set *NodeSet) addLeaf(node *leaf) { set.leaves = append(set.leaves, node) } -// Size returns the number of updated and deleted nodes contained in the set. +// Size returns the number of dirty nodes in set. func (set *NodeSet) Size() (int, int) { - return len(set.updates.order), len(set.deletes) + return set.updates, set.deletes } // Hashes returns the hashes of all updated nodes. TODO(rjl493456442) how can // we get rid of it? func (set *NodeSet) Hashes() []common.Hash { var ret []common.Hash - for _, node := range set.updates.nodes { + for _, node := range set.nodes { ret = append(ret, node.hash) } return ret @@ -163,19 +166,23 @@ func (set *NodeSet) Hashes() []common.Hash { func (set *NodeSet) Summary() string { var out = new(strings.Builder) fmt.Fprintf(out, "nodeset owner: %v\n", set.owner) - if set.updates != nil { - for _, key := range set.updates.order { - updated := set.updates.nodes[key] - if updated.prev != nil { - fmt.Fprintf(out, " [*]: %x -> %v prev: %x\n", key, updated.hash, updated.prev) - } else { - fmt.Fprintf(out, " [+]: %x -> %v\n", key, updated.hash) + if set.nodes != nil { + for path, n := range set.nodes { + // Deletion + if n.isDeleted() { + fmt.Fprintf(out, " [-]: %x prev: %x\n", path, set.accessList[path]) + continue } + // Insertion + origin, ok := set.accessList[path] + if !ok { + fmt.Fprintf(out, " [+]: %x -> %v\n", path, n.hash) + continue + } + // Update + fmt.Fprintf(out, " [*]: %x -> %v prev: %x\n", path, n.hash, origin) } } - for k, n := range set.deletes { - fmt.Fprintf(out, " [-]: %x -> %x\n", k, n) - } for _, n := range set.leaves { fmt.Fprintf(out, "[leaf]: %v\n", n) } diff --git a/trie/proof.go b/trie/proof.go index af49ce36b36..f11dfc47afa 100644 --- a/trie/proof.go +++ b/trie/proof.go @@ -563,7 +563,7 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, key } // Rebuild the trie with the leaf stream, the shape of trie // should be same with the original one. - tr := &Trie{root: root, reader: newEmptyReader()} + tr := &Trie{root: root, reader: newEmptyReader(), tracer: newTracer()} if empty { tr.root = nil } diff --git a/trie/proof_test.go b/trie/proof_test.go index 61667b20ab1..5796a308930 100644 --- a/trie/proof_test.go +++ b/trie/proof_test.go @@ -23,7 +23,6 @@ import ( mrand "math/rand" "sort" "testing" - "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -31,10 +30,6 @@ import ( "github.com/ethereum/go-ethereum/ethdb/memorydb" ) -func init() { - mrand.Seed(time.Now().Unix()) -} - // makeProvers creates Merkle trie provers based on different implementations to // test all variations. func makeProvers(trie *Trie) []func(key []byte) *memorydb.Database { diff --git a/trie/stacktrie.go b/trie/stacktrie.go index fb8cc0d763e..e7b3171af6e 100644 --- a/trie/stacktrie.go +++ b/trie/stacktrie.go @@ -25,6 +25,7 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -407,7 +408,7 @@ func (st *StackTrie) hashRec(hasher *hasher, path []byte) { return case emptyNode: - st.val = emptyRoot.Bytes() + st.val = types.EmptyRootHash.Bytes() st.key = st.key[:0] st.nodeType = hashedNode return diff --git a/trie/sync.go b/trie/sync.go index 4bf735c02f2..4f558459917 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/prque" "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/log" ) @@ -184,7 +185,7 @@ func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallb // hex format and contain all the parent path if it's layered trie node. func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, parentPath []byte, callback LeafCallback) { // Short circuit if the trie is empty or already known - if root == emptyRoot { + if root == types.EmptyRootHash { return } if s.membatch.hasNode(path) { @@ -217,7 +218,7 @@ func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, par // as is. func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash, parentPath []byte) { // Short circuit if the entry is empty or already known - if hash == emptyState { + if hash == types.EmptyCodeHash { return } if s.membatch.hasCode(hash) { diff --git a/trie/sync_test.go b/trie/sync_test.go index 709f22949f1..fc871a22c80 100644 --- a/trie/sync_test.go +++ b/trie/sync_test.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb/memorydb" ) @@ -104,7 +105,7 @@ func TestEmptySync(t *testing.T) { dbA := NewDatabase(rawdb.NewMemoryDatabase()) dbB := NewDatabase(rawdb.NewMemoryDatabase()) emptyA, _ := New(TrieID(common.Hash{}), dbA) - emptyB, _ := New(TrieID(emptyRoot), dbB) + emptyB, _ := New(TrieID(types.EmptyRootHash), dbB) for i, trie := range []*Trie{emptyA, emptyB} { sync := NewSync(trie.Hash(), memorydb.New(), nil, []*Database{dbA, dbB}[i].Scheme()) diff --git a/trie/tracer.go b/trie/tracer.go new file mode 100644 index 00000000000..a27e371c7ac --- /dev/null +++ b/trie/tracer.go @@ -0,0 +1,125 @@ +// 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 trie + +import "github.com/ethereum/go-ethereum/common" + +// tracer tracks the changes of trie nodes. During the trie operations, +// some nodes can be deleted from the trie, while these deleted nodes +// won't be captured by trie.Hasher or trie.Committer. Thus, these deleted +// nodes won't be removed from the disk at all. Tracer is an auxiliary tool +// used to track all insert and delete operations of trie and capture all +// deleted nodes eventually. +// +// The changed nodes can be mainly divided into two categories: the leaf +// node and intermediate node. The former is inserted/deleted by callers +// while the latter is inserted/deleted in order to follow the rule of trie. +// This tool can track all of them no matter the node is embedded in its +// parent or not, but valueNode is never tracked. +// +// Besides, it's also used for recording the original value of the nodes +// when they are resolved from the disk. The pre-value of the nodes will +// be used to construct trie history in the future. +// +// Note tracer is not thread-safe, callers should be responsible for handling +// the concurrency issues by themselves. +type tracer struct { + inserts map[string]struct{} + deletes map[string]struct{} + accessList map[string][]byte +} + +// newTracer initializes the tracer for capturing trie changes. +func newTracer() *tracer { + return &tracer{ + inserts: make(map[string]struct{}), + deletes: make(map[string]struct{}), + accessList: make(map[string][]byte), + } +} + +// onRead tracks the newly loaded trie node and caches the rlp-encoded +// blob internally. Don't change the value outside of function since +// it's not deep-copied. +func (t *tracer) onRead(path []byte, val []byte) { + t.accessList[string(path)] = val +} + +// onInsert tracks the newly inserted trie node. If it's already +// in the deletion set (resurrected node), then just wipe it from +// the deletion set as it's "untouched". +func (t *tracer) onInsert(path []byte) { + if _, present := t.deletes[string(path)]; present { + delete(t.deletes, string(path)) + return + } + t.inserts[string(path)] = struct{}{} +} + +// onDelete tracks the newly deleted trie node. If it's already +// in the addition set, then just wipe it from the addition set +// as it's untouched. +func (t *tracer) onDelete(path []byte) { + if _, present := t.inserts[string(path)]; present { + delete(t.inserts, string(path)) + return + } + t.deletes[string(path)] = struct{}{} +} + +// reset clears the content tracked by tracer. +func (t *tracer) reset() { + t.inserts = make(map[string]struct{}) + t.deletes = make(map[string]struct{}) + t.accessList = make(map[string][]byte) +} + +// copy returns a deep copied tracer instance. +func (t *tracer) copy() *tracer { + var ( + inserts = make(map[string]struct{}) + deletes = make(map[string]struct{}) + accessList = make(map[string][]byte) + ) + for path := range t.inserts { + inserts[path] = struct{}{} + } + for path := range t.deletes { + deletes[path] = struct{}{} + } + for path, blob := range t.accessList { + accessList[path] = common.CopyBytes(blob) + } + return &tracer{ + inserts: inserts, + deletes: deletes, + accessList: accessList, + } +} + +// markDeletions puts all tracked deletions into the provided nodeset. +func (t *tracer) markDeletions(set *NodeSet) { + for path := range t.deletes { + // It's possible a few deleted nodes were embedded + // in their parent before, the deletions can be no + // effect by deleting nothing, filter them out. + if _, ok := set.accessList[path]; !ok { + continue + } + set.markDeleted([]byte(path)) + } +} diff --git a/trie/tracer_test.go b/trie/tracer_test.go new file mode 100644 index 00000000000..5e627c89c9b --- /dev/null +++ b/trie/tracer_test.go @@ -0,0 +1,368 @@ +// 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 trie + +import ( + "bytes" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" +) + +var ( + tiny = []struct{ k, v string }{ + {"k1", "v1"}, + {"k2", "v2"}, + {"k3", "v3"}, + } + nonAligned = []struct{ k, v string }{ + {"do", "verb"}, + {"ether", "wookiedoo"}, + {"horse", "stallion"}, + {"shaman", "horse"}, + {"doge", "coin"}, + {"dog", "puppy"}, + {"somethingveryoddindeedthis is", "myothernodedata"}, + } + standard = []struct{ k, v string }{ + {string(randBytes(32)), "verb"}, + {string(randBytes(32)), "wookiedoo"}, + {string(randBytes(32)), "stallion"}, + {string(randBytes(32)), "horse"}, + {string(randBytes(32)), "coin"}, + {string(randBytes(32)), "puppy"}, + {string(randBytes(32)), "myothernodedata"}, + } +) + +func TestTrieTracer(t *testing.T) { + testTrieTracer(t, tiny) + testTrieTracer(t, nonAligned) + testTrieTracer(t, standard) +} + +// Tests if the trie diffs are tracked correctly. Tracer should capture +// all non-leaf dirty nodes, no matter the node is embedded or not. +func testTrieTracer(t *testing.T, vals []struct{ k, v string }) { + db := NewDatabase(rawdb.NewMemoryDatabase()) + trie := NewEmpty(db) + + // Determine all new nodes are tracked + for _, val := range vals { + trie.Update([]byte(val.k), []byte(val.v)) + } + insertSet := copySet(trie.tracer.inserts) // copy before commit + deleteSet := copySet(trie.tracer.deletes) // copy before commit + root, nodes := trie.Commit(false) + db.Update(NewWithNodeSet(nodes)) + + seen := setKeys(iterNodes(db, root)) + if !compareSet(insertSet, seen) { + t.Fatal("Unexpected insertion set") + } + if !compareSet(deleteSet, nil) { + t.Fatal("Unexpected deletion set") + } + + // Determine all deletions are tracked + trie, _ = New(TrieID(root), db) + for _, val := range vals { + trie.Delete([]byte(val.k)) + } + insertSet, deleteSet = copySet(trie.tracer.inserts), copySet(trie.tracer.deletes) + if !compareSet(insertSet, nil) { + t.Fatal("Unexpected insertion set") + } + if !compareSet(deleteSet, seen) { + t.Fatal("Unexpected deletion set") + } +} + +// Test that after inserting a new batch of nodes and deleting them immediately, +// the trie tracer should be cleared normally as no operation happened. +func TestTrieTracerNoop(t *testing.T) { + testTrieTracerNoop(t, tiny) + testTrieTracerNoop(t, nonAligned) + testTrieTracerNoop(t, standard) +} + +func testTrieTracerNoop(t *testing.T, vals []struct{ k, v string }) { + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + for _, val := range vals { + trie.Update([]byte(val.k), []byte(val.v)) + } + for _, val := range vals { + trie.Delete([]byte(val.k)) + } + if len(trie.tracer.inserts) != 0 { + t.Fatal("Unexpected insertion set") + } + if len(trie.tracer.deletes) != 0 { + t.Fatal("Unexpected deletion set") + } +} + +// Tests if the accessList is correctly tracked. +func TestAccessList(t *testing.T) { + testAccessList(t, tiny) + testAccessList(t, nonAligned) + testAccessList(t, standard) +} + +func testAccessList(t *testing.T, vals []struct{ k, v string }) { + var ( + db = NewDatabase(rawdb.NewMemoryDatabase()) + trie = NewEmpty(db) + orig = trie.Copy() + ) + // Create trie from scratch + for _, val := range vals { + trie.Update([]byte(val.k), []byte(val.v)) + } + root, nodes := trie.Commit(false) + db.Update(NewWithNodeSet(nodes)) + + trie, _ = New(TrieID(root), db) + if err := verifyAccessList(orig, trie, nodes); err != nil { + t.Fatalf("Invalid accessList %v", err) + } + + // Update trie + trie, _ = New(TrieID(root), db) + orig = trie.Copy() + for _, val := range vals { + trie.Update([]byte(val.k), randBytes(32)) + } + root, nodes = trie.Commit(false) + db.Update(NewWithNodeSet(nodes)) + + trie, _ = New(TrieID(root), db) + if err := verifyAccessList(orig, trie, nodes); err != nil { + t.Fatalf("Invalid accessList %v", err) + } + + // Add more new nodes + trie, _ = New(TrieID(root), db) + orig = trie.Copy() + var keys []string + for i := 0; i < 30; i++ { + key := randBytes(32) + keys = append(keys, string(key)) + trie.Update(key, randBytes(32)) + } + root, nodes = trie.Commit(false) + db.Update(NewWithNodeSet(nodes)) + + trie, _ = New(TrieID(root), db) + if err := verifyAccessList(orig, trie, nodes); err != nil { + t.Fatalf("Invalid accessList %v", err) + } + + // Partial deletions + trie, _ = New(TrieID(root), db) + orig = trie.Copy() + for _, key := range keys { + trie.Update([]byte(key), nil) + } + root, nodes = trie.Commit(false) + db.Update(NewWithNodeSet(nodes)) + + trie, _ = New(TrieID(root), db) + if err := verifyAccessList(orig, trie, nodes); err != nil { + t.Fatalf("Invalid accessList %v", err) + } + + // Delete all + trie, _ = New(TrieID(root), db) + orig = trie.Copy() + for _, val := range vals { + trie.Update([]byte(val.k), nil) + } + root, nodes = trie.Commit(false) + db.Update(NewWithNodeSet(nodes)) + + trie, _ = New(TrieID(root), db) + if err := verifyAccessList(orig, trie, nodes); err != nil { + t.Fatalf("Invalid accessList %v", err) + } +} + +// Tests origin values won't be tracked in Iterator or Prover +func TestAccessListLeak(t *testing.T) { + var ( + db = NewDatabase(rawdb.NewMemoryDatabase()) + trie = NewEmpty(db) + ) + // Create trie from scratch + for _, val := range standard { + trie.Update([]byte(val.k), []byte(val.v)) + } + root, nodes := trie.Commit(false) + db.Update(NewWithNodeSet(nodes)) + + var cases = []struct { + op func(tr *Trie) + }{ + { + func(tr *Trie) { + it := tr.NodeIterator(nil) + for it.Next(true) { + } + }, + }, + { + func(tr *Trie) { + it := NewIterator(tr.NodeIterator(nil)) + for it.Next() { + } + }, + }, + { + func(tr *Trie) { + for _, val := range standard { + tr.Prove([]byte(val.k), 0, rawdb.NewMemoryDatabase()) + } + }, + }, + } + for _, c := range cases { + trie, _ = New(TrieID(root), db) + n1 := len(trie.tracer.accessList) + c.op(trie) + n2 := len(trie.tracer.accessList) + + if n1 != n2 { + t.Fatalf("AccessList is leaked, prev %d after %d", n1, n2) + } + } +} + +// Tests whether the original tree node is correctly deleted after being embedded +// in its parent due to the smaller size of the original tree node. +func TestTinyTree(t *testing.T) { + var ( + db = NewDatabase(rawdb.NewMemoryDatabase()) + trie = NewEmpty(db) + ) + for _, val := range tiny { + trie.Update([]byte(val.k), randBytes(32)) + } + root, set := trie.Commit(false) + db.Update(NewWithNodeSet(set)) + + trie, _ = New(TrieID(root), db) + orig := trie.Copy() + for _, val := range tiny { + trie.Update([]byte(val.k), []byte(val.v)) + } + root, set = trie.Commit(false) + db.Update(NewWithNodeSet(set)) + + trie, _ = New(TrieID(root), db) + if err := verifyAccessList(orig, trie, set); err != nil { + t.Fatalf("Invalid accessList %v", err) + } +} + +func compareSet(setA, setB map[string]struct{}) bool { + if len(setA) != len(setB) { + return false + } + for key := range setA { + if _, ok := setB[key]; !ok { + return false + } + } + return true +} + +func forNodes(tr *Trie) map[string][]byte { + var ( + it = tr.NodeIterator(nil) + nodes = make(map[string][]byte) + ) + for it.Next(true) { + if it.Leaf() { + continue + } + nodes[string(it.Path())] = common.CopyBytes(it.NodeBlob()) + } + return nodes +} + +func iterNodes(db *Database, root common.Hash) map[string][]byte { + tr, _ := New(TrieID(root), db) + return forNodes(tr) +} + +func forHashedNodes(tr *Trie) map[string][]byte { + var ( + it = tr.NodeIterator(nil) + nodes = make(map[string][]byte) + ) + for it.Next(true) { + if it.Hash() == (common.Hash{}) { + continue + } + nodes[string(it.Path())] = common.CopyBytes(it.NodeBlob()) + } + return nodes +} + +func diffTries(trieA, trieB *Trie) (map[string][]byte, map[string][]byte, map[string][]byte) { + var ( + nodesA = forHashedNodes(trieA) + nodesB = forHashedNodes(trieB) + inA = make(map[string][]byte) // hashed nodes in trie a but not b + inB = make(map[string][]byte) // hashed nodes in trie b but not a + both = make(map[string][]byte) // hashed nodes in both tries but different value + ) + for path, blobA := range nodesA { + if blobB, ok := nodesB[path]; ok { + if bytes.Equal(blobA, blobB) { + continue + } + both[path] = blobA + continue + } + inA[path] = blobA + } + for path, blobB := range nodesB { + if _, ok := nodesA[path]; ok { + continue + } + inB[path] = blobB + } + return inA, inB, both +} + +func setKeys(set map[string][]byte) map[string]struct{} { + keys := make(map[string]struct{}) + for k := range set { + keys[k] = struct{}{} + } + return keys +} + +func copySet(set map[string]struct{}) map[string]struct{} { + copied := make(map[string]struct{}) + for k := range set { + copied[k] = struct{}{} + } + return copied +} diff --git a/trie/trie.go b/trie/trie.go index c467ac47662..17bacba00fd 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -23,18 +23,10 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) -var ( - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // emptyState is the known hash of an empty state trie entry. - emptyState = crypto.Keccak256Hash(nil) -) - // Trie is a Merkle Patricia Trie. Use New to create a trie that sits on // top of a database. Whenever trie performs a commit operation, the generated // nodes will be gathered and returned in a set. Once the trie is committed, @@ -89,9 +81,9 @@ func New(id *ID, db NodeReader) (*Trie, error) { trie := &Trie{ owner: id.Owner, reader: reader, - //tracer: newTracer(), + tracer: newTracer(), } - if id.Root != (common.Hash{}) && id.Root != emptyRoot { + if id.Root != (common.Hash{}) && id.Root != types.EmptyRootHash { rootnode, err := trie.resolveAndTrack(id.Root[:], nil) if err != nil { return nil, err @@ -555,7 +547,7 @@ func (t *Trie) resolveAndTrack(n hashNode, prefix []byte) (node, error) { // Hash returns the root hash of the trie. It does not write to the // database and can be used even if the trie doesn't have one. func (t *Trie) Hash() common.Hash { - hash, cached, _ := t.hashRoot() + hash, cached := t.hashRoot() t.root = cached return common.BytesToHash(hash.(hashNode)) } @@ -569,14 +561,14 @@ func (t *Trie) Hash() common.Hash { func (t *Trie) Commit(collectLeaf bool) (common.Hash, *NodeSet) { defer t.tracer.reset() + nodes := NewNodeSet(t.owner, t.tracer.accessList) + t.tracer.markDeletions(nodes) + // Trie is empty and can be classified into two types of situations: // - The trie was empty and no update happens // - The trie was non-empty and all nodes are dropped if t.root == nil { - // Wrap tracked deletions as the return - set := NewNodeSet(t.owner) - t.tracer.markDeletions(set) - return emptyRoot, set + return types.EmptyRootHash, nodes } // Derive the hash for all dirty nodes first. We hold the assumption // in the following procedure that all nodes are hashed. @@ -590,23 +582,23 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *NodeSet) { t.root = hashedNode return rootHash, nil } - h := newCommitter(t.owner, t.tracer, collectLeaf) - newRoot, nodes := h.Commit(t.root) - t.root = newRoot + t.root = newCommitter(nodes, collectLeaf).Commit(t.root) return rootHash, nodes } // hashRoot calculates the root hash of the given trie -func (t *Trie) hashRoot() (node, node, error) { +func (t *Trie) hashRoot() (node, node) { if t.root == nil { - return hashNode(emptyRoot.Bytes()), nil, nil + return hashNode(types.EmptyRootHash.Bytes()), nil } // If the number of changes is below 100, we let one thread handle it h := newHasher(t.unhashed >= 100) - defer returnHasherToPool(h) + defer func() { + returnHasherToPool(h) + t.unhashed = 0 + }() hashed, cached := h.hash(t.root, true) - t.unhashed = 0 - return hashed, cached, nil + return hashed, cached } // Reset drops the referenced root node and cleans all internal state. diff --git a/trie/trie_test.go b/trie/trie_test.go index ece19fdff10..e415937073e 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -18,6 +18,7 @@ package trie import ( "bytes" + crand "crypto/rand" "encoding/binary" "errors" "fmt" @@ -46,7 +47,7 @@ func init() { func TestEmptyTrie(t *testing.T) { trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) res := trie.Hash() - exp := emptyRoot + exp := types.EmptyRootHash if res != exp { t.Errorf("expected %x got %x", exp, res) } @@ -402,6 +403,51 @@ func (randTest) Generate(r *rand.Rand, size int) reflect.Value { return reflect.ValueOf(steps) } +func verifyAccessList(old *Trie, new *Trie, set *NodeSet) error { + deletes, inserts, updates := diffTries(old, new) + + // Check insertion set + for path := range inserts { + n, ok := set.nodes[path] + if !ok || n.isDeleted() { + return errors.New("expect new node") + } + _, ok = set.accessList[path] + if ok { + return errors.New("unexpected origin value") + } + } + // Check deletion set + for path, blob := range deletes { + n, ok := set.nodes[path] + if !ok || !n.isDeleted() { + return errors.New("expect deleted node") + } + v, ok := set.accessList[path] + if !ok { + return errors.New("expect origin value") + } + if !bytes.Equal(v, blob) { + return errors.New("invalid origin value") + } + } + // Check update set + for path, blob := range updates { + n, ok := set.nodes[path] + if !ok || n.isDeleted() { + return errors.New("expect updated node") + } + v, ok := set.accessList[path] + if !ok { + return errors.New("expect origin value") + } + if !bytes.Equal(v, blob) { + return errors.New("invalid origin value") + } + } + return nil +} + func runRandTest(rt randTest) bool { var ( triedb = NewDatabase(rawdb.NewMemoryDatabase()) @@ -409,8 +455,6 @@ func runRandTest(rt randTest) bool { values = make(map[string]string) // tracks content of the trie origTrie = NewEmpty(triedb) ) - tr.tracer = newTracer() - for i, step := range rt { // fmt.Printf("{op: %d, key: common.Hex2Bytes(\"%x\"), value: common.Hex2Bytes(\"%x\")}, // step %d\n", // step.op, step.key, step.value, i) @@ -430,7 +474,7 @@ func runRandTest(rt randTest) bool { } case opProve: hash := tr.Hash() - if hash == emptyRoot { + if hash == types.EmptyRootHash { continue } proofDb := rawdb.NewMemoryDatabase() @@ -446,24 +490,6 @@ func runRandTest(rt randTest) bool { tr.Hash() case opCommit: root, nodes := tr.Commit(true) - // Validity the returned nodeset - if nodes != nil { - for path, node := range nodes.updates.nodes { - blob, _, _ := origTrie.TryGetNode(hexToCompact([]byte(path))) - got := node.prev - if !bytes.Equal(blob, got) { - rt[i].err = fmt.Errorf("prevalue mismatch for 0x%x, got 0x%x want 0x%x", path, got, blob) - panic(rt[i].err) - } - } - for path, prev := range nodes.deletes { - blob, _, _ := origTrie.TryGetNode(hexToCompact([]byte(path))) - if !bytes.Equal(blob, prev) { - rt[i].err = fmt.Errorf("prevalue mismatch for 0x%x, got 0x%x want 0x%x", path, prev, blob) - return false - } - } - } if nodes != nil { triedb.Update(NewWithNodeSet(nodes)) } @@ -472,13 +498,13 @@ func runRandTest(rt randTest) bool { rt[i].err = err return false } + if nodes != nil { + if err := verifyAccessList(origTrie, newtr, nodes); err != nil { + rt[i].err = err + return false + } + } tr = newtr - - // Enable node tracing. Resolve the root node again explicitly - // since it's not captured at the beginning. - tr.tracer = newTracer() - tr.resolveAndTrack(root.Bytes(), nil) - origTrie = tr.Copy() case opItercheckhash: checktr := NewEmpty(triedb) @@ -491,8 +517,6 @@ func runRandTest(rt randTest) bool { } case opNodeDiff: var ( - inserted = tr.tracer.insertList() - deleted = tr.tracer.deleteList() origIter = origTrie.NodeIterator(nil) curIter = tr.NodeIterator(nil) origSeen = make(map[string]struct{}) @@ -526,19 +550,19 @@ func runRandTest(rt randTest) bool { deleteExp[path] = struct{}{} } } - if len(insertExp) != len(inserted) { + if len(insertExp) != len(tr.tracer.inserts) { rt[i].err = fmt.Errorf("insert set mismatch") } - if len(deleteExp) != len(deleted) { + if len(deleteExp) != len(tr.tracer.deletes) { rt[i].err = fmt.Errorf("delete set mismatch") } - for _, insert := range inserted { - if _, present := insertExp[string(insert)]; !present { + for insert := range tr.tracer.inserts { + if _, present := insertExp[insert]; !present { rt[i].err = fmt.Errorf("missing inserted node") } } - for _, del := range deleted { - if _, present := deleteExp[string(del)]; !present { + for del := range tr.tracer.deletes { + if _, present := deleteExp[del]; !present { rt[i].err = fmt.Errorf("missing deleted node") } } @@ -717,7 +741,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { for i := 0; i < len(accounts); i++ { var ( nonce = uint64(random.Int63()) - root = emptyRoot + root = types.EmptyRootHash code = crypto.Keccak256(nil) ) // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, @@ -1127,8 +1151,8 @@ func TestDecodeNode(t *testing.T) { elems = make([]byte, 20) ) for i := 0; i < 5000000; i++ { - rand.Read(hash) - rand.Read(elems) + crand.Read(hash) + crand.Read(elems) decodeNode(hash, elems) } } diff --git a/trie/util_test.go b/trie/util_test.go deleted file mode 100644 index 01a46553aa6..00000000000 --- a/trie/util_test.go +++ /dev/null @@ -1,304 +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 trie - -import ( - "bytes" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" -) - -// Tests if the trie diffs are tracked correctly. -func TestTrieTracer(t *testing.T) { - db := NewDatabase(rawdb.NewMemoryDatabase()) - trie := NewEmpty(db) - trie.tracer = newTracer() - - // Insert a batch of entries, all the nodes should be marked as inserted - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"dog", "puppy"}, - {"somethingveryoddindeedthis is", "myothernodedata"}, - } - for _, val := range vals { - trie.Update([]byte(val.k), []byte(val.v)) - } - trie.Hash() - - seen := make(map[string]struct{}) - it := trie.NodeIterator(nil) - for it.Next(true) { - if it.Leaf() { - continue - } - seen[string(it.Path())] = struct{}{} - } - inserted := trie.tracer.insertList() - if len(inserted) != len(seen) { - t.Fatalf("Unexpected inserted node tracked want %d got %d", len(seen), len(inserted)) - } - for _, k := range inserted { - _, ok := seen[string(k)] - if !ok { - t.Fatalf("Unexpected inserted node") - } - } - deleted := trie.tracer.deleteList() - if len(deleted) != 0 { - t.Fatalf("Unexpected deleted node tracked %d", len(deleted)) - } - - // Commit the changes and re-create with new root - root, nodes := trie.Commit(false) - if err := db.Update(NewWithNodeSet(nodes)); err != nil { - t.Fatal(err) - } - trie, _ = New(TrieID(root), db) - trie.tracer = newTracer() - - // Delete all the elements, check deletion set - for _, val := range vals { - trie.Delete([]byte(val.k)) - } - trie.Hash() - - inserted = trie.tracer.insertList() - if len(inserted) != 0 { - t.Fatalf("Unexpected inserted node tracked %d", len(inserted)) - } - deleted = trie.tracer.deleteList() - if len(deleted) != len(seen) { - t.Fatalf("Unexpected deleted node tracked want %d got %d", len(seen), len(deleted)) - } - for _, k := range deleted { - _, ok := seen[string(k)] - if !ok { - t.Fatalf("Unexpected inserted node") - } - } -} - -func TestTrieTracerNoop(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) - trie.tracer = newTracer() - - // Insert a batch of entries, all the nodes should be marked as inserted - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"dog", "puppy"}, - {"somethingveryoddindeedthis is", "myothernodedata"}, - } - for _, val := range vals { - trie.Update([]byte(val.k), []byte(val.v)) - } - for _, val := range vals { - trie.Delete([]byte(val.k)) - } - if len(trie.tracer.insertList()) != 0 { - t.Fatalf("Unexpected inserted node tracked %d", len(trie.tracer.insertList())) - } - if len(trie.tracer.deleteList()) != 0 { - t.Fatalf("Unexpected deleted node tracked %d", len(trie.tracer.deleteList())) - } -} - -func TestTrieTracePrevValue(t *testing.T) { - db := NewDatabase(rawdb.NewMemoryDatabase()) - trie := NewEmpty(db) - trie.tracer = newTracer() - - paths, blobs := trie.tracer.prevList() - if len(paths) != 0 || len(blobs) != 0 { - t.Fatalf("Nothing should be tracked") - } - // Insert a batch of entries, all the nodes should be marked as inserted - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"dog", "puppy"}, - {"somethingveryoddindeedthis is", "myothernodedata"}, - } - for _, val := range vals { - trie.Update([]byte(val.k), []byte(val.v)) - } - paths, blobs = trie.tracer.prevList() - if len(paths) != 0 || len(blobs) != 0 { - t.Fatalf("Nothing should be tracked") - } - - // Commit the changes and re-create with new root - root, nodes := trie.Commit(false) - if err := db.Update(NewWithNodeSet(nodes)); err != nil { - t.Fatal(err) - } - trie, _ = New(TrieID(root), db) - trie.tracer = newTracer() - trie.resolveAndTrack(root.Bytes(), nil) - - // Load all nodes in trie - for _, val := range vals { - trie.TryGet([]byte(val.k)) - } - - // Ensure all nodes are tracked by tracer with correct prev-values - iter := trie.NodeIterator(nil) - seen := make(map[string][]byte) - for iter.Next(true) { - // Embedded nodes are ignored since they are not present in - // database. - if iter.Hash() == (common.Hash{}) { - continue - } - seen[string(iter.Path())] = common.CopyBytes(iter.NodeBlob()) - } - - paths, blobs = trie.tracer.prevList() - if len(paths) != len(seen) || len(blobs) != len(seen) { - t.Fatalf("Unexpected tracked values") - } - for i, path := range paths { - blob := blobs[i] - prev, ok := seen[string(path)] - if !ok { - t.Fatalf("Missing node %v", path) - } - if !bytes.Equal(blob, prev) { - t.Fatalf("Unexpected value path: %v, want: %v, got: %v", path, prev, blob) - } - } - - // Re-open the trie and iterate the trie, ensure nothing will be tracked. - // Iterator will not link any loaded nodes to trie. - trie, _ = New(TrieID(root), db) - trie.tracer = newTracer() - - iter = trie.NodeIterator(nil) - for iter.Next(true) { - } - paths, blobs = trie.tracer.prevList() - if len(paths) != 0 || len(blobs) != 0 { - t.Fatalf("Nothing should be tracked") - } - - // Re-open the trie and generate proof for entries, ensure nothing will - // be tracked. Prover will not link any loaded nodes to trie. - trie, _ = New(TrieID(root), db) - trie.tracer = newTracer() - for _, val := range vals { - trie.Prove([]byte(val.k), 0, rawdb.NewMemoryDatabase()) - } - paths, blobs = trie.tracer.prevList() - if len(paths) != 0 || len(blobs) != 0 { - t.Fatalf("Nothing should be tracked") - } - - // Delete entries from trie, ensure all previous values are correct. - trie, _ = New(TrieID(root), db) - trie.tracer = newTracer() - trie.resolveAndTrack(root.Bytes(), nil) - - for _, val := range vals { - trie.TryDelete([]byte(val.k)) - } - paths, blobs = trie.tracer.prevList() - if len(paths) != len(seen) || len(blobs) != len(seen) { - t.Fatalf("Unexpected tracked values") - } - for i, path := range paths { - blob := blobs[i] - prev, ok := seen[string(path)] - if !ok { - t.Fatalf("Missing node %v", path) - } - if !bytes.Equal(blob, prev) { - t.Fatalf("Unexpected value path: %v, want: %v, got: %v", path, prev, blob) - } - } -} - -func TestDeleteAll(t *testing.T) { - db := NewDatabase(rawdb.NewMemoryDatabase()) - trie := NewEmpty(db) - trie.tracer = newTracer() - - // Insert a batch of entries, all the nodes should be marked as inserted - vals := []struct{ k, v string }{ - {"do", "verb"}, - {"ether", "wookiedoo"}, - {"horse", "stallion"}, - {"shaman", "horse"}, - {"doge", "coin"}, - {"dog", "puppy"}, - {"somethingveryoddindeedthis is", "myothernodedata"}, - } - for _, val := range vals { - trie.Update([]byte(val.k), []byte(val.v)) - } - root, set := trie.Commit(false) - if err := db.Update(NewWithNodeSet(set)); err != nil { - t.Fatal(err) - } - // Delete entries from trie, ensure all values are detected - trie, _ = New(TrieID(root), db) - trie.tracer = newTracer() - trie.resolveAndTrack(root.Bytes(), nil) - - // Iterate all existent nodes - var ( - it = trie.NodeIterator(nil) - nodes = make(map[string][]byte) - ) - for it.Next(true) { - if it.Hash() != (common.Hash{}) { - nodes[string(it.Path())] = common.CopyBytes(it.NodeBlob()) - } - } - - // Perform deletion to purge the entire trie - for _, val := range vals { - trie.Delete([]byte(val.k)) - } - root, set = trie.Commit(false) - if root != emptyRoot { - t.Fatalf("Invalid trie root %v", root) - } - for path, blob := range set.deletes { - prev, ok := nodes[path] - if !ok { - t.Fatalf("Extra node deleted %v", []byte(path)) - } - if !bytes.Equal(prev, blob) { - t.Fatalf("Unexpected previous value %v", []byte(path)) - } - } - if len(set.deletes) != len(nodes) { - t.Fatalf("Unexpected deletion set") - } -} diff --git a/trie/utils.go b/trie/utils.go deleted file mode 100644 index 5dce65cd297..00000000000 --- a/trie/utils.go +++ /dev/null @@ -1,199 +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 trie - -// tracer tracks the changes of trie nodes. During the trie operations, -// some nodes can be deleted from the trie, while these deleted nodes -// won't be captured by trie.Hasher or trie.Committer. Thus, these deleted -// nodes won't be removed from the disk at all. Tracer is an auxiliary tool -// used to track all insert and delete operations of trie and capture all -// deleted nodes eventually. -// -// The changed nodes can be mainly divided into two categories: the leaf -// node and intermediate node. The former is inserted/deleted by callers -// while the latter is inserted/deleted in order to follow the rule of trie. -// This tool can track all of them no matter the node is embedded in its -// parent or not, but valueNode is never tracked. -// -// Besides, it's also used for recording the original value of the nodes -// when they are resolved from the disk. The pre-value of the nodes will -// be used to construct reverse-diffs in the future. -// -// Note tracer is not thread-safe, callers should be responsible for handling -// the concurrency issues by themselves. -type tracer struct { - insert map[string]struct{} - delete map[string]struct{} - origin map[string][]byte -} - -// newTracer initializes the tracer for capturing trie changes. -func newTracer() *tracer { - return &tracer{ - insert: make(map[string]struct{}), - delete: make(map[string]struct{}), - origin: make(map[string][]byte), - } -} - -// onRead tracks the newly loaded trie node and caches the rlp-encoded blob internally. -// Don't change the value outside of function since it's not deep-copied. -func (t *tracer) onRead(path []byte, val []byte) { - // Tracer isn't used right now, remove this check later. - if t == nil { - return - } - t.origin[string(path)] = val -} - -// onInsert tracks the newly inserted trie node. If it's already in the deletion set -// (resurrected node), then just wipe it from the deletion set as the "untouched". -func (t *tracer) onInsert(path []byte) { - // Tracer isn't used right now, remove this check later. - if t == nil { - return - } - if _, present := t.delete[string(path)]; present { - delete(t.delete, string(path)) - return - } - t.insert[string(path)] = struct{}{} -} - -// onDelete tracks the newly deleted trie node. If it's already -// in the addition set, then just wipe it from the addition set -// as it's untouched. -func (t *tracer) onDelete(path []byte) { - // Tracer isn't used right now, remove this check later. - if t == nil { - return - } - if _, present := t.insert[string(path)]; present { - delete(t.insert, string(path)) - return - } - t.delete[string(path)] = struct{}{} -} - -// insertList returns the tracked inserted trie nodes in list format. -func (t *tracer) insertList() [][]byte { - // Tracer isn't used right now, remove this check later. - if t == nil { - return nil - } - var ret [][]byte - for path := range t.insert { - ret = append(ret, []byte(path)) - } - return ret -} - -// deleteList returns the tracked deleted trie nodes in list format. -func (t *tracer) deleteList() [][]byte { - // Tracer isn't used right now, remove this check later. - if t == nil { - return nil - } - var ret [][]byte - for path := range t.delete { - ret = append(ret, []byte(path)) - } - return ret -} - -// prevList returns the tracked node blobs in list format. -func (t *tracer) prevList() ([][]byte, [][]byte) { - // Tracer isn't used right now, remove this check later. - if t == nil { - return nil, nil - } - var ( - paths [][]byte - blobs [][]byte - ) - for path, blob := range t.origin { - paths = append(paths, []byte(path)) - blobs = append(blobs, blob) - } - return paths, blobs -} - -// getPrev returns the cached original value of the specified node. -func (t *tracer) getPrev(path []byte) []byte { - // Tracer isn't used right now, remove this check later. - if t == nil { - return nil - } - return t.origin[string(path)] -} - -// reset clears the content tracked by tracer. -func (t *tracer) reset() { - // Tracer isn't used right now, remove this check later. - if t == nil { - return - } - t.insert = make(map[string]struct{}) - t.delete = make(map[string]struct{}) - t.origin = make(map[string][]byte) -} - -// copy returns a deep copied tracer instance. -func (t *tracer) copy() *tracer { - // Tracer isn't used right now, remove this check later. - if t == nil { - return nil - } - var ( - insert = make(map[string]struct{}) - delete = make(map[string]struct{}) - origin = make(map[string][]byte) - ) - for key := range t.insert { - insert[key] = struct{}{} - } - for key := range t.delete { - delete[key] = struct{}{} - } - for key, val := range t.origin { - origin[key] = val - } - return &tracer{ - insert: insert, - delete: delete, - origin: origin, - } -} - -// markDeletions puts all tracked deletions into the provided nodeset. -func (t *tracer) markDeletions(set *NodeSet) { - // Tracer isn't used right now, remove this check later. - if t == nil { - return - } - for _, path := range t.deleteList() { - // There are a few possibilities for this scenario(the node is deleted - // but not present in database previously), for example the node was - // embedded in the parent and now deleted from the trie. In this case - // it's noop from database's perspective. - val := t.getPrev(path) - if len(val) == 0 { - continue - } - set.markDeleted(path, val) - } -}