diff --git a/accounts/keystore/watch.go b/accounts/keystore/watch.go
index ad176040d..d6ef53327 100644
--- a/accounts/keystore/watch.go
+++ b/accounts/keystore/watch.go
@@ -14,7 +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 (darwin && !ios && cgo) || freebsd || (linux && !arm64) || netbsd || solaris
// +build darwin,!ios,cgo freebsd linux,!arm64 netbsd solaris
package keystore
diff --git a/accounts/keystore/watch_fallback.go b/accounts/keystore/watch_fallback.go
index e40eca42f..de0e87f8a 100644
--- a/accounts/keystore/watch_fallback.go
+++ b/accounts/keystore/watch_fallback.go
@@ -14,7 +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 (darwin && !cgo) || ios || (linux && arm64) || windows || (!darwin && !freebsd && !linux && !netbsd && !solaris)
// +build darwin,!cgo ios linux,arm64 windows !darwin,!freebsd,!linux,!netbsd,!solaris
// This is the fallback implementation of directory watching.
diff --git a/build/ci.go b/build/ci.go
index eca7e46e8..df1cb50ab 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -14,7 +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 none
// +build none
/*
diff --git a/build/update-license.go b/build/update-license.go
index 5a98304fc..aa4d6100d 100644
--- a/build/update-license.go
+++ b/build/update-license.go
@@ -14,7 +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 none
// +build none
/*
diff --git a/cmd/evm/disasm.go b/cmd/evm/disasm.go
index 68a09cbf5..f9719497f 100644
--- a/cmd/evm/disasm.go
+++ b/cmd/evm/disasm.go
@@ -46,7 +46,7 @@ func disasmCmd(ctx *cli.Context) error {
case ctx.GlobalIsSet(InputFlag.Name):
in = ctx.GlobalString(InputFlag.Name)
default:
- return errors.New("Missing filename or --input value")
+ return errors.New("missing filename or --input value")
}
code := strings.TrimSpace(in)
diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go
index 0471037ed..aadebdd43 100644
--- a/cmd/evm/internal/t8ntool/execution.go
+++ b/cmd/evm/internal/t8ntool/execution.go
@@ -82,7 +82,7 @@ type stEnvMarshaling struct {
// Apply applies a set of transactions to a pre-state
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
txs types.Transactions, miningReward int64,
- getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.Tracer, err error)) (*state.StateDB, *ExecutionResult, error) {
+ getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) {
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
// required blockhashes
@@ -223,7 +223,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
statedb.AddBalance(pre.Env.Coinbase, minerReward)
}
// Commit block
- root, _, err := statedb.Commit(chainConfig.IsEIP158(vmContext.BlockNumber))
+ statedb.Finalise(chainConfig.IsEIP158(vmContext.BlockNumber))
+ statedb.AccountsIntermediateRoot()
+ root, _, err := statedb.Commit(nil)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not commit state: %v", err)
return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
@@ -252,7 +254,9 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
}
}
// Commit and re-open to start with a clean state.
- root, _, _ := statedb.Commit(false)
+ statedb.Finalise(false)
+ statedb.AccountsIntermediateRoot()
+ root, _, _ := statedb.Commit(nil)
statedb, _ = state.New(root, sdb, nil)
return statedb
}
diff --git a/cmd/evm/internal/t8ntool/flags.go b/cmd/evm/internal/t8ntool/flags.go
index a599462cc..a3ba9acc2 100644
--- a/cmd/evm/internal/t8ntool/flags.go
+++ b/cmd/evm/internal/t8ntool/flags.go
@@ -30,7 +30,7 @@ var (
Name: "trace",
Usage: "Output full trace logs to files .jsonl",
}
- TraceDisableMemoryFlag = cli.BoolFlag{
+ TraceDisableMemoryFlag = cli.BoolTFlag{
Name: "trace.nomemory",
Usage: "Disable full memory dump in traces",
}
@@ -38,7 +38,7 @@ var (
Name: "trace.nostack",
Usage: "Disable stack output in traces",
}
- TraceDisableReturnDataFlag = cli.BoolFlag{
+ TraceDisableReturnDataFlag = cli.BoolTFlag{
Name: "trace.noreturndata",
Usage: "Disable return data output in traces",
}
diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go
index fedcd1243..f5c0dd42f 100644
--- a/cmd/evm/internal/t8ntool/transition.go
+++ b/cmd/evm/internal/t8ntool/transition.go
@@ -81,10 +81,10 @@ func Main(ctx *cli.Context) error {
var (
err error
- tracer vm.Tracer
+ tracer vm.EVMLogger
baseDir = ""
)
- var getTracer func(txIndex int, txHash common.Hash) (vm.Tracer, error)
+ var getTracer func(txIndex int, txHash common.Hash) (vm.EVMLogger, error)
// If user specified a basedir, make sure it exists
if ctx.IsSet(OutputBasedir.Name) {
@@ -99,10 +99,10 @@ func Main(ctx *cli.Context) error {
if ctx.Bool(TraceFlag.Name) {
// Configure the EVM logger
logConfig := &vm.LogConfig{
- DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
- DisableMemory: ctx.Bool(TraceDisableMemoryFlag.Name),
- DisableReturnData: ctx.Bool(TraceDisableReturnDataFlag.Name),
- Debug: true,
+ DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
+ EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name),
+ EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name),
+ Debug: true,
}
var prevFile *os.File
// This one closes the last file
@@ -111,7 +111,7 @@ func Main(ctx *cli.Context) error {
prevFile.Close()
}
}()
- getTracer = func(txIndex int, txHash common.Hash) (vm.Tracer, error) {
+ getTracer = func(txIndex int, txHash common.Hash) (vm.EVMLogger, error) {
if prevFile != nil {
prevFile.Close()
}
@@ -123,7 +123,7 @@ func Main(ctx *cli.Context) error {
return vm.NewJSONLogger(logConfig, traceFile), nil
}
} else {
- getTracer = func(txIndex int, txHash common.Hash) (tracer vm.Tracer, err error) {
+ getTracer = func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error) {
return nil, nil
}
}
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index 8a3e4e0ea..d78970e7d 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -113,7 +113,7 @@ var (
Name: "receiver",
Usage: "The transaction receiver (execution context)",
}
- DisableMemoryFlag = cli.BoolFlag{
+ DisableMemoryFlag = cli.BoolTFlag{
Name: "nomemory",
Usage: "disable memory output",
}
@@ -125,9 +125,9 @@ var (
Name: "nostorage",
Usage: "disable storage output",
}
- DisableReturnDataFlag = cli.BoolFlag{
+ DisableReturnDataFlag = cli.BoolTFlag{
Name: "noreturndata",
- Usage: "disable return data output",
+ Usage: "enable return data output",
}
EVMInterpreterFlag = cli.StringFlag{
Name: "vm.evm",
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index 4063767cb..fd1827018 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -108,15 +108,15 @@ func runCmd(ctx *cli.Context) error {
glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
log.Root().SetHandler(glogger)
logconfig := &vm.LogConfig{
- DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name),
- DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
- DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name),
- DisableReturnData: ctx.GlobalBool(DisableReturnDataFlag.Name),
- Debug: ctx.GlobalBool(DebugFlag.Name),
+ EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name),
+ DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
+ DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name),
+ EnableReturnData: !ctx.GlobalBool(DisableReturnDataFlag.Name),
+ Debug: ctx.GlobalBool(DebugFlag.Name),
}
var (
- tracer vm.Tracer
+ tracer vm.EVMLogger
debugLogger *vm.StructLogger
statedb *state.StateDB
chainConfig *params.ChainConfig
@@ -268,7 +268,9 @@ func runCmd(ctx *cli.Context) error {
output, leftOverGas, stats, err := timedExec(bench, execFunc)
if ctx.GlobalBool(DumpFlag.Name) {
- statedb.Commit(true)
+ statedb.Finalise(true)
+ statedb.AccountsIntermediateRoot()
+ statedb.Commit(nil)
statedb.IntermediateRoot(true)
fmt.Println(string(statedb.Dump(false, false, true)))
}
diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go
index c4df936c7..c373772fb 100644
--- a/cmd/evm/staterunner.go
+++ b/cmd/evm/staterunner.go
@@ -59,13 +59,13 @@ func stateTestCmd(ctx *cli.Context) error {
// Configure the EVM logger
config := &vm.LogConfig{
- DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name),
- DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
- DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name),
- DisableReturnData: ctx.GlobalBool(DisableReturnDataFlag.Name),
+ EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name),
+ DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
+ DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name),
+ EnableReturnData: !ctx.GlobalBool(DisableReturnDataFlag.Name),
}
var (
- tracer vm.Tracer
+ tracer vm.EVMLogger
debugger *vm.StructLogger
)
switch {
@@ -101,7 +101,8 @@ func stateTestCmd(ctx *cli.Context) error {
_, state, err := test.Run(st, cfg, false)
// print state root for evmlab tracing
if ctx.GlobalBool(MachineFlag.Name) && state != nil {
- fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false))
+ root := state.IntermediateRoot(false)
+ fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", root)
}
if err != nil {
// Test failed, mark as so and dump any state to aid debugging
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index 1152bfdfd..a30efbbde 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -458,7 +458,7 @@ func importPreimages(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, false)
+ db := utils.MakeChainDatabase(ctx, stack, false, false)
start := time.Now()
if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil {
@@ -477,7 +477,7 @@ func exportPreimages(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, true)
+ db := utils.MakeChainDatabase(ctx, stack, true, false)
start := time.Now()
if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil {
@@ -491,7 +491,7 @@ func dump(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, true)
+ db := utils.MakeChainDatabase(ctx, stack, true, false)
for _, arg := range ctx.Args() {
var header *types.Header
if hashish(arg) {
diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go
index 4c70373e9..2ac8b803c 100644
--- a/cmd/geth/dbcmd.go
+++ b/cmd/geth/dbcmd.go
@@ -62,6 +62,7 @@ Remove blockchain and state databases`,
dbPutCmd,
dbGetSlotsCmd,
dbDumpFreezerIndex,
+ ancientInspectCmd,
},
}
dbInspectCmd = cli.Command{
@@ -195,6 +196,16 @@ WARNING: This is a low-level operation which may cause database corruption!`,
},
Description: "This command displays information about the freezer index.",
}
+ ancientInspectCmd = cli.Command{
+ Action: utils.MigrateFlags(ancientInspect),
+ Name: "inspect-reserved-oldest-blocks",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ },
+ Usage: "Inspect the ancientStore information",
+ Description: `This commands will read current offset from kvdb, which is the current offset and starting BlockNumber
+of ancientStore, will also displays the reserved number of blocks in ancientStore `,
+ }
)
func removeDB(ctx *cli.Context) error {
@@ -282,12 +293,21 @@ func inspect(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, true)
+ db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
return rawdb.InspectDatabase(db, prefix, start)
}
+func ancientInspect(ctx *cli.Context) error {
+ stack, _ := makeConfigNode(ctx)
+ defer stack.Close()
+
+ db := utils.MakeChainDatabase(ctx, stack, true, true)
+ defer db.Close()
+ return rawdb.AncientInspect(db)
+}
+
func showLeveldbStats(db ethdb.Stater) {
if stats, err := db.Stat("leveldb.stats"); err != nil {
log.Warn("Failed to read database stats", "error", err)
@@ -305,7 +325,7 @@ func dbStats(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, true)
+ db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
showLeveldbStats(db)
@@ -316,7 +336,7 @@ func dbCompact(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, false)
+ db := utils.MakeChainDatabase(ctx, stack, false, false)
defer db.Close()
log.Info("Stats before compaction")
@@ -340,7 +360,7 @@ func dbGet(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, true)
+ db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
key, err := hexutil.Decode(ctx.Args().Get(0))
@@ -365,7 +385,7 @@ func dbDelete(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, false)
+ db := utils.MakeChainDatabase(ctx, stack, false, false)
defer db.Close()
key, err := hexutil.Decode(ctx.Args().Get(0))
@@ -392,7 +412,7 @@ func dbPut(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, false)
+ db := utils.MakeChainDatabase(ctx, stack, false, false)
defer db.Close()
var (
@@ -426,7 +446,7 @@ func dbDumpTrie(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- db := utils.MakeChainDatabase(ctx, stack, true)
+ db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
var (
root []byte
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 8be8d20bf..e0f29bce7 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -39,6 +39,11 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
+
+ // Force-load the tracer engines to trigger registration
+ _ "github.com/ethereum/go-ethereum/eth/tracers/js"
+ _ "github.com/ethereum/go-ethereum/eth/tracers/native"
+
"gopkg.in/urfave/cli.v1"
)
@@ -67,6 +72,7 @@ var (
utils.DirectBroadcastFlag,
utils.DisableSnapProtocolFlag,
utils.DiffSyncFlag,
+ utils.PipeCommitFlag,
utils.RangeLimitFlag,
utils.USBFlag,
utils.SmartCardDaemonPathFlag,
@@ -90,6 +96,7 @@ var (
utils.TxPoolAccountQueueFlag,
utils.TxPoolGlobalQueueFlag,
utils.TxPoolLifetimeFlag,
+ utils.TxPoolReannounceTimeFlag,
utils.SyncModeFlag,
utils.ExitWhenSyncedFlag,
utils.GCModeFlag,
@@ -159,6 +166,8 @@ var (
utils.MinerNotifyFullFlag,
configFileFlag,
utils.CatalystFlag,
+ utils.BlockAmountReserved,
+ utils.CheckSnapshotWithMPT,
}
rpcFlags = []cli.Flag{
diff --git a/cmd/geth/pruneblock_test.go b/cmd/geth/pruneblock_test.go
new file mode 100644
index 000000000..7d78f444f
--- /dev/null
+++ b/cmd/geth/pruneblock_test.go
@@ -0,0 +1,242 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package main
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "io/ioutil"
+ "math/big"
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/cmd/utils"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state/pruner"
+ "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/eth"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+var (
+ canonicalSeed = 1
+ blockPruneBackUpBlockNumber = 128
+ key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ address = crypto.PubkeyToAddress(key.PublicKey)
+ balance = big.NewInt(10000000)
+ gspec = &core.Genesis{Config: params.TestChainConfig, Alloc: core.GenesisAlloc{address: {Balance: balance}}}
+ signer = types.LatestSigner(gspec.Config)
+ config = &core.CacheConfig{
+ TrieCleanLimit: 256,
+ TrieDirtyLimit: 256,
+ TrieTimeLimit: 5 * time.Minute,
+ SnapshotLimit: 0, // Disable snapshot
+ TriesInMemory: 128,
+ }
+ engine = ethash.NewFullFaker()
+)
+
+func TestOfflineBlockPrune(t *testing.T) {
+ //Corner case for 0 remain in ancinetStore.
+ testOfflineBlockPruneWithAmountReserved(t, 0)
+ //General case.
+ testOfflineBlockPruneWithAmountReserved(t, 100)
+}
+
+func testOfflineBlockPruneWithAmountReserved(t *testing.T, amountReserved uint64) {
+ datadir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("Failed to create temporary datadir: %v", err)
+ }
+ os.RemoveAll(datadir)
+
+ chaindbPath := filepath.Join(datadir, "chaindata")
+ oldAncientPath := filepath.Join(chaindbPath, "ancient")
+ newAncientPath := filepath.Join(chaindbPath, "ancient_back")
+
+ db, blocks, blockList, receiptsList, externTdList, startBlockNumber, _ := BlockchainCreator(t, chaindbPath, oldAncientPath, amountReserved)
+ node, _ := startEthService(t, gspec, blocks, chaindbPath)
+ defer node.Close()
+
+ //Initialize a block pruner for pruning, only remain amountReserved blocks backward.
+ testBlockPruner := pruner.NewBlockPruner(db, node, oldAncientPath, newAncientPath, amountReserved)
+ if err != nil {
+ t.Fatalf("failed to make new blockpruner: %v", err)
+ }
+ if err := testBlockPruner.BlockPruneBackUp(chaindbPath, 512, utils.MakeDatabaseHandles(), "", false, false); err != nil {
+ t.Fatalf("Failed to back up block: %v", err)
+ }
+
+ dbBack, err := rawdb.NewLevelDBDatabaseWithFreezer(chaindbPath, 0, 0, newAncientPath, "", false, true, false)
+ if err != nil {
+ t.Fatalf("failed to create database with ancient backend")
+ }
+ defer dbBack.Close()
+
+ //check against if the backup data matched original one
+ for blockNumber := startBlockNumber; blockNumber < startBlockNumber+amountReserved; blockNumber++ {
+ blockHash := rawdb.ReadCanonicalHash(dbBack, blockNumber)
+ block := rawdb.ReadBlock(dbBack, blockHash, blockNumber)
+
+ if block.Hash() != blockHash {
+ t.Fatalf("block data did not match between oldDb and backupDb")
+ }
+ if blockList[blockNumber-startBlockNumber].Hash() != blockHash {
+ t.Fatalf("block data did not match between oldDb and backupDb")
+ }
+
+ receipts := rawdb.ReadRawReceipts(dbBack, blockHash, blockNumber)
+ if err := checkReceiptsRLP(receipts, receiptsList[blockNumber-startBlockNumber]); err != nil {
+ t.Fatalf("receipts did not match between oldDb and backupDb")
+ }
+ // // Calculate the total difficulty of the block
+ td := rawdb.ReadTd(dbBack, blockHash, blockNumber)
+ if td == nil {
+ t.Fatalf("Failed to ReadTd: %v", consensus.ErrUnknownAncestor)
+ }
+ if td.Cmp(externTdList[blockNumber-startBlockNumber]) != 0 {
+ t.Fatalf("externTd did not match between oldDb and backupDb")
+ }
+ }
+
+ //check if ancientDb freezer replaced successfully
+ testBlockPruner.AncientDbReplacer()
+ if _, err := os.Stat(newAncientPath); err != nil {
+ if !os.IsNotExist(err) {
+ t.Fatalf("ancientDb replaced unsuccessfully")
+ }
+ }
+ if _, err := os.Stat(oldAncientPath); err != nil {
+ t.Fatalf("ancientDb replaced unsuccessfully")
+ }
+}
+
+func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemain uint64) (ethdb.Database, []*types.Block, []*types.Block, []types.Receipts, []*big.Int, uint64, *core.BlockChain) {
+ //create a database with ancient freezer
+ db, err := rawdb.NewLevelDBDatabaseWithFreezer(chaindbPath, 0, 0, AncientPath, "", false, false, false)
+ if err != nil {
+ t.Fatalf("failed to create database with ancient backend")
+ }
+ defer db.Close()
+ genesis := gspec.MustCommit(db)
+ // Initialize a fresh chain with only a genesis block
+ blockchain, err := core.NewBlockChain(db, config, gspec.Config, engine, vm.Config{}, nil, nil)
+ if err != nil {
+ t.Fatalf("Failed to create chain: %v", err)
+ }
+
+ // Make chain starting from genesis
+ blocks, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 500, func(i int, block *core.BlockGen) {
+ block.SetCoinbase(common.Address{0: byte(canonicalSeed), 19: byte(i)})
+ tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key)
+ if err != nil {
+ panic(err)
+ }
+ block.AddTx(tx)
+ block.SetDifficulty(big.NewInt(1000000))
+ })
+ if _, err := blockchain.InsertChain(blocks); err != nil {
+ t.Fatalf("Failed to import canonical chain start: %v", err)
+ }
+
+ // Force run a freeze cycle
+ type freezer interface {
+ Freeze(threshold uint64) error
+ Ancients() (uint64, error)
+ }
+ db.(freezer).Freeze(10)
+
+ frozen, err := db.Ancients()
+ //make sure there're frozen items
+ if err != nil || frozen == 0 {
+ t.Fatalf("Failed to import canonical chain start: %v", err)
+ }
+ if frozen < blockRemain {
+ t.Fatalf("block amount is not enough for pruning: %v", err)
+ }
+
+ oldOffSet := rawdb.ReadOffSetOfCurrentAncientFreezer(db)
+ // Get the actual start block number.
+ startBlockNumber := frozen - blockRemain + oldOffSet
+ // Initialize the slice to buffer the block data left.
+ blockList := make([]*types.Block, 0, blockPruneBackUpBlockNumber)
+ receiptsList := make([]types.Receipts, 0, blockPruneBackUpBlockNumber)
+ externTdList := make([]*big.Int, 0, blockPruneBackUpBlockNumber)
+ // All ancient data within the most recent 128 blocks write into memory buffer for future new ancient_back directory usage.
+ for blockNumber := startBlockNumber; blockNumber < frozen+oldOffSet; blockNumber++ {
+ blockHash := rawdb.ReadCanonicalHash(db, blockNumber)
+ block := rawdb.ReadBlock(db, blockHash, blockNumber)
+ blockList = append(blockList, block)
+ receipts := rawdb.ReadRawReceipts(db, blockHash, blockNumber)
+ receiptsList = append(receiptsList, receipts)
+ // Calculate the total difficulty of the block
+ td := rawdb.ReadTd(db, blockHash, blockNumber)
+ if td == nil {
+ t.Fatalf("Failed to ReadTd: %v", consensus.ErrUnknownAncestor)
+ }
+ externTdList = append(externTdList, td)
+ }
+
+ return db, blocks, blockList, receiptsList, externTdList, startBlockNumber, blockchain
+}
+
+func checkReceiptsRLP(have, want types.Receipts) error {
+ if len(have) != len(want) {
+ return fmt.Errorf("receipts sizes mismatch: have %d, want %d", len(have), len(want))
+ }
+ for i := 0; i < len(want); i++ {
+ rlpHave, err := rlp.EncodeToBytes(have[i])
+ if err != nil {
+ return err
+ }
+ rlpWant, err := rlp.EncodeToBytes(want[i])
+ if err != nil {
+ return err
+ }
+ if !bytes.Equal(rlpHave, rlpWant) {
+ return fmt.Errorf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant))
+ }
+ }
+ return nil
+}
+
+// startEthService creates a full node instance for testing.
+func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block, chaindbPath string) (*node.Node, *eth.Ethereum) {
+ t.Helper()
+ n, err := node.New(&node.Config{DataDir: chaindbPath})
+ if err != nil {
+ t.Fatal("can't create node:", err)
+ }
+
+ if err := n.Start(); err != nil {
+ t.Fatal("can't start node:", err)
+ }
+
+ return n, nil
+}
diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go
index 2f615a2c1..20920a0f9 100644
--- a/cmd/geth/snapshot.go
+++ b/cmd/geth/snapshot.go
@@ -19,8 +19,14 @@ package main
import (
"bytes"
"errors"
+ "fmt"
+ "os"
+ "path/filepath"
"time"
+ "github.com/prometheus/tsdb/fileutil"
+ cli "gopkg.in/urfave/cli.v1"
+
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
@@ -28,10 +34,11 @@ import (
"github.com/ethereum/go-ethereum/core/state/pruner"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- cli "gopkg.in/urfave/cli.v1"
)
var (
@@ -78,6 +85,30 @@ WARNING: It's necessary to delete the trie clean cache after the pruning.
If you specify another directory for the trie clean cache via "--cache.trie.journal"
during the use of Geth, please also specify it here for correct deletion. Otherwise
the trie clean cache with default directory will be deleted.
+`,
+ },
+ {
+ Name: "prune-block",
+ Usage: "Prune block data offline",
+ Action: utils.MigrateFlags(pruneBlock),
+ Category: "MISCELLANEOUS COMMANDS",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ utils.AncientFlag,
+ utils.BlockAmountReserved,
+ utils.TriesInMemoryFlag,
+ utils.CheckSnapshotWithMPT,
+ },
+ Description: `
+geth offline prune-block for block data in ancientdb.
+The amount of blocks expected for remaining after prune can be specified via block-amount-reserved in this command,
+will prune and only remain the specified amount of old block data in ancientdb.
+the brief workflow is to backup the the number of this specified amount blocks backward in original ancientdb
+into new ancient_backup, then delete the original ancientdb dir and rename the ancient_backup to original one for replacement,
+finally assemble the statedb and new ancientDb together.
+The purpose of doing it is because the block data will be moved into the ancient store when it
+becomes old enough(exceed the Threshold 90000), the disk usage will be very large over time, and is occupied mainly by ancientDb,
+so it's very necessary to do block data prune, this feature will handle it.
`,
},
{
@@ -149,11 +180,164 @@ It's also usable without snapshot enabled.
}
)
+func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) {
+ //The layer of tries trees that keep in memory.
+ TriesInMemory := int(ctx.GlobalUint64(utils.TriesInMemoryFlag.Name))
+ chaindb := utils.MakeChainDatabase(ctx, stack, false, true)
+ defer chaindb.Close()
+
+ if !ctx.GlobalBool(utils.CheckSnapshotWithMPT.Name) {
+ return chaindb, nil
+ }
+ headBlock := rawdb.ReadHeadBlock(chaindb)
+ if headBlock == nil {
+ return nil, errors.New("failed to load head block")
+ }
+ headHeader := headBlock.Header()
+ //Make sure the MPT and snapshot matches before pruning, otherwise the node can not start.
+ snaptree, err := snapshot.New(chaindb, trie.NewDatabase(chaindb), 256, TriesInMemory, headBlock.Root(), false, false, false)
+ if err != nil {
+ log.Error("snaptree error", "err", err)
+ return nil, err // The relevant snapshot(s) might not exist
+ }
+
+ // Use the HEAD-(n-1) as the target root. The reason for picking it is:
+ // - in most of the normal cases, the related state is available
+ // - the probability of this layer being reorg is very low
+
+ // Retrieve all snapshot layers from the current HEAD.
+ // In theory there are n difflayers + 1 disk layer present,
+ // so n diff layers are expected to be returned.
+ layers := snaptree.Snapshots(headHeader.Root, TriesInMemory, true)
+ if len(layers) != TriesInMemory {
+ // Reject if the accumulated diff layers are less than n. It
+ // means in most of normal cases, there is no associated state
+ // with bottom-most diff layer.
+ log.Error("snapshot layers != TriesInMemory", "err", err)
+ return nil, fmt.Errorf("snapshot not old enough yet: need %d more blocks", TriesInMemory-len(layers))
+ }
+ // Use the bottom-most diff layer as the target
+ targetRoot := layers[len(layers)-1].Root()
+
+ // Ensure the root is really present. The weak assumption
+ // is the presence of root can indicate the presence of the
+ // entire trie.
+ if blob := rawdb.ReadTrieNode(chaindb, targetRoot); len(blob) == 0 {
+ // The special case is for clique based networks(rinkeby, goerli
+ // and some other private networks), it's possible that two
+ // consecutive blocks will have same root. In this case snapshot
+ // difflayer won't be created. So HEAD-(n-1) may not paired with
+ // head-(n-1) layer. Instead the paired layer is higher than the
+ // bottom-most diff layer. Try to find the bottom-most snapshot
+ // layer with state available.
+ //
+ // Note HEAD is ignored. Usually there is the associated
+ // state available, but we don't want to use the topmost state
+ // as the pruning target.
+ var found bool
+ for i := len(layers) - 2; i >= 1; i-- {
+ if blob := rawdb.ReadTrieNode(chaindb, layers[i].Root()); len(blob) != 0 {
+ targetRoot = layers[i].Root()
+ found = true
+ log.Info("Selecting middle-layer as the pruning target", "root", targetRoot, "depth", i)
+ break
+ }
+ }
+ if !found {
+ if blob := rawdb.ReadTrieNode(chaindb, snaptree.DiskRoot()); len(blob) != 0 {
+ targetRoot = snaptree.DiskRoot()
+ found = true
+ log.Info("Selecting disk-layer as the pruning target", "root", targetRoot)
+ }
+ }
+ if !found {
+ if len(layers) > 0 {
+ log.Error("no snapshot paired state")
+ return nil, errors.New("no snapshot paired state")
+ }
+ return nil, fmt.Errorf("associated state[%x] is not present", targetRoot)
+ }
+ } else {
+ if len(layers) > 0 {
+ log.Info("Selecting bottom-most difflayer as the pruning target", "root", targetRoot, "height", headHeader.Number.Uint64()-uint64(len(layers)-1))
+ } else {
+ log.Info("Selecting user-specified state as the pruning target", "root", targetRoot)
+ }
+ }
+ return chaindb, nil
+}
+
+func pruneBlock(ctx *cli.Context) error {
+ stack, config := makeConfigNode(ctx)
+ defer stack.Close()
+ blockAmountReserved := ctx.GlobalUint64(utils.BlockAmountReserved.Name)
+ chaindb, err := accessDb(ctx, stack)
+ if err != nil {
+ return err
+ }
+ var newAncientPath string
+ oldAncientPath := ctx.GlobalString(utils.AncientFlag.Name)
+ if !filepath.IsAbs(oldAncientPath) {
+ oldAncientPath = stack.ResolvePath(oldAncientPath)
+ }
+
+ path, _ := filepath.Split(oldAncientPath)
+ if path == "" {
+ return errors.New("prune failed, did not specify the AncientPath")
+ }
+ newAncientPath = filepath.Join(path, "ancient_back")
+
+ blockpruner := pruner.NewBlockPruner(chaindb, stack, oldAncientPath, newAncientPath, blockAmountReserved)
+
+ lock, exist, err := fileutil.Flock(filepath.Join(oldAncientPath, "PRUNEFLOCK"))
+ if err != nil {
+ log.Error("file lock error", "err", err)
+ return err
+ }
+ if exist {
+ defer lock.Release()
+ log.Info("file lock existed, waiting for prune recovery and continue", "err", err)
+ if err := blockpruner.RecoverInterruption("chaindata", config.Eth.DatabaseCache, utils.MakeDatabaseHandles(), "", false); err != nil {
+ log.Error("Pruning failed", "err", err)
+ return err
+ }
+ log.Info("Block prune successfully")
+ return nil
+ }
+
+ if _, err := os.Stat(newAncientPath); err == nil {
+ // No file lock found for old ancientDB but new ancientDB exsisted, indicating the geth was interrupted
+ // after old ancientDB removal, this happened after backup successfully, so just rename the new ancientDB
+ if err := blockpruner.AncientDbReplacer(); err != nil {
+ log.Error("Failed to rename new ancient directory")
+ return err
+ }
+ log.Info("Block prune successfully")
+ return nil
+ }
+ name := "chaindata"
+ if err := blockpruner.BlockPruneBackUp(name, config.Eth.DatabaseCache, utils.MakeDatabaseHandles(), "", false, false); err != nil {
+ log.Error("Failed to back up block", "err", err)
+ return err
+ }
+
+ log.Info("backup block successfully")
+
+ //After backing up successfully, rename the new ancientdb name to the original one, and delete the old ancientdb
+ if err := blockpruner.AncientDbReplacer(); err != nil {
+ return err
+ }
+
+ lock.Release()
+ log.Info("Block prune successfully")
+ return nil
+}
+
func pruneState(ctx *cli.Context) error {
stack, config := makeConfigNode(ctx)
defer stack.Close()
- chaindb := utils.MakeChainDatabase(ctx, stack, false)
+ chaindb := utils.MakeChainDatabase(ctx, stack, false, false)
pruner, err := pruner.NewPruner(chaindb, stack.ResolvePath(""), stack.ResolvePath(config.Eth.TrieCleanCacheJournal), ctx.GlobalUint64(utils.BloomFilterSizeFlag.Name), ctx.GlobalUint64(utils.TriesInMemoryFlag.Name))
if err != nil {
log.Error("Failed to open snapshot tree", "err", err)
@@ -182,7 +366,7 @@ func verifyState(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- chaindb := utils.MakeChainDatabase(ctx, stack, true)
+ chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
@@ -220,7 +404,7 @@ func traverseState(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- chaindb := utils.MakeChainDatabase(ctx, stack, true)
+ chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
@@ -310,7 +494,7 @@ func traverseRawState(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- chaindb := utils.MakeChainDatabase(ctx, stack, true)
+ chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index 2a208c827..a1a0a7d0b 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -58,6 +58,8 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.LightKDFFlag,
utils.WhitelistFlag,
utils.TriesInMemoryFlag,
+ utils.BlockAmountReserved,
+ utils.CheckSnapshotWithMPT,
},
},
{
@@ -108,6 +110,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.TxPoolAccountQueueFlag,
utils.TxPoolGlobalQueueFlag,
utils.TxPoolLifetimeFlag,
+ utils.TxPoolReannounceTimeFlag,
},
},
{
diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go
index 09844652e..c3d51765f 100644
--- a/cmd/utils/diskusage.go
+++ b/cmd/utils/diskusage.go
@@ -14,7 +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 !windows && !openbsd
// +build !windows,!openbsd
package utils
diff --git a/cmd/utils/diskusage_openbsd.go b/cmd/utils/diskusage_openbsd.go
index 52502d0cf..54f759d29 100644
--- a/cmd/utils/diskusage_openbsd.go
+++ b/cmd/utils/diskusage_openbsd.go
@@ -14,7 +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 openbsd
// +build openbsd
package utils
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index c4dbd8491..8f5141907 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -33,6 +33,10 @@ import (
"text/template"
"time"
+ pcsclite "github.com/gballet/go-libpcsclite"
+ gopsutil "github.com/shirou/gopsutil/mem"
+ "gopkg.in/urfave/cli.v1"
+
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
@@ -66,9 +70,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/params"
- pcsclite "github.com/gballet/go-libpcsclite"
- gopsutil "github.com/shirou/gopsutil/mem"
- "gopkg.in/urfave/cli.v1"
)
func init() {
@@ -126,6 +127,10 @@ var (
Usage: "Enable diffy sync, Please note that enable diffsync will improve the syncing speed, " +
"but will degrade the security to light client level",
}
+ PipeCommitFlag = cli.BoolFlag{
+ Name: "pipecommit",
+ Usage: "Enable MPT pipeline commit, it will improve syncing performance. It is an experimental feature(default is false)",
+ }
RangeLimitFlag = cli.BoolFlag{
Name: "rangelimit",
Usage: "Enable 5000 blocks limit for range query",
@@ -398,6 +403,11 @@ var (
Usage: "Maximum amount of time non-executable transaction are queued",
Value: ethconfig.Defaults.TxPool.Lifetime,
}
+ TxPoolReannounceTimeFlag = cli.DurationFlag{
+ Name: "txpool.reannouncetime",
+ Usage: "Duration for announcing local pending transactions again (default = 10 years, minimum = 1 minute)",
+ Value: ethconfig.Defaults.TxPool.ReannounceTime,
+ }
// Performance tuning settings
CacheFlag = cli.IntFlag{
Name: "cache",
@@ -444,8 +454,8 @@ var (
}
DiffBlockFlag = cli.Uint64Flag{
Name: "diffblock",
- Usage: "The number of blocks should be persisted in db (default = 864000 )",
- Value: uint64(864000),
+ Usage: "The number of blocks should be persisted in db (default = 86400)",
+ Value: uint64(86400),
}
// Miner settings
MiningEnabledFlag = cli.BoolFlag{
@@ -822,6 +832,16 @@ var (
Name: "catalyst",
Usage: "Catalyst mode (eth2 integration testing)",
}
+
+ BlockAmountReserved = cli.Uint64Flag{
+ Name: "block-amount-reserved",
+ Usage: "Sets the expected remained amount of blocks for offline block prune",
+ }
+
+ CheckSnapshotWithMPT = cli.BoolFlag{
+ Name: "check-snapshot-with-mpt",
+ Usage: "Enable checking between snapshot and MPT ",
+ }
)
// MakeDataDir retrieves the currently requested data directory, terminating
@@ -1410,6 +1430,9 @@ func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
}
+ if ctx.GlobalIsSet(TxPoolReannounceTimeFlag.Name) {
+ cfg.ReannounceTime = ctx.GlobalDuration(TxPoolReannounceTimeFlag.Name)
+ }
}
func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
@@ -1613,6 +1636,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.GlobalIsSet(DiffSyncFlag.Name) {
cfg.DiffSync = ctx.GlobalBool(DiffSyncFlag.Name)
}
+ if ctx.GlobalIsSet(PipeCommitFlag.Name) {
+ cfg.PipeCommit = ctx.GlobalBool(PipeCommitFlag.Name)
+ }
if ctx.GlobalIsSet(RangeLimitFlag.Name) {
cfg.RangeLimit = ctx.GlobalBool(RangeLimitFlag.Name)
}
@@ -1756,7 +1782,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.GlobalIsSet(DataDirFlag.Name) {
// Check if we have an already initialized chain and fall back to
// that if so. Otherwise we need to generate a new genesis spec.
- chaindb := MakeChainDatabase(ctx, stack, false) // TODO (MariusVanDerWijden) make this read only
+ chaindb := MakeChainDatabase(ctx, stack, false, false) // TODO (MariusVanDerWijden) make this read only
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
cfg.Genesis = nil // fallback to db content
}
@@ -1875,7 +1901,7 @@ func SplitTagsFlag(tagsFlag string) map[string]string {
}
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
-func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database {
+func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database {
var (
cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
handles = MakeDatabaseHandles()
@@ -1888,7 +1914,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
chainDb, err = stack.OpenDatabase(name, cache, handles, "", readonly)
} else {
name := "chaindata"
- chainDb, err = stack.OpenDatabaseWithFreezer(name, cache, handles, ctx.GlobalString(AncientFlag.Name), "", readonly)
+ chainDb, err = stack.OpenDatabaseWithFreezer(name, cache, handles, ctx.GlobalString(AncientFlag.Name), "", readonly, disableFreeze, false)
}
if err != nil {
Fatalf("Could not open database: %v", err)
@@ -1918,7 +1944,7 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
// MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
var err error
- chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database
+ chainDb = MakeChainDatabase(ctx, stack, false, false) // TODO(rjl493456442) support read-only database
config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
if err != nil {
Fatalf("%v", err)
diff --git a/common/fdlimit/fdlimit_bsd.go b/common/fdlimit/fdlimit_bsd.go
index a3a6902c0..86181337a 100644
--- a/common/fdlimit/fdlimit_bsd.go
+++ b/common/fdlimit/fdlimit_bsd.go
@@ -14,7 +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 freebsd || dragonfly
// +build freebsd dragonfly
package fdlimit
diff --git a/common/fdlimit/fdlimit_unix.go b/common/fdlimit/fdlimit_unix.go
index a1f388ebb..e5a575f7a 100644
--- a/common/fdlimit/fdlimit_unix.go
+++ b/common/fdlimit/fdlimit_unix.go
@@ -14,7 +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 linux || netbsd || openbsd || solaris
// +build linux netbsd openbsd solaris
package fdlimit
diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go
index dfec81f6a..2c8094ca3 100644
--- a/consensus/clique/clique.go
+++ b/consensus/clique/clique.go
@@ -560,7 +560,11 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB,
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
// No block rewards in PoA, so the state remains as is and uncles are dropped
+ var err error
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
+ if err != nil {
+ return nil, nil, err
+ }
header.UncleHash = types.CalcUncleHash(nil)
// Assemble and return the final block for sealing
diff --git a/consensus/ethash/difficulty.go b/consensus/ethash/difficulty.go
index 66a18059c..59c4ac741 100644
--- a/consensus/ethash/difficulty.go
+++ b/consensus/ethash/difficulty.go
@@ -52,7 +52,8 @@ func CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int {
- num = block.number
*/
- pDiff, _ := uint256.FromBig(parent.Difficulty) // pDiff: pdiff
+ pDiff := uint256.NewInt()
+ pDiff.SetFromBig(parent.Difficulty) // pDiff: pdiff
adjust := pDiff.Clone()
adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048
@@ -95,7 +96,8 @@ func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int {
- num = block.number
*/
- pDiff, _ := uint256.FromBig(parent.Difficulty) // pDiff: pdiff
+ pDiff := uint256.NewInt()
+ pDiff.SetFromBig(parent.Difficulty) // pDiff: pdiff
adjust := pDiff.Clone()
adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048
diff --git a/core/block_validator.go b/core/block_validator.go
index 12fa908cd..b109c1e54 100644
--- a/core/block_validator.go
+++ b/core/block_validator.go
@@ -18,6 +18,7 @@ package core
import (
"fmt"
+ "time"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state"
@@ -26,6 +27,8 @@ import (
"github.com/ethereum/go-ethereum/trie"
)
+const badBlockCacheExpire = 30 * time.Second
+
// BlockValidator is responsible for validating block headers, uncles and
// processed state.
//
@@ -54,6 +57,9 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
return ErrKnownBlock
}
+ if v.bc.isCachedBadBlock(block) {
+ return ErrKnownBadBlock
+ }
// Header validity is known at this point, check the uncles and transactions
header := block.Header()
if err := v.engine.VerifyUncles(v.bc, block); err != nil {
@@ -106,7 +112,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// transition, such as amount of used gas, the receipt roots and the state root
// itself. ValidateState returns a database batch if the validation was a success
// otherwise nil and an error is returned.
-func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
+func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, skipHeavyVerify bool) error {
header := block.Header()
if block.GasUsed() != usedGas {
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
@@ -125,17 +131,26 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
if receiptSha != header.ReceiptHash {
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
- } else {
- return nil
}
+ return nil
},
- func() error {
+ }
+ if skipHeavyVerify {
+ validateFuns = append(validateFuns, func() error {
+ if err := statedb.WaitPipeVerification(); err != nil {
+ return err
+ }
+ statedb.Finalise(v.config.IsEIP158(header.Number))
+ statedb.AccountsIntermediateRoot()
+ return nil
+ })
+ } else {
+ validateFuns = append(validateFuns, func() error {
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
- } else {
- return nil
}
- },
+ return nil
+ })
}
validateRes := make(chan error, len(validateFuns))
for _, f := range validateFuns {
diff --git a/core/blockchain.go b/core/blockchain.go
index 91371940c..6c87ffc70 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -77,7 +77,8 @@ var (
blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil)
blockReorgInvalidatedTx = metrics.NewRegisteredMeter("chain/reorg/invalidTx", nil)
- errInsertionInterrupted = errors.New("insertion is interrupted")
+ errInsertionInterrupted = errors.New("insertion is interrupted")
+ errStateRootVerificationFailed = errors.New("state root verification failed")
)
const (
@@ -87,9 +88,11 @@ const (
diffLayerRLPCacheLimit = 256
receiptsCacheLimit = 10000
txLookupCacheLimit = 1024
+ maxBadBlockLimit = 16
maxFutureBlocks = 256
maxTimeFutureBlocks = 30
maxBeyondBlocks = 2048
+ prefetchTxNumber = 100
diffLayerFreezerRecheckInterval = 3 * time.Second
diffLayerPruneRecheckInterval = 1 * time.Second // The interval to prune unverified diff layers
@@ -98,6 +101,8 @@ const (
maxDiffForkDist = 11 // Maximum allowed backward distance from the chain head
maxDiffLimitForBroadcast = 128 // Maximum number of unique diff layers a peer may have broadcasted
+ rewindBadBlockInterval = 1 * time.Second
+
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
//
// Changelog:
@@ -176,10 +181,11 @@ type BlockChain struct {
chainConfig *params.ChainConfig // Chain & network configuration
cacheConfig *CacheConfig // Cache configuration for pruning
- db ethdb.Database // Low level persistent database to store final content in
- snaps *snapshot.Tree // Snapshot tree for fast trie leaf access
- triegc *prque.Prque // Priority queue mapping block numbers to tries to gc
- gcproc time.Duration // Accumulates canonical block processing for trie dumping
+ db ethdb.Database // Low level persistent database to store final content in
+ snaps *snapshot.Tree // Snapshot tree for fast trie leaf access
+ triegc *prque.Prque // Priority queue mapping block numbers to tries to gc
+ gcproc time.Duration // Accumulates canonical block processing for trie dumping
+ commitLock sync.Mutex // CommitLock is used to protect above field from being modified concurrently
// txLookupLimit is the maximum number of blocks from head whose tx indices
// are reserved:
@@ -212,6 +218,7 @@ type BlockChain struct {
blockCache *lru.Cache // Cache for the most recent entire blocks
txLookupCache *lru.Cache // Cache for the most recent transaction lookup data.
futureBlocks *lru.Cache // future blocks are blocks added for later processing
+ badBlockCache *lru.Cache // Cache for the blocks that failed to pass MPT root verification
// trusted diff layers
diffLayerCache *lru.Cache // Cache for the diffLayers
@@ -233,10 +240,12 @@ type BlockChain struct {
running int32 // 0 if chain is running, 1 when stopped
procInterrupt int32 // interrupt signaler for block processing
- engine consensus.Engine
- validator Validator // Block and state validator interface
- processor Processor // Block transaction processor interface
- vmConfig vm.Config
+ engine consensus.Engine
+ prefetcher Prefetcher
+ validator Validator // Block and state validator interface
+ processor Processor // Block transaction processor interface
+ vmConfig vm.Config
+ pipeCommit bool
shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
terminateInsert func(common.Hash, uint64) bool // Testing hook used to terminate ancient receipt chain insertion.
@@ -260,6 +269,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
receiptsCache, _ := lru.New(receiptsCacheLimit)
blockCache, _ := lru.New(blockCacheLimit)
txLookupCache, _ := lru.New(txLookupCacheLimit)
+ badBlockCache, _ := lru.New(maxBadBlockLimit)
+
futureBlocks, _ := lru.New(maxFutureBlocks)
diffLayerCache, _ := lru.New(diffLayerCacheLimit)
diffLayerRLPCache, _ := lru.New(diffLayerRLPCacheLimit)
@@ -281,6 +292,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
bodyRLPCache: bodyRLPCache,
receiptsCache: receiptsCache,
blockCache: blockCache,
+ badBlockCache: badBlockCache,
diffLayerCache: diffLayerCache,
diffLayerRLPCache: diffLayerRLPCache,
txLookupCache: txLookupCache,
@@ -295,6 +307,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
diffNumToBlockHashes: make(map[uint64]map[common.Hash]struct{}),
diffPeersToDiffHashes: make(map[string]map[common.Hash]struct{}),
}
+ bc.prefetcher = NewStatePrefetcher(chainConfig, bc, engine)
bc.validator = NewBlockValidator(chainConfig, bc, engine)
bc.processor = NewStateProcessor(chainConfig, bc, engine)
@@ -322,9 +335,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
rawdb.InitDatabaseFromFreezer(bc.db)
// If ancient database is not empty, reconstruct all missing
// indices in the background.
- frozen, _ := bc.db.Ancients()
+ frozen, _ := bc.db.ItemAmountInAncient()
if frozen > 0 {
- txIndexBlock = frozen
+ txIndexBlock, _ = bc.db.Ancients()
}
}
if err := bc.loadLastState(); err != nil {
@@ -359,7 +372,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
}
}
// Ensure that a previous crash in SetHead doesn't leave extra ancients
- if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 {
+ if frozen, err := bc.db.ItemAmountInAncient(); err == nil && frozen > 0 {
+ frozen, err = bc.db.Ancients()
+ if err != nil {
+ return nil, err
+ }
var (
needRewind bool
low uint64
@@ -454,7 +471,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
go bc.trustedDiffLayerLoop()
}
go bc.untrustedDiffLayerPruneLoop()
-
+ if bc.pipeCommit {
+ // check current block and rewind invalid one
+ go bc.rewindInvalidHeaderBlockLoop()
+ }
return bc, nil
}
@@ -478,6 +498,9 @@ func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts) {
}
func (bc *BlockChain) cacheDiffLayer(diffLayer *types.DiffLayer) {
+ if bc.diffLayerCache.Len() >= diffLayerCacheLimit {
+ bc.diffLayerCache.RemoveOldest()
+ }
bc.diffLayerCache.Add(diffLayer.BlockHash, diffLayer)
if bc.db.DiffStore() != nil {
// push to priority queue before persisting
@@ -567,6 +590,25 @@ func (bc *BlockChain) SetHead(head uint64) error {
return err
}
+func (bc *BlockChain) tryRewindBadBlocks() {
+ bc.chainmu.Lock()
+ defer bc.chainmu.Unlock()
+ block := bc.CurrentBlock()
+ snaps := bc.snaps
+ // Verified and Result is false
+ if snaps != nil && snaps.Snapshot(block.Root()) != nil &&
+ snaps.Snapshot(block.Root()).Verified() && !snaps.Snapshot(block.Root()).WaitAndGetVerifyRes() {
+ // Rewind by one block
+ log.Warn("current block verified failed, rewind to its parent", "height", block.NumberU64(), "hash", block.Hash())
+ bc.futureBlocks.Remove(block.Hash())
+ bc.badBlockCache.Add(block.Hash(), time.Now())
+ bc.diffLayerCache.Remove(block.Hash())
+ bc.diffLayerRLPCache.Remove(block.Hash())
+ bc.reportBlock(block, nil, errStateRootVerificationFailed)
+ bc.setHeadBeyondRoot(block.NumberU64()-1, common.Hash{})
+ }
+}
+
// SetHeadBeyondRoot rewinds the local chain to a new head with the extra condition
// that the rewind must pass the specified state root. This method is meant to be
// used when rewinding with snapshots enabled to ensure that we go back further than
@@ -578,7 +620,10 @@ func (bc *BlockChain) SetHead(head uint64) error {
func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64, error) {
bc.chainmu.Lock()
defer bc.chainmu.Unlock()
+ return bc.setHeadBeyondRoot(head, root)
+}
+func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash) (uint64, error) {
// Track the block number of the requested root hash
var rootNumber uint64 // (no root == always 0)
@@ -1008,7 +1053,7 @@ func (bc *BlockChain) GetDiffAccounts(blockHash common.Hash) ([]common.Address,
if diffLayer == nil {
if header.TxHash != types.EmptyRootHash {
- return nil, fmt.Errorf("no diff layer found")
+ return nil, ErrDiffLayerNotFound
}
return nil, nil
@@ -1046,6 +1091,12 @@ func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool {
// HasState checks if state trie is fully present in the database or not.
func (bc *BlockChain) HasState(hash common.Hash) bool {
+ if bc.pipeCommit && bc.snaps != nil {
+ // If parent snap is pending on verification, treat it as state exist
+ if s := bc.snaps.Snapshot(hash); s != nil && !s.Verified() {
+ return true
+ }
+ }
_, err := bc.stateCache.OpenTrie(hash)
return err == nil
}
@@ -1657,8 +1708,78 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
}
wg.Done()
}()
+
+ tryCommitTrieDB := func() error {
+ bc.commitLock.Lock()
+ defer bc.commitLock.Unlock()
+
+ triedb := bc.stateCache.TrieDB()
+ // If we're running an archive node, always flush
+ if bc.cacheConfig.TrieDirtyDisabled {
+ err := triedb.Commit(block.Root(), false, nil)
+ if err != nil {
+ return err
+ }
+ } else {
+ // Full but not archive node, do proper garbage collection
+ triedb.Reference(block.Root(), common.Hash{}) // metadata reference to keep trie alive
+ bc.triegc.Push(block.Root(), -int64(block.NumberU64()))
+
+ if current := block.NumberU64(); current > bc.triesInMemory {
+ // If we exceeded our memory allowance, flush matured singleton nodes to disk
+ var (
+ nodes, imgs = triedb.Size()
+ limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
+ )
+ if nodes > limit || imgs > 4*1024*1024 {
+ triedb.Cap(limit - ethdb.IdealBatchSize)
+ }
+ // Find the next state trie we need to commit
+ chosen := current - bc.triesInMemory
+
+ // If we exceeded out time allowance, flush an entire trie to disk
+ if bc.gcproc > bc.cacheConfig.TrieTimeLimit {
+ canWrite := true
+ if posa, ok := bc.engine.(consensus.PoSA); ok {
+ if !posa.EnoughDistance(bc, block.Header()) {
+ canWrite = false
+ }
+ }
+ if canWrite {
+ // If the header is missing (canonical chain behind), we're reorging a low
+ // diff sidechain. Suspend committing until this operation is completed.
+ header := bc.GetHeaderByNumber(chosen)
+ if header == nil {
+ log.Warn("Reorg in progress, trie commit postponed", "number", chosen)
+ } else {
+ // If we're exceeding limits but haven't reached a large enough memory gap,
+ // warn the user that the system is becoming unstable.
+ if chosen < lastWrite+bc.triesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
+ log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/float64(bc.triesInMemory))
+ }
+ // Flush an entire trie and restart the counters
+ triedb.Commit(header.Root, true, nil)
+ lastWrite = chosen
+ bc.gcproc = 0
+ }
+ }
+ }
+ // Garbage collect anything below our required write retention
+ for !bc.triegc.Empty() {
+ root, number := bc.triegc.Pop()
+ if uint64(-number) > chosen {
+ bc.triegc.Push(root, number)
+ break
+ }
+ go triedb.Dereference(root.(common.Hash))
+ }
+ }
+ }
+ return nil
+ }
+
// Commit all cached state changes into underlying memory database.
- root, diffLayer, err := state.Commit(bc.chainConfig.IsEIP158(block.Number()))
+ _, diffLayer, err := state.Commit(bc.tryRewindBadBlocks, tryCommitTrieDB)
if err != nil {
return NonStatTy, err
}
@@ -1671,69 +1792,9 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
diffLayer.Number = block.NumberU64()
bc.cacheDiffLayer(diffLayer)
}
- triedb := bc.stateCache.TrieDB()
- // If we're running an archive node, always flush
- if bc.cacheConfig.TrieDirtyDisabled {
- if err := triedb.Commit(root, false, nil); err != nil {
- return NonStatTy, err
- }
- } else {
- // Full but not archive node, do proper garbage collection
- triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
- bc.triegc.Push(root, -int64(block.NumberU64()))
-
- if current := block.NumberU64(); current > bc.triesInMemory {
- // If we exceeded our memory allowance, flush matured singleton nodes to disk
- var (
- nodes, imgs = triedb.Size()
- limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
- )
- if nodes > limit || imgs > 4*1024*1024 {
- triedb.Cap(limit - ethdb.IdealBatchSize)
- }
- // Find the next state trie we need to commit
- chosen := current - bc.triesInMemory
-
- // If we exceeded out time allowance, flush an entire trie to disk
- if bc.gcproc > bc.cacheConfig.TrieTimeLimit {
- canWrite := true
- if posa, ok := bc.engine.(consensus.PoSA); ok {
- if !posa.EnoughDistance(bc, block.Header()) {
- canWrite = false
- }
- }
- if canWrite {
- // If the header is missing (canonical chain behind), we're reorging a low
- // diff sidechain. Suspend committing until this operation is completed.
- header := bc.GetHeaderByNumber(chosen)
- if header == nil {
- log.Warn("Reorg in progress, trie commit postponed", "number", chosen)
- } else {
- // If we're exceeding limits but haven't reached a large enough memory gap,
- // warn the user that the system is becoming unstable.
- if chosen < lastWrite+bc.triesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
- log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/float64(bc.triesInMemory))
- }
- // Flush an entire trie and restart the counters
- triedb.Commit(header.Root, true, nil)
- lastWrite = chosen
- bc.gcproc = 0
- }
- }
- }
- // Garbage collect anything below our required write retention
- for !bc.triegc.Empty() {
- root, number := bc.triegc.Pop()
- if uint64(-number) > chosen {
- bc.triegc.Push(root, number)
- break
- }
- go triedb.Dereference(root.(common.Hash))
- }
- }
- }
wg.Wait()
+
// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
@@ -2048,10 +2109,22 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
// Enable prefetching to pull in trie node paths while processing transactions
statedb.StartPrefetcher("chain")
-
+ var followupInterrupt uint32
+ // For diff sync, it may fallback to full sync, so we still do prefetch
+ if len(block.Transactions()) >= prefetchTxNumber {
+ throwaway := statedb.Copy()
+ go func(start time.Time, followup *types.Block, throwaway *state.StateDB, interrupt *uint32) {
+ bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt)
+ }(time.Now(), block, throwaway, &followupInterrupt)
+ }
//Process block using the parent state as reference point
substart := time.Now()
+ if bc.pipeCommit {
+ statedb.EnablePipeCommit()
+ }
+ statedb.SetExpectedStateRoot(block.Root())
statedb, receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
+ atomic.StoreUint32(&followupInterrupt, 1)
activeState = statedb
if err != nil {
bc.reportBlock(block, receipts, err)
@@ -2070,7 +2143,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
// Validate the state using the default validator
substart = time.Now()
if !statedb.IsLightProcessed() {
- if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
+ if err := bc.validator.ValidateState(block, statedb, receipts, usedGas, bc.pipeCommit); err != nil {
log.Error("validate state failed", "error", err)
bc.reportBlock(block, receipts, err)
return it.index, err
@@ -2485,10 +2558,26 @@ func (bc *BlockChain) update() {
}
}
+func (bc *BlockChain) rewindInvalidHeaderBlockLoop() {
+ recheck := time.NewTicker(rewindBadBlockInterval)
+ defer recheck.Stop()
+ for {
+ select {
+ case <-recheck.C:
+ bc.tryRewindBadBlocks()
+ case <-bc.quit:
+ return
+ }
+ }
+}
+
func (bc *BlockChain) trustedDiffLayerLoop() {
- recheck := time.Tick(diffLayerFreezerRecheckInterval)
+ recheck := time.NewTicker(diffLayerFreezerRecheckInterval)
bc.wg.Add(1)
- defer bc.wg.Done()
+ defer func() {
+ bc.wg.Done()
+ recheck.Stop()
+ }()
for {
select {
case diff := <-bc.diffQueueBuffer:
@@ -2521,29 +2610,28 @@ func (bc *BlockChain) trustedDiffLayerLoop() {
batch.Reset()
}
return
- case <-recheck:
+ case <-recheck.C:
currentHeight := bc.CurrentBlock().NumberU64()
var batch ethdb.Batch
for !bc.diffQueue.Empty() {
diff, prio := bc.diffQueue.Pop()
diffLayer := diff.(*types.DiffLayer)
- // if the block old enough
- if int64(currentHeight)+prio >= int64(bc.triesInMemory) {
- canonicalHash := bc.GetCanonicalHash(uint64(-prio))
- // on the canonical chain
- if canonicalHash == diffLayer.BlockHash {
- if batch == nil {
- batch = bc.db.DiffStore().NewBatch()
- }
- rawdb.WriteDiffLayer(batch, diffLayer.BlockHash, diffLayer)
- staleHash := bc.GetCanonicalHash(uint64(-prio) - bc.diffLayerFreezerBlockLimit)
- rawdb.DeleteDiffLayer(batch, staleHash)
- }
- } else {
+ // if the block not old enough
+ if int64(currentHeight)+prio < int64(bc.triesInMemory) {
bc.diffQueue.Push(diffLayer, prio)
break
}
+ canonicalHash := bc.GetCanonicalHash(uint64(-prio))
+ // on the canonical chain
+ if canonicalHash == diffLayer.BlockHash {
+ if batch == nil {
+ batch = bc.db.DiffStore().NewBatch()
+ }
+ rawdb.WriteDiffLayer(batch, diffLayer.BlockHash, diffLayer)
+ staleHash := bc.GetCanonicalHash(uint64(-prio) - bc.diffLayerFreezerBlockLimit)
+ rawdb.DeleteDiffLayer(batch, staleHash)
+ }
if batch != nil && batch.ValueSize() > ethdb.IdealBatchSize {
if err := batch.Write(); err != nil {
panic(fmt.Sprintf("Failed to write diff layer, error %v", err))
@@ -2616,34 +2704,6 @@ func (bc *BlockChain) removeDiffLayers(diffHash common.Hash) {
}
}
-func (bc *BlockChain) RemoveDiffPeer(pid string) {
- bc.diffMux.Lock()
- defer bc.diffMux.Unlock()
- if invaliDiffHashes := bc.diffPeersToDiffHashes[pid]; invaliDiffHashes != nil {
- for invalidDiffHash := range invaliDiffHashes {
- lastDiffHash := false
- if peers, ok := bc.diffHashToPeers[invalidDiffHash]; ok {
- delete(peers, pid)
- if len(peers) == 0 {
- lastDiffHash = true
- delete(bc.diffHashToPeers, invalidDiffHash)
- }
- }
- if lastDiffHash {
- affectedBlockHash := bc.diffHashToBlockHash[invalidDiffHash]
- if diffs, exist := bc.blockHashToDiffLayers[affectedBlockHash]; exist {
- delete(diffs, invalidDiffHash)
- if len(diffs) == 0 {
- delete(bc.blockHashToDiffLayers, affectedBlockHash)
- }
- }
- delete(bc.diffHashToBlockHash, invalidDiffHash)
- }
- }
- delete(bc.diffPeersToDiffHashes, pid)
- }
-}
-
func (bc *BlockChain) untrustedDiffLayerPruneLoop() {
recheck := time.NewTicker(diffLayerPruneRecheckInterval)
bc.wg.Add(1)
@@ -2711,24 +2771,27 @@ func (bc *BlockChain) HandleDiffLayer(diffLayer *types.DiffLayer, pid string, fu
// Basic check
currentHeight := bc.CurrentBlock().NumberU64()
if diffLayer.Number > currentHeight && diffLayer.Number-currentHeight > maxDiffQueueDist {
- log.Error("diff layers too new from current", "pid", pid)
+ log.Debug("diff layers too new from current", "pid", pid)
return nil
}
if diffLayer.Number < currentHeight && currentHeight-diffLayer.Number > maxDiffForkDist {
- log.Error("diff layers too old from current", "pid", pid)
+ log.Debug("diff layers too old from current", "pid", pid)
return nil
}
bc.diffMux.Lock()
defer bc.diffMux.Unlock()
+ if blockHash, exist := bc.diffHashToBlockHash[diffLayer.DiffHash]; exist && blockHash == diffLayer.BlockHash {
+ return nil
+ }
if !fulfilled && len(bc.diffPeersToDiffHashes[pid]) > maxDiffLimitForBroadcast {
- log.Error("too many accumulated diffLayers", "pid", pid)
+ log.Debug("too many accumulated diffLayers", "pid", pid)
return nil
}
if len(bc.diffPeersToDiffHashes[pid]) > maxDiffLimit {
- log.Error("too many accumulated diffLayers", "pid", pid)
+ log.Debug("too many accumulated diffLayers", "pid", pid)
return nil
}
if _, exist := bc.diffPeersToDiffHashes[pid]; exist {
@@ -2844,6 +2907,18 @@ func (bc *BlockChain) maintainTxIndex(ancients uint64) {
}
}
+func (bc *BlockChain) isCachedBadBlock(block *types.Block) bool {
+ if timeAt, exist := bc.badBlockCache.Get(block.Hash()); exist {
+ putAt := timeAt.(time.Time)
+ if time.Since(putAt) >= badBlockCacheExpire {
+ bc.badBlockCache.Remove(block.Hash())
+ return false
+ }
+ return true
+ }
+ return false
+}
+
// reportBlock logs a bad block error.
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
rawdb.WriteBadBlock(bc.db, block)
@@ -3014,6 +3089,11 @@ func EnableLightProcessor(bc *BlockChain) *BlockChain {
return bc
}
+func EnablePipelineCommit(bc *BlockChain) *BlockChain {
+ bc.pipeCommit = true
+ return bc
+}
+
func EnablePersistDiff(limit uint64) BlockChainOption {
return func(chain *BlockChain) *BlockChain {
chain.diffLayerFreezerBlockLimit = limit
diff --git a/core/blockchain_diff_test.go b/core/blockchain_diff_test.go
index 0b289bdc1..2575843a9 100644
--- a/core/blockchain_diff_test.go
+++ b/core/blockchain_diff_test.go
@@ -21,6 +21,8 @@
package core
import (
+ "bytes"
+ "encoding/hex"
"math/big"
"testing"
"time"
@@ -42,9 +44,43 @@ import (
var (
// testKey is a private key to use for funding a tester account.
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ contractCode, _ = hex.DecodeString("608060405260016000806101000a81548160ff02191690831515021790555034801561002a57600080fd5b506101688061003a6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806389a2d8011461003b578063b0483f4814610059575b600080fd5b610043610075565b60405161005091906100f4565b60405180910390f35b610073600480360381019061006e91906100bc565b61008b565b005b60008060009054906101000a900460ff16905090565b806000806101000a81548160ff02191690831515021790555050565b6000813590506100b68161011b565b92915050565b6000602082840312156100ce57600080fd5b60006100dc848285016100a7565b91505092915050565b6100ee8161010f565b82525050565b600060208201905061010960008301846100e5565b92915050565b60008115159050919050565b6101248161010f565b811461012f57600080fd5b5056fea264697066735822122092f788b569bfc3786e90601b5dbec01cfc3d76094164fd66ca7d599c4239fc5164736f6c63430008000033")
+ contractAddr = common.HexToAddress("0xe74a3c7427cda785e0000d42a705b1f3fd371e09")
+ contractSlot = common.HexToHash("0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
+ contractData1, _ = hex.DecodeString("b0483f480000000000000000000000000000000000000000000000000000000000000000")
+ contractData2, _ = hex.DecodeString("b0483f480000000000000000000000000000000000000000000000000000000000000001")
+ commonGas = 192138
// testAddr is the Ethereum address of the tester account.
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
+
+ checkBlocks = map[int]checkBlockParam{
+ 12: {
+ txs: []checkTransactionParam{
+ {
+ to: &contractAddr,
+ slot: contractSlot,
+ value: []byte{01},
+ },
+ }},
+
+ 13: {
+ txs: []checkTransactionParam{
+ {
+ to: &contractAddr,
+ slot: contractSlot,
+ value: []byte{},
+ },
+ }},
+ 14: {
+ txs: []checkTransactionParam{
+ {
+ to: &contractAddr,
+ slot: contractSlot,
+ value: []byte{01},
+ },
+ }},
+ }
// testBlocks is the test parameters array for specific blocks.
testBlocks = []testBlockParam{
{
@@ -52,7 +88,7 @@ var (
blockNr: 11,
txs: []testTransactionParam{
{
- to: common.Address{0x01},
+ to: &common.Address{0x01},
value: big.NewInt(1),
gasPrice: big.NewInt(1),
data: nil,
@@ -63,51 +99,74 @@ var (
blockNr: 12,
txs: []testTransactionParam{
{
- to: common.Address{0x01},
+ to: &common.Address{0x01},
value: big.NewInt(1),
gasPrice: big.NewInt(1),
data: nil,
},
{
- to: common.Address{0x02},
+ to: &common.Address{0x02},
value: big.NewInt(2),
gasPrice: big.NewInt(2),
data: nil,
},
+ {
+ to: nil,
+ value: big.NewInt(0),
+ gasPrice: big.NewInt(2),
+ data: contractCode,
+ },
},
},
{
blockNr: 13,
txs: []testTransactionParam{
{
- to: common.Address{0x01},
+ to: &common.Address{0x01},
value: big.NewInt(1),
gasPrice: big.NewInt(1),
data: nil,
},
{
- to: common.Address{0x02},
+ to: &common.Address{0x02},
value: big.NewInt(2),
gasPrice: big.NewInt(2),
data: nil,
},
{
- to: common.Address{0x03},
+ to: &common.Address{0x03},
value: big.NewInt(3),
gasPrice: big.NewInt(3),
data: nil,
},
+ {
+ to: &contractAddr,
+ value: big.NewInt(0),
+ gasPrice: big.NewInt(3),
+ data: contractData1,
+ },
},
},
{
blockNr: 14,
+ txs: []testTransactionParam{
+ {
+ to: &contractAddr,
+ value: big.NewInt(0),
+ gasPrice: big.NewInt(3),
+ data: contractData2,
+ },
+ },
+ },
+ {
+ blockNr: 15,
txs: []testTransactionParam{},
},
}
)
type testTransactionParam struct {
- to common.Address
+ to *common.Address
value *big.Int
gasPrice *big.Int
data []byte
@@ -118,6 +177,16 @@ type testBlockParam struct {
txs []testTransactionParam
}
+type checkTransactionParam struct {
+ to *common.Address
+ slot common.Hash
+ value []byte
+}
+
+type checkBlockParam struct {
+ txs []checkTransactionParam
+}
+
// testBackend is a mock implementation of the live Ethereum message handler. Its
// purpose is to allow testing the request/reply workflows and wire serialization
// in the `eth` protocol without actually doing any data processing.
@@ -153,8 +222,15 @@ func newTestBackendWithGenerator(blocks int, lightProcess bool) *testBackend {
// Specific block setting, the index in this generator has 1 diff from specified blockNr.
if i+1 == testBlock.blockNr {
for _, testTransaction := range testBlock.txs {
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), testTransaction.to,
- testTransaction.value, params.TxGas, testTransaction.gasPrice, testTransaction.data), signer, testKey)
+ var transaction *types.Transaction
+ if testTransaction.to == nil {
+ transaction = types.NewContractCreation(block.TxNonce(testAddr),
+ testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
+ } else {
+ transaction = types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
+ testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
+ }
+ tx, err := types.SignTx(transaction, signer, testKey)
if err != nil {
panic(err)
}
@@ -168,8 +244,8 @@ func newTestBackendWithGenerator(blocks int, lightProcess bool) *testBackend {
// We want to simulate an empty middle block, having the same state as the
// first one. The last is needs a state change again to force a reorg.
for _, testTransaction := range testBlocks[0].txs {
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), testTransaction.to,
- testTransaction.value, params.TxGas, testTransaction.gasPrice, testTransaction.data), signer, testKey)
+ tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
+ testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data), signer, testKey)
if err != nil {
panic(err)
}
@@ -244,6 +320,14 @@ func TestProcessDiffLayer(t *testing.T) {
if err != nil {
t.Errorf("failed to insert block %v", err)
}
+ if checks, exist := checkBlocks[i]; exist {
+ for _, check := range checks.txs {
+ s, _ := lightBackend.Chain().Snapshots().Snapshot(block.Root()).Storage(crypto.Keccak256Hash((*check.to)[:]), check.slot)
+ if !bytes.Equal(s, check.value) {
+ t.Fatalf("Expected value %x, get %x", check.value, s)
+ }
+ }
+ }
}
currentBlock := lightBackend.chain.CurrentBlock()
nextBlock := fullBackend.chain.GetBlockByNumber(currentBlock.NumberU64() + 1)
@@ -280,11 +364,15 @@ func TestFreezeDiffLayer(t *testing.T) {
blockNum := 1024
fullBackend := newTestBackend(blockNum, true)
defer fullBackend.close()
+ for len(fullBackend.chain.diffQueueBuffer) > 0 {
+ // Wait for the buffer to be zero.
+ }
// Minus one empty block.
- if fullBackend.chain.diffQueue.Size() != blockNum-1 {
- t.Errorf("size of diff queue is wrong, expected: %d, get: %d", blockNum, fullBackend.chain.diffQueue.Size())
+ if fullBackend.chain.diffQueue.Size() > blockNum-1 && fullBackend.chain.diffQueue.Size() < blockNum-2 {
+ t.Errorf("size of diff queue is wrong, expected: %d, get: %d", blockNum-1, fullBackend.chain.diffQueue.Size())
}
- time.Sleep(diffLayerFreezerRecheckInterval + 1*time.Second)
+
+ time.Sleep(diffLayerFreezerRecheckInterval + 2*time.Second)
if fullBackend.chain.diffQueue.Size() != int(fullBackend.chain.triesInMemory) {
t.Errorf("size of diff queue is wrong, expected: %d, get: %d", blockNum, fullBackend.chain.diffQueue.Size())
}
@@ -318,7 +406,7 @@ func TestPruneDiffLayer(t *testing.T) {
if len(fullBackend.chain.diffNumToBlockHashes) != maxDiffForkDist {
t.Error("unexpected size of diffNumToBlockHashes")
}
- if len(fullBackend.chain.diffPeersToDiffHashes) != 2 {
+ if len(fullBackend.chain.diffPeersToDiffHashes) != 1 {
t.Error("unexpected size of diffPeersToDiffHashes")
}
if len(fullBackend.chain.blockHashToDiffLayers) != maxDiffForkDist {
@@ -381,13 +469,14 @@ func TestGetDiffAccounts(t *testing.T) {
t.Errorf("the diff accounts does't include addr: %v", testAddr)
}
}
-
for _, transaction := range testBlock.txs {
+ if transaction.to == nil || len(transaction.data) > 0 {
+ continue
+ }
for idx, account := range accounts {
- if transaction.to == account {
+ if *transaction.to == account {
break
}
-
if idx == len(accounts)-1 {
t.Errorf("the diff accounts does't include addr: %v", transaction.to)
}
diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go
index 5ddb6d2e0..b85f9c9e0 100644
--- a/core/blockchain_repair_test.go
+++ b/core/blockchain_repair_test.go
@@ -1762,7 +1762,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
}
os.RemoveAll(datadir)
- db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
+ db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false, false, false)
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
}
@@ -1832,7 +1832,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
db.Close()
// Start a new blockchain back up and see where the repait leads us
- db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
+ db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false, false, false)
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
}
diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go
index 6caec36ea..bdcca988a 100644
--- a/core/blockchain_sethead_test.go
+++ b/core/blockchain_sethead_test.go
@@ -1961,7 +1961,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
}
os.RemoveAll(datadir)
- db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
+ db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false, false, false)
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
}
diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go
index b61eb741f..530ad035d 100644
--- a/core/blockchain_snapshot_test.go
+++ b/core/blockchain_snapshot_test.go
@@ -64,7 +64,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
}
os.RemoveAll(datadir)
- db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
+ db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false, false, false)
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
}
@@ -248,7 +248,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
db.Close()
// Start a new blockchain back up and see where the repair leads us
- newdb, err := rawdb.NewLevelDBDatabaseWithFreezer(snaptest.datadir, 0, 0, snaptest.datadir, "", false)
+ newdb, err := rawdb.NewLevelDBDatabaseWithFreezer(snaptest.datadir, 0, 0, snaptest.datadir, "", false, false, false)
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
}
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 4314bd45a..50d02e0ac 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -43,7 +43,8 @@ import (
// So we can deterministically seed different blockchains
var (
canonicalSeed = 1
- forkSeed = 2
+ forkSeed1 = 2
+ forkSeed2 = 3
TestTriesInMemory = 128
)
@@ -51,14 +52,18 @@ var (
// newCanonical creates a chain database, and injects a deterministic canonical
// chain. Depending on the full flag, if creates either a full block chain or a
// header only chain.
-func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) {
+func newCanonical(engine consensus.Engine, n int, full, pipeline bool) (ethdb.Database, *BlockChain, error) {
var (
db = rawdb.NewMemoryDatabase()
genesis = new(Genesis).MustCommit(db)
)
// Initialize a fresh chain with only a genesis block
- blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
+ var ops []BlockChainOption
+ if pipeline {
+ ops = append(ops, EnablePipelineCommit)
+ }
+ blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, ops...)
// Create and inject the requested chain
if n == 0 {
return db, blockchain, nil
@@ -76,9 +81,53 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *B
}
// Test fork of length N starting from block i
-func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) {
+func testInvalidStateRootBlockImport(t *testing.T, blockchain *BlockChain, i, n int, pipeline bool) {
+ // Copy old chain up to #i into a new db
+ db, blockchain2, err := newCanonical(ethash.NewFaker(), i, true, pipeline)
+ if err != nil {
+ t.Fatal("could not make new canonical in testFork", err)
+ }
+ defer blockchain2.Stop()
+
+ // Assert the chains have the same header/block at #i
+ hash1 := blockchain.GetBlockByNumber(uint64(i)).Hash()
+ hash2 := blockchain2.GetBlockByNumber(uint64(i)).Hash()
+ if hash1 != hash2 {
+ t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1)
+ }
+ // Extend the newly created chain
+ blockChainB := makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed1)
+ for idx, block := range blockChainB {
+ block.SetRoot(common.Hash{0: byte(forkSeed1), 19: byte(idx)})
+ }
+ previousBlock := blockchain.CurrentBlock()
+ // Sanity check that the forked chain can be imported into the original
+ if _, err := blockchain.InsertChain(blockChainB); err == nil {
+ t.Fatalf("failed to report insert error")
+ }
+
+ time.Sleep(2 * rewindBadBlockInterval)
+ latestBlock := blockchain.CurrentBlock()
+ if latestBlock.Hash() != previousBlock.Hash() || latestBlock.NumberU64() != previousBlock.NumberU64() {
+ t.Fatalf("rewind do not take effect")
+ }
+ db, blockchain3, err := newCanonical(ethash.NewFaker(), i, true, pipeline)
+ if err != nil {
+ t.Fatal("could not make new canonical in testFork", err)
+ }
+ defer blockchain3.Stop()
+
+ blockChainC := makeBlockChain(blockchain3.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed2)
+
+ if _, err := blockchain.InsertChain(blockChainC); err != nil {
+ t.Fatalf("failed to insert forking chain: %v", err)
+ }
+}
+
+// Test fork of length N starting from block i
+func testFork(t *testing.T, blockchain *BlockChain, i, n int, full, pipeline bool, comparator func(td1, td2 *big.Int)) {
// Copy old chain up to #i into a new db
- db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full)
+ db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, pipeline)
if err != nil {
t.Fatal("could not make new canonical in testFork", err)
}
@@ -102,12 +151,12 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
headerChainB []*types.Header
)
if full {
- blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed)
+ blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed1)
if _, err := blockchain2.InsertChain(blockChainB); err != nil {
t.Fatalf("failed to insert forking chain: %v", err)
}
} else {
- headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed)
+ headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed1)
if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil {
t.Fatalf("failed to insert forking chain: %v", err)
}
@@ -117,7 +166,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
if full {
tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash())
- if err := testBlockChainImport(blockChainB, blockchain); err != nil {
+ if err := testBlockChainImport(blockChainB, pipeline, blockchain); err != nil {
t.Fatalf("failed to import forked block chain: %v", err)
}
tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash())
@@ -134,7 +183,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
// testBlockChainImport tries to process a chain of blocks, writing them into
// the database if successful.
-func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
+func testBlockChainImport(chain types.Blocks, pipelineCommit bool, blockchain *BlockChain) error {
for _, block := range chain {
// Try and process the block
err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true)
@@ -151,12 +200,16 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
if err != nil {
return err
}
+ statedb.SetExpectedStateRoot(block.Root())
+ if pipelineCommit {
+ statedb.EnablePipeCommit()
+ }
statedb, receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{})
if err != nil {
blockchain.reportBlock(block, receipts, err)
return err
}
- err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas)
+ err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, pipelineCommit)
if err != nil {
blockchain.reportBlock(block, receipts, err)
return err
@@ -164,7 +217,9 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
blockchain.chainmu.Lock()
rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash())))
rawdb.WriteBlock(blockchain.db, block)
- statedb.Commit(false)
+ statedb.Finalise(false)
+ statedb.AccountsIntermediateRoot()
+ statedb.Commit(nil)
blockchain.chainmu.Unlock()
}
return nil
@@ -187,8 +242,22 @@ func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error
return nil
}
+func TestBlockImportVerification(t *testing.T) {
+ length := 5
+
+ // Make first chain starting from genesis
+ _, processor, err := newCanonical(ethash.NewFaker(), length, true, true)
+ if err != nil {
+ t.Fatalf("failed to make new canonical chain: %v", err)
+ }
+ defer processor.Stop()
+ // Start fork from current height
+ processor = EnablePipelineCommit(processor)
+ testInvalidStateRootBlockImport(t, processor, length, 10, true)
+}
+
func TestLastBlock(t *testing.T) {
- _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true)
+ _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, false)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -205,14 +274,20 @@ func TestLastBlock(t *testing.T) {
// Tests that given a starting canonical chain of a given size, it can be extended
// with various length chains.
-func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) }
-func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) }
+func TestExtendCanonicalHeaders(t *testing.T) {
+ testExtendCanonical(t, false, false)
-func testExtendCanonical(t *testing.T, full bool) {
+}
+func TestExtendCanonicalBlocks(t *testing.T) {
+ testExtendCanonical(t, true, false)
+ testExtendCanonical(t, true, true)
+}
+
+func testExtendCanonical(t *testing.T, full, pipeline bool) {
length := 5
// Make first chain starting from genesis
- _, processor, err := newCanonical(ethash.NewFaker(), length, full)
+ _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -225,22 +300,25 @@ func testExtendCanonical(t *testing.T, full bool) {
}
}
// Start fork from current height
- testFork(t, processor, length, 1, full, better)
- testFork(t, processor, length, 2, full, better)
- testFork(t, processor, length, 5, full, better)
- testFork(t, processor, length, 10, full, better)
+ testFork(t, processor, length, 1, full, pipeline, better)
+ testFork(t, processor, length, 2, full, pipeline, better)
+ testFork(t, processor, length, 5, full, pipeline, better)
+ testFork(t, processor, length, 10, full, pipeline, better)
}
// Tests that given a starting canonical chain of a given size, creating shorter
// forks do not take canonical ownership.
-func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) }
-func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) }
+func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false, false) }
+func TestShorterForkBlocks(t *testing.T) {
+ testShorterFork(t, true, false)
+ testShorterFork(t, true, true)
+}
-func testShorterFork(t *testing.T, full bool) {
+func testShorterFork(t *testing.T, full, pipeline bool) {
length := 10
// Make first chain starting from genesis
- _, processor, err := newCanonical(ethash.NewFaker(), length, full)
+ _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -253,24 +331,30 @@ func testShorterFork(t *testing.T, full bool) {
}
}
// Sum of numbers must be less than `length` for this to be a shorter fork
- testFork(t, processor, 0, 3, full, worse)
- testFork(t, processor, 0, 7, full, worse)
- testFork(t, processor, 1, 1, full, worse)
- testFork(t, processor, 1, 7, full, worse)
- testFork(t, processor, 5, 3, full, worse)
- testFork(t, processor, 5, 4, full, worse)
+ testFork(t, processor, 0, 3, full, pipeline, worse)
+ testFork(t, processor, 0, 7, full, pipeline, worse)
+ testFork(t, processor, 1, 1, full, pipeline, worse)
+ testFork(t, processor, 1, 7, full, pipeline, worse)
+ testFork(t, processor, 5, 3, full, pipeline, worse)
+ testFork(t, processor, 5, 4, full, pipeline, worse)
}
// Tests that given a starting canonical chain of a given size, creating longer
// forks do take canonical ownership.
-func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) }
-func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) }
+func TestLongerForkHeaders(t *testing.T) {
+ testLongerFork(t, false, false)
+}
+func TestLongerForkBlocks(t *testing.T) {
+ testLongerFork(t, true, false)
+ testLongerFork(t, true, true)
-func testLongerFork(t *testing.T, full bool) {
+}
+
+func testLongerFork(t *testing.T, full, pipeline bool) {
length := 10
// Make first chain starting from genesis
- _, processor, err := newCanonical(ethash.NewFaker(), length, full)
+ _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -283,24 +367,28 @@ func testLongerFork(t *testing.T, full bool) {
}
}
// Sum of numbers must be greater than `length` for this to be a longer fork
- testFork(t, processor, 0, 11, full, better)
- testFork(t, processor, 0, 15, full, better)
- testFork(t, processor, 1, 10, full, better)
- testFork(t, processor, 1, 12, full, better)
- testFork(t, processor, 5, 6, full, better)
- testFork(t, processor, 5, 8, full, better)
+ testFork(t, processor, 0, 11, full, pipeline, better)
+ testFork(t, processor, 0, 15, full, pipeline, better)
+ testFork(t, processor, 1, 10, full, pipeline, better)
+ testFork(t, processor, 1, 12, full, pipeline, better)
+ testFork(t, processor, 5, 6, full, pipeline, better)
+ testFork(t, processor, 5, 8, full, pipeline, better)
}
// Tests that given a starting canonical chain of a given size, creating equal
// forks do take canonical ownership.
-func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) }
-func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) }
+func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false, false) }
+func TestEqualForkBlocks(t *testing.T) {
+ testEqualFork(t, true, true)
+ testEqualFork(t, true, false)
+
+}
-func testEqualFork(t *testing.T, full bool) {
+func testEqualFork(t *testing.T, full, pipeline bool) {
length := 10
// Make first chain starting from genesis
- _, processor, err := newCanonical(ethash.NewFaker(), length, full)
+ _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -313,21 +401,24 @@ func testEqualFork(t *testing.T, full bool) {
}
}
// Sum of numbers must be equal to `length` for this to be an equal fork
- testFork(t, processor, 0, 10, full, equal)
- testFork(t, processor, 1, 9, full, equal)
- testFork(t, processor, 2, 8, full, equal)
- testFork(t, processor, 5, 5, full, equal)
- testFork(t, processor, 6, 4, full, equal)
- testFork(t, processor, 9, 1, full, equal)
+ testFork(t, processor, 0, 10, full, pipeline, equal)
+ testFork(t, processor, 1, 9, full, pipeline, equal)
+ testFork(t, processor, 2, 8, full, pipeline, equal)
+ testFork(t, processor, 5, 5, full, pipeline, equal)
+ testFork(t, processor, 6, 4, full, pipeline, equal)
+ testFork(t, processor, 9, 1, full, pipeline, equal)
}
// Tests that chains missing links do not get accepted by the processor.
-func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) }
-func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) }
+func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false, false) }
+func TestBrokenBlockChain(t *testing.T) {
+ testBrokenChain(t, true, false)
+ testBrokenChain(t, true, true)
+}
-func testBrokenChain(t *testing.T, full bool) {
+func testBrokenChain(t *testing.T, full, pipeline bool) {
// Make chain starting from genesis
- db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full)
+ db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -335,12 +426,12 @@ func testBrokenChain(t *testing.T, full bool) {
// Create a forked chain, and try to insert with a missing link
if full {
- chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:]
- if err := testBlockChainImport(chain, blockchain); err == nil {
+ chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed1)[1:]
+ if err := testBlockChainImport(chain, pipeline, blockchain); err == nil {
t.Errorf("broken block chain not reported")
}
} else {
- chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:]
+ chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed1)[1:]
if err := testHeaderChainImport(chain, blockchain); err == nil {
t.Errorf("broken header chain not reported")
}
@@ -349,19 +440,25 @@ func testBrokenChain(t *testing.T, full bool) {
// Tests that reorganising a long difficult chain after a short easy one
// overwrites the canonical numbers and links in the database.
-func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) }
-func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) }
+func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false, false) }
+func TestReorgLongBlocks(t *testing.T) {
+ testReorgLong(t, true, false)
+ testReorgLong(t, true, true)
+}
-func testReorgLong(t *testing.T, full bool) {
- testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full)
+func testReorgLong(t *testing.T, full, pipeline bool) {
+ testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full, pipeline)
}
// Tests that reorganising a short difficult chain after a long easy one
// overwrites the canonical numbers and links in the database.
-func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) }
-func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) }
+func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false, false) }
+func TestReorgShortBlocks(t *testing.T) {
+ testReorgShort(t, true, false)
+ testReorgShort(t, true, true)
+}
-func testReorgShort(t *testing.T, full bool) {
+func testReorgShort(t *testing.T, full, pipeline bool) {
// Create a long easy chain vs. a short heavy one. Due to difficulty adjustment
// we need a fairly long chain of blocks with different difficulties for a short
// one to become heavyer than a long one. The 96 is an empirical value.
@@ -373,12 +470,12 @@ func testReorgShort(t *testing.T, full bool) {
for i := 0; i < len(diff); i++ {
diff[i] = -9
}
- testReorg(t, easy, diff, 12615120, full)
+ testReorg(t, easy, diff, 12615120, full, pipeline)
}
-func testReorg(t *testing.T, first, second []int64, td int64, full bool) {
+func testReorg(t *testing.T, first, second []int64, td int64, full, pipeline bool) {
// Create a pristine chain and database
- db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full)
+ db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -444,12 +541,16 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) {
}
// Tests that the insertion functions detect banned hashes.
-func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) }
-func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) }
+func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false, false) }
+func TestBadBlockHashes(t *testing.T) {
+ testBadHashes(t, true, true)
+ testBadHashes(t, true, false)
-func testBadHashes(t *testing.T, full bool) {
+}
+
+func testBadHashes(t *testing.T, full, pipeline bool) {
// Create a pristine chain and database
- db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full)
+ db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -478,12 +579,16 @@ func testBadHashes(t *testing.T, full bool) {
// Tests that bad hashes are detected on boot, and the chain rolled back to a
// good state prior to the bad hash.
-func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) }
-func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) }
+func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false, false) }
+func TestReorgBadBlockHashes(t *testing.T) {
+ testReorgBadHashes(t, true, false)
+ testReorgBadHashes(t, true, true)
+
+}
-func testReorgBadHashes(t *testing.T, full bool) {
+func testReorgBadHashes(t *testing.T, full, pipeline bool) {
// Create a pristine chain and database
- db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full)
+ db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -533,13 +638,16 @@ func testReorgBadHashes(t *testing.T, full bool) {
}
// Tests chain insertions in the face of one entity containing an invalid nonce.
-func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) }
-func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) }
+func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false, false) }
+func TestBlocksInsertNonceError(t *testing.T) {
+ testInsertNonceError(t, true, false)
+ testInsertNonceError(t, true, true)
+}
-func testInsertNonceError(t *testing.T, full bool) {
+func testInsertNonceError(t *testing.T, full, pipeline bool) {
for i := 1; i < 25 && !t.Failed(); i++ {
// Create a pristine chain and database
- db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full)
+ db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -653,7 +761,7 @@ func TestFastVsFullChains(t *testing.T) {
t.Fatalf("failed to create temp freezer dir: %v", err)
}
defer os.Remove(frdir)
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
+ ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -727,7 +835,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
t.Fatalf("failed to create temp freezer dir: %v", err)
}
defer os.Remove(dir)
- db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "", false)
+ db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -1212,7 +1320,7 @@ done:
// Tests if the canonical block can be fetched from the database during chain insertion.
func TestCanonicalBlockRetrieval(t *testing.T) {
- _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true)
+ _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, false)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -1568,8 +1676,8 @@ func TestLargeReorgTrieGC(t *testing.T) {
t.Fatalf("failed to finalize competitor chain: %v", err)
}
for i, block := range competitor[:len(competitor)-TestTriesInMemory] {
- if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
- t.Fatalf("competitor %d: competing chain state missing", i)
+ if node, err := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
+ t.Fatalf("competitor %d: competing chain state missing, err: %v", i, err)
}
}
}
@@ -1594,7 +1702,7 @@ func TestBlockchainRecovery(t *testing.T) {
}
defer os.Remove(frdir)
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
+ ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -1651,7 +1759,7 @@ func TestIncompleteAncientReceiptChainInsertion(t *testing.T) {
t.Fatalf("failed to create temp freezer dir: %v", err)
}
defer os.Remove(frdir)
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
+ ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -1850,7 +1958,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
t.Fatalf("failed to create temp freezer dir: %v", err)
}
defer os.Remove(dir)
- chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "", false)
+ chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -2130,7 +2238,7 @@ func TestTransactionIndices(t *testing.T) {
t.Fatalf("failed to create temp freezer dir: %v", err)
}
defer os.Remove(frdir)
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
+ ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -2158,7 +2266,7 @@ func TestTransactionIndices(t *testing.T) {
// Init block chain with external ancients, check all needed indices has been indexed.
limit := []uint64{0, 32, 64, 128}
for _, l := range limit {
- ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
+ ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -2178,7 +2286,7 @@ func TestTransactionIndices(t *testing.T) {
}
// Reconstruct a block chain which only reserves HEAD-64 tx indices
- ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
+ ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
@@ -2257,7 +2365,7 @@ func TestSkipStaleTxIndicesInFastSync(t *testing.T) {
t.Fatalf("failed to create temp freezer dir: %v", err)
}
defer os.Remove(frdir)
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
+ ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err)
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index d8e3ee012..0e3f9256e 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -223,7 +223,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
block, _, _ := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts)
// Write state changes to db
- root, _, err := statedb.Commit(config.IsEIP158(b.header.Number))
+ root, _, err := statedb.Commit(nil)
if err != nil {
panic(fmt.Sprintf("state write error: %v", err))
}
@@ -254,9 +254,9 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
} else {
time = parent.Time() + 10 // block time is fixed at 10 seconds
}
-
+ root := state.IntermediateRoot(chain.Config().IsEIP158(parent.Number()))
return &types.Header{
- Root: state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
+ Root: root,
ParentHash: parent.Hash(),
Coinbase: parent.Coinbase(),
Difficulty: engine.CalcDifficulty(chain, time, &types.Header{
diff --git a/core/error.go b/core/error.go
index 197dd8156..0830a699f 100644
--- a/core/error.go
+++ b/core/error.go
@@ -31,6 +31,12 @@ var (
// ErrNoGenesis is returned when there is no Genesis Block.
ErrNoGenesis = errors.New("genesis not found in chain")
+
+ // ErrDiffLayerNotFound is returned when diff layer not found.
+ ErrDiffLayerNotFound = errors.New("diff layer not found")
+
+ // ErrKnownBadBlock is return when the block is a known bad block
+ ErrKnownBadBlock = errors.New("already known bad block")
)
// List of evm-call-message pre-checking errors. All state transition messages will
diff --git a/core/events.go b/core/events.go
index ac935a137..5e730a24a 100644
--- a/core/events.go
+++ b/core/events.go
@@ -24,6 +24,9 @@ import (
// NewTxsEvent is posted when a batch of transactions enter the transaction pool.
type NewTxsEvent struct{ Txs []*types.Transaction }
+// ReannoTxsEvent is posted when a batch of local pending transactions exceed a specified duration.
+type ReannoTxsEvent struct{ Txs []*types.Transaction }
+
// NewMinedBlockEvent is posted when a block has been imported.
type NewMinedBlockEvent struct{ Block *types.Block }
diff --git a/core/genesis.go b/core/genesis.go
index 930352294..94bb06dd7 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -298,7 +298,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
if g.Difficulty == nil {
head.Difficulty = params.GenesisDifficulty
}
- statedb.Commit(false)
+ statedb.Commit(nil)
statedb.Database().TrieDB().Commit(root, true, nil)
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil))
diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go
index ea9dc436c..f99511e45 100644
--- a/core/rawdb/accessors_chain_test.go
+++ b/core/rawdb/accessors_chain_test.go
@@ -440,7 +440,7 @@ func TestAncientStorage(t *testing.T) {
}
defer os.Remove(frdir)
- db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false)
+ db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false, false, false)
if err != nil {
t.Fatalf("failed to create database with ancient backend")
}
diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go
index 4dca06765..22d5188e9 100644
--- a/core/rawdb/chain_iterator.go
+++ b/core/rawdb/chain_iterator.go
@@ -35,7 +35,7 @@ import (
// injects into the database the block hash->number mappings.
func InitDatabaseFromFreezer(db ethdb.Database) {
// If we can't access the freezer or it's empty, abort
- frozen, err := db.Ancients()
+ frozen, err := db.ItemAmountInAncient()
if err != nil || frozen == 0 {
return
}
@@ -44,8 +44,9 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
start = time.Now()
logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log
hash common.Hash
+ offset = db.AncientOffSet()
)
- for i := uint64(0); i < frozen; i++ {
+ for i := uint64(0) + offset; i < frozen+offset; i++ {
// Since the freezer has all data in sequential order on a file,
// it would be 'neat' to read more data in one go, and let the
// freezerdb return N items (e.g up to 1000 items per go)
diff --git a/core/rawdb/database.go b/core/rawdb/database.go
index 82d5df06c..3342b36f3 100644
--- a/core/rawdb/database.go
+++ b/core/rawdb/database.go
@@ -20,16 +20,18 @@ import (
"bytes"
"errors"
"fmt"
+ "math/big"
"os"
"sync/atomic"
"time"
+ "github.com/olekukonko/tablewriter"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/leveldb"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/log"
- "github.com/olekukonko/tablewriter"
)
// freezerdb is a database wrapper that enabled freezer data retrievals.
@@ -112,6 +114,11 @@ func (db *nofreezedb) Ancients() (uint64, error) {
return 0, errNotSupported
}
+// Ancients returns an error as we don't have a backing chain freezer.
+func (db *nofreezedb) ItemAmountInAncient() (uint64, error) {
+ return 0, errNotSupported
+}
+
// AncientSize returns an error as we don't have a backing chain freezer.
func (db *nofreezedb) AncientSize(kind string) (uint64, error) {
return 0, errNotSupported
@@ -140,6 +147,10 @@ func (db *nofreezedb) SetDiffStore(diff ethdb.KeyValueStore) {
db.diffStore = diff
}
+func (db *nofreezedb) AncientOffSet() uint64 {
+ return 0
+}
+
// NewDatabase creates a high level database on top of a given key-value data
// store without a freezer moving immutable chain segments into cold storage.
func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
@@ -148,15 +159,69 @@ func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
}
}
+func ReadOffSetOfCurrentAncientFreezer(db ethdb.KeyValueReader) uint64 {
+ offset, _ := db.Get(offSetOfCurrentAncientFreezer)
+ if offset == nil {
+ return 0
+ }
+ return new(big.Int).SetBytes(offset).Uint64()
+}
+
+func ReadOffSetOfLastAncientFreezer(db ethdb.KeyValueReader) uint64 {
+ offset, _ := db.Get(offSetOfLastAncientFreezer)
+ if offset == nil {
+ return 0
+ }
+ return new(big.Int).SetBytes(offset).Uint64()
+}
+
+func WriteOffSetOfCurrentAncientFreezer(db ethdb.KeyValueWriter, offset uint64) {
+ if err := db.Put(offSetOfCurrentAncientFreezer, new(big.Int).SetUint64(offset).Bytes()); err != nil {
+ log.Crit("Failed to store offSetOfAncientFreezer", "err", err)
+ }
+}
+func WriteOffSetOfLastAncientFreezer(db ethdb.KeyValueWriter, offset uint64) {
+ if err := db.Put(offSetOfLastAncientFreezer, new(big.Int).SetUint64(offset).Bytes()); err != nil {
+ log.Crit("Failed to store offSetOfAncientFreezer", "err", err)
+ }
+}
+
+// NewFreezerDb only create a freezer without statedb.
+func NewFreezerDb(db ethdb.KeyValueStore, frz, namespace string, readonly bool, newOffSet uint64) (*freezer, error) {
+ // Create the idle freezer instance, this operation should be atomic to avoid mismatch between offset and acientDB.
+ frdb, err := newFreezer(frz, namespace, readonly)
+ if err != nil {
+ return nil, err
+ }
+ frdb.offset = newOffSet
+ frdb.frozen += newOffSet
+ return frdb, nil
+}
+
// NewDatabaseWithFreezer creates a high level database on top of a given key-
// value data store with a freezer moving immutable chain segments into cold
// storage.
-func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string, readonly bool) (ethdb.Database, error) {
+func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string, readonly, disableFreeze, isLastOffset bool) (ethdb.Database, error) {
// Create the idle freezer instance
frdb, err := newFreezer(freezer, namespace, readonly)
if err != nil {
return nil, err
}
+
+ var offset uint64
+ // The offset of ancientDB should be handled differently in different scenarios.
+ if isLastOffset {
+ offset = ReadOffSetOfLastAncientFreezer(db)
+ } else {
+ offset = ReadOffSetOfCurrentAncientFreezer(db)
+ }
+
+ frdb.offset = offset
+
+ // Some blocks in ancientDB may have already been frozen and been pruned, so adding the offset to
+ // reprensent the absolute number of blocks already frozen.
+ frdb.frozen += offset
+
// Since the freezer can be stored separately from the user's key-value database,
// there's a fairly high probability that the user requests invalid combinations
// of the freezer and database. Ensure that we don't shoot ourselves in the foot
@@ -179,7 +244,10 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
// If the genesis hash is empty, we have a new key-value store, so nothing to
// validate in this method. If, however, the genesis hash is not nil, compare
// it to the freezer content.
- if kvgenesis, _ := db.Get(headerHashKey(0)); len(kvgenesis) > 0 {
+ // Only to check the followings when offset equal to 0, otherwise the block number
+ // in ancientdb did not start with 0, no genesis block in ancientdb as well.
+
+ if kvgenesis, _ := db.Get(headerHashKey(0)); offset == 0 && len(kvgenesis) > 0 {
if frozen, _ := frdb.Ancients(); frozen > 0 {
// If the freezer already contains something, ensure that the genesis blocks
// match, otherwise we might mix up freezers across chains and destroy both
@@ -221,8 +289,9 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
// feezer.
}
}
+
// Freezer is consistent with the key-value database, permit combining the two
- if !frdb.readonly {
+ if !disableFreeze && !frdb.readonly {
go frdb.freeze(db)
}
return &freezerdb{
@@ -256,12 +325,12 @@ func NewLevelDBDatabase(file string, cache int, handles int, namespace string, r
// NewLevelDBDatabaseWithFreezer creates a persistent key-value database with a
// freezer moving immutable chain segments into cold storage.
-func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string, readonly bool) (ethdb.Database, error) {
+func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string, readonly, disableFreeze, isLastOffset bool) (ethdb.Database, error) {
kvdb, err := leveldb.New(file, cache, handles, namespace, readonly)
if err != nil {
return nil, err
}
- frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace, readonly)
+ frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace, readonly, disableFreeze, isLastOffset)
if err != nil {
kvdb.Close()
return nil, err
@@ -298,6 +367,35 @@ func (s *stat) Size() string {
func (s *stat) Count() string {
return s.count.String()
}
+func AncientInspect(db ethdb.Database) error {
+ offset := counter(ReadOffSetOfCurrentAncientFreezer(db))
+ // Get number of ancient rows inside the freezer.
+ ancients := counter(0)
+ if count, err := db.ItemAmountInAncient(); err != nil {
+ log.Error("failed to get the items amount in ancientDB", "err", err)
+ return err
+ } else {
+ ancients = counter(count)
+ }
+ var endNumber counter
+ if offset+ancients <= 0 {
+ endNumber = 0
+ } else {
+ endNumber = offset + ancients - 1
+ }
+ stats := [][]string{
+ {"Offset/StartBlockNumber", "Offset/StartBlockNumber of ancientDB", offset.String()},
+ {"Amount of remained items in AncientStore", "Remaining items of ancientDB", ancients.String()},
+ {"The last BlockNumber within ancientDB", "The last BlockNumber", endNumber.String()},
+ }
+ table := tablewriter.NewWriter(os.Stdout)
+ table.SetHeader([]string{"Database", "Category", "Items"})
+ table.SetFooter([]string{"", "AncientStore information", ""})
+ table.AppendBulk(stats)
+ table.Render()
+
+ return nil
+}
// InspectDatabase traverses the entire database and checks the size
// of all different categories of data.
@@ -431,9 +529,10 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
}
// Get number of ancient rows inside the freezer
ancients := counter(0)
- if count, err := db.Ancients(); err == nil {
+ if count, err := db.ItemAmountInAncient(); err == nil {
ancients = counter(count)
}
+
// Display the database statistic.
stats := [][]string{
{"Key-Value store", "Headers", headers.Size(), headers.Count()},
diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go
index 94b99a64e..92dfc9604 100644
--- a/core/rawdb/freezer.go
+++ b/core/rawdb/freezer.go
@@ -85,6 +85,8 @@ type freezer struct {
quit chan struct{}
closeOnce sync.Once
+
+ offset uint64 // Starting BlockNumber in current freezer
}
// newFreezer creates a chain freezer that moves ancient chain data into
@@ -164,7 +166,7 @@ func (f *freezer) Close() error {
// in the freezer.
func (f *freezer) HasAncient(kind string, number uint64) (bool, error) {
if table := f.tables[kind]; table != nil {
- return table.has(number), nil
+ return table.has(number - f.offset), nil
}
return false, nil
}
@@ -172,7 +174,7 @@ func (f *freezer) HasAncient(kind string, number uint64) (bool, error) {
// Ancient retrieves an ancient binary blob from the append-only immutable files.
func (f *freezer) Ancient(kind string, number uint64) ([]byte, error) {
if table := f.tables[kind]; table != nil {
- return table.Retrieve(number)
+ return table.Retrieve(number - f.offset)
}
return nil, errUnknownTable
}
@@ -182,6 +184,16 @@ func (f *freezer) Ancients() (uint64, error) {
return atomic.LoadUint64(&f.frozen), nil
}
+// ItemAmountInAncient returns the actual length of current ancientDB.
+func (f *freezer) ItemAmountInAncient() (uint64, error) {
+ return atomic.LoadUint64(&f.frozen) - atomic.LoadUint64(&f.offset), nil
+}
+
+// AncientOffSet returns the offset of current ancientDB.
+func (f *freezer) AncientOffSet() uint64 {
+ return atomic.LoadUint64(&f.offset)
+}
+
// AncientSize returns the ancient size of the specified category.
func (f *freezer) AncientSize(kind string) (uint64, error) {
if table := f.tables[kind]; table != nil {
@@ -216,23 +228,23 @@ func (f *freezer) AppendAncient(number uint64, hash, header, body, receipts, td
}
}()
// Inject all the components into the relevant data tables
- if err := f.tables[freezerHashTable].Append(f.frozen, hash[:]); err != nil {
+ if err := f.tables[freezerHashTable].Append(f.frozen-f.offset, hash[:]); err != nil {
log.Error("Failed to append ancient hash", "number", f.frozen, "hash", hash, "err", err)
return err
}
- if err := f.tables[freezerHeaderTable].Append(f.frozen, header); err != nil {
+ if err := f.tables[freezerHeaderTable].Append(f.frozen-f.offset, header); err != nil {
log.Error("Failed to append ancient header", "number", f.frozen, "hash", hash, "err", err)
return err
}
- if err := f.tables[freezerBodiesTable].Append(f.frozen, body); err != nil {
+ if err := f.tables[freezerBodiesTable].Append(f.frozen-f.offset, body); err != nil {
log.Error("Failed to append ancient body", "number", f.frozen, "hash", hash, "err", err)
return err
}
- if err := f.tables[freezerReceiptTable].Append(f.frozen, receipts); err != nil {
+ if err := f.tables[freezerReceiptTable].Append(f.frozen-f.offset, receipts); err != nil {
log.Error("Failed to append ancient receipts", "number", f.frozen, "hash", hash, "err", err)
return err
}
- if err := f.tables[freezerDifficultyTable].Append(f.frozen, td); err != nil {
+ if err := f.tables[freezerDifficultyTable].Append(f.frozen-f.offset, td); err != nil {
log.Error("Failed to append ancient difficulty", "number", f.frozen, "hash", hash, "err", err)
return err
}
@@ -249,7 +261,7 @@ func (f *freezer) TruncateAncients(items uint64) error {
return nil
}
for _, table := range f.tables {
- if err := table.truncate(items); err != nil {
+ if err := table.truncate(items - f.offset); err != nil {
return err
}
}
diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go
index b4fb99e45..ece5006c3 100644
--- a/core/rawdb/schema.go
+++ b/core/rawdb/schema.go
@@ -69,6 +69,12 @@ var (
// fastTxLookupLimitKey tracks the transaction lookup limit during fast sync.
fastTxLookupLimitKey = []byte("FastTransactionLookupLimit")
+ //offSet of new updated ancientDB.
+ offSetOfCurrentAncientFreezer = []byte("offSetOfCurrentAncientFreezer")
+
+ //offSet of the ancientDB before updated version.
+ offSetOfLastAncientFreezer = []byte("offSetOfLastAncientFreezer")
+
// badBlockKey tracks the list of bad blocks seen by local
badBlockKey = []byte("InvalidBlock")
diff --git a/core/rawdb/table.go b/core/rawdb/table.go
index a27f5f8ed..0dcaf8cfb 100644
--- a/core/rawdb/table.go
+++ b/core/rawdb/table.go
@@ -68,6 +68,16 @@ func (t *table) Ancients() (uint64, error) {
return t.db.Ancients()
}
+// ItemAmountInAncient returns the actual length of current ancientDB.
+func (t *table) ItemAmountInAncient() (uint64, error) {
+ return t.db.ItemAmountInAncient()
+}
+
+// AncientOffSet returns the offset of current ancientDB.
+func (t *table) AncientOffSet() uint64 {
+ return t.db.AncientOffSet()
+}
+
// AncientSize is a noop passthrough that just forwards the request to the underlying
// database.
func (t *table) AncientSize(kind string) (uint64, error) {
diff --git a/core/state/database.go b/core/state/database.go
index b65dfca15..487589324 100644
--- a/core/state/database.go
+++ b/core/state/database.go
@@ -257,6 +257,9 @@ func (db *cachingDB) Purge() {
// CopyTrie returns an independent copy of the given trie.
func (db *cachingDB) CopyTrie(t Trie) Trie {
+ if t == nil {
+ return nil
+ }
switch t := t.(type) {
case *trie.SecureTrie:
return t.Copy()
diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go
index bb599fcd8..5b070f3af 100644
--- a/core/state/pruner/pruner.go
+++ b/core/state/pruner/pruner.go
@@ -27,7 +27,10 @@ import (
"strings"
"time"
+ "github.com/prometheus/tsdb/fileutil"
+
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot"
@@ -35,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
@@ -85,6 +89,14 @@ type Pruner struct {
triesInMemory uint64
}
+type BlockPruner struct {
+ db ethdb.Database
+ oldAncientPath string
+ newAncientPath string
+ node *node.Node
+ BlockAmountReserved uint64
+}
+
// NewPruner creates the pruner instance.
func NewPruner(db ethdb.Database, datadir, trieCachePath string, bloomSize, triesInMemory uint64) (*Pruner, error) {
headBlock := rawdb.ReadHeadBlock(db)
@@ -101,6 +113,7 @@ func NewPruner(db ethdb.Database, datadir, trieCachePath string, bloomSize, trie
bloomSize = 256
}
stateBloom, err := newStateBloomWithSize(bloomSize)
+
if err != nil {
return nil, err
}
@@ -115,6 +128,16 @@ func NewPruner(db ethdb.Database, datadir, trieCachePath string, bloomSize, trie
}, nil
}
+func NewBlockPruner(db ethdb.Database, n *node.Node, oldAncientPath, newAncientPath string, BlockAmountReserved uint64) *BlockPruner {
+ return &BlockPruner{
+ db: db,
+ oldAncientPath: oldAncientPath,
+ newAncientPath: newAncientPath,
+ node: n,
+ BlockAmountReserved: BlockAmountReserved,
+ }
+}
+
func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, stateBloom *stateBloom, bloomPath string, middleStateRoots map[common.Hash]struct{}, start time.Time) error {
// Delete all stale trie nodes in the disk. With the help of state bloom
// the trie nodes(and codes) belong to the active state will be filtered
@@ -233,6 +256,194 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta
return nil
}
+func (p *BlockPruner) backUpOldDb(name string, cache, handles int, namespace string, readonly, interrupt bool) error {
+ // Open old db wrapper.
+ chainDb, err := p.node.OpenDatabaseWithFreezer(name, cache, handles, p.oldAncientPath, namespace, readonly, true, interrupt)
+ if err != nil {
+ log.Error("Failed to open ancient database", "err=", err)
+ return err
+ }
+ defer chainDb.Close()
+ log.Info("chainDB opened successfully")
+
+ // Get the number of items in old ancient db.
+ itemsOfAncient, err := chainDb.ItemAmountInAncient()
+ log.Info("the number of items in ancientDB is ", "itemsOfAncient", itemsOfAncient)
+
+ // If we can't access the freezer or it's empty, abort.
+ if err != nil || itemsOfAncient == 0 {
+ log.Error("can't access the freezer or it's empty, abort")
+ return errors.New("can't access the freezer or it's empty, abort")
+ }
+
+ // If the items in freezer is less than the block amount that we want to reserve, it is not enough, should stop.
+ if itemsOfAncient < p.BlockAmountReserved {
+ log.Error("the number of old blocks is not enough to reserve,", "ancient items", itemsOfAncient, "the amount specified", p.BlockAmountReserved)
+ return errors.New("the number of old blocks is not enough to reserve")
+ }
+
+ var oldOffSet uint64
+ if interrupt {
+ // The interrupt scecario within this function is specific for old and new ancientDB exsisted concurrently,
+ // should use last version of offset for oldAncientDB, because current offset is
+ // actually of the new ancientDB_Backup, but what we want is the offset of ancientDB being backup.
+ oldOffSet = rawdb.ReadOffSetOfLastAncientFreezer(chainDb)
+ } else {
+ // Using current version of ancientDB for oldOffSet because the db for backup is current version.
+ oldOffSet = rawdb.ReadOffSetOfCurrentAncientFreezer(chainDb)
+ }
+ log.Info("the oldOffSet is ", "oldOffSet", oldOffSet)
+
+ // Get the start BlockNumber for pruning.
+ startBlockNumber := oldOffSet + itemsOfAncient - p.BlockAmountReserved
+ log.Info("new offset/new startBlockNumber is ", "new offset", startBlockNumber)
+
+ // Create new ancientdb backup and record the new and last version of offset in kvDB as well.
+ // For every round, newoffset actually equals to the startBlockNumber in ancient backup db.
+ frdbBack, err := rawdb.NewFreezerDb(chainDb, p.newAncientPath, namespace, readonly, startBlockNumber)
+ if err != nil {
+ log.Error("Failed to create ancient freezer backup", "err=", err)
+ return err
+ }
+ defer frdbBack.Close()
+
+ offsetBatch := chainDb.NewBatch()
+ rawdb.WriteOffSetOfCurrentAncientFreezer(offsetBatch, startBlockNumber)
+ rawdb.WriteOffSetOfLastAncientFreezer(offsetBatch, oldOffSet)
+ if err := offsetBatch.Write(); err != nil {
+ log.Crit("Failed to write offset into disk", "err", err)
+ }
+
+ // It's guaranteed that the old/new offsets are updated as well as the new ancientDB are created if this flock exist.
+ lock, _, err := fileutil.Flock(filepath.Join(p.newAncientPath, "PRUNEFLOCKBACK"))
+ if err != nil {
+ log.Error("file lock error", "err", err)
+ return err
+ }
+
+ log.Info("prune info", "old offset", oldOffSet, "number of items in ancientDB", itemsOfAncient, "amount to reserve", p.BlockAmountReserved)
+ log.Info("new offset/new startBlockNumber recorded successfully ", "new offset", startBlockNumber)
+
+ start := time.Now()
+ // All ancient data after and including startBlockNumber should write into new ancientDB ancient_back.
+ for blockNumber := startBlockNumber; blockNumber < itemsOfAncient+oldOffSet; blockNumber++ {
+ blockHash := rawdb.ReadCanonicalHash(chainDb, blockNumber)
+ block := rawdb.ReadBlock(chainDb, blockHash, blockNumber)
+ receipts := rawdb.ReadRawReceipts(chainDb, blockHash, blockNumber)
+ // Calculate the total difficulty of the block
+ td := rawdb.ReadTd(chainDb, blockHash, blockNumber)
+ if td == nil {
+ return consensus.ErrUnknownAncestor
+ }
+ // Write into new ancient_back db.
+ rawdb.WriteAncientBlock(frdbBack, block, receipts, td)
+ // Print the log every 5s for better trace.
+ if common.PrettyDuration(time.Since(start)) > common.PrettyDuration(5*time.Second) {
+ log.Info("block backup process running successfully", "current blockNumber for backup", blockNumber)
+ start = time.Now()
+ }
+ }
+ lock.Release()
+ log.Info("block back up done", "current start blockNumber in ancientDB", startBlockNumber)
+ return nil
+}
+
+// Backup the ancient data for the old ancient db, i.e. the most recent 128 blocks in ancient db.
+func (p *BlockPruner) BlockPruneBackUp(name string, cache, handles int, namespace string, readonly, interrupt bool) error {
+
+ start := time.Now()
+
+ if err := p.backUpOldDb(name, cache, handles, namespace, readonly, interrupt); err != nil {
+ return err
+ }
+
+ log.Info("Block pruning BackUp successfully", "time duration since start is", common.PrettyDuration(time.Since(start)))
+ return nil
+}
+
+func (p *BlockPruner) RecoverInterruption(name string, cache, handles int, namespace string, readonly bool) error {
+ log.Info("RecoverInterruption for block prune")
+ newExist, err := CheckFileExist(p.newAncientPath)
+ if err != nil {
+ log.Error("newAncientDb path error")
+ return err
+ }
+
+ if newExist {
+ log.Info("New ancientDB_backup existed in interruption scenario")
+ flockOfAncientBack, err := CheckFileExist(filepath.Join(p.newAncientPath, "PRUNEFLOCKBACK"))
+ if err != nil {
+ log.Error("Failed to check flock of ancientDB_Back %v", err)
+ return err
+ }
+
+ // Indicating both old and new ancientDB existed concurrently.
+ // Delete directly for the new ancientdb to prune from start, e.g.: path ../chaindb/ancient_backup
+ if err := os.RemoveAll(p.newAncientPath); err != nil {
+ log.Error("Failed to remove old ancient directory %v", err)
+ return err
+ }
+ if flockOfAncientBack {
+ // Indicating the oldOffset/newOffset have already been updated.
+ if err := p.BlockPruneBackUp(name, cache, handles, namespace, readonly, true); err != nil {
+ log.Error("Failed to prune")
+ return err
+ }
+ } else {
+ // Indicating the flock did not exist and the new offset did not be updated, so just handle this case as usual.
+ if err := p.BlockPruneBackUp(name, cache, handles, namespace, readonly, false); err != nil {
+ log.Error("Failed to prune")
+ return err
+ }
+ }
+
+ if err := p.AncientDbReplacer(); err != nil {
+ log.Error("Failed to replace ancientDB")
+ return err
+ }
+ } else {
+ log.Info("New ancientDB_backup did not exist in interruption scenario")
+ // Indicating new ancientDB even did not be created, just prune starting at backup from startBlockNumber as usual,
+ // in this case, the new offset have not been written into kvDB.
+ if err := p.BlockPruneBackUp(name, cache, handles, namespace, readonly, false); err != nil {
+ log.Error("Failed to prune")
+ return err
+ }
+ if err := p.AncientDbReplacer(); err != nil {
+ log.Error("Failed to replace ancientDB")
+ return err
+ }
+ }
+
+ return nil
+}
+
+func CheckFileExist(path string) (bool, error) {
+ if _, err := os.Stat(path); err != nil {
+ if os.IsNotExist(err) {
+ // Indicating the file didn't exist.
+ return false, nil
+ }
+ return true, err
+ }
+ return true, nil
+}
+
+func (p *BlockPruner) AncientDbReplacer() error {
+ // Delete directly for the old ancientdb, e.g.: path ../chaindb/ancient
+ if err := os.RemoveAll(p.oldAncientPath); err != nil {
+ log.Error("Failed to remove old ancient directory %v", err)
+ return err
+ }
+
+ // Rename the new ancientdb path same to the old
+ if err := os.Rename(p.newAncientPath, p.oldAncientPath); err != nil {
+ log.Error("Failed to rename new ancient directory")
+ return err
+ }
+ return nil
+}
+
// Prune deletes all historical state nodes except the nodes belong to the
// specified state version. If user doesn't specify the state version, use
// the bottom-most snapshot diff layer as the target.
diff --git a/core/state/snapshot/difflayer.go b/core/state/snapshot/difflayer.go
index c0f0dab56..65b2729d9 100644
--- a/core/state/snapshot/difflayer.go
+++ b/core/state/snapshot/difflayer.go
@@ -118,6 +118,9 @@ type diffLayer struct {
storageList map[common.Hash][]common.Hash // List of storage slots for iterated retrievals, one per account. Any existing lists are sorted if non-nil
storageData map[common.Hash]map[common.Hash][]byte // Keyed storage slots for direct retrieval. one per account (nil means deleted)
+ verifiedCh chan struct{} // the difflayer is verified when verifiedCh is nil or closed
+ valid bool // mark the difflayer is valid or not.
+
diffed *bloomfilter.Filter // Bloom filter tracking all the diffed items up to the disk layer
lock sync.RWMutex
@@ -168,7 +171,7 @@ func (h storageBloomHasher) Sum64() uint64 {
// newDiffLayer creates a new diff on top of an existing snapshot, whether that's a low
// level persistent database or a hierarchical diff already.
-func newDiffLayer(parent snapshot, root common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer {
+func newDiffLayer(parent snapshot, root common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte, verified chan struct{}) *diffLayer {
// Create the new layer with some pre-allocated data segments
dl := &diffLayer{
parent: parent,
@@ -177,6 +180,7 @@ func newDiffLayer(parent snapshot, root common.Hash, destructs map[common.Hash]s
accountData: accounts,
storageData: storage,
storageList: make(map[common.Hash][]common.Hash),
+ verifiedCh: verified,
}
switch parent := parent.(type) {
case *diskLayer:
@@ -256,6 +260,32 @@ func (dl *diffLayer) Root() common.Hash {
return dl.root
}
+// WaitAndGetVerifyRes will wait until the diff layer been verified and return the verification result
+func (dl *diffLayer) WaitAndGetVerifyRes() bool {
+ if dl.verifiedCh == nil {
+ return true
+ }
+ <-dl.verifiedCh
+ return dl.valid
+}
+
+func (dl *diffLayer) MarkValid() {
+ dl.valid = true
+}
+
+// Represent whether the difflayer is been verified, does not means it is a valid or invalid difflayer
+func (dl *diffLayer) Verified() bool {
+ if dl.verifiedCh == nil {
+ return true
+ }
+ select {
+ case <-dl.verifiedCh:
+ return true
+ default:
+ return false
+ }
+}
+
// Parent returns the subsequent layer of a diff layer.
func (dl *diffLayer) Parent() snapshot {
return dl.parent
@@ -423,8 +453,8 @@ func (dl *diffLayer) storage(accountHash, storageHash common.Hash, depth int) ([
// Update creates a new layer on top of the existing snapshot diff tree with
// the specified data items.
-func (dl *diffLayer) Update(blockRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer {
- return newDiffLayer(dl, blockRoot, destructs, accounts, storage)
+func (dl *diffLayer) Update(blockRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte, verified chan struct{}) *diffLayer {
+ return newDiffLayer(dl, blockRoot, destructs, accounts, storage, verified)
}
// flatten pushes all data from this point downwards, flattening everything into
diff --git a/core/state/snapshot/difflayer_test.go b/core/state/snapshot/difflayer_test.go
index 919af5fa8..5311a0d68 100644
--- a/core/state/snapshot/difflayer_test.go
+++ b/core/state/snapshot/difflayer_test.go
@@ -79,11 +79,11 @@ func TestMergeBasics(t *testing.T) {
}
}
// Add some (identical) layers on top
- parent := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage))
- child := newDiffLayer(parent, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage))
- child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage))
- child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage))
- child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage))
+ parent := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage), nil)
+ child := newDiffLayer(parent, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage), nil)
+ child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage), nil)
+ child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage), nil)
+ child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage), nil)
// And flatten
merged := (child.flatten()).(*diffLayer)
@@ -151,13 +151,13 @@ func TestMergeDelete(t *testing.T) {
}
}
// Add some flipAccs-flopping layers on top
- parent := newDiffLayer(emptyLayer(), common.Hash{}, flipDrops(), flipAccs(), storage)
- child := parent.Update(common.Hash{}, flopDrops(), flopAccs(), storage)
- child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage)
- child = child.Update(common.Hash{}, flopDrops(), flopAccs(), storage)
- child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage)
- child = child.Update(common.Hash{}, flopDrops(), flopAccs(), storage)
- child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage)
+ parent := newDiffLayer(emptyLayer(), common.Hash{}, flipDrops(), flipAccs(), storage, nil)
+ child := parent.Update(common.Hash{}, flopDrops(), flopAccs(), storage, nil)
+ child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage, nil)
+ child = child.Update(common.Hash{}, flopDrops(), flopAccs(), storage, nil)
+ child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage, nil)
+ child = child.Update(common.Hash{}, flopDrops(), flopAccs(), storage, nil)
+ child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage, nil)
if data, _ := child.Account(h1); data == nil {
t.Errorf("last diff layer: expected %x account to be non-nil", h1)
@@ -209,7 +209,7 @@ func TestInsertAndMerge(t *testing.T) {
accounts = make(map[common.Hash][]byte)
storage = make(map[common.Hash]map[common.Hash][]byte)
)
- parent = newDiffLayer(emptyLayer(), common.Hash{}, destructs, accounts, storage)
+ parent = newDiffLayer(emptyLayer(), common.Hash{}, destructs, accounts, storage, nil)
}
{
var (
@@ -220,7 +220,7 @@ func TestInsertAndMerge(t *testing.T) {
accounts[acc] = randomAccount()
storage[acc] = make(map[common.Hash][]byte)
storage[acc][slot] = []byte{0x01}
- child = newDiffLayer(parent, common.Hash{}, destructs, accounts, storage)
+ child = newDiffLayer(parent, common.Hash{}, destructs, accounts, storage, nil)
}
// And flatten
merged := (child.flatten()).(*diffLayer)
@@ -256,7 +256,7 @@ func BenchmarkSearch(b *testing.B) {
for i := 0; i < 10000; i++ {
accounts[randomHash()] = randomAccount()
}
- return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage)
+ return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage, nil)
}
var layer snapshot
layer = emptyLayer()
@@ -298,7 +298,7 @@ func BenchmarkSearchSlot(b *testing.B) {
accStorage[randomHash()] = value
storage[accountKey] = accStorage
}
- return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage)
+ return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage, nil)
}
var layer snapshot
layer = emptyLayer()
@@ -336,7 +336,7 @@ func BenchmarkFlatten(b *testing.B) {
}
storage[accountKey] = accStorage
}
- return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage)
+ return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage, nil)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -386,7 +386,7 @@ func BenchmarkJournal(b *testing.B) {
}
storage[accountKey] = accStorage
}
- return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage)
+ return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage, nil)
}
layer := snapshot(new(diskLayer))
for i := 1; i < 128; i++ {
diff --git a/core/state/snapshot/disklayer.go b/core/state/snapshot/disklayer.go
index 7cbf6e293..c1de41782 100644
--- a/core/state/snapshot/disklayer.go
+++ b/core/state/snapshot/disklayer.go
@@ -49,6 +49,16 @@ func (dl *diskLayer) Root() common.Hash {
return dl.root
}
+func (dl *diskLayer) WaitAndGetVerifyRes() bool {
+ return true
+}
+
+func (dl *diskLayer) MarkValid() {}
+
+func (dl *diskLayer) Verified() bool {
+ return true
+}
+
// Parent always returns nil as there's no layer below the disk.
func (dl *diskLayer) Parent() snapshot {
return nil
@@ -161,6 +171,6 @@ func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
// Update creates a new layer on top of the existing snapshot diff tree with
// the specified data items. Note, the maps are retained by the method to avoid
// copying everything.
-func (dl *diskLayer) Update(blockHash common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer {
- return newDiffLayer(dl, blockHash, destructs, accounts, storage)
+func (dl *diskLayer) Update(blockHash common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte, verified chan struct{}) *diffLayer {
+ return newDiffLayer(dl, blockHash, destructs, accounts, storage, verified)
}
diff --git a/core/state/snapshot/disklayer_test.go b/core/state/snapshot/disklayer_test.go
index 362edba90..689ed3877 100644
--- a/core/state/snapshot/disklayer_test.go
+++ b/core/state/snapshot/disklayer_test.go
@@ -134,7 +134,7 @@ func TestDiskMerge(t *testing.T) {
conModCache: {conModCacheSlot: reverse(conModCacheSlot[:])},
conDelNoCache: {conDelNoCacheSlot: nil},
conDelCache: {conDelCacheSlot: nil},
- }); err != nil {
+ }, nil); err != nil {
t.Fatalf("failed to update snapshot tree: %v", err)
}
if err := snaps.Cap(diffRoot, 0); err != nil {
@@ -357,7 +357,7 @@ func TestDiskPartialMerge(t *testing.T) {
conModCache: {conModCacheSlot: reverse(conModCacheSlot[:])},
conDelNoCache: {conDelNoCacheSlot: nil},
conDelCache: {conDelCacheSlot: nil},
- }); err != nil {
+ }, nil); err != nil {
t.Fatalf("test %d: failed to update snapshot tree: %v", i, err)
}
if err := snaps.Cap(diffRoot, 0); err != nil {
@@ -468,7 +468,7 @@ func TestDiskGeneratorPersistence(t *testing.T) {
// Modify or delete some accounts, flatten everything onto disk
if err := snaps.update(diffRoot, baseRoot, nil, map[common.Hash][]byte{
accTwo: accTwo[:],
- }, nil); err != nil {
+ }, nil, nil); err != nil {
t.Fatalf("failed to update snapshot tree: %v", err)
}
if err := snaps.Cap(diffRoot, 0); err != nil {
@@ -488,7 +488,7 @@ func TestDiskGeneratorPersistence(t *testing.T) {
accThree: accThree.Bytes(),
}, map[common.Hash]map[common.Hash][]byte{
accThree: {accThreeSlot: accThreeSlot.Bytes()},
- }); err != nil {
+ }, nil); err != nil {
t.Fatalf("failed to update snapshot tree: %v", err)
}
diskLayer := snaps.layers[snaps.diskRoot()].(*diskLayer)
diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go
index 7e29e51b2..a9f89b20b 100644
--- a/core/state/snapshot/generate.go
+++ b/core/state/snapshot/generate.go
@@ -560,6 +560,12 @@ func (dl *diskLayer) generate(stats *generatorStats) {
default:
}
if batch.ValueSize() > ethdb.IdealBatchSize || abort != nil {
+ if bytes.Compare(currentLocation, dl.genMarker) < 0 {
+ log.Error("Snapshot generator went backwards",
+ "currentLocation", fmt.Sprintf("%x", currentLocation),
+ "genMarker", fmt.Sprintf("%x", dl.genMarker))
+ }
+
// Flush out the batch anyway no matter it's empty or not.
// It's possible that all the states are recovered and the
// generation indeed makes progress.
@@ -634,8 +640,14 @@ func (dl *diskLayer) generate(stats *generatorStats) {
stats.storage += common.StorageSize(1 + common.HashLength + dataLen)
stats.accounts++
}
+ marker := accountHash[:]
+ // If the snap generation goes here after interrupted, genMarker may go backward
+ // when last genMarker is consisted of accountHash and storageHash
+ if accMarker != nil && bytes.Equal(marker, accMarker) && len(dl.genMarker) > common.HashLength {
+ marker = dl.genMarker[:]
+ }
// If we've exceeded our batch allowance or termination was requested, flush to disk
- if err := checkAndFlush(accountHash[:]); err != nil {
+ if err := checkAndFlush(marker); err != nil {
return err
}
// If the iterated account is the contract, create a further loop to
diff --git a/core/state/snapshot/iterator_test.go b/core/state/snapshot/iterator_test.go
index 2a27b0157..3ffaff32e 100644
--- a/core/state/snapshot/iterator_test.go
+++ b/core/state/snapshot/iterator_test.go
@@ -53,7 +53,7 @@ func TestAccountIteratorBasics(t *testing.T) {
}
}
// Add some (identical) layers on top
- diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage))
+ diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage), nil)
it := diffLayer.AccountIterator(common.Hash{})
verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator
@@ -91,7 +91,7 @@ func TestStorageIteratorBasics(t *testing.T) {
nilStorage[h] = nilstorage
}
// Add some (identical) layers on top
- diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, nil, copyAccounts(accounts), copyStorage(storage))
+ diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, nil, copyAccounts(accounts), copyStorage(storage), nil)
for account := range accounts {
it, _ := diffLayer.StorageIterator(account, common.Hash{})
verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator
@@ -222,13 +222,13 @@ func TestAccountIteratorTraversal(t *testing.T) {
}
// Stack three diff layers on top with various overlaps
snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil,
- randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil)
+ randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil, nil)
snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil,
- randomAccountSet("0xbb", "0xdd", "0xf0"), nil)
+ randomAccountSet("0xbb", "0xdd", "0xf0"), nil, nil)
snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil,
- randomAccountSet("0xcc", "0xf0", "0xff"), nil)
+ randomAccountSet("0xcc", "0xf0", "0xff"), nil, nil)
// Verify the single and multi-layer iterators
head := snaps.Snapshot(common.HexToHash("0x04"))
@@ -269,13 +269,13 @@ func TestStorageIteratorTraversal(t *testing.T) {
}
// Stack three diff layers on top with various overlaps
snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil), nil)
snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x04", "0x05", "0x06"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x04", "0x05", "0x06"}}, nil), nil)
snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil), nil)
// Verify the single and multi-layer iterators
head := snaps.Snapshot(common.HexToHash("0x04"))
@@ -353,14 +353,14 @@ func TestAccountIteratorTraversalValues(t *testing.T) {
}
}
// Assemble a stack of snapshots from the account layers
- snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, a, nil)
- snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, b, nil)
- snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, c, nil)
- snaps.update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, d, nil)
- snaps.update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, e, nil)
- snaps.update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, f, nil)
- snaps.update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, g, nil)
- snaps.update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, h, nil)
+ snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, a, nil, nil)
+ snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, b, nil, nil)
+ snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, c, nil, nil)
+ snaps.update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, d, nil, nil)
+ snaps.update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, e, nil, nil)
+ snaps.update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, f, nil, nil)
+ snaps.update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, g, nil, nil)
+ snaps.update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, h, nil, nil)
it, _ := snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{})
head := snaps.Snapshot(common.HexToHash("0x09"))
@@ -452,14 +452,14 @@ func TestStorageIteratorTraversalValues(t *testing.T) {
}
}
// Assemble a stack of snapshots from the account layers
- snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, randomAccountSet("0xaa"), wrapStorage(a))
- snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, randomAccountSet("0xaa"), wrapStorage(b))
- snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, randomAccountSet("0xaa"), wrapStorage(c))
- snaps.update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, randomAccountSet("0xaa"), wrapStorage(d))
- snaps.update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, randomAccountSet("0xaa"), wrapStorage(e))
- snaps.update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, randomAccountSet("0xaa"), wrapStorage(e))
- snaps.update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, randomAccountSet("0xaa"), wrapStorage(g))
- snaps.update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, randomAccountSet("0xaa"), wrapStorage(h))
+ snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, randomAccountSet("0xaa"), wrapStorage(a), nil)
+ snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, randomAccountSet("0xaa"), wrapStorage(b), nil)
+ snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, randomAccountSet("0xaa"), wrapStorage(c), nil)
+ snaps.update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, randomAccountSet("0xaa"), wrapStorage(d), nil)
+ snaps.update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, randomAccountSet("0xaa"), wrapStorage(e), nil)
+ snaps.update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, randomAccountSet("0xaa"), wrapStorage(e), nil)
+ snaps.update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, randomAccountSet("0xaa"), wrapStorage(g), nil)
+ snaps.update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, randomAccountSet("0xaa"), wrapStorage(h), nil)
it, _ := snaps.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{})
head := snaps.Snapshot(common.HexToHash("0x09"))
@@ -522,7 +522,7 @@ func TestAccountIteratorLargeTraversal(t *testing.T) {
},
}
for i := 1; i < 128; i++ {
- snaps.update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil)
+ snaps.update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil, nil)
}
// Iterate the entire stack and ensure everything is hit only once
head := snaps.Snapshot(common.HexToHash("0x80"))
@@ -567,13 +567,13 @@ func TestAccountIteratorFlattening(t *testing.T) {
}
// Create a stack of diffs on top
snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil,
- randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil)
+ randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil, nil)
snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil,
- randomAccountSet("0xbb", "0xdd", "0xf0"), nil)
+ randomAccountSet("0xbb", "0xdd", "0xf0"), nil, nil)
snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil,
- randomAccountSet("0xcc", "0xf0", "0xff"), nil)
+ randomAccountSet("0xcc", "0xf0", "0xff"), nil, nil)
// Create an iterator and flatten the data from underneath it
it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{})
@@ -598,13 +598,13 @@ func TestAccountIteratorSeek(t *testing.T) {
},
}
snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil,
- randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil)
+ randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil, nil)
snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil,
- randomAccountSet("0xbb", "0xdd", "0xf0"), nil)
+ randomAccountSet("0xbb", "0xdd", "0xf0"), nil, nil)
snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil,
- randomAccountSet("0xcc", "0xf0", "0xff"), nil)
+ randomAccountSet("0xcc", "0xf0", "0xff"), nil, nil)
// Account set is now
// 02: aa, ee, f0, ff
@@ -662,13 +662,13 @@ func TestStorageIteratorSeek(t *testing.T) {
}
// Stack three diff layers on top with various overlaps
snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil), nil)
snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x05", "0x06"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x05", "0x06"}}, nil), nil)
snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x05", "0x08"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x05", "0x08"}}, nil), nil)
// Account set is now
// 02: 01, 03, 05
@@ -725,17 +725,17 @@ func TestAccountIteratorDeletions(t *testing.T) {
}
// Stack three diff layers on top with various overlaps
snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"),
- nil, randomAccountSet("0x11", "0x22", "0x33"), nil)
+ nil, randomAccountSet("0x11", "0x22", "0x33"), nil, nil)
deleted := common.HexToHash("0x22")
destructed := map[common.Hash]struct{}{
deleted: {},
}
snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"),
- destructed, randomAccountSet("0x11", "0x33"), nil)
+ destructed, randomAccountSet("0x11", "0x33"), nil, nil)
snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"),
- nil, randomAccountSet("0x33", "0x44", "0x55"), nil)
+ nil, randomAccountSet("0x33", "0x44", "0x55"), nil, nil)
// The output should be 11,33,44,55
it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{})
@@ -771,10 +771,10 @@ func TestStorageIteratorDeletions(t *testing.T) {
}
// Stack three diff layers on top with various overlaps
snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil), nil)
snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x04", "0x06"}}, [][]string{{"0x01", "0x03"}}))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x04", "0x06"}}, [][]string{{"0x01", "0x03"}}), nil)
// The output should be 02,04,05,06
it, _ := snaps.StorageIterator(common.HexToHash("0x03"), common.HexToHash("0xaa"), common.Hash{})
@@ -790,7 +790,7 @@ func TestStorageIteratorDeletions(t *testing.T) {
destructed := map[common.Hash]struct{}{
common.HexToHash("0xaa"): {},
}
- snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), destructed, nil, nil)
+ snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), destructed, nil, nil, nil)
it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{})
verifyIterator(t, 0, it, verifyStorage)
@@ -798,7 +798,7 @@ func TestStorageIteratorDeletions(t *testing.T) {
// Re-insert the slots of the same account
snaps.update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil,
- randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x07", "0x08", "0x09"}}, nil))
+ randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x07", "0x08", "0x09"}}, nil), nil)
// The output should be 07,08,09
it, _ = snaps.StorageIterator(common.HexToHash("0x05"), common.HexToHash("0xaa"), common.Hash{})
@@ -806,7 +806,7 @@ func TestStorageIteratorDeletions(t *testing.T) {
it.Release()
// Destruct the whole storage but re-create the account in the same layer
- snaps.update(common.HexToHash("0x06"), common.HexToHash("0x05"), destructed, randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x11", "0x12"}}, nil))
+ snaps.update(common.HexToHash("0x06"), common.HexToHash("0x05"), destructed, randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x11", "0x12"}}, nil), nil)
it, _ = snaps.StorageIterator(common.HexToHash("0x06"), common.HexToHash("0xaa"), common.Hash{})
verifyIterator(t, 2, it, verifyStorage) // The output should be 11,12
it.Release()
@@ -848,7 +848,7 @@ func BenchmarkAccountIteratorTraversal(b *testing.B) {
},
}
for i := 1; i <= 100; i++ {
- snaps.update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil)
+ snaps.update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil, nil)
}
// We call this once before the benchmark, so the creation of
// sorted accountlists are not included in the results.
@@ -943,9 +943,9 @@ func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) {
base.root: base,
},
}
- snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, makeAccounts(2000), nil)
+ snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, makeAccounts(2000), nil, nil)
for i := 2; i <= 100; i++ {
- snaps.update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(20), nil)
+ snaps.update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(20), nil, nil)
}
// We call this once before the benchmark, so the creation of
// sorted accountlists are not included in the results.
diff --git a/core/state/snapshot/journal.go b/core/state/snapshot/journal.go
index 5cfb9a9f2..35c69cfd6 100644
--- a/core/state/snapshot/journal.go
+++ b/core/state/snapshot/journal.go
@@ -243,7 +243,7 @@ func loadDiffLayer(parent snapshot, r *rlp.Stream) (snapshot, error) {
}
storageData[entry.Hash] = slots
}
- return loadDiffLayer(newDiffLayer(parent, root, destructSet, accountData, storageData), r)
+ return loadDiffLayer(newDiffLayer(parent, root, destructSet, accountData, storageData, nil), r)
}
// Journal terminates any in-progress snapshot generation, also implicitly pushing
diff --git a/core/state/snapshot/snapshot.go b/core/state/snapshot/snapshot.go
index 46d1b06de..8ac93f28e 100644
--- a/core/state/snapshot/snapshot.go
+++ b/core/state/snapshot/snapshot.go
@@ -101,6 +101,15 @@ type Snapshot interface {
// Root returns the root hash for which this snapshot was made.
Root() common.Hash
+ // WaitAndGetVerifyRes will wait until the snapshot been verified and return verification result
+ WaitAndGetVerifyRes() bool
+
+ // Verified returns whether the snapshot is verified
+ Verified() bool
+
+ // Store the verification result
+ MarkValid()
+
// Account directly retrieves the account associated with a particular hash in
// the snapshot slim data format.
Account(hash common.Hash) (*Account, error)
@@ -130,7 +139,7 @@ type snapshot interface {
// the specified data items.
//
// Note, the maps are retained by the method to avoid copying everything.
- Update(blockRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer
+ Update(blockRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte, verified chan struct{}) *diffLayer
// Journal commits an entire diff hierarchy to disk into a single journal entry.
// This is meant to be used during shutdown to persist the snapshot without
@@ -322,14 +331,14 @@ func (t *Tree) Snapshots(root common.Hash, limits int, nodisk bool) []Snapshot {
return ret
}
-func (t *Tree) Update(blockRoot common.Hash, parentRoot common.Hash, destructs map[common.Address]struct{}, accounts map[common.Address][]byte, storage map[common.Address]map[string][]byte) error {
+func (t *Tree) Update(blockRoot common.Hash, parentRoot common.Hash, destructs map[common.Address]struct{}, accounts map[common.Address][]byte, storage map[common.Address]map[string][]byte, verified chan struct{}) error {
hashDestructs, hashAccounts, hashStorage := transformSnapData(destructs, accounts, storage)
- return t.update(blockRoot, parentRoot, hashDestructs, hashAccounts, hashStorage)
+ return t.update(blockRoot, parentRoot, hashDestructs, hashAccounts, hashStorage, verified)
}
// Update adds a new snapshot into the tree, if that can be linked to an existing
// old parent. It is disallowed to insert a disk layer (the origin of all).
-func (t *Tree) update(blockRoot common.Hash, parentRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) error {
+func (t *Tree) update(blockRoot common.Hash, parentRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte, verified chan struct{}) error {
// Reject noop updates to avoid self-loops in the snapshot tree. This is a
// special case that can only happen for Clique networks where empty blocks
// don't modify the state (0 block subsidy).
@@ -344,7 +353,7 @@ func (t *Tree) update(blockRoot common.Hash, parentRoot common.Hash, destructs m
if parent == nil {
return fmt.Errorf("parent [%#x] snapshot missing", parentRoot)
}
- snap := parent.(snapshot).Update(blockRoot, destructs, accounts, storage)
+ snap := parent.(snapshot).Update(blockRoot, destructs, accounts, storage, verified)
// Save the new snapshot for later
t.lock.Lock()
diff --git a/core/state/snapshot/snapshot_test.go b/core/state/snapshot/snapshot_test.go
index f8ced6366..187186a3b 100644
--- a/core/state/snapshot/snapshot_test.go
+++ b/core/state/snapshot/snapshot_test.go
@@ -105,7 +105,7 @@ func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) {
accounts := map[common.Hash][]byte{
common.HexToHash("0xa1"): randomAccount(),
}
- if err := snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil); err != nil {
+ if err := snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil, nil); err != nil {
t.Fatalf("failed to create a diff layer: %v", err)
}
if n := len(snaps.layers); n != 2 {
@@ -149,10 +149,10 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) {
accounts := map[common.Hash][]byte{
common.HexToHash("0xa1"): randomAccount(),
}
- if err := snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil); err != nil {
+ if err := snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil, nil); err != nil {
t.Fatalf("failed to create a diff layer: %v", err)
}
- if err := snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, accounts, nil); err != nil {
+ if err := snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, accounts, nil, nil); err != nil {
t.Fatalf("failed to create a diff layer: %v", err)
}
if n := len(snaps.layers); n != 3 {
@@ -197,13 +197,13 @@ func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) {
accounts := map[common.Hash][]byte{
common.HexToHash("0xa1"): randomAccount(),
}
- if err := snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil); err != nil {
+ if err := snaps.update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil, nil); err != nil {
t.Fatalf("failed to create a diff layer: %v", err)
}
- if err := snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, accounts, nil); err != nil {
+ if err := snaps.update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, accounts, nil, nil); err != nil {
t.Fatalf("failed to create a diff layer: %v", err)
}
- if err := snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, accounts, nil); err != nil {
+ if err := snaps.update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, accounts, nil, nil); err != nil {
t.Fatalf("failed to create a diff layer: %v", err)
}
if n := len(snaps.layers); n != 4 {
@@ -257,12 +257,12 @@ func TestPostCapBasicDataAccess(t *testing.T) {
},
}
// The lowest difflayer
- snaps.update(common.HexToHash("0xa1"), common.HexToHash("0x01"), nil, setAccount("0xa1"), nil)
- snaps.update(common.HexToHash("0xa2"), common.HexToHash("0xa1"), nil, setAccount("0xa2"), nil)
- snaps.update(common.HexToHash("0xb2"), common.HexToHash("0xa1"), nil, setAccount("0xb2"), nil)
+ snaps.update(common.HexToHash("0xa1"), common.HexToHash("0x01"), nil, setAccount("0xa1"), nil, nil)
+ snaps.update(common.HexToHash("0xa2"), common.HexToHash("0xa1"), nil, setAccount("0xa2"), nil, nil)
+ snaps.update(common.HexToHash("0xb2"), common.HexToHash("0xa1"), nil, setAccount("0xb2"), nil, nil)
- snaps.update(common.HexToHash("0xa3"), common.HexToHash("0xa2"), nil, setAccount("0xa3"), nil)
- snaps.update(common.HexToHash("0xb3"), common.HexToHash("0xb2"), nil, setAccount("0xb3"), nil)
+ snaps.update(common.HexToHash("0xa3"), common.HexToHash("0xa2"), nil, setAccount("0xa3"), nil, nil)
+ snaps.update(common.HexToHash("0xb3"), common.HexToHash("0xb2"), nil, setAccount("0xb3"), nil, nil)
// checkExist verifies if an account exiss in a snapshot
checkExist := func(layer *diffLayer, key string) error {
@@ -357,7 +357,7 @@ func TestSnaphots(t *testing.T) {
)
for i := 0; i < 129; i++ {
head = makeRoot(uint64(i + 2))
- snaps.update(head, last, nil, setAccount(fmt.Sprintf("%d", i+2)), nil)
+ snaps.update(head, last, nil, setAccount(fmt.Sprintf("%d", i+2)), nil, nil)
last = head
snaps.Cap(head, 128) // 130 layers (128 diffs + 1 accumulator + 1 disk)
}
diff --git a/core/state/state_test.go b/core/state/state_test.go
index 77847772c..4be9ae8ce 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -54,7 +54,9 @@ func TestDump(t *testing.T) {
// write some of them to the trie
s.state.updateStateObject(obj1)
s.state.updateStateObject(obj2)
- s.state.Commit(false)
+ s.state.Finalise(false)
+ s.state.AccountsIntermediateRoot()
+ s.state.Commit(nil)
// check that DumpToCollector contains the state objects that are in trie
got := string(s.state.Dump(false, false, true))
@@ -95,7 +97,9 @@ func TestNull(t *testing.T) {
var value common.Hash
s.state.SetState(address, common.Hash{}, value)
- s.state.Commit(false)
+ s.state.Finalise(false)
+ s.state.AccountsIntermediateRoot()
+ s.state.Commit(nil)
if value := s.state.GetState(address, common.Hash{}); value != (common.Hash{}) {
t.Errorf("expected empty current value, got %x", value)
@@ -167,7 +171,9 @@ func TestSnapshot2(t *testing.T) {
so0.deleted = false
state.SetStateObject(so0)
- root, _, _ := state.Commit(false)
+ state.Finalise(false)
+ state.AccountsIntermediateRoot()
+ root, _, _ := state.Commit(nil)
state, _ = New(root, state.db, state.snaps)
// and one with deleted == true
diff --git a/core/state/statedb.go b/core/state/statedb.go
index c7a9d92ef..5ea84f403 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -74,14 +74,20 @@ func (n *proofList) Delete(key []byte) error {
// * Accounts
type StateDB struct {
db Database
+ prefetcherLock sync.Mutex
prefetcher *triePrefetcher
originalRoot common.Hash // The pre-state root, before any changes were made
+ expectedRoot common.Hash // The state root in the block header
+ stateRoot common.Hash // The calculation result of IntermediateRoot
+
trie Trie
hasher crypto.KeccakState
diffLayer *types.DiffLayer
diffTries map[common.Address]Trie
diffCode map[common.Hash][]byte
lightProcessed bool
+ fullProcessed bool
+ pipeCommit bool
snapMux sync.Mutex
snaps *snapshot.Tree
@@ -154,11 +160,6 @@ func newStateDB(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB,
journal: newJournal(),
hasher: crypto.NewKeccakState(),
}
- tr, err := db.OpenTrie(root)
- if err != nil {
- return nil, err
- }
- sdb.trie = tr
if sdb.snaps != nil {
if sdb.snap = sdb.snaps.Snapshot(root); sdb.snap != nil {
sdb.snapDestructs = make(map[common.Address]struct{})
@@ -166,6 +167,14 @@ func newStateDB(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB,
sdb.snapStorage = make(map[common.Address]map[string][]byte)
}
}
+
+ snapVerified := sdb.snap != nil && sdb.snap.Verified()
+ tr, err := db.OpenTrie(root)
+ // return error when 1. failed to open trie and 2. the snap is nil or the snap is not nil and done verification
+ if err != nil && (sdb.snap == nil || snapVerified) {
+ return nil, err
+ }
+ sdb.trie = tr
return sdb, nil
}
@@ -173,6 +182,8 @@ func newStateDB(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB,
// state trie concurrently while the state is mutated so that when we reach the
// commit phase, most of the needed data is already hot.
func (s *StateDB) StartPrefetcher(namespace string) {
+ s.prefetcherLock.Lock()
+ defer s.prefetcherLock.Unlock()
if s.prefetcher != nil {
s.prefetcher.close()
s.prefetcher = nil
@@ -185,17 +196,36 @@ func (s *StateDB) StartPrefetcher(namespace string) {
// StopPrefetcher terminates a running prefetcher and reports any leftover stats
// from the gathered metrics.
func (s *StateDB) StopPrefetcher() {
+ s.prefetcherLock.Lock()
+ defer s.prefetcherLock.Unlock()
if s.prefetcher != nil {
s.prefetcher.close()
s.prefetcher = nil
}
}
+// Mark that the block is processed by diff layer
+func (s *StateDB) SetExpectedStateRoot(root common.Hash) {
+ s.expectedRoot = root
+}
+
// Mark that the block is processed by diff layer
func (s *StateDB) MarkLightProcessed() {
s.lightProcessed = true
}
+// Enable the pipeline commit function of statedb
+func (s *StateDB) EnablePipeCommit() {
+ if s.snap != nil {
+ s.pipeCommit = true
+ }
+}
+
+// Mark that the block is full processed
+func (s *StateDB) MarkFullProcessed() {
+ s.fullProcessed = true
+}
+
func (s *StateDB) IsLightProcessed() bool {
return s.lightProcessed
}
@@ -211,8 +241,20 @@ func (s *StateDB) Error() error {
return s.dbErr
}
-func (s *StateDB) Trie() Trie {
- return s.trie
+// Not thread safe
+func (s *StateDB) Trie() (Trie, error) {
+ if s.trie == nil {
+ err := s.WaitPipeVerification()
+ if err != nil {
+ return nil, err
+ }
+ tr, err := s.db.OpenTrie(s.originalRoot)
+ if err != nil {
+ return nil, err
+ }
+ s.trie = tr
+ }
+ return s.trie, nil
}
func (s *StateDB) SetDiff(diffLayer *types.DiffLayer, diffTries map[common.Address]Trie, diffCode map[common.Hash][]byte) {
@@ -360,6 +402,9 @@ func (s *StateDB) GetProof(addr common.Address) ([][]byte, error) {
// GetProofByHash returns the Merkle proof for a given account.
func (s *StateDB) GetProofByHash(addrHash common.Hash) ([][]byte, error) {
var proof proofList
+ if _, err := s.Trie(); err != nil {
+ return nil, err
+ }
err := s.trie.Prove(addrHash[:], 0, &proof)
return proof, err
}
@@ -904,6 +949,17 @@ func (s *StateDB) GetRefund() uint64 {
return s.refund
}
+// GetRefund returns the current value of the refund counter.
+func (s *StateDB) WaitPipeVerification() error {
+ // We need wait for the parent trie to commit
+ if s.snap != nil {
+ if valid := s.snap.WaitAndGetVerifyRes(); !valid {
+ return fmt.Errorf("verification on parent snap failed")
+ }
+ }
+ return nil
+}
+
// Finalise finalises the state by removing the s destructed objects and clears
// the journal as well as the refunds. Finalise, however, will not push any updates
// into the tries just yet. Only IntermediateRoot or Commit will do that.
@@ -963,22 +1019,11 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
}
// Finalise all the dirty storage states and write them into the tries
s.Finalise(deleteEmptyObjects)
+ s.AccountsIntermediateRoot()
+ return s.StateIntermediateRoot()
+}
- // If there was a trie prefetcher operating, it gets aborted and irrevocably
- // modified after we start retrieving tries. Remove it from the statedb after
- // this round of use.
- //
- // This is weird pre-byzantium since the first tx runs with a prefetcher and
- // the remainder without, but pre-byzantium even the initial prefetcher is
- // useless, so no sleep lost.
- prefetcher := s.prefetcher
- if s.prefetcher != nil {
- defer func() {
- s.prefetcher.close()
- s.prefetcher = nil
- }()
- }
-
+func (s *StateDB) AccountsIntermediateRoot() {
tasks := make(chan func())
finishCh := make(chan struct{})
defer close(finishCh)
@@ -995,6 +1040,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
}
}()
}
+
// Although naively it makes sense to retrieve the account trie and then do
// the contract storage and account updates sequentially, that short circuits
// the account prefetcher. Instead, let's process all the storage updates
@@ -1026,6 +1072,27 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
}
}
wg.Wait()
+}
+
+func (s *StateDB) StateIntermediateRoot() common.Hash {
+ // If there was a trie prefetcher operating, it gets aborted and irrevocably
+ // modified after we start retrieving tries. Remove it from the statedb after
+ // this round of use.
+ //
+ // This is weird pre-byzantium since the first tx runs with a prefetcher and
+ // the remainder without, but pre-byzantium even the initial prefetcher is
+ // useless, so no sleep lost.
+ prefetcher := s.prefetcher
+ defer func() {
+ s.prefetcherLock.Lock()
+ if s.prefetcher != nil {
+ s.prefetcher.close()
+ s.prefetcher = nil
+ }
+ // try not use defer inside defer
+ s.prefetcherLock.Unlock()
+ }()
+
// Now we're about to start to write changes to the trie. The trie is so far
// _untouched_. We can check with the prefetcher, if it can give us a trie
// which has the same root, but also has some content loaded into it.
@@ -1037,7 +1104,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
if s.trie == nil {
tr, err := s.db.OpenTrie(s.originalRoot)
if err != nil {
- panic("Failed to open trie tree")
+ panic(fmt.Sprintf("Failed to open trie tree %s", s.originalRoot))
}
s.trie = tr
}
@@ -1081,9 +1148,12 @@ func (s *StateDB) clearJournalAndRefund() {
s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entires
}
-func (s *StateDB) LightCommit(root common.Hash) (common.Hash, *types.DiffLayer, error) {
+func (s *StateDB) LightCommit() (common.Hash, *types.DiffLayer, error) {
codeWriter := s.db.TrieDB().DiskDB().NewBatch()
+ // light process already verified it, expectedRoot is trustworthy.
+ root := s.expectedRoot
+
commitFuncs := []func() error{
func() error {
for codeHash, code := range s.diffCode {
@@ -1171,7 +1241,8 @@ func (s *StateDB) LightCommit(root common.Hash) (common.Hash, *types.DiffLayer,
}
// Only update if there's a state transition (skip empty Clique blocks)
if parent := s.snap.Root(); parent != root {
- if err := s.snaps.Update(root, parent, s.snapDestructs, s.snapAccounts, s.snapStorage); err != nil {
+ // for light commit, always do sync commit
+ if err := s.snaps.Update(root, parent, s.snapDestructs, s.snapAccounts, s.snapStorage, nil); err != nil {
log.Warn("Failed to update snapshot tree", "from", parent, "to", root, "err", err)
}
// Keep n diff layers in the memory
@@ -1205,23 +1276,42 @@ func (s *StateDB) LightCommit(root common.Hash) (common.Hash, *types.DiffLayer,
}
// Commit writes the state to the underlying in-memory trie database.
-func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer, error) {
+func (s *StateDB) Commit(failPostCommitFunc func(), postCommitFuncs ...func() error) (common.Hash, *types.DiffLayer, error) {
if s.dbErr != nil {
return common.Hash{}, nil, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
}
// Finalize any pending changes and merge everything into the tries
- root := s.IntermediateRoot(deleteEmptyObjects)
if s.lightProcessed {
- return s.LightCommit(root)
+ root, diff, err := s.LightCommit()
+ if err != nil {
+ return root, diff, err
+ }
+ for _, postFunc := range postCommitFuncs {
+ err = postFunc()
+ if err != nil {
+ return root, diff, err
+ }
+ }
+ return root, diff, nil
}
var diffLayer *types.DiffLayer
+ var verified chan struct{}
+ var snapUpdated chan struct{}
if s.snap != nil {
diffLayer = &types.DiffLayer{}
}
- commitFuncs := []func() error{
- func() error {
- // Commit objects to the trie, measuring the elapsed time
- tasks := make(chan func(batch ethdb.KeyValueWriter))
+ if s.pipeCommit {
+ // async commit the MPT
+ verified = make(chan struct{})
+ snapUpdated = make(chan struct{})
+ }
+
+ commmitTrie := func() error {
+ commitErr := func() error {
+ if s.stateRoot = s.StateIntermediateRoot(); s.fullProcessed && s.expectedRoot != s.stateRoot {
+ return fmt.Errorf("invalid merkle root (remote: %x local: %x)", s.expectedRoot, s.stateRoot)
+ }
+ tasks := make(chan func())
taskResults := make(chan error, len(s.stateObjectsDirty))
tasksNum := 0
finishCh := make(chan struct{})
@@ -1232,17 +1322,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer
wg.Add(1)
go func() {
defer wg.Done()
- codeWriter := s.db.TrieDB().DiskDB().NewBatch()
for {
select {
case task := <-tasks:
- task(codeWriter)
+ task()
case <-finishCh:
- if codeWriter.ValueSize() > 0 {
- if err := codeWriter.Write(); err != nil {
- log.Crit("Failed to commit dirty codes", "error", err)
- }
- }
return
}
}
@@ -1265,11 +1349,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer
for addr := range s.stateObjectsDirty {
if obj := s.stateObjects[addr]; !obj.deleted {
// Write any contract code associated with the state object
- tasks <- func(codeWriter ethdb.KeyValueWriter) {
- if obj.code != nil && obj.dirtyCode {
- rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
- obj.dirtyCode = false
- }
+ tasks <- func() {
// Write any storage changes in the state object to its storage trie
if err := obj.CommitTrie(s.db); err != nil {
taskResults <- err
@@ -1289,14 +1369,6 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer
}
close(finishCh)
- if len(s.stateObjectsDirty) > 0 {
- s.stateObjectsDirty = make(map[common.Address]struct{}, len(s.stateObjectsDirty)/2)
- }
- // Write the account trie changes, measuing the amount of wasted time
- var start time.Time
- if metrics.EnabledExpensive {
- start = time.Now()
- }
// The onleaf func is called _serially_, so we can reuse the same account
// for unmarshalling every time.
var account Account
@@ -1312,14 +1384,60 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer
if err != nil {
return err
}
- if metrics.EnabledExpensive {
- s.AccountCommits += time.Since(start)
- }
if root != emptyRoot {
s.db.CacheAccount(root, s.trie)
}
+ for _, postFunc := range postCommitFuncs {
+ err = postFunc()
+ if err != nil {
+ return err
+ }
+ }
wg.Wait()
return nil
+ }()
+
+ if s.pipeCommit {
+ if commitErr == nil {
+ <-snapUpdated
+ s.snaps.Snapshot(s.stateRoot).MarkValid()
+ } else {
+ // The blockchain will do the further rewind if write block not finish yet
+ if failPostCommitFunc != nil {
+ <-snapUpdated
+ failPostCommitFunc()
+ }
+ log.Error("state verification failed", "err", commitErr)
+ }
+ close(verified)
+ }
+ return commitErr
+ }
+
+ commitFuncs := []func() error{
+ func() error {
+ codeWriter := s.db.TrieDB().DiskDB().NewBatch()
+ for addr := range s.stateObjectsDirty {
+ if obj := s.stateObjects[addr]; !obj.deleted {
+ if obj.code != nil && obj.dirtyCode {
+ rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
+ obj.dirtyCode = false
+ if codeWriter.ValueSize() > ethdb.IdealBatchSize {
+ if err := codeWriter.Write(); err != nil {
+ return err
+ }
+ codeWriter.Reset()
+ }
+ }
+ }
+ }
+ if codeWriter.ValueSize() > 0 {
+ if err := codeWriter.Write(); err != nil {
+ log.Crit("Failed to commit dirty codes", "error", err)
+ return err
+ }
+ }
+ return nil
},
func() error {
// If snapshotting is enabled, update the snapshot tree with this new version
@@ -1327,18 +1445,23 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer
if metrics.EnabledExpensive {
defer func(start time.Time) { s.SnapshotCommits += time.Since(start) }(time.Now())
}
+ if s.pipeCommit {
+ defer close(snapUpdated)
+ }
// Only update if there's a state transition (skip empty Clique blocks)
- if parent := s.snap.Root(); parent != root {
- if err := s.snaps.Update(root, parent, s.snapDestructs, s.snapAccounts, s.snapStorage); err != nil {
- log.Warn("Failed to update snapshot tree", "from", parent, "to", root, "err", err)
+ if parent := s.snap.Root(); parent != s.expectedRoot {
+ if err := s.snaps.Update(s.expectedRoot, parent, s.snapDestructs, s.snapAccounts, s.snapStorage, verified); err != nil {
+ log.Warn("Failed to update snapshot tree", "from", parent, "to", s.expectedRoot, "err", err)
}
// Keep n diff layers in the memory
// - head layer is paired with HEAD state
// - head-1 layer is paired with HEAD-1 state
// - head-(n-1) layer(bottom-most diff layer) is paired with HEAD-(n-1)state
- if err := s.snaps.Cap(root, s.snaps.CapLimit()); err != nil {
- log.Warn("Failed to cap snapshot tree", "root", root, "layers", s.snaps.CapLimit(), "err", err)
- }
+ go func() {
+ if err := s.snaps.Cap(s.expectedRoot, s.snaps.CapLimit()); err != nil {
+ log.Warn("Failed to cap snapshot tree", "root", s.expectedRoot, "layers", s.snaps.CapLimit(), "err", err)
+ }
+ }()
}
}
return nil
@@ -1350,6 +1473,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer
return nil
},
}
+ if s.pipeCommit {
+ go commmitTrie()
+ } else {
+ commitFuncs = append(commitFuncs, commmitTrie)
+ }
commitRes := make(chan error, len(commitFuncs))
for _, f := range commitFuncs {
tmpFunc := f
@@ -1363,7 +1491,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, *types.DiffLayer
return common.Hash{}, nil, r
}
}
- s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil
+ root := s.stateRoot
+ if s.pipeCommit {
+ root = s.expectedRoot
+ }
+
return root, diffLayer, nil
}
@@ -1493,3 +1625,11 @@ func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addre
}
return s.accessList.Contains(addr, slot)
}
+
+func (s *StateDB) GetDirtyAccounts() []common.Address {
+ accounts := make([]common.Address, 0, len(s.stateObjectsDirty))
+ for account := range s.stateObjectsDirty {
+ accounts = append(accounts, account)
+ }
+ return accounts
+}
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index 2c0b9296f..acbbf1cd2 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -102,7 +102,9 @@ func TestIntermediateLeaks(t *testing.T) {
}
// Commit and cross check the databases.
- transRoot, _, err := transState.Commit(false)
+ transState.Finalise(false)
+ transState.AccountsIntermediateRoot()
+ transRoot, _, err := transState.Commit(nil)
if err != nil {
t.Fatalf("failed to commit transition state: %v", err)
}
@@ -110,7 +112,9 @@ func TestIntermediateLeaks(t *testing.T) {
t.Errorf("can not commit trie %v to persistent database", transRoot.Hex())
}
- finalRoot, _, err := finalState.Commit(false)
+ finalState.Finalise(false)
+ finalState.AccountsIntermediateRoot()
+ finalRoot, _, err := finalState.Commit(nil)
if err != nil {
t.Fatalf("failed to commit final state: %v", err)
}
@@ -473,7 +477,7 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
func TestTouchDelete(t *testing.T) {
s := newStateTest()
s.state.GetOrNewStateObject(common.Address{})
- root, _, _ := s.state.Commit(false)
+ root, _, _ := s.state.Commit(nil)
s.state, _ = New(root, s.state.db, s.state.snaps)
snapshot := s.state.Snapshot()
@@ -546,7 +550,9 @@ func TestCopyCommitCopy(t *testing.T) {
t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
}
- copyOne.Commit(false)
+ copyOne.Finalise(false)
+ copyOne.AccountsIntermediateRoot()
+ copyOne.Commit(nil)
if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42)
}
@@ -631,7 +637,10 @@ func TestCopyCopyCommitCopy(t *testing.T) {
if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) {
t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
}
- copyTwo.Commit(false)
+
+ copyTwo.Finalise(false)
+ copyTwo.AccountsIntermediateRoot()
+ copyTwo.Commit(nil)
if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42)
}
@@ -675,7 +684,9 @@ func TestDeleteCreateRevert(t *testing.T) {
addr := common.BytesToAddress([]byte("so"))
state.SetBalance(addr, big.NewInt(1))
- root, _, _ := state.Commit(false)
+ state.Finalise(false)
+ state.AccountsIntermediateRoot()
+ root, _, _ := state.Commit(nil)
state, _ = New(root, state.db, state.snaps)
// Simulate self-destructing in one transaction, then create-reverting in another
@@ -686,8 +697,10 @@ func TestDeleteCreateRevert(t *testing.T) {
state.SetBalance(addr, big.NewInt(2))
state.RevertToSnapshot(id)
+ state.Finalise(true)
+ state.AccountsIntermediateRoot()
// Commit the entire state and make sure we don't crash and have the correct state
- root, _, _ = state.Commit(true)
+ root, _, _ = state.Commit(nil)
state, _ = New(root, state.db, state.snaps)
if state.getStateObject(addr) != nil {
@@ -712,7 +725,9 @@ func TestMissingTrieNodes(t *testing.T) {
a2 := common.BytesToAddress([]byte("another"))
state.SetBalance(a2, big.NewInt(100))
state.SetCode(a2, []byte{1, 2, 4})
- root, _, _ = state.Commit(false)
+ state.Finalise(false)
+ state.AccountsIntermediateRoot()
+ root, _, _ = state.Commit(nil)
t.Logf("root: %x", root)
// force-flush
state.Database().TrieDB().Cap(0)
@@ -736,7 +751,9 @@ func TestMissingTrieNodes(t *testing.T) {
}
// Modify the state
state.SetBalance(addr, big.NewInt(2))
- root, _, err := state.Commit(false)
+ state.Finalise(false)
+ state.AccountsIntermediateRoot()
+ root, _, err := state.Commit(nil)
if err == nil {
t.Fatalf("expected error, got root :%x", root)
}
diff --git a/core/state/sync_test.go b/core/state/sync_test.go
index 24cae5900..fe896791d 100644
--- a/core/state/sync_test.go
+++ b/core/state/sync_test.go
@@ -69,7 +69,9 @@ func makeTestState() (Database, common.Hash, []*testAccount) {
state.updateStateObject(obj)
accounts = append(accounts, acc)
}
- root, _, _ := state.Commit(false)
+ state.Finalise(false)
+ state.AccountsIntermediateRoot()
+ root, _, _ := state.Commit(nil)
// Return the generated state
return db, root, accounts
diff --git a/core/state/trie_prefetcher.go b/core/state/trie_prefetcher.go
index ddecd7a20..ed60c811d 100644
--- a/core/state/trie_prefetcher.go
+++ b/core/state/trie_prefetcher.go
@@ -20,7 +20,6 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/gopool"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
@@ -106,7 +105,7 @@ func (p *triePrefetcher) close() {
for _, fetcher := range p.fetchers {
p.abortChan <- fetcher // safe to do multiple times
<-fetcher.term
- if metrics.Enabled {
+ if metrics.EnabledExpensive {
if fetcher.root == p.root {
p.accountLoadMeter.Mark(int64(len(fetcher.seen)))
p.accountDupMeter.Mark(int64(fetcher.dups))
@@ -257,9 +256,7 @@ func newSubfetcher(db Database, root common.Hash, accountHash common.Hash) *subf
seen: make(map[string]struct{}),
accountHash: accountHash,
}
- gopool.Submit(func() {
- sf.loop()
- })
+ go sf.loop()
return sf
}
@@ -322,8 +319,7 @@ func (sf *subfetcher) loop() {
trie, err = sf.db.OpenStorageTrie(sf.accountHash, sf.root)
}
if err != nil {
- log.Warn("Trie prefetcher failed opening trie", "root", sf.root, "err", err)
- return
+ log.Debug("Trie prefetcher failed opening trie", "root", sf.root, "err", err)
}
sf.trie = trie
@@ -332,6 +328,18 @@ func (sf *subfetcher) loop() {
select {
case <-sf.wake:
// Subfetcher was woken up, retrieve any tasks to avoid spinning the lock
+ if sf.trie == nil {
+ if sf.accountHash == emptyAddr {
+ sf.trie, err = sf.db.OpenTrie(sf.root)
+ } else {
+ // address is useless
+ sf.trie, err = sf.db.OpenStorageTrie(sf.accountHash, sf.root)
+ }
+ if err != nil {
+ continue
+ }
+ }
+
sf.lock.Lock()
tasks := sf.tasks
sf.tasks = nil
diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go
index dacd8df40..d559a03a0 100644
--- a/core/state_prefetcher.go
+++ b/core/state_prefetcher.go
@@ -26,6 +26,8 @@ import (
"github.com/ethereum/go-ethereum/params"
)
+const prefetchThread = 2
+
// statePrefetcher is a basic Prefetcher, which blindly executes a block on top
// of an arbitrary state with the goal of prefetching potentially useful state
// data from disk before the main block processor start executing.
@@ -35,51 +37,63 @@ type statePrefetcher struct {
engine consensus.Engine // Consensus engine used for block rewards
}
+// NewStatePrefetcher initialises a new statePrefetcher.
+func NewStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *statePrefetcher {
+ return &statePrefetcher{
+ config: config,
+ bc: bc,
+ engine: engine,
+ }
+}
+
// 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.
+// only goal is to pre-cache transaction signatures and snapshot clean state.
func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) {
var (
- header = block.Header()
- gaspool = new(GasPool).AddGas(block.GasLimit())
- blockContext = NewEVMBlockContext(header, p.bc, nil)
- evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
- signer = types.MakeSigner(p.config, header.Number)
+ header = block.Header()
+ signer = types.MakeSigner(p.config, header.Number)
)
- // Iterate over and process the individual transactions
- byzantium := p.config.IsByzantium(block.Number())
- for i, tx := range block.Transactions() {
- // If block precaching was interrupted, abort
- if interrupt != nil && atomic.LoadUint32(interrupt) == 1 {
- return
- }
- // Convert the transaction into an executable message and pre-cache its sender
- msg, err := tx.AsMessage(signer)
- if err != nil {
- return // Also invalid block, bail out
- }
- statedb.Prepare(tx.Hash(), block.Hash(), i)
- if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil {
- return // Ugh, something went horribly wrong, bail out
- }
- // If we're pre-byzantium, pre-load trie nodes for the intermediate root
- if !byzantium {
- statedb.IntermediateRoot(true)
- }
+ transactions := block.Transactions()
+ sortTransactions := make([][]*types.Transaction, prefetchThread)
+ for i := 0; i < prefetchThread; i++ {
+ sortTransactions[i] = make([]*types.Transaction, 0, len(transactions)/prefetchThread)
+ }
+ for idx := range transactions {
+ threadIdx := idx % prefetchThread
+ sortTransactions[threadIdx] = append(sortTransactions[threadIdx], transactions[idx])
}
- // If were post-byzantium, pre-load trie nodes for the final root hash
- if byzantium {
- statedb.IntermediateRoot(true)
+ // No need to execute the first batch, since the main processor will do it.
+ for i := 0; i < prefetchThread; i++ {
+ go func(idx int) {
+ newStatedb := statedb.Copy()
+ gaspool := new(GasPool).AddGas(block.GasLimit())
+ blockContext := NewEVMBlockContext(header, p.bc, nil)
+ evm := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
+ // Iterate over and process the individual transactions
+ for i, tx := range sortTransactions[idx] {
+ // If block precaching was interrupted, abort
+ if interrupt != nil && atomic.LoadUint32(interrupt) == 1 {
+ return
+ }
+ // Convert the transaction into an executable message and pre-cache its sender
+ msg, err := tx.AsMessage(signer)
+ if err != nil {
+ return // Also invalid block, bail out
+ }
+ newStatedb.Prepare(tx.Hash(), header.Hash(), i)
+ precacheTransaction(msg, p.config, gaspool, newStatedb, header, evm)
+ }
+ }(i)
}
}
// 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 types.Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) {
// Update the evm with the new transaction context.
evm.Reset(NewEVMTxContext(msg), statedb)
// Add addresses to access list if applicable
- _, err := ApplyMessage(evm, msg, gaspool)
- return err
+ ApplyMessage(evm, msg, gaspool)
}
diff --git a/core/state_processor.go b/core/state_processor.go
index b52908206..14fe9b4b9 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -43,8 +43,8 @@ import (
const (
fullProcessCheck = 21 // On diff sync mode, will do full process every fullProcessCheck randomly
- recentTime = 2048 * 3
- recentDiffLayerTimeout = 20
+ recentTime = 1024 * 3
+ recentDiffLayerTimeout = 5
farDiffLayerTimeout = 2
)
@@ -68,15 +68,16 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen
}
type LightStateProcessor struct {
- randomGenerator *rand.Rand
+ check int64
StateProcessor
}
func NewLightStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *LightStateProcessor {
randomGenerator := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
+ check := randomGenerator.Int63n(fullProcessCheck)
return &LightStateProcessor{
- randomGenerator: randomGenerator,
- StateProcessor: *NewStateProcessor(config, bc, engine),
+ check: check,
+ StateProcessor: *NewStateProcessor(config, bc, engine),
}
}
@@ -86,7 +87,7 @@ func (p *LightStateProcessor) Process(block *types.Block, statedb *state.StateDB
allowLightProcess = posa.AllowLightProcess(p.bc, block.Header())
}
// random fallback to full process
- if check := p.randomGenerator.Int63n(fullProcessCheck); allowLightProcess && check != 0 && len(block.Transactions()) != 0 {
+ if allowLightProcess && block.NumberU64()%fullProcessCheck != uint64(p.check) && len(block.Transactions()) != 0 {
var pid string
if peer, ok := block.ReceivedFrom.(PeerIDer); ok {
pid = peer.ID()
@@ -122,6 +123,10 @@ func (p *LightStateProcessor) Process(block *types.Block, statedb *state.StateDB
statedb.StopPrefetcher()
parent := p.bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
statedb, err = state.New(parent.Root, p.bc.stateCache, p.bc.snaps)
+ statedb.SetExpectedStateRoot(block.Root())
+ if p.bc.pipeCommit {
+ statedb.EnablePipeCommit()
+ }
if err != nil {
return statedb, nil, nil, 0, err
}
@@ -147,9 +152,12 @@ func (p *LightStateProcessor) LightProcess(diffLayer *types.DiffLayer, block *ty
for _, c := range diffLayer.Codes {
fullDiffCode[c.Hash] = c.Code
}
-
+ stateTrie, err := statedb.Trie()
+ if err != nil {
+ return nil, nil, 0, err
+ }
for des := range snapDestructs {
- statedb.Trie().TryDelete(des[:])
+ stateTrie.TryDelete(des[:])
}
threads := gopool.Threads(len(snapAccounts))
@@ -190,7 +198,7 @@ func (p *LightStateProcessor) LightProcess(diffLayer *types.DiffLayer, block *ty
// fetch previous state
var previousAccount state.Account
stateMux.Lock()
- enc, err := statedb.Trie().TryGet(diffAccount[:])
+ enc, err := stateTrie.TryGet(diffAccount[:])
stateMux.Unlock()
if err != nil {
errChan <- err
@@ -252,7 +260,7 @@ func (p *LightStateProcessor) LightProcess(diffLayer *types.DiffLayer, block *ty
//update storage
latestRoot := common.BytesToHash(latestAccount.Root)
- if latestRoot != previousAccount.Root && latestRoot != types.EmptyRootHash {
+ if latestRoot != previousAccount.Root {
accountTrie, err := statedb.Database().OpenStorageTrie(addrHash, previousAccount.Root)
if err != nil {
errChan <- err
@@ -302,7 +310,7 @@ func (p *LightStateProcessor) LightProcess(diffLayer *types.DiffLayer, block *ty
return
}
stateMux.Lock()
- err = statedb.Trie().TryUpdate(diffAccount[:], bz)
+ err = stateTrie.TryUpdate(diffAccount[:], bz)
stateMux.Unlock()
if err != nil {
errChan <- err
@@ -329,7 +337,7 @@ func (p *LightStateProcessor) LightProcess(diffLayer *types.DiffLayer, block *ty
}
// Do validate in advance so that we can fall back to full process
- if err := p.bc.validator.ValidateState(block, statedb, diffLayer.Receipts, gasUsed); err != nil {
+ if err := p.bc.validator.ValidateState(block, statedb, diffLayer.Receipts, gasUsed, false); err != nil {
log.Error("validate state failed during diff sync", "error", err)
return nil, nil, 0, err
}
@@ -396,6 +404,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// initilise bloom processors
bloomProcessors := NewAsyncReceiptBloomGenerator(txNum)
+ statedb.MarkFullProcessed()
// usually do have two tx, one for validator set contract, another for system reward contract.
systemTxs := make([]*types.Transaction, 0, 2)
diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go
index cdc95314d..49963a56c 100644
--- a/core/systemcontracts/upgrade.go
+++ b/core/systemcontracts/upgrade.go
@@ -41,6 +41,8 @@ var (
nielsUpgrade = make(map[string]*Upgrade)
mirrorUpgrade = make(map[string]*Upgrade)
+
+ brunoUpgrade = make(map[string]*Upgrade)
)
func init() {
@@ -91,6 +93,21 @@ func init() {
UpgradeName: "mirror",
Configs: []*UpgradeConfig{},
}
+
+ brunoUpgrade[mainNet] = &Upgrade{
+ UpgradeName: "bruno",
+ Configs: []*UpgradeConfig{},
+ }
+
+ brunoUpgrade[chapelNet] = &Upgrade{
+ UpgradeName: "bruno",
+ Configs: []*UpgradeConfig{},
+ }
+
+ brunoUpgrade[rialtoNet] = &Upgrade{
+ UpgradeName: "bruno",
+ Configs: []*UpgradeConfig{},
+ }
}
func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, statedb *state.StateDB) {
@@ -123,6 +140,10 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I
applySystemContractUpgrade(mirrorUpgrade[network], blockNumber, statedb, logger)
}
+ if config.IsOnBruno(blockNumber) {
+ applySystemContractUpgrade(brunoUpgrade[network], blockNumber, statedb, logger)
+ }
+
/*
apply other upgrades
*/
diff --git a/core/tx_pool.go b/core/tx_pool.go
index d0304857c..4c08bc72b 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -49,6 +49,9 @@ 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
+
+ // txReannoMaxNum is the maximum number of transactions a reannounce action can include.
+ txReannoMaxNum = 1024
)
var (
@@ -88,6 +91,7 @@ var (
var (
evictionInterval = time.Minute // Time interval to check for evictable transactions
statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats
+ reannounceInterval = time.Minute // Time interval to check for reannounce transactions
)
var (
@@ -152,7 +156,8 @@ type TxPoolConfig struct {
AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account
GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts
- Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
+ Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
+ ReannounceTime time.Duration // Duration for announcing local pending transactions again
}
// DefaultTxPoolConfig contains the default configurations for the transaction
@@ -169,7 +174,8 @@ var DefaultTxPoolConfig = TxPoolConfig{
AccountQueue: 64,
GlobalQueue: 1024,
- Lifetime: 3 * time.Hour,
+ Lifetime: 3 * time.Hour,
+ ReannounceTime: 10 * 365 * 24 * time.Hour,
}
// sanitize checks the provided user configurations and changes anything that's
@@ -208,6 +214,10 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig {
log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultTxPoolConfig.Lifetime)
conf.Lifetime = DefaultTxPoolConfig.Lifetime
}
+ if conf.ReannounceTime < time.Minute {
+ log.Warn("Sanitizing invalid txpool reannounce time", "provided", conf.ReannounceTime, "updated", time.Minute)
+ conf.ReannounceTime = time.Minute
+ }
return conf
}
@@ -219,14 +229,15 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig {
// current state) and future transactions. Transactions move between those
// two states over time as they are received and processed.
type TxPool struct {
- config TxPoolConfig
- chainconfig *params.ChainConfig
- chain blockChain
- gasPrice *big.Int
- txFeed event.Feed
- scope event.SubscriptionScope
- signer types.Signer
- mu sync.RWMutex
+ config TxPoolConfig
+ chainconfig *params.ChainConfig
+ chain blockChain
+ gasPrice *big.Int
+ txFeed event.Feed
+ reannoTxFeed event.Feed // Event feed for announcing transactions again
+ scope event.SubscriptionScope
+ signer types.Signer
+ mu sync.RWMutex
istanbul bool // Fork indicator whether we are in the istanbul stage.
eip2718 bool // Fork indicator whether we are using EIP-2718 type transactions.
@@ -323,14 +334,16 @@ func (pool *TxPool) loop() {
var (
prevPending, prevQueued, prevStales int
// Start the stats reporting and transaction eviction tickers
- report = time.NewTicker(statsReportInterval)
- evict = time.NewTicker(evictionInterval)
- journal = time.NewTicker(pool.config.Rejournal)
+ report = time.NewTicker(statsReportInterval)
+ evict = time.NewTicker(evictionInterval)
+ reannounce = time.NewTicker(reannounceInterval)
+ journal = time.NewTicker(pool.config.Rejournal)
// Track the previous head headers for transaction reorgs
head = pool.chain.CurrentBlock()
)
defer report.Stop()
defer evict.Stop()
+ defer reannounce.Stop()
defer journal.Stop()
for {
@@ -378,6 +391,33 @@ func (pool *TxPool) loop() {
}
pool.mu.Unlock()
+ case <-reannounce.C:
+ pool.mu.RLock()
+ reannoTxs := func() []*types.Transaction {
+ txs := make([]*types.Transaction, 0)
+ for addr, list := range pool.pending {
+ if !pool.locals.contains(addr) {
+ continue
+ }
+
+ for _, tx := range list.Flatten() {
+ // Default ReannounceTime is 10 years, won't announce by default.
+ if time.Since(tx.Time()) < pool.config.ReannounceTime {
+ break
+ }
+ txs = append(txs, tx)
+ if len(txs) >= txReannoMaxNum {
+ return txs
+ }
+ }
+ }
+ return txs
+ }()
+ pool.mu.RUnlock()
+ if len(reannoTxs) > 0 {
+ pool.reannoTxFeed.Send(ReannoTxsEvent{reannoTxs})
+ }
+
// Handle local transaction journal rotation
case <-journal.C:
if pool.journal != nil {
@@ -412,6 +452,12 @@ func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- NewTxsEvent) event.Subscripti
return pool.scope.Track(pool.txFeed.Subscribe(ch))
}
+// SubscribeReannoTxsEvent registers a subscription of ReannoTxsEvent and
+// starts sending event to the given channel.
+func (pool *TxPool) SubscribeReannoTxsEvent(ch chan<- ReannoTxsEvent) event.Subscription {
+ return pool.scope.Track(pool.reannoTxFeed.Subscribe(ch))
+}
+
// GasPrice returns the current gas price enforced by the transaction pool.
func (pool *TxPool) GasPrice() *big.Int {
pool.mu.RLock()
diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go
index 5d555f5a9..5f27631e1 100644
--- a/core/tx_pool_test.go
+++ b/core/tx_pool_test.go
@@ -1933,6 +1933,47 @@ func TestTransactionSlotCount(t *testing.T) {
}
}
+// Tests the local pending transaction announced again correctly.
+func TestTransactionPendingReannouce(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{statedb, 1000000, new(event.Feed)}
+
+ config := testTxPoolConfig
+ // This ReannounceTime will be modified to time.Minute when creating tx_pool.
+ config.ReannounceTime = time.Second
+ reannounceInterval = time.Second
+
+ pool := NewTxPool(config, params.TestChainConfig, blockchain)
+ // Modify ReannounceTime to trigger quicker.
+ pool.config.ReannounceTime = time.Second
+ defer pool.Stop()
+
+ key, _ := crypto.GenerateKey()
+ account := crypto.PubkeyToAddress(key.PublicKey)
+ pool.currentState.AddBalance(account, big.NewInt(1000000))
+
+ events := make(chan ReannoTxsEvent, testTxPoolConfig.AccountQueue)
+ sub := pool.reannoTxFeed.Subscribe(events)
+ defer sub.Unsubscribe()
+
+ // Generate a batch of transactions and add to tx_pool locally.
+ txs := make([]*types.Transaction, 0, testTxPoolConfig.AccountQueue)
+ for i := uint64(0); i < testTxPoolConfig.AccountQueue; i++ {
+ txs = append(txs, transaction(i, 100000, key))
+ }
+ pool.AddLocals(txs)
+
+ select {
+ case ev := <-events:
+ t.Logf("received reannouce event, txs length: %d", len(ev.Txs))
+ case <-time.After(5 * time.Second):
+ t.Errorf("reannouce event not fired")
+ }
+}
+
// Benchmarks the speed of validating the contents of the pending queue of the
// transaction pool.
func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) }
diff --git a/core/types.go b/core/types.go
index 49bd58e08..5ed4817e6 100644
--- a/core/types.go
+++ b/core/types.go
@@ -31,7 +31,7 @@ type Validator interface {
// ValidateState validates the given statedb and optionally the receipts and
// gas used.
- ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
+ ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64, skipHeavyVerify bool) error
}
// Prefetcher is an interface for pre-caching transaction signatures and state.
diff --git a/core/types/transaction.go b/core/types/transaction.go
index b127cb2af..74c011544 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -82,6 +82,11 @@ type TxData interface {
setSignatureValues(chainID, v, r, s *big.Int)
}
+// Time returns transaction's time
+func (tx *Transaction) Time() time.Time {
+ return tx.time
+}
+
// EncodeRLP implements rlp.Encoder
func (tx *Transaction) EncodeRLP(w io.Writer) error {
if tx.Type() == LegacyTxType {
diff --git a/core/vm/access_list_tracer.go b/core/vm/access_list_tracer.go
index b5bc961c8..d7993b4f7 100644
--- a/core/vm/access_list_tracer.go
+++ b/core/vm/access_list_tracer.go
@@ -141,7 +141,7 @@ func (a *AccessListTracer) CaptureStart(env *EVM, from common.Address, to common
}
// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
-func (a *AccessListTracer) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
+func (a *AccessListTracer) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
stack := scope.Stack
if (op == SLOAD || op == SSTORE) && stack.len() >= 1 {
slot := common.Hash(stack.data[stack.len()-1].Bytes32())
@@ -161,11 +161,16 @@ func (a *AccessListTracer) CaptureState(env *EVM, pc uint64, op OpCode, gas, cos
}
}
-func (*AccessListTracer) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
+func (*AccessListTracer) CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
}
func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
+func (*AccessListTracer) CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
+
// AccessList returns the current accesslist maintained by the tracer.
func (a *AccessListTracer) AccessList() types.AccessList {
return a.list.accessList()
diff --git a/core/vm/contract.go b/core/vm/contract.go
index 6fac7f985..dfc3ecd73 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -22,12 +22,18 @@ import (
lru "github.com/hashicorp/golang-lru"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/metrics"
"github.com/holiman/uint256"
)
const codeBitmapCacheSize = 2000
-var codeBitmapCache, _ = lru.New(codeBitmapCacheSize)
+var (
+ codeBitmapCache, _ = lru.New(codeBitmapCacheSize)
+
+ contractCodeBitmapHitMeter = metrics.NewRegisteredMeter("vm/contract/code/bitmap/hit", nil)
+ contractCodeBitmapMissMeter = metrics.NewRegisteredMeter("vm/contract/code/bitmap/miss", nil)
+)
// ContractRef is a reference to the contract's backing object
type ContractRef interface {
@@ -117,12 +123,14 @@ func (c *Contract) isCode(udest uint64) bool {
analysis, exist := c.jumpdests[c.CodeHash]
if !exist {
if cached, ok := codeBitmapCache.Get(c.CodeHash); ok {
+ contractCodeBitmapHitMeter.Mark(1)
analysis = cached.(bitvec)
} else {
// Do the analysis and save in parent context
// We do not need to store it in c.analysis
analysis = codeBitmap(c.Code)
c.jumpdests[c.CodeHash] = analysis
+ contractCodeBitmapMissMeter.Mark(1)
codeBitmapCache.Add(c.CodeHash, analysis)
}
}
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 26a5fa7c4..53e2e8797 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -232,9 +232,14 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
if !evm.StateDB.Exist(addr) {
if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
// Calling a non existing account, don't do anything, but ping the tracer
- if evm.vmConfig.Debug && evm.depth == 0 {
- evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
- evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
+ if evm.vmConfig.Debug {
+ if evm.depth == 0 {
+ evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
+ } else {
+ evm.vmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ evm.vmConfig.Tracer.CaptureExit(ret, 0, nil)
+ }
}
return nil, gas, nil
}
@@ -243,11 +248,19 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
// Capture the tracer start/end events in debug mode
- if evm.vmConfig.Debug && evm.depth == 0 {
- evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
- defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
- evm.vmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
- }(gas, time.Now())
+ if evm.vmConfig.Debug {
+ if evm.depth == 0 {
+ evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
+ evm.vmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
+ }(gas, time.Now())
+ } else {
+ // Handle tracer events for entering and exiting a call frame
+ evm.vmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ defer func(startGas uint64) {
+ evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
}
if isPrecompile {
@@ -307,6 +320,14 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
}
var snapshot = evm.StateDB.Snapshot()
+ // Invoke tracer hooks that signal entering/exiting a call frame
+ if evm.vmConfig.Debug {
+ evm.vmConfig.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
+ defer func(startGas uint64) {
+ evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
+
// It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas)
@@ -343,6 +364,14 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
}
var snapshot = evm.StateDB.Snapshot()
+ // Invoke tracer hooks that signal entering/exiting a call frame
+ if evm.vmConfig.Debug {
+ evm.vmConfig.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil)
+ defer func(startGas uint64) {
+ evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
+
// It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas)
@@ -388,6 +417,14 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// future scenarios
evm.StateDB.AddBalance(addr, big0)
+ // Invoke tracer hooks that signal entering/exiting a call frame
+ if evm.vmConfig.Debug {
+ evm.vmConfig.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
+ defer func(startGas uint64) {
+ evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
+ }(gas)
+ }
+
if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas)
} else {
@@ -427,7 +464,7 @@ func (c *codeAndHash) Hash() common.Hash {
}
// create creates a new contract using code as deployment code.
-func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
+func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm.depth > int(params.CallCreateDepth) {
@@ -465,9 +502,14 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
return nil, address, gas, nil
}
- if evm.vmConfig.Debug && evm.depth == 0 {
- evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
+ if evm.vmConfig.Debug {
+ if evm.depth == 0 {
+ evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
+ } else {
+ evm.vmConfig.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
+ }
}
+
start := time.Now()
ret, err := run(evm, contract, nil, false)
@@ -500,8 +542,12 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}
}
- if evm.vmConfig.Debug && evm.depth == 0 {
- evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
+ if evm.vmConfig.Debug {
+ if evm.depth == 0 {
+ evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
+ } else {
+ evm.vmConfig.Tracer.CaptureExit(ret, gas-contract.Gas, err)
+ }
}
return ret, address, contract.Gas, err
}
@@ -509,7 +555,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// Create creates a new contract using code as deployment code.
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
- return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr)
+ return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE)
}
// Create2 creates a new contract using code as deployment code.
@@ -519,7 +565,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
codeAndHash := &codeAndHash{code: code}
contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())
- return evm.create(caller, codeAndHash, gas, endowment, contractAddr)
+ return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
}
// ChainConfig returns the environment's chain configuration
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index f0eac1cc3..0ecf28d59 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -791,6 +791,10 @@ func opSuicide(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
interpreter.evm.StateDB.Suicide(scope.Contract.Address())
+ if interpreter.cfg.Debug {
+ interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
+ interpreter.cfg.Tracer.CaptureExit([]byte{}, 0, nil)
+ }
return nil, nil
}
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index 5fcf36cbb..d17ccfab8 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -568,11 +568,11 @@ func BenchmarkOpSHA3(bench *testing.B) {
env.interpreter = evmInterpreter
mem.Resize(32)
pc := uint64(0)
- start := uint256.NewInt(0)
+ start := uint256.NewInt()
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- stack.pushN(*uint256.NewInt(0).SetUint64(32), *start)
+ stack.pushN(*uint256.NewInt().SetUint64(32), *start)
opSha3(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
}
}
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index c004672ca..1155037a1 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -34,10 +34,10 @@ var EVMInterpreterPool = sync.Pool{
// Config are the configuration options for the Interpreter
type Config struct {
- Debug bool // Enables debugging
- Tracer Tracer // Opcode logger
- NoRecursion bool // Disables call, callcode, delegate call and create
- EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
+ Debug bool // Enables debugging
+ Tracer EVMLogger // Opcode logger
+ NoRecursion bool // Disables call, callcode, delegate call and create
+ EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
JumpTable [256]*operation // EVM instruction table, automatically populated if unset
@@ -183,9 +183,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
pc = uint64(0) // program counter
cost uint64
// copies used by tracer
- pcCopy uint64 // needed for the deferred Tracer
- gasCopy uint64 // for Tracer to log gas remaining before execution
- logged bool // deferred Tracer should ignore already logged steps
+ pcCopy uint64 // needed for the deferred EVMLogger
+ gasCopy uint64 // for EVMLogger to log gas remaining before execution
+ logged bool // deferred EVMLogger should ignore already logged steps
res []byte // result of the opcode execution function
)
// Don't move this deferrred function, it's placed before the capturestate-deferred method,
@@ -200,9 +200,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
defer func() {
if err != nil {
if !logged {
- in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
+ in.cfg.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
} else {
- in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err)
+ in.cfg.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err)
}
}
}()
@@ -284,7 +284,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
}
if in.cfg.Debug {
- in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
+ in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
logged = true
}
diff --git a/core/vm/logger.go b/core/vm/logger.go
index be24f315c..f8f08e726 100644
--- a/core/vm/logger.go
+++ b/core/vm/logger.go
@@ -47,12 +47,12 @@ func (s Storage) Copy() Storage {
// LogConfig are the configuration options for structured logger the EVM
type LogConfig struct {
- DisableMemory bool // disable memory capture
- DisableStack bool // disable stack capture
- DisableStorage bool // disable storage capture
- DisableReturnData bool // disable return data capture
- Debug bool // print output during capture end
- Limit int // maximum length of output, but zero means unlimited
+ EnableMemory bool // enable memory capture
+ DisableStack bool // disable stack capture
+ DisableStorage bool // disable storage capture
+ EnableReturnData bool // enable return data capture
+ Debug bool // print output during capture end
+ Limit int // maximum length of output, but zero means unlimited
// Chain overrides, can be used to execute a trace using future fork rules
Overrides *params.ChainConfig `json:"overrides,omitempty"`
}
@@ -99,25 +99,28 @@ func (s *StructLog) ErrorString() string {
return ""
}
-// Tracer is used to collect execution traces from an EVM transaction
+// EVMLogger is used to collect execution traces from an EVM transaction
// execution. CaptureState is called for each step of the VM with the
// current VM state.
// Note that reference types are actual VM data structures; make copies
// if you need to retain them beyond the current call.
-type Tracer interface {
+type EVMLogger interface {
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
- CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error)
- CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error)
+ CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error)
+ CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
+ CaptureExit(output []byte, gasUsed uint64, err error)
+ CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error)
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
}
-// StructLogger is an EVM state logger and implements Tracer.
+// StructLogger is an EVM state logger and implements EVMLogger.
//
// StructLogger can capture state based on the given Log configuration and also keeps
// a track record of modified storage which is used in reporting snapshots of the
// contract their storage.
type StructLogger struct {
cfg LogConfig
+ env *EVM
storage map[common.Address]Storage
logs []StructLog
@@ -144,14 +147,15 @@ func (l *StructLogger) Reset() {
l.err = nil
}
-// CaptureStart implements the Tracer interface to initialize the tracing operation.
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
func (l *StructLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ l.env = env
}
// CaptureState logs a new structured log message and pushes it out to the environment
//
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
-func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
+func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
memory := scope.Memory
stack := scope.Stack
contract := scope.Contract
@@ -161,7 +165,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
}
// Copy a snapshot of the current memory state to a new buffer
var mem []byte
- if !l.cfg.DisableMemory {
+ if l.cfg.EnableMemory {
mem = make([]byte, len(memory.Data()))
copy(mem, memory.Data())
}
@@ -185,7 +189,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
if op == SLOAD && stack.len() >= 1 {
var (
address = common.Hash(stack.data[stack.len()-1].Bytes32())
- value = env.StateDB.GetState(contract.Address(), address)
+ value = l.env.StateDB.GetState(contract.Address(), address)
)
l.storage[contract.Address()][address] = value
storage = l.storage[contract.Address()].Copy()
@@ -200,18 +204,18 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
}
}
var rdata []byte
- if !l.cfg.DisableReturnData {
+ if l.cfg.EnableReturnData {
rdata = make([]byte, len(rData))
copy(rdata, rData)
}
// create a new snapshot of the EVM.
- log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, env.StateDB.GetRefund(), err}
+ log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, l.env.StateDB.GetRefund(), err}
l.logs = append(l.logs, log)
}
-// CaptureFault implements the Tracer interface to trace an execution fault
+// CaptureFault implements the EVMLogger interface to trace an execution fault
// while running an opcode.
-func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
+func (l *StructLogger) CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
}
// CaptureEnd is called after the call finishes to finalize the tracing.
@@ -226,6 +230,11 @@ func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration
}
}
+func (l *StructLogger) CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
+
// StructLogs returns the captured log entries.
func (l *StructLogger) StructLogs() []StructLog { return l.logs }
@@ -285,12 +294,13 @@ func WriteLogs(writer io.Writer, logs []*types.Log) {
type mdLogger struct {
out io.Writer
cfg *LogConfig
+ env *EVM
}
// NewMarkdownLogger creates a logger which outputs information in a format adapted
// for human readability, and is also a valid markdown table
func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger {
- l := &mdLogger{writer, cfg}
+ l := &mdLogger{out: writer, cfg: cfg}
if l.cfg == nil {
l.cfg = &LogConfig{}
}
@@ -298,6 +308,7 @@ func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger {
}
func (t *mdLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ t.env = env
if !create {
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `0x%x`\nGas: `%d`\nValue `%v` wei\n",
from.String(), to.String(),
@@ -315,7 +326,7 @@ func (t *mdLogger) CaptureStart(env *EVM, from common.Address, to common.Address
}
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
-func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
+func (t *mdLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
stack := scope.Stack
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
@@ -328,14 +339,14 @@ func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64
b := fmt.Sprintf("[%v]", strings.Join(a, ","))
fmt.Fprintf(t.out, "%10v |", b)
}
- fmt.Fprintf(t.out, "%10v |", env.StateDB.GetRefund())
+ fmt.Fprintf(t.out, "%10v |", t.env.StateDB.GetRefund())
fmt.Fprintln(t.out, "")
if err != nil {
fmt.Fprintf(t.out, "Error: %v\n", err)
}
}
-func (t *mdLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
+func (t *mdLogger) CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
}
@@ -343,3 +354,8 @@ func (t *mdLogger) CaptureEnd(output []byte, gasUsed uint64, tm time.Duration, e
fmt.Fprintf(t.out, "\nOutput: `0x%x`\nConsumed gas: `%d`\nError: `%v`\n",
output, gasUsed, err)
}
+
+func (t *mdLogger) CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
diff --git a/core/vm/logger_json.go b/core/vm/logger_json.go
index 0975452b6..c249dba7e 100644
--- a/core/vm/logger_json.go
+++ b/core/vm/logger_json.go
@@ -29,12 +29,13 @@ import (
type JSONLogger struct {
encoder *json.Encoder
cfg *LogConfig
+ env *EVM
}
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
// into the provided stream.
func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger {
- l := &JSONLogger{json.NewEncoder(writer), cfg}
+ l := &JSONLogger{encoder: json.NewEncoder(writer), cfg: cfg}
if l.cfg == nil {
l.cfg = &LogConfig{}
}
@@ -42,12 +43,13 @@ func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger {
}
func (l *JSONLogger) CaptureStart(env *EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ l.env = env
}
-func (l *JSONLogger) CaptureFault(*EVM, uint64, OpCode, uint64, uint64, *ScopeContext, int, error) {}
+func (l *JSONLogger) CaptureFault(uint64, OpCode, uint64, uint64, *ScopeContext, int, error) {}
// CaptureState outputs state information on the logger.
-func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
+func (l *JSONLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
memory := scope.Memory
stack := scope.Stack
@@ -58,16 +60,16 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
GasCost: cost,
MemorySize: memory.Len(),
Depth: depth,
- RefundCounter: env.StateDB.GetRefund(),
+ RefundCounter: l.env.StateDB.GetRefund(),
Err: err,
}
- if !l.cfg.DisableMemory {
+ if l.cfg.EnableMemory {
log.Memory = memory.Data()
}
if !l.cfg.DisableStack {
log.Stack = stack.data
}
- if !l.cfg.DisableReturnData {
+ if l.cfg.EnableReturnData {
log.ReturnData = rData
}
l.encoder.Encode(log)
@@ -86,3 +88,8 @@ func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration,
}
l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), t, ""})
}
+
+func (l *JSONLogger) CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go
index 02182d1f2..5d1aa8e54 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/logger_test.go
@@ -60,10 +60,11 @@ func TestStoreCapture(t *testing.T) {
Contract: contract,
}
)
- scope.Stack.push(uint256.NewInt(0).SetUint64(1))
- scope.Stack.push(uint256.NewInt(0))
+ scope.Stack.push(uint256.NewInt().SetUint64(1))
+ scope.Stack.push(uint256.NewInt())
var index common.Hash
- logger.CaptureState(env, 0, SSTORE, 0, 0, scope, nil, 0, nil)
+ logger.CaptureStart(env, common.Address{}, contract.Address(), false, nil, 0, nil)
+ logger.CaptureState(0, SSTORE, 0, 0, scope, nil, 0, nil)
if len(logger.storage[contract.Address()]) == 0 {
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(),
len(logger.storage[contract.Address()]))
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index dcf2d0d44..fea7817ff 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -33,7 +33,11 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
+
+ // force-load js tracers to trigger registration
+ _ "github.com/ethereum/go-ethereum/eth/tracers/js"
)
func TestDefaults(t *testing.T) {
@@ -329,12 +333,12 @@ type stepCounter struct {
func (s *stepCounter) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
}
-func (s *stepCounter) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+func (s *stepCounter) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
}
func (s *stepCounter) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
-func (s *stepCounter) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+func (s *stepCounter) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
s.steps++
// Enable this for more output
//s.inner.CaptureState(env, pc, op, gas, cost, memory, stack, rStack, contract, depth, err)
@@ -342,11 +346,21 @@ func (s *stepCounter) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, co
// benchmarkNonModifyingCode benchmarks code, but if the code modifies the
// state, this should not be used, since it does not reset the state between runs.
-func benchmarkNonModifyingCode(gas uint64, code []byte, name string, b *testing.B) {
+func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode string, b *testing.B) {
cfg := new(Config)
setDefaults(cfg)
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
cfg.GasLimit = gas
+ if len(tracerCode) > 0 {
+ tracer, err := tracers.New(tracerCode, new(tracers.Context))
+ if err != nil {
+ b.Fatal(err)
+ }
+ cfg.EVMConfig = vm.Config{
+ Debug: true,
+ Tracer: tracer,
+ }
+ }
var (
destination = common.BytesToAddress([]byte("contract"))
vmenv = NewEnv(cfg)
@@ -486,12 +500,12 @@ func BenchmarkSimpleLoop(b *testing.B) {
// Tracer: tracer,
// }})
// 100M gas
- benchmarkNonModifyingCode(100000000, staticCallIdentity, "staticcall-identity-100M", b)
- benchmarkNonModifyingCode(100000000, callIdentity, "call-identity-100M", b)
- benchmarkNonModifyingCode(100000000, loopingCode, "loop-100M", b)
- benchmarkNonModifyingCode(100000000, callInexistant, "call-nonexist-100M", b)
- benchmarkNonModifyingCode(100000000, callEOA, "call-EOA-100M", b)
- benchmarkNonModifyingCode(100000000, calllRevertingContractWithInput, "call-reverting-100M", b)
+ benchmarkNonModifyingCode(100000000, staticCallIdentity, "staticcall-identity-100M", "", b)
+ benchmarkNonModifyingCode(100000000, callIdentity, "call-identity-100M", "", b)
+ benchmarkNonModifyingCode(100000000, loopingCode, "loop-100M", "", b)
+ benchmarkNonModifyingCode(100000000, callInexistant, "call-nonexist-100M", "", b)
+ benchmarkNonModifyingCode(100000000, callEOA, "call-EOA-100M", "", b)
+ benchmarkNonModifyingCode(100000000, calllRevertingContractWithInput, "call-reverting-100M", "", b)
//benchmarkNonModifyingCode(10000000, staticCallIdentity, "staticcall-identity-10M", b)
//benchmarkNonModifyingCode(10000000, loopingCode, "loop-10M", b)
@@ -500,7 +514,7 @@ func BenchmarkSimpleLoop(b *testing.B) {
// TestEip2929Cases contains various testcases that are used for
// EIP-2929 about gas repricings
func TestEip2929Cases(t *testing.T) {
-
+ t.Skip("Test only useful for generating documentation")
id := 1
prettyPrint := func(comment string, code []byte) {
@@ -688,3 +702,241 @@ func TestColdAccountAccessCost(t *testing.T) {
}
}
}
+
+func TestRuntimeJSTracer(t *testing.T) {
+ jsTracers := []string{
+ `{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, steps:0,
+ step: function() { this.steps++},
+ fault: function() {},
+ result: function() {
+ return [this.enters, this.exits,this.enterGas,this.gasUsed, this.steps].join(",")
+ },
+ enter: function(frame) {
+ this.enters++;
+ this.enterGas = frame.getGas();
+ },
+ exit: function(res) {
+ this.exits++;
+ this.gasUsed = res.getGasUsed();
+ }}`,
+ `{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, steps:0,
+ fault: function() {},
+ result: function() {
+ return [this.enters, this.exits,this.enterGas,this.gasUsed, this.steps].join(",")
+ },
+ enter: function(frame) {
+ this.enters++;
+ this.enterGas = frame.getGas();
+ },
+ exit: function(res) {
+ this.exits++;
+ this.gasUsed = res.getGasUsed();
+ }}`}
+ tests := []struct {
+ code []byte
+ // One result per tracer
+ results []string
+ }{
+ {
+ // CREATE
+ code: []byte{
+ // Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes)
+ byte(vm.PUSH5),
+ // Init code: PUSH1 0, PUSH1 0, RETURN (3 steps)
+ byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN),
+ byte(vm.PUSH1), 0,
+ byte(vm.MSTORE),
+ // length, offset, value
+ byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0,
+ byte(vm.CREATE),
+ byte(vm.POP),
+ },
+ results: []string{`"1,1,4294935775,6,12"`, `"1,1,4294935775,6,0"`},
+ },
+ {
+ // CREATE2
+ code: []byte{
+ // Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes)
+ byte(vm.PUSH5),
+ // Init code: PUSH1 0, PUSH1 0, RETURN (3 steps)
+ byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN),
+ byte(vm.PUSH1), 0,
+ byte(vm.MSTORE),
+ // salt, length, offset, value
+ byte(vm.PUSH1), 1, byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0,
+ byte(vm.CREATE2),
+ byte(vm.POP),
+ },
+ results: []string{`"1,1,4294935766,6,13"`, `"1,1,4294935766,6,0"`},
+ },
+ {
+ // CALL
+ code: []byte{
+ // outsize, outoffset, insize, inoffset
+ byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
+ byte(vm.PUSH1), 0, // value
+ byte(vm.PUSH1), 0xbb, //address
+ byte(vm.GAS), // gas
+ byte(vm.CALL),
+ byte(vm.POP),
+ },
+ results: []string{`"1,1,4294964716,6,13"`, `"1,1,4294964716,6,0"`},
+ },
+ {
+ // CALLCODE
+ code: []byte{
+ // outsize, outoffset, insize, inoffset
+ byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
+ byte(vm.PUSH1), 0, // value
+ byte(vm.PUSH1), 0xcc, //address
+ byte(vm.GAS), // gas
+ byte(vm.CALLCODE),
+ byte(vm.POP),
+ },
+ results: []string{`"1,1,4294964716,6,13"`, `"1,1,4294964716,6,0"`},
+ },
+ {
+ // STATICCALL
+ code: []byte{
+ // outsize, outoffset, insize, inoffset
+ byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
+ byte(vm.PUSH1), 0xdd, //address
+ byte(vm.GAS), // gas
+ byte(vm.STATICCALL),
+ byte(vm.POP),
+ },
+ results: []string{`"1,1,4294964719,6,12"`, `"1,1,4294964719,6,0"`},
+ },
+ {
+ // DELEGATECALL
+ code: []byte{
+ // outsize, outoffset, insize, inoffset
+ byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
+ byte(vm.PUSH1), 0xee, //address
+ byte(vm.GAS), // gas
+ byte(vm.DELEGATECALL),
+ byte(vm.POP),
+ },
+ results: []string{`"1,1,4294964719,6,12"`, `"1,1,4294964719,6,0"`},
+ },
+ {
+ // CALL self-destructing contract
+ code: []byte{
+ // outsize, outoffset, insize, inoffset
+ byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0,
+ byte(vm.PUSH1), 0, // value
+ byte(vm.PUSH1), 0xff, //address
+ byte(vm.GAS), // gas
+ byte(vm.CALL),
+ byte(vm.POP),
+ },
+ results: []string{`"2,2,0,5003,12"`, `"2,2,0,5003,0"`},
+ },
+ }
+ calleeCode := []byte{
+ byte(vm.PUSH1), 0,
+ byte(vm.PUSH1), 0,
+ byte(vm.RETURN),
+ }
+ depressedCode := []byte{
+ byte(vm.PUSH1), 0xaa,
+ byte(vm.SELFDESTRUCT),
+ }
+ main := common.HexToAddress("0xaa")
+ for i, jsTracer := range jsTracers {
+ for j, tc := range tests {
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
+ statedb.SetCode(main, tc.code)
+ statedb.SetCode(common.HexToAddress("0xbb"), calleeCode)
+ statedb.SetCode(common.HexToAddress("0xcc"), calleeCode)
+ statedb.SetCode(common.HexToAddress("0xdd"), calleeCode)
+ statedb.SetCode(common.HexToAddress("0xee"), calleeCode)
+ statedb.SetCode(common.HexToAddress("0xff"), depressedCode)
+
+ tracer, err := tracers.New(jsTracer, new(tracers.Context))
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, _, err = Call(main, nil, &Config{
+ State: statedb,
+ EVMConfig: vm.Config{
+ Debug: true,
+ Tracer: tracer,
+ }})
+ if err != nil {
+ t.Fatal("didn't expect error", err)
+ }
+ res, err := tracer.GetResult()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if have, want := string(res), tc.results[i]; have != want {
+ t.Errorf("wrong result for tracer %d testcase %d, have \n%v\nwant\n%v\n", i, j, have, want)
+ }
+ }
+ }
+}
+
+func TestJSTracerCreateTx(t *testing.T) {
+ jsTracer := `
+ {enters: 0, exits: 0,
+ step: function() {},
+ fault: function() {},
+ result: function() { return [this.enters, this.exits].join(",") },
+ enter: function(frame) { this.enters++ },
+ exit: function(res) { this.exits++ }}`
+ code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)}
+
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
+ tracer, err := tracers.New(jsTracer, new(tracers.Context))
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, _, _, err = Create(code, &Config{
+ State: statedb,
+ EVMConfig: vm.Config{
+ Debug: true,
+ Tracer: tracer,
+ }})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ res, err := tracer.GetResult()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if have, want := string(res), `"0,0"`; have != want {
+ t.Errorf("wrong result for tracer, have \n%v\nwant\n%v\n", have, want)
+ }
+}
+
+func BenchmarkTracerStepVsCallFrame(b *testing.B) {
+ // Simply pushes and pops some values in a loop
+ code := []byte{
+ byte(vm.JUMPDEST),
+ byte(vm.PUSH1), 0,
+ byte(vm.PUSH1), 0,
+ byte(vm.POP),
+ byte(vm.POP),
+ byte(vm.PUSH1), 0, // jumpdestination
+ byte(vm.JUMP),
+ }
+
+ stepTracer := `
+ {
+ step: function() {},
+ fault: function() {},
+ result: function() {},
+ }`
+ callFrameTracer := `
+ {
+ enter: function() {},
+ exit: function() {},
+ fault: function() {},
+ result: function() {},
+ }`
+
+ benchmarkNonModifyingCode(10000000, code, "tracer-step-10M", stepTracer, b)
+ benchmarkNonModifyingCode(10000000, code, "tracer-call-frame-10M", callFrameTracer, b)
+}
diff --git a/core/vm/stack.go b/core/vm/stack.go
index c71d2653a..220f97c89 100644
--- a/core/vm/stack.go
+++ b/core/vm/stack.go
@@ -91,7 +91,7 @@ func (st *Stack) Print() {
fmt.Println("### stack ###")
if len(st.data) > 0 {
for i, val := range st.data {
- fmt.Printf("%-3d %v\n", i, val)
+ fmt.Printf("%-3d %s\n", i, val.String())
}
} else {
fmt.Println("-- empty --")
diff --git a/crypto/blake2b/blake2bAVX2_amd64.go b/crypto/blake2b/blake2bAVX2_amd64.go
index 3a85d0e73..0d52b1869 100644
--- a/crypto/blake2b/blake2bAVX2_amd64.go
+++ b/crypto/blake2b/blake2bAVX2_amd64.go
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build go1.7 && amd64 && !gccgo && !appengine
// +build go1.7,amd64,!gccgo,!appengine
package blake2b
diff --git a/crypto/blake2b/blake2b_amd64.go b/crypto/blake2b/blake2b_amd64.go
index a318b2b61..4dbe90da8 100644
--- a/crypto/blake2b/blake2b_amd64.go
+++ b/crypto/blake2b/blake2b_amd64.go
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !go1.7 && amd64 && !gccgo && !appengine
// +build !go1.7,amd64,!gccgo,!appengine
package blake2b
diff --git a/crypto/blake2b/blake2b_f_fuzz.go b/crypto/blake2b/blake2b_f_fuzz.go
index b2f405707..ab7334280 100644
--- a/crypto/blake2b/blake2b_f_fuzz.go
+++ b/crypto/blake2b/blake2b_f_fuzz.go
@@ -1,4 +1,3 @@
-//go:build gofuzz
// +build gofuzz
package blake2b
diff --git a/crypto/blake2b/blake2b_ref.go b/crypto/blake2b/blake2b_ref.go
index 095c71a64..9d0ade473 100644
--- a/crypto/blake2b/blake2b_ref.go
+++ b/crypto/blake2b/blake2b_ref.go
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !amd64 || appengine || gccgo
// +build !amd64 appengine gccgo
package blake2b
diff --git a/crypto/blake2b/register.go b/crypto/blake2b/register.go
index 9d8633963..efd689af4 100644
--- a/crypto/blake2b/register.go
+++ b/crypto/blake2b/register.go
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build go1.9
// +build go1.9
package blake2b
diff --git a/crypto/bls12381/arithmetic_decl.go b/crypto/bls12381/arithmetic_decl.go
index f6d232d65..ec0b21e80 100644
--- a/crypto/bls12381/arithmetic_decl.go
+++ b/crypto/bls12381/arithmetic_decl.go
@@ -14,7 +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 (amd64 && blsasm) || (amd64 && blsadx)
// +build amd64,blsasm amd64,blsadx
package bls12381
diff --git a/crypto/bls12381/arithmetic_fallback.go b/crypto/bls12381/arithmetic_fallback.go
index c09ae0d91..91cabf4f3 100644
--- a/crypto/bls12381/arithmetic_fallback.go
+++ b/crypto/bls12381/arithmetic_fallback.go
@@ -31,7 +31,6 @@
// Package bls (generated by goff) contains field arithmetics operations
-//go:build !amd64 || (!blsasm && !blsadx)
// +build !amd64 !blsasm,!blsadx
package bls12381
diff --git a/crypto/bls12381/arithmetic_x86_adx.go b/crypto/bls12381/arithmetic_x86_adx.go
index a40c7384e..9c30741e6 100644
--- a/crypto/bls12381/arithmetic_x86_adx.go
+++ b/crypto/bls12381/arithmetic_x86_adx.go
@@ -14,7 +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 amd64 && blsadx
// +build amd64,blsadx
package bls12381
diff --git a/crypto/bls12381/arithmetic_x86_noadx.go b/crypto/bls12381/arithmetic_x86_noadx.go
index 679b30ec8..eaac4b45d 100644
--- a/crypto/bls12381/arithmetic_x86_noadx.go
+++ b/crypto/bls12381/arithmetic_x86_noadx.go
@@ -14,7 +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 amd64 && blsasm
// +build amd64,blsasm
package bls12381
diff --git a/crypto/bn256/bn256_fast.go b/crypto/bn256/bn256_fast.go
index e3c9b6051..14b596539 100644
--- a/crypto/bn256/bn256_fast.go
+++ b/crypto/bn256/bn256_fast.go
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
-//go:build amd64 || arm64
// +build amd64 arm64
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
diff --git a/crypto/bn256/bn256_slow.go b/crypto/bn256/bn256_slow.go
index 4c0c351e2..49021082f 100644
--- a/crypto/bn256/bn256_slow.go
+++ b/crypto/bn256/bn256_slow.go
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
-//go:build !amd64 && !arm64
// +build !amd64,!arm64
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
diff --git a/crypto/bn256/cloudflare/gfp_decl.go b/crypto/bn256/cloudflare/gfp_decl.go
index ec4018e88..fdea5c11a 100644
--- a/crypto/bn256/cloudflare/gfp_decl.go
+++ b/crypto/bn256/cloudflare/gfp_decl.go
@@ -1,4 +1,3 @@
-//go:build (amd64 && !generic) || (arm64 && !generic)
// +build amd64,!generic arm64,!generic
package bn256
diff --git a/crypto/bn256/cloudflare/gfp_generic.go b/crypto/bn256/cloudflare/gfp_generic.go
index 7742dda4c..8e6be9596 100644
--- a/crypto/bn256/cloudflare/gfp_generic.go
+++ b/crypto/bn256/cloudflare/gfp_generic.go
@@ -1,4 +1,3 @@
-//go:build (!amd64 && !arm64) || generic
// +build !amd64,!arm64 generic
package bn256
diff --git a/crypto/secp256k1/dummy.go b/crypto/secp256k1/dummy.go
index 65a75080f..c0f2ee52c 100644
--- a/crypto/secp256k1/dummy.go
+++ b/crypto/secp256k1/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// This file is part of a workaround for `go mod vendor` which won't vendor
diff --git a/crypto/secp256k1/libsecp256k1/contrib/dummy.go b/crypto/secp256k1/libsecp256k1/contrib/dummy.go
index 2c946210c..fda594be9 100644
--- a/crypto/secp256k1/libsecp256k1/contrib/dummy.go
+++ b/crypto/secp256k1/libsecp256k1/contrib/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// Package c contains only a C file.
diff --git a/crypto/secp256k1/libsecp256k1/dummy.go b/crypto/secp256k1/libsecp256k1/dummy.go
index 04bbe3d76..379b16992 100644
--- a/crypto/secp256k1/libsecp256k1/dummy.go
+++ b/crypto/secp256k1/libsecp256k1/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// Package c contains only a C file.
diff --git a/crypto/secp256k1/libsecp256k1/include/dummy.go b/crypto/secp256k1/libsecp256k1/include/dummy.go
index 64c71b845..5af540c73 100644
--- a/crypto/secp256k1/libsecp256k1/include/dummy.go
+++ b/crypto/secp256k1/libsecp256k1/include/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// Package c contains only a C file.
diff --git a/crypto/secp256k1/libsecp256k1/src/dummy.go b/crypto/secp256k1/libsecp256k1/src/dummy.go
index 2df270adc..65868f38a 100644
--- a/crypto/secp256k1/libsecp256k1/src/dummy.go
+++ b/crypto/secp256k1/libsecp256k1/src/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// Package c contains only a C file.
diff --git a/crypto/secp256k1/libsecp256k1/src/modules/dummy.go b/crypto/secp256k1/libsecp256k1/src/modules/dummy.go
index 99c538db5..3c7a69643 100644
--- a/crypto/secp256k1/libsecp256k1/src/modules/dummy.go
+++ b/crypto/secp256k1/libsecp256k1/src/modules/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// Package c contains only a C file.
diff --git a/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go b/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go
index 48c2e0aa5..b6fc38327 100644
--- a/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go
+++ b/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// Package c contains only a C file.
diff --git a/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go b/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go
index 8efbd7abe..b9491f0cb 100644
--- a/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go
+++ b/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go
@@ -1,4 +1,3 @@
-//go:build dummy
// +build dummy
// Package c contains only a C file.
diff --git a/crypto/signature_cgo.go b/crypto/signature_cgo.go
index f8c6d4930..1fe84509e 100644
--- a/crypto/signature_cgo.go
+++ b/crypto/signature_cgo.go
@@ -14,7 +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 !nacl && !js && cgo
// +build !nacl,!js,cgo
package crypto
diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go
index 200c15ac0..067d32e13 100644
--- a/crypto/signature_nocgo.go
+++ b/crypto/signature_nocgo.go
@@ -14,7 +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 nacl || js || !cgo
// +build nacl js !cgo
package crypto
diff --git a/crypto/signify/signify_fuzz.go b/crypto/signify/signify_fuzz.go
index 2dc9b2102..f9167900a 100644
--- a/crypto/signify/signify_fuzz.go
+++ b/crypto/signify/signify_fuzz.go
@@ -14,7 +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 gofuzz
// +build gofuzz
package signify
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 18514b7cc..daf6c19ec 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -338,8 +338,8 @@ func (b *EthAPIBackend) StartMining(threads int) error {
return b.eth.StartMining(threads)
}
-func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) {
- return b.eth.stateAtBlock(block, reexec, base, checkLive)
+func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) {
+ return b.eth.stateAtBlock(block, reexec, base, checkLive, preferDisk)
}
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
diff --git a/eth/api_test.go b/eth/api_test.go
index b44eed40b..359671579 100644
--- a/eth/api_test.go
+++ b/eth/api_test.go
@@ -77,7 +77,9 @@ func TestAccountRange(t *testing.T) {
m[addr] = true
}
}
- state.Commit(true)
+ state.Finalise(true)
+ state.AccountsIntermediateRoot()
+ state.Commit(nil)
root := state.IntermediateRoot(true)
trie, err := statedb.OpenTrie(root)
@@ -134,7 +136,7 @@ func TestEmptyAccountRange(t *testing.T) {
statedb = state.NewDatabase(rawdb.NewMemoryDatabase())
state, _ = state.New(common.Hash{}, statedb, nil)
)
- state.Commit(true)
+ state.Commit(nil)
state.IntermediateRoot(true)
results := state.IteratorDump(true, true, true, (common.Hash{}).Bytes(), AccountRangeMaxResults)
if bytes.Equal(results.Next, (common.Hash{}).Bytes()) {
diff --git a/eth/backend.go b/eth/backend.go
index f6599529d..ab9300643 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -203,6 +203,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.DiffSync {
bcOps = append(bcOps, core.EnableLightProcessor)
}
+ if config.PipeCommit {
+ bcOps = append(bcOps, core.EnablePipelineCommit)
+ }
if config.PersistDiff {
bcOps = append(bcOps, core.EnablePersistDiff(config.DiffBlock))
}
diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go
index 001b27147..593c62944 100644
--- a/eth/catalyst/api_test.go
+++ b/eth/catalyst/api_test.go
@@ -82,6 +82,7 @@ func generateTestChainWithFork(n int, fork int) (*core.Genesis, []*types.Block,
RamanujanBlock: big.NewInt(0),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
Ethash: new(params.EthashConfig),
}
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 5da80c9d3..e1225e7a1 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -53,6 +53,9 @@ var (
ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion
ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts
+ diffFetchTick = 10 * time.Millisecond
+ diffFetchLimit = 5
+
qosTuningPeers = 5 // Number of peers to tune based on (best peers)
qosConfidenceCap = 10 // Number of peers above which not to modify RTT confidence
qosTuningImpact = 0.25 // Impact that a new tuning target has on the previous value
@@ -161,10 +164,10 @@ type Downloader struct {
quitLock sync.Mutex // Lock to prevent double closes
// Testing hooks
- syncInitHook func(uint64, uint64) // Method to call upon initiating a new sync run
- bodyFetchHook func([]*types.Header, ...interface{}) // Method to call upon starting a block body fetch
- receiptFetchHook func([]*types.Header, ...interface{}) // Method to call upon starting a receipt fetch
- chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations)
+ syncInitHook func(uint64, uint64) // Method to call upon initiating a new sync run
+ 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, chan struct{}) // Method to call upon inserting a chain of blocks (possibly in multiple invocations)
}
// LightChain encapsulates functions required to synchronise a light chain.
@@ -232,27 +235,35 @@ type IPeerSet interface {
func EnableDiffFetchOp(peers IPeerSet) DownloadOption {
return func(dl *Downloader) *Downloader {
- var hook = func(headers []*types.Header, args ...interface{}) {
- if len(args) < 2 {
- return
- }
- peerID, ok := args[1].(string)
- if !ok {
- return
- }
- mode, ok := args[0].(SyncMode)
- if !ok {
- return
- }
- if ep := peers.GetDiffPeer(peerID); mode == FullSync && ep != nil {
- hashes := make([]common.Hash, 0, len(headers))
- for _, header := range headers {
- hashes = append(hashes, header.Hash())
- }
- ep.RequestDiffLayers(hashes)
+ var hook = func(results []*fetchResult, stop chan struct{}) {
+ if dl.getMode() == FullSync {
+ go func() {
+ ticker := time.NewTicker(diffFetchTick)
+ defer ticker.Stop()
+ for _, r := range results {
+ Wait:
+ for {
+ select {
+ case <-stop:
+ return
+ case <-ticker.C:
+ if dl.blockchain.CurrentHeader().Number.Int64()+int64(diffFetchLimit) > r.Header.Number.Int64() {
+ break Wait
+ }
+ }
+ }
+ if ep := peers.GetDiffPeer(r.pid); ep != nil {
+ // It turns out a diff layer is 5x larger than block, we just request one diffLayer each time
+ err := ep.RequestDiffLayers([]common.Hash{r.Header.Hash()})
+ if err != nil {
+ return
+ }
+ }
+ }
+ }()
}
}
- dl.bodyFetchHook = hook
+ dl.chainInsertHook = hook
return dl
}
}
@@ -588,10 +599,10 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
d.ancientLimit = 0
}
frozen, _ := d.stateDB.Ancients() // Ignore the error here since light client can also hit here.
-
+ itemAmountInAncient, _ := d.stateDB.ItemAmountInAncient()
// If a part of blockchain data has already been written into active store,
// disable the ancient style insertion explicitly.
- if origin >= frozen && frozen != 0 {
+ if origin >= frozen && itemAmountInAncient != 0 {
d.ancientLimit = 0
log.Info("Disabling direct-ancient mode", "origin", origin, "ancient", frozen-1)
} else if d.ancientLimit > 0 {
@@ -1405,7 +1416,7 @@ func (d *Downloader) fetchReceipts(from uint64) error {
// - kind: textual label of the type being downloaded to display in log messages
func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool,
expire func() map[string]int, pending func() int, inFlight func() bool, reserve func(*peerConnection, int) (*fetchRequest, bool, bool),
- fetchHook func([]*types.Header, ...interface{}), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int,
+ fetchHook func([]*types.Header), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int,
idle func() ([]*peerConnection, int), setIdle func(*peerConnection, int, time.Time), kind string) error {
// Create a ticker to detect expired retrieval tasks
@@ -1554,7 +1565,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
}
// Fetch the chunk and make sure any errors return the hashes to the queue
if fetchHook != nil {
- fetchHook(request.Headers, d.getMode(), peer.id)
+ fetchHook(request.Headers)
}
if err := fetch(peer, request); err != nil {
// Although we could try and make an attempt to fix this, this error really
@@ -1759,12 +1770,15 @@ func (d *Downloader) processFullSyncContent() error {
if len(results) == 0 {
return nil
}
+ stop := make(chan struct{})
if d.chainInsertHook != nil {
- d.chainInsertHook(results)
+ d.chainInsertHook(results, stop)
}
if err := d.importBlockResults(results); err != nil {
+ close(stop)
return err
}
+ close(stop)
}
}
@@ -1850,7 +1864,7 @@ func (d *Downloader) processFastSyncContent() error {
}
}
if d.chainInsertHook != nil {
- d.chainInsertHook(results)
+ d.chainInsertHook(results, nil)
}
// If we haven't downloaded the pivot block yet, check pivot staleness
// notifications from the header downloader
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index 66f687202..4b76b6a5d 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -565,7 +565,7 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
// Wrap the importer to allow stepping
blocked, proceed := uint32(0), make(chan struct{})
- tester.downloader.chainInsertHook = func(results []*fetchResult) {
+ tester.downloader.chainInsertHook = func(results []*fetchResult, _ chan struct{}) {
atomic.StoreUint32(&blocked, uint32(len(results)))
<-proceed
}
@@ -921,10 +921,10 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
// Instrument the downloader to signal body requests
bodiesHave, receiptsHave := int32(0), int32(0)
- tester.downloader.bodyFetchHook = func(headers []*types.Header, _ ...interface{}) {
+ tester.downloader.bodyFetchHook = func(headers []*types.Header) {
atomic.AddInt32(&bodiesHave, int32(len(headers)))
}
- tester.downloader.receiptFetchHook = func(headers []*types.Header, _ ...interface{}) {
+ tester.downloader.receiptFetchHook = func(headers []*types.Header) {
atomic.AddInt32(&receiptsHave, int32(len(headers)))
}
// Synchronise with the peer and make sure all blocks were retrieved
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index ac7edc2c6..3b01984da 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -63,6 +63,7 @@ type fetchRequest struct {
// all outstanding pieces complete and the result as a whole can be processed.
type fetchResult struct {
pending int32 // Flag telling what deliveries are outstanding
+ pid string
Header *types.Header
Uncles []*types.Header
@@ -70,9 +71,10 @@ type fetchResult struct {
Receipts types.Receipts
}
-func newFetchResult(header *types.Header, fastSync bool) *fetchResult {
+func newFetchResult(header *types.Header, fastSync bool, pid string) *fetchResult {
item := &fetchResult{
Header: header,
+ pid: pid,
}
if !header.EmptyBody() {
item.pending |= (1 << bodyType)
@@ -503,7 +505,7 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common
// we can ask the resultcache if this header is within the
// "prioritized" segment of blocks. If it is not, we need to throttle
- stale, throttle, item, err := q.resultCache.AddFetch(header, q.mode == FastSync)
+ stale, throttle, item, err := q.resultCache.AddFetch(header, q.mode == FastSync, p.id)
if stale {
// Don't put back in the task queue, this item has already been
// delivered upstream
diff --git a/eth/downloader/resultstore.go b/eth/downloader/resultstore.go
index 21928c2a0..98ce75593 100644
--- a/eth/downloader/resultstore.go
+++ b/eth/downloader/resultstore.go
@@ -75,7 +75,7 @@ func (r *resultStore) SetThrottleThreshold(threshold uint64) uint64 {
// throttled - if true, the store is at capacity, this particular header is not prio now
// item - the result to store data into
// err - any error that occurred
-func (r *resultStore) AddFetch(header *types.Header, fastSync bool) (stale, throttled bool, item *fetchResult, err error) {
+func (r *resultStore) AddFetch(header *types.Header, fastSync bool, pid string) (stale, throttled bool, item *fetchResult, err error) {
r.lock.Lock()
defer r.lock.Unlock()
@@ -85,7 +85,7 @@ func (r *resultStore) AddFetch(header *types.Header, fastSync bool) (stale, thro
return stale, throttled, item, err
}
if item == nil {
- item = newFetchResult(header, fastSync)
+ item = newFetchResult(header, fastSync, pid)
r.items[index] = item
}
return stale, throttled, item, err
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index 83db7fc99..09baad1e1 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -80,7 +80,7 @@ var Defaults = Config{
TrieTimeout: 60 * time.Minute,
TriesInMemory: 128,
SnapshotCache: 102,
- DiffBlock: uint64(864000),
+ DiffBlock: uint64(86400),
Miner: miner.Config{
GasFloor: 8000000,
GasCeil: 8000000,
@@ -137,6 +137,7 @@ type Config struct {
DirectBroadcast bool
DisableSnapProtocol bool //Whether disable snap protocol
DiffSync bool // Whether support diff sync
+ PipeCommit bool
RangeLimit bool
TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
diff --git a/eth/handler.go b/eth/handler.go
index f00f955b3..cbc6eca80 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -73,6 +73,10 @@ type txPool interface {
// SubscribeNewTxsEvent should return an event subscription of
// NewTxsEvent and send events to the given channel.
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
+
+ // SubscribeReannoTxsEvent should return an event subscription of
+ // ReannoTxsEvent and send events to the given channel.
+ SubscribeReannoTxsEvent(chan<- core.ReannoTxsEvent) event.Subscription
}
// handlerConfig is the collection of initialization parameters to create a full
@@ -120,6 +124,8 @@ type handler struct {
eventMux *event.TypeMux
txsCh chan core.NewTxsEvent
txsSub event.Subscription
+ reannoTxsCh chan core.ReannoTxsEvent
+ reannoTxsSub event.Subscription
minedBlockSub *event.TypeMuxSubscription
whitelist map[uint64]common.Hash
@@ -432,6 +438,12 @@ func (h *handler) Start(maxPeers int) {
h.txsSub = h.txpool.SubscribeNewTxsEvent(h.txsCh)
go h.txBroadcastLoop()
+ // announce local pending transactions again
+ h.wg.Add(1)
+ h.reannoTxsCh = make(chan core.ReannoTxsEvent, txChanSize)
+ h.reannoTxsSub = h.txpool.SubscribeReannoTxsEvent(h.reannoTxsCh)
+ go h.txReannounceLoop()
+
// broadcast mined blocks
h.wg.Add(1)
h.minedBlockSub = h.eventMux.Subscribe(core.NewMinedBlockEvent{})
@@ -445,6 +457,7 @@ func (h *handler) Start(maxPeers int) {
func (h *handler) Stop() {
h.txsSub.Unsubscribe() // quits txBroadcastLoop
+ h.reannoTxsSub.Unsubscribe() // quits txReannounceLoop
h.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop
// Quit chainSync and txsync64.
@@ -549,6 +562,24 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
"tx packs", directPeers, "broadcast txs", directCount)
}
+// ReannounceTransactions will announce a batch of local pending transactions
+// to a square root of all peers.
+func (h *handler) ReannounceTransactions(txs types.Transactions) {
+ hashes := make([]common.Hash, 0, txs.Len())
+ for _, tx := range txs {
+ hashes = append(hashes, tx.Hash())
+ }
+
+ // Announce transactions hash to a batch of peers
+ peersCount := uint(math.Sqrt(float64(h.peers.len())))
+ peers := h.peers.headPeers(peersCount)
+ for _, peer := range peers {
+ peer.AsyncSendPooledTransactionHashes(hashes)
+ }
+ log.Debug("Transaction reannounce", "txs", len(txs),
+ "announce packs", peersCount, "announced hashes", peersCount*uint(len(hashes)))
+}
+
// minedBroadcastLoop sends mined blocks to connected peers.
func (h *handler) minedBroadcastLoop() {
defer h.wg.Done()
@@ -573,3 +604,16 @@ func (h *handler) txBroadcastLoop() {
}
}
}
+
+// txReannounceLoop announces local pending transactions to connected peers again.
+func (h *handler) txReannounceLoop() {
+ defer h.wg.Done()
+ for {
+ select {
+ case event := <-h.reannoTxsCh:
+ h.ReannounceTransactions(event.Txs)
+ case <-h.reannoTxsSub.Err():
+ return
+ }
+ }
+}
diff --git a/eth/handler_diff.go b/eth/handler_diff.go
index a5fbfdb0a..6d5436bf9 100644
--- a/eth/handler_diff.go
+++ b/eth/handler_diff.go
@@ -47,7 +47,6 @@ func (h *diffHandler) RunPeer(peer *diff.Peer, hand diff.Handler) error {
ps.lock.Unlock()
return err
}
- defer h.chain.RemoveDiffPeer(peer.ID())
return (*handler)(h).runDiffExtension(peer, hand)
}
diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go
index 271bae07c..e85c74e6f 100644
--- a/eth/handler_eth_test.go
+++ b/eth/handler_eth_test.go
@@ -239,6 +239,76 @@ func testForkIDSplit(t *testing.T, protocol uint) {
func TestRecvTransactions65(t *testing.T) { testRecvTransactions(t, eth.ETH65) }
func TestRecvTransactions66(t *testing.T) { testRecvTransactions(t, eth.ETH66) }
+func TestWaitDiffExtensionTimout(t *testing.T) {
+ t.Parallel()
+
+ // Create a message handler, configure it to accept transactions and watch them
+ handler := newTestHandler()
+ defer handler.close()
+
+ // Create a source peer to send messages through and a sink handler to receive them
+ _, p2pSink := p2p.MsgPipe()
+ defer p2pSink.Close()
+
+ protos := []p2p.Protocol{
+ {
+ Name: "diff",
+ Version: 1,
+ },
+ }
+
+ sink := eth.NewPeer(eth.ETH67, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", []p2p.Cap{
+ {
+ Name: "diff",
+ Version: 1,
+ },
+ }), p2pSink, nil)
+ defer sink.Close()
+
+ err := handler.handler.runEthPeer(sink, func(peer *eth.Peer) error {
+ return eth.Handle((*ethHandler)(handler.handler), peer)
+ })
+
+ if err == nil || err.Error() != "peer wait timeout" {
+ t.Fatalf("error should be `peer wait timeout`")
+ }
+}
+
+func TestWaitSnapExtensionTimout(t *testing.T) {
+ t.Parallel()
+
+ // Create a message handler, configure it to accept transactions and watch them
+ handler := newTestHandler()
+ defer handler.close()
+
+ // Create a source peer to send messages through and a sink handler to receive them
+ _, p2pSink := p2p.MsgPipe()
+ defer p2pSink.Close()
+
+ protos := []p2p.Protocol{
+ {
+ Name: "snap",
+ Version: 1,
+ },
+ }
+
+ sink := eth.NewPeer(eth.ETH67, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", []p2p.Cap{
+ {
+ Name: "snap",
+ Version: 1,
+ },
+ }), p2pSink, nil)
+ defer sink.Close()
+
+ err := handler.handler.runEthPeer(sink, func(peer *eth.Peer) error {
+ return eth.Handle((*ethHandler)(handler.handler), peer)
+ })
+
+ if err == nil || err.Error() != "peer wait timeout" {
+ t.Fatalf("error should be `peer wait timeout`")
+ }
+}
+
func testRecvTransactions(t *testing.T, protocol uint) {
t.Parallel()
@@ -450,6 +520,59 @@ func testTransactionPropagation(t *testing.T, protocol uint) {
}
}
+// Tests that local pending transactions get propagated to peers.
+func TestTransactionPendingReannounce(t *testing.T) {
+ t.Parallel()
+
+ // Create a source handler to announce transactions from and a sink handler
+ // to receive them.
+ source := newTestHandler()
+ defer source.close()
+
+ sink := newTestHandler()
+ defer sink.close()
+ sink.handler.acceptTxs = 1 // mark synced to accept transactions
+
+ sourcePipe, sinkPipe := p2p.MsgPipe()
+ defer sourcePipe.Close()
+ defer sinkPipe.Close()
+
+ sourcePeer := eth.NewPeer(eth.ETH65, p2p.NewPeer(enode.ID{0}, "", nil), sourcePipe, source.txpool)
+ sinkPeer := eth.NewPeer(eth.ETH65, p2p.NewPeer(enode.ID{0}, "", nil), sinkPipe, sink.txpool)
+ defer sourcePeer.Close()
+ defer sinkPeer.Close()
+
+ go source.handler.runEthPeer(sourcePeer, func(peer *eth.Peer) error {
+ return eth.Handle((*ethHandler)(source.handler), peer)
+ })
+ go sink.handler.runEthPeer(sinkPeer, func(peer *eth.Peer) error {
+ return eth.Handle((*ethHandler)(sink.handler), peer)
+ })
+
+ // Subscribe transaction pools
+ txCh := make(chan core.NewTxsEvent, 1024)
+ sub := sink.txpool.SubscribeNewTxsEvent(txCh)
+ defer sub.Unsubscribe()
+
+ txs := make([]*types.Transaction, 64)
+ 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
+ }
+ source.txpool.ReannouceTransactions(txs)
+
+ for arrived := 0; arrived < len(txs); {
+ select {
+ case event := <-txCh:
+ arrived += len(event.Txs)
+ case <-time.NewTimer(time.Second).C:
+ t.Errorf("sink: transaction propagation timed out: have %d, want %d", arrived, len(txs))
+ }
+ }
+}
+
// Tests that post eth protocol handshake, clients perform a mutual checkpoint
// challenge to validate each other's chains. Hash mismatches, or missing ones
// during a fast sync should lead to the peer getting dropped.
diff --git a/eth/handler_test.go b/eth/handler_test.go
index a90ef5c34..c3b7b769b 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -48,8 +48,9 @@ var (
type testTxPool struct {
pool map[common.Hash]*types.Transaction // Hash map of collected transactions
- txFeed event.Feed // Notification feed to allow waiting for inclusion
- lock sync.RWMutex // Protects the transaction pool
+ txFeed event.Feed // Notification feed to allow waiting for inclusion
+ reannoTxFeed event.Feed // Notification feed to trigger reannouce
+ lock sync.RWMutex // Protects the transaction pool
}
// newTestTxPool creates a mock transaction pool.
@@ -90,6 +91,18 @@ func (p *testTxPool) AddRemotes(txs []*types.Transaction) []error {
return make([]error, len(txs))
}
+// ReannouceTransactions announce the transactions to some peers.
+func (p *testTxPool) ReannouceTransactions(txs []*types.Transaction) []error {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ for _, tx := range txs {
+ p.pool[tx.Hash()] = tx
+ }
+ p.reannoTxFeed.Send(core.ReannoTxsEvent{Txs: txs})
+ return make([]error, len(txs))
+}
+
// Pending returns all the transactions known to the pool
func (p *testTxPool) Pending() (map[common.Address]types.Transactions, error) {
p.lock.RLock()
@@ -112,6 +125,12 @@ func (p *testTxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subs
return p.txFeed.Subscribe(ch)
}
+// SubscribeReannoTxsEvent should return an event subscription of ReannoTxsEvent and
+// send events to the given channel.
+func (p *testTxPool) SubscribeReannoTxsEvent(ch chan<- core.ReannoTxsEvent) event.Subscription {
+ return p.reannoTxFeed.Subscribe(ch)
+}
+
// testHandler is a live implementation of the Ethereum protocol handler, just
// preinitialized with some sane testing defaults and the transaction pool mocked
// out.
diff --git a/eth/peerset.go b/eth/peerset.go
index 5b6f7ed69..0f5245a05 100644
--- a/eth/peerset.go
+++ b/eth/peerset.go
@@ -294,6 +294,22 @@ func (ps *peerSet) peer(id string) *ethPeer {
return ps.peers[id]
}
+// headPeers retrieves a specified number list of peers.
+func (ps *peerSet) headPeers(num uint) []*ethPeer {
+ ps.lock.RLock()
+ defer ps.lock.RUnlock()
+
+ if num > uint(len(ps.peers)) {
+ num = uint(len(ps.peers))
+ }
+
+ list := make([]*ethPeer, 0, num)
+ for _, p := range ps.peers {
+ list = append(list, p)
+ }
+ return list
+}
+
// peersWithoutBlock retrieves a list of peers that do not have a given block in
// their set of known hashes so it might be propagated to them.
func (ps *peerSet) peersWithoutBlock(hash common.Hash) []*ethPeer {
diff --git a/eth/protocols/diff/handler.go b/eth/protocols/diff/handler.go
index 8678ff7f6..18ec4e254 100644
--- a/eth/protocols/diff/handler.go
+++ b/eth/protocols/diff/handler.go
@@ -17,7 +17,7 @@ const (
softResponseLimit = 2 * 1024 * 1024
// maxDiffLayerServe is the maximum number of diff layers to serve.
- maxDiffLayerServe = 1024
+ maxDiffLayerServe = 128
)
var requestTracker = NewTracker(time.Minute)
diff --git a/eth/protocols/snap/range.go b/eth/protocols/snap/range.go
index 2627cb954..dd380ff47 100644
--- a/eth/protocols/snap/range.go
+++ b/eth/protocols/snap/range.go
@@ -42,15 +42,15 @@ func newHashRange(start common.Hash, num uint64) *hashRange {
step256.SetFromBig(step)
return &hashRange{
- current: new(uint256.Int).SetBytes32(start[:]),
+ current: uint256.NewInt().SetBytes32(start[:]),
step: step256,
}
}
// Next pushes the hash range to the next interval.
func (r *hashRange) Next() bool {
- next, overflow := new(uint256.Int).AddOverflow(r.current, r.step)
- if overflow {
+ next := new(uint256.Int)
+ if overflow := next.AddOverflow(r.current, r.step); overflow {
return false
}
r.current = next
@@ -65,17 +65,16 @@ func (r *hashRange) Start() common.Hash {
// End returns the last hash in the current interval.
func (r *hashRange) End() common.Hash {
// If the end overflows (non divisible range), return a shorter interval
- next, overflow := new(uint256.Int).AddOverflow(r.current, r.step)
- if overflow {
+ next := new(uint256.Int)
+ if overflow := next.AddOverflow(r.current, r.step); overflow {
return common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
}
- return next.SubUint64(next, 1).Bytes32()
+ return new(uint256.Int).Sub(next, uint256.NewInt().SetOne()).Bytes32()
}
// incHash returns the next hash, in lexicographical order (a.k.a plus one)
func incHash(h common.Hash) common.Hash {
- var a uint256.Int
- a.SetBytes32(h[:])
- a.AddUint64(&a, 1)
+ a := uint256.NewInt().SetBytes32(h[:])
+ a.Add(a, uint256.NewInt().SetOne())
return common.Hash(a.Bytes32())
}
diff --git a/eth/state_accessor.go b/eth/state_accessor.go
index 461dc491f..24a0e776f 100644
--- a/eth/state_accessor.go
+++ b/eth/state_accessor.go
@@ -37,7 +37,17 @@ import (
// are attempted to be reexecuted to generate the desired state. The optional
// base layer statedb can be passed then it's regarded as the statedb of the
// parent block.
-func (eth *Ethereum) stateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (statedb *state.StateDB, err error) {
+// Parameters:
+// - block: The block for which we want the state (== state at the stateRoot of the parent)
+// - reexec: The maximum number of blocks to reprocess trying to obtain the desired state
+// - base: If the caller is tracing multiple blocks, the caller can provide the parent state
+// continuously from the callsite.
+// - checklive: if true, then the live 'blockchain' state database is used. If the caller want to
+// perform Commit or other 'save-to-disk' changes, this should be set to false to avoid
+// storing trash persistently
+// - preferDisk: this arg can be used by the caller to signal that even though the 'base' is provided,
+// it would be preferrable to start from a fresh state, if we have it on disk.
+func (eth *Ethereum) stateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) {
var (
current *types.Block
database state.Database
@@ -52,6 +62,15 @@ func (eth *Ethereum) stateAtBlock(block *types.Block, reexec uint64, base *state
}
}
if base != nil {
+ if preferDisk {
+ // Create an ephemeral trie.Database for isolating the live one. Otherwise
+ // the internal junks created by tracing will be persisted into the disk.
+ database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16})
+ if statedb, err = state.New(block.Root(), database, nil); err == nil {
+ log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
+ return statedb, nil
+ }
+ }
// The optional base statedb is given, mark the start point as parent block
statedb, database, report = base, base.Database(), false
current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
@@ -119,9 +138,12 @@ func (eth *Ethereum) stateAtBlock(block *types.Block, reexec uint64, base *state
return nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err)
}
// Finalize the state so any modifications are written to the trie
- root, _, err := statedb.Commit(eth.blockchain.Config().IsEIP158(current.Number()))
+ statedb.Finalise(eth.blockchain.Config().IsEIP158(current.Number()))
+ statedb.AccountsIntermediateRoot()
+ root, _, err := statedb.Commit(nil)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w",
+ current.NumberU64(), current.Root().Hex(), err)
}
statedb, err = state.New(root, database, nil)
if err != nil {
@@ -153,7 +175,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec
}
// Lookup the statedb of parent block from the live database,
// otherwise regenerate it on the flight.
- statedb, err := eth.stateAtBlock(parent, reexec, nil, true)
+ statedb, err := eth.stateAtBlock(parent, reexec, nil, true, false)
if err != nil {
return nil, vm.BlockContext{}, nil, err
}
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index 5f20858b2..8ee2c22ff 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -55,6 +55,13 @@ const (
// and reexecute to produce missing historical state necessary to run a specific
// trace.
defaultTraceReexec = uint64(128)
+
+ // defaultTracechainMemLimit is the size of the triedb, at which traceChain
+ // switches over and tries to use a disk-backed database instead of building
+ // on top of memory.
+ // For non-archive nodes, this limit _will_ be overblown, as disk-backed tries
+ // will only be found every ~15K blocks or so.
+ defaultTracechainMemLimit = common.StorageSize(500 * 1024 * 1024)
)
// Backend interface provides the common API services (that are provided by
@@ -69,7 +76,10 @@ type Backend interface {
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
ChainDb() ethdb.Database
- StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error)
+ // StateAtBlock returns the state corresponding to the stateroot of the block.
+ // N.B: For executing transactions on block N, the required stateRoot is block N-1,
+ // so this method should be called with the parent.
+ StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error)
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error)
}
@@ -180,13 +190,6 @@ type StdTraceConfig struct {
TxHash common.Hash
}
-// txTraceContext is the contextual infos about a transaction before it gets run.
-type txTraceContext struct {
- index int // Index of the transaction within the block
- hash common.Hash // Hash of the transaction
- block common.Hash // Hash of the block containing the transaction
-}
-
// txTraceResult is the result of a single transaction trace.
type txTraceResult struct {
Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
@@ -274,10 +277,10 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
// Trace all the transactions contained within
for i, tx := range task.block.Transactions() {
msg, _ := tx.AsMessage(signer)
- txctx := &txTraceContext{
- index: i,
- hash: tx.Hash(),
- block: task.block.Hash(),
+ txctx := &Context{
+ BlockHash: task.block.Hash(),
+ TxIndex: i,
+ TxHash: tx.Hash(),
}
res, err := api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, config)
if err != nil {
@@ -299,7 +302,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
})
}
// Start a goroutine to feed all the blocks into the tracers
- begin := time.Now()
+ var (
+ begin = time.Now()
+ derefTodo []common.Hash // list of hashes to dereference from the db
+ derefsMu sync.Mutex // mutex for the derefs
+ )
gopool.Submit(func() {
var (
@@ -325,6 +332,7 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
}
close(results)
}()
+ var preferDisk bool
// Feed all the blocks both into the tracer, as well as fast process concurrently
for number = start.NumberU64(); number < end.NumberU64(); number++ {
// Stop tracing if interruption was requested
@@ -333,6 +341,14 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
return
default:
}
+ // clean out any derefs
+ derefsMu.Lock()
+ for _, h := range derefTodo {
+ statedb.Database().TrieDB().Dereference(h)
+ }
+ derefTodo = derefTodo[:0]
+ derefsMu.Unlock()
+
// Print progress logs if long enough time elapsed
if time.Since(logged) > 8*time.Second {
logged = time.Now()
@@ -346,18 +362,24 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
}
// Prepare the statedb for tracing. Don't use the live database for
// tracing to avoid persisting state junks into the database.
- statedb, err = api.backend.StateAtBlock(localctx, block, reexec, statedb, false)
+ statedb, err = api.backend.StateAtBlock(localctx, block, reexec, statedb, false, preferDisk)
if err != nil {
failed = err
break
}
- if statedb.Database().TrieDB() != nil {
+ if trieDb := statedb.Database().TrieDB(); trieDb != nil {
// Hold the reference for tracer, will be released at the final stage
- statedb.Database().TrieDB().Reference(block.Root(), common.Hash{})
+ trieDb.Reference(block.Root(), common.Hash{})
// Release the parent state because it's already held by the tracer
if parent != (common.Hash{}) {
- statedb.Database().TrieDB().Dereference(parent)
+ trieDb.Dereference(parent)
+ }
+ // Prefer disk if the trie db memory grows too much
+ s1, s2 := trieDb.Size()
+ if !preferDisk && (s1+s2) > defaultTracechainMemLimit {
+ log.Info("Switching to prefer-disk mode for tracing", "size", s1+s2)
+ preferDisk = true
}
}
parent = block.Root()
@@ -391,12 +413,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
Hash: res.block.Hash(),
Traces: res.results,
}
+ // Schedule any parent tries held in memory by this task for dereferencing
done[uint64(result.Block)] = result
-
- // Dereference any parent tries held in memory by this task
- if res.statedb.Database().TrieDB() != nil {
- res.statedb.Database().TrieDB().Dereference(res.rootref)
- }
+ derefsMu.Lock()
+ derefTodo = append(derefTodo, res.rootref)
+ derefsMu.Unlock()
// Stream completed traces to the user, aborting on the first error
for result, ok := done[next]; ok; result, ok = done[next] {
if len(result.Traces) > 0 || next == end.NumberU64() {
@@ -454,12 +475,11 @@ func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *Tra
// EVM against a block pulled from the pool of bad ones and returns them as a JSON
// object.
func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
- for _, block := range rawdb.ReadAllBadBlocks(api.backend.ChainDb()) {
- if block.Hash() == hash {
- return api.traceBlock(ctx, block, config)
- }
+ block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
+ if block == nil {
+ return nil, fmt.Errorf("bad block %#x not found", hash)
}
- return nil, fmt.Errorf("bad block %#x not found", hash)
+ return api.traceBlock(ctx, block, config)
}
// StandardTraceBlockToFile dumps the structured logs created during the
@@ -473,16 +493,85 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash,
return api.standardTraceBlockToFile(ctx, block, config)
}
+// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
+// of intermediate roots: the stateroot after each transaction.
+func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
+ block, _ := api.blockByHash(ctx, hash)
+ if block == nil {
+ // Check in the bad blocks
+ block = rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
+ }
+ if block == nil {
+ return nil, fmt.Errorf("block %#x not found", hash)
+ }
+ if block.NumberU64() == 0 {
+ return nil, errors.New("genesis is not traceable")
+ }
+ parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
+ if err != nil {
+ return nil, err
+ }
+ reexec := defaultTraceReexec
+ if config != nil && config.Reexec != nil {
+ reexec = *config.Reexec
+ }
+ statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
+ if err != nil {
+ return nil, err
+ }
+ var (
+ roots []common.Hash
+ signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
+ chainConfig = api.backend.ChainConfig()
+ vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
+ deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
+ )
+ for i, tx := range block.Transactions() {
+ var (
+ msg, _ = tx.AsMessage(signer)
+ txContext = core.NewEVMTxContext(msg)
+ vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
+ )
+
+ if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
+ if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
+ balance := statedb.GetBalance(consensus.SystemAddress)
+ if balance.Cmp(common.Big0) > 0 {
+ statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
+ statedb.AddBalance(vmctx.Coinbase, balance)
+ }
+ }
+ }
+
+ statedb.Prepare(tx.Hash(), block.Hash(), i)
+ if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); 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
+ // be included, but still want the intermediate roots that led to that point.
+ // It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
+ // executable.
+ // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
+ return roots, nil
+ }
+ // calling IntermediateRoot will internally call Finalize on the state
+ // so any modifications are written to the trie
+ root := statedb.IntermediateRoot(deleteEmptyObjects)
+
+ roots = append(roots, root)
+ }
+ return roots, nil
+}
+
// StandardTraceBadBlockToFile dumps the structured logs created during the
// execution of EVM against a block pulled from the pool of bad ones to the
// local file system and returns a list of files to the caller.
func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
- for _, block := range rawdb.ReadAllBadBlocks(api.backend.ChainDb()) {
- if block.Hash() == hash {
- return api.standardTraceBlockToFile(ctx, block, config)
- }
+ block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
+ if block == nil {
+ return nil, fmt.Errorf("bad block %#x not found", hash)
}
- return nil, fmt.Errorf("bad block %#x not found", hash)
+ return api.standardTraceBlockToFile(ctx, block, config)
}
// traceBlock configures a new tracer according to the provided configuration, and
@@ -500,7 +589,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
- statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true)
+ statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
if err != nil {
return nil, err
}
@@ -520,16 +609,18 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
blockHash := block.Hash()
for th := 0; th < threads; th++ {
+ blockCtx := blockCtx
+
pend.Add(1)
gopool.Submit(func() {
defer pend.Done()
// Fetch and execute the next transaction trace tasks
for task := range jobs {
msg, _ := txs[task.index].AsMessage(signer)
- txctx := &txTraceContext{
- index: task.index,
- hash: txs[task.index].Hash(),
- block: blockHash,
+ txctx := &Context{
+ BlockHash: blockHash,
+ TxIndex: task.index,
+ TxHash: txs[task.index].Hash(),
}
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
if err != nil {
@@ -542,6 +633,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
}
// Feed the transactions into the tracers and return
var failed error
+ blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
for i, tx := range txs {
// Send the trace task over for execution
jobs <- &txTraceTask{statedb: statedb.Copy(), index: i}
@@ -600,7 +692,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
- statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true)
+ statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
if err != nil {
return nil, err
}
@@ -740,10 +832,10 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
if err != nil {
return nil, err
}
- txctx := &txTraceContext{
- index: int(index),
- hash: hash,
- block: blockHash,
+ txctx := &Context{
+ BlockHash: blockHash,
+ TxIndex: int(index),
+ TxHash: hash,
}
return api.traceTx(ctx, msg, txctx, vmctx, statedb, config)
}
@@ -773,7 +865,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHa
if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
- statedb, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true)
+ statedb, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
if err != nil {
return nil, err
}
@@ -796,21 +888,23 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.CallArgs, blockNrOrHa
Reexec: config.Reexec,
}
}
- return api.traceTx(ctx, msg, new(txTraceContext), vmctx, statedb, traceConfig)
+ return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig)
}
// 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 *txTraceContext, 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) {
// Assemble the structured logger or the JavaScript tracer
var (
- tracer vm.Tracer
+ tracer vm.EVMLogger
err error
txContext = core.NewEVMTxContext(message)
)
switch {
- case config != nil && config.Tracer != nil:
+ case config == nil:
+ tracer = vm.NewStructLogger(nil)
+ case config.Tracer != nil:
// Define a meaningful timeout of a single transaction trace
timeout := defaultTraceTimeout
if config.Timeout != nil {
@@ -818,23 +912,19 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *txTrac
return nil, err
}
}
- // Constuct the JavaScript tracer to execute with
- if tracer, err = New(*config.Tracer, txContext); err != nil {
+ if t, err := New(*config.Tracer, txctx); err != nil {
return nil, err
+ } else {
+ deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
+ go func() {
+ <-deadlineCtx.Done()
+ if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
+ t.Stop(errors.New("execution timeout"))
+ }
+ }()
+ defer cancel()
+ tracer = t
}
- // Handle timeouts and RPC cancellations
- deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
- gopool.Submit(func() {
- <-deadlineCtx.Done()
- if deadlineCtx.Err() == context.DeadlineExceeded {
- tracer.(*Tracer).Stop(errors.New("execution timeout"))
- }
- })
- defer cancel()
-
- case config == nil:
- tracer = vm.NewStructLogger(nil)
-
default:
tracer = vm.NewStructLogger(config.LogConfig)
}
@@ -851,7 +941,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *txTrac
}
// Call Prepare to clear out the statedb access list
- statedb.Prepare(txctx.hash, txctx.block, txctx.index)
+ statedb.Prepare(txctx.TxHash, txctx.BlockHash, txctx.TxIndex)
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
if err != nil {
@@ -873,7 +963,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *txTrac
StructLogs: ethapi.FormatLogs(tracer.StructLogs()),
}, nil
- case *Tracer:
+ case Tracer:
return tracer.GetResult()
default:
diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go
index 598c84c3b..6a64de0e3 100644
--- a/eth/tracers/api_test.go
+++ b/eth/tracers/api_test.go
@@ -139,7 +139,7 @@ func (b *testBackend) ChainDb() ethdb.Database {
return b.chaindb
}
-func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) {
+func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (*state.StateDB, error) {
statedb, err := b.chain.StateAt(block.Root())
if err != nil {
return nil, errStateNotFound
@@ -307,147 +307,6 @@ func TestTraceCall(t *testing.T) {
}
}
-func TestOverridenTraceCall(t *testing.T) {
- t.Parallel()
-
- // Initialize test accounts
- accounts := newAccounts(3)
- genesis := &core.Genesis{Alloc: core.GenesisAlloc{
- accounts[0].addr: {Balance: big.NewInt(params.Ether)},
- accounts[1].addr: {Balance: big.NewInt(params.Ether)},
- accounts[2].addr: {Balance: big.NewInt(params.Ether)},
- }}
- genBlocks := 10
- signer := types.HomesteadSigner{}
- api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
- // Transfer from account[0] to account[1]
- // value: 1000 wei
- // fee: 0 wei
- tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, big.NewInt(0), nil), signer, accounts[0].key)
- b.AddTx(tx)
- }))
- randomAccounts, tracer := newAccounts(3), "callTracer"
-
- var testSuite = []struct {
- blockNumber rpc.BlockNumber
- call ethapi.CallArgs
- config *TraceCallConfig
- expectErr error
- expect *callTrace
- }{
- // Succcessful call with state overriding
- {
- blockNumber: rpc.PendingBlockNumber,
- call: ethapi.CallArgs{
- From: &randomAccounts[0].addr,
- To: &randomAccounts[1].addr,
- Value: (*hexutil.Big)(big.NewInt(1000)),
- },
- config: &TraceCallConfig{
- Tracer: &tracer,
- StateOverrides: ðapi.StateOverride{
- randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
- },
- },
- expectErr: nil,
- expect: &callTrace{
- Type: "CALL",
- From: randomAccounts[0].addr,
- To: randomAccounts[1].addr,
- Gas: newRPCUint64(24979000),
- GasUsed: newRPCUint64(0),
- Value: (*hexutil.Big)(big.NewInt(1000)),
- },
- },
- // Invalid call without state overriding
- {
- blockNumber: rpc.PendingBlockNumber,
- call: ethapi.CallArgs{
- From: &randomAccounts[0].addr,
- To: &randomAccounts[1].addr,
- Value: (*hexutil.Big)(big.NewInt(1000)),
- },
- config: &TraceCallConfig{
- Tracer: &tracer,
- },
- expectErr: core.ErrInsufficientFundsForTransfer,
- expect: nil,
- },
- // Successful simple contract call
- //
- // // SPDX-License-Identifier: GPL-3.0
- //
- // pragma solidity >=0.7.0 <0.8.0;
- //
- // /**
- // * @title Storage
- // * @dev Store & retrieve value in a variable
- // */
- // contract Storage {
- // uint256 public number;
- // constructor() {
- // number = block.number;
- // }
- // }
- {
- blockNumber: rpc.PendingBlockNumber,
- call: ethapi.CallArgs{
- From: &randomAccounts[0].addr,
- To: &randomAccounts[2].addr,
- Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number()
- },
- config: &TraceCallConfig{
- Tracer: &tracer,
- StateOverrides: ðapi.StateOverride{
- randomAccounts[2].addr: ethapi.OverrideAccount{
- Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
- StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}),
- },
- },
- },
- expectErr: nil,
- expect: &callTrace{
- Type: "CALL",
- From: randomAccounts[0].addr,
- To: randomAccounts[2].addr,
- Input: hexutil.Bytes(common.Hex2Bytes("8381f58a")),
- Output: hexutil.Bytes(common.BigToHash(big.NewInt(123)).Bytes()),
- Gas: newRPCUint64(24978936),
- GasUsed: newRPCUint64(2283),
- Value: (*hexutil.Big)(big.NewInt(0)),
- },
- },
- }
- for _, testspec := range testSuite {
- result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
- if testspec.expectErr != nil {
- if err == nil {
- t.Errorf("Expect error %v, get nothing", testspec.expectErr)
- continue
- }
- if !errors.Is(err, testspec.expectErr) {
- t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err)
- }
- } else {
- if err != nil {
- t.Errorf("Expect no error, get %v", err)
- continue
- }
- ret := new(callTrace)
- if err := json.Unmarshal(result.(json.RawMessage), ret); err != nil {
- t.Fatalf("failed to unmarshal trace result: %v", err)
- }
- if !jsonEqual(ret, testspec.expect) {
- // uncomment this for easier debugging
- //have, _ := json.MarshalIndent(ret, "", " ")
- //want, _ := json.MarshalIndent(testspec.expect, "", " ")
- //t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
- t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, testspec.expect)
- }
- }
- }
-}
-
func TestTraceTransaction(t *testing.T) {
t.Parallel()
@@ -504,90 +363,177 @@ func TestTraceBlock(t *testing.T) {
var testSuite = []struct {
blockNumber rpc.BlockNumber
config *TraceConfig
- expect interface{}
+ want string
expectErr error
}{
// Trace genesis block, expect error
{
blockNumber: rpc.BlockNumber(0),
- config: nil,
- expect: nil,
expectErr: errors.New("genesis is not traceable"),
},
// Trace head block
{
blockNumber: rpc.BlockNumber(genBlocks),
- config: nil,
- expectErr: nil,
- expect: []*txTraceResult{
- {
- Result: ðapi.ExecutionResult{
- Gas: params.TxGas,
- Failed: false,
- ReturnValue: "",
- StructLogs: []ethapi.StructLogRes{},
- },
- },
- },
+ want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
},
// Trace non-existent block
{
blockNumber: rpc.BlockNumber(genBlocks + 1),
- config: nil,
expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
- expect: nil,
},
// Trace latest block
{
blockNumber: rpc.LatestBlockNumber,
- config: nil,
- expectErr: nil,
- expect: []*txTraceResult{
- {
- Result: ðapi.ExecutionResult{
- Gas: params.TxGas,
- Failed: false,
- ReturnValue: "",
- StructLogs: []ethapi.StructLogRes{},
- },
+ want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
+ },
+ // Trace pending block
+ {
+ blockNumber: rpc.PendingBlockNumber,
+ want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
+ },
+ }
+ for i, tc := range testSuite {
+ result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config)
+ if tc.expectErr != nil {
+ if err == nil {
+ t.Errorf("test %d, want error %v", i, tc.expectErr)
+ continue
+ }
+ if !reflect.DeepEqual(err, tc.expectErr) {
+ t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err)
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("test %d, want no error, have %v", i, err)
+ continue
+ }
+ have, _ := json.Marshal(result)
+ want := tc.want
+ if string(have) != want {
+ t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want)
+ }
+ }
+}
+
+func TestTracingWithOverrides(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ accounts := newAccounts(3)
+ genesis := &core.Genesis{Alloc: core.GenesisAlloc{
+ accounts[0].addr: {Balance: big.NewInt(params.Ether)},
+ accounts[1].addr: {Balance: big.NewInt(params.Ether)},
+ accounts[2].addr: {Balance: big.NewInt(params.Ether)},
+ }}
+ genBlocks := 10
+ signer := types.HomesteadSigner{}
+ api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
+ // Transfer from account[0] to account[1]
+ // value: 1000 wei
+ // fee: 0 wei
+ tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, big.NewInt(0), nil), signer, accounts[0].key)
+ b.AddTx(tx)
+ }))
+ randomAccounts := newAccounts(3)
+ type res struct {
+ Gas int
+ Failed bool
+ returnValue string
+ }
+ var testSuite = []struct {
+ blockNumber rpc.BlockNumber
+ call ethapi.CallArgs
+ config *TraceCallConfig
+ expectErr error
+ want string
+ }{
+ // Call which can only succeed if state is state overridden
+ {
+ blockNumber: rpc.PendingBlockNumber,
+ call: ethapi.CallArgs{
+ From: &randomAccounts[0].addr,
+ To: &randomAccounts[1].addr,
+ Value: (*hexutil.Big)(big.NewInt(1000)),
+ },
+ config: &TraceCallConfig{
+ StateOverrides: ðapi.StateOverride{
+ randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
},
},
+ want: `{"gas":21000,"failed":false,"returnValue":""}`,
},
- // Trace pending block
+ // Invalid call without state overriding
+ {
+ blockNumber: rpc.PendingBlockNumber,
+ call: ethapi.CallArgs{
+ From: &randomAccounts[0].addr,
+ To: &randomAccounts[1].addr,
+ Value: (*hexutil.Big)(big.NewInt(1000)),
+ },
+ config: &TraceCallConfig{},
+ expectErr: core.ErrInsufficientFundsForTransfer,
+ },
+ // Successful simple contract call
+ //
+ // // SPDX-License-Identifier: GPL-3.0
+ //
+ // pragma solidity >=0.7.0 <0.8.0;
+ //
+ // /**
+ // * @title Storage
+ // * @dev Store & retrieve value in a variable
+ // */
+ // contract Storage {
+ // uint256 public number;
+ // constructor() {
+ // number = block.number;
+ // }
+ // }
{
blockNumber: rpc.PendingBlockNumber,
- config: nil,
- expectErr: nil,
- expect: []*txTraceResult{
- {
- Result: ðapi.ExecutionResult{
- Gas: params.TxGas,
- Failed: false,
- ReturnValue: "",
- StructLogs: []ethapi.StructLogRes{},
+ call: ethapi.CallArgs{
+ From: &randomAccounts[0].addr,
+ To: &randomAccounts[2].addr,
+ Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number()
+ },
+ config: &TraceCallConfig{
+ //Tracer: &tracer,
+ StateOverrides: ðapi.StateOverride{
+ randomAccounts[2].addr: ethapi.OverrideAccount{
+ Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
+ StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}),
},
},
},
+ want: `{"gas":23347,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000007b"}`,
},
}
- for _, testspec := range testSuite {
- result, err := api.TraceBlockByNumber(context.Background(), testspec.blockNumber, testspec.config)
- if testspec.expectErr != nil {
+ for i, tc := range testSuite {
+ result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
+ if tc.expectErr != nil {
if err == nil {
- t.Errorf("Expect error %v, get nothing", testspec.expectErr)
+ t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)
continue
}
- if !reflect.DeepEqual(err, testspec.expectErr) {
- t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err)
- }
- } else {
- if err != nil {
- t.Errorf("Expect no error, get %v", err)
- continue
- }
- if !reflect.DeepEqual(result, testspec.expect) {
- t.Errorf("Result mismatch, want %v, get %v", testspec.expect, result)
+ if !errors.Is(err, tc.expectErr) {
+ t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err)
}
+ continue
+ }
+ if err != nil {
+ t.Errorf("test %d: want no error, have %v", i, err)
+ continue
+ }
+ // Turn result into res-struct
+ var (
+ have res
+ want res
+ )
+ resBytes, _ := json.Marshal(result)
+ json.Unmarshal(resBytes, &have)
+ json.Unmarshal([]byte(tc.want), &want)
+ if !reflect.DeepEqual(have, want) {
+ t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(resBytes), want)
}
}
}
@@ -618,11 +564,6 @@ func newRPCBalance(balance *big.Int) **hexutil.Big {
return &rpcBalance
}
-func newRPCUint64(number uint64) *hexutil.Uint64 {
- rpcUint64 := hexutil.Uint64(number)
- return &rpcUint64
-}
-
func newRPCBytes(bytes []byte) *hexutil.Bytes {
rpcBytes := hexutil.Bytes(bytes)
return &rpcBytes
diff --git a/eth/tracers/internal/tracers/call_tracer_js.js b/eth/tracers/internal/tracers/call_tracer_js.js
new file mode 100644
index 000000000..fccec1886
--- /dev/null
+++ b/eth/tracers/internal/tracers/call_tracer_js.js
@@ -0,0 +1,112 @@
+// 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 .
+
+
+// callFrameTracer uses the new call frame tracing methods to report useful information
+// about internal messages of a transaction.
+{
+ callstack: [{}],
+ fault: function(log, db) { },
+ result: function(ctx, db) {
+ // Prepare outer message info
+ var result = {
+ type: ctx.type,
+ from: toHex(ctx.from),
+ to: toHex(ctx.to),
+ value: '0x' + ctx.value.toString(16),
+ gas: '0x' + bigInt(ctx.gas).toString(16),
+ gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16),
+ input: toHex(ctx.input),
+ output: toHex(ctx.output),
+ }
+ if (this.callstack[0].calls !== undefined) {
+ result.calls = this.callstack[0].calls
+ }
+ if (this.callstack[0].error !== undefined) {
+ result.error = this.callstack[0].error
+ } else if (ctx.error !== undefined) {
+ result.error = ctx.error
+ }
+ if (result.error !== undefined && (result.error !== "execution reverted" || result.output === "0x")) {
+ delete result.output
+ }
+
+ return this.finalize(result)
+ },
+ enter: function(frame) {
+ var call = {
+ type: frame.getType(),
+ from: toHex(frame.getFrom()),
+ to: toHex(frame.getTo()),
+ input: toHex(frame.getInput()),
+ gas: '0x' + bigInt(frame.getGas()).toString('16'),
+ }
+ if (frame.getValue() !== undefined) {
+ call.value = '0x' + bigInt(frame.getValue()).toString(16)
+ }
+ this.callstack.push(call)
+ },
+ exit: function(frameResult) {
+ var len = this.callstack.length
+ if (len > 1) {
+ var call = this.callstack.pop()
+ call.gasUsed = '0x' + bigInt(frameResult.getGasUsed()).toString('16')
+ var error = frameResult.getError()
+ if (error === undefined) {
+ call.output = toHex(frameResult.getOutput())
+ } else {
+ call.error = error
+ if (call.type === 'CREATE' || call.type === 'CREATE2') {
+ delete call.to
+ }
+ }
+ len -= 1
+ if (this.callstack[len - 1].calls === undefined) {
+ this.callstack[len - 1].calls = []
+ }
+ this.callstack[len - 1].calls.push(call)
+ }
+ },
+ // finalize recreates a call object using the final desired field oder for json
+ // serialization. This is a nicety feature to pass meaningfully ordered results
+ // to users who don't interpret it, just display it.
+ finalize: function(call) {
+ var sorted = {
+ type: call.type,
+ from: call.from,
+ to: call.to,
+ value: call.value,
+ gas: call.gas,
+ gasUsed: call.gasUsed,
+ input: call.input,
+ output: call.output,
+ error: call.error,
+ time: call.time,
+ calls: call.calls,
+ }
+ for (var key in sorted) {
+ if (sorted[key] === undefined) {
+ delete sorted[key]
+ }
+ }
+ if (sorted.calls !== undefined) {
+ for (var i = 0; i < sorted.calls.length; i++) {
+ sorted.calls[i] = this.finalize(sorted.calls[i])
+ }
+ }
+ return sorted
+ }
+}
diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go
new file mode 100644
index 000000000..a71b36f0e
--- /dev/null
+++ b/eth/tracers/internal/tracetest/calltrace_test.go
@@ -0,0 +1,394 @@
+// 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 tracetest
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "math/big"
+ "path/filepath"
+ "reflect"
+ "strings"
+ "testing"
+ "unicode"
+
+ "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/rawdb"
+ "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/eth/tracers"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/tests"
+
+ // Force-load native and js pacakges, to trigger registration
+ _ "github.com/ethereum/go-ethereum/eth/tracers/js"
+ _ "github.com/ethereum/go-ethereum/eth/tracers/native"
+)
+
+// To generate a new callTracer test, copy paste the makeTest method below into
+// a Geth console and call it with a transaction hash you which to export.
+
+/*
+// makeTest generates a callTracer test by running a prestate reassembled and a
+// call trace run, assembling all the gathered information into a test case.
+var makeTest = function(tx, rewind) {
+ // Generate the genesis block from the block, transaction and prestate data
+ var block = eth.getBlock(eth.getTransaction(tx).blockHash);
+ var genesis = eth.getBlock(block.parentHash);
+
+ delete genesis.gasUsed;
+ delete genesis.logsBloom;
+ delete genesis.parentHash;
+ delete genesis.receiptsRoot;
+ delete genesis.sha3Uncles;
+ delete genesis.size;
+ delete genesis.transactions;
+ delete genesis.transactionsRoot;
+ delete genesis.uncles;
+
+ genesis.gasLimit = genesis.gasLimit.toString();
+ genesis.number = genesis.number.toString();
+ genesis.timestamp = genesis.timestamp.toString();
+
+ genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer", rewind: rewind});
+ for (var key in genesis.alloc) {
+ genesis.alloc[key].nonce = genesis.alloc[key].nonce.toString();
+ }
+ genesis.config = admin.nodeInfo.protocols.eth.config;
+
+ // Generate the call trace and produce the test input
+ var result = debug.traceTransaction(tx, {tracer: "callTracer", rewind: rewind});
+ delete result.time;
+
+ console.log(JSON.stringify({
+ genesis: genesis,
+ context: {
+ number: block.number.toString(),
+ difficulty: block.difficulty,
+ timestamp: block.timestamp.toString(),
+ gasLimit: block.gasLimit.toString(),
+ miner: block.miner,
+ },
+ input: eth.getRawTransaction(tx),
+ result: result,
+ }, null, 2));
+}
+*/
+
+type callContext struct {
+ Number math.HexOrDecimal64 `json:"number"`
+ Difficulty *math.HexOrDecimal256 `json:"difficulty"`
+ Time math.HexOrDecimal64 `json:"timestamp"`
+ GasLimit math.HexOrDecimal64 `json:"gasLimit"`
+ Miner common.Address `json:"miner"`
+}
+
+// callTrace is the result of a callTracer run.
+type callTrace struct {
+ Type string `json:"type"`
+ From common.Address `json:"from"`
+ To common.Address `json:"to"`
+ Input hexutil.Bytes `json:"input"`
+ Output hexutil.Bytes `json:"output"`
+ Gas *hexutil.Uint64 `json:"gas,omitempty"`
+ GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"`
+ Value *hexutil.Big `json:"value,omitempty"`
+ Error string `json:"error,omitempty"`
+ Calls []callTrace `json:"calls,omitempty"`
+}
+
+// callTracerTest defines a single test to check the call tracer against.
+type callTracerTest struct {
+ Genesis *core.Genesis `json:"genesis"`
+ Context *callContext `json:"context"`
+ Input string `json:"input"`
+ Result *callTrace `json:"result"`
+}
+
+// Iterates over all the input-output datasets in the tracer test harness and
+// runs the JavaScript tracers against them.
+func TestCallTracerLegacy(t *testing.T) {
+ testCallTracer("callTracerLegacy", "call_tracer_legacy", t)
+}
+
+func TestCallTracerJs(t *testing.T) {
+ testCallTracer("callTracerJs", "call_tracer", t)
+}
+
+func TestCallTracerNative(t *testing.T) {
+ testCallTracer("callTracer", "call_tracer", t)
+}
+
+func testCallTracer(tracerName string, dirPath string, t *testing.T) {
+ files, err := ioutil.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()
+
+ var (
+ test = new(callTracerTest)
+ tx = new(types.Transaction)
+ )
+ // Call tracer test found, read if from disk
+ if blob, err := ioutil.ReadFile(filepath.Join("testdata", dirPath, file.Name())); err != nil {
+ t.Fatalf("failed to read testcase: %v", err)
+ } else if err := json.Unmarshal(blob, test); err != nil {
+ t.Fatalf("failed to parse testcase: %v", err)
+ }
+ if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil {
+ t.Fatalf("failed to parse testcase input: %v", err)
+ }
+ // Configure a blockchain with the given prestate
+ var (
+ signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
+ 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: new(big.Int).SetUint64(uint64(test.Context.Time)),
+ Difficulty: (*big.Int)(test.Context.Difficulty),
+ GasLimit: uint64(test.Context.GasLimit),
+ }
+ _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false)
+ )
+ tracer, err := tracers.New(tracerName, new(tracers.Context))
+ if err != nil {
+ 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)
+ if err != nil {
+ t.Fatalf("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 {
+ t.Fatalf("failed to execute transaction: %v", err)
+ }
+ // Retrieve the trace result and compare against the etalon
+ res, err := tracer.GetResult()
+ if err != nil {
+ t.Fatalf("failed to retrieve trace result: %v", err)
+ }
+ ret := new(callTrace)
+ if err := json.Unmarshal(res, ret); err != nil {
+ t.Fatalf("failed to unmarshal trace result: %v", err)
+ }
+
+ if !jsonEqual(ret, test.Result) {
+ // uncomment this for easier debugging
+ //have, _ := json.MarshalIndent(ret, "", " ")
+ //want, _ := json.MarshalIndent(test.Result, "", " ")
+ //t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
+ t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result)
+ }
+ })
+ }
+}
+
+// jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to
+// comparison
+func jsonEqual(x, y interface{}) bool {
+ xTrace := new(callTrace)
+ yTrace := new(callTrace)
+ 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)
+}
+
+// camel converts a snake cased input string into a camel cased output.
+func camel(str string) string {
+ pieces := strings.Split(str, "_")
+ for i := 1; i < len(pieces); i++ {
+ pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:]
+ }
+ return strings.Join(pieces, "")
+}
+func BenchmarkTracers(b *testing.B) {
+ files, err := ioutil.ReadDir(filepath.Join("testdata", "call_tracer"))
+ if err != nil {
+ b.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
+ b.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(b *testing.B) {
+ blob, err := ioutil.ReadFile(filepath.Join("testdata", "call_tracer", file.Name()))
+ if err != nil {
+ b.Fatalf("failed to read testcase: %v", err)
+ }
+ test := new(callTracerTest)
+ if err := json.Unmarshal(blob, test); err != nil {
+ b.Fatalf("failed to parse testcase: %v", err)
+ }
+ benchTracer("callTracerNative", test, b)
+ })
+ }
+}
+
+func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
+ // Configure a blockchain with the given prestate
+ tx := new(types.Transaction)
+ if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil {
+ 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)
+ if err != nil {
+ b.Fatalf("failed to prepare transaction for tracing: %v", err)
+ }
+ 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: new(big.Int).SetUint64(uint64(test.Context.Time)),
+ Difficulty: (*big.Int)(test.Context.Difficulty),
+ GasLimit: uint64(test.Context.GasLimit),
+ }
+ _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ tracer, err := tracers.New(tracerName, new(tracers.Context))
+ if err != nil {
+ b.Fatalf("failed to create call tracer: %v", err)
+ }
+ evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
+ snap := statedb.Snapshot()
+ st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
+ if _, err = st.TransitionDb(); err != nil {
+ b.Fatalf("failed to execute transaction: %v", err)
+ }
+ if _, err = tracer.GetResult(); err != nil {
+ b.Fatal(err)
+ }
+ statedb.RevertToSnapshot(snap)
+ }
+}
+
+// TestZeroValueToNotExitCall tests the calltracer(s) on the following:
+// Tx to A, A calls B with zero value. B does not already exist.
+// Expected: that enter/exit is invoked and the inner call is shown in the result
+func TestZeroValueToNotExitCall(t *testing.T) {
+ var to = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
+ privkey, err := crypto.HexToECDSA("0000000000000000deadbeef00000000000000000000000000000000deadbeef")
+ if err != nil {
+ t.Fatalf("err %v", err)
+ }
+ signer := types.NewEIP155Signer(big.NewInt(1))
+ tx, err := types.SignNewTx(privkey, signer, &types.LegacyTx{
+ GasPrice: big.NewInt(0),
+ Gas: 50000,
+ To: &to,
+ })
+ if err != nil {
+ t.Fatalf("err %v", err)
+ }
+ origin, _ := signer.Sender(tx)
+ txContext := vm.TxContext{
+ Origin: origin,
+ GasPrice: big.NewInt(1),
+ }
+ context := vm.BlockContext{
+ CanTransfer: core.CanTransfer,
+ Transfer: core.Transfer,
+ Coinbase: common.Address{},
+ BlockNumber: new(big.Int).SetUint64(8000000),
+ Time: new(big.Int).SetUint64(5),
+ Difficulty: big.NewInt(0x30000),
+ GasLimit: uint64(6000000),
+ }
+ var code = []byte{
+ byte(vm.PUSH1), 0x0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), // in and outs zero
+ byte(vm.DUP1), byte(vm.PUSH1), 0xff, byte(vm.GAS), // value=0,address=0xff, gas=GAS
+ byte(vm.CALL),
+ }
+ var alloc = core.GenesisAlloc{
+ to: core.GenesisAccount{
+ Nonce: 1,
+ Code: code,
+ },
+ origin: core.GenesisAccount{
+ Nonce: 0,
+ Balance: big.NewInt(500000000000000),
+ },
+ }
+ _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false)
+ // Create the tracer, the EVM environment and run it
+ tracer, err := tracers.New("callTracer", nil)
+ if err != nil {
+ 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)
+ if err != nil {
+ t.Fatalf("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 {
+ t.Fatalf("failed to execute transaction: %v", err)
+ }
+ // Retrieve the trace result and compare against the etalon
+ res, err := tracer.GetResult()
+ if err != nil {
+ t.Fatalf("failed to retrieve trace result: %v", err)
+ }
+ have := new(callTrace)
+ if err := json.Unmarshal(res, have); err != nil {
+ t.Fatalf("failed to unmarshal trace result: %v", err)
+ }
+ wantStr := `{"type":"CALL","from":"0x682a80a6f560eec50d54e63cbeda1c324c5f8d1b","to":"0x00000000000000000000000000000000deadbeef","value":"0x0","gas":"0x7148","gasUsed":"0x2d0","input":"0x","output":"0x","calls":[{"type":"CALL","from":"0x00000000000000000000000000000000deadbeef","to":"0x00000000000000000000000000000000000000ff","value":"0x0","gas":"0x6cbf","gasUsed":"0x0","input":"0x","output":"0x"}]}`
+ want := new(callTrace)
+ json.Unmarshal([]byte(wantStr), want)
+ if !jsonEqual(have, want) {
+ t.Error("have != want")
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/create.json b/eth/tracers/internal/tracetest/testdata/call_tracer/create.json
new file mode 100644
index 000000000..8699bf3e7
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/create.json
@@ -0,0 +1,58 @@
+{
+ "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": {
+ "from": "0x13e4acefe6a6700604929946e70e6443e4e73447",
+ "gas": "0x5e106",
+ "gasUsed": "0x5e106",
+ "input": "0x606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a11",
+ "output": "0x606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029",
+ "to": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448",
+ "type": "CREATE",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/deep_calls.json b/eth/tracers/internal/tracetest/testdata/call_tracer/deep_calls.json
new file mode 100644
index 000000000..0353d4cfa
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/deep_calls.json
@@ -0,0 +1,415 @@
+{
+ "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": {
+ "calls": [
+ {
+ "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "gas": "0x31217",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e7472616374617069000000000000000000000000000000000000000000",
+ "output": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x2a68d",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x23ac9",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e7472616374646200000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x23366",
+ "gasUsed": "0x273",
+ "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x7986bad81f4cbd9317f5a46861437dae58d69113",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x29f35",
+ "gasUsed": "0xf8d",
+ "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x28a9e",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x21d79",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x2165b",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000",
+ "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x1a8e8",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x1a2c6",
+ "gasUsed": "0x3cb",
+ "input": "0xc9503fe2",
+ "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x19b72",
+ "gasUsed": "0x3cb",
+ "input": "0xc9503fe2",
+ "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x19428",
+ "gasUsed": "0x305",
+ "input": "0x6f265b93",
+ "output": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x18d45",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x1734e",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x20ee1",
+ "gasUsed": "0x5374",
+ "input": "0x581d5d60000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1b6c1",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1af69",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "gas": "0x143a5",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1a91d",
+ "gasUsed": "0x12fa",
+ "input": "0x0accce0600000000000000000000000000000000000000000000000000000000000000025842545553440000000000000000000000000000000000000000000000000000000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "output": "0x",
+ "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x19177",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x18a22",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x18341",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000",
+ "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x17bec",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1764e",
+ "gasUsed": "0x45c",
+ "input": "0xf92eb7745842545553440000000000000000000000000000000000000000000000000000",
+ "output": "0x00000000000000000000000000000000000000000000002816d180e30c390000",
+ "to": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "gas": "0x108ba",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x16e62",
+ "gasUsed": "0xebb",
+ "input": "0x645a3b72584254555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002816d180e30c390000",
+ "output": "0x",
+ "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x283b9",
+ "gasUsed": "0xc51c",
+ "input": "0x949ae479000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "gas": "0x30b4a",
+ "gasUsed": "0xedb7",
+ "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x70c9217d814985faef62b124420f8dfbddd96433",
+ "gas": "0x37b38",
+ "gasUsed": "0x12bb3",
+ "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/delegatecall.json b/eth/tracers/internal/tracetest/testdata/call_tracer/delegatecall.json
new file mode 100644
index 000000000..f7ad6df5f
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/delegatecall.json
@@ -0,0 +1,97 @@
+{
+ "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": {
+ "calls": [
+ {
+ "calls": [
+ {
+ "from": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff",
+ "gas": "0x2bf459",
+ "gasUsed": "0x2aa",
+ "input": "0x7d65837a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2",
+ "type": "DELEGATECALL"
+ }
+ ],
+ "from": "0x269296dddce321a6bcbaa2f0181127593d732cba",
+ "gas": "0x2cae73",
+ "gasUsed": "0xa9d",
+ "input": "0x5dbe47e8000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xa529806c67cc6486d4d62024471772f47f6fd672",
+ "gas": "0x2d6e28",
+ "gasUsed": "0x64bd",
+ "input": "0x7065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e",
+ "output": "0x",
+ "to": "0x269296dddce321a6bcbaa2f0181127593d732cba",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
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
new file mode 100644
index 000000000..9395eb401
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json
@@ -0,0 +1,77 @@
+{
+ "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": {
+ "calls": [
+ {
+ "error": "contract creation code storage out of gas",
+ "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a",
+ "gas": "0x39ff0",
+ "gasUsed": "0x39ff0",
+ "input": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182",
+ "type": "CREATE",
+ "value": "0x0"
+ }
+ ],
+ "error": "invalid jump destination",
+ "from": "0xe4a13bc304682a903e9472f469c33801dd18d9e8",
+ "gas": "0x435c8",
+ "gasUsed": "0x435c8",
+ "input": "0x3b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8",
+ "to": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json
new file mode 100644
index 000000000..6e221b3c0
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json
@@ -0,0 +1,63 @@
+{
+ "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": {
+ "type": "CALL",
+ "from": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31",
+ "to": "0x6c06b16512b332e6cd8293a2974872674716ce18",
+ "value": "0x0",
+ "gas": "0x1a466",
+ "gasUsed": "0x1dc6",
+ "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000",
+ "output": "0x",
+ "calls": []
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.json b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.json
new file mode 100644
index 000000000..7627c8c23
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.json
@@ -0,0 +1,81 @@
+{
+ "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": {
+ "calls": [
+ {
+ "error": "invalid opcode: opcode 0xfe not defined",
+ "from": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76",
+ "gas": "0x75fe3",
+ "gasUsed": "0x75fe3",
+ "input": "0xa9059cbb000000000000000000000000d4fcab9f0a6dc0493af47c864f6f17a8a5e2e82600000000000000000000000000000000000000000000000000000000000002f4",
+ "to": "0xe819f024b41358d2c08e3a868a5c5dd0566078d4",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "error": "execution reverted",
+ "from": "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826",
+ "gas": "0x78d9e",
+ "gasUsed": "0x76fc0",
+ "input": "0x",
+ "to": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76",
+ "type": "CALL",
+ "value": "0xe92596fd6290000"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/oog.json b/eth/tracers/internal/tracetest/testdata/call_tracer/oog.json
new file mode 100644
index 000000000..de4fed6ab
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/oog.json
@@ -0,0 +1,60 @@
+{
+ "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": {
+ "error": "out of gas",
+ "from": "0x94194bc2aaf494501d7880b61274a169f6502a54",
+ "gas": "0x7045",
+ "gasUsed": "0x7045",
+ "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000",
+ "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/revert.json b/eth/tracers/internal/tracetest/testdata/call_tracer/revert.json
new file mode 100644
index 000000000..059040a1c
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/revert.json
@@ -0,0 +1,58 @@
+{
+ "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": {
+ "error": "execution reverted",
+ "from": "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9",
+ "gas": "0x2d55e8",
+ "gasUsed": "0xc3",
+ "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/revert_reason.json b/eth/tracers/internal/tracetest/testdata/call_tracer/revert_reason.json
new file mode 100644
index 000000000..094b04467
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/revert_reason.json
@@ -0,0 +1,64 @@
+{
+ "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": {
+ "error": "execution reverted",
+ "from": "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1",
+ "gas": "0x2d7308",
+ "gasUsed": "0x588",
+ "input": "0x5c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf1",
+ "to": "0xf58833cf0c791881b494eb79d461e08a1f043f52",
+ "type": "CALL",
+ "value": "0x0",
+ "output": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001e53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e0000"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/selfdestruct.json b/eth/tracers/internal/tracetest/testdata/call_tracer/selfdestruct.json
new file mode 100644
index 000000000..dd717906b
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/selfdestruct.json
@@ -0,0 +1,75 @@
+{
+ "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": "0x61deadff",
+ "nonce": "1",
+ "storage": {}
+ },
+ "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": {
+ "calls": [
+ {
+ "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "gas": "0x0",
+ "gasUsed": "0x0",
+ "input": "0x",
+ "to": "0x000000000000000000000000000000000000dEaD",
+ "type": "SELFDESTRUCT",
+ "value": "0x4d87094125a369d9bd5"
+ }
+ ],
+ "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb",
+ "gas": "0x10738",
+ "gasUsed": "0x7533",
+ "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
+ "output": "0x",
+ "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/simple.json b/eth/tracers/internal/tracetest/testdata/call_tracer/simple.json
new file mode 100644
index 000000000..08cb7b2d0
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/simple.json
@@ -0,0 +1,80 @@
+{
+ "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": {
+ "calls": [
+ {
+ "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "gas": "0x6d05",
+ "gasUsed": "0x0",
+ "input": "0x",
+ "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
+ "type": "CALL",
+ "value": "0x6f05b59d3b20000"
+ }
+ ],
+ "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb",
+ "gas": "0x10738",
+ "gasUsed": "0x3ef9",
+ "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer/throw.json
new file mode 100644
index 000000000..09cf44977
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/throw.json
@@ -0,0 +1,62 @@
+{
+ "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": {
+ "error": "invalid jump destination",
+ "from": "0x70c9217d814985faef62b124420f8dfbddd96433",
+ "gas": "0x37b38",
+ "gasUsed": "0x37b38",
+ "input": "0x51a34eb8000000000000000000000000000000000000000000000027fad02094277c0000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/create.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/create.json
new file mode 100644
index 000000000..8699bf3e7
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/create.json
@@ -0,0 +1,58 @@
+{
+ "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": {
+ "from": "0x13e4acefe6a6700604929946e70e6443e4e73447",
+ "gas": "0x5e106",
+ "gasUsed": "0x5e106",
+ "input": "0x606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a11",
+ "output": "0x606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029",
+ "to": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448",
+ "type": "CREATE",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/deep_calls.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/deep_calls.json
new file mode 100644
index 000000000..0353d4cfa
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/deep_calls.json
@@ -0,0 +1,415 @@
+{
+ "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": {
+ "calls": [
+ {
+ "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "gas": "0x31217",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e7472616374617069000000000000000000000000000000000000000000",
+ "output": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x2a68d",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x23ac9",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e7472616374646200000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x23366",
+ "gasUsed": "0x273",
+ "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x7986bad81f4cbd9317f5a46861437dae58d69113",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x29f35",
+ "gasUsed": "0xf8d",
+ "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x28a9e",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x21d79",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x2165b",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000",
+ "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x1a8e8",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x1a2c6",
+ "gasUsed": "0x3cb",
+ "input": "0xc9503fe2",
+ "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x19b72",
+ "gasUsed": "0x3cb",
+ "input": "0xc9503fe2",
+ "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x19428",
+ "gasUsed": "0x305",
+ "input": "0x6f265b93",
+ "output": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x18d45",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "gas": "0x1734e",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x20ee1",
+ "gasUsed": "0x5374",
+ "input": "0x581d5d60000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1b6c1",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1af69",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "gas": "0x143a5",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1a91d",
+ "gasUsed": "0x12fa",
+ "input": "0x0accce0600000000000000000000000000000000000000000000000000000000000000025842545553440000000000000000000000000000000000000000000000000000000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "output": "0x",
+ "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x19177",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x18a22",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x18341",
+ "gasUsed": "0x334",
+ "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000",
+ "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x17bec",
+ "gasUsed": "0x229",
+ "input": "0x2e94420f",
+ "output": "0x5842545553440000000000000000000000000000000000000000000000000000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x1764e",
+ "gasUsed": "0x45c",
+ "input": "0xf92eb7745842545553440000000000000000000000000000000000000000000000000000",
+ "output": "0x00000000000000000000000000000000000000000000002816d180e30c390000",
+ "to": "0xcf00ffd997ad14939736f026006498e3f099baaf",
+ "type": "CALL",
+ "value": "0x0"
+ },
+ {
+ "calls": [
+ {
+ "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "gas": "0x108ba",
+ "gasUsed": "0x24d",
+ "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "gas": "0x16e62",
+ "gasUsed": "0xebb",
+ "input": "0x645a3b72584254555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002816d180e30c390000",
+ "output": "0x",
+ "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "gas": "0x283b9",
+ "gasUsed": "0xc51c",
+ "input": "0x949ae479000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0x3e9286eafa2db8101246c2131c09b49080d00690",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "gas": "0x30b4a",
+ "gasUsed": "0xedb7",
+ "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0x70c9217d814985faef62b124420f8dfbddd96433",
+ "gas": "0x37b38",
+ "gasUsed": "0x12bb3",
+ "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000",
+ "output": "0x",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/delegatecall.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/delegatecall.json
new file mode 100644
index 000000000..f7ad6df5f
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/delegatecall.json
@@ -0,0 +1,97 @@
+{
+ "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": {
+ "calls": [
+ {
+ "calls": [
+ {
+ "from": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff",
+ "gas": "0x2bf459",
+ "gasUsed": "0x2aa",
+ "input": "0x7d65837a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2",
+ "type": "DELEGATECALL"
+ }
+ ],
+ "from": "0x269296dddce321a6bcbaa2f0181127593d732cba",
+ "gas": "0x2cae73",
+ "gasUsed": "0xa9d",
+ "input": "0x5dbe47e8000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "from": "0xa529806c67cc6486d4d62024471772f47f6fd672",
+ "gas": "0x2d6e28",
+ "gasUsed": "0x64bd",
+ "input": "0x7065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e",
+ "output": "0x",
+ "to": "0x269296dddce321a6bcbaa2f0181127593d732cba",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_create_oog_outer_throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_create_oog_outer_throw.json
new file mode 100644
index 000000000..72152e27e
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_create_oog_outer_throw.json
@@ -0,0 +1,77 @@
+{
+ "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": {
+ "calls": [
+ {
+ "error": "internal failure",
+ "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a",
+ "gas": "0x39ff0",
+ "gasUsed": "0x39ff0",
+ "input": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182",
+ "type": "CREATE",
+ "value": "0x0"
+ }
+ ],
+ "error": "invalid jump destination",
+ "from": "0xe4a13bc304682a903e9472f469c33801dd18d9e8",
+ "gas": "0x435c8",
+ "gasUsed": "0x435c8",
+ "input": "0x3b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8",
+ "to": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_instafail.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_instafail.json
new file mode 100644
index 000000000..86070d130
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/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": {
+ "type": "CALL",
+ "from": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31",
+ "to": "0x6c06b16512b332e6cd8293a2974872674716ce18",
+ "value": "0x0",
+ "gas": "0x1a466",
+ "gasUsed": "0x1dc6",
+ "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000",
+ "output": "0x",
+ "calls": [
+ {
+ "type": "CALL",
+ "from": "0x6c06b16512b332e6cd8293a2974872674716ce18",
+ "to": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31",
+ "value": "0x14d1120d7b160000",
+ "error":"internal failure",
+ "input": "0x"
+ }
+ ]
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_throw_outer_revert.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_throw_outer_revert.json
new file mode 100644
index 000000000..7627c8c23
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_throw_outer_revert.json
@@ -0,0 +1,81 @@
+{
+ "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": {
+ "calls": [
+ {
+ "error": "invalid opcode: opcode 0xfe not defined",
+ "from": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76",
+ "gas": "0x75fe3",
+ "gasUsed": "0x75fe3",
+ "input": "0xa9059cbb000000000000000000000000d4fcab9f0a6dc0493af47c864f6f17a8a5e2e82600000000000000000000000000000000000000000000000000000000000002f4",
+ "to": "0xe819f024b41358d2c08e3a868a5c5dd0566078d4",
+ "type": "CALL",
+ "value": "0x0"
+ }
+ ],
+ "error": "execution reverted",
+ "from": "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826",
+ "gas": "0x78d9e",
+ "gasUsed": "0x76fc0",
+ "input": "0x",
+ "to": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76",
+ "type": "CALL",
+ "value": "0xe92596fd6290000"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/oog.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/oog.json
new file mode 100644
index 000000000..de4fed6ab
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/oog.json
@@ -0,0 +1,60 @@
+{
+ "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": {
+ "error": "out of gas",
+ "from": "0x94194bc2aaf494501d7880b61274a169f6502a54",
+ "gas": "0x7045",
+ "gasUsed": "0x7045",
+ "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000",
+ "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert.json
new file mode 100644
index 000000000..059040a1c
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert.json
@@ -0,0 +1,58 @@
+{
+ "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": {
+ "error": "execution reverted",
+ "from": "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9",
+ "gas": "0x2d55e8",
+ "gasUsed": "0xc3",
+ "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert_reason.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert_reason.json
new file mode 100644
index 000000000..094b04467
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert_reason.json
@@ -0,0 +1,64 @@
+{
+ "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": {
+ "error": "execution reverted",
+ "from": "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1",
+ "gas": "0x2d7308",
+ "gasUsed": "0x588",
+ "input": "0x5c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf1",
+ "to": "0xf58833cf0c791881b494eb79d461e08a1f043f52",
+ "type": "CALL",
+ "value": "0x0",
+ "output": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001e53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e0000"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/selfdestruct.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/selfdestruct.json
new file mode 100644
index 000000000..132cefa16
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/selfdestruct.json
@@ -0,0 +1,73 @@
+{
+ "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": "0x61deadff",
+ "nonce": "1",
+ "storage": {}
+ },
+ "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": {
+ "calls": [
+ {
+ "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "input": "0x",
+ "to": "0x000000000000000000000000000000000000dEaD",
+ "type": "SELFDESTRUCT",
+ "value": "0x4d87094125a369d9bd5"
+ }
+ ],
+ "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb",
+ "gas": "0x10738",
+ "gasUsed": "0x7533",
+ "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
+ "output": "0x",
+ "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/simple.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/simple.json
new file mode 100644
index 000000000..b46432122
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/simple.json
@@ -0,0 +1,78 @@
+{
+ "context": {
+ "difficulty": "3502894804",
+ "gasLimit": "4722976",
+ "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724",
+ "number": "2289806",
+ "timestamp": "1513601314"
+ },
+ "genesis": {
+ "alloc": {
+ "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": {
+ "balance": "0x0",
+ "code": "0x",
+ "nonce": "22",
+ "storage": {}
+ },
+ "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": {
+ "balance": "0x4d87094125a369d9bd5",
+ "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029",
+ "nonce": "1",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb",
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834"
+ }
+ },
+ "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": {
+ "balance": "0x1780d77678137ac1b775",
+ "code": "0x",
+ "nonce": "29072",
+ "storage": {}
+ }
+ },
+ "config": {
+ "byzantiumBlock": 1700000,
+ "chainId": 3,
+ "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": {
+ "calls": [
+ {
+ "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "input": "0x",
+ "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
+ "type": "CALL",
+ "value": "0x6f05b59d3b20000"
+ }
+ ],
+ "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb",
+ "gas": "0x10738",
+ "gasUsed": "0x3ef9",
+ "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/throw.json
new file mode 100644
index 000000000..09cf44977
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/throw.json
@@ -0,0 +1,62 @@
+{
+ "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": {
+ "error": "invalid jump destination",
+ "from": "0x70c9217d814985faef62b124420f8dfbddd96433",
+ "gas": "0x37b38",
+ "gasUsed": "0x37b38",
+ "input": "0x51a34eb8000000000000000000000000000000000000000000000027fad02094277c0000",
+ "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
+ "type": "CALL",
+ "value": "0x0"
+ }
+}
diff --git a/eth/tracers/tracer.go b/eth/tracers/js/bigint.go
similarity index 57%
rename from eth/tracers/tracer.go
rename to eth/tracers/js/bigint.go
index ba6592537..9aeb33042 100644
--- a/eth/tracers/tracer.go
+++ b/eth/tracers/js/bigint.go
@@ -1,4 +1,4 @@
-// Copyright 2017 The go-ethereum Authors
+// 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
@@ -14,639 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package tracers
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "math/big"
- "sync/atomic"
- "time"
- "unsafe"
-
- "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/vm"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/log"
- "gopkg.in/olebedev/go-duktape.v3"
-)
+package js
// bigIntegerJS is the minified version of https://github.com/peterolson/BigInteger.js.
const bigIntegerJS = `var bigInt=function(undefined){"use strict";var BASE=1e7,LOG_BASE=7,MAX_INT=9007199254740992,MAX_INT_ARR=smallToArray(MAX_INT),LOG_MAX_INT=Math.log(MAX_INT);function Integer(v,radix){if(typeof v==="undefined")return Integer[0];if(typeof radix!=="undefined")return+radix===10?parseValue(v):parseBase(v,radix);return parseValue(v)}function BigInteger(value,sign){this.value=value;this.sign=sign;this.isSmall=false}BigInteger.prototype=Object.create(Integer.prototype);function SmallInteger(value){this.value=value;this.sign=value<0;this.isSmall=true}SmallInteger.prototype=Object.create(Integer.prototype);function isPrecise(n){return-MAX_INT0)return Math.floor(n);return Math.ceil(n)}function add(a,b){var l_a=a.length,l_b=b.length,r=new Array(l_a),carry=0,base=BASE,sum,i;for(i=0;i=base?1:0;r[i]=sum-carry*base}while(i0)r.push(carry);return r}function addAny(a,b){if(a.length>=b.length)return add(a,b);return add(b,a)}function addSmall(a,carry){var l=a.length,r=new Array(l),base=BASE,sum,i;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}BigInteger.prototype.add=function(v){var n=parseValue(v);if(this.sign!==n.sign){return this.subtract(n.negate())}var a=this.value,b=n.value;if(n.isSmall){return new BigInteger(addSmall(a,Math.abs(b)),this.sign)}return new BigInteger(addAny(a,b),this.sign)};BigInteger.prototype.plus=BigInteger.prototype.add;SmallInteger.prototype.add=function(v){var n=parseValue(v);var a=this.value;if(a<0!==n.sign){return this.subtract(n.negate())}var b=n.value;if(n.isSmall){if(isPrecise(a+b))return new SmallInteger(a+b);b=smallToArray(Math.abs(b))}return new BigInteger(addSmall(b,Math.abs(a)),a<0)};SmallInteger.prototype.plus=SmallInteger.prototype.add;function subtract(a,b){var a_l=a.length,b_l=b.length,r=new Array(a_l),borrow=0,base=BASE,i,difference;for(i=0;i=0){value=subtract(a,b)}else{value=subtract(b,a);sign=!sign}value=arrayToSmall(value);if(typeof value==="number"){if(sign)value=-value;return new SmallInteger(value)}return new BigInteger(value,sign)}function subtractSmall(a,b,sign){var l=a.length,r=new Array(l),carry=-b,base=BASE,i,difference;for(i=0;i=0)};SmallInteger.prototype.minus=SmallInteger.prototype.subtract;BigInteger.prototype.negate=function(){return new BigInteger(this.value,!this.sign)};SmallInteger.prototype.negate=function(){var sign=this.sign;var small=new SmallInteger(-this.value);small.sign=!sign;return small};BigInteger.prototype.abs=function(){return new BigInteger(this.value,false)};SmallInteger.prototype.abs=function(){return new SmallInteger(Math.abs(this.value))};function multiplyLong(a,b){var a_l=a.length,b_l=b.length,l=a_l+b_l,r=createArray(l),base=BASE,product,carry,i,a_i,b_j;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}function shiftLeft(x,n){var r=[];while(n-- >0)r.push(0);return r.concat(x)}function multiplyKaratsuba(x,y){var n=Math.max(x.length,y.length);if(n<=30)return multiplyLong(x,y);n=Math.ceil(n/2);var b=x.slice(n),a=x.slice(0,n),d=y.slice(n),c=y.slice(0,n);var ac=multiplyKaratsuba(a,c),bd=multiplyKaratsuba(b,d),abcd=multiplyKaratsuba(addAny(a,b),addAny(c,d));var product=addAny(addAny(ac,shiftLeft(subtract(subtract(abcd,ac),bd),n)),shiftLeft(bd,2*n));trim(product);return product}function useKaratsuba(l1,l2){return-.012*l1-.012*l2+15e-6*l1*l2>0}BigInteger.prototype.multiply=function(v){var n=parseValue(v),a=this.value,b=n.value,sign=this.sign!==n.sign,abs;if(n.isSmall){if(b===0)return Integer[0];if(b===1)return this;if(b===-1)return this.negate();abs=Math.abs(b);if(abs=0;shift--){quotientDigit=base-1;if(remainder[shift+b_l]!==divisorMostSignificantDigit){quotientDigit=Math.floor((remainder[shift+b_l]*base+remainder[shift+b_l-1])/divisorMostSignificantDigit)}carry=0;borrow=0;l=divisor.length;for(i=0;ib_l){highx=(highx+1)*base}guess=Math.ceil(highx/highy);do{check=multiplySmall(b,guess);if(compareAbs(check,part)<=0)break;guess--}while(guess);result.push(guess);part=subtract(part,check)}result.reverse();return[arrayToSmall(result),arrayToSmall(part)]}function divModSmall(value,lambda){var length=value.length,quotient=createArray(length),base=BASE,i,q,remainder,divisor;remainder=0;for(i=length-1;i>=0;--i){divisor=remainder*base+value[i];q=truncate(divisor/lambda);remainder=divisor-q*lambda;quotient[i]=q|0}return[quotient,remainder|0]}function divModAny(self,v){var value,n=parseValue(v);var a=self.value,b=n.value;var quotient;if(b===0)throw new Error("Cannot divide by zero");if(self.isSmall){if(n.isSmall){return[new SmallInteger(truncate(a/b)),new SmallInteger(a%b)]}return[Integer[0],self]}if(n.isSmall){if(b===1)return[self,Integer[0]];if(b==-1)return[self.negate(),Integer[0]];var abs=Math.abs(b);if(absb.length?1:-1}for(var i=a.length-1;i>=0;i--){if(a[i]!==b[i])return a[i]>b[i]?1:-1}return 0}BigInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall)return 1;return compareAbs(a,b)};SmallInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=Math.abs(this.value),b=n.value;if(n.isSmall){b=Math.abs(b);return a===b?0:a>b?1:-1}return-1};BigInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(this.sign!==n.sign){return n.sign?1:-1}if(n.isSmall){return this.sign?-1:1}return compareAbs(a,b)*(this.sign?-1:1)};BigInteger.prototype.compareTo=BigInteger.prototype.compare;SmallInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall){return a==b?0:a>b?1:-1}if(a<0!==n.sign){return a<0?-1:1}return a<0?1:-1};SmallInteger.prototype.compareTo=SmallInteger.prototype.compare;BigInteger.prototype.equals=function(v){return this.compare(v)===0};SmallInteger.prototype.eq=SmallInteger.prototype.equals=BigInteger.prototype.eq=BigInteger.prototype.equals;BigInteger.prototype.notEquals=function(v){return this.compare(v)!==0};SmallInteger.prototype.neq=SmallInteger.prototype.notEquals=BigInteger.prototype.neq=BigInteger.prototype.notEquals;BigInteger.prototype.greater=function(v){return this.compare(v)>0};SmallInteger.prototype.gt=SmallInteger.prototype.greater=BigInteger.prototype.gt=BigInteger.prototype.greater;BigInteger.prototype.lesser=function(v){return this.compare(v)<0};SmallInteger.prototype.lt=SmallInteger.prototype.lesser=BigInteger.prototype.lt=BigInteger.prototype.lesser;BigInteger.prototype.greaterOrEquals=function(v){return this.compare(v)>=0};SmallInteger.prototype.geq=SmallInteger.prototype.greaterOrEquals=BigInteger.prototype.geq=BigInteger.prototype.greaterOrEquals;BigInteger.prototype.lesserOrEquals=function(v){return this.compare(v)<=0};SmallInteger.prototype.leq=SmallInteger.prototype.lesserOrEquals=BigInteger.prototype.leq=BigInteger.prototype.lesserOrEquals;BigInteger.prototype.isEven=function(){return(this.value[0]&1)===0};SmallInteger.prototype.isEven=function(){return(this.value&1)===0};BigInteger.prototype.isOdd=function(){return(this.value[0]&1)===1};SmallInteger.prototype.isOdd=function(){return(this.value&1)===1};BigInteger.prototype.isPositive=function(){return!this.sign};SmallInteger.prototype.isPositive=function(){return this.value>0};BigInteger.prototype.isNegative=function(){return this.sign};SmallInteger.prototype.isNegative=function(){return this.value<0};BigInteger.prototype.isUnit=function(){return false};SmallInteger.prototype.isUnit=function(){return Math.abs(this.value)===1};BigInteger.prototype.isZero=function(){return false};SmallInteger.prototype.isZero=function(){return this.value===0};BigInteger.prototype.isDivisibleBy=function(v){var n=parseValue(v);var value=n.value;if(value===0)return false;if(value===1)return true;if(value===2)return this.isEven();return this.mod(n).equals(Integer[0])};SmallInteger.prototype.isDivisibleBy=BigInteger.prototype.isDivisibleBy;function isBasicPrime(v){var n=v.abs();if(n.isUnit())return false;if(n.equals(2)||n.equals(3)||n.equals(5))return true;if(n.isEven()||n.isDivisibleBy(3)||n.isDivisibleBy(5))return false;if(n.lesser(25))return true}BigInteger.prototype.isPrime=function(){var isPrime=isBasicPrime(this);if(isPrime!==undefined)return isPrime;var n=this.abs(),nPrev=n.prev();var a=[2,3,5,7,11,13,17,19],b=nPrev,d,t,i,x;while(b.isEven())b=b.divide(2);for(i=0;i-MAX_INT)return new SmallInteger(value-1);return new BigInteger(MAX_INT_ARR,true)};var powersOfTwo=[1];while(2*powersOfTwo[powersOfTwo.length-1]<=BASE)powersOfTwo.push(2*powersOfTwo[powersOfTwo.length-1]);var powers2Length=powersOfTwo.length,highestPower2=powersOfTwo[powers2Length-1];function shift_isSmall(n){return(typeof n==="number"||typeof n==="string")&&+Math.abs(n)<=BASE||n instanceof BigInteger&&n.value.length<=1}BigInteger.prototype.shiftLeft=function(n){if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftRight(-n);var result=this;while(n>=powers2Length){result=result.multiply(highestPower2);n-=powers2Length-1}return result.multiply(powersOfTwo[n])};SmallInteger.prototype.shiftLeft=BigInteger.prototype.shiftLeft;BigInteger.prototype.shiftRight=function(n){var remQuo;if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftLeft(-n);var result=this;while(n>=powers2Length){if(result.isZero())return result;remQuo=divModAny(result,highestPower2);result=remQuo[1].isNegative()?remQuo[0].prev():remQuo[0];n-=powers2Length-1}remQuo=divModAny(result,powersOfTwo[n]);return remQuo[1].isNegative()?remQuo[0].prev():remQuo[0]};SmallInteger.prototype.shiftRight=BigInteger.prototype.shiftRight;function bitwise(x,y,fn){y=parseValue(y);var xSign=x.isNegative(),ySign=y.isNegative();var xRem=xSign?x.not():x,yRem=ySign?y.not():y;var xDigit=0,yDigit=0;var xDivMod=null,yDivMod=null;var result=[];while(!xRem.isZero()||!yRem.isZero()){xDivMod=divModAny(xRem,highestPower2);xDigit=xDivMod[1].toJSNumber();if(xSign){xDigit=highestPower2-1-xDigit}yDivMod=divModAny(yRem,highestPower2);yDigit=yDivMod[1].toJSNumber();if(ySign){yDigit=highestPower2-1-yDigit}xRem=xDivMod[0];yRem=yDivMod[0];result.push(fn(xDigit,yDigit))}var sum=fn(xSign?1:0,ySign?1:0)!==0?bigInt(-1):bigInt(0);for(var i=result.length-1;i>=0;i-=1){sum=sum.multiply(highestPower2).add(bigInt(result[i]))}return sum}BigInteger.prototype.not=function(){return this.negate().prev()};SmallInteger.prototype.not=BigInteger.prototype.not;BigInteger.prototype.and=function(n){return bitwise(this,n,function(a,b){return a&b})};SmallInteger.prototype.and=BigInteger.prototype.and;BigInteger.prototype.or=function(n){return bitwise(this,n,function(a,b){return a|b})};SmallInteger.prototype.or=BigInteger.prototype.or;BigInteger.prototype.xor=function(n){return bitwise(this,n,function(a,b){return a^b})};SmallInteger.prototype.xor=BigInteger.prototype.xor;var LOBMASK_I=1<<30,LOBMASK_BI=(BASE&-BASE)*(BASE&-BASE)|LOBMASK_I;function roughLOB(n){var v=n.value,x=typeof v==="number"?v|LOBMASK_I:v[0]+v[1]*BASE|LOBMASK_BI;return x&-x}function max(a,b){a=parseValue(a);b=parseValue(b);return a.greater(b)?a:b}function min(a,b){a=parseValue(a);b=parseValue(b);return a.lesser(b)?a:b}function gcd(a,b){a=parseValue(a).abs();b=parseValue(b).abs();if(a.equals(b))return a;if(a.isZero())return b;if(b.isZero())return a;var c=Integer[1],d,t;while(a.isEven()&&b.isEven()){d=Math.min(roughLOB(a),roughLOB(b));a=a.divide(d);b=b.divide(d);c=c.multiply(d)}while(a.isEven()){a=a.divide(roughLOB(a))}do{while(b.isEven()){b=b.divide(roughLOB(b))}if(a.greater(b)){t=b;b=a;a=t}b=b.subtract(a)}while(!b.isZero());return c.isUnit()?a:a.multiply(c)}function lcm(a,b){a=parseValue(a).abs();b=parseValue(b).abs();return a.divide(gcd(a,b)).multiply(b)}function randBetween(a,b){a=parseValue(a);b=parseValue(b);var low=min(a,b),high=max(a,b);var range=high.subtract(low).add(1);if(range.isSmall)return low.add(Math.floor(Math.random()*range));var length=range.value.length-1;var result=[],restricted=true;for(var i=length;i>=0;i--){var top=restricted?range.value[i]:BASE;var digit=truncate(Math.random()*top);result.unshift(digit);if(digit=absBase){if(c==="1"&&absBase===1)continue;throw new Error(c+" is not a valid digit in base "+base+".")}else if(c.charCodeAt(0)-87>=absBase){throw new Error(c+" is not a valid digit in base "+base+".")}}}if(2<=base&&base<=36){if(length<=LOG_MAX_INT/Math.log(base)){var result=parseInt(text,base);if(isNaN(result)){throw new Error(c+" is not a valid digit in base "+base+".")}return new SmallInteger(parseInt(text,base))}}base=parseValue(base);var digits=[];var isNegative=text[0]==="-";for(i=isNegative?1:0;i");digits.push(parseValue(text.slice(start+1,i)))}else throw new Error(c+" is not a valid character")}return parseBaseFromArray(digits,base,isNegative)};function parseBaseFromArray(digits,base,isNegative){var val=Integer[0],pow=Integer[1],i;for(i=digits.length-1;i>=0;i--){val=val.add(digits[i].times(pow));pow=pow.times(base)}return isNegative?val.negate():val}function stringify(digit){var v=digit.value;if(typeof v==="number")v=[v];if(v.length===1&&v[0]<=35){return"0123456789abcdefghijklmnopqrstuvwxyz".charAt(v[0])}return"<"+v+">"}function toBase(n,base){base=bigInt(base);if(base.isZero()){if(n.isZero())return"0";throw new Error("Cannot convert nonzero numbers to base 0.")}if(base.equals(-1)){if(n.isZero())return"0";if(n.isNegative())return new Array(1-n).join("10");return"1"+new Array(+n).join("01")}var minusSign="";if(n.isNegative()&&base.isPositive()){minusSign="-";n=n.abs()}if(base.equals(1)){if(n.isZero())return"0";return minusSign+new Array(+n+1).join(1)}var out=[];var left=n,divmod;while(left.isNegative()||left.compareAbs(base)>=0){divmod=left.divmod(base);left=divmod.quotient;var digit=divmod.remainder;if(digit.isNegative()){digit=base.minus(digit).abs();left=left.next()}out.push(stringify(digit))}out.push(stringify(left));return minusSign+out.reverse().join("")}BigInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!==10)return toBase(this,radix);var v=this.value,l=v.length,str=String(v[--l]),zeros="0000000",digit;while(--l>=0){digit=String(v[l]);str+=zeros.slice(digit.length)+digit}var sign=this.sign?"-":"";return sign+str};SmallInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!=10)return toBase(this,radix);return String(this.value)};BigInteger.prototype.toJSON=SmallInteger.prototype.toJSON=function(){return this.toString()};BigInteger.prototype.valueOf=function(){return+this.toString()};BigInteger.prototype.toJSNumber=BigInteger.prototype.valueOf;SmallInteger.prototype.valueOf=function(){return this.value};SmallInteger.prototype.toJSNumber=SmallInteger.prototype.valueOf;function parseStringValue(v){if(isPrecise(+v)){var x=+v;if(x===truncate(x))return new SmallInteger(x);throw"Invalid integer: "+v}var sign=v[0]==="-";if(sign)v=v.slice(1);var split=v.split(/e/i);if(split.length>2)throw new Error("Invalid integer: "+split.join("e"));if(split.length===2){var exp=split[1];if(exp[0]==="+")exp=exp.slice(1);exp=+exp;if(exp!==truncate(exp)||!isPrecise(exp))throw new Error("Invalid integer: "+exp+" is not a valid exponent.");var text=split[0];var decimalPlace=text.indexOf(".");if(decimalPlace>=0){exp-=text.length-decimalPlace-1;text=text.slice(0,decimalPlace)+text.slice(decimalPlace+1)}if(exp<0)throw new Error("Cannot include negative exponent part for integers");text+=new Array(exp+1).join("0");v=text}var isValid=/^([0-9][0-9]*)$/.test(v);if(!isValid)throw new Error("Invalid integer: "+v);var r=[],max=v.length,l=LOG_BASE,min=max-l;while(max>0){r.push(+v.slice(min,max));min-=l;if(min<0)min=0;max-=l}trim(r);return new BigInteger(r,sign)}function parseNumberValue(v){if(isPrecise(v)){if(v!==truncate(v))throw new Error(v+" is not an integer.");return new SmallInteger(v)}return parseStringValue(v.toString())}function parseValue(v){if(typeof v==="number"){return parseNumberValue(v)}if(typeof v==="string"){return parseStringValue(v)}return v}for(var i=0;i<1e3;i++){Integer[i]=new SmallInteger(i);if(i>0)Integer[-i]=new SmallInteger(-i)}Integer.one=Integer[1];Integer.zero=Integer[0];Integer.minusOne=Integer[-1];Integer.max=max;Integer.min=min;Integer.gcd=gcd;Integer.lcm=lcm;Integer.isInstance=function(x){return x instanceof BigInteger||x instanceof SmallInteger};Integer.randBetween=randBetween;Integer.fromArray=function(digits,base,isNegative){return parseBaseFromArray(digits.map(parseValue),parseValue(base||10),isNegative)};return Integer}();if(typeof module!=="undefined"&&module.hasOwnProperty("exports")){module.exports=bigInt}if(typeof define==="function"&&define.amd){define("big-integer",[],function(){return bigInt})}; bigInt`
-
-// makeSlice convert an unsafe memory pointer with the given type into a Go byte
-// slice.
-//
-// Note, the returned slice uses the same memory area as the input arguments.
-// If those are duktape stack items, popping them off **will** make the slice
-// contents change.
-func makeSlice(ptr unsafe.Pointer, size uint) []byte {
- var sl = struct {
- addr uintptr
- len int
- cap int
- }{uintptr(ptr), int(size), int(size)}
-
- return *(*[]byte)(unsafe.Pointer(&sl))
-}
-
-// popSlice pops a buffer off the JavaScript stack and returns it as a slice.
-func popSlice(ctx *duktape.Context) []byte {
- blob := common.CopyBytes(makeSlice(ctx.GetBuffer(-1)))
- ctx.Pop()
- return blob
-}
-
-// pushBigInt create a JavaScript BigInteger in the VM.
-func pushBigInt(n *big.Int, ctx *duktape.Context) {
- ctx.GetGlobalString("bigInt")
- ctx.PushString(n.String())
- ctx.Call(1)
-}
-
-// opWrapper provides a JavaScript wrapper around OpCode.
-type opWrapper struct {
- op vm.OpCode
-}
-
-// pushObject assembles a JSVM object wrapping a swappable opcode and pushes it
-// onto the VM stack.
-func (ow *opWrapper) pushObject(vm *duktape.Context) {
- obj := vm.PushObject()
-
- vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(int(ow.op)); return 1 })
- vm.PutPropString(obj, "toNumber")
-
- vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushString(ow.op.String()); return 1 })
- vm.PutPropString(obj, "toString")
-
- vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushBoolean(ow.op.IsPush()); return 1 })
- vm.PutPropString(obj, "isPush")
-}
-
-// memoryWrapper provides a JavaScript wrapper around vm.Memory.
-type memoryWrapper struct {
- memory *vm.Memory
-}
-
-// slice returns the requested range of memory as a byte slice.
-func (mw *memoryWrapper) slice(begin, end int64) []byte {
- if end == begin {
- return []byte{}
- }
- if end < begin || begin < 0 {
- // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
- // runtime goes belly up https://github.com/golang/go/issues/15639.
- log.Warn("Tracer accessed out of bound memory", "offset", begin, "end", end)
- return nil
- }
- if mw.memory.Len() < int(end) {
- // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
- // runtime goes belly up https://github.com/golang/go/issues/15639.
- log.Warn("Tracer accessed out of bound memory", "available", mw.memory.Len(), "offset", begin, "size", end-begin)
- return nil
- }
- return mw.memory.GetCopy(begin, end-begin)
-}
-
-// getUint returns the 32 bytes at the specified address interpreted as a uint.
-func (mw *memoryWrapper) getUint(addr int64) *big.Int {
- if mw.memory.Len() < int(addr)+32 || addr < 0 {
- // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
- // runtime goes belly up https://github.com/golang/go/issues/15639.
- log.Warn("Tracer accessed out of bound memory", "available", mw.memory.Len(), "offset", addr, "size", 32)
- return new(big.Int)
- }
- return new(big.Int).SetBytes(mw.memory.GetPtr(addr, 32))
-}
-
-// pushObject assembles a JSVM object wrapping a swappable memory and pushes it
-// onto the VM stack.
-func (mw *memoryWrapper) pushObject(vm *duktape.Context) {
- obj := vm.PushObject()
-
- // Generate the `slice` method which takes two ints and returns a buffer
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- blob := mw.slice(int64(ctx.GetInt(-2)), int64(ctx.GetInt(-1)))
- ctx.Pop2()
-
- ptr := ctx.PushFixedBuffer(len(blob))
- copy(makeSlice(ptr, uint(len(blob))), blob)
- return 1
- })
- vm.PutPropString(obj, "slice")
-
- // Generate the `getUint` method which takes an int and returns a bigint
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- offset := int64(ctx.GetInt(-1))
- ctx.Pop()
-
- pushBigInt(mw.getUint(offset), ctx)
- return 1
- })
- vm.PutPropString(obj, "getUint")
-}
-
-// stackWrapper provides a JavaScript wrapper around vm.Stack.
-type stackWrapper struct {
- stack *vm.Stack
-}
-
-// peek returns the nth-from-the-top element of the stack.
-func (sw *stackWrapper) peek(idx int) *big.Int {
- if len(sw.stack.Data()) <= idx || idx < 0 {
- // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
- // runtime goes belly up https://github.com/golang/go/issues/15639.
- log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data()), "index", idx)
- return new(big.Int)
- }
- return sw.stack.Back(idx).ToBig()
-}
-
-// pushObject assembles a JSVM object wrapping a swappable stack and pushes it
-// onto the VM stack.
-func (sw *stackWrapper) pushObject(vm *duktape.Context) {
- obj := vm.PushObject()
-
- vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(len(sw.stack.Data())); return 1 })
- vm.PutPropString(obj, "length")
-
- // Generate the `peek` method which takes an int and returns a bigint
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- offset := ctx.GetInt(-1)
- ctx.Pop()
-
- pushBigInt(sw.peek(offset), ctx)
- return 1
- })
- vm.PutPropString(obj, "peek")
-}
-
-// dbWrapper provides a JavaScript wrapper around vm.Database.
-type dbWrapper struct {
- db vm.StateDB
-}
-
-// pushObject assembles a JSVM object wrapping a swappable database and pushes it
-// onto the VM stack.
-func (dw *dbWrapper) pushObject(vm *duktape.Context) {
- obj := vm.PushObject()
-
- // Push the wrapper for statedb.GetBalance
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- pushBigInt(dw.db.GetBalance(common.BytesToAddress(popSlice(ctx))), ctx)
- return 1
- })
- vm.PutPropString(obj, "getBalance")
-
- // Push the wrapper for statedb.GetNonce
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- ctx.PushInt(int(dw.db.GetNonce(common.BytesToAddress(popSlice(ctx)))))
- return 1
- })
- vm.PutPropString(obj, "getNonce")
-
- // Push the wrapper for statedb.GetCode
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- code := dw.db.GetCode(common.BytesToAddress(popSlice(ctx)))
-
- ptr := ctx.PushFixedBuffer(len(code))
- copy(makeSlice(ptr, uint(len(code))), code)
- return 1
- })
- vm.PutPropString(obj, "getCode")
-
- // Push the wrapper for statedb.GetState
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- hash := popSlice(ctx)
- addr := popSlice(ctx)
-
- state := dw.db.GetState(common.BytesToAddress(addr), common.BytesToHash(hash))
-
- ptr := ctx.PushFixedBuffer(len(state))
- copy(makeSlice(ptr, uint(len(state))), state[:])
- return 1
- })
- vm.PutPropString(obj, "getState")
-
- // Push the wrapper for statedb.Exists
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- ctx.PushBoolean(dw.db.Exist(common.BytesToAddress(popSlice(ctx))))
- return 1
- })
- vm.PutPropString(obj, "exists")
-}
-
-// contractWrapper provides a JavaScript wrapper around vm.Contract
-type contractWrapper struct {
- contract *vm.Contract
-}
-
-// pushObject assembles a JSVM object wrapping a swappable contract and pushes it
-// onto the VM stack.
-func (cw *contractWrapper) pushObject(vm *duktape.Context) {
- obj := vm.PushObject()
-
- // Push the wrapper for contract.Caller
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- ptr := ctx.PushFixedBuffer(20)
- copy(makeSlice(ptr, 20), cw.contract.Caller().Bytes())
- return 1
- })
- vm.PutPropString(obj, "getCaller")
-
- // Push the wrapper for contract.Address
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- ptr := ctx.PushFixedBuffer(20)
- copy(makeSlice(ptr, 20), cw.contract.Address().Bytes())
- return 1
- })
- vm.PutPropString(obj, "getAddress")
-
- // Push the wrapper for contract.Value
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- pushBigInt(cw.contract.Value(), ctx)
- return 1
- })
- vm.PutPropString(obj, "getValue")
-
- // Push the wrapper for contract.Input
- vm.PushGoFunction(func(ctx *duktape.Context) int {
- blob := cw.contract.Input
-
- ptr := ctx.PushFixedBuffer(len(blob))
- copy(makeSlice(ptr, uint(len(blob))), blob)
- return 1
- })
- vm.PutPropString(obj, "getInput")
-}
-
-// Tracer provides an implementation of Tracer that evaluates a Javascript
-// function for each VM execution step.
-type Tracer struct {
- vm *duktape.Context // Javascript VM instance
-
- tracerObject int // Stack index of the tracer JavaScript object
- stateObject int // Stack index of the global state to pull arguments from
-
- opWrapper *opWrapper // Wrapper around the VM opcode
- stackWrapper *stackWrapper // Wrapper around the VM stack
- memoryWrapper *memoryWrapper // Wrapper around the VM memory
- contractWrapper *contractWrapper // Wrapper around the contract object
- dbWrapper *dbWrapper // Wrapper around the VM environment
-
- pcValue *uint // Swappable pc value wrapped by a log accessor
- gasValue *uint // Swappable gas value wrapped by a log accessor
- costValue *uint // Swappable cost value wrapped by a log accessor
- depthValue *uint // Swappable depth value wrapped by a log accessor
- errorValue *string // Swappable error value wrapped by a log accessor
- refundValue *uint // Swappable refund value wrapped by a log accessor
-
- ctx map[string]interface{} // Transaction context gathered throughout execution
- err error // Error, if one has occurred
-
- interrupt uint32 // Atomic flag to signal execution interruption
- reason error // Textual reason for the interruption
-}
-
-// New instantiates a new tracer instance. code specifies a Javascript snippet,
-// which must evaluate to an expression returning an object with 'step', 'fault'
-// and 'result' functions.
-func New(code string, txCtx vm.TxContext) (*Tracer, error) {
- // Resolve any tracers by name and assemble the tracer object
- if tracer, ok := tracer(code); ok {
- code = tracer
- }
- tracer := &Tracer{
- vm: duktape.New(),
- ctx: make(map[string]interface{}),
- opWrapper: new(opWrapper),
- stackWrapper: new(stackWrapper),
- memoryWrapper: new(memoryWrapper),
- contractWrapper: new(contractWrapper),
- dbWrapper: new(dbWrapper),
- pcValue: new(uint),
- gasValue: new(uint),
- costValue: new(uint),
- depthValue: new(uint),
- refundValue: new(uint),
- }
- tracer.ctx["gasPrice"] = txCtx.GasPrice
-
- // Set up builtins for this environment
- tracer.vm.PushGlobalGoFunction("toHex", func(ctx *duktape.Context) int {
- ctx.PushString(hexutil.Encode(popSlice(ctx)))
- return 1
- })
- tracer.vm.PushGlobalGoFunction("toWord", func(ctx *duktape.Context) int {
- var word common.Hash
- if ptr, size := ctx.GetBuffer(-1); ptr != nil {
- word = common.BytesToHash(makeSlice(ptr, size))
- } else {
- word = common.HexToHash(ctx.GetString(-1))
- }
- ctx.Pop()
- copy(makeSlice(ctx.PushFixedBuffer(32), 32), word[:])
- return 1
- })
- tracer.vm.PushGlobalGoFunction("toAddress", func(ctx *duktape.Context) int {
- var addr common.Address
- if ptr, size := ctx.GetBuffer(-1); ptr != nil {
- addr = common.BytesToAddress(makeSlice(ptr, size))
- } else {
- addr = common.HexToAddress(ctx.GetString(-1))
- }
- ctx.Pop()
- copy(makeSlice(ctx.PushFixedBuffer(20), 20), addr[:])
- return 1
- })
- tracer.vm.PushGlobalGoFunction("toContract", func(ctx *duktape.Context) int {
- var from common.Address
- if ptr, size := ctx.GetBuffer(-2); ptr != nil {
- from = common.BytesToAddress(makeSlice(ptr, size))
- } else {
- from = common.HexToAddress(ctx.GetString(-2))
- }
- nonce := uint64(ctx.GetInt(-1))
- ctx.Pop2()
-
- contract := crypto.CreateAddress(from, nonce)
- copy(makeSlice(ctx.PushFixedBuffer(20), 20), contract[:])
- return 1
- })
- tracer.vm.PushGlobalGoFunction("toContract2", func(ctx *duktape.Context) int {
- var from common.Address
- if ptr, size := ctx.GetBuffer(-3); ptr != nil {
- from = common.BytesToAddress(makeSlice(ptr, size))
- } else {
- from = common.HexToAddress(ctx.GetString(-3))
- }
- // Retrieve salt hex string from js stack
- salt := common.HexToHash(ctx.GetString(-2))
- // Retrieve code slice from js stack
- var code []byte
- if ptr, size := ctx.GetBuffer(-1); ptr != nil {
- code = common.CopyBytes(makeSlice(ptr, size))
- } else {
- code = common.FromHex(ctx.GetString(-1))
- }
- codeHash := crypto.Keccak256(code)
- ctx.Pop3()
- contract := crypto.CreateAddress2(from, salt, codeHash)
- copy(makeSlice(ctx.PushFixedBuffer(20), 20), contract[:])
- return 1
- })
- tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int {
- _, ok := vm.PrecompiledContractsIstanbul[common.BytesToAddress(popSlice(ctx))]
- ctx.PushBoolean(ok)
- return 1
- })
- tracer.vm.PushGlobalGoFunction("slice", func(ctx *duktape.Context) int {
- start, end := ctx.GetInt(-2), ctx.GetInt(-1)
- ctx.Pop2()
-
- blob := popSlice(ctx)
- size := end - start
-
- if start < 0 || start > end || end > len(blob) {
- // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
- // runtime goes belly up https://github.com/golang/go/issues/15639.
- log.Warn("Tracer accessed out of bound memory", "available", len(blob), "offset", start, "size", size)
- ctx.PushFixedBuffer(0)
- return 1
- }
- copy(makeSlice(ctx.PushFixedBuffer(size), uint(size)), blob[start:end])
- return 1
- })
- // Push the JavaScript tracer as object #0 onto the JSVM stack and validate it
- if err := tracer.vm.PevalString("(" + code + ")"); err != nil {
- log.Warn("Failed to compile tracer", "err", err)
- return nil, err
- }
- tracer.tracerObject = 0 // yeah, nice, eval can't return the index itself
-
- if !tracer.vm.GetPropString(tracer.tracerObject, "step") {
- return nil, fmt.Errorf("trace object must expose a function step()")
- }
- tracer.vm.Pop()
-
- if !tracer.vm.GetPropString(tracer.tracerObject, "fault") {
- return nil, fmt.Errorf("trace object must expose a function fault()")
- }
- tracer.vm.Pop()
-
- if !tracer.vm.GetPropString(tracer.tracerObject, "result") {
- return nil, fmt.Errorf("trace object must expose a function result()")
- }
- tracer.vm.Pop()
-
- // Tracer is valid, inject the big int library to access large numbers
- tracer.vm.EvalString(bigIntegerJS)
- tracer.vm.PutGlobalString("bigInt")
-
- // Push the global environment state as object #1 into the JSVM stack
- tracer.stateObject = tracer.vm.PushObject()
-
- logObject := tracer.vm.PushObject()
-
- tracer.opWrapper.pushObject(tracer.vm)
- tracer.vm.PutPropString(logObject, "op")
-
- tracer.stackWrapper.pushObject(tracer.vm)
- tracer.vm.PutPropString(logObject, "stack")
-
- tracer.memoryWrapper.pushObject(tracer.vm)
- tracer.vm.PutPropString(logObject, "memory")
-
- tracer.contractWrapper.pushObject(tracer.vm)
- tracer.vm.PutPropString(logObject, "contract")
-
- tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.pcValue); return 1 })
- tracer.vm.PutPropString(logObject, "getPC")
-
- tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.gasValue); return 1 })
- tracer.vm.PutPropString(logObject, "getGas")
-
- tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.costValue); return 1 })
- tracer.vm.PutPropString(logObject, "getCost")
-
- tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.depthValue); return 1 })
- tracer.vm.PutPropString(logObject, "getDepth")
-
- tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.refundValue); return 1 })
- tracer.vm.PutPropString(logObject, "getRefund")
-
- tracer.vm.PushGoFunction(func(ctx *duktape.Context) int {
- if tracer.errorValue != nil {
- ctx.PushString(*tracer.errorValue)
- } else {
- ctx.PushUndefined()
- }
- return 1
- })
- tracer.vm.PutPropString(logObject, "getError")
-
- tracer.vm.PutPropString(tracer.stateObject, "log")
-
- tracer.dbWrapper.pushObject(tracer.vm)
- tracer.vm.PutPropString(tracer.stateObject, "db")
-
- return tracer, nil
-}
-
-// Stop terminates execution of the tracer at the first opportune moment.
-func (jst *Tracer) Stop(err error) {
- jst.reason = err
- atomic.StoreUint32(&jst.interrupt, 1)
-}
-
-// call executes a method on a JS object, catching any errors, formatting and
-// returning them as error objects.
-func (jst *Tracer) call(method string, args ...string) (json.RawMessage, error) {
- // Execute the JavaScript call and return any error
- jst.vm.PushString(method)
- for _, arg := range args {
- jst.vm.GetPropString(jst.stateObject, arg)
- }
- code := jst.vm.PcallProp(jst.tracerObject, len(args))
- defer jst.vm.Pop()
-
- if code != 0 {
- err := jst.vm.SafeToString(-1)
- return nil, errors.New(err)
- }
- // No error occurred, extract return value and return
- return json.RawMessage(jst.vm.JsonEncode(-1)), nil
-}
-
-func wrapError(context string, err error) error {
- return fmt.Errorf("%v in server-side tracer function '%v'", err, context)
-}
-
-// CaptureStart implements the Tracer interface to initialize the tracing operation.
-func (jst *Tracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
- jst.ctx["type"] = "CALL"
- if create {
- jst.ctx["type"] = "CREATE"
- }
- jst.ctx["from"] = from
- jst.ctx["to"] = to
- jst.ctx["input"] = input
- jst.ctx["gas"] = gas
- jst.ctx["value"] = value
-
- // Initialize the context
- jst.ctx["block"] = env.Context.BlockNumber.Uint64()
- jst.dbWrapper.db = env.StateDB
- // Compute intrinsic gas
- isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber)
- isIstanbul := env.ChainConfig().IsIstanbul(env.Context.BlockNumber)
- intrinsicGas, err := core.IntrinsicGas(input, nil, jst.ctx["type"] == "CREATE", isHomestead, isIstanbul)
- if err != nil {
- return
- }
- jst.ctx["intrinsicGas"] = intrinsicGas
-}
-
-// CaptureState implements the Tracer interface to trace a single step of VM execution.
-func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
- if jst.err != nil {
- return
- }
- // If tracing was interrupted, set the error and stop
- if atomic.LoadUint32(&jst.interrupt) > 0 {
- jst.err = jst.reason
- return
- }
- jst.opWrapper.op = op
- jst.stackWrapper.stack = scope.Stack
- jst.memoryWrapper.memory = scope.Memory
- jst.contractWrapper.contract = scope.Contract
-
- *jst.pcValue = uint(pc)
- *jst.gasValue = uint(gas)
- *jst.costValue = uint(cost)
- *jst.depthValue = uint(depth)
- *jst.refundValue = uint(env.StateDB.GetRefund())
-
- jst.errorValue = nil
- if err != nil {
- jst.errorValue = new(string)
- *jst.errorValue = err.Error()
- }
-
- if _, err := jst.call("step", "log", "db"); err != nil {
- jst.err = wrapError("step", err)
- }
-}
-
-// CaptureFault implements the Tracer interface to trace an execution fault
-func (jst *Tracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
- if jst.err != nil {
- return
- }
- // Apart from the error, everything matches the previous invocation
- jst.errorValue = new(string)
- *jst.errorValue = err.Error()
-
- if _, err := jst.call("fault", "log", "db"); err != nil {
- jst.err = wrapError("fault", err)
- }
-}
-
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (jst *Tracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
- jst.ctx["output"] = output
- jst.ctx["time"] = t.String()
- jst.ctx["gasUsed"] = gasUsed
-
- if err != nil {
- jst.ctx["error"] = err.Error()
- }
-}
-
-// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error
-func (jst *Tracer) GetResult() (json.RawMessage, error) {
- // Transform the context into a JavaScript object and inject into the state
- obj := jst.vm.PushObject()
-
- for key, val := range jst.ctx {
- switch val := val.(type) {
- case uint64:
- jst.vm.PushUint(uint(val))
-
- case string:
- jst.vm.PushString(val)
-
- case []byte:
- ptr := jst.vm.PushFixedBuffer(len(val))
- copy(makeSlice(ptr, uint(len(val))), val)
-
- case common.Address:
- ptr := jst.vm.PushFixedBuffer(20)
- copy(makeSlice(ptr, 20), val[:])
-
- case *big.Int:
- pushBigInt(val, jst.vm)
-
- default:
- panic(fmt.Sprintf("unsupported type: %T", val))
- }
- jst.vm.PutPropString(obj, key)
- }
- jst.vm.PutPropString(jst.stateObject, "ctx")
-
- // Finalize the trace and return the results
- result, err := jst.call("result", "ctx", "db")
- if err != nil {
- jst.err = wrapError("result", err)
- }
- // Clean up the JavaScript environment
- jst.vm.DestroyHeap()
- jst.vm.Destroy()
-
- return result, jst.err
-}
diff --git a/eth/tracers/js/internal/tracers/4byte_tracer.js b/eth/tracers/js/internal/tracers/4byte_tracer.js
new file mode 100644
index 000000000..9ec3209f8
--- /dev/null
+++ b/eth/tracers/js/internal/tracers/4byte_tracer.js
@@ -0,0 +1,65 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// 4byteTracer searches for 4byte-identifiers, and collects them for post-processing.
+// It collects the methods identifiers along with the size of the supplied data, so
+// a reversed signature can be matched against the size of the data.
+//
+// Example:
+// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"})
+// {
+// 0x27dc297e-128: 1,
+// 0x38cc4831-0: 2,
+// 0x524f3889-96: 1,
+// 0xadf59f99-288: 1,
+// 0xc281d19e-0: 1
+// }
+{
+ // ids aggregates the 4byte ids found.
+ ids : {},
+
+ // store save the given indentifier and datasize.
+ store: function(id, size){
+ var key = "" + toHex(id) + "-" + size;
+ this.ids[key] = this.ids[key] + 1 || 1;
+ },
+
+ enter: function(frame) {
+ // Skip any pre-compile invocations, those are just fancy opcodes
+ if (isPrecompiled(frame.getTo())) {
+ return;
+ }
+ var input = frame.getInput()
+ if (input.length >= 4) {
+ this.store(slice(input, 0, 4), input.length - 4);
+ }
+ },
+
+ exit: function(frameResult) {},
+
+ // fault is invoked when the actual execution of an opcode fails.
+ fault: function(log, db) {},
+
+ // result is invoked when all the opcodes have been iterated over and returns
+ // the final result of the tracing.
+ result: function(ctx) {
+ // Save the outer calldata also
+ if (ctx.input.length >= 4) {
+ this.store(slice(ctx.input, 0, 4), ctx.input.length-4)
+ }
+ return this.ids;
+ },
+}
diff --git a/eth/tracers/internal/tracers/4byte_tracer.js b/eth/tracers/js/internal/tracers/4byte_tracer_legacy.js
similarity index 100%
rename from eth/tracers/internal/tracers/4byte_tracer.js
rename to eth/tracers/js/internal/tracers/4byte_tracer_legacy.js
diff --git a/eth/tracers/internal/tracers/assets.go b/eth/tracers/js/internal/tracers/assets.go
similarity index 57%
rename from eth/tracers/internal/tracers/assets.go
rename to eth/tracers/js/internal/tracers/assets.go
index 7f45ab286..37e370240 100644
--- a/eth/tracers/internal/tracers/assets.go
+++ b/eth/tracers/js/internal/tracers/assets.go
@@ -1,8 +1,10 @@
// Code generated by go-bindata. DO NOT EDIT.
// sources:
-// 4byte_tracer.js (2.933kB)
+// 4byte_tracer.js (2.224kB)
+// 4byte_tracer_legacy.js (2.933kB)
// bigram_tracer.js (1.712kB)
-// call_tracer.js (8.956kB)
+// call_tracer_js.js (3.497kB)
+// call_tracer_legacy.js (8.956kB)
// evmdis_tracer.js (4.195kB)
// noop_tracer.js (1.271kB)
// opcount_tracer.js (1.372kB)
@@ -77,7 +79,7 @@ func (fi bindataFileInfo) Sys() interface{} {
return nil
}
-var __4byte_tracerJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x56\x5b\x6f\xdb\x4a\x0e\x7e\xb6\x7f\x05\xd7\x2f\xb5\x51\x59\x8e\x2f\x89\x2f\xd9\x16\xf0\xe6\xa4\x6d\x80\x9c\x24\x88\xdd\x3d\x28\x16\xfb\x30\x9e\xa1\xac\xd9\xc8\x33\xc2\x0c\xe5\x4b\x73\xf2\xdf\x17\x1c\x49\x89\x93\xd3\x62\xbb\x4f\x96\x47\xc3\x8f\x1f\xc9\x8f\xa4\x7a\x3d\xb8\xb0\xf9\xc1\xe9\x75\x4a\x30\x38\xe9\x8f\x61\x99\x22\xac\x6d\x17\x29\x45\x87\xc5\x06\xe6\x05\xa5\xd6\xf9\x66\xaf\x07\xcb\x54\x7b\x48\x74\x86\xa0\x3d\xe4\xc2\x11\xd8\x04\xe8\xcd\xfd\x4c\xaf\x9c\x70\x87\xb8\xd9\xeb\x95\x36\x3f\x7c\xcd\x08\x89\x43\x04\x6f\x13\xda\x09\x87\x33\x38\xd8\x02\xa4\x30\xe0\x50\x69\x4f\x4e\xaf\x0a\x42\xd0\x04\xc2\xa8\x9e\x75\xb0\xb1\x4a\x27\x07\x86\xd4\x04\x85\x51\xe8\x82\x6b\x42\xb7\xf1\x35\x8f\xcf\x37\x5f\xe1\x1a\xbd\x47\x07\x9f\xd1\xa0\x13\x19\xdc\x15\xab\x4c\x4b\xb8\xd6\x12\x8d\x47\x10\x1e\x72\x3e\xf1\x29\x2a\x58\x05\x38\x36\xfc\xc4\x54\x16\x15\x15\xf8\x64\x0b\xa3\x04\x69\x6b\x22\x40\xcd\xcc\x61\x8b\xce\x6b\x6b\x60\x58\xbb\xaa\x00\x23\xb0\x8e\x41\xda\x82\x38\x00\x07\x36\x67\xbb\x0e\x08\x73\x80\x4c\xd0\x8b\xe9\x2f\x24\xe4\x25\x6e\x05\xda\x04\x37\xa9\xcd\x11\x28\x15\xc4\x51\xef\x74\x96\xc1\x0a\xa1\xf0\x98\x14\x59\xc4\x68\xab\x82\xe0\x8f\xab\xe5\x97\xdb\xaf\x4b\x98\xdf\x7c\x83\x3f\xe6\xf7\xf7\xf3\x9b\xe5\xb7\x73\xd8\x69\x4a\x6d\x41\x80\x5b\x2c\xa1\xf4\x26\xcf\x34\x2a\xd8\x09\xe7\x84\xa1\x03\xd8\x84\x11\x7e\xbf\xbc\xbf\xf8\x32\xbf\x59\xce\xff\x71\x75\x7d\xb5\xfc\x06\xd6\xc1\xa7\xab\xe5\xcd\xe5\x62\x01\x9f\x6e\xef\x61\x0e\x77\xf3\xfb\xe5\xd5\xc5\xd7\xeb\xf9\x3d\xdc\x7d\xbd\xbf\xbb\x5d\x5c\xc6\xb0\x40\x66\x85\x6c\xff\xbf\x73\x9e\x84\xea\x39\x04\x85\x24\x74\xe6\xeb\x4c\x7c\xb3\x05\xf8\xd4\x16\x99\x82\x54\x6c\x11\x1c\x4a\xd4\x5b\x54\x20\x40\xda\xfc\xf0\xcb\x45\x65\x2c\x91\x59\xb3\x0e\x31\xff\x54\x90\x70\x95\x80\xb1\x14\x81\x47\x84\xbf\xa7\x44\xf9\xac\xd7\xdb\xed\x76\xf1\xda\x14\xb1\x75\xeb\x5e\x56\xc2\xf9\xde\xc7\xb8\xc9\x98\xa3\xd5\x81\x70\xe9\x84\x44\x07\x1e\x85\x93\x29\xfa\x10\x4c\x78\xd1\xd5\x0a\x0d\xe9\x44\xa3\xf3\x11\x8b\x14\xa4\xcd\x32\x94\xe4\x99\xc1\x26\x5c\xcc\xad\xa7\x6e\xee\xac\x44\xef\xb5\x59\x73\xe0\x70\x45\xaf\x2e\xc2\x06\x29\xb5\xca\xc3\x11\xdc\xdb\x68\xbc\xfe\x8e\x75\x36\x7c\x91\x97\x65\x54\x82\x44\x04\xde\x86\xe8\xc1\x21\xcb\x0c\x15\x78\xbd\x36\x82\x0a\x87\xa1\x97\x56\x08\x1b\x41\x92\xc5\x2e\xd6\x42\x1b\x4f\x7f\x01\x64\x9c\xba\x22\x97\x7b\xb1\xc9\x33\x9c\xf1\x33\xc0\x47\x50\xb8\x2a\xd6\x31\x71\x0a\x96\x4e\x18\x2f\x24\x8b\xbb\x0d\xad\x93\xfd\xa0\x3f\xc2\xd3\xe9\x18\x87\xa7\x4a\x9c\x4c\x86\x67\xd3\x41\x72\x3a\x9c\x9c\xf5\x47\x7d\x3c\x9b\x26\xa3\x31\x4e\xc7\xc3\xd5\x40\x9e\x9e\xe1\x58\x4c\x4e\xc6\xc3\x55\x1f\xc5\xc9\x24\x51\xe3\xd3\x71\x1f\xa7\x0a\x5b\x11\x3c\x06\x60\x37\x83\xd6\x51\xa6\x5b\x4f\x9d\xd2\xfb\x63\xf9\x03\x70\xb2\x1f\x8c\x95\x1c\x4c\xc7\xd8\xed\x0f\x26\x33\xe8\x47\x2f\x6f\x86\x13\x29\x47\x93\x61\xbf\x7b\x32\x83\xc1\xd1\xf9\xe9\x60\x94\x0c\x27\x93\x69\x77\x7a\xf6\xda\x40\xa8\xe4\x74\x9a\x4c\xa7\xdd\xc1\xe4\x0d\x94\x1c\x4c\xfa\xaa\x3f\x45\x86\xea\x97\xc7\x4f\xcd\xc7\x66\x83\x07\x8e\xf2\x20\xd6\x6b\x87\x6b\x41\x58\x56\x2d\x30\x0e\x2f\x12\x1e\x16\x71\xb3\xc1\xcf\x33\x78\x7c\x8a\x9a\xc1\x46\x8a\x2c\x5b\x1e\x72\x56\x35\x15\xce\x78\x78\x97\x88\xcc\xe3\xbb\xa0\x0b\x63\x4d\x97\x2f\x78\x1e\x1f\x01\x2f\x47\x7c\xe8\x6a\xa3\x70\x1f\x2e\xf0\x51\xa2\x9d\x27\x1e\xb3\x62\x13\x10\x45\xc2\xd3\xe4\xdd\x56\x64\x05\xbe\x8b\x40\xc7\x18\xc3\x06\x37\x5c\x54\xe1\x28\x6e\x36\x6a\x97\x33\x48\x0a\x53\x56\xca\xe6\x9e\x5c\xe7\xb1\xd9\x68\xf8\x9d\x26\x99\x1e\x1d\x48\xe1\x11\x5a\x17\xf3\xeb\xeb\xd6\x0c\x5e\xfe\x5c\xdc\xfe\x76\xd9\x9a\x35\x1b\x0d\x76\xb9\x16\x2c\x6d\xa5\x5c\x04\x5b\x91\x45\xa5\xbb\xea\xc7\x7f\x0f\x0f\xb6\xa0\xfa\xd7\x7f\x67\xb3\x32\x5e\x18\x9e\x43\xaf\x07\x9e\x84\x7c\x80\x9c\x1c\x90\x2d\xcd\x9a\xcf\xae\x7f\xbb\xbc\xbe\xfc\x3c\x5f\x5e\xbe\xa2\xb0\x58\xce\x97\x57\x17\xe5\xd1\x5f\x49\xfc\x1f\xfe\x07\x3f\xf3\xdf\x68\x3c\x35\x9f\x6f\x85\x9a\x9c\x37\x1b\x75\xd5\x3c\xf1\x9c\xf2\x3c\x8d\xc2\x18\xd1\x3c\x3c\xb9\x2c\x55\x6b\x86\x3e\xe7\x8e\xe1\x0e\x8a\x9b\x8d\x70\xff\x28\xdf\x5a\x45\xa1\xb9\x42\x86\xb7\xc2\xc1\x03\x1e\xe0\x03\xb4\x5a\xf0\x1e\xc8\x7e\xc1\x7d\x5b\xab\x0e\xbc\x87\x56\x97\x4f\xf8\xe6\x79\xb3\xd1\xa0\x54\xfb\x58\x2b\xff\xaf\x07\x3c\xfc\x1b\x3e\xc0\xeb\xff\xef\xa1\x0f\x7f\xfe\x09\xfd\x57\x34\x31\xe7\x85\xa1\xcd\xd6\x3e\xa0\x0a\x92\xe1\x01\x70\x00\x9b\x4b\xab\xaa\x8d\xc1\x11\xfc\xf3\x77\xc0\x3d\xca\x82\xd0\x07\xba\x98\x1f\xb1\xcd\xec\x3a\x02\xb5\xea\x00\xb3\xed\xf5\x60\xf1\xa0\xf3\xb0\xb8\x4a\x14\x5f\xc2\xf0\x46\x34\x96\x40\x1b\x42\x67\x44\x16\xa4\xed\xab\xf8\x24\xd5\x7c\x6b\xf5\x31\x6a\x6c\xf3\x98\xec\x82\x9c\x36\xeb\x76\xa7\xc3\x31\xea\x04\xda\x7f\x93\x54\xfa\xaa\xd2\x7f\x5e\x15\xe3\xd8\x75\xee\xb0\x2b\xed\x26\x0f\x5f\x19\x66\x6b\x65\xd8\xc3\x3e\x02\x4a\x2d\xef\x6f\x87\xf0\x9f\xc2\x13\x24\xc2\xc8\x67\xa2\x15\xbe\xf6\x77\x0e\x2b\x63\xd5\x26\x3b\x57\xca\xa1\xf7\x81\x51\x50\x42\xcc\x6d\xd6\xee\x77\x5e\xc8\xf5\xcf\x3a\x9d\xce\xcf\x48\x7d\x16\x61\xf7\xbf\x0a\xbc\x5e\x62\x55\xfc\xda\x2c\xbe\xc3\x07\x78\xe3\x41\x12\x57\xad\x13\x87\x5e\xbd\x4d\xda\xcf\x19\x08\xd7\x3f\x7e\x80\x51\xe5\xb2\x84\xb8\x4d\x92\x1f\x61\xbc\xb1\x2f\x65\x12\x14\x17\x22\x62\xd1\xbb\x43\xec\x79\x6d\xb5\x03\x48\x54\x61\xbd\x87\x51\x27\x0a\xd4\xba\xa3\x4e\x15\x4f\x2d\x9d\x44\x14\x19\x1d\x6b\x67\x97\x56\xdf\x07\x42\x52\x21\xb2\x4a\x2e\xfc\xad\x63\x13\x10\xa6\x56\x54\x52\x6e\xee\x46\xb0\xff\xa1\x86\xa0\x76\xe1\xd0\xff\xc8\x07\x27\x8f\xfd\xd4\xe2\x0a\x3b\x7f\x85\xdc\x60\x84\x4e\xf0\x47\x8f\xdd\x56\x2d\x56\x0d\xcd\x00\x57\xce\x42\xce\x7f\x05\x5c\x2d\x2e\xde\x1e\x61\xa9\x36\xca\xf3\x23\x52\x92\xf6\x2f\xa2\xae\x9b\xd9\x16\x3c\x3f\xb9\x86\xdc\xc0\x20\x32\x6f\xab\xaa\x48\xda\xc7\xda\xe4\x05\xc5\x19\x9a\x35\xa5\xc7\x15\x3a\x4a\x7a\x99\xe9\xe7\xcb\x11\x9c\x44\x21\xd1\x6f\xcd\xbb\xa3\xce\xeb\x29\x53\xf7\x73\xd9\xc1\x4f\xcd\xff\x06\x00\x00\xff\xff\x8e\xc8\x27\x72\x75\x0b\x00\x00")
+var __4byte_tracerJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x55\x5b\x6f\x22\x39\x13\x7d\x86\x5f\x71\xc4\x13\x68\x9a\x4b\x73\x09\x97\xf9\x32\x12\xdf\x28\x99\x41\xca\x66\x22\x42\x34\x8a\x56\xfb\x60\xda\xd5\xdd\xde\x18\xbb\x65\xbb\xb9\x6c\x26\xff\x7d\x65\x37\xe4\x36\xbb\xda\x79\x02\xec\xaa\x73\xaa\x4e\x1d\x17\xdd\x2e\x3e\xeb\xe2\x60\x44\x96\x3b\xf4\x7b\xf1\x18\xab\x9c\x90\xe9\x36\xb9\x9c\x0c\x95\x1b\xcc\x4b\x97\x6b\x63\xeb\xdd\x2e\x56\xb9\xb0\x48\x85\x24\x08\x8b\x82\x19\x07\x9d\xc2\xbd\x8b\x97\x62\x6d\x98\x39\x74\xea\xdd\x6e\x95\xf3\x8f\xd7\x1e\x21\x35\x44\xb0\x3a\x75\x3b\x66\x68\x86\x83\x2e\x91\x30\x05\x43\x5c\x58\x67\xc4\xba\x74\x04\xe1\xc0\x14\xef\x6a\x83\x8d\xe6\x22\x3d\x78\x48\xe1\x50\x2a\x4e\x26\x50\x3b\x32\x1b\x7b\xaa\xe3\xcb\xf5\x1d\xae\xc8\x5a\x32\xf8\x42\x8a\x0c\x93\xb8\x29\xd7\x52\x24\xb8\x12\x09\x29\x4b\x60\x16\x85\x3f\xb1\x39\x71\xac\x03\x9c\x4f\xbc\xf4\xa5\xdc\x1e\x4b\xc1\xa5\x2e\x15\x67\x4e\x68\x15\x81\x84\xaf\x1c\x5b\x32\x56\x68\x85\xc1\x89\xea\x08\x18\x41\x1b\x0f\xd2\x64\xce\x37\x60\xa0\x0b\x9f\xd7\x02\x53\x07\x48\xe6\x5e\x52\x7f\x41\x90\x97\xbe\x39\x84\x0a\x34\xb9\x2e\x08\x2e\x67\xce\x77\xbd\x13\x52\x62\x4d\x28\x2d\xa5\xa5\x8c\x3c\xda\xba\x74\xf8\xbe\x58\x7d\xfd\x76\xb7\xc2\xfc\xfa\x1e\xdf\xe7\xcb\xe5\xfc\x7a\x75\xff\x11\x3b\xe1\x72\x5d\x3a\xd0\x96\x2a\x28\xb1\x29\xa4\x20\x8e\x1d\x33\x86\x29\x77\x80\x4e\x3d\xc2\x6f\x17\xcb\xcf\x5f\xe7\xd7\xab\xf9\xff\x17\x57\x8b\xd5\x3d\xb4\xc1\xe5\x62\x75\x7d\x71\x7b\x8b\xcb\x6f\x4b\xcc\x71\x33\x5f\xae\x16\x9f\xef\xae\xe6\x4b\xdc\xdc\x2d\x6f\xbe\xdd\x5e\x74\x70\x4b\xbe\x2a\xf2\xf9\xff\xad\x79\x1a\xa6\x67\x08\x9c\x1c\x13\xd2\x9e\x94\xb8\xd7\x25\x6c\xae\x4b\xc9\x91\xb3\x2d\xc1\x50\x42\x62\x4b\x1c\x0c\x89\x2e\x0e\xbf\x3c\x54\x8f\xc5\xa4\x56\x59\xe8\xf9\x5f\x0d\x89\x45\x0a\xa5\x5d\x04\x4b\x84\xff\xe5\xce\x15\xb3\x6e\x77\xb7\xdb\x75\x32\x55\x76\xb4\xc9\xba\xb2\x82\xb3\xdd\x4f\x9d\xba\xc7\x1c\xae\x0f\x8e\x56\x86\x25\x64\x60\x89\x99\x24\x27\x1b\x9a\x09\x17\x6d\xc1\x49\x39\x91\x0a\x32\x36\xf2\x26\x45\xa2\xa5\xa4\xc4\x59\x5f\xc1\x26\x04\x16\xda\xba\x76\x61\x74\x42\xd6\x0a\x95\xf9\xc6\xb1\x70\x6f\x02\xb1\x21\x97\x6b\x6e\xf1\x0a\xee\x7d\x37\x56\xfc\x45\x27\x35\x6c\x59\x54\x63\xe4\xcc\xb1\x08\x56\x87\xee\x61\xc8\xdb\x8c\x38\xac\xc8\x14\x73\xa5\xa1\xf0\x96\xd6\x84\x0d\x73\x89\x37\x3b\xcb\x98\x50\xd6\xfd\x04\xe8\x71\x4e\x13\xb9\xd8\xb3\x4d\x21\x69\xe6\xbf\x03\x9f\xc0\x69\x5d\x66\x1d\xe7\x25\x58\x19\xa6\x2c\x4b\xbc\xb9\x9b\x68\xf4\xf6\xfd\x78\x48\xa3\xe9\x98\x06\x23\xce\x7a\x93\xc1\xd9\xb4\x9f\x8e\x06\x93\xb3\x78\x18\xd3\xd9\x34\x1d\x8e\x69\x3a\x1e\xac\xfb\xc9\xe8\x8c\xc6\x6c\xd2\x1b\x0f\xd6\x31\xb1\xde\x24\xe5\xe3\xd1\x38\xa6\x29\xa7\x46\x84\xc7\x00\x6c\x66\x68\xbc\x52\xba\xf1\xd4\xaa\xd8\x1f\xab\x0f\xa0\xb7\xef\x8f\x79\xd2\x9f\x8e\xa9\x1d\xf7\x27\x33\xc4\xd1\xcb\xcd\x60\x92\x24\xc3\xc9\x20\x6e\xf7\x66\xe8\xbf\x3a\x1f\xf5\x87\xe9\x60\x32\x99\xb6\xa7\x67\x6f\x13\x18\x4f\x47\xd3\x74\x3a\x6d\xf7\x27\xef\xa0\x92\xfe\x24\xe6\xf1\x94\x3c\x54\x5c\x1d\x3f\xd5\x1f\xeb\x35\xbf\x70\xb8\x05\xcb\x32\x43\x19\x73\x54\x4d\x2d\x54\x1c\x2e\x52\xbf\x2c\x3a\xf5\x9a\xff\x3e\xc3\xe3\x53\x54\x0f\x39\xd6\x79\xc7\x5b\xef\xeb\x60\x48\xe1\x9f\xa1\x50\xcf\x43\x0e\x8e\xf1\xda\xfb\x59\x74\xea\xb5\x10\x3f\x43\x5a\xaa\x4a\x63\xc1\xa3\x30\xa6\xd6\x63\xbd\x56\xdb\x32\x83\x07\x3a\xe0\x1c\x8d\x06\x3e\xc0\xe9\xaf\xb4\x6f\x0a\xde\xc2\x07\x34\xda\xfe\xc4\x47\x7e\xac\xd7\x6a\x2e\x17\xb6\x23\xb8\xfd\xfd\x81\x0e\x7f\xe0\x1c\x6f\x7f\x7f\x40\x8c\x1f\x3f\x10\x7f\xac\xd7\x42\x99\xa4\x9c\x97\xff\x99\x33\x35\x6c\x43\x2d\x78\xc6\x6e\x17\xb7\x0f\xa2\x08\x6b\xac\x30\xd4\x4e\xf4\xa6\x08\x8b\x5f\x6d\x75\x12\x56\xa3\x8d\xe0\x72\xed\x57\xaa\x21\xfc\x59\x5a\x87\x94\xa9\xe4\x00\x5d\x24\x9a\x93\xad\xd7\x6a\x22\x45\x53\xd8\x1b\x43\xc7\x64\x5e\x11\x74\x32\x72\x2b\xdd\x6c\xb5\x2a\xa6\x9a\x21\x57\x1a\xe5\xab\x7f\x3a\xb6\x2a\x54\x51\x3a\x9c\xe3\x39\x7c\xe1\x0f\x9a\xad\x13\xa6\xff\xd5\x91\xa4\x32\x97\xe3\xd3\x39\x86\x47\xa0\xd0\x6c\xd0\xb1\x69\xfd\x5b\xae\x02\x23\xf4\x22\x0c\x5b\x11\xde\xa4\xb5\x31\x6c\x1d\x29\x2b\x29\xf6\xc2\xbd\x57\x62\x49\xb6\x94\xae\xf5\x32\xd3\x94\x95\xd2\xf9\x45\xed\x55\x78\xf0\xab\x34\x3f\xee\x56\x96\xb8\x92\x49\xd0\x9e\x92\xd2\x03\xf8\xc7\xc5\xd4\x51\x0b\xa4\xd5\xd6\xab\x85\xfc\x57\x2c\x52\x67\x11\xf8\xfa\x15\x83\x09\x94\x3f\x51\x30\x29\x03\xcd\x51\xdb\x6a\x5d\xae\xc9\x3b\xca\x91\x61\xfe\xff\x42\x6f\x8f\x9e\xaa\xe4\xb4\x01\xce\xe7\xa4\x42\x31\x79\x02\x3e\xbe\x79\xff\xf0\xc2\x3e\xaa\x55\xe7\xaf\x6a\x4a\xdc\xfe\xc5\x01\x27\xf7\xea\xd2\xff\x91\x25\x4c\x4a\xef\x58\x30\x69\xf5\x71\x16\x89\xdb\x77\x7e\x79\x1e\xcf\xc1\xcf\x33\x79\x9f\xde\x1e\xb6\x8e\x3e\xa8\xda\x78\x36\x70\x65\xd9\xa7\xfa\xdf\x01\x00\x00\xff\xff\xf6\xa8\xa1\xb9\xb0\x08\x00\x00")
func _4byte_tracerJsBytes() ([]byte, error) {
return bindataRead(
@@ -93,6 +95,26 @@ func _4byte_tracerJs() (*asset, error) {
}
info := bindataFileInfo{name: "4byte_tracer.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+ a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6b, 0xa8, 0x46, 0xa2, 0x3a, 0x2b, 0xaa, 0xb9, 0xb9, 0xba, 0xe2, 0x22, 0x10, 0xe, 0xe7, 0x4c, 0x24, 0xfc, 0x4c, 0x85, 0xeb, 0x96, 0x48, 0xe8, 0x7f, 0xc8, 0xe0, 0xd0, 0xd, 0x26, 0xa1, 0xb2}}
+ return a, nil
+}
+
+var __4byte_tracer_legacyJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x56\x5b\x6f\xdb\x4a\x0e\x7e\xb6\x7f\x05\xd7\x2f\xb5\x51\x59\x8e\x2f\x89\x2f\xd9\x16\xf0\xe6\xa4\x6d\x80\x9c\x24\x88\xdd\x3d\x28\x16\xfb\x30\x9e\xa1\xac\xd9\xc8\x33\xc2\x0c\xe5\x4b\x73\xf2\xdf\x17\x1c\x49\x89\x93\xd3\x62\xbb\x4f\x96\x47\xc3\x8f\x1f\xc9\x8f\xa4\x7a\x3d\xb8\xb0\xf9\xc1\xe9\x75\x4a\x30\x38\xe9\x8f\x61\x99\x22\xac\x6d\x17\x29\x45\x87\xc5\x06\xe6\x05\xa5\xd6\xf9\x66\xaf\x07\xcb\x54\x7b\x48\x74\x86\xa0\x3d\xe4\xc2\x11\xd8\x04\xe8\xcd\xfd\x4c\xaf\x9c\x70\x87\xb8\xd9\xeb\x95\x36\x3f\x7c\xcd\x08\x89\x43\x04\x6f\x13\xda\x09\x87\x33\x38\xd8\x02\xa4\x30\xe0\x50\x69\x4f\x4e\xaf\x0a\x42\xd0\x04\xc2\xa8\x9e\x75\xb0\xb1\x4a\x27\x07\x86\xd4\x04\x85\x51\xe8\x82\x6b\x42\xb7\xf1\x35\x8f\xcf\x37\x5f\xe1\x1a\xbd\x47\x07\x9f\xd1\xa0\x13\x19\xdc\x15\xab\x4c\x4b\xb8\xd6\x12\x8d\x47\x10\x1e\x72\x3e\xf1\x29\x2a\x58\x05\x38\x36\xfc\xc4\x54\x16\x15\x15\xf8\x64\x0b\xa3\x04\x69\x6b\x22\x40\xcd\xcc\x61\x8b\xce\x6b\x6b\x60\x58\xbb\xaa\x00\x23\xb0\x8e\x41\xda\x82\x38\x00\x07\x36\x67\xbb\x0e\x08\x73\x80\x4c\xd0\x8b\xe9\x2f\x24\xe4\x25\x6e\x05\xda\x04\x37\xa9\xcd\x11\x28\x15\xc4\x51\xef\x74\x96\xc1\x0a\xa1\xf0\x98\x14\x59\xc4\x68\xab\x82\xe0\x8f\xab\xe5\x97\xdb\xaf\x4b\x98\xdf\x7c\x83\x3f\xe6\xf7\xf7\xf3\x9b\xe5\xb7\x73\xd8\x69\x4a\x6d\x41\x80\x5b\x2c\xa1\xf4\x26\xcf\x34\x2a\xd8\x09\xe7\x84\xa1\x03\xd8\x84\x11\x7e\xbf\xbc\xbf\xf8\x32\xbf\x59\xce\xff\x71\x75\x7d\xb5\xfc\x06\xd6\xc1\xa7\xab\xe5\xcd\xe5\x62\x01\x9f\x6e\xef\x61\x0e\x77\xf3\xfb\xe5\xd5\xc5\xd7\xeb\xf9\x3d\xdc\x7d\xbd\xbf\xbb\x5d\x5c\xc6\xb0\x40\x66\x85\x6c\xff\xbf\x73\x9e\x84\xea\x39\x04\x85\x24\x74\xe6\xeb\x4c\x7c\xb3\x05\xf8\xd4\x16\x99\x82\x54\x6c\x11\x1c\x4a\xd4\x5b\x54\x20\x40\xda\xfc\xf0\xcb\x45\x65\x2c\x91\x59\xb3\x0e\x31\xff\x54\x90\x70\x95\x80\xb1\x14\x81\x47\x84\xbf\xa7\x44\xf9\xac\xd7\xdb\xed\x76\xf1\xda\x14\xb1\x75\xeb\x5e\x56\xc2\xf9\xde\xc7\xb8\xc9\x98\xa3\xd5\x81\x70\xe9\x84\x44\x07\x1e\x85\x93\x29\xfa\x10\x4c\x78\xd1\xd5\x0a\x0d\xe9\x44\xa3\xf3\x11\x8b\x14\xa4\xcd\x32\x94\xe4\x99\xc1\x26\x5c\xcc\xad\xa7\x6e\xee\xac\x44\xef\xb5\x59\x73\xe0\x70\x45\xaf\x2e\xc2\x06\x29\xb5\xca\xc3\x11\xdc\xdb\x68\xbc\xfe\x8e\x75\x36\x7c\x91\x97\x65\x54\x82\x44\x04\xde\x86\xe8\xc1\x21\xcb\x0c\x15\x78\xbd\x36\x82\x0a\x87\xa1\x97\x56\x08\x1b\x41\x92\xc5\x2e\xd6\x42\x1b\x4f\x7f\x01\x64\x9c\xba\x22\x97\x7b\xb1\xc9\x33\x9c\xf1\x33\xc0\x47\x50\xb8\x2a\xd6\x31\x71\x0a\x96\x4e\x18\x2f\x24\x8b\xbb\x0d\xad\x93\xfd\xa0\x3f\xc2\xd3\xe9\x18\x87\xa7\x4a\x9c\x4c\x86\x67\xd3\x41\x72\x3a\x9c\x9c\xf5\x47\x7d\x3c\x9b\x26\xa3\x31\x4e\xc7\xc3\xd5\x40\x9e\x9e\xe1\x58\x4c\x4e\xc6\xc3\x55\x1f\xc5\xc9\x24\x51\xe3\xd3\x71\x1f\xa7\x0a\x5b\x11\x3c\x06\x60\x37\x83\xd6\x51\xa6\x5b\x4f\x9d\xd2\xfb\x63\xf9\x03\x70\xb2\x1f\x8c\x95\x1c\x4c\xc7\xd8\xed\x0f\x26\x33\xe8\x47\x2f\x6f\x86\x13\x29\x47\x93\x61\xbf\x7b\x32\x83\xc1\xd1\xf9\xe9\x60\x94\x0c\x27\x93\x69\x77\x7a\xf6\xda\x40\xa8\xe4\x74\x9a\x4c\xa7\xdd\xc1\xe4\x0d\x94\x1c\x4c\xfa\xaa\x3f\x45\x86\xea\x97\xc7\x4f\xcd\xc7\x66\x83\x07\x8e\xf2\x20\xd6\x6b\x87\x6b\x41\x58\x56\x2d\x30\x0e\x2f\x12\x1e\x16\x71\xb3\xc1\xcf\x33\x78\x7c\x8a\x9a\xc1\x46\x8a\x2c\x5b\x1e\x72\x56\x35\x15\xce\x78\x78\x97\x88\xcc\xe3\xbb\xa0\x0b\x63\x4d\x97\x2f\x78\x1e\x1f\x01\x2f\x47\x7c\xe8\x6a\xa3\x70\x1f\x2e\xf0\x51\xa2\x9d\x27\x1e\xb3\x62\x13\x10\x45\xc2\xd3\xe4\xdd\x56\x64\x05\xbe\x8b\x40\xc7\x18\xc3\x06\x37\x5c\x54\xe1\x28\x6e\x36\x6a\x97\x33\x48\x0a\x53\x56\xca\xe6\x9e\x5c\xe7\xb1\xd9\x68\xf8\x9d\x26\x99\x1e\x1d\x48\xe1\x11\x5a\x17\xf3\xeb\xeb\xd6\x0c\x5e\xfe\x5c\xdc\xfe\x76\xd9\x9a\x35\x1b\x0d\x76\xb9\x16\x2c\x6d\xa5\x5c\x04\x5b\x91\x45\xa5\xbb\xea\xc7\x7f\x0f\x0f\xb6\xa0\xfa\xd7\x7f\x67\xb3\x32\x5e\x18\x9e\x43\xaf\x07\x9e\x84\x7c\x80\x9c\x1c\x90\x2d\xcd\x9a\xcf\xae\x7f\xbb\xbc\xbe\xfc\x3c\x5f\x5e\xbe\xa2\xb0\x58\xce\x97\x57\x17\xe5\xd1\x5f\x49\xfc\x1f\xfe\x07\x3f\xf3\xdf\x68\x3c\x35\x9f\x6f\x85\x9a\x9c\x37\x1b\x75\xd5\x3c\xf1\x9c\xf2\x3c\x8d\xc2\x18\xd1\x3c\x3c\xb9\x2c\x55\x6b\x86\x3e\xe7\x8e\xe1\x0e\x8a\x9b\x8d\x70\xff\x28\xdf\x5a\x45\xa1\xb9\x42\x86\xb7\xc2\xc1\x03\x1e\xe0\x03\xb4\x5a\xf0\x1e\xc8\x7e\xc1\x7d\x5b\xab\x0e\xbc\x87\x56\x97\x4f\xf8\xe6\x79\xb3\xd1\xa0\x54\xfb\x58\x2b\xff\xaf\x07\x3c\xfc\x1b\x3e\xc0\xeb\xff\xef\xa1\x0f\x7f\xfe\x09\xfd\x57\x34\x31\xe7\x85\xa1\xcd\xd6\x3e\xa0\x0a\x92\xe1\x01\x70\x00\x9b\x4b\xab\xaa\x8d\xc1\x11\xfc\xf3\x77\xc0\x3d\xca\x82\xd0\x07\xba\x98\x1f\xb1\xcd\xec\x3a\x02\xb5\xea\x00\xb3\xed\xf5\x60\xf1\xa0\xf3\xb0\xb8\x4a\x14\x5f\xc2\xf0\x46\x34\x96\x40\x1b\x42\x67\x44\x16\xa4\xed\xab\xf8\x24\xd5\x7c\x6b\xf5\x31\x6a\x6c\xf3\x98\xec\x82\x9c\x36\xeb\x76\xa7\xc3\x31\xea\x04\xda\x7f\x93\x54\xfa\xaa\xd2\x7f\x5e\x15\xe3\xd8\x75\xee\xb0\x2b\xed\x26\x0f\x5f\x19\x66\x6b\x65\xd8\xc3\x3e\x02\x4a\x2d\xef\x6f\x87\xf0\x9f\xc2\x13\x24\xc2\xc8\x67\xa2\x15\xbe\xf6\x77\x0e\x2b\x63\xd5\x26\x3b\x57\xca\xa1\xf7\x81\x51\x50\x42\xcc\x6d\xd6\xee\x77\x5e\xc8\xf5\xcf\x3a\x9d\xce\xcf\x48\x7d\x16\x61\xf7\xbf\x0a\xbc\x5e\x62\x55\xfc\xda\x2c\xbe\xc3\x07\x78\xe3\x41\x12\x57\xad\x13\x87\x5e\xbd\x4d\xda\xcf\x19\x08\xd7\x3f\x7e\x80\x51\xe5\xb2\x84\xb8\x4d\x92\x1f\x61\xbc\xb1\x2f\x65\x12\x14\x17\x22\x62\xd1\xbb\x43\xec\x79\x6d\xb5\x03\x48\x54\x61\xbd\x87\x51\x27\x0a\xd4\xba\xa3\x4e\x15\x4f\x2d\x9d\x44\x14\x19\x1d\x6b\x67\x97\x56\xdf\x07\x42\x52\x21\xb2\x4a\x2e\xfc\xad\x63\x13\x10\xa6\x56\x54\x52\x6e\xee\x46\xb0\xff\xa1\x86\xa0\x76\xe1\xd0\xff\xc8\x07\x27\x8f\xfd\xd4\xe2\x0a\x3b\x7f\x85\xdc\x60\x84\x4e\xf0\x47\x8f\xdd\x56\x2d\x56\x0d\xcd\x00\x57\xce\x42\xce\x7f\x05\x5c\x2d\x2e\xde\x1e\x61\xa9\x36\xca\xf3\x23\x52\x92\xf6\x2f\xa2\xae\x9b\xd9\x16\x3c\x3f\xb9\x86\xdc\xc0\x20\x32\x6f\xab\xaa\x48\xda\xc7\xda\xe4\x05\xc5\x19\x9a\x35\xa5\xc7\x15\x3a\x4a\x7a\x99\xe9\xe7\xcb\x11\x9c\x44\x21\xd1\x6f\xcd\xbb\xa3\xce\xeb\x29\x53\xf7\x73\xd9\xc1\x4f\xcd\xff\x06\x00\x00\xff\xff\x8e\xc8\x27\x72\x75\x0b\x00\x00")
+
+func _4byte_tracer_legacyJsBytes() ([]byte, error) {
+ return bindataRead(
+ __4byte_tracer_legacyJs,
+ "4byte_tracer_legacy.js",
+ )
+}
+
+func _4byte_tracer_legacyJs() (*asset, error) {
+ bytes, err := _4byte_tracer_legacyJsBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "4byte_tracer_legacy.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0xc5, 0x48, 0x2d, 0xd9, 0x43, 0x95, 0x93, 0x3b, 0x93, 0x2c, 0x47, 0x8c, 0x84, 0x32, 0x3c, 0x8b, 0x2e, 0xf3, 0x72, 0xc4, 0x57, 0xe6, 0x3a, 0xb3, 0xdf, 0x1d, 0xbf, 0x45, 0x3, 0xfc, 0xa}}
return a, nil
}
@@ -117,22 +139,42 @@ func bigram_tracerJs() (*asset, error) {
return a, nil
}
-var _call_tracerJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x5a\xdf\x6f\x1b\x37\xf2\x7f\x96\xfe\x8a\x89\x1f\x6a\x09\x51\x24\x39\xe9\xb7\x5f\xc0\xae\x7a\x50\x1d\x25\x35\xe0\xc6\x81\xad\x34\x08\x82\x3c\x50\xbb\xb3\x12\x6b\x8a\xdc\x92\x5c\xc9\xba\xd6\xff\xfb\x61\x86\xdc\xd5\xae\x24\x3b\xbe\x5e\x71\xe8\xbd\x69\x97\x33\xc3\xe1\xcc\x67\x7e\x71\x35\x18\xc0\xb9\xc9\x37\x56\xce\x17\x1e\x5e\x0e\x4f\xfe\x1f\xa6\x0b\x84\xb9\x79\x81\x7e\x81\x16\x8b\x25\x8c\x0b\xbf\x30\xd6\xb5\x07\x03\x98\x2e\xa4\x83\x4c\x2a\x04\xe9\x20\x17\xd6\x83\xc9\xc0\xef\xd0\x2b\x39\xb3\xc2\x6e\xfa\xed\xc1\x20\xf0\x1c\x5c\x26\x09\x99\x45\x04\x67\x32\xbf\x16\x16\x4f\x61\x63\x0a\x48\x84\x06\x8b\xa9\x74\xde\xca\x59\xe1\x11\xa4\x07\xa1\xd3\x81\xb1\xb0\x34\xa9\xcc\x36\x24\x52\x7a\x28\x74\x8a\x96\xb7\xf6\x68\x97\xae\xd4\xe3\xed\xbb\x0f\x70\x89\xce\xa1\x85\xb7\xa8\xd1\x0a\x05\xef\x8b\x99\x92\x09\x5c\xca\x04\xb5\x43\x10\x0e\x72\x7a\xe3\x16\x98\xc2\x8c\xc5\x11\xe3\x1b\x52\xe5\x26\xaa\x02\x6f\x4c\xa1\x53\xe1\xa5\xd1\x3d\x40\x49\x9a\xc3\x0a\xad\x93\x46\xc3\xab\x72\xab\x28\xb0\x07\xc6\x92\x90\x8e\xf0\x74\x00\x0b\x26\x27\xbe\x2e\x08\xbd\x01\x25\xfc\x96\xf5\x09\x06\xd9\x9e\x3b\x05\xa9\x79\x9b\x85\xc9\x11\xfc\x42\x78\x3a\xf5\x5a\x2a\x05\x33\x84\xc2\x61\x56\xa8\x1e\x49\x9b\x15\x1e\x3e\x5e\x4c\x7f\xba\xfa\x30\x85\xf1\xbb\x4f\xf0\x71\x7c\x7d\x3d\x7e\x37\xfd\x74\x06\x6b\xe9\x17\xa6\xf0\x80\x2b\x0c\xa2\xe4\x32\x57\x12\x53\x58\x0b\x6b\x85\xf6\x1b\x30\x19\x49\xf8\x79\x72\x7d\xfe\xd3\xf8\xdd\x74\xfc\xe3\xc5\xe5\xc5\xf4\x13\x18\x0b\x6f\x2e\xa6\xef\x26\x37\x37\xf0\xe6\xea\x1a\xc6\xf0\x7e\x7c\x3d\xbd\x38\xff\x70\x39\xbe\x86\xf7\x1f\xae\xdf\x5f\xdd\x4c\xfa\x70\x83\xa4\x15\x12\xff\xd7\x6d\x9e\xb1\xf7\x2c\x42\x8a\x5e\x48\xe5\x4a\x4b\x7c\x32\x05\xb8\x85\x29\x54\x0a\x0b\xb1\x42\xb0\x98\xa0\x5c\x61\x0a\x02\x12\x93\x6f\x9e\xec\x54\x92\x25\x94\xd1\x73\x3e\xf3\x83\x80\x84\x8b\x0c\xb4\xf1\x3d\x70\x88\xf0\xfd\xc2\xfb\xfc\x74\x30\x58\xaf\xd7\xfd\xb9\x2e\xfa\xc6\xce\x07\x2a\x88\x73\x83\x1f\xfa\x6d\x92\x99\x08\xa5\xa6\x56\x24\x68\xc9\x39\x02\xb2\x82\xcc\xaf\xcc\x5a\x83\xb7\x42\x3b\x91\x90\xab\xe9\x77\xc2\x60\x14\x1e\xf0\x8e\x9e\xbc\x23\xd0\x82\xc5\xdc\x58\xfa\xad\x54\x89\x33\xa9\x3d\x5a\x2d\x14\xcb\x76\xb0\x14\x29\xc2\x6c\x03\xa2\x2e\xb0\x57\x3f\x0c\xc1\x28\xb8\x1b\xa4\xce\x8c\x5d\x32\x2c\xfb\xed\xdf\xdb\xad\xa8\xa1\xf3\x22\xb9\x25\x05\x49\x7e\x52\x58\x8b\xda\x93\x29\x0b\xeb\xe4\x0a\x99\x04\x02\x4d\xb4\xe7\xe4\x97\x9f\x01\xef\x30\x29\x82\xa4\x56\x25\xe4\x14\x3e\xff\x7e\xff\xa5\xd7\x66\xd1\x29\xba\x04\x75\x8a\x29\x9f\xef\xd6\xc1\x7a\xc1\x16\x85\x35\x1e\xaf\x10\x7e\x2d\x9c\xaf\xd1\x64\xd6\x2c\x41\x68\x30\x05\x21\xbe\x6e\x1d\xa9\xbd\x61\x81\x82\x7e\x6b\xb4\xac\x51\xbf\xdd\xaa\x98\x4f\x21\x13\xca\x61\xdc\xd7\x79\xcc\xe9\x34\x52\xaf\xcc\x2d\x49\x36\x96\x20\x6c\x37\x60\xf2\xc4\xa4\x31\x18\xe8\x1c\xd5\x31\xd0\xf5\xdb\x2d\xe2\x3b\x85\xac\xd0\xbc\x6d\x47\x99\x79\x0f\xd2\x59\x17\x7e\x6f\xb7\x48\xec\xb9\xc8\x7d\x61\x91\xed\x89\xd6\x1a\xeb\x40\x2e\x97\x98\x4a\xe1\x51\x6d\xda\xad\xd6\x4a\xd8\xb0\x00\x23\x50\x66\xde\x9f\xa3\x9f\xd0\x63\xa7\x7b\xd6\x6e\xb5\x64\x06\x9d\xb0\xfa\x6c\x34\xe2\xec\x93\x49\x8d\x69\x10\xdf\xf2\x0b\xe9\xfa\x99\x28\x94\xaf\xf6\x25\xa6\x96\x45\x5f\x58\x4d\x3f\xef\x83\x16\x1f\x11\x8c\x56\x1b\x48\x28\xcb\x88\x19\x85\xa7\xdb\x38\x8f\xcb\x78\x38\xd7\x83\x4c\x38\x32\xa1\xcc\x60\x8d\x90\x5b\x7c\x91\x2c\x90\x7c\xa7\x13\x8c\x5a\xba\x8d\x63\xa7\x8e\x80\x76\xeb\x9b\xbc\xef\xcd\xbb\x62\x39\x43\xdb\xe9\xc2\x37\x30\xbc\xcb\x86\x5d\x18\x8d\xf8\x47\xa9\x7b\xe4\x89\xfa\x92\x14\x93\xc7\x83\x32\xff\x8d\xb7\x52\xcf\xc3\x59\xa3\xae\x17\x19\x08\xd0\xb8\x86\xc4\x68\x06\x35\x79\x65\x86\x52\xcf\x21\xb1\x28\x3c\xa6\x3d\x10\x69\x0a\xde\x04\xe4\x55\x38\x6b\x6e\x09\xdf\x7c\x03\x1d\xda\x6c\x04\xc7\xe7\xd7\x93\xf1\x74\x72\x0c\x7f\xfc\x01\xe1\xcd\x51\x78\xf3\xf2\xa8\x5b\xd3\x4c\xea\xab\x2c\x8b\xca\xb1\xc0\x7e\x8e\x78\xdb\x39\xe9\xf6\x57\x42\x15\x78\x95\x05\x35\x23\xed\x44\xa7\x30\x8a\x3c\xcf\x77\x79\x5e\x36\x78\x88\x69\x30\x80\xb1\x73\xb8\x9c\x29\xdc\x0f\xc8\x18\xb1\x1c\xbc\xce\x53\xc6\x22\xf4\x25\x66\x99\x2b\x24\x54\x95\xbb\x46\xf3\xb3\xc6\x2d\xbf\xc9\xf1\x14\x00\xc0\xe4\x3d\x7e\x41\xb1\xc0\x2f\xbc\xf9\x09\xef\xd8\x47\xa5\x09\x09\x55\xe3\x34\xb5\xe8\x5c\xa7\xdb\x0d\xe4\x52\xe7\x85\x3f\x6d\x90\x2f\x71\x69\xec\xa6\xef\x28\x21\x75\xf8\x68\xbd\x70\xd2\x92\x67\x2e\xdc\x85\x26\x9e\x88\xd4\xb7\xc2\x75\xb6\x4b\xe7\xc6\xf9\xd3\x72\x89\x1e\xca\x35\xb6\x05\xb1\x1d\x0f\xef\x8e\xf7\xad\x35\xec\x6e\x91\x70\xf2\x5d\x97\x58\xee\xcf\x2a\x7c\x57\x69\xa2\x9f\x17\x6e\xd1\x61\x38\x6d\x57\xb7\xa9\x60\x04\xde\x16\x78\x10\xfe\x0c\xa9\x7d\x38\x39\x54\x19\xe5\x12\x6f\x8b\x84\x61\x35\x17\x9c\x69\x38\xd2\x05\x65\x5e\x57\xcc\xd8\xe6\xde\x98\x7d\x74\x45\x70\xdd\x4c\x2e\xdf\xbc\x9e\xdc\x4c\xaf\x3f\x9c\x4f\x8f\x6b\x70\x52\x98\x79\x52\xaa\x79\x06\x85\x7a\xee\x17\xac\x3f\x89\x6b\xae\x7e\x26\x9e\x17\x27\x5f\xc2\x1b\x18\x1d\x08\xf9\xd6\xe3\x1c\xf0\xf9\x0b\xcb\xbe\xdf\x37\x5f\x93\x34\x18\xf3\xaf\x41\x92\x37\x4c\x5c\x92\x7b\x53\x12\x3c\xee\xe7\xbf\x18\x54\xe9\x8c\x28\x7e\x14\x4a\xe8\x04\x1f\xd1\x79\x1f\x6b\xf5\xa4\x79\x20\x0f\x2d\xd1\x2f\x4c\xca\x85\x21\x11\xa1\xb6\x94\x08\x4a\x8d\xc6\x7f\x3f\x1b\x8d\x2f\x2f\x6b\xb9\x88\x9f\xcf\xaf\x5e\xd7\xf3\xd3\xf1\xeb\xc9\xe5\xe4\xed\x78\x3a\xd9\xa5\xbd\x99\x8e\xa7\x17\xe7\xfc\xb6\x4c\x5d\x83\x01\xdc\xdc\xca\x9c\x2b\x0c\xe7\x6d\xb3\xcc\xb9\x55\xae\xf4\x75\x3d\xf0\x0b\x43\x4d\xa8\x8d\x05\x34\x13\x3a\x29\x0b\x9b\x2b\x01\xeb\x0d\xc1\xf5\x21\xe7\x9d\xec\x38\xaf\x82\xb0\x74\xef\x2d\xc6\x4d\xd3\x8e\x37\xa5\x5e\x5b\x83\x06\x34\x72\xf2\xe7\x04\xdb\x79\xfa\x21\xe1\x1f\x30\x84\x53\x38\x89\x59\xf4\x91\x34\xfd\x12\x9e\x93\xf8\x3f\x91\xac\x5f\x1d\xe0\xfc\x7b\xa6\xec\xbd\x40\xfb\xef\xa7\x72\x53\xf8\xab\x2c\x3b\x85\x5d\x23\x7e\xbb\x67\xc4\x8a\xfe\x12\xf5\x3e\xfd\xff\xed\xd1\x6f\xd3\x3e\xa1\xca\xe4\xf0\x6c\x0f\x22\x21\xe9\x3e\xdb\x89\x83\x68\x5c\x6e\xef\x58\x1a\x8c\x1e\x28\x34\x2f\x9b\x18\x7e\x28\x53\xfe\x47\x85\xe6\x60\x9b\x4a\xcd\x68\xb3\x11\xed\x81\x45\x6f\x25\xae\x68\xd4\x3c\x76\x2c\x92\x1a\x76\xb3\xa6\xf4\xd5\x87\x8f\x18\x24\x6a\x44\x4e\x2e\xb1\xc1\xa7\xfe\x8c\x7b\x5e\x6a\xd2\xe3\xa8\xc6\x10\x13\xdc\x87\x5b\x84\xa5\xd8\xd0\xa8\x96\x15\xfa\x76\x03\x73\xe1\x20\xdd\x68\xb1\x94\x89\x0b\xf2\xb8\xb9\xb7\x38\x17\x96\xc5\x5a\xfc\xad\x40\x47\x73\x1f\x01\x59\x24\xbe\x10\x4a\x6d\x60\x2e\x69\x78\x23\xee\xce\xcb\x57\xc3\x21\x38\x2f\x73\xd4\x69\x0f\xbe\x7b\x35\xf8\xee\x5b\xb0\x85\xc2\x6e\xbf\x5d\x2b\x61\xd5\x51\xa3\x37\x68\x21\xa2\xe7\x35\xe6\x7e\xd1\xe9\xc2\x0f\x0f\xd4\xc2\x07\x0a\xdb\x41\x5a\x78\x01\x27\x5f\xfa\xa4\xd7\xa8\x81\xdb\xe0\x49\x40\xe5\x30\x4a\xa3\x81\xf7\xea\xf5\x55\xe7\x56\x58\xa1\xc4\x0c\xbb\xa7\x3c\x00\xb3\xad\xd6\x22\x4e\x40\xe4\x14\xc8\x95\x90\x1a\x44\x92\x98\x42\x7b\x32\x7c\x39\xcc\xa8\x0d\xe5\xf7\x63\x5f\xca\xe3\x59\x51\x24\x09\x3a\x57\xa6\x7b\xf6\x1a\xa9\x23\x96\xc4\x0d\x52\x3b\x99\x62\xcd\x2b\x94\x1d\x0c\xa7\xe6\x48\x41\xa3\x74\x29\x70\x69\x1c\x6d\x32\x43\x58\x5b\x1a\xbc\x9c\xd4\x09\xdf\x3c\xa4\x48\xd6\x76\x60\x34\x08\x50\x86\xaf\x3b\x38\xc6\x41\xd8\xb9\xeb\x87\x7c\x4f\xdb\x52\xce\xd1\x66\xdd\x6f\x02\xb9\x0e\x55\x1e\x71\x76\x5a\x21\x0d\x78\x27\x9d\xe7\x8e\x9a\xb4\x94\x0e\x02\x92\xa5\x9e\xf7\x20\x37\x39\xe7\xe9\xaf\x95\xb3\x98\xac\xaf\x27\xbf\x4c\xae\xab\xc6\xe7\xe9\x4e\x2c\x67\x9e\xa3\x6a\x24\x04\x4b\xf3\x96\xc7\xf4\xe8\xc0\x10\x73\x00\x50\xa3\x07\x00\x45\xf2\xb7\xb5\xf1\x7d\xed\x38\x4a\x38\xbf\x75\xcc\x1c\xc3\x3c\x57\x57\xc0\x15\xca\xbb\x9d\xdc\xbd\x9b\x1c\x4c\x5e\x56\x08\x52\x8a\xd3\x0e\x25\xf6\xdd\x49\xa3\xb1\xb0\x1d\x38\xb6\xf8\xbc\xa8\xd9\x78\xcd\xed\x66\x20\xaa\xa5\x06\x5e\x2f\xfb\x56\x11\xaa\x01\xeb\x6e\x0a\x4f\x70\xa0\xfa\xbd\x4d\x7e\x73\xe1\x3e\x38\xf6\x7a\x4c\x7f\x33\x39\xbf\xd0\xbe\x53\x2e\x5e\x68\x78\x01\xe5\x03\x25\x75\x78\xd1\x88\xa2\x03\xd9\xb1\x95\xa2\x42\x8f\xb0\x15\x71\x06\x3b\xaf\x48\x50\x30\x07\x1b\xcd\xa2\xdf\x2f\xce\xc3\x28\x8d\x0c\xf6\xcc\xa2\xef\xe3\x6f\x85\x50\xae\x33\xac\x9a\x85\x70\x02\x6f\xb8\xbc\x8d\xf6\x3a\x49\xe2\x69\xf6\x8e\x67\x35\xb6\x68\x8d\x92\x2d\x74\x82\xe7\x26\xc5\x47\x25\x44\x11\x31\x6d\x54\xbe\x8c\xc0\x3c\xd4\x7b\xb7\xea\x04\x70\x54\x35\x04\x99\x90\xaa\xb0\x78\x74\x06\x07\xd2\x8e\x2b\x6c\x26\x12\xf6\xa5\x43\xe0\x69\xdd\x81\x33\x4b\x5c\x98\x75\x50\xe0\x50\xf2\xda\x07\x47\x85\x83\x9d\xf2\xc1\xd7\x4e\xc2\x41\xe1\xc4\x1c\x6b\xe0\xa8\x0c\x5e\x3a\xea\xe0\x15\xc2\x9f\x86\xce\xf3\xea\xf1\x09\x28\xba\xff\x6b\xe0\xb1\xe3\xe7\xbd\x3e\xa7\x24\xe2\x6e\xa7\xf6\x50\x2a\x1b\x9a\x91\xbf\x97\xe3\x9f\x1c\x61\xbb\xb4\xe1\x68\x4d\xe2\x70\xc0\x6d\x5f\xf3\x75\xf7\x57\xab\x0f\x79\xfe\xa1\x96\x89\x30\xaa\x7f\xc5\xc4\x6f\x71\xca\x5d\x0e\x3d\xe5\x16\x57\xd2\x14\x54\xc0\xf0\x7f\x69\x1c\xae\x5a\xbe\xfb\x76\xeb\x3e\xde\x0b\xb2\xdf\xea\x17\x83\xeb\x45\xbc\xd7\x0e\xdd\x52\xad\x7c\x18\xae\xad\xf1\xba\x30\x0b\x37\xce\x2d\xe6\x7f\xe4\x82\x30\x06\xba\x37\x39\xb5\x03\xb1\x3a\x29\x8b\x22\xdd\x54\x05\xb1\x17\x1a\x11\x58\x08\x9d\xc6\x61\x44\xa4\xa9\x24\x79\x0c\x42\xd2\x50\xcc\x85\xd4\xed\x83\x66\xfc\x6a\x15\x3e\x84\x8c\xbd\xde\xb6\x5e\x48\xe3\x10\x49\x13\x1f\x6b\xdc\x7e\x42\xc1\xdc\x09\xa2\xdd\xbb\xce\x78\x5d\x6a\xb4\x2b\x96\xdc\x09\x83\x58\x09\xa9\x04\x4d\x5f\xdc\x61\xe9\x14\x12\x85\x42\x87\x2f\x1c\x98\x79\xb3\x42\xeb\xda\x4f\x00\xf9\x9f\xc1\xf8\x4e\x56\x2c\x1f\xa3\x39\x9e\x1e\xb3\x4f\x8d\xd8\x70\xfc\x37\x4a\x78\x1f\xe1\x55\x33\x6f\x88\x2c\xe9\xf9\xe3\x17\x6a\xdf\x7e\x5a\x48\x71\xcf\x44\x34\x3f\xc0\xb0\xd6\x97\xff\x5d\x82\x6c\x1f\x62\x97\x55\x7f\x16\x0f\xef\x8d\xe9\x81\x42\xc1\x53\x52\xf9\x69\xaa\xec\x47\x1f\x1b\xda\xca\xe8\x0d\x1d\xdd\x5e\xf8\xf2\x9d\xde\x02\xcb\x1b\x90\xd0\xda\xcf\x10\x35\x48\x8f\x56\xd0\x3c\x44\xe8\x8a\x5f\x53\x48\x4b\xc7\xe2\xd8\x2f\x92\x82\x2e\x0a\x8e\x9f\x36\xa8\x30\x4b\x3d\xef\xb7\x5b\xe1\x7d\x2d\xde\x13\x7f\xb7\x8d\xf7\x50\x01\x99\x33\xde\x09\x54\x57\x02\x89\xbf\xe3\x6e\x91\xc7\xe6\x9d\x7b\x01\x5a\xa3\x57\x61\xa6\xde\xb9\x05\x60\xc6\x78\x13\xb0\x7b\x27\x46\x6b\xfc\xae\x01\x70\x26\x9d\x0b\x17\xc4\xec\x84\x84\xbf\xdb\x8f\x88\x92\x81\x82\xe1\xf4\x30\x03\x2d\x1d\x60\xda\xb9\x99\x20\x62\x7e\x15\x56\x43\x3d\x3f\xad\xaf\x86\x57\xf1\xa0\x72\x59\xb3\x8d\x5c\xb2\x6d\xee\xcf\x0e\x27\xb9\x61\x89\xc7\xc3\xc9\x8c\x6c\x5e\x01\xf6\x01\xd6\xfa\xac\xb1\x4f\xf2\x58\xaa\x64\xe9\x65\x66\x7b\x80\x95\xa5\xd7\x5a\x0e\x7f\xf7\x74\x91\x15\x71\x5d\xc5\x06\x4d\x43\x08\xdf\x36\xee\x2d\x1f\x9a\xb4\x68\x50\x89\x84\x65\x73\x35\x1a\x1d\x0d\xef\xaa\x0f\x23\x31\x57\x35\x68\x4a\x25\x42\x64\x84\xf3\x72\x54\xc8\x7f\x62\xdc\xb6\x1e\x83\xe5\x12\x58\x0c\x1f\x70\xb8\x9b\xa5\x10\x34\x33\x6e\x20\x0a\x47\xa3\xe8\x36\xb6\x52\x74\xd2\x62\x0a\x99\x44\x95\x82\x49\xd1\xf2\xa0\xfb\xab\x33\x3a\x7c\xaa\x43\x2b\x49\x62\xf8\x24\x19\xfe\x1d\xc0\x1f\x4a\xb5\x4c\xd0\x6f\x20\x43\xc1\xdf\xdc\xbc\x81\x5c\x38\x07\x4b\x14\x34\xda\x66\x85\x52\x1b\x30\x36\x45\x12\x5e\xcd\x7a\x14\xd6\x06\x0a\x87\xd6\xc1\x7a\x61\x62\xa9\xe5\x16\x2f\xa7\x6e\x55\xfa\x5e\xbc\xce\x91\x2e\x57\x62\x03\xd2\x53\x59\x8f\x87\xaa\x47\x7a\xf5\xa1\x8b\xbf\x96\x19\x32\xf0\x7e\x98\x97\x53\x61\x33\xce\xf9\x35\x3d\x35\x23\x3c\x0e\x45\xcd\xd8\xde\x5e\x74\x35\x03\xb9\x2c\x3d\xcd\x68\xad\x17\xb2\x66\x48\xf2\x0a\x3f\x35\x83\xb1\xd6\x6a\xf3\x02\x23\xa8\x62\xe0\xa7\x9d\xf0\x64\x2d\x63\x7c\x86\xcf\xba\x15\x39\x3f\xf5\x22\x60\xc8\x8b\x1d\x32\xce\x2d\x6e\x28\x9b\x07\x1b\xd5\x4a\x53\x78\xf1\xf9\x16\x37\x5f\x0e\x57\xa2\x08\xc7\x1a\x5d\x55\x7a\xca\xb0\x08\x6b\x8f\x24\x83\x4a\x0b\x39\x1a\x9e\x81\xfc\xbe\xce\x50\x56\x4f\x90\xcf\x9f\x97\x7b\xd6\xd7\x3f\xcb\x2f\x65\x84\x57\x88\xdf\x59\xef\x36\x34\x8a\x31\x12\x68\x28\x28\xda\xf7\xed\x7f\x05\x00\x00\xff\xff\xfb\x65\x93\x4f\xfc\x22\x00\x00")
+var _call_tracer_jsJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x56\x5f\x6f\xdb\x38\x0c\x7f\x8e\x3f\x05\xaf\x0f\x4b\x82\x65\x71\xbb\x03\xf6\xd0\x2d\x03\x72\x45\xbb\x05\xe8\xb5\x45\x9a\xde\x50\x14\x7d\x50\x6c\xda\xd6\xa6\x48\x86\x44\x37\xcd\x6d\xfd\xee\x07\x4a\x76\x6a\x67\x59\x6f\x2f\x06\x2c\x92\x3f\xfe\xfb\x51\x54\x1c\xc3\x89\x29\x37\x56\xe6\x05\xc1\xdb\xc3\xb7\x47\xb0\x28\x10\x72\xf3\x06\xa9\x40\x8b\xd5\x0a\xa6\x15\x15\xc6\xba\x28\x8e\x61\x51\x48\x07\x99\x54\x08\xd2\x41\x29\x2c\x81\xc9\x80\x76\xf4\x95\x5c\x5a\x61\x37\xe3\x28\x8e\x83\xcd\x5e\x31\x23\x64\x16\x11\x9c\xc9\x68\x2d\x2c\x1e\xc3\xc6\x54\x90\x08\x0d\x16\x53\xe9\xc8\xca\x65\x45\x08\x92\x40\xe8\x34\x36\x16\x56\x26\x95\xd9\x86\x21\x25\x41\xa5\x53\xb4\xde\x35\xa1\x5d\xb9\x26\x8e\x4f\x17\x37\x70\x8e\xce\xa1\x85\x4f\xa8\xd1\x0a\x05\x57\xd5\x52\xc9\x04\xce\x65\x82\xda\x21\x08\x07\x25\x9f\xb8\x02\x53\x58\x7a\x38\x36\x3c\xe3\x50\xae\xeb\x50\xe0\xcc\x54\x3a\x15\x24\x8d\x1e\x01\x4a\x8e\x1c\x1e\xd0\x3a\x69\x34\xfc\xd9\xb8\xaa\x01\x47\x60\x2c\x83\x0c\x04\x71\x02\x16\x4c\xc9\x76\x43\x10\x7a\x03\x4a\xd0\xb3\xe9\x6f\x14\xe4\x39\xef\x14\xa4\xf6\x6e\x0a\x53\x22\x50\x21\x88\xb3\x5e\x4b\xa5\x60\x89\x50\x39\xcc\x2a\x35\x62\xb4\x65\x45\xf0\x65\xb6\xf8\x7c\x79\xb3\x80\xe9\xc5\x2d\x7c\x99\xce\xe7\xd3\x8b\xc5\xed\x7b\x58\x4b\x2a\x4c\x45\x80\x0f\x18\xa0\xe4\xaa\x54\x12\x53\x58\x0b\x6b\x85\xa6\x0d\x98\x8c\x11\xfe\x3e\x9d\x9f\x7c\x9e\x5e\x2c\xa6\x7f\xcd\xce\x67\x8b\x5b\x30\x16\xce\x66\x8b\x8b\xd3\xeb\x6b\x38\xbb\x9c\xc3\x14\xae\xa6\xf3\xc5\xec\xe4\xe6\x7c\x3a\x87\xab\x9b\xf9\xd5\xe5\xf5\xe9\x18\xae\x91\xa3\x42\xb6\xff\xff\x9a\x67\xbe\x7b\x16\x21\x45\x12\x52\xb9\xa6\x12\xb7\xa6\x02\x57\x98\x4a\xa5\x50\x88\x07\x04\x8b\x09\xca\x07\x4c\x41\x40\x62\xca\xcd\x6f\x37\x95\xb1\x84\x32\x3a\xf7\x39\xff\x92\x90\x30\xcb\x40\x1b\x1a\x81\x43\x84\x0f\x05\x51\x79\x1c\xc7\xeb\xf5\x7a\x9c\xeb\x6a\x6c\x6c\x1e\xab\x00\xe7\xe2\x8f\xe3\x28\x62\xd0\x44\x28\x75\x66\xc5\x0a\x17\x56\x24\x68\xb9\xee\xce\xc3\x6b\x5c\x7b\x21\x64\x2c\x05\xb2\x22\x91\x3a\x87\x15\x52\x61\x52\x07\x64\xc0\x62\x69\x2c\xd5\x9d\x02\xa9\x33\x63\x57\x9e\x51\x3e\xd8\x25\x37\x46\x6a\x42\xab\x85\x82\x15\x3a\x27\x72\xf4\x2c\x16\x0c\xa6\x9d\x48\xc8\x53\xe6\x7b\xd4\x63\x3f\x8e\x44\xf2\xed\x18\xee\xbe\x3f\xdd\x8f\xa2\x5e\x26\x2a\x45\xc7\x90\x55\xda\x6b\x0d\x94\xc9\x47\x90\x2e\x87\xf0\xfd\x69\x14\xf5\x2c\xba\xae\x38\xa1\xc7\x5a\x1c\xf5\x7a\x71\x0c\x57\x16\x4b\x66\xb9\xa9\x98\x9d\xb5\x73\x1f\x62\xd4\xeb\x3d\x08\x0b\x01\x01\x26\xde\xa0\x47\x9b\x12\x8f\x01\x00\x12\x7a\x1c\xf3\xcf\x88\x4f\x33\x6b\x56\xfe\x94\xcc\x67\x7c\x64\x1f\x63\x3e\x1a\x7a\x21\x19\x2f\x6a\x0b\xc9\x04\xd1\x83\x50\x95\x87\xeb\x1f\x3e\xf6\xe1\xb5\x07\xf5\x67\x63\x32\xd7\x64\xa5\xce\x07\x47\xef\x82\x6a\x2e\x5c\x80\xa9\x55\x97\x32\x9f\x69\xf2\x68\xb9\x70\xc3\xbd\x06\x37\x0e\xd3\xe3\xfd\x06\x2c\xda\x63\x24\x75\x59\xd1\x71\x27\x56\x7f\x14\xa4\xa6\xa2\x20\x7e\x96\x86\x23\x2f\x7e\x8a\x7a\x3d\x99\xc1\x80\x0a\xe9\xc6\xdb\x3e\xdd\x1d\xde\x87\x1f\xf8\x63\x32\xf1\x37\x55\x26\x35\xa6\xa1\xfe\x75\x7b\x6a\x85\x09\xfc\xc2\xf4\x45\x70\xb4\xd6\xd8\x97\xc0\x83\xc2\x3e\x70\x2f\x61\x70\x40\xe5\x10\x18\x9f\x73\xfa\x6d\xc4\xad\x72\x2b\xc0\x8e\x4a\x07\x03\x5e\xbd\xda\x23\x3e\xc0\x47\x4c\x2a\xa6\x26\x58\x7c\x40\x4b\x98\x1e\xc0\x8f\x1f\x35\xed\xea\xfa\xc2\x64\x32\x39\x38\x7c\x3c\x18\xd6\x71\xa4\xa8\x90\xb0\xab\xe3\x63\x88\x38\x46\xaa\xac\x0e\xd9\x66\x52\x0b\x25\xff\xc5\xda\xed\x30\xea\xf1\x4c\x20\x8f\x5a\x6b\x24\xfc\xd8\x06\x64\x26\xbc\x1f\xe5\x0e\xdd\xbd\xc2\x38\x47\x5a\x6c\x4a\x1c\x0c\x5b\x94\x0f\x44\xd8\xca\xcf\xac\x59\x0d\x86\xcf\xb4\xdf\x11\x2f\x4c\x23\xac\x79\xb6\x23\x9f\xf1\x69\xa3\xe2\x09\xdf\xe5\xee\x56\xf1\x93\x70\x83\x61\x8b\xbe\xfd\xa3\x77\xfd\x0e\x07\xb7\x9a\xff\xf0\x34\x0d\x86\x3b\xdd\xf4\xb9\x71\x9e\x61\xda\x26\xbf\x70\x53\x1b\x77\xe7\xa4\xf6\xd2\x65\xd3\xb8\xac\x5c\x31\xe0\xdf\xa6\xc6\x8f\x92\x76\x4b\x3c\x0f\x4d\xd8\x16\x5a\xa1\xfe\x89\x96\x63\x85\x3a\xa7\xa2\x4e\x83\x35\x3e\xc2\x51\xdd\xf5\x56\x73\x76\xbd\x9b\x72\x30\xdc\xe6\x54\x8f\x37\x4c\xf6\x95\x2f\x04\x51\x17\x91\xd5\x7e\x2e\x64\xe3\xab\xa1\xf9\x8e\xdd\x29\x1f\x07\x77\x1c\x63\xad\xb5\x67\x5a\x42\x34\x0d\x83\xdb\xcd\x7e\x06\xbb\xf4\xd2\xc1\xd0\xc3\xd5\x73\xd8\x32\x6e\x42\x68\xa6\x2c\xb8\xf4\x22\xa6\xa6\x77\xdb\x3f\x99\x9f\x4e\x17\xa7\x7d\x9e\x9a\xbd\x92\xb7\xfd\x26\xa0\x66\x70\x82\x9a\xf1\x67\x4f\x51\xf3\xe1\x6a\xbf\x99\xc0\x51\x93\xd9\xce\x85\xa1\x50\xbf\x39\x6a\x2e\xb3\xbd\xf9\xbe\x68\x00\x77\xf7\x5b\x4f\x2f\x28\x76\x98\xc4\xda\xcc\xa6\x38\x86\x66\x94\xf9\x5d\x60\x51\x10\x3a\x7e\x18\x30\x1b\xcc\xf2\x2b\x26\xbc\x5c\x79\xe9\xf2\x3e\xf6\xaa\x90\xa2\x93\x16\x53\xc8\x24\xaa\x14\x0c\xbf\x10\xf9\xe9\xf1\xd5\x19\xed\x01\x1d\x5a\xc9\x88\x7e\x0f\x8f\xc3\x6b\x56\x32\xa8\x96\x09\xd2\x06\x32\x14\x54\x59\xe4\xf5\x5d\x0a\xe7\x60\x85\x42\x4b\x9d\x67\x95\x52\x1b\x30\x36\x45\x06\x0f\xf7\x8a\xf3\x80\x64\x78\xc1\x5b\x07\xeb\xc2\x40\x6a\x74\xbf\x5e\xea\xa5\x45\x7e\xaf\x8d\xe0\x6b\xe5\x88\x5f\x75\xa5\x12\x1b\x90\x34\x8e\x7a\x4d\x52\xed\xfd\xcc\x99\x6f\x47\xc4\x19\xbe\x10\x7f\x5e\xbe\x4d\x9b\xbb\xdb\xd7\x1f\xf3\x5f\x77\xef\xd6\xdd\xee\x6e\xdc\xe7\xe9\xef\xae\xd7\x66\x82\xba\x3b\xb4\x3d\x57\xdd\x45\xe9\x25\xfe\xaf\xbb\x22\x5b\xdc\xf7\x02\xcf\xe0\xad\x81\xff\x0b\x51\xca\x55\x3b\x27\xb9\x0a\xf1\x78\x2e\x6c\xd5\xfd\x5f\x73\xbf\x71\x17\x07\x5c\x9c\x6f\xb8\xe1\x87\x71\xa8\x51\xcd\x41\xe6\x6d\x38\xb8\xfb\x86\x9b\xfb\xfd\x3c\xad\xa7\xa0\xa5\xd7\x30\xb3\xb9\x3f\x83\xe8\x85\xc5\xbd\x0d\x42\x4e\x0e\xdf\x83\xfc\xd0\x36\xa8\xef\xb0\xf7\x20\x5f\xbf\x6e\x5c\xb6\xe5\x77\xf2\xbe\xb9\xc2\xb6\x0b\x6a\x47\x3e\x6c\x07\x54\x6f\xb4\xa0\x12\xf5\x9e\xa2\xa7\xe8\xbf\x00\x00\x00\xff\xff\x2a\xac\x9f\xff\xa9\x0d\x00\x00")
+
+func call_tracer_jsJsBytes() ([]byte, error) {
+ return bindataRead(
+ _call_tracer_jsJs,
+ "call_tracer_js.js",
+ )
+}
+
+func call_tracer_jsJs() (*asset, error) {
+ bytes, err := call_tracer_jsJsBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "call_tracer_js.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+ a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x42, 0x13, 0x7a, 0x14, 0xbf, 0xa7, 0x49, 0x4f, 0xb4, 0x4f, 0x45, 0x1, 0xbc, 0x9e, 0xd1, 0x8e, 0xc7, 0xee, 0x61, 0xfa, 0x82, 0x52, 0xa4, 0x78, 0xfe, 0xff, 0xb1, 0x68, 0x1d, 0xcc, 0x1d, 0x8e}}
+ return a, nil
+}
+
+var _call_tracer_legacyJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x5a\xdf\x6f\x1b\x37\xf2\x7f\x96\xfe\x8a\x89\x1f\x6a\x09\x51\x24\x39\xe9\xb7\x5f\xc0\xae\x7a\x50\x1d\x25\x35\xe0\xc6\x81\xad\x34\x08\x82\x3c\x50\xbb\xb3\x12\x6b\x8a\xdc\x92\x5c\xc9\xba\xd6\xff\xfb\x61\x86\xdc\xd5\xae\x24\x3b\xbe\x5e\x71\xe8\xbd\x69\x97\x33\xc3\xe1\xcc\x67\x7e\x71\x35\x18\xc0\xb9\xc9\x37\x56\xce\x17\x1e\x5e\x0e\x4f\xfe\x1f\xa6\x0b\x84\xb9\x79\x81\x7e\x81\x16\x8b\x25\x8c\x0b\xbf\x30\xd6\xb5\x07\x03\x98\x2e\xa4\x83\x4c\x2a\x04\xe9\x20\x17\xd6\x83\xc9\xc0\xef\xd0\x2b\x39\xb3\xc2\x6e\xfa\xed\xc1\x20\xf0\x1c\x5c\x26\x09\x99\x45\x04\x67\x32\xbf\x16\x16\x4f\x61\x63\x0a\x48\x84\x06\x8b\xa9\x74\xde\xca\x59\xe1\x11\xa4\x07\xa1\xd3\x81\xb1\xb0\x34\xa9\xcc\x36\x24\x52\x7a\x28\x74\x8a\x96\xb7\xf6\x68\x97\xae\xd4\xe3\xed\xbb\x0f\x70\x89\xce\xa1\x85\xb7\xa8\xd1\x0a\x05\xef\x8b\x99\x92\x09\x5c\xca\x04\xb5\x43\x10\x0e\x72\x7a\xe3\x16\x98\xc2\x8c\xc5\x11\xe3\x1b\x52\xe5\x26\xaa\x02\x6f\x4c\xa1\x53\xe1\xa5\xd1\x3d\x40\x49\x9a\xc3\x0a\xad\x93\x46\xc3\xab\x72\xab\x28\xb0\x07\xc6\x92\x90\x8e\xf0\x74\x00\x0b\x26\x27\xbe\x2e\x08\xbd\x01\x25\xfc\x96\xf5\x09\x06\xd9\x9e\x3b\x05\xa9\x79\x9b\x85\xc9\x11\xfc\x42\x78\x3a\xf5\x5a\x2a\x05\x33\x84\xc2\x61\x56\xa8\x1e\x49\x9b\x15\x1e\x3e\x5e\x4c\x7f\xba\xfa\x30\x85\xf1\xbb\x4f\xf0\x71\x7c\x7d\x3d\x7e\x37\xfd\x74\x06\x6b\xe9\x17\xa6\xf0\x80\x2b\x0c\xa2\xe4\x32\x57\x12\x53\x58\x0b\x6b\x85\xf6\x1b\x30\x19\x49\xf8\x79\x72\x7d\xfe\xd3\xf8\xdd\x74\xfc\xe3\xc5\xe5\xc5\xf4\x13\x18\x0b\x6f\x2e\xa6\xef\x26\x37\x37\xf0\xe6\xea\x1a\xc6\xf0\x7e\x7c\x3d\xbd\x38\xff\x70\x39\xbe\x86\xf7\x1f\xae\xdf\x5f\xdd\x4c\xfa\x70\x83\xa4\x15\x12\xff\xd7\x6d\x9e\xb1\xf7\x2c\x42\x8a\x5e\x48\xe5\x4a\x4b\x7c\x32\x05\xb8\x85\x29\x54\x0a\x0b\xb1\x42\xb0\x98\xa0\x5c\x61\x0a\x02\x12\x93\x6f\x9e\xec\x54\x92\x25\x94\xd1\x73\x3e\xf3\x83\x80\x84\x8b\x0c\xb4\xf1\x3d\x70\x88\xf0\xfd\xc2\xfb\xfc\x74\x30\x58\xaf\xd7\xfd\xb9\x2e\xfa\xc6\xce\x07\x2a\x88\x73\x83\x1f\xfa\x6d\x92\x99\x08\xa5\xa6\x56\x24\x68\xc9\x39\x02\xb2\x82\xcc\xaf\xcc\x5a\x83\xb7\x42\x3b\x91\x90\xab\xe9\x77\xc2\x60\x14\x1e\xf0\x8e\x9e\xbc\x23\xd0\x82\xc5\xdc\x58\xfa\xad\x54\x89\x33\xa9\x3d\x5a\x2d\x14\xcb\x76\xb0\x14\x29\xc2\x6c\x03\xa2\x2e\xb0\x57\x3f\x0c\xc1\x28\xb8\x1b\xa4\xce\x8c\x5d\x32\x2c\xfb\xed\xdf\xdb\xad\xa8\xa1\xf3\x22\xb9\x25\x05\x49\x7e\x52\x58\x8b\xda\x93\x29\x0b\xeb\xe4\x0a\x99\x04\x02\x4d\xb4\xe7\xe4\x97\x9f\x01\xef\x30\x29\x82\xa4\x56\x25\xe4\x14\x3e\xff\x7e\xff\xa5\xd7\x66\xd1\x29\xba\x04\x75\x8a\x29\x9f\xef\xd6\xc1\x7a\xc1\x16\x85\x35\x1e\xaf\x10\x7e\x2d\x9c\xaf\xd1\x64\xd6\x2c\x41\x68\x30\x05\x21\xbe\x6e\x1d\xa9\xbd\x61\x81\x82\x7e\x6b\xb4\xac\x51\xbf\xdd\xaa\x98\x4f\x21\x13\xca\x61\xdc\xd7\x79\xcc\xe9\x34\x52\xaf\xcc\x2d\x49\x36\x96\x20\x6c\x37\x60\xf2\xc4\xa4\x31\x18\xe8\x1c\xd5\x31\xd0\xf5\xdb\x2d\xe2\x3b\x85\xac\xd0\xbc\x6d\x47\x99\x79\x0f\xd2\x59\x17\x7e\x6f\xb7\x48\xec\xb9\xc8\x7d\x61\x91\xed\x89\xd6\x1a\xeb\x40\x2e\x97\x98\x4a\xe1\x51\x6d\xda\xad\xd6\x4a\xd8\xb0\x00\x23\x50\x66\xde\x9f\xa3\x9f\xd0\x63\xa7\x7b\xd6\x6e\xb5\x64\x06\x9d\xb0\xfa\x6c\x34\xe2\xec\x93\x49\x8d\x69\x10\xdf\xf2\x0b\xe9\xfa\x99\x28\x94\xaf\xf6\x25\xa6\x96\x45\x5f\x58\x4d\x3f\xef\x83\x16\x1f\x11\x8c\x56\x1b\x48\x28\xcb\x88\x19\x85\xa7\xdb\x38\x8f\xcb\x78\x38\xd7\x83\x4c\x38\x32\xa1\xcc\x60\x8d\x90\x5b\x7c\x91\x2c\x90\x7c\xa7\x13\x8c\x5a\xba\x8d\x63\xa7\x8e\x80\x76\xeb\x9b\xbc\xef\xcd\xbb\x62\x39\x43\xdb\xe9\xc2\x37\x30\xbc\xcb\x86\x5d\x18\x8d\xf8\x47\xa9\x7b\xe4\x89\xfa\x92\x14\x93\xc7\x83\x32\xff\x8d\xb7\x52\xcf\xc3\x59\xa3\xae\x17\x19\x08\xd0\xb8\x86\xc4\x68\x06\x35\x79\x65\x86\x52\xcf\x21\xb1\x28\x3c\xa6\x3d\x10\x69\x0a\xde\x04\xe4\x55\x38\x6b\x6e\x09\xdf\x7c\x03\x1d\xda\x6c\x04\xc7\xe7\xd7\x93\xf1\x74\x72\x0c\x7f\xfc\x01\xe1\xcd\x51\x78\xf3\xf2\xa8\x5b\xd3\x4c\xea\xab\x2c\x8b\xca\xb1\xc0\x7e\x8e\x78\xdb\x39\xe9\xf6\x57\x42\x15\x78\x95\x05\x35\x23\xed\x44\xa7\x30\x8a\x3c\xcf\x77\x79\x5e\x36\x78\x88\x69\x30\x80\xb1\x73\xb8\x9c\x29\xdc\x0f\xc8\x18\xb1\x1c\xbc\xce\x53\xc6\x22\xf4\x25\x66\x99\x2b\x24\x54\x95\xbb\x46\xf3\xb3\xc6\x2d\xbf\xc9\xf1\x14\x00\xc0\xe4\x3d\x7e\x41\xb1\xc0\x2f\xbc\xf9\x09\xef\xd8\x47\xa5\x09\x09\x55\xe3\x34\xb5\xe8\x5c\xa7\xdb\x0d\xe4\x52\xe7\x85\x3f\x6d\x90\x2f\x71\x69\xec\xa6\xef\x28\x21\x75\xf8\x68\xbd\x70\xd2\x92\x67\x2e\xdc\x85\x26\x9e\x88\xd4\xb7\xc2\x75\xb6\x4b\xe7\xc6\xf9\xd3\x72\x89\x1e\xca\x35\xb6\x05\xb1\x1d\x0f\xef\x8e\xf7\xad\x35\xec\x6e\x91\x70\xf2\x5d\x97\x58\xee\xcf\x2a\x7c\x57\x69\xa2\x9f\x17\x6e\xd1\x61\x38\x6d\x57\xb7\xa9\x60\x04\xde\x16\x78\x10\xfe\x0c\xa9\x7d\x38\x39\x54\x19\xe5\x12\x6f\x8b\x84\x61\x35\x17\x9c\x69\x38\xd2\x05\x65\x5e\x57\xcc\xd8\xe6\xde\x98\x7d\x74\x45\x70\xdd\x4c\x2e\xdf\xbc\x9e\xdc\x4c\xaf\x3f\x9c\x4f\x8f\x6b\x70\x52\x98\x79\x52\xaa\x79\x06\x85\x7a\xee\x17\xac\x3f\x89\x6b\xae\x7e\x26\x9e\x17\x27\x5f\xc2\x1b\x18\x1d\x08\xf9\xd6\xe3\x1c\xf0\xf9\x0b\xcb\xbe\xdf\x37\x5f\x93\x34\x18\xf3\xaf\x41\x92\x37\x4c\x5c\x92\x7b\x53\x12\x3c\xee\xe7\xbf\x18\x54\xe9\x8c\x28\x7e\x14\x4a\xe8\x04\x1f\xd1\x79\x1f\x6b\xf5\xa4\x79\x20\x0f\x2d\xd1\x2f\x4c\xca\x85\x21\x11\xa1\xb6\x94\x08\x4a\x8d\xc6\x7f\x3f\x1b\x8d\x2f\x2f\x6b\xb9\x88\x9f\xcf\xaf\x5e\xd7\xf3\xd3\xf1\xeb\xc9\xe5\xe4\xed\x78\x3a\xd9\xa5\xbd\x99\x8e\xa7\x17\xe7\xfc\xb6\x4c\x5d\x83\x01\xdc\xdc\xca\x9c\x2b\x0c\xe7\x6d\xb3\xcc\xb9\x55\xae\xf4\x75\x3d\xf0\x0b\x43\x4d\xa8\x8d\x05\x34\x13\x3a\x29\x0b\x9b\x2b\x01\xeb\x0d\xc1\xf5\x21\xe7\x9d\xec\x38\xaf\x82\xb0\x74\xef\x2d\xc6\x4d\xd3\x8e\x37\xa5\x5e\x5b\x83\x06\x34\x72\xf2\xe7\x04\xdb\x79\xfa\x21\xe1\x1f\x30\x84\x53\x38\x89\x59\xf4\x91\x34\xfd\x12\x9e\x93\xf8\x3f\x91\xac\x5f\x1d\xe0\xfc\x7b\xa6\xec\xbd\x40\xfb\xef\xa7\x72\x53\xf8\xab\x2c\x3b\x85\x5d\x23\x7e\xbb\x67\xc4\x8a\xfe\x12\xf5\x3e\xfd\xff\xed\xd1\x6f\xd3\x3e\xa1\xca\xe4\xf0\x6c\x0f\x22\x21\xe9\x3e\xdb\x89\x83\x68\x5c\x6e\xef\x58\x1a\x8c\x1e\x28\x34\x2f\x9b\x18\x7e\x28\x53\xfe\x47\x85\xe6\x60\x9b\x4a\xcd\x68\xb3\x11\xed\x81\x45\x6f\x25\xae\x68\xd4\x3c\x76\x2c\x92\x1a\x76\xb3\xa6\xf4\xd5\x87\x8f\x18\x24\x6a\x44\x4e\x2e\xb1\xc1\xa7\xfe\x8c\x7b\x5e\x6a\xd2\xe3\xa8\xc6\x10\x13\xdc\x87\x5b\x84\xa5\xd8\xd0\xa8\x96\x15\xfa\x76\x03\x73\xe1\x20\xdd\x68\xb1\x94\x89\x0b\xf2\xb8\xb9\xb7\x38\x17\x96\xc5\x5a\xfc\xad\x40\x47\x73\x1f\x01\x59\x24\xbe\x10\x4a\x6d\x60\x2e\x69\x78\x23\xee\xce\xcb\x57\xc3\x21\x38\x2f\x73\xd4\x69\x0f\xbe\x7b\x35\xf8\xee\x5b\xb0\x85\xc2\x6e\xbf\x5d\x2b\x61\xd5\x51\xa3\x37\x68\x21\xa2\xe7\x35\xe6\x7e\xd1\xe9\xc2\x0f\x0f\xd4\xc2\x07\x0a\xdb\x41\x5a\x78\x01\x27\x5f\xfa\xa4\xd7\xa8\x81\xdb\xe0\x49\x40\xe5\x30\x4a\xa3\x81\xf7\xea\xf5\x55\xe7\x56\x58\xa1\xc4\x0c\xbb\xa7\x3c\x00\xb3\xad\xd6\x22\x4e\x40\xe4\x14\xc8\x95\x90\x1a\x44\x92\x98\x42\x7b\x32\x7c\x39\xcc\xa8\x0d\xe5\xf7\x63\x5f\xca\xe3\x59\x51\x24\x09\x3a\x57\xa6\x7b\xf6\x1a\xa9\x23\x96\xc4\x0d\x52\x3b\x99\x62\xcd\x2b\x94\x1d\x0c\xa7\xe6\x48\x41\xa3\x74\x29\x70\x69\x1c\x6d\x32\x43\x58\x5b\x1a\xbc\x9c\xd4\x09\xdf\x3c\xa4\x48\xd6\x76\x60\x34\x08\x50\x86\xaf\x3b\x38\xc6\x41\xd8\xb9\xeb\x87\x7c\x4f\xdb\x52\xce\xd1\x66\xdd\x6f\x02\xb9\x0e\x55\x1e\x71\x76\x5a\x21\x0d\x78\x27\x9d\xe7\x8e\x9a\xb4\x94\x0e\x02\x92\xa5\x9e\xf7\x20\x37\x39\xe7\xe9\xaf\x95\xb3\x98\xac\xaf\x27\xbf\x4c\xae\xab\xc6\xe7\xe9\x4e\x2c\x67\x9e\xa3\x6a\x24\x04\x4b\xf3\x96\xc7\xf4\xe8\xc0\x10\x73\x00\x50\xa3\x07\x00\x45\xf2\xb7\xb5\xf1\x7d\xed\x38\x4a\x38\xbf\x75\xcc\x1c\xc3\x3c\x57\x57\xc0\x15\xca\xbb\x9d\xdc\xbd\x9b\x1c\x4c\x5e\x56\x08\x52\x8a\xd3\x0e\x25\xf6\xdd\x49\xa3\xb1\xb0\x1d\x38\xb6\xf8\xbc\xa8\xd9\x78\xcd\xed\x66\x20\xaa\xa5\x06\x5e\x2f\xfb\x56\x11\xaa\x01\xeb\x6e\x0a\x4f\x70\xa0\xfa\xbd\x4d\x7e\x73\xe1\x3e\x38\xf6\x7a\x4c\x7f\x33\x39\xbf\xd0\xbe\x53\x2e\x5e\x68\x78\x01\xe5\x03\x25\x75\x78\xd1\x88\xa2\x03\xd9\xb1\x95\xa2\x42\x8f\xb0\x15\x71\x06\x3b\xaf\x48\x50\x30\x07\x1b\xcd\xa2\xdf\x2f\xce\xc3\x28\x8d\x0c\xf6\xcc\xa2\xef\xe3\x6f\x85\x50\xae\x33\xac\x9a\x85\x70\x02\x6f\xb8\xbc\x8d\xf6\x3a\x49\xe2\x69\xf6\x8e\x67\x35\xb6\x68\x8d\x92\x2d\x74\x82\xe7\x26\xc5\x47\x25\x44\x11\x31\x6d\x54\xbe\x8c\xc0\x3c\xd4\x7b\xb7\xea\x04\x70\x54\x35\x04\x99\x90\xaa\xb0\x78\x74\x06\x07\xd2\x8e\x2b\x6c\x26\x12\xf6\xa5\x43\xe0\x69\xdd\x81\x33\x4b\x5c\x98\x75\x50\xe0\x50\xf2\xda\x07\x47\x85\x83\x9d\xf2\xc1\xd7\x4e\xc2\x41\xe1\xc4\x1c\x6b\xe0\xa8\x0c\x5e\x3a\xea\xe0\x15\xc2\x9f\x86\xce\xf3\xea\xf1\x09\x28\xba\xff\x6b\xe0\xb1\xe3\xe7\xbd\x3e\xa7\x24\xe2\x6e\xa7\xf6\x50\x2a\x1b\x9a\x91\xbf\x97\xe3\x9f\x1c\x61\xbb\xb4\xe1\x68\x4d\xe2\x70\xc0\x6d\x5f\xf3\x75\xf7\x57\xab\x0f\x79\xfe\xa1\x96\x89\x30\xaa\x7f\xc5\xc4\x6f\x71\xca\x5d\x0e\x3d\xe5\x16\x57\xd2\x14\x54\xc0\xf0\x7f\x69\x1c\xae\x5a\xbe\xfb\x76\xeb\x3e\xde\x0b\xb2\xdf\xea\x17\x83\xeb\x45\xbc\xd7\x0e\xdd\x52\xad\x7c\x18\xae\xad\xf1\xba\x30\x0b\x37\xce\x2d\xe6\x7f\xe4\x82\x30\x06\xba\x37\x39\xb5\x03\xb1\x3a\x29\x8b\x22\xdd\x54\x05\xb1\x17\x1a\x11\x58\x08\x9d\xc6\x61\x44\xa4\xa9\x24\x79\x0c\x42\xd2\x50\xcc\x85\xd4\xed\x83\x66\xfc\x6a\x15\x3e\x84\x8c\xbd\xde\xb6\x5e\x48\xe3\x10\x49\x13\x1f\x6b\xdc\x7e\x42\xc1\xdc\x09\xa2\xdd\xbb\xce\x78\x5d\x6a\xb4\x2b\x96\xdc\x09\x83\x58\x09\xa9\x04\x4d\x5f\xdc\x61\xe9\x14\x12\x85\x42\x87\x2f\x1c\x98\x79\xb3\x42\xeb\xda\x4f\x00\xf9\x9f\xc1\xf8\x4e\x56\x2c\x1f\xa3\x39\x9e\x1e\xb3\x4f\x8d\xd8\x70\xfc\x37\x4a\x78\x1f\xe1\x55\x33\x6f\x88\x2c\xe9\xf9\xe3\x17\x6a\xdf\x7e\x5a\x48\x71\xcf\x44\x34\x3f\xc0\xb0\xd6\x97\xff\x5d\x82\x6c\x1f\x62\x97\x55\x7f\x16\x0f\xef\x8d\xe9\x81\x42\xc1\x53\x52\xf9\x69\xaa\xec\x47\x1f\x1b\xda\xca\xe8\x0d\x1d\xdd\x5e\xf8\xf2\x9d\xde\x02\xcb\x1b\x90\xd0\xda\xcf\x10\x35\x48\x8f\x56\xd0\x3c\x44\xe8\x8a\x5f\x53\x48\x4b\xc7\xe2\xd8\x2f\x92\x82\x2e\x0a\x8e\x9f\x36\xa8\x30\x4b\x3d\xef\xb7\x5b\xe1\x7d\x2d\xde\x13\x7f\xb7\x8d\xf7\x50\x01\x99\x33\xde\x09\x54\x57\x02\x89\xbf\xe3\x6e\x91\xc7\xe6\x9d\x7b\x01\x5a\xa3\x57\x61\xa6\xde\xb9\x05\x60\xc6\x78\x13\xb0\x7b\x27\x46\x6b\xfc\xae\x01\x70\x26\x9d\x0b\x17\xc4\xec\x84\x84\xbf\xdb\x8f\x88\x92\x81\x82\xe1\xf4\x30\x03\x2d\x1d\x60\xda\xb9\x99\x20\x62\x7e\x15\x56\x43\x3d\x3f\xad\xaf\x86\x57\xf1\xa0\x72\x59\xb3\x8d\x5c\xb2\x6d\xee\xcf\x0e\x27\xb9\x61\x89\xc7\xc3\xc9\x8c\x6c\x5e\x01\xf6\x01\xd6\xfa\xac\xb1\x4f\xf2\x58\xaa\x64\xe9\x65\x66\x7b\x80\x95\xa5\xd7\x5a\x0e\x7f\xf7\x74\x91\x15\x71\x5d\xc5\x06\x4d\x43\x08\xdf\x36\xee\x2d\x1f\x9a\xb4\x68\x50\x89\x84\x65\x73\x35\x1a\x1d\x0d\xef\xaa\x0f\x23\x31\x57\x35\x68\x4a\x25\x42\x64\x84\xf3\x72\x54\xc8\x7f\x62\xdc\xb6\x1e\x83\xe5\x12\x58\x0c\x1f\x70\xb8\x9b\xa5\x10\x34\x33\x6e\x20\x0a\x47\xa3\xe8\x36\xb6\x52\x74\xd2\x62\x0a\x99\x44\x95\x82\x49\xd1\xf2\xa0\xfb\xab\x33\x3a\x7c\xaa\x43\x2b\x49\x62\xf8\x24\x19\xfe\x1d\xc0\x1f\x4a\xb5\x4c\xd0\x6f\x20\x43\xc1\xdf\xdc\xbc\x81\x5c\x38\x07\x4b\x14\x34\xda\x66\x85\x52\x1b\x30\x36\x45\x12\x5e\xcd\x7a\x14\xd6\x06\x0a\x87\xd6\xc1\x7a\x61\x62\xa9\xe5\x16\x2f\xa7\x6e\x55\xfa\x5e\xbc\xce\x91\x2e\x57\x62\x03\xd2\x53\x59\x8f\x87\xaa\x47\x7a\xf5\xa1\x8b\xbf\x96\x19\x32\xf0\x7e\x98\x97\x53\x61\x33\xce\xf9\x35\x3d\x35\x23\x3c\x0e\x45\xcd\xd8\xde\x5e\x74\x35\x03\xb9\x2c\x3d\xcd\x68\xad\x17\xb2\x66\x48\xf2\x0a\x3f\x35\x83\xb1\xd6\x6a\xf3\x02\x23\xa8\x62\xe0\xa7\x9d\xf0\x64\x2d\x63\x7c\x86\xcf\xba\x15\x39\x3f\xf5\x22\x60\xc8\x8b\x1d\x32\xce\x2d\x6e\x28\x9b\x07\x1b\xd5\x4a\x53\x78\xf1\xf9\x16\x37\x5f\x0e\x57\xa2\x08\xc7\x1a\x5d\x55\x7a\xca\xb0\x08\x6b\x8f\x24\x83\x4a\x0b\x39\x1a\x9e\x81\xfc\xbe\xce\x50\x56\x4f\x90\xcf\x9f\x97\x7b\xd6\xd7\x3f\xcb\x2f\x65\x84\x57\x88\xdf\x59\xef\x36\x34\x8a\x31\x12\x68\x28\x28\xda\xf7\xed\x7f\x05\x00\x00\xff\xff\xfb\x65\x93\x4f\xfc\x22\x00\x00")
-func call_tracerJsBytes() ([]byte, error) {
+func call_tracer_legacyJsBytes() ([]byte, error) {
return bindataRead(
- _call_tracerJs,
- "call_tracer.js",
+ _call_tracer_legacyJs,
+ "call_tracer_legacy.js",
)
}
-func call_tracerJs() (*asset, error) {
- bytes, err := call_tracerJsBytes()
+func call_tracer_legacyJs() (*asset, error) {
+ bytes, err := call_tracer_legacyJsBytes()
if err != nil {
return nil, err
}
- info := bindataFileInfo{name: "call_tracer.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+ info := bindataFileInfo{name: "call_tracer_legacy.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x46, 0x79, 0xb6, 0xbc, 0xd2, 0xc, 0x25, 0xb1, 0x22, 0x56, 0xef, 0x77, 0xb9, 0x5e, 0x2e, 0xf4, 0xda, 0xb2, 0x2f, 0x53, 0xa4, 0xff, 0xc8, 0xac, 0xbb, 0x75, 0x22, 0x46, 0x59, 0xe3, 0x1d, 0x7d}}
return a, nil
}
@@ -348,15 +390,17 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
- "4byte_tracer.js": _4byte_tracerJs,
- "bigram_tracer.js": bigram_tracerJs,
- "call_tracer.js": call_tracerJs,
- "evmdis_tracer.js": evmdis_tracerJs,
- "noop_tracer.js": noop_tracerJs,
- "opcount_tracer.js": opcount_tracerJs,
- "prestate_tracer.js": prestate_tracerJs,
- "trigram_tracer.js": trigram_tracerJs,
- "unigram_tracer.js": unigram_tracerJs,
+ "4byte_tracer.js": _4byte_tracerJs,
+ "4byte_tracer_legacy.js": _4byte_tracer_legacyJs,
+ "bigram_tracer.js": bigram_tracerJs,
+ "call_tracer_js.js": call_tracer_jsJs,
+ "call_tracer_legacy.js": call_tracer_legacyJs,
+ "evmdis_tracer.js": evmdis_tracerJs,
+ "noop_tracer.js": noop_tracerJs,
+ "opcount_tracer.js": opcount_tracerJs,
+ "prestate_tracer.js": prestate_tracerJs,
+ "trigram_tracer.js": trigram_tracerJs,
+ "unigram_tracer.js": unigram_tracerJs,
}
// AssetDebug is true if the assets were built with the debug flag enabled.
@@ -403,15 +447,17 @@ type bintree struct {
}
var _bintree = &bintree{nil, map[string]*bintree{
- "4byte_tracer.js": {_4byte_tracerJs, map[string]*bintree{}},
- "bigram_tracer.js": {bigram_tracerJs, map[string]*bintree{}},
- "call_tracer.js": {call_tracerJs, map[string]*bintree{}},
- "evmdis_tracer.js": {evmdis_tracerJs, map[string]*bintree{}},
- "noop_tracer.js": {noop_tracerJs, map[string]*bintree{}},
- "opcount_tracer.js": {opcount_tracerJs, map[string]*bintree{}},
- "prestate_tracer.js": {prestate_tracerJs, map[string]*bintree{}},
- "trigram_tracer.js": {trigram_tracerJs, map[string]*bintree{}},
- "unigram_tracer.js": {unigram_tracerJs, map[string]*bintree{}},
+ "4byte_tracer.js": {_4byte_tracerJs, map[string]*bintree{}},
+ "4byte_tracer_legacy.js": {_4byte_tracer_legacyJs, map[string]*bintree{}},
+ "bigram_tracer.js": {bigram_tracerJs, map[string]*bintree{}},
+ "call_tracer_js.js": {call_tracer_jsJs, map[string]*bintree{}},
+ "call_tracer_legacy.js": {call_tracer_legacyJs, map[string]*bintree{}},
+ "evmdis_tracer.js": {evmdis_tracerJs, map[string]*bintree{}},
+ "noop_tracer.js": {noop_tracerJs, map[string]*bintree{}},
+ "opcount_tracer.js": {opcount_tracerJs, map[string]*bintree{}},
+ "prestate_tracer.js": {prestate_tracerJs, map[string]*bintree{}},
+ "trigram_tracer.js": {trigram_tracerJs, map[string]*bintree{}},
+ "unigram_tracer.js": {unigram_tracerJs, map[string]*bintree{}},
}}
// RestoreAsset restores an asset under the given directory.
diff --git a/eth/tracers/internal/tracers/bigram_tracer.js b/eth/tracers/js/internal/tracers/bigram_tracer.js
similarity index 100%
rename from eth/tracers/internal/tracers/bigram_tracer.js
rename to eth/tracers/js/internal/tracers/bigram_tracer.js
diff --git a/eth/tracers/js/internal/tracers/call_tracer_js.js b/eth/tracers/js/internal/tracers/call_tracer_js.js
new file mode 100644
index 000000000..7da7bf216
--- /dev/null
+++ b/eth/tracers/js/internal/tracers/call_tracer_js.js
@@ -0,0 +1,112 @@
+// 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 .
+
+
+// callFrameTracer uses the new call frame tracing methods to report useful information
+// about internal messages of a transaction.
+{
+ callstack: [{}],
+ fault: function(log, db) {},
+ result: function(ctx, db) {
+ // Prepare outer message info
+ var result = {
+ type: ctx.type,
+ from: toHex(ctx.from),
+ to: toHex(ctx.to),
+ value: '0x' + ctx.value.toString(16),
+ gas: '0x' + bigInt(ctx.gas).toString(16),
+ gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16),
+ input: toHex(ctx.input),
+ output: toHex(ctx.output),
+ }
+ if (this.callstack[0].calls !== undefined) {
+ result.calls = this.callstack[0].calls
+ }
+ if (this.callstack[0].error !== undefined) {
+ result.error = this.callstack[0].error
+ } else if (ctx.error !== undefined) {
+ result.error = ctx.error
+ }
+ if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) {
+ delete result.output
+ }
+
+ return this.finalize(result)
+ },
+ enter: function(frame) {
+ var call = {
+ type: frame.getType(),
+ from: toHex(frame.getFrom()),
+ to: toHex(frame.getTo()),
+ input: toHex(frame.getInput()),
+ gas: '0x' + bigInt(frame.getGas()).toString('16'),
+ }
+ if (frame.getValue() !== undefined){
+ call.value='0x' + bigInt(frame.getValue()).toString(16)
+ }
+ this.callstack.push(call)
+ },
+ exit: function(frameResult) {
+ var len = this.callstack.length
+ if (len > 1) {
+ var call = this.callstack.pop()
+ call.gasUsed = '0x' + bigInt(frameResult.getGasUsed()).toString('16')
+ var error = frameResult.getError()
+ if (error === undefined) {
+ call.output = toHex(frameResult.getOutput())
+ } else {
+ call.error = error
+ if (call.type === 'CREATE' || call.type === 'CREATE2') {
+ delete call.to
+ }
+ }
+ len -= 1
+ if (this.callstack[len-1].calls === undefined) {
+ this.callstack[len-1].calls = []
+ }
+ this.callstack[len-1].calls.push(call)
+ }
+ },
+ // finalize recreates a call object using the final desired field oder for json
+ // serialization. This is a nicety feature to pass meaningfully ordered results
+ // to users who don't interpret it, just display it.
+ finalize: function(call) {
+ var sorted = {
+ type: call.type,
+ from: call.from,
+ to: call.to,
+ value: call.value,
+ gas: call.gas,
+ gasUsed: call.gasUsed,
+ input: call.input,
+ output: call.output,
+ error: call.error,
+ time: call.time,
+ calls: call.calls,
+ }
+ for (var key in sorted) {
+ if (sorted[key] === undefined) {
+ delete sorted[key]
+ }
+ }
+ if (sorted.calls !== undefined) {
+ for (var i=0; i.
+
+// package js is a collection of tracers written in javascript.
+package js
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math/big"
+ "strings"
+ "sync/atomic"
+ "time"
+ "unicode"
+ "unsafe"
+
+ "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/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ tracers2 "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/eth/tracers/js/internal/tracers"
+ "github.com/ethereum/go-ethereum/log"
+ "gopkg.in/olebedev/go-duktape.v3"
+)
+
+// camel converts a snake cased input string into a camel cased output.
+func camel(str string) string {
+ pieces := strings.Split(str, "_")
+ for i := 1; i < len(pieces); i++ {
+ pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:]
+ }
+ return strings.Join(pieces, "")
+}
+
+var assetTracers = make(map[string]string)
+
+// init retrieves the JavaScript transaction tracers included in go-ethereum.
+func init() {
+ for _, file := range tracers.AssetNames() {
+ name := camel(strings.TrimSuffix(file, ".js"))
+ assetTracers[name] = string(tracers.MustAsset(file))
+ }
+ tracers2.RegisterLookup(true, newJsTracer)
+}
+
+// makeSlice convert an unsafe memory pointer with the given type into a Go byte
+// slice.
+//
+// Note, the returned slice uses the same memory area as the input arguments.
+// If those are duktape stack items, popping them off **will** make the slice
+// contents change.
+func makeSlice(ptr unsafe.Pointer, size uint) []byte {
+ var sl = struct {
+ addr uintptr
+ len int
+ cap int
+ }{uintptr(ptr), int(size), int(size)}
+
+ return *(*[]byte)(unsafe.Pointer(&sl))
+}
+
+// popSlice pops a buffer off the JavaScript stack and returns it as a slice.
+func popSlice(ctx *duktape.Context) []byte {
+ blob := common.CopyBytes(makeSlice(ctx.GetBuffer(-1)))
+ ctx.Pop()
+ return blob
+}
+
+// pushBigInt create a JavaScript BigInteger in the VM.
+func pushBigInt(n *big.Int, ctx *duktape.Context) {
+ ctx.GetGlobalString("bigInt")
+ ctx.PushString(n.String())
+ ctx.Call(1)
+}
+
+// opWrapper provides a JavaScript wrapper around OpCode.
+type opWrapper struct {
+ op vm.OpCode
+}
+
+// pushObject assembles a JSVM object wrapping a swappable opcode and pushes it
+// onto the VM stack.
+func (ow *opWrapper) pushObject(vm *duktape.Context) {
+ obj := vm.PushObject()
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(int(ow.op)); return 1 })
+ vm.PutPropString(obj, "toNumber")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushString(ow.op.String()); return 1 })
+ vm.PutPropString(obj, "toString")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushBoolean(ow.op.IsPush()); return 1 })
+ vm.PutPropString(obj, "isPush")
+}
+
+// memoryWrapper provides a JavaScript wrapper around vm.Memory.
+type memoryWrapper struct {
+ memory *vm.Memory
+}
+
+// slice returns the requested range of memory as a byte slice.
+func (mw *memoryWrapper) slice(begin, end int64) []byte {
+ if end == begin {
+ return []byte{}
+ }
+ if end < begin || begin < 0 {
+ // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
+ // runtime goes belly up https://github.com/golang/go/issues/15639.
+ log.Warn("Tracer accessed out of bound memory", "offset", begin, "end", end)
+ return nil
+ }
+ if mw.memory.Len() < int(end) {
+ // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
+ // runtime goes belly up https://github.com/golang/go/issues/15639.
+ log.Warn("Tracer accessed out of bound memory", "available", mw.memory.Len(), "offset", begin, "size", end-begin)
+ return nil
+ }
+ return mw.memory.GetCopy(begin, end-begin)
+}
+
+// getUint returns the 32 bytes at the specified address interpreted as a uint.
+func (mw *memoryWrapper) getUint(addr int64) *big.Int {
+ if mw.memory.Len() < int(addr)+32 || addr < 0 {
+ // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
+ // runtime goes belly up https://github.com/golang/go/issues/15639.
+ log.Warn("Tracer accessed out of bound memory", "available", mw.memory.Len(), "offset", addr, "size", 32)
+ return new(big.Int)
+ }
+ return new(big.Int).SetBytes(mw.memory.GetPtr(addr, 32))
+}
+
+// pushObject assembles a JSVM object wrapping a swappable memory and pushes it
+// onto the VM stack.
+func (mw *memoryWrapper) pushObject(vm *duktape.Context) {
+ obj := vm.PushObject()
+
+ // Generate the `slice` method which takes two ints and returns a buffer
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ blob := mw.slice(int64(ctx.GetInt(-2)), int64(ctx.GetInt(-1)))
+ ctx.Pop2()
+
+ ptr := ctx.PushFixedBuffer(len(blob))
+ copy(makeSlice(ptr, uint(len(blob))), blob)
+ return 1
+ })
+ vm.PutPropString(obj, "slice")
+
+ // Generate the `getUint` method which takes an int and returns a bigint
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ offset := int64(ctx.GetInt(-1))
+ ctx.Pop()
+
+ pushBigInt(mw.getUint(offset), ctx)
+ return 1
+ })
+ vm.PutPropString(obj, "getUint")
+}
+
+// stackWrapper provides a JavaScript wrapper around vm.Stack.
+type stackWrapper struct {
+ stack *vm.Stack
+}
+
+// peek returns the nth-from-the-top element of the stack.
+func (sw *stackWrapper) peek(idx int) *big.Int {
+ if len(sw.stack.Data()) <= idx || idx < 0 {
+ // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
+ // runtime goes belly up https://github.com/golang/go/issues/15639.
+ log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data()), "index", idx)
+ return new(big.Int)
+ }
+ return sw.stack.Back(idx).ToBig()
+}
+
+// pushObject assembles a JSVM object wrapping a swappable stack and pushes it
+// onto the VM stack.
+func (sw *stackWrapper) pushObject(vm *duktape.Context) {
+ obj := vm.PushObject()
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(len(sw.stack.Data())); return 1 })
+ vm.PutPropString(obj, "length")
+
+ // Generate the `peek` method which takes an int and returns a bigint
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ offset := ctx.GetInt(-1)
+ ctx.Pop()
+
+ pushBigInt(sw.peek(offset), ctx)
+ return 1
+ })
+ vm.PutPropString(obj, "peek")
+}
+
+// dbWrapper provides a JavaScript wrapper around vm.Database.
+type dbWrapper struct {
+ db vm.StateDB
+}
+
+// pushObject assembles a JSVM object wrapping a swappable database and pushes it
+// onto the VM stack.
+func (dw *dbWrapper) pushObject(vm *duktape.Context) {
+ obj := vm.PushObject()
+
+ // Push the wrapper for statedb.GetBalance
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ pushBigInt(dw.db.GetBalance(common.BytesToAddress(popSlice(ctx))), ctx)
+ return 1
+ })
+ vm.PutPropString(obj, "getBalance")
+
+ // Push the wrapper for statedb.GetNonce
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ ctx.PushInt(int(dw.db.GetNonce(common.BytesToAddress(popSlice(ctx)))))
+ return 1
+ })
+ vm.PutPropString(obj, "getNonce")
+
+ // Push the wrapper for statedb.GetCode
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ code := dw.db.GetCode(common.BytesToAddress(popSlice(ctx)))
+
+ ptr := ctx.PushFixedBuffer(len(code))
+ copy(makeSlice(ptr, uint(len(code))), code)
+ return 1
+ })
+ vm.PutPropString(obj, "getCode")
+
+ // Push the wrapper for statedb.GetState
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ hash := popSlice(ctx)
+ addr := popSlice(ctx)
+
+ state := dw.db.GetState(common.BytesToAddress(addr), common.BytesToHash(hash))
+
+ ptr := ctx.PushFixedBuffer(len(state))
+ copy(makeSlice(ptr, uint(len(state))), state[:])
+ return 1
+ })
+ vm.PutPropString(obj, "getState")
+
+ // Push the wrapper for statedb.Exists
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ ctx.PushBoolean(dw.db.Exist(common.BytesToAddress(popSlice(ctx))))
+ return 1
+ })
+ vm.PutPropString(obj, "exists")
+}
+
+// contractWrapper provides a JavaScript wrapper around vm.Contract
+type contractWrapper struct {
+ contract *vm.Contract
+}
+
+// pushObject assembles a JSVM object wrapping a swappable contract and pushes it
+// onto the VM stack.
+func (cw *contractWrapper) pushObject(vm *duktape.Context) {
+ obj := vm.PushObject()
+
+ // Push the wrapper for contract.Caller
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ ptr := ctx.PushFixedBuffer(20)
+ copy(makeSlice(ptr, 20), cw.contract.Caller().Bytes())
+ return 1
+ })
+ vm.PutPropString(obj, "getCaller")
+
+ // Push the wrapper for contract.Address
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ ptr := ctx.PushFixedBuffer(20)
+ copy(makeSlice(ptr, 20), cw.contract.Address().Bytes())
+ return 1
+ })
+ vm.PutPropString(obj, "getAddress")
+
+ // Push the wrapper for contract.Value
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ pushBigInt(cw.contract.Value(), ctx)
+ return 1
+ })
+ vm.PutPropString(obj, "getValue")
+
+ // Push the wrapper for contract.Input
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ blob := cw.contract.Input
+
+ ptr := ctx.PushFixedBuffer(len(blob))
+ copy(makeSlice(ptr, uint(len(blob))), blob)
+ return 1
+ })
+ vm.PutPropString(obj, "getInput")
+}
+
+type frame struct {
+ typ *string
+ from *common.Address
+ to *common.Address
+ input []byte
+ gas *uint
+ value *big.Int
+}
+
+func newFrame() *frame {
+ return &frame{
+ typ: new(string),
+ from: new(common.Address),
+ to: new(common.Address),
+ gas: new(uint),
+ }
+}
+
+func (f *frame) pushObject(vm *duktape.Context) {
+ obj := vm.PushObject()
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { pushValue(ctx, *f.typ); return 1 })
+ vm.PutPropString(obj, "getType")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { pushValue(ctx, *f.from); return 1 })
+ vm.PutPropString(obj, "getFrom")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { pushValue(ctx, *f.to); return 1 })
+ vm.PutPropString(obj, "getTo")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { pushValue(ctx, f.input); return 1 })
+ vm.PutPropString(obj, "getInput")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { pushValue(ctx, *f.gas); return 1 })
+ vm.PutPropString(obj, "getGas")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ if f.value != nil {
+ pushValue(ctx, f.value)
+ } else {
+ ctx.PushUndefined()
+ }
+ return 1
+ })
+ vm.PutPropString(obj, "getValue")
+}
+
+type frameResult struct {
+ gasUsed *uint
+ output []byte
+ errorValue *string
+}
+
+func newFrameResult() *frameResult {
+ return &frameResult{
+ gasUsed: new(uint),
+ }
+}
+
+func (r *frameResult) pushObject(vm *duktape.Context) {
+ obj := vm.PushObject()
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { pushValue(ctx, *r.gasUsed); return 1 })
+ vm.PutPropString(obj, "getGasUsed")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int { pushValue(ctx, r.output); return 1 })
+ vm.PutPropString(obj, "getOutput")
+
+ vm.PushGoFunction(func(ctx *duktape.Context) int {
+ if r.errorValue != nil {
+ pushValue(ctx, *r.errorValue)
+ } else {
+ ctx.PushUndefined()
+ }
+ return 1
+ })
+ vm.PutPropString(obj, "getError")
+}
+
+// jsTracer provides an implementation of Tracer that evaluates a Javascript
+// function for each VM execution step.
+type jsTracer struct {
+ vm *duktape.Context // Javascript VM instance
+ env *vm.EVM // EVM instance executing the code being traced
+
+ tracerObject int // Stack index of the tracer JavaScript object
+ stateObject int // Stack index of the global state to pull arguments from
+
+ opWrapper *opWrapper // Wrapper around the VM opcode
+ stackWrapper *stackWrapper // Wrapper around the VM stack
+ memoryWrapper *memoryWrapper // Wrapper around the VM memory
+ contractWrapper *contractWrapper // Wrapper around the contract object
+ dbWrapper *dbWrapper // Wrapper around the VM environment
+
+ pcValue *uint // Swappable pc value wrapped by a log accessor
+ gasValue *uint // Swappable gas value wrapped by a log accessor
+ costValue *uint // Swappable cost value wrapped by a log accessor
+ depthValue *uint // Swappable depth value wrapped by a log accessor
+ errorValue *string // Swappable error value wrapped by a log accessor
+ refundValue *uint // Swappable refund value wrapped by a log accessor
+
+ frame *frame // Represents entry into call frame. Fields are swappable
+ frameResult *frameResult // Represents exit from a call frame. Fields are swappable
+
+ ctx map[string]interface{} // Transaction context gathered throughout execution
+ err error // Error, if one has occurred
+
+ interrupt uint32 // Atomic flag to signal execution interruption
+ reason error // Textual reason for the interruption
+
+ activePrecompiles []common.Address // Updated on CaptureStart based on given rules
+ traceSteps bool // When true, will invoke step() on each opcode
+ traceCallFrames bool // When true, will invoke enter() and exit() js funcs
+}
+
+// New instantiates a new tracer instance. code specifies a Javascript snippet,
+// which must evaluate to an expression returning an object with 'step', 'fault'
+// and 'result' functions.
+func newJsTracer(code string, ctx *tracers2.Context) (tracers2.Tracer, error) {
+ if c, ok := assetTracers[code]; ok {
+ code = c
+ }
+ if ctx == nil {
+ ctx = new(tracers2.Context)
+ }
+ tracer := &jsTracer{
+ vm: duktape.New(),
+ ctx: make(map[string]interface{}),
+ opWrapper: new(opWrapper),
+ stackWrapper: new(stackWrapper),
+ memoryWrapper: new(memoryWrapper),
+ contractWrapper: new(contractWrapper),
+ dbWrapper: new(dbWrapper),
+ pcValue: new(uint),
+ gasValue: new(uint),
+ costValue: new(uint),
+ depthValue: new(uint),
+ refundValue: new(uint),
+ frame: newFrame(),
+ frameResult: newFrameResult(),
+ }
+ if ctx.BlockHash != (common.Hash{}) {
+ tracer.ctx["blockHash"] = ctx.BlockHash
+
+ if ctx.TxHash != (common.Hash{}) {
+ tracer.ctx["txIndex"] = ctx.TxIndex
+ tracer.ctx["txHash"] = ctx.TxHash
+ }
+ }
+ // Set up builtins for this environment
+ tracer.vm.PushGlobalGoFunction("toHex", func(ctx *duktape.Context) int {
+ ctx.PushString(hexutil.Encode(popSlice(ctx)))
+ return 1
+ })
+ tracer.vm.PushGlobalGoFunction("toWord", func(ctx *duktape.Context) int {
+ var word common.Hash
+ if ptr, size := ctx.GetBuffer(-1); ptr != nil {
+ word = common.BytesToHash(makeSlice(ptr, size))
+ } else {
+ word = common.HexToHash(ctx.GetString(-1))
+ }
+ ctx.Pop()
+ copy(makeSlice(ctx.PushFixedBuffer(32), 32), word[:])
+ return 1
+ })
+ tracer.vm.PushGlobalGoFunction("toAddress", func(ctx *duktape.Context) int {
+ var addr common.Address
+ if ptr, size := ctx.GetBuffer(-1); ptr != nil {
+ addr = common.BytesToAddress(makeSlice(ptr, size))
+ } else {
+ addr = common.HexToAddress(ctx.GetString(-1))
+ }
+ ctx.Pop()
+ copy(makeSlice(ctx.PushFixedBuffer(20), 20), addr[:])
+ return 1
+ })
+ tracer.vm.PushGlobalGoFunction("toContract", func(ctx *duktape.Context) int {
+ var from common.Address
+ if ptr, size := ctx.GetBuffer(-2); ptr != nil {
+ from = common.BytesToAddress(makeSlice(ptr, size))
+ } else {
+ from = common.HexToAddress(ctx.GetString(-2))
+ }
+ nonce := uint64(ctx.GetInt(-1))
+ ctx.Pop2()
+
+ contract := crypto.CreateAddress(from, nonce)
+ copy(makeSlice(ctx.PushFixedBuffer(20), 20), contract[:])
+ return 1
+ })
+ tracer.vm.PushGlobalGoFunction("toContract2", func(ctx *duktape.Context) int {
+ var from common.Address
+ if ptr, size := ctx.GetBuffer(-3); ptr != nil {
+ from = common.BytesToAddress(makeSlice(ptr, size))
+ } else {
+ from = common.HexToAddress(ctx.GetString(-3))
+ }
+ // Retrieve salt hex string from js stack
+ salt := common.HexToHash(ctx.GetString(-2))
+ // Retrieve code slice from js stack
+ var code []byte
+ if ptr, size := ctx.GetBuffer(-1); ptr != nil {
+ code = common.CopyBytes(makeSlice(ptr, size))
+ } else {
+ code = common.FromHex(ctx.GetString(-1))
+ }
+ codeHash := crypto.Keccak256(code)
+ ctx.Pop3()
+ contract := crypto.CreateAddress2(from, salt, codeHash)
+ copy(makeSlice(ctx.PushFixedBuffer(20), 20), contract[:])
+ return 1
+ })
+ tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int {
+ addr := common.BytesToAddress(popSlice(ctx))
+ for _, p := range tracer.activePrecompiles {
+ if p == addr {
+ ctx.PushBoolean(true)
+ return 1
+ }
+ }
+ ctx.PushBoolean(false)
+ return 1
+ })
+ tracer.vm.PushGlobalGoFunction("slice", func(ctx *duktape.Context) int {
+ start, end := ctx.GetInt(-2), ctx.GetInt(-1)
+ ctx.Pop2()
+
+ blob := popSlice(ctx)
+ size := end - start
+
+ if start < 0 || start > end || end > len(blob) {
+ // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
+ // runtime goes belly up https://github.com/golang/go/issues/15639.
+ log.Warn("Tracer accessed out of bound memory", "available", len(blob), "offset", start, "size", size)
+ ctx.PushFixedBuffer(0)
+ return 1
+ }
+ copy(makeSlice(ctx.PushFixedBuffer(size), uint(size)), blob[start:end])
+ return 1
+ })
+ // Push the JavaScript tracer as object #0 onto the JSVM stack and validate it
+ if err := tracer.vm.PevalString("(" + code + ")"); err != nil {
+ log.Warn("Failed to compile tracer", "err", err)
+ return nil, err
+ }
+ tracer.tracerObject = 0 // yeah, nice, eval can't return the index itself
+
+ hasStep := tracer.vm.GetPropString(tracer.tracerObject, "step")
+ tracer.vm.Pop()
+
+ if !tracer.vm.GetPropString(tracer.tracerObject, "fault") {
+ return nil, fmt.Errorf("trace object must expose a function fault()")
+ }
+ tracer.vm.Pop()
+
+ if !tracer.vm.GetPropString(tracer.tracerObject, "result") {
+ return nil, fmt.Errorf("trace object must expose a function result()")
+ }
+ tracer.vm.Pop()
+
+ hasEnter := tracer.vm.GetPropString(tracer.tracerObject, "enter")
+ tracer.vm.Pop()
+ hasExit := tracer.vm.GetPropString(tracer.tracerObject, "exit")
+ tracer.vm.Pop()
+ if hasEnter != hasExit {
+ return nil, fmt.Errorf("trace object must expose either both or none of enter() and exit()")
+ }
+ tracer.traceCallFrames = hasEnter && hasExit
+ tracer.traceSteps = hasStep
+
+ // Tracer is valid, inject the big int library to access large numbers
+ tracer.vm.EvalString(bigIntegerJS)
+ tracer.vm.PutGlobalString("bigInt")
+
+ // Push the global environment state as object #1 into the JSVM stack
+ tracer.stateObject = tracer.vm.PushObject()
+
+ logObject := tracer.vm.PushObject()
+
+ tracer.opWrapper.pushObject(tracer.vm)
+ tracer.vm.PutPropString(logObject, "op")
+
+ tracer.stackWrapper.pushObject(tracer.vm)
+ tracer.vm.PutPropString(logObject, "stack")
+
+ tracer.memoryWrapper.pushObject(tracer.vm)
+ tracer.vm.PutPropString(logObject, "memory")
+
+ tracer.contractWrapper.pushObject(tracer.vm)
+ tracer.vm.PutPropString(logObject, "contract")
+
+ tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.pcValue); return 1 })
+ tracer.vm.PutPropString(logObject, "getPC")
+
+ tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.gasValue); return 1 })
+ tracer.vm.PutPropString(logObject, "getGas")
+
+ tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.costValue); return 1 })
+ tracer.vm.PutPropString(logObject, "getCost")
+
+ tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.depthValue); return 1 })
+ tracer.vm.PutPropString(logObject, "getDepth")
+
+ tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.refundValue); return 1 })
+ tracer.vm.PutPropString(logObject, "getRefund")
+
+ tracer.vm.PushGoFunction(func(ctx *duktape.Context) int {
+ if tracer.errorValue != nil {
+ ctx.PushString(*tracer.errorValue)
+ } else {
+ ctx.PushUndefined()
+ }
+ return 1
+ })
+ tracer.vm.PutPropString(logObject, "getError")
+
+ tracer.vm.PutPropString(tracer.stateObject, "log")
+
+ tracer.frame.pushObject(tracer.vm)
+ tracer.vm.PutPropString(tracer.stateObject, "frame")
+
+ tracer.frameResult.pushObject(tracer.vm)
+ tracer.vm.PutPropString(tracer.stateObject, "frameResult")
+
+ tracer.dbWrapper.pushObject(tracer.vm)
+ tracer.vm.PutPropString(tracer.stateObject, "db")
+
+ return tracer, nil
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (jst *jsTracer) Stop(err error) {
+ jst.reason = err
+ atomic.StoreUint32(&jst.interrupt, 1)
+}
+
+// call executes a method on a JS object, catching any errors, formatting and
+// returning them as error objects.
+func (jst *jsTracer) call(noret bool, method string, args ...string) (json.RawMessage, error) {
+ // Execute the JavaScript call and return any error
+ jst.vm.PushString(method)
+ for _, arg := range args {
+ jst.vm.GetPropString(jst.stateObject, arg)
+ }
+ code := jst.vm.PcallProp(jst.tracerObject, len(args))
+ defer jst.vm.Pop()
+
+ if code != 0 {
+ err := jst.vm.SafeToString(-1)
+ return nil, errors.New(err)
+ }
+ // No error occurred, extract return value and return
+ if noret {
+ return nil, nil
+ }
+ // Push a JSON marshaller onto the stack. We can't marshal from the out-
+ // side because duktape can crash on large nestings and we can't catch
+ // C++ exceptions ourselves from Go. TODO(karalabe): Yuck, why wrap?!
+ jst.vm.PushString("(JSON.stringify)")
+ jst.vm.Eval()
+
+ jst.vm.Swap(-1, -2)
+ if code = jst.vm.Pcall(1); code != 0 {
+ err := jst.vm.SafeToString(-1)
+ return nil, errors.New(err)
+ }
+ return json.RawMessage(jst.vm.SafeToString(-1)), nil
+}
+
+func wrapError(context string, err error) error {
+ return fmt.Errorf("%v in server-side tracer function '%v'", err, context)
+}
+
+// CaptureStart implements the Tracer interface to initialize the tracing operation.
+func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ jst.env = env
+ jst.ctx["type"] = "CALL"
+ if create {
+ jst.ctx["type"] = "CREATE"
+ }
+ jst.ctx["from"] = from
+ jst.ctx["to"] = to
+ jst.ctx["input"] = input
+ jst.ctx["gas"] = gas
+ jst.ctx["gasPrice"] = env.TxContext.GasPrice
+ jst.ctx["value"] = value
+
+ // Initialize the context
+ jst.ctx["block"] = env.Context.BlockNumber.Uint64()
+ jst.dbWrapper.db = env.StateDB
+ // Update list of precompiles based on current block
+ rules := env.ChainConfig().Rules(env.Context.BlockNumber)
+ jst.activePrecompiles = vm.ActivePrecompiles(rules)
+
+ // Compute intrinsic gas
+ isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber)
+ isIstanbul := env.ChainConfig().IsIstanbul(env.Context.BlockNumber)
+ intrinsicGas, err := core.IntrinsicGas(input, nil, jst.ctx["type"] == "CREATE", isHomestead, isIstanbul)
+ if err != nil {
+ return
+ }
+ jst.ctx["intrinsicGas"] = intrinsicGas
+}
+
+// CaptureState implements the Tracer interface to trace a single step of VM execution.
+func (jst *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ if !jst.traceSteps {
+ return
+ }
+ if jst.err != nil {
+ return
+ }
+ // If tracing was interrupted, set the error and stop
+ if atomic.LoadUint32(&jst.interrupt) > 0 {
+ jst.err = jst.reason
+ jst.env.Cancel()
+ return
+ }
+ jst.opWrapper.op = op
+ jst.stackWrapper.stack = scope.Stack
+ jst.memoryWrapper.memory = scope.Memory
+ jst.contractWrapper.contract = scope.Contract
+
+ *jst.pcValue = uint(pc)
+ *jst.gasValue = uint(gas)
+ *jst.costValue = uint(cost)
+ *jst.depthValue = uint(depth)
+ *jst.refundValue = uint(jst.env.StateDB.GetRefund())
+
+ jst.errorValue = nil
+ if err != nil {
+ jst.errorValue = new(string)
+ *jst.errorValue = err.Error()
+ }
+
+ if _, err := jst.call(true, "step", "log", "db"); err != nil {
+ jst.err = wrapError("step", err)
+ }
+}
+
+// CaptureFault implements the Tracer interface to trace an execution fault
+func (jst *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+ if jst.err != nil {
+ return
+ }
+ // Apart from the error, everything matches the previous invocation
+ jst.errorValue = new(string)
+ *jst.errorValue = err.Error()
+
+ if _, err := jst.call(true, "fault", "log", "db"); err != nil {
+ jst.err = wrapError("fault", err)
+ }
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (jst *jsTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
+ jst.ctx["output"] = output
+ jst.ctx["time"] = t.String()
+ jst.ctx["gasUsed"] = gasUsed
+
+ if err != nil {
+ jst.ctx["error"] = err.Error()
+ }
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (jst *jsTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ if !jst.traceCallFrames {
+ return
+ }
+ if jst.err != nil {
+ return
+ }
+ // If tracing was interrupted, set the error and stop
+ if atomic.LoadUint32(&jst.interrupt) > 0 {
+ jst.err = jst.reason
+ return
+ }
+
+ *jst.frame.typ = typ.String()
+ *jst.frame.from = from
+ *jst.frame.to = to
+ jst.frame.input = common.CopyBytes(input)
+ *jst.frame.gas = uint(gas)
+ jst.frame.value = nil
+ if value != nil {
+ jst.frame.value = new(big.Int).SetBytes(value.Bytes())
+ }
+
+ if _, err := jst.call(true, "enter", "frame"); err != nil {
+ jst.err = wrapError("enter", err)
+ }
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (jst *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+ if !jst.traceCallFrames {
+ return
+ }
+ // If tracing was interrupted, set the error and stop
+ if atomic.LoadUint32(&jst.interrupt) > 0 {
+ jst.err = jst.reason
+ return
+ }
+
+ jst.frameResult.output = common.CopyBytes(output)
+ *jst.frameResult.gasUsed = uint(gasUsed)
+ jst.frameResult.errorValue = nil
+ if err != nil {
+ jst.frameResult.errorValue = new(string)
+ *jst.frameResult.errorValue = err.Error()
+ }
+
+ if _, err := jst.call(true, "exit", "frameResult"); err != nil {
+ jst.err = wrapError("exit", err)
+ }
+}
+
+// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error
+func (jst *jsTracer) GetResult() (json.RawMessage, error) {
+ // Transform the context into a JavaScript object and inject into the state
+ obj := jst.vm.PushObject()
+
+ for key, val := range jst.ctx {
+ jst.addToObj(obj, key, val)
+ }
+ jst.vm.PutPropString(jst.stateObject, "ctx")
+
+ // Finalize the trace and return the results
+ result, err := jst.call(false, "result", "ctx", "db")
+ if err != nil {
+ jst.err = wrapError("result", err)
+ }
+ // Clean up the JavaScript environment
+ jst.vm.DestroyHeap()
+ jst.vm.Destroy()
+
+ return result, jst.err
+}
+
+// addToObj pushes a field to a JS object.
+func (jst *jsTracer) addToObj(obj int, key string, val interface{}) {
+ pushValue(jst.vm, val)
+ jst.vm.PutPropString(obj, key)
+}
+
+func pushValue(ctx *duktape.Context, val interface{}) {
+ switch val := val.(type) {
+ case uint64:
+ ctx.PushUint(uint(val))
+ case string:
+ ctx.PushString(val)
+ case []byte:
+ ptr := ctx.PushFixedBuffer(len(val))
+ copy(makeSlice(ptr, uint(len(val))), val)
+ case common.Address:
+ ptr := ctx.PushFixedBuffer(20)
+ copy(makeSlice(ptr, 20), val[:])
+ case *big.Int:
+ pushBigInt(val, ctx)
+ case int:
+ ctx.PushInt(val)
+ case uint:
+ ctx.PushUint(val)
+ case common.Hash:
+ ptr := ctx.PushFixedBuffer(32)
+ copy(makeSlice(ptr, 32), val[:])
+ default:
+ panic(fmt.Sprintf("unsupported type: %T", val))
+ }
+}
diff --git a/eth/tracers/tracer_test.go b/eth/tracers/js/tracer_test.go
similarity index 51%
rename from eth/tracers/tracer_test.go
rename to eth/tracers/js/tracer_test.go
index 7cda2e533..2253ae597 100644
--- a/eth/tracers/tracer_test.go
+++ b/eth/tracers/js/tracer_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 .
-package tracers
+package js
import (
"encoding/json"
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
)
@@ -59,13 +60,13 @@ func testCtx() *vmContext {
return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
}
-func runTrace(tracer *Tracer, vmctx *vmContext) (json.RawMessage, error) {
- env := vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
+func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig) (json.RawMessage, error) {
var (
+ env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Debug: true, Tracer: tracer})
startGas uint64 = 10000
value = big.NewInt(0)
+ contract = vm.NewContract(account{}, account{}, value, startGas)
)
- contract := vm.NewContract(account{}, account{}, value, startGas)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
@@ -78,22 +79,22 @@ func runTrace(tracer *Tracer, vmctx *vmContext) (json.RawMessage, error) {
}
func TestTracer(t *testing.T) {
- execTracer := func(code string) []byte {
+ execTracer := func(code string) ([]byte, string) {
t.Helper()
- ctx := &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
- tracer, err := New(code, ctx.txCtx)
+ tracer, err := newJsTracer(code, nil)
if err != nil {
t.Fatal(err)
}
- ret, err := runTrace(tracer, ctx)
+ ret, err := runTrace(tracer, testCtx(), params.TestChainConfig)
if err != nil {
- t.Fatal(err)
+ return nil, err.Error() // Stringify to allow comparison without nil checks
}
- return ret
+ return ret, ""
}
for i, tt := range []struct {
code string
want string
+ fail string
}{
{ // tests that we don't panic on bad arguments to memory access
code: "{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}",
@@ -116,49 +117,47 @@ func TestTracer(t *testing.T) {
}, { // tests intrinsic gas
code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed+'.'+ctx.intrinsicGas; }}",
want: `"100000.6.21000"`,
+ }, { // tests too deep object / serialization crash
+ code: "{step: function() {}, fault: function() {}, result: function() { var o={}; var x=o; for (var i=0; i<1000; i++){ o.foo={}; o=o.foo; } return x; }}",
+ fail: "RangeError: json encode recursion limit in server-side tracer function 'result'",
},
} {
- if have := execTracer(tt.code); tt.want != string(have) {
- t.Errorf("testcase %d: expected return value to be %s got %s\n\tcode: %v", i, tt.want, string(have), tt.code)
+ if have, err := execTracer(tt.code); tt.want != string(have) || tt.fail != err {
+ t.Errorf("testcase %d: expected return value to be '%s' got '%s', error to be '%s' got '%s'\n\tcode: %v", i, tt.want, string(have), tt.fail, err, tt.code)
}
}
}
func TestHalt(t *testing.T) {
t.Skip("duktape doesn't support abortion")
-
timeout := errors.New("stahp")
- vmctx := testCtx()
- tracer, err := New("{step: function() { while(1); }, result: function() { return null; }}", vmctx.txCtx)
+ tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil)
if err != nil {
t.Fatal(err)
}
-
go func() {
time.Sleep(1 * time.Second)
tracer.Stop(timeout)
}()
-
- if _, err = runTrace(tracer, vmctx); err.Error() != "stahp in server-side tracer function 'step'" {
+ if _, err = runTrace(tracer, testCtx(), params.TestChainConfig); err.Error() != "stahp in server-side tracer function 'step'" {
t.Errorf("Expected timeout error, got %v", err)
}
}
func TestHaltBetweenSteps(t *testing.T) {
- vmctx := testCtx()
- tracer, err := New("{step: function() {}, fault: function() {}, result: function() { return null; }}", vmctx.txCtx)
+ tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil)
if err != nil {
t.Fatal(err)
}
- env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
+ env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(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),
}
-
- tracer.CaptureState(env, 0, 0, 0, 0, scope, nil, 0, nil)
+ tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 0, big.NewInt(0))
+ tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
timeout := errors.New("stahp")
tracer.Stop(timeout)
- tracer.CaptureState(env, 0, 0, 0, 0, scope, nil, 0, nil)
+ tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
if _, err := tracer.GetResult(); err.Error() != timeout.Error() {
t.Errorf("Expected timeout error, got %v", err)
@@ -168,22 +167,16 @@ func TestHaltBetweenSteps(t *testing.T) {
// TestNoStepExec tests a regular value transfer (no exec), and accessing the statedb
// in 'result'
func TestNoStepExec(t *testing.T) {
- runEmptyTrace := func(tracer *Tracer, vmctx *vmContext) (json.RawMessage, error) {
- env := vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
- startGas := uint64(10000)
- contract := vm.NewContract(account{}, account{}, big.NewInt(0), startGas)
- tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, big.NewInt(0))
- tracer.CaptureEnd(nil, startGas-contract.Gas, 1, nil)
- return tracer.GetResult()
- }
execTracer := func(code string) []byte {
t.Helper()
- ctx := &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
- tracer, err := New(code, ctx.txCtx)
+ tracer, err := newJsTracer(code, nil)
if err != nil {
t.Fatal(err)
}
- ret, err := runEmptyTrace(tracer, ctx)
+ env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(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, 1, nil)
+ ret, err := tracer.GetResult()
if err != nil {
t.Fatal(err)
}
@@ -203,3 +196,63 @@ func TestNoStepExec(t *testing.T) {
}
}
}
+
+func TestIsPrecompile(t *testing.T) {
+ chaincfg := ¶ms.ChainConfig{ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, EIP150Block: big.NewInt(0), EIP150Hash: common.Hash{}, EIP155Block: big.NewInt(0), EIP158Block: big.NewInt(0), ByzantiumBlock: big.NewInt(100), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(200), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(300), CatalystBlock: nil, Ethash: new(params.EthashConfig), Clique: nil}
+ chaincfg.ByzantiumBlock = big.NewInt(100)
+ chaincfg.IstanbulBlock = big.NewInt(200)
+ chaincfg.BerlinBlock = big.NewInt(300)
+ txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
+ tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150)}
+ res, err := runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg)
+ if err != nil {
+ t.Error(err)
+ }
+ if string(res) != "false" {
+ t.Errorf("Tracer should not consider blake2f as precompile in byzantium")
+ }
+
+ tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil)
+ blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)}
+ res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg)
+ if err != nil {
+ t.Error(err)
+ }
+ if string(res) != "true" {
+ t.Errorf("Tracer should consider blake2f as precompile in istanbul")
+ }
+}
+
+func TestEnterExit(t *testing.T) {
+ // test that either both or none of enter() and exit() are defined
+ if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context)); err == nil {
+ t.Fatal("tracer creation should've failed without exit() definition")
+ }
+ if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context)); err != nil {
+ t.Fatal(err)
+ }
+ // test that the enter and exit method are correctly invoked and the values passed
+ tracer, err := newJsTracer("{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, step: function() {}, fault: function() {}, result: function() { return {enters: this.enters, exits: this.exits, enterGas: this.enterGas, gasUsed: this.gasUsed} }, enter: function(frame) { this.enters++; this.enterGas = frame.getGas(); }, exit: function(res) { this.exits++; this.gasUsed = res.getGasUsed(); }}", new(tracers.Context))
+ if err != nil {
+ t.Fatal(err)
+ }
+ scope := &vm.ScopeContext{
+ Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ }
+ tracer.CaptureEnter(vm.CALL, scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
+ tracer.CaptureExit([]byte{}, 400, nil)
+
+ have, err := tracer.GetResult()
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := `{"enters":1,"exits":1,"enterGas":1000,"gasUsed":400}`
+ if string(have) != want {
+ t.Errorf("Number of invocations of enter() and exit() is wrong. Have %s, want %s\n", have, want)
+ }
+}
diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go
new file mode 100644
index 000000000..16ea75aa4
--- /dev/null
+++ b/eth/tracers/native/call.go
@@ -0,0 +1,182 @@
+// 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 native
+
+import (
+ "encoding/json"
+ "errors"
+ "math/big"
+ "strconv"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+)
+
+func init() {
+ register("callTracer", newCallTracer)
+}
+
+type callFrame struct {
+ Type string `json:"type"`
+ From string `json:"from"`
+ To string `json:"to,omitempty"`
+ Value string `json:"value,omitempty"`
+ Gas string `json:"gas"`
+ GasUsed string `json:"gasUsed"`
+ Input string `json:"input"`
+ Output string `json:"output,omitempty"`
+ Error string `json:"error,omitempty"`
+ Calls []callFrame `json:"calls,omitempty"`
+}
+
+type callTracer struct {
+ env *vm.EVM
+ callstack []callFrame
+ interrupt uint32 // Atomic flag to signal execution interruption
+ reason error // Textual reason for the interruption
+}
+
+// newCallTracer returns a native go tracer which tracks
+// call frames of a tx, and implements vm.EVMLogger.
+func newCallTracer() tracers.Tracer {
+ // First callframe contains tx context info
+ // and is populated on start and end.
+ t := &callTracer{callstack: make([]callFrame, 1)}
+ return t
+}
+
+// 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) {
+ t.env = env
+ t.callstack[0] = callFrame{
+ Type: "CALL",
+ From: addrToHex(from),
+ To: addrToHex(to),
+ Input: bytesToHex(input),
+ Gas: uintToHex(gas),
+ Value: bigToHex(value),
+ }
+ if create {
+ t.callstack[0].Type = "CREATE"
+ }
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
+ t.callstack[0].GasUsed = uintToHex(gasUsed)
+ if err != nil {
+ t.callstack[0].Error = err.Error()
+ if err.Error() == "execution reverted" && len(output) > 0 {
+ t.callstack[0].Output = bytesToHex(output)
+ }
+ } else {
+ t.callstack[0].Output = bytesToHex(output)
+ }
+}
+
+// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
+func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault.
+func (t *callTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ // Skip if tracing was interrupted
+ if atomic.LoadUint32(&t.interrupt) > 0 {
+ t.env.Cancel()
+ return
+ }
+
+ call := callFrame{
+ Type: typ.String(),
+ From: addrToHex(from),
+ To: addrToHex(to),
+ Input: bytesToHex(input),
+ Gas: uintToHex(gas),
+ Value: bigToHex(value),
+ }
+ t.callstack = append(t.callstack, call)
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+ size := len(t.callstack)
+ if size <= 1 {
+ return
+ }
+ // pop call
+ call := t.callstack[size-1]
+ t.callstack = t.callstack[:size-1]
+ size -= 1
+
+ call.GasUsed = uintToHex(gasUsed)
+ if err == nil {
+ call.Output = bytesToHex(output)
+ } else {
+ call.Error = err.Error()
+ if call.Type == "CREATE" || call.Type == "CREATE2" {
+ call.To = ""
+ }
+ }
+ t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
+}
+
+// GetResult returns the json-encoded nested list of call traces, and any
+// error arising from the encoding or forceful termination (via `Stop`).
+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
+ }
+ return json.RawMessage(res), t.reason
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *callTracer) Stop(err error) {
+ t.reason = err
+ atomic.StoreUint32(&t.interrupt, 1)
+}
+
+func bytesToHex(s []byte) string {
+ return "0x" + common.Bytes2Hex(s)
+}
+
+func bigToHex(n *big.Int) string {
+ if n == nil {
+ return ""
+ }
+ return "0x" + n.Text(16)
+}
+
+func uintToHex(n uint64) string {
+ return "0x" + strconv.FormatUint(n, 16)
+}
+
+func addrToHex(a common.Address) string {
+ return strings.ToLower(a.Hex())
+}
diff --git a/eth/tracers/native/noop.go b/eth/tracers/native/noop.go
new file mode 100644
index 000000000..ee110ef7d
--- /dev/null
+++ b/eth/tracers/native/noop.go
@@ -0,0 +1,74 @@
+// 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 native
+
+import (
+ "encoding/json"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+)
+
+func init() {
+ register("noopTracerNative", newNoopTracer)
+}
+
+// noopTracer is a go implementation of the Tracer interface which
+// performs no action. It's mostly useful for testing purposes.
+type noopTracer struct{}
+
+// newNoopTracer returns a new noop tracer.
+func newNoopTracer() tracers.Tracer {
+ return &noopTracer{}
+}
+
+// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
+func (t *noopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+}
+
+// CaptureEnd is called after the call finishes to finalize the tracing.
+func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
+}
+
+// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
+func (t *noopTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+}
+
+// CaptureFault implements the EVMLogger interface to trace an execution fault.
+func (t *noopTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
+}
+
+// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *noopTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// execute any code.
+func (t *noopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+}
+
+// GetResult returns an empty json object.
+func (t *noopTracer) GetResult() (json.RawMessage, error) {
+ return json.RawMessage(`{}`), nil
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *noopTracer) Stop(err error) {
+}
diff --git a/eth/tracers/native/tracer.go b/eth/tracers/native/tracer.go
new file mode 100644
index 000000000..3158654f3
--- /dev/null
+++ b/eth/tracers/native/tracer.go
@@ -0,0 +1,79 @@
+// 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 native is a collection of tracers written in go.
+
+In order to add a native tracer and have it compiled into the binary, a new
+file needs to be added to this folder, containing an implementation of the
+`eth.tracers.Tracer` interface.
+
+Aside from implementing the tracer, it also needs to register itself, using the
+`register` method -- and this needs to be done in the package initialization.
+
+Example:
+
+```golang
+func init() {
+ register("noopTracerNative", newNoopTracer)
+}
+```
+*/
+package native
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/eth/tracers"
+)
+
+// init registers itself this packages as a lookup for tracers.
+func init() {
+ tracers.RegisterLookup(false, lookup)
+}
+
+/*
+ctors is a map of package-local tracer constructors.
+
+We cannot be certain about the order of init-functions within a package,
+The go spec (https://golang.org/ref/spec#Package_initialization) says
+
+> To ensure reproducible initialization behavior, build systems
+> are encouraged to present multiple files belonging to the same
+> package in lexical file name order to a compiler.
+
+Hence, we cannot make the map in init, but must make it upon first use.
+*/
+var ctors map[string]func() tracers.Tracer
+
+// register is used by native tracers to register their presence.
+func register(name string, ctor func() tracers.Tracer) {
+ if ctors == nil {
+ ctors = make(map[string]func() tracers.Tracer)
+ }
+ ctors[name] = ctor
+}
+
+// lookup returns a tracer, if one can be matched to the given name.
+func lookup(name string, ctx *tracers.Context) (tracers.Tracer, error) {
+ if ctors == nil {
+ ctors = make(map[string]func() tracers.Tracer)
+ }
+ if ctor, ok := ctors[name]; ok {
+ return ctor(), nil
+ }
+ return nil, errors.New("no tracer found")
+}
diff --git a/eth/tracers/tracers.go b/eth/tracers/tracers.go
index 4e1ef23ad..e7073e7d2 100644
--- a/eth/tracers/tracers.go
+++ b/eth/tracers/tracers.go
@@ -14,40 +14,59 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-// Package tracers is a collection of JavaScript transaction tracers.
+// Package tracers is a manager for transaction tracing engines.
package tracers
import (
- "strings"
- "unicode"
+ "encoding/json"
+ "errors"
- "github.com/ethereum/go-ethereum/eth/tracers/internal/tracers"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
)
-// all contains all the built in JavaScript tracers by name.
-var all = make(map[string]string)
+// 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)
+}
-// camel converts a snake cased input string into a camel cased output.
-func camel(str string) string {
- pieces := strings.Split(str, "_")
- for i := 1; i < len(pieces); i++ {
- pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:]
- }
- return strings.Join(pieces, "")
+// Tracer interface extends vm.EVMLogger and additionally
+// allows collecting the tracing result.
+type Tracer interface {
+ vm.EVMLogger
+ GetResult() (json.RawMessage, error)
+ // Stop terminates execution of the tracer at the first opportune moment.
+ Stop(err error)
}
-// init retrieves the JavaScript transaction tracers included in go-ethereum.
-func init() {
- for _, file := range tracers.AssetNames() {
- name := camel(strings.TrimSuffix(file, ".js"))
- all[name] = string(tracers.MustAsset(file))
+type lookupFunc func(string, *Context) (Tracer, error)
+
+var (
+ lookups []lookupFunc
+)
+
+// RegisterLookup registers a method as a lookup for tracers, meaning that
+// users can invoke a named tracer through that lookup. If 'wildcard' is true,
+// then the lookup will be placed last. This is typically meant for interpreted
+// engines (js) which can evaluate dynamic user-supplied code.
+func RegisterLookup(wildcard bool, lookup lookupFunc) {
+ if wildcard {
+ lookups = append(lookups, lookup)
+ } else {
+ lookups = append([]lookupFunc{lookup}, lookups...)
}
}
-// tracer retrieves a specific JavaScript tracer by name.
-func tracer(name string) (string, bool) {
- if tracer, ok := all[name]; ok {
- return tracer, true
+// New returns a new instance of a tracer, by iterating through the
+// registered lookups.
+func New(code string, ctx *Context) (Tracer, error) {
+ for _, lookup := range lookups {
+ if tracer, err := lookup(code, ctx); err == nil {
+ return tracer, nil
+ }
}
- return "", false
+ return nil, errors.New("tracer not found")
}
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index 0bc4cd81e..a3f5fc361 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -17,79 +17,20 @@
package tracers
import (
- "crypto/ecdsa"
- "crypto/rand"
- "encoding/json"
- "io/ioutil"
"math/big"
- "path/filepath"
- "reflect"
- "strings"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/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/crypto"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests"
)
-// To generate a new callTracer test, copy paste the makeTest method below into
-// a Geth console and call it with a transaction hash you which to export.
-
-/*
-// makeTest generates a callTracer test by running a prestate reassembled and a
-// call trace run, assembling all the gathered information into a test case.
-var makeTest = function(tx, rewind) {
- // Generate the genesis block from the block, transaction and prestate data
- var block = eth.getBlock(eth.getTransaction(tx).blockHash);
- var genesis = eth.getBlock(block.parentHash);
-
- delete genesis.gasUsed;
- delete genesis.logsBloom;
- delete genesis.parentHash;
- delete genesis.receiptsRoot;
- delete genesis.sha3Uncles;
- delete genesis.size;
- delete genesis.transactions;
- delete genesis.transactionsRoot;
- delete genesis.uncles;
-
- genesis.gasLimit = genesis.gasLimit.toString();
- genesis.number = genesis.number.toString();
- genesis.timestamp = genesis.timestamp.toString();
-
- genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer", rewind: rewind});
- for (var key in genesis.alloc) {
- genesis.alloc[key].nonce = genesis.alloc[key].nonce.toString();
- }
- genesis.config = admin.nodeInfo.protocols.eth.config;
-
- // Generate the call trace and produce the test input
- var result = debug.traceTransaction(tx, {tracer: "callTracer", rewind: rewind});
- delete result.time;
-
- console.log(JSON.stringify({
- genesis: genesis,
- context: {
- number: block.number.toString(),
- difficulty: block.difficulty,
- timestamp: block.timestamp.toString(),
- gasLimit: block.gasLimit.toString(),
- miner: block.miner,
- },
- input: eth.getRawTransaction(tx),
- result: result,
- }, null, 2));
-}
-*/
-
// callTrace is the result of a callTracer run.
type callTrace struct {
Type string `json:"type"`
@@ -104,203 +45,6 @@ type callTrace struct {
Calls []callTrace `json:"calls,omitempty"`
}
-type callContext struct {
- Number math.HexOrDecimal64 `json:"number"`
- Difficulty *math.HexOrDecimal256 `json:"difficulty"`
- Time math.HexOrDecimal64 `json:"timestamp"`
- GasLimit math.HexOrDecimal64 `json:"gasLimit"`
- Miner common.Address `json:"miner"`
-}
-
-// callTracerTest defines a single test to check the call tracer against.
-type callTracerTest struct {
- Genesis *core.Genesis `json:"genesis"`
- Context *callContext `json:"context"`
- Input string `json:"input"`
- Result *callTrace `json:"result"`
-}
-
-func TestPrestateTracerCreate2(t *testing.T) {
- unsignedTx := types.NewTransaction(1, common.HexToAddress("0x00000000000000000000000000000000deadbeef"),
- new(big.Int), 5000000, big.NewInt(1), []byte{})
-
- privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
- if err != nil {
- t.Fatalf("err %v", err)
- }
- signer := types.NewEIP155Signer(big.NewInt(1))
- tx, err := types.SignTx(unsignedTx, signer, privateKeyECDSA)
- if err != nil {
- t.Fatalf("err %v", err)
- }
- /**
- This comes from one of the test-vectors on the Skinny Create2 - EIP
-
- address 0x00000000000000000000000000000000deadbeef
- salt 0x00000000000000000000000000000000000000000000000000000000cafebabe
- init_code 0xdeadbeef
- gas (assuming no mem expansion): 32006
- result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7
- */
- origin, _ := signer.Sender(tx)
- txContext := vm.TxContext{
- Origin: origin,
- GasPrice: big.NewInt(1),
- }
- context := vm.BlockContext{
- CanTransfer: core.CanTransfer,
- Transfer: core.Transfer,
- Coinbase: common.Address{},
- BlockNumber: new(big.Int).SetUint64(8000000),
- Time: new(big.Int).SetUint64(5),
- Difficulty: big.NewInt(0x30000),
- GasLimit: uint64(6000000),
- }
- alloc := core.GenesisAlloc{}
-
- // The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
- // the address
- alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{
- Nonce: 1,
- Code: hexutil.MustDecode("0x63deadbeef60005263cafebabe6004601c6000F560005260206000F3"),
- Balance: big.NewInt(1),
- }
- alloc[origin] = core.GenesisAccount{
- Nonce: 1,
- Code: []byte{},
- Balance: big.NewInt(500000000000000),
- }
- _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false)
-
- // Create the tracer, the EVM environment and run it
- tracer, err := New("prestateTracer", txContext)
- if err != nil {
- 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)
- if err != nil {
- t.Fatalf("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 {
- t.Fatalf("failed to execute transaction: %v", err)
- }
- // Retrieve the trace result and compare against the etalon
- res, err := tracer.GetResult()
- if err != nil {
- t.Fatalf("failed to retrieve trace result: %v", err)
- }
- ret := make(map[string]interface{})
- if err := json.Unmarshal(res, &ret); err != nil {
- t.Fatalf("failed to unmarshal trace result: %v", err)
- }
- if _, has := ret["0x60f3f640a8508fc6a86d45df051962668e1e8ac7"]; !has {
- t.Fatalf("Expected 0x60f3f640a8508fc6a86d45df051962668e1e8ac7 in result")
- }
-}
-
-// Iterates over all the input-output datasets in the tracer test harness and
-// runs the JavaScript tracers against them.
-func TestCallTracer(t *testing.T) {
- files, err := ioutil.ReadDir("testdata")
- if err != nil {
- t.Fatalf("failed to retrieve tracer test suite: %v", err)
- }
- for _, file := range files {
- if !strings.HasPrefix(file.Name(), "call_tracer_") {
- continue
- }
- file := file // capture range variable
- t.Run(camel(strings.TrimSuffix(strings.TrimPrefix(file.Name(), "call_tracer_"), ".json")), func(t *testing.T) {
- t.Parallel()
-
- // Call tracer test found, read if from disk
- blob, err := ioutil.ReadFile(filepath.Join("testdata", file.Name()))
- if err != nil {
- t.Fatalf("failed to read testcase: %v", err)
- }
- test := new(callTracerTest)
- if err := json.Unmarshal(blob, test); err != nil {
- t.Fatalf("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 {
- t.Fatalf("failed to parse testcase input: %v", err)
- }
- signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
- 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: new(big.Int).SetUint64(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 := New("callTracer", txContext)
- if err != nil {
- 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)
- if err != nil {
- t.Fatalf("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 {
- t.Fatalf("failed to execute transaction: %v", err)
- }
- // Retrieve the trace result and compare against the etalon
- res, err := tracer.GetResult()
- if err != nil {
- t.Fatalf("failed to retrieve trace result: %v", err)
- }
- ret := new(callTrace)
- if err := json.Unmarshal(res, ret); err != nil {
- t.Fatalf("failed to unmarshal trace result: %v", err)
- }
-
- if !jsonEqual(ret, test.Result) {
- // uncomment this for easier debugging
- //have, _ := json.MarshalIndent(ret, "", " ")
- //want, _ := json.MarshalIndent(test.Result, "", " ")
- //t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
- t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result)
- }
- })
- }
-}
-
-// jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to
-// comparison
-func jsonEqual(x, y interface{}) bool {
- xTrace := new(callTrace)
- yTrace := new(callTrace)
- 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 BenchmarkTransactionTrace(b *testing.B) {
key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
from := crypto.PubkeyToAddress(key.PublicKey)
@@ -353,8 +97,8 @@ func BenchmarkTransactionTrace(b *testing.B) {
tracer := vm.NewStructLogger(&vm.LogConfig{
Debug: false,
//DisableStorage: true,
- //DisableMemory: true,
- //DisableReturnData: true,
+ //EnableMemory: false,
+ //EnableReturnData: false,
})
evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer})
msg, err := tx.AsMessage(signer)
diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go
index 1ec5b3d62..f38625bd2 100644
--- a/ethclient/ethclient_test.go
+++ b/ethclient/ethclient_test.go
@@ -271,6 +271,7 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
config := ðconfig.Config{Genesis: genesis}
config.Ethash.PowMode = ethash.ModeFake
config.SnapshotCache = 256
+ config.TriesInMemory = 128
ethservice, err := eth.New(n, config)
if err != nil {
t.Fatalf("can't create new ethereum service: %v", err)
@@ -464,7 +465,6 @@ func testBalanceAt(t *testing.T, client *rpc.Client) {
}
func testTransactionInBlockInterrupted(t *testing.T, client *rpc.Client) {
- t.Skip("skip in ci")
ec := NewClient(client)
// Get current block by number
diff --git a/ethdb/database.go b/ethdb/database.go
index 40d0e01d5..e437817a2 100644
--- a/ethdb/database.go
+++ b/ethdb/database.go
@@ -81,6 +81,12 @@ type AncientReader interface {
// AncientSize returns the ancient size of the specified category.
AncientSize(kind string) (uint64, error)
+
+ // ItemAmountInAncient returns the actual length of current ancientDB.
+ ItemAmountInAncient() (uint64, error)
+
+ // AncientOffSet returns the offset of current ancientDB.
+ AncientOffSet() uint64
}
// AncientWriter contains the methods required to write to immutable ancient data.
diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go
index 9ff1a2ce1..5d19cc357 100644
--- a/ethdb/leveldb/leveldb.go
+++ b/ethdb/leveldb/leveldb.go
@@ -14,7 +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 !js
// +build !js
// Package leveldb implements the key-value database layer based on LevelDB.
diff --git a/go.mod b/go.mod
index 5ab7c7780..c58a45dfd 100644
--- a/go.mod
+++ b/go.mod
@@ -39,7 +39,7 @@ require (
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/holiman/bloomfilter/v2 v2.0.3
- github.com/holiman/uint256 v1.2.0
+ github.com/holiman/uint256 v1.1.1
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88
github.com/influxdata/influxdb v1.8.3
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458
diff --git a/go.sum b/go.sum
index 6a9e8f1ff..6ab7ca8c4 100644
--- a/go.sum
+++ b/go.sum
@@ -219,8 +219,8 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuW
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
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.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw=
+github.com/holiman/uint256 v1.1.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.1-0.20210310174557-0ca763054c88 h1:bcAj8KroPf552TScjFPIakjH2/tdIrIH8F+cc4v4SRo=
github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
diff --git a/internal/debug/loudpanic.go b/internal/debug/loudpanic.go
index 86e6bc88f..572ebcefa 100644
--- a/internal/debug/loudpanic.go
+++ b/internal/debug/loudpanic.go
@@ -14,7 +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.6
// +build go1.6
package debug
diff --git a/internal/debug/loudpanic_fallback.go b/internal/debug/loudpanic_fallback.go
index 377490e5b..4ce4985da 100644
--- a/internal/debug/loudpanic_fallback.go
+++ b/internal/debug/loudpanic_fallback.go
@@ -14,7 +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.6
// +build !go1.6
package debug
diff --git a/internal/debug/trace.go b/internal/debug/trace.go
index a273e4a9d..cab5deaaf 100644
--- a/internal/debug/trace.go
+++ b/internal/debug/trace.go
@@ -14,8 +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 go1.5
-// +build go1.5
+//+build go1.5
package debug
diff --git a/internal/debug/trace_fallback.go b/internal/debug/trace_fallback.go
index ec07d991e..4118ff408 100644
--- a/internal/debug/trace_fallback.go
+++ b/internal/debug/trace_fallback.go
@@ -14,8 +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 !go1.5
-// +build !go1.5
+//+build !go1.5
// no-op implementation of tracing methods for Go < 1.5.
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index da4cf8cad..091e9e7e8 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -1098,34 +1098,99 @@ func (s *PublicBlockChainAPI) GetDiffAccounts(ctx context.Context, blockNr rpc.B
return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
}
- return s.b.Chain().GetDiffAccounts(header.Hash())
-}
-
-// GetDiffAccountsWithScope returns detailed changes of some interested accounts in a specific block number.
-func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, blockNr rpc.BlockNumber, accounts []common.Address) (*types.DiffAccountsInBlock, error) {
- if s.b.Chain() == nil {
- return nil, fmt.Errorf("blockchain not support get diff accounts")
+ accounts, err := s.b.Chain().GetDiffAccounts(header.Hash())
+ if err == nil || !errors.Is(err, core.ErrDiffLayerNotFound) {
+ return accounts, err
}
+ // Replay the block when diff layer not found, it is very slow.
block, err := s.b.BlockByNumber(ctx, blockNr)
if err != nil {
return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
}
+ _, statedb, err := s.replay(ctx, block, nil)
+ if err != nil {
+ return nil, err
+ }
+ return statedb.GetDirtyAccounts(), nil
+}
+
+func (s *PublicBlockChainAPI) needToReplay(ctx context.Context, block *types.Block, accounts []common.Address) (bool, error) {
+ receipts, err := s.b.GetReceipts(ctx, block.Hash())
+ if err != nil || len(receipts) != len(block.Transactions()) {
+ return false, fmt.Errorf("receipt incorrect for block number (%d): %v", block.NumberU64(), err)
+ }
+
+ accountSet := make(map[common.Address]struct{}, len(accounts))
+ for _, account := range accounts {
+ accountSet[account] = struct{}{}
+ }
+ spendValueMap := make(map[common.Address]int64, len(accounts))
+ receiveValueMap := make(map[common.Address]int64, len(accounts))
+
+ signer := types.MakeSigner(s.b.ChainConfig(), block.Number())
+ for index, tx := range block.Transactions() {
+ receipt := receipts[index]
+ from, err := types.Sender(signer, tx)
+ if err != nil {
+ return false, fmt.Errorf("get sender for tx failed: %v", err)
+ }
+
+ if _, exists := accountSet[from]; exists {
+ spendValueMap[from] += int64(receipt.GasUsed) * tx.GasPrice().Int64()
+ if receipt.Status == types.ReceiptStatusSuccessful {
+ spendValueMap[from] += tx.Value().Int64()
+ }
+ }
+
+ if tx.To() == nil {
+ continue
+ }
+
+ if _, exists := accountSet[*tx.To()]; exists && receipt.Status == types.ReceiptStatusSuccessful {
+ receiveValueMap[*tx.To()] += tx.Value().Int64()
+ }
+ }
+
parent, err := s.b.BlockByHash(ctx, block.ParentHash())
if err != nil {
- return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr-1, err)
+ return false, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err)
}
- statedb, err := s.b.Chain().StateAt(parent.Root())
+ parentState, err := s.b.Chain().StateAt(parent.Root())
+ if err != nil {
+ return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64()-1, err)
+ }
+ currentState, err := s.b.Chain().StateAt(block.Root())
if err != nil {
- return nil, fmt.Errorf("state not found for block number (%d): %v", blockNr-1, err)
+ return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64(), err)
+ }
+ for _, account := range accounts {
+ parentBalance := parentState.GetBalance(account).Int64()
+ currentBalance := currentState.GetBalance(account).Int64()
+ if receiveValueMap[account]-spendValueMap[account] != currentBalance-parentBalance {
+ return true, nil
+ }
}
+ return false, nil
+}
+
+func (s *PublicBlockChainAPI) replay(ctx context.Context, block *types.Block, accounts []common.Address) (*types.DiffAccountsInBlock, *state.StateDB, error) {
result := &types.DiffAccountsInBlock{
- Number: uint64(blockNr),
+ Number: block.NumberU64(),
BlockHash: block.Hash(),
Transactions: make([]types.DiffAccountsInTx, 0),
}
+ parent, err := s.b.BlockByHash(ctx, block.ParentHash())
+ if err != nil {
+ return nil, nil, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err)
+ }
+ statedb, err := s.b.Chain().StateAt(parent.Root())
+ if err != nil {
+ return nil, nil, fmt.Errorf("state not found for block number (%d): %v", block.NumberU64()-1, err)
+ }
+
accountSet := make(map[common.Address]struct{}, len(accounts))
for _, account := range accounts {
accountSet[account] = struct{}{}
@@ -1173,7 +1238,7 @@ func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, bloc
}
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
- return nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
+ return nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
}
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
@@ -1192,7 +1257,34 @@ func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, bloc
}
}
- return result, nil
+ return result, statedb, nil
+}
+
+// GetDiffAccountsWithScope returns detailed changes of some interested accounts in a specific block number.
+func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, blockNr rpc.BlockNumber, accounts []common.Address) (*types.DiffAccountsInBlock, error) {
+ if s.b.Chain() == nil {
+ return nil, fmt.Errorf("blockchain not support get diff accounts")
+ }
+
+ block, err := s.b.BlockByNumber(ctx, blockNr)
+ if err != nil {
+ return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
+ }
+
+ needReplay, err := s.needToReplay(ctx, block, accounts)
+ if err != nil {
+ return nil, err
+ }
+ if !needReplay {
+ return &types.DiffAccountsInBlock{
+ Number: uint64(blockNr),
+ BlockHash: block.Hash(),
+ Transactions: make([]types.DiffAccountsInTx, 0),
+ }, nil
+ }
+
+ result, _, err := s.replay(ctx, block, accounts)
+ return result, err
}
// ExecutionResult groups all structured logs emitted by the EVM
diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go
index 1934412c9..2975720b8 100644
--- a/internal/web3ext/web3ext.go
+++ b/internal/web3ext/web3ext.go
@@ -419,6 +419,12 @@ web3._extend({
params: 2,
inputFormatter: [null, null]
}),
+ new web3._extend.Method({
+ name: 'intermediateRoots',
+ call: 'debug_intermediateRoots',
+ params: 2,
+ inputFormatter: [null, null]
+ }),
new web3._extend.Method({
name: 'standardTraceBlockToFile',
call: 'debug_standardTraceBlockToFile',
diff --git a/les/api_backend.go b/les/api_backend.go
index c8eca2d90..243a0ac81 100644
--- a/les/api_backend.go
+++ b/les/api_backend.go
@@ -305,7 +305,7 @@ func (b *LesApiBackend) CurrentHeader() *types.Header {
return b.eth.blockchain.CurrentHeader()
}
-func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) {
+func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (*state.StateDB, error) {
return b.eth.stateAtBlock(ctx, block, reexec)
}
diff --git a/log/handler_go13.go b/log/handler_go13.go
index 4df694deb..0843ed0e5 100644
--- a/log/handler_go13.go
+++ b/log/handler_go13.go
@@ -1,4 +1,3 @@
-//go:build !go1.4
// +build !go1.4
package log
diff --git a/log/handler_go14.go b/log/handler_go14.go
index d0cb14aa0..05dedbf2a 100644
--- a/log/handler_go14.go
+++ b/log/handler_go14.go
@@ -1,4 +1,3 @@
-//go:build go1.4
// +build go1.4
package log
diff --git a/log/syslog.go b/log/syslog.go
index 451d831b6..71a17b30b 100644
--- a/log/syslog.go
+++ b/log/syslog.go
@@ -1,4 +1,3 @@
-//go:build !windows && !plan9
// +build !windows,!plan9
package log
diff --git a/metrics/cpu_disabled.go b/metrics/cpu_disabled.go
index c59198874..6c3428993 100644
--- a/metrics/cpu_disabled.go
+++ b/metrics/cpu_disabled.go
@@ -14,7 +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 ios
// +build ios
package metrics
diff --git a/metrics/cpu_enabled.go b/metrics/cpu_enabled.go
index a55e6e23c..02192928b 100644
--- a/metrics/cpu_enabled.go
+++ b/metrics/cpu_enabled.go
@@ -14,7 +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 !ios
// +build !ios
package metrics
diff --git a/metrics/cpu_syscall.go b/metrics/cpu_syscall.go
index b96e6727b..e245453e8 100644
--- a/metrics/cpu_syscall.go
+++ b/metrics/cpu_syscall.go
@@ -14,7 +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 !windows
// +build !windows
package metrics
diff --git a/metrics/disk_nop.go b/metrics/disk_nop.go
index 58fa4e02f..4319f8b27 100644
--- a/metrics/disk_nop.go
+++ b/metrics/disk_nop.go
@@ -14,7 +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 !linux
// +build !linux
package metrics
diff --git a/metrics/runtime_cgo.go b/metrics/runtime_cgo.go
index 7d0af4f7e..e3391f4e8 100644
--- a/metrics/runtime_cgo.go
+++ b/metrics/runtime_cgo.go
@@ -1,5 +1,5 @@
-//go:build cgo && !appengine
-// +build cgo,!appengine
+// +build cgo
+// +build !appengine
package metrics
diff --git a/metrics/runtime_gccpufraction.go b/metrics/runtime_gccpufraction.go
index 28cd44752..ca12c05ba 100644
--- a/metrics/runtime_gccpufraction.go
+++ b/metrics/runtime_gccpufraction.go
@@ -1,4 +1,3 @@
-//go:build go1.5
// +build go1.5
package metrics
diff --git a/metrics/runtime_no_cgo.go b/metrics/runtime_no_cgo.go
index 86fbfd910..616a3b475 100644
--- a/metrics/runtime_no_cgo.go
+++ b/metrics/runtime_no_cgo.go
@@ -1,4 +1,3 @@
-//go:build !cgo || appengine
// +build !cgo appengine
package metrics
diff --git a/metrics/runtime_no_gccpufraction.go b/metrics/runtime_no_gccpufraction.go
index af1a4b63c..be96aa6f1 100644
--- a/metrics/runtime_no_gccpufraction.go
+++ b/metrics/runtime_no_gccpufraction.go
@@ -1,4 +1,3 @@
-//go:build !go1.5
// +build !go1.5
package metrics
diff --git a/metrics/syslog.go b/metrics/syslog.go
index 551a2bd0f..a0ed4b1b2 100644
--- a/metrics/syslog.go
+++ b/metrics/syslog.go
@@ -1,4 +1,3 @@
-//go:build !windows
// +build !windows
package metrics
diff --git a/miner/worker.go b/miner/worker.go
index 2dcb75ac1..28ef170e4 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -634,6 +634,7 @@ func (w *worker) resultLoop() {
logs = append(logs, receipt.Logs...)
}
// Commit block and state to database.
+ task.state.SetExpectedStateRoot(block.Root())
_, err := w.chain.WriteBlockWithState(block, receipts, logs, task.state, true)
if err != nil {
log.Error("Failed writing block to chain", "err", err)
@@ -994,6 +995,10 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
// and commits new work if consensus engine is running.
func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error {
s := w.current.state
+ err := s.WaitPipeVerification()
+ if err != nil {
+ return err
+ }
block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(w.current.header), s, w.current.txs, uncles, w.current.receipts)
if err != nil {
return err
diff --git a/mobile/geth_android.go b/mobile/geth_android.go
index cfdf1c28c..8e4ebe638 100644
--- a/mobile/geth_android.go
+++ b/mobile/geth_android.go
@@ -14,7 +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 android
// +build android
package geth
diff --git a/mobile/geth_ios.go b/mobile/geth_ios.go
index aab839727..307cd0858 100644
--- a/mobile/geth_ios.go
+++ b/mobile/geth_ios.go
@@ -14,7 +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 ios
// +build ios
package geth
diff --git a/mobile/geth_other.go b/mobile/geth_other.go
index c5cad4a7b..6f0c5dda6 100644
--- a/mobile/geth_other.go
+++ b/mobile/geth_other.go
@@ -14,7 +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 !android && !ios
// +build !android,!ios
package geth
diff --git a/node/node.go b/node/node.go
index f1564bea2..b6e1246b3 100644
--- a/node/node.go
+++ b/node/node.go
@@ -27,6 +27,8 @@ import (
"strings"
"sync"
+ "github.com/prometheus/tsdb/fileutil"
+
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
@@ -35,7 +37,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/prometheus/tsdb/fileutil"
)
// Node is a container on which services can be registered.
@@ -68,6 +69,8 @@ const (
closedState
)
+const chainDataHandlesPercentage = 80
+
// New creates a new P2P node, ready for protocol registration.
func New(conf *Config) (*Node, error) {
// Copy config and resolve the datadir so future changes to the current
@@ -580,12 +583,16 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r
}
func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, diff, namespace string, readonly, persistDiff bool) (ethdb.Database, error) {
- chainDB, err := n.OpenDatabaseWithFreezer(name, cache, handles, freezer, namespace, readonly)
+ chainDataHandles := handles
+ if persistDiff {
+ chainDataHandles = handles * chainDataHandlesPercentage / 100
+ }
+ chainDB, err := n.OpenDatabaseWithFreezer(name, cache, chainDataHandles, freezer, namespace, readonly, false, false)
if err != nil {
return nil, err
}
if persistDiff {
- diffStore, err := n.OpenDiffDatabase(name, handles, diff, namespace, readonly)
+ diffStore, err := n.OpenDiffDatabase(name, handles-chainDataHandles, diff, namespace, readonly)
if err != nil {
chainDB.Close()
return nil, err
@@ -600,7 +607,7 @@ func (n *Node) OpenAndMergeDatabase(name string, cache, handles int, freezer, di
// also attaching a chain freezer to it that moves ancient chain data from the
// database to immutable append-only files. If the node is an ephemeral one, a
// memory database is returned.
-func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer, namespace string, readonly bool) (ethdb.Database, error) {
+func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer, namespace string, readonly, disableFreeze, isLastOffset bool) (ethdb.Database, error) {
n.lock.Lock()
defer n.lock.Unlock()
if n.state == closedState {
@@ -619,7 +626,7 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer,
case !filepath.IsAbs(freezer):
freezer = n.ResolvePath(freezer)
}
- db, err = rawdb.NewLevelDBDatabaseWithFreezer(root, cache, handles, freezer, namespace, readonly)
+ db, err = rawdb.NewLevelDBDatabaseWithFreezer(root, cache, handles, freezer, namespace, readonly, disableFreeze, isLastOffset)
}
if err == nil {
diff --git a/p2p/netutil/toobig_notwindows.go b/p2p/netutil/toobig_notwindows.go
index f9f936ae5..47b643857 100644
--- a/p2p/netutil/toobig_notwindows.go
+++ b/p2p/netutil/toobig_notwindows.go
@@ -14,8 +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 !windows
-// +build !windows
+//+build !windows
package netutil
diff --git a/p2p/netutil/toobig_windows.go b/p2p/netutil/toobig_windows.go
index 652903e83..dfbb6d44f 100644
--- a/p2p/netutil/toobig_windows.go
+++ b/p2p/netutil/toobig_windows.go
@@ -14,8 +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 windows
-// +build windows
+//+build windows
package netutil
diff --git a/p2p/server_test.go b/p2p/server_test.go
index a5b3190ae..4ad8eb18e 100644
--- a/p2p/server_test.go
+++ b/p2p/server_test.go
@@ -203,6 +203,29 @@ func TestServerDial(t *testing.T) {
}
}
+func TestServerStopTimeout(t *testing.T) {
+ srv := &Server{Config: Config{
+ PrivateKey: newkey(),
+ MaxPeers: 1,
+ NoDiscovery: true,
+ Logger: testlog.Logger(t, log.LvlTrace).New("server", "1"),
+ }}
+ srv.Start()
+ srv.loopWG.Add(1)
+
+ stopChan := make(chan struct{})
+ go func() {
+ srv.Stop()
+ close(stopChan)
+ }()
+
+ select {
+ case <-stopChan:
+ case <-time.After(10 * time.Second):
+ t.Error("server should be shutdown in 10 seconds")
+ }
+}
+
// This test checks that RemovePeer disconnects the peer if it is connected.
func TestServerRemovePeerDisconnect(t *testing.T) {
srv1 := &Server{Config: Config{
diff --git a/params/config.go b/params/config.go
index 81ff4da9c..c09a57649 100644
--- a/params/config.go
+++ b/params/config.go
@@ -34,7 +34,7 @@ var (
BSCGenesisHash = common.HexToHash("0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b")
ChapelGenesisHash = common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34")
- RialtoGenesisHash = common.HexToHash("0x005dc005bddd1967de6187c1c23be801eb7abdd80cebcc24f341b727b70311d6")
+ RialtoGenesisHash = common.HexToHash("0xaabe549bfa85c84f7aee9da7010b97453ad686f2c2d8ce00503d1a00c72cad54")
YoloV3GenesisHash = common.HexToHash("0xf1f2876e8500c77afcc03228757b39477eceffccf645b734967fe3c7e16967b7")
)
@@ -75,6 +75,7 @@ var (
RamanujanBlock: big.NewInt(0),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
BerlinBlock: big.NewInt(12_244_000),
Ethash: new(EthashConfig),
}
@@ -118,6 +119,7 @@ var (
RamanujanBlock: big.NewInt(0),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
BerlinBlock: big.NewInt(9_812_189),
Ethash: new(EthashConfig),
}
@@ -161,6 +163,7 @@ var (
RamanujanBlock: big.NewInt(0),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
BerlinBlock: big.NewInt(8_290_928),
Clique: &CliqueConfig{
Period: 15,
@@ -203,6 +206,7 @@ var (
RamanujanBlock: big.NewInt(0),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(1_561_651),
MuirGlacierBlock: nil,
BerlinBlock: big.NewInt(4_460_644),
@@ -246,6 +250,7 @@ var (
RamanujanBlock: big.NewInt(0),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(5184000),
+ BrunoBlock: big.NewInt(13082000),
Parlia: &ParliaConfig{
Period: 3,
Epoch: 200,
@@ -266,6 +271,7 @@ var (
RamanujanBlock: big.NewInt(1010000),
NielsBlock: big.NewInt(1014369),
MirrorSyncBlock: big.NewInt(5582500),
+ BrunoBlock: big.NewInt(13837000),
Parlia: &ParliaConfig{
Period: 3,
Epoch: 200,
@@ -286,6 +292,7 @@ var (
RamanujanBlock: big.NewInt(400),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(400),
+ BrunoBlock: big.NewInt(400),
Parlia: &ParliaConfig{
Period: 3,
Epoch: 200,
@@ -308,6 +315,7 @@ var (
RamanujanBlock: big.NewInt(0),
NielsBlock: big.NewInt(0),
MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
MuirGlacierBlock: nil,
BerlinBlock: nil, // Don't enable Berlin directly, we're YOLOing it
YoloV3Block: big.NewInt(0),
@@ -322,16 +330,16 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
- AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil}
+ AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus.
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
- AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
+ AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
- TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil}
+ TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil}
TestRules = TestChainConfig.Rules(new(big.Int))
)
@@ -418,6 +426,7 @@ type ChainConfig struct {
RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty" toml:",omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated)
NielsBlock *big.Int `json:"nielsBlock,omitempty" toml:",omitempty"` // nielsBlock switch block (nil = no fork, 0 = already activated)
MirrorSyncBlock *big.Int `json:"mirrorSyncBlock,omitempty" toml:",omitempty"` // mirrorSyncBlock switch block (nil = no fork, 0 = already activated)
+ BrunoBlock *big.Int `json:"brunoBlock,omitempty" toml:",omitempty"` // brunoBlock switch block (nil = no fork, 0 = already activated)
// Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty" toml:",omitempty"`
@@ -468,7 +477,7 @@ func (c *ChainConfig) String() string {
default:
engine = "unknown"
}
- return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Berlin: %v, YOLO v3: %v, Engine: %v}",
+ return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, Engine: %v}",
c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
@@ -484,6 +493,7 @@ func (c *ChainConfig) String() string {
c.RamanujanBlock,
c.NielsBlock,
c.MirrorSyncBlock,
+ c.BrunoBlock,
c.BerlinBlock,
c.YoloV3Block,
engine,
@@ -555,6 +565,16 @@ func (c *ChainConfig) IsOnMirrorSync(num *big.Int) bool {
return configNumEqual(c.MirrorSyncBlock, num)
}
+// IsBruno returns whether num is either equal to the Burn fork block or greater.
+func (c *ChainConfig) IsBruno(num *big.Int) bool {
+ return isForked(c.BrunoBlock, num)
+}
+
+// IsOnBruno returns whether num is equal to the Burn fork block
+func (c *ChainConfig) IsOnBruno(num *big.Int) bool {
+ return configNumEqual(c.BrunoBlock, num)
+}
+
// IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater.
func (c *ChainConfig) IsMuirGlacier(num *big.Int) bool {
return isForked(c.MuirGlacierBlock, num)
@@ -616,6 +636,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
var lastFork fork
for _, cur := range []fork{
{name: "mirrorSyncBlock", block: c.MirrorSyncBlock},
+ {name: "brunoBlock", block: c.BrunoBlock},
{name: "berlinBlock", block: c.BerlinBlock},
} {
if lastFork.name != "" {
@@ -695,6 +716,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
if isForkIncompatible(c.MirrorSyncBlock, newcfg.MirrorSyncBlock, head) {
return newCompatError("mirrorSync fork block", c.MirrorSyncBlock, newcfg.MirrorSyncBlock)
}
+ if isForkIncompatible(c.BrunoBlock, newcfg.BrunoBlock, head) {
+ return newCompatError("bruno fork block", c.BrunoBlock, newcfg.BrunoBlock)
+ }
return nil
}
diff --git a/params/protocol_params.go b/params/protocol_params.go
index 857bb9a58..84515869b 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -114,7 +114,6 @@ const (
// Precompiled contract gas prices
- //TODO need further discussion
TendermintHeaderValidateGas uint64 = 3000 // Gas for validate tendermiint consensus state
IAVLMerkleProofValidateGas uint64 = 3000 // Gas for validate merkle proof
diff --git a/params/version.go b/params/version.go
index c90a95a46..519aaecad 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 = 0 // Minor version component of the current release
- VersionPatch = 2 // Patch version component of the current release
+ VersionPatch = 3 // Patch version component of the current release
VersionMeta = "" // Version metadata to append to the version string
)
diff --git a/rlp/safe.go b/rlp/safe.go
index 6f3b151ff..a80380aef 100644
--- a/rlp/safe.go
+++ b/rlp/safe.go
@@ -14,7 +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 nacl || js || !cgo
// +build nacl js !cgo
package rlp
diff --git a/rlp/unsafe.go b/rlp/unsafe.go
index 30bb9a659..94ed5405a 100644
--- a/rlp/unsafe.go
+++ b/rlp/unsafe.go
@@ -14,7 +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 !nacl && !js && cgo
// +build !nacl,!js,cgo
package rlp
diff --git a/rpc/constants_unix.go b/rpc/constants_unix.go
index 1f04d15d7..2f98d6499 100644
--- a/rpc/constants_unix.go
+++ b/rpc/constants_unix.go
@@ -14,7 +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 darwin || dragonfly || freebsd || linux || nacl || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package rpc
diff --git a/rpc/constants_unix_nocgo.go b/rpc/constants_unix_nocgo.go
index a62e4ee52..ecb231f92 100644
--- a/rpc/constants_unix_nocgo.go
+++ b/rpc/constants_unix_nocgo.go
@@ -14,7 +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 !cgo && !windows
// +build !cgo,!windows
package rpc
diff --git a/rpc/ipc_js.go b/rpc/ipc_js.go
index 453a20bc1..7e7554a76 100644
--- a/rpc/ipc_js.go
+++ b/rpc/ipc_js.go
@@ -14,7 +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 js
// +build js
package rpc
diff --git a/rpc/ipc_unix.go b/rpc/ipc_unix.go
index 249a9cf04..f4690cc0a 100644
--- a/rpc/ipc_unix.go
+++ b/rpc/ipc_unix.go
@@ -14,7 +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 darwin || dragonfly || freebsd || linux || nacl || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package rpc
diff --git a/rpc/ipc_windows.go b/rpc/ipc_windows.go
index adb1826f0..ca56a3ce4 100644
--- a/rpc/ipc_windows.go
+++ b/rpc/ipc_windows.go
@@ -14,7 +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 windows
// +build windows
package rpc
diff --git a/tests/fuzzers/bls12381/bls12381_fuzz.go b/tests/fuzzers/bls12381/bls12381_fuzz.go
index b283ed11f..5c28b952d 100644
--- a/tests/fuzzers/bls12381/bls12381_fuzz.go
+++ b/tests/fuzzers/bls12381/bls12381_fuzz.go
@@ -14,7 +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 gofuzz
// +build gofuzz
package bls
@@ -29,6 +28,7 @@ import (
gnark "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
+
"github.com/ethereum/go-ethereum/crypto/bls12381"
)
diff --git a/tests/fuzzers/bn256/bn256_fuzz.go b/tests/fuzzers/bn256/bn256_fuzz.go
index 11fd9e18d..030ac19b3 100644
--- a/tests/fuzzers/bn256/bn256_fuzz.go
+++ b/tests/fuzzers/bn256/bn256_fuzz.go
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
-//go:build gofuzz
// +build gofuzz
package bn256
diff --git a/tests/state_test.go b/tests/state_test.go
index c1d9f6a0d..bb80a162a 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -105,7 +105,7 @@ func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
}
buf := new(bytes.Buffer)
w := bufio.NewWriter(buf)
- tracer := vm.NewJSONLogger(&vm.LogConfig{DisableMemory: true}, w)
+ tracer := vm.NewJSONLogger(&vm.LogConfig{}, w)
config.Debug, config.Tracer = true, tracer
err2 := test(config)
if !errors.Is(err, err2) {
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index 77d4fd08d..a688254a2 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -198,7 +198,9 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
}
// Commit block
- statedb.Commit(config.IsEIP158(block.Number()))
+ statedb.Finalise(config.IsEIP158(block.Number()))
+ statedb.AccountsIntermediateRoot()
+ statedb.Commit(nil)
// Add 0-value mining reward. This only makes a difference in the cases
// where
// - the coinbase suicided, or
@@ -226,7 +228,9 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
}
}
// Commit and re-open to start with a clean state.
- root, _, _ := statedb.Commit(false)
+ statedb.Finalise(false)
+ statedb.AccountsIntermediateRoot()
+ root, _, _ := statedb.Commit(nil)
var snaps *snapshot.Tree
if snapshotter {
diff --git a/trie/database.go b/trie/database.go
index 76f8b26cc..b6a3154d4 100644
--- a/trie/database.go
+++ b/trie/database.go
@@ -605,14 +605,16 @@ func (db *Database) Cap(limit common.StorageSize) error {
// outside code doesn't see an inconsistent state (referenced data removed from
// memory cache during commit but not yet in persistent storage). This is ensured
// by only uncaching existing data when the database write finalizes.
+ db.lock.RLock()
nodes, storage, start := len(db.dirties), db.dirtiesSize, time.Now()
- batch := db.diskdb.NewBatch()
-
// db.dirtiesSize only contains the useful data in the cache, but when reporting
// the total memory consumption, the maintenance metadata is also needed to be
// counted.
size := db.dirtiesSize + common.StorageSize((len(db.dirties)-1)*cachedNodeSize)
size += db.childrenSize - common.StorageSize(len(db.dirties[common.Hash{}].children)*(common.HashLength+2))
+ db.lock.RUnlock()
+
+ batch := db.diskdb.NewBatch()
// If the preimage cache got large enough, push to disk. If it's still small
// leave for later to deduplicate writes.
@@ -632,27 +634,35 @@ func (db *Database) Cap(limit common.StorageSize) error {
}
// Keep committing nodes from the flush-list until we're below allowance
oldest := db.oldest
- for size > limit && oldest != (common.Hash{}) {
- // Fetch the oldest referenced node and push into the batch
- node := db.dirties[oldest]
- rawdb.WriteTrieNode(batch, oldest, node.rlp())
-
- // If we exceeded the ideal batch size, commit and reset
- if batch.ValueSize() >= ethdb.IdealBatchSize {
- if err := batch.Write(); err != nil {
- log.Error("Failed to write flush list to disk", "err", err)
- return err
+ err := func() error {
+ db.lock.RLock()
+ defer db.lock.RUnlock()
+ for size > limit && oldest != (common.Hash{}) {
+ // Fetch the oldest referenced node and push into the batch
+ node := db.dirties[oldest]
+ rawdb.WriteTrieNode(batch, oldest, node.rlp())
+
+ // If we exceeded the ideal batch size, commit and reset
+ if batch.ValueSize() >= ethdb.IdealBatchSize {
+ if err := batch.Write(); err != nil {
+ log.Error("Failed to write flush list to disk", "err", err)
+ return err
+ }
+ batch.Reset()
}
- batch.Reset()
- }
- // Iterate to the next flush item, or abort if the size cap was achieved. Size
- // is the total size, including the useful cached data (hash -> blob), the
- // cache item metadata, as well as external children mappings.
- size -= common.StorageSize(common.HashLength + int(node.size) + cachedNodeSize)
- if node.children != nil {
- size -= common.StorageSize(cachedNodeChildrenSize + len(node.children)*(common.HashLength+2))
+ // Iterate to the next flush item, or abort if the size cap was achieved. Size
+ // is the total size, including the useful cached data (hash -> blob), the
+ // cache item metadata, as well as external children mappings.
+ size -= common.StorageSize(common.HashLength + int(node.size) + cachedNodeSize)
+ if node.children != nil {
+ size -= common.StorageSize(cachedNodeChildrenSize + len(node.children)*(common.HashLength+2))
+ }
+ oldest = node.flushNext
}
- oldest = node.flushNext
+ return nil
+ }()
+ if err != nil {
+ return err
}
// Flush out any remainder data from the last batch
if err := batch.Write(); err != nil {
@@ -722,7 +732,9 @@ func (db *Database) Commit(node common.Hash, report bool, callback func(common.H
batch.Reset()
}
// Move the trie itself into the batch, flushing if enough data is accumulated
+ db.lock.RLock()
nodes, storage := len(db.dirties), db.dirtiesSize
+ db.lock.RUnlock()
uncacher := &cleaner{db}
if err := db.commit(node, batch, uncacher, callback); err != nil {
@@ -766,10 +778,14 @@ func (db *Database) Commit(node common.Hash, report bool, callback func(common.H
// commit is the private locked version of Commit.
func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleaner, callback func(common.Hash)) error {
// If the node does not exist, it's a previously committed node
+ db.lock.RLock()
node, ok := db.dirties[hash]
if !ok {
+ db.lock.RUnlock()
return nil
}
+ db.lock.RUnlock()
+
var err error
node.forChilds(func(child common.Hash) {
if err == nil {
diff --git a/trie/proof.go b/trie/proof.go
index 80227149e..51ecea0c3 100644
--- a/trie/proof.go
+++ b/trie/proof.go
@@ -472,7 +472,7 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, key
if len(keys) != len(values) {
return false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values))
}
- // Ensure the received batch is monotonic increasing and contains no deletions.
+ // Ensure the received batch is monotonic increasing and contains no deletions
for i := 0; i < len(keys)-1; i++ {
if bytes.Compare(keys[i], keys[i+1]) >= 0 {
return false, errors.New("range is not monotonically increasing")
diff --git a/trie/proof_test.go b/trie/proof_test.go
index a35b7144c..95ad6169c 100644
--- a/trie/proof_test.go
+++ b/trie/proof_test.go
@@ -813,6 +813,85 @@ func TestBloatedProof(t *testing.T) {
}
}
+// TestEmptyValueRangeProof tests normal range proof with both edge proofs
+// as the existent proof, but with an extra empty value included, which is a
+// noop technically, but practically should be rejected.
+func TestEmptyValueRangeProof(t *testing.T) {
+ trie, values := randomTrie(512)
+ var entries entrySlice
+ for _, kv := range values {
+ entries = append(entries, kv)
+ }
+ sort.Sort(entries)
+
+ // Create a new entry with a slightly modified key
+ mid := len(entries) / 2
+ key := common.CopyBytes(entries[mid-1].k)
+ for n := len(key) - 1; n >= 0; n-- {
+ if key[n] < 0xff {
+ key[n]++
+ break
+ }
+ }
+ noop := &kv{key, []byte{}, false}
+ entries = append(append(append([]*kv{}, entries[:mid]...), noop), entries[mid:]...)
+
+ start, end := 1, len(entries)-1
+
+ proof := memorydb.New()
+ if err := trie.Prove(entries[start].k, 0, proof); err != nil {
+ t.Fatalf("Failed to prove the first node %v", err)
+ }
+ if err := trie.Prove(entries[end-1].k, 0, proof); err != nil {
+ t.Fatalf("Failed to prove the last node %v", err)
+ }
+ var keys [][]byte
+ var vals [][]byte
+ for i := start; i < end; i++ {
+ keys = append(keys, entries[i].k)
+ vals = append(vals, entries[i].v)
+ }
+ _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof)
+ if err == nil {
+ t.Fatalf("Expected failure on noop entry")
+ }
+}
+
+// TestAllElementsEmptyValueRangeProof tests the range proof with all elements,
+// but with an extra empty value included, which is a noop technically, but
+// practically should be rejected.
+func TestAllElementsEmptyValueRangeProof(t *testing.T) {
+ trie, values := randomTrie(512)
+ var entries entrySlice
+ for _, kv := range values {
+ entries = append(entries, kv)
+ }
+ sort.Sort(entries)
+
+ // Create a new entry with a slightly modified key
+ mid := len(entries) / 2
+ key := common.CopyBytes(entries[mid-1].k)
+ for n := len(key) - 1; n >= 0; n-- {
+ if key[n] < 0xff {
+ key[n]++
+ break
+ }
+ }
+ noop := &kv{key, []byte{}, false}
+ entries = append(append(append([]*kv{}, entries[:mid]...), noop), entries[mid:]...)
+
+ var keys [][]byte
+ var vals [][]byte
+ for i := 0; i < len(entries); i++ {
+ keys = append(keys, entries[i].k)
+ vals = append(vals, entries[i].v)
+ }
+ _, err := VerifyRangeProof(trie.Hash(), nil, nil, keys, vals, nil)
+ if err == nil {
+ t.Fatalf("Expected failure on noop entry")
+ }
+}
+
// mutateByte changes one byte in b.
func mutateByte(b []byte) {
for r := mrand.Intn(len(b)); ; {