Merge pull request #2281 from obscuren/configurable-genesis
core: homestead chain configuration & artificial gas floor target mining flag
This commit is contained in:
commit
c58079461b
@ -24,10 +24,14 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
|
||||||
|
var chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)}
|
||||||
|
|
||||||
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
|
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
|
||||||
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
|
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
|
||||||
|
|
||||||
@ -46,7 +50,7 @@ type SimulatedBackend struct {
|
|||||||
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
|
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
|
||||||
database, _ := ethdb.NewMemDatabase()
|
database, _ := ethdb.NewMemDatabase()
|
||||||
core.WriteGenesisBlockForTesting(database, accounts...)
|
core.WriteGenesisBlockForTesting(database, accounts...)
|
||||||
blockchain, _ := core.NewBlockChain(database, new(core.FakePow), new(event.TypeMux))
|
blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux))
|
||||||
|
|
||||||
backend := &SimulatedBackend{
|
backend := &SimulatedBackend{
|
||||||
database: database,
|
database: database,
|
||||||
@ -102,7 +106,7 @@ func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pe
|
|||||||
data: data,
|
data: data,
|
||||||
}
|
}
|
||||||
// Execute the call and return
|
// Execute the call and return
|
||||||
vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil)
|
vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
|
||||||
gaspool := new(core.GasPool).AddGas(common.MaxBig)
|
gaspool := new(core.GasPool).AddGas(common.MaxBig)
|
||||||
|
|
||||||
out, _, err := core.ApplyMessage(vmenv, msg, gaspool)
|
out, _, err := core.ApplyMessage(vmenv, msg, gaspool)
|
||||||
@ -145,7 +149,7 @@ func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *com
|
|||||||
data: data,
|
data: data,
|
||||||
}
|
}
|
||||||
// Execute the call and return
|
// Execute the call and return
|
||||||
vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil)
|
vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
|
||||||
gaspool := new(core.GasPool).AddGas(common.MaxBig)
|
gaspool := new(core.GasPool).AddGas(common.MaxBig)
|
||||||
|
|
||||||
_, gas, err := core.ApplyMessage(vmenv, msg, gaspool)
|
_, gas, err := core.ApplyMessage(vmenv, msg, gaspool)
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,9 +74,9 @@ func runTestWithReader(test string, r io.Reader) error {
|
|||||||
var err error
|
var err error
|
||||||
switch strings.ToLower(test) {
|
switch strings.ToLower(test) {
|
||||||
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
|
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
|
||||||
err = tests.RunBlockTestWithReader(r, skipTests)
|
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, r, skipTests)
|
||||||
case "st", "state", "statetest", "statetests":
|
case "st", "state", "statetest", "statetests":
|
||||||
err = tests.RunStateTestWithReader(r, skipTests)
|
err = tests.RunStateTestWithReader(tests.RuleSet{params.MainNetHomesteadBlock}, r, skipTests)
|
||||||
case "tx", "transactiontest", "transactiontests":
|
case "tx", "transactiontest", "transactiontests":
|
||||||
err = tests.RunTransactionTestsWithReader(r, skipTests)
|
err = tests.RunTransactionTestsWithReader(r, skipTests)
|
||||||
case "vm", "vmtest", "vmtests":
|
case "vm", "vmtest", "vmtests":
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -106,9 +105,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func run(ctx *cli.Context) {
|
func run(ctx *cli.Context) {
|
||||||
vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name)
|
|
||||||
vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name)
|
|
||||||
|
|
||||||
glog.SetToStderr(true)
|
glog.SetToStderr(true)
|
||||||
glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
|
glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
|
||||||
|
|
||||||
@ -118,8 +114,10 @@ func run(ctx *cli.Context) {
|
|||||||
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
|
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
|
||||||
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
|
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
|
||||||
|
|
||||||
vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)), &vm.Config{
|
vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)), vm.Config{
|
||||||
Debug: ctx.GlobalBool(DebugFlag.Name),
|
Debug: ctx.GlobalBool(DebugFlag.Name),
|
||||||
|
ForceJit: ctx.GlobalBool(ForceJitFlag.Name),
|
||||||
|
EnableJit: !ctx.GlobalBool(DisableJitFlag.Name),
|
||||||
})
|
})
|
||||||
|
|
||||||
tstart := time.Now()
|
tstart := time.Now()
|
||||||
@ -180,8 +178,7 @@ type VMEnv struct {
|
|||||||
evm *vm.EVM
|
evm *vm.EVM
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg *vm.Config) *VMEnv {
|
func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg vm.Config) *VMEnv {
|
||||||
params.HomesteadBlock = new(big.Int)
|
|
||||||
env := &VMEnv{
|
env := &VMEnv{
|
||||||
state: state,
|
state: state,
|
||||||
transactor: &transactor,
|
transactor: &transactor,
|
||||||
@ -194,6 +191,12 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
|
|||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ruleSet implements vm.RuleSet and will always default to the homestead rule set.
|
||||||
|
type ruleSet struct{}
|
||||||
|
|
||||||
|
func (ruleSet) IsHomestead(*big.Int) bool { return true }
|
||||||
|
|
||||||
|
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
|
||||||
func (self *VMEnv) Vm() vm.Vm { return self.evm }
|
func (self *VMEnv) Vm() vm.Vm { return self.evm }
|
||||||
func (self *VMEnv) Db() vm.Database { return self.state }
|
func (self *VMEnv) Db() vm.Database { return self.state }
|
||||||
func (self *VMEnv) MakeSnapshot() vm.Database { return self.state.Copy() }
|
func (self *VMEnv) MakeSnapshot() vm.Database { return self.state.Copy() }
|
||||||
|
@ -106,6 +106,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
|
|||||||
core.WriteGenesisBlockForTesting(db, core.GenesisAccount{common.HexToAddress(testAddress), common.String2Big(testBalance)})
|
core.WriteGenesisBlockForTesting(db, core.GenesisAccount{common.HexToAddress(testAddress), common.String2Big(testBalance)})
|
||||||
|
|
||||||
ethConf := ð.Config{
|
ethConf := ð.Config{
|
||||||
|
ChainConfig: &core.ChainConfig{HomesteadBlock: new(big.Int)},
|
||||||
TestGenesisState: db,
|
TestGenesisState: db,
|
||||||
AccountManager: accman,
|
AccountManager: accman,
|
||||||
DocRoot: "/",
|
DocRoot: "/",
|
||||||
|
@ -32,7 +32,9 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/debug"
|
"github.com/ethereum/go-ethereum/internal/debug"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
@ -108,7 +110,6 @@ Runs quick benchmark on first GPU found.
|
|||||||
The output of this command is supposed to be machine-readable.
|
The output of this command is supposed to be machine-readable.
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
Name: "wallet",
|
Name: "wallet",
|
||||||
Usage: "ethereum presale wallet",
|
Usage: "ethereum presale wallet",
|
||||||
@ -247,6 +248,16 @@ nodes.
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Action: initGenesis,
|
||||||
|
Name: "init",
|
||||||
|
Usage: "bootstraps and initialises a new genesis block (JSON)",
|
||||||
|
Description: `
|
||||||
|
The init command initialises a new genesis block and definition for the network.
|
||||||
|
This is a destructive action and changes the network in which you will be
|
||||||
|
participating.
|
||||||
|
`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Action: console,
|
Action: console,
|
||||||
Name: "console",
|
Name: "console",
|
||||||
@ -255,7 +266,8 @@ nodes.
|
|||||||
The Geth console is an interactive shell for the JavaScript runtime environment
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||||
See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
|
See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
|
||||||
`},
|
`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Action: attach,
|
Action: attach,
|
||||||
Name: "attach",
|
Name: "attach",
|
||||||
@ -347,7 +359,6 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
|
|||||||
go metrics.CollectProcessMetrics(3 * time.Second)
|
go metrics.CollectProcessMetrics(3 * time.Second)
|
||||||
|
|
||||||
utils.SetupNetwork(ctx)
|
utils.SetupNetwork(ctx)
|
||||||
utils.SetupVM(ctx)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,6 +428,31 @@ func attach(ctx *cli.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initGenesis will initialise the given JSON format genesis file and writes it as
|
||||||
|
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
|
||||||
|
func initGenesis(ctx *cli.Context) {
|
||||||
|
genesisPath := ctx.Args().First()
|
||||||
|
if len(genesisPath) == 0 {
|
||||||
|
utils.Fatalf("must supply path to genesis JSON file")
|
||||||
|
}
|
||||||
|
|
||||||
|
chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("could not open database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
genesisFile, err := os.Open(genesisPath)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("failed to read genesis file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
block, err := core.WriteGenesisBlock(chainDb, genesisFile)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("failed to write genesis block: %v", err)
|
||||||
|
}
|
||||||
|
glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
// console starts a new geth node, attaching a JavaScript console to it at the
|
// console starts a new geth node, attaching a JavaScript console to it at the
|
||||||
// same time.
|
// same time.
|
||||||
func console(ctx *cli.Context) {
|
func console(ctx *cli.Context) {
|
||||||
|
@ -121,6 +121,7 @@ var AppHelpFlagGroups = []flagGroup{
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.MiningEnabledFlag,
|
utils.MiningEnabledFlag,
|
||||||
utils.MinerThreadsFlag,
|
utils.MinerThreadsFlag,
|
||||||
|
utils.TargetGasLimitFlag,
|
||||||
utils.MiningGPUFlag,
|
utils.MiningGPUFlag,
|
||||||
utils.AutoDAGFlag,
|
utils.AutoDAGFlag,
|
||||||
utils.EtherbaseFlag,
|
utils.EtherbaseFlag,
|
||||||
|
@ -34,7 +34,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
@ -173,6 +172,11 @@ var (
|
|||||||
Name: "minergpus",
|
Name: "minergpus",
|
||||||
Usage: "List of GPUs to use for mining (e.g. '0,1' will use the first two GPUs found)",
|
Usage: "List of GPUs to use for mining (e.g. '0,1' will use the first two GPUs found)",
|
||||||
}
|
}
|
||||||
|
TargetGasLimitFlag = cli.StringFlag{
|
||||||
|
Name: "targetgaslimit",
|
||||||
|
Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
|
||||||
|
Value: params.GenesisGasLimit.String(),
|
||||||
|
}
|
||||||
AutoDAGFlag = cli.BoolFlag{
|
AutoDAGFlag = cli.BoolFlag{
|
||||||
Name: "autodag",
|
Name: "autodag",
|
||||||
Usage: "Enable automatic DAG pregeneration",
|
Usage: "Enable automatic DAG pregeneration",
|
||||||
@ -656,6 +660,7 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
|
|||||||
accman := MakeAccountManager(ctx)
|
accman := MakeAccountManager(ctx)
|
||||||
|
|
||||||
ethConf := ð.Config{
|
ethConf := ð.Config{
|
||||||
|
ChainConfig: MustMakeChainConfig(ctx),
|
||||||
Genesis: MakeGenesisBlock(ctx),
|
Genesis: MakeGenesisBlock(ctx),
|
||||||
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
|
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
|
||||||
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
|
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
|
||||||
@ -701,8 +706,6 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
|
|||||||
ethConf.Genesis = core.TestNetGenesisBlock()
|
ethConf.Genesis = core.TestNetGenesisBlock()
|
||||||
}
|
}
|
||||||
state.StartingNonce = 1048576 // (2**20)
|
state.StartingNonce = 1048576 // (2**20)
|
||||||
// overwrite homestead block
|
|
||||||
params.HomesteadBlock = params.TestNetHomesteadBlock
|
|
||||||
|
|
||||||
case ctx.GlobalBool(DevModeFlag.Name):
|
case ctx.GlobalBool(DevModeFlag.Name):
|
||||||
// Override the base network stack configs
|
// Override the base network stack configs
|
||||||
@ -758,25 +761,56 @@ func SetupNetwork(ctx *cli.Context) {
|
|||||||
core.BlockReward = big.NewInt(1.5e+18)
|
core.BlockReward = big.NewInt(1.5e+18)
|
||||||
core.ExpDiffPeriod = big.NewInt(math.MaxInt64)
|
core.ExpDiffPeriod = big.NewInt(math.MaxInt64)
|
||||||
}
|
}
|
||||||
|
params.TargetGasLimit = common.String2Big(ctx.GlobalString(TargetGasLimitFlag.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupVM configured the VM package's global settings
|
// MustMakeChainConfig reads the chain configuration from the given database.
|
||||||
func SetupVM(ctx *cli.Context) {
|
func MustMakeChainConfig(ctx *cli.Context) *core.ChainConfig {
|
||||||
vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name)
|
var (
|
||||||
vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name)
|
db = MakeChainDatabase(ctx)
|
||||||
vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
|
genesis = core.GetBlock(db, core.GetCanonicalHash(db, 0))
|
||||||
|
)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
chainConfig, err := core.GetChainConfig(db, genesis.Hash())
|
||||||
|
if err != nil {
|
||||||
|
if err != core.ChainConfigNotFoundErr {
|
||||||
|
Fatalf("Could not make chain configuration: %v", err)
|
||||||
|
}
|
||||||
|
var homesteadBlockNo *big.Int
|
||||||
|
if ctx.GlobalBool(TestNetFlag.Name) {
|
||||||
|
homesteadBlockNo = params.TestNetHomesteadBlock
|
||||||
|
} else {
|
||||||
|
homesteadBlockNo = params.MainNetHomesteadBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
chainConfig = &core.ChainConfig{
|
||||||
|
HomesteadBlock: homesteadBlockNo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chainConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
|
||||||
|
func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
|
||||||
|
var (
|
||||||
|
datadir = MustMakeDataDir(ctx)
|
||||||
|
cache = ctx.GlobalInt(CacheFlag.Name)
|
||||||
|
handles = MakeDatabaseHandles()
|
||||||
|
)
|
||||||
|
|
||||||
|
chainDb, err := ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache, handles)
|
||||||
|
if err != nil {
|
||||||
|
Fatalf("Could not open database: %v", err)
|
||||||
|
}
|
||||||
|
return chainDb
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeChain creates a chain manager from set command line flags.
|
// MakeChain creates a chain manager from set command line flags.
|
||||||
func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
|
func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
|
||||||
datadir := MustMakeDataDir(ctx)
|
|
||||||
cache := ctx.GlobalInt(CacheFlag.Name)
|
|
||||||
handles := MakeDatabaseHandles()
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if chainDb, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache, handles); err != nil {
|
chainDb = MakeChainDatabase(ctx)
|
||||||
Fatalf("Could not open database: %v", err)
|
|
||||||
}
|
|
||||||
if ctx.GlobalBool(OlympicFlag.Name) {
|
if ctx.GlobalBool(OlympicFlag.Name) {
|
||||||
_, err := core.WriteTestNetGenesisBlock(chainDb)
|
_, err := core.WriteTestNetGenesisBlock(chainDb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -784,10 +818,10 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eventMux := new(event.TypeMux)
|
chainConfig := MustMakeChainConfig(ctx)
|
||||||
pow := ethash.New()
|
|
||||||
//genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB)
|
var eventMux event.TypeMux
|
||||||
chain, err = core.NewBlockChain(chainDb, pow, eventMux)
|
chain, err = core.NewBlockChain(chainDb, chainConfig, ethash.New(), &eventMux)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Could not start chainmanager: %v", err)
|
Fatalf("Could not start chainmanager: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Report gives off a warning requesting the user to submit an issue to the github tracker.
|
||||||
func Report(extra ...interface{}) {
|
func Report(extra ...interface{}) {
|
||||||
fmt.Fprintln(os.Stderr, "You've encountered a sought after, hard to reproduce bug. Please report this to the developers <3 https://github.com/ethereum/go-ethereum/issues")
|
fmt.Fprintln(os.Stderr, "You've encountered a sought after, hard to reproduce bug. Please report this to the developers <3 https://github.com/ethereum/go-ethereum/issues")
|
||||||
fmt.Fprintln(os.Stderr, extra...)
|
fmt.Fprintln(os.Stderr, extra...)
|
||||||
@ -34,3 +36,17 @@ func Report(extra ...interface{}) {
|
|||||||
|
|
||||||
fmt.Fprintln(os.Stderr, "#### BUG! PLEASE REPORT ####")
|
fmt.Fprintln(os.Stderr, "#### BUG! PLEASE REPORT ####")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrintDepricationWarning prinst the given string in a box using fmt.Println.
|
||||||
|
func PrintDepricationWarning(str string) {
|
||||||
|
line := strings.Repeat("#", len(str)+4)
|
||||||
|
emptyLine := strings.Repeat(" ", len(str))
|
||||||
|
fmt.Printf(`
|
||||||
|
%s
|
||||||
|
# %s #
|
||||||
|
# %s #
|
||||||
|
# %s #
|
||||||
|
%s
|
||||||
|
|
||||||
|
`, line, emptyLine, str, emptyLine, line)
|
||||||
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
@ -35,6 +36,7 @@ import (
|
|||||||
|
|
||||||
// registryAPIBackend is a backend for an Ethereum Registry.
|
// registryAPIBackend is a backend for an Ethereum Registry.
|
||||||
type registryAPIBackend struct {
|
type registryAPIBackend struct {
|
||||||
|
config *core.ChainConfig
|
||||||
bc *core.BlockChain
|
bc *core.BlockChain
|
||||||
chainDb ethdb.Database
|
chainDb ethdb.Database
|
||||||
txPool *core.TxPool
|
txPool *core.TxPool
|
||||||
@ -43,12 +45,22 @@ type registryAPIBackend struct {
|
|||||||
|
|
||||||
// PrivateRegistarAPI offers various functions to access the Ethereum registry.
|
// PrivateRegistarAPI offers various functions to access the Ethereum registry.
|
||||||
type PrivateRegistarAPI struct {
|
type PrivateRegistarAPI struct {
|
||||||
|
config *core.ChainConfig
|
||||||
be *registryAPIBackend
|
be *registryAPIBackend
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
|
// NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
|
||||||
func NewPrivateRegistarAPI(bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
|
func NewPrivateRegistarAPI(config *core.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
|
||||||
return &PrivateRegistarAPI{®istryAPIBackend{bc, chainDb, txPool, am}}
|
return &PrivateRegistarAPI{
|
||||||
|
config: config,
|
||||||
|
be: ®istryAPIBackend{
|
||||||
|
config: config,
|
||||||
|
bc: bc,
|
||||||
|
chainDb: chainDb,
|
||||||
|
txPool: txPool,
|
||||||
|
am: am,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGlobalRegistrar allows clients to set the global registry for the node.
|
// SetGlobalRegistrar allows clients to set the global registry for the node.
|
||||||
@ -179,7 +191,7 @@ func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
header := be.bc.CurrentBlock().Header()
|
header := be.bc.CurrentBlock().Header()
|
||||||
vmenv := core.NewEnv(statedb, be.bc, msg, header, nil)
|
vmenv := core.NewEnv(statedb, be.config, be.bc, msg, header, vm.Config{})
|
||||||
gp := new(core.GasPool).AddGas(common.MaxBig)
|
gp := new(core.GasPool).AddGas(common.MaxBig)
|
||||||
res, gas, err := core.ApplyMessage(vmenv, msg, gp)
|
res, gas, err := core.ApplyMessage(vmenv, msg, gp)
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
|||||||
// Time the insertion of the new chain.
|
// Time the insertion of the new chain.
|
||||||
// State and blocks are stored in the same DB.
|
// State and blocks are stored in the same DB.
|
||||||
evmux := new(event.TypeMux)
|
evmux := new(event.TypeMux)
|
||||||
chainman, _ := NewBlockChain(db, FakePow{}, evmux)
|
chainman, _ := NewBlockChain(db, &ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
|
||||||
defer chainman.Stop()
|
defer chainman.Stop()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -41,13 +41,15 @@ var (
|
|||||||
//
|
//
|
||||||
// BlockValidator implements Validator.
|
// BlockValidator implements Validator.
|
||||||
type BlockValidator struct {
|
type BlockValidator struct {
|
||||||
|
config *ChainConfig // Chain configuration options
|
||||||
bc *BlockChain // Canonical block chain
|
bc *BlockChain // Canonical block chain
|
||||||
Pow pow.PoW // Proof of work used for validating
|
Pow pow.PoW // Proof of work used for validating
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockValidator returns a new block validator which is safe for re-use
|
// NewBlockValidator returns a new block validator which is safe for re-use
|
||||||
func NewBlockValidator(blockchain *BlockChain, pow pow.PoW) *BlockValidator {
|
func NewBlockValidator(config *ChainConfig, blockchain *BlockChain, pow pow.PoW) *BlockValidator {
|
||||||
validator := &BlockValidator{
|
validator := &BlockValidator{
|
||||||
|
config: config,
|
||||||
Pow: pow,
|
Pow: pow,
|
||||||
bc: blockchain,
|
bc: blockchain,
|
||||||
}
|
}
|
||||||
@ -80,7 +82,7 @@ func (v *BlockValidator) ValidateBlock(block *types.Block) error {
|
|||||||
|
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
// validate the block header
|
// validate the block header
|
||||||
if err := ValidateHeader(v.Pow, header, parent.Header(), false, false); err != nil {
|
if err := ValidateHeader(v.config, v.Pow, header, parent.Header(), false, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// verify the uncles are correctly rewarded
|
// verify the uncles are correctly rewarded
|
||||||
@ -175,7 +177,7 @@ func (v *BlockValidator) VerifyUncles(block, parent *types.Block) error {
|
|||||||
return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
|
return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ValidateHeader(v.Pow, uncle, ancestors[uncle.ParentHash].Header(), true, true); err != nil {
|
if err := ValidateHeader(v.config, v.Pow, uncle, ancestors[uncle.ParentHash].Header(), true, true); err != nil {
|
||||||
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
|
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,13 +197,13 @@ func (v *BlockValidator) ValidateHeader(header, parent *types.Header, checkPow b
|
|||||||
if v.bc.HasHeader(header.Hash()) {
|
if v.bc.HasHeader(header.Hash()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ValidateHeader(v.Pow, header, parent, checkPow, false)
|
return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validates a header. Returns an error if the header is invalid.
|
// Validates a header. Returns an error if the header is invalid.
|
||||||
//
|
//
|
||||||
// See YP section 4.3.4. "Block Header Validity"
|
// See YP section 4.3.4. "Block Header Validity"
|
||||||
func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
|
func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
|
||||||
if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
|
if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
|
||||||
return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
|
return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
|
||||||
}
|
}
|
||||||
@ -219,7 +221,7 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
|
|||||||
return BlockEqualTSErr
|
return BlockEqualTSErr
|
||||||
}
|
}
|
||||||
|
|
||||||
expd := CalcDifficulty(header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty)
|
expd := CalcDifficulty(config, header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty)
|
||||||
if expd.Cmp(header.Difficulty) != 0 {
|
if expd.Cmp(header.Difficulty) != 0 {
|
||||||
return fmt.Errorf("Difficulty check failed for header %v, %v", header.Difficulty, expd)
|
return fmt.Errorf("Difficulty check failed for header %v, %v", header.Difficulty, expd)
|
||||||
}
|
}
|
||||||
@ -251,8 +253,8 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
|
|||||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns
|
// CalcDifficulty is the difficulty adjustment algorithm. It returns
|
||||||
// the difficulty that a new block should have when created at time
|
// the difficulty that a new block should have when created at time
|
||||||
// given the parent block's time and difficulty.
|
// given the parent block's time and difficulty.
|
||||||
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
func CalcDifficulty(config *ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||||
if params.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
|
if config.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
|
||||||
return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
|
return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
|
||||||
} else {
|
} else {
|
||||||
return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
|
return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
|
||||||
@ -363,11 +365,11 @@ func CalcGasLimit(parent *types.Block) *big.Int {
|
|||||||
gl = gl.Add(gl, contrib)
|
gl = gl.Add(gl, contrib)
|
||||||
gl.Set(common.BigMax(gl, params.MinGasLimit))
|
gl.Set(common.BigMax(gl, params.MinGasLimit))
|
||||||
|
|
||||||
// however, if we're now below the target (GenesisGasLimit) we increase the
|
// however, if we're now below the target (TargetGasLimit) we increase the
|
||||||
// limit as much as we can (parentGasLimit / 1024 -1)
|
// limit as much as we can (parentGasLimit / 1024 -1)
|
||||||
if gl.Cmp(params.GenesisGasLimit) < 0 {
|
if gl.Cmp(params.TargetGasLimit) < 0 {
|
||||||
gl.Add(parent.GasLimit(), decay)
|
gl.Add(parent.GasLimit(), decay)
|
||||||
gl.Set(common.BigMin(gl, params.GenesisGasLimit))
|
gl.Set(common.BigMin(gl, params.TargetGasLimit))
|
||||||
}
|
}
|
||||||
return gl
|
return gl
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,16 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/pow/ezp"
|
"github.com/ethereum/go-ethereum/pow/ezp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testChainConfig() *ChainConfig {
|
||||||
|
return &ChainConfig{HomesteadBlock: big.NewInt(0)}
|
||||||
|
}
|
||||||
|
|
||||||
func proc() (Validator, *BlockChain) {
|
func proc() (Validator, *BlockChain) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
var mux event.TypeMux
|
var mux event.TypeMux
|
||||||
|
|
||||||
WriteTestNetGenesisBlock(db)
|
WriteTestNetGenesisBlock(db)
|
||||||
blockchain, err := NewBlockChain(db, thePow(), &mux)
|
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &mux)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
@ -49,13 +53,14 @@ func TestNumber(t *testing.T) {
|
|||||||
statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
|
statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
|
||||||
header := makeHeader(chain.Genesis(), statedb)
|
header := makeHeader(chain.Genesis(), statedb)
|
||||||
header.Number = big.NewInt(3)
|
header.Number = big.NewInt(3)
|
||||||
err := ValidateHeader(pow, header, chain.Genesis().Header(), false, false)
|
cfg := testChainConfig()
|
||||||
|
err := ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
|
||||||
if err != BlockNumberErr {
|
if err != BlockNumberErr {
|
||||||
t.Errorf("expected block number error, got %q", err)
|
t.Errorf("expected block number error, got %q", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
header = makeHeader(chain.Genesis(), statedb)
|
header = makeHeader(chain.Genesis(), statedb)
|
||||||
err = ValidateHeader(pow, header, chain.Genesis().Header(), false, false)
|
err = ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
|
||||||
if err == BlockNumberErr {
|
if err == BlockNumberErr {
|
||||||
t.Errorf("didn't expect block number error")
|
t.Errorf("didn't expect block number error")
|
||||||
}
|
}
|
||||||
|
@ -80,11 +80,12 @@ const (
|
|||||||
// included in the canonical one where as GetBlockByNumber always represents the
|
// included in the canonical one where as GetBlockByNumber always represents the
|
||||||
// canonical chain.
|
// canonical chain.
|
||||||
type BlockChain struct {
|
type BlockChain struct {
|
||||||
|
config *ChainConfig // chain & network configuration
|
||||||
|
|
||||||
hc *HeaderChain
|
hc *HeaderChain
|
||||||
chainDb ethdb.Database
|
chainDb ethdb.Database
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
genesisBlock *types.Block
|
genesisBlock *types.Block
|
||||||
vmConfig *vm.Config
|
|
||||||
|
|
||||||
mu sync.RWMutex // global mutex for locking chain operations
|
mu sync.RWMutex // global mutex for locking chain operations
|
||||||
chainmu sync.RWMutex // blockchain insertion lock
|
chainmu sync.RWMutex // blockchain insertion lock
|
||||||
@ -113,13 +114,14 @@ type BlockChain struct {
|
|||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
// available in the database. It initialiser the default Ethereum Validator and
|
// available in the database. It initialiser the default Ethereum Validator and
|
||||||
// Processor.
|
// Processor.
|
||||||
func NewBlockChain(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
|
func NewBlockChain(chainDb ethdb.Database, config *ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
|
||||||
bodyCache, _ := lru.New(bodyCacheLimit)
|
bodyCache, _ := lru.New(bodyCacheLimit)
|
||||||
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
||||||
blockCache, _ := lru.New(blockCacheLimit)
|
blockCache, _ := lru.New(blockCacheLimit)
|
||||||
futureBlocks, _ := lru.New(maxFutureBlocks)
|
futureBlocks, _ := lru.New(maxFutureBlocks)
|
||||||
|
|
||||||
bc := &BlockChain{
|
bc := &BlockChain{
|
||||||
|
config: config,
|
||||||
chainDb: chainDb,
|
chainDb: chainDb,
|
||||||
eventMux: mux,
|
eventMux: mux,
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
@ -129,24 +131,21 @@ func NewBlockChain(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*Bl
|
|||||||
futureBlocks: futureBlocks,
|
futureBlocks: futureBlocks,
|
||||||
pow: pow,
|
pow: pow,
|
||||||
}
|
}
|
||||||
bc.SetValidator(NewBlockValidator(bc, pow))
|
bc.SetValidator(NewBlockValidator(config, bc, pow))
|
||||||
bc.SetProcessor(NewStateProcessor(bc))
|
bc.SetProcessor(NewStateProcessor(config, bc))
|
||||||
|
|
||||||
gv := func() HeaderValidator { return bc.Validator() }
|
gv := func() HeaderValidator { return bc.Validator() }
|
||||||
var err error
|
var err error
|
||||||
bc.hc, err = NewHeaderChain(chainDb, gv, bc.getProcInterrupt)
|
bc.hc, err = NewHeaderChain(chainDb, config, gv, bc.getProcInterrupt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.genesisBlock = bc.GetBlockByNumber(0)
|
bc.genesisBlock = bc.GetBlockByNumber(0)
|
||||||
if bc.genesisBlock == nil {
|
if bc.genesisBlock == nil {
|
||||||
bc.genesisBlock, err = WriteDefaultGenesisBlock(chainDb)
|
return nil, ErrNoGenesis
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bc.loadLastState(); err != nil {
|
if err := bc.loadLastState(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -163,10 +162,6 @@ func NewBlockChain(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*Bl
|
|||||||
return bc, nil
|
return bc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BlockChain) SetConfig(vmConfig *vm.Config) {
|
|
||||||
self.vmConfig = vmConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BlockChain) getProcInterrupt() bool {
|
func (self *BlockChain) getProcInterrupt() bool {
|
||||||
return atomic.LoadInt32(&self.procInterrupt) == 1
|
return atomic.LoadInt32(&self.procInterrupt) == 1
|
||||||
}
|
}
|
||||||
@ -896,7 +891,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
|||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
// Process block using the parent state as reference point.
|
// Process block using the parent state as reference point.
|
||||||
receipts, logs, usedGas, err := self.processor.Process(block, statedb, self.vmConfig)
|
receipts, logs, usedGas, err := self.processor.Process(block, statedb, self.config.VmConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportBlock(block, err)
|
reportBlock(block, err)
|
||||||
return i, err
|
return i, err
|
||||||
|
@ -53,7 +53,7 @@ func thePow() pow.PoW {
|
|||||||
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
|
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
|
||||||
var eventMux event.TypeMux
|
var eventMux event.TypeMux
|
||||||
WriteTestNetGenesisBlock(db)
|
WriteTestNetGenesisBlock(db)
|
||||||
blockchain, err := NewBlockChain(db, thePow(), &eventMux)
|
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &eventMux)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed creating blockchain:", err)
|
t.Error("failed creating blockchain:", err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@ -141,7 +141,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, nil)
|
receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportBlock(block, err)
|
reportBlock(block, err)
|
||||||
return err
|
return err
|
||||||
@ -435,7 +435,7 @@ func (bproc) ValidateHeader(*types.Header, *types.Header, bool) error { return n
|
|||||||
func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
|
func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg *vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
||||||
return nil, nil, nil, nil
|
return nil, nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,9 +477,10 @@ func chm(genesis *types.Block, db ethdb.Database) *BlockChain {
|
|||||||
genesisBlock: genesis,
|
genesisBlock: genesis,
|
||||||
eventMux: &eventMux,
|
eventMux: &eventMux,
|
||||||
pow: FakePow{},
|
pow: FakePow{},
|
||||||
|
config: testChainConfig(),
|
||||||
}
|
}
|
||||||
valFn := func() HeaderValidator { return bc.Validator() }
|
valFn := func() HeaderValidator { return bc.Validator() }
|
||||||
bc.hc, _ = NewHeaderChain(db, valFn, bc.getProcInterrupt)
|
bc.hc, _ = NewHeaderChain(db, testChainConfig(), valFn, bc.getProcInterrupt)
|
||||||
bc.bodyCache, _ = lru.New(100)
|
bc.bodyCache, _ = lru.New(100)
|
||||||
bc.bodyRLPCache, _ = lru.New(100)
|
bc.bodyRLPCache, _ = lru.New(100)
|
||||||
bc.blockCache, _ = lru.New(100)
|
bc.blockCache, _ = lru.New(100)
|
||||||
@ -613,7 +614,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
|
|||||||
defer func() { delete(BadHashes, headers[3].Hash()) }()
|
defer func() { delete(BadHashes, headers[3].Hash()) }()
|
||||||
}
|
}
|
||||||
// Create a new chain manager and check it rolled back the state
|
// Create a new chain manager and check it rolled back the state
|
||||||
ncm, err := NewBlockChain(db, FakePow{}, new(event.TypeMux))
|
ncm, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create new chain manager: %v", err)
|
t.Fatalf("failed to create new chain manager: %v", err)
|
||||||
}
|
}
|
||||||
@ -667,7 +668,7 @@ func testInsertNonceError(t *testing.T, full bool) {
|
|||||||
failHash = headers[failAt].Hash()
|
failHash = headers[failAt].Hash()
|
||||||
|
|
||||||
blockchain.pow = failPow{failNum}
|
blockchain.pow = failPow{failNum}
|
||||||
blockchain.validator = NewBlockValidator(blockchain, failPow{failNum})
|
blockchain.validator = NewBlockValidator(testChainConfig(), blockchain, failPow{failNum})
|
||||||
|
|
||||||
failRes, err = blockchain.InsertHeaderChain(headers, 1)
|
failRes, err = blockchain.InsertHeaderChain(headers, 1)
|
||||||
}
|
}
|
||||||
@ -733,7 +734,7 @@ func TestFastVsFullChains(t *testing.T) {
|
|||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, FakePow{}, new(event.TypeMux))
|
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
@ -741,7 +742,7 @@ func TestFastVsFullChains(t *testing.T) {
|
|||||||
// Fast import the chain as a non-archive node to test
|
// Fast import the chain as a non-archive node to test
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||||
fast, _ := NewBlockChain(fastDb, FakePow{}, new(event.TypeMux))
|
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
@ -817,7 +818,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
|||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, FakePow{}, new(event.TypeMux))
|
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
@ -829,7 +830,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
|||||||
// Import the chain as a non-archive node and ensure all pointers are updated
|
// Import the chain as a non-archive node and ensure all pointers are updated
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||||
fast, _ := NewBlockChain(fastDb, FakePow{}, new(event.TypeMux))
|
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
@ -848,7 +849,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
|||||||
// Import the chain as a light node and ensure all pointers are updated
|
// Import the chain as a light node and ensure all pointers are updated
|
||||||
lightDb, _ := ethdb.NewMemDatabase()
|
lightDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
|
||||||
light, _ := NewBlockChain(lightDb, FakePow{}, new(event.TypeMux))
|
light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
||||||
|
|
||||||
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
||||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||||
@ -913,7 +914,7 @@ func TestChainTxReorgs(t *testing.T) {
|
|||||||
})
|
})
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
||||||
}
|
}
|
||||||
@ -986,7 +987,7 @@ func TestLogReorgs(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
||||||
|
|
||||||
subs := evmux.Subscribe(RemovedLogsEvent{})
|
subs := evmux.Subscribe(RemovedLogsEvent{})
|
||||||
chain, _ := GenerateChain(genesis, db, 2, func(i int, gen *BlockGen) {
|
chain, _ := GenerateChain(genesis, db, 2, func(i int, gen *BlockGen) {
|
||||||
@ -1022,25 +1023,23 @@ func TestReorgSideEvent(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
||||||
|
|
||||||
chain, _ := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {
|
chain, _ := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {})
|
||||||
if i == 2 {
|
|
||||||
gen.OffsetTime(9)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
t.Fatalf("failed to insert chain: %v", err)
|
t.Fatalf("failed to insert chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
replacementBlocks, _ := GenerateChain(genesis, db, 4, func(i int, gen *BlockGen) {
|
replacementBlocks, _ := GenerateChain(genesis, db, 4, func(i int, gen *BlockGen) {
|
||||||
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(key1)
|
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(key1)
|
||||||
|
if i == 2 {
|
||||||
|
gen.OffsetTime(-1)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tx: %v", err)
|
t.Fatalf("failed to create tx: %v", err)
|
||||||
}
|
}
|
||||||
gen.AddTx(tx)
|
gen.AddTx(tx)
|
||||||
})
|
})
|
||||||
|
|
||||||
subs := evmux.Subscribe(ChainSideEvent{})
|
subs := evmux.Subscribe(ChainSideEvent{})
|
||||||
if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
|
if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
|
||||||
t.Fatalf("failed to insert chain: %v", err)
|
t.Fatalf("failed to insert chain: %v", err)
|
||||||
|
@ -23,11 +23,21 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/pow"
|
"github.com/ethereum/go-ethereum/pow"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: move this to another package.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// MakeChainConfig returns a new ChainConfig with the ethereum default chain settings.
|
||||||
|
func MakeChainConfig() *ChainConfig {
|
||||||
|
return &ChainConfig{HomesteadBlock: big.NewInt(0)}
|
||||||
|
}
|
||||||
|
|
||||||
// FakePow is a non-validating proof of work implementation.
|
// FakePow is a non-validating proof of work implementation.
|
||||||
// It returns true from Verify for any block.
|
// It returns true from Verify for any block.
|
||||||
type FakePow struct{}
|
type FakePow struct{}
|
||||||
@ -91,7 +101,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
|
|||||||
b.SetCoinbase(common.Address{})
|
b.SetCoinbase(common.Address{})
|
||||||
}
|
}
|
||||||
b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
|
b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
|
||||||
receipt, _, _, err := ApplyTransaction(nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, nil)
|
receipt, _, _, err := ApplyTransaction(MakeChainConfig(), nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -148,7 +158,7 @@ func (b *BlockGen) OffsetTime(seconds int64) {
|
|||||||
if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
|
if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
|
||||||
panic("block time out of range")
|
panic("block time out of range")
|
||||||
}
|
}
|
||||||
b.header.Difficulty = CalcDifficulty(b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
|
b.header.Difficulty = CalcDifficulty(MakeChainConfig(), b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateChain creates a chain of n blocks. The first block's
|
// GenerateChain creates a chain of n blocks. The first block's
|
||||||
@ -203,7 +213,7 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
|
|||||||
Root: state.IntermediateRoot(),
|
Root: state.IntermediateRoot(),
|
||||||
ParentHash: parent.Hash(),
|
ParentHash: parent.Hash(),
|
||||||
Coinbase: parent.Coinbase(),
|
Coinbase: parent.Coinbase(),
|
||||||
Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
|
Difficulty: CalcDifficulty(MakeChainConfig(), time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
|
||||||
GasLimit: CalcGasLimit(parent),
|
GasLimit: CalcGasLimit(parent),
|
||||||
GasUsed: new(big.Int),
|
GasUsed: new(big.Int),
|
||||||
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
||||||
@ -222,7 +232,7 @@ func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
|
|||||||
// Initialize a fresh chain with only a genesis block
|
// Initialize a fresh chain with only a genesis block
|
||||||
genesis, _ := WriteTestNetGenesisBlock(db)
|
genesis, _ := WriteTestNetGenesisBlock(db)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
|
||||||
// Create and inject the requested chain
|
// Create and inject the requested chain
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return db, blockchain, nil
|
return db, blockchain, nil
|
||||||
|
@ -77,7 +77,7 @@ func ExampleGenerateChain() {
|
|||||||
|
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
fmt.Printf("insert error (block %d): %v\n", i, err)
|
fmt.Printf("insert error (block %d): %v\n", i, err)
|
||||||
return
|
return
|
||||||
|
46
core/config.go
Normal file
46
core/config.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
|
||||||
|
|
||||||
|
// ChainConfig is the core config which determines the blockchain settings.
|
||||||
|
//
|
||||||
|
// ChainConfig is stored in the database on a per block basis. This means
|
||||||
|
// that any network, identified by its genesis block, can have its own
|
||||||
|
// set of configuration options.
|
||||||
|
type ChainConfig struct {
|
||||||
|
HomesteadBlock *big.Int // homestead switch block
|
||||||
|
|
||||||
|
VmConfig vm.Config `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHomestead returns whether num is either equal to the homestead block or greater.
|
||||||
|
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
|
||||||
|
if num == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return num.Cmp(c.HomesteadBlock) >= 0
|
||||||
|
}
|
@ -19,6 +19,7 @@ package core
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
@ -50,6 +51,8 @@ var (
|
|||||||
MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
|
MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
|
||||||
|
|
||||||
blockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
|
blockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
|
||||||
|
|
||||||
|
configPrefix = []byte("ethereum-config-") // config prefix for the db
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetCanonicalHash retrieves a hash assigned to a canonical block number.
|
// GetCanonicalHash retrieves a hash assigned to a canonical block number.
|
||||||
@ -527,3 +530,34 @@ func WriteBlockChainVersion(db ethdb.Database, vsn int) {
|
|||||||
enc, _ := rlp.EncodeToBytes(uint(vsn))
|
enc, _ := rlp.EncodeToBytes(uint(vsn))
|
||||||
db.Put([]byte("BlockchainVersion"), enc)
|
db.Put([]byte("BlockchainVersion"), enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteChainConfig writes the chain config settings to the database.
|
||||||
|
func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *ChainConfig) error {
|
||||||
|
// short circuit and ignore if nil config. GetChainConfig
|
||||||
|
// will return a default.
|
||||||
|
if cfg == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonChainConfig, err := json.Marshal(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.Put(append(configPrefix, hash[:]...), jsonChainConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChainConfig will fetch the network settings based on the given hash.
|
||||||
|
func GetChainConfig(db ethdb.Database, hash common.Hash) (*ChainConfig, error) {
|
||||||
|
jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...))
|
||||||
|
if len(jsonChainConfig) == 0 {
|
||||||
|
return nil, ChainConfigNotFoundErr
|
||||||
|
}
|
||||||
|
|
||||||
|
var config ChainConfig
|
||||||
|
if err := json.Unmarshal(jsonChainConfig, &config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &config, nil
|
||||||
|
}
|
||||||
|
@ -126,7 +126,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
|
|||||||
// When an error was returned by the EVM or when setting the creation code
|
// When an error was returned by the EVM or when setting the creation code
|
||||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||||
// when we're in homestead this also counts for code storage gas errors.
|
// when we're in homestead this also counts for code storage gas errors.
|
||||||
if err != nil && (params.IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
|
if err != nil && (env.RuleSet().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
|
||||||
contract.UseGas(contract.Gas)
|
contract.UseGas(contract.Gas)
|
||||||
|
|
||||||
env.SetSnapshot(snapshotPreTransfer)
|
env.SetSnapshot(snapshotPreTransfer)
|
||||||
|
@ -43,6 +43,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var genesis struct {
|
var genesis struct {
|
||||||
|
ChainConfig *ChainConfig
|
||||||
Nonce string
|
Nonce string
|
||||||
Timestamp string
|
Timestamp string
|
||||||
ParentHash string
|
ParentHash string
|
||||||
@ -114,6 +115,10 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
|
|||||||
if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil {
|
if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := WriteChainConfig(chainDb, block.Hash(), genesis.ChainConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return block, nil
|
return block, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ import (
|
|||||||
// It is not thread safe either, the encapsulating chain structures should do
|
// It is not thread safe either, the encapsulating chain structures should do
|
||||||
// the necessary mutex locking/unlocking.
|
// the necessary mutex locking/unlocking.
|
||||||
type HeaderChain struct {
|
type HeaderChain struct {
|
||||||
|
config *ChainConfig
|
||||||
|
|
||||||
chainDb ethdb.Database
|
chainDb ethdb.Database
|
||||||
genesisHeader *types.Header
|
genesisHeader *types.Header
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ type getHeaderValidatorFn func() HeaderValidator
|
|||||||
// getValidator should return the parent's validator
|
// getValidator should return the parent's validator
|
||||||
// procInterrupt points to the parent's interrupt semaphore
|
// procInterrupt points to the parent's interrupt semaphore
|
||||||
// wg points to the parent's shutdown wait group
|
// wg points to the parent's shutdown wait group
|
||||||
func NewHeaderChain(chainDb ethdb.Database, getValidator getHeaderValidatorFn, procInterrupt func() bool) (*HeaderChain, error) {
|
func NewHeaderChain(chainDb ethdb.Database, config *ChainConfig, getValidator getHeaderValidatorFn, procInterrupt func() bool) (*HeaderChain, error) {
|
||||||
headerCache, _ := lru.New(headerCacheLimit)
|
headerCache, _ := lru.New(headerCacheLimit)
|
||||||
tdCache, _ := lru.New(tdCacheLimit)
|
tdCache, _ := lru.New(tdCacheLimit)
|
||||||
|
|
||||||
@ -73,6 +75,7 @@ func NewHeaderChain(chainDb ethdb.Database, getValidator getHeaderValidatorFn, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
hc := &HeaderChain{
|
hc := &HeaderChain{
|
||||||
|
config: config,
|
||||||
chainDb: chainDb,
|
chainDb: chainDb,
|
||||||
headerCache: headerCache,
|
headerCache: headerCache,
|
||||||
tdCache: tdCache,
|
tdCache: tdCache,
|
||||||
@ -436,13 +439,15 @@ func (hc *HeaderChain) SetGenesis(head *types.Header) {
|
|||||||
//
|
//
|
||||||
// headerValidator implements HeaderValidator.
|
// headerValidator implements HeaderValidator.
|
||||||
type headerValidator struct {
|
type headerValidator struct {
|
||||||
|
config *ChainConfig
|
||||||
hc *HeaderChain // Canonical header chain
|
hc *HeaderChain // Canonical header chain
|
||||||
Pow pow.PoW // Proof of work used for validating
|
Pow pow.PoW // Proof of work used for validating
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockValidator returns a new block validator which is safe for re-use
|
// NewBlockValidator returns a new block validator which is safe for re-use
|
||||||
func NewHeaderValidator(chain *HeaderChain, pow pow.PoW) HeaderValidator {
|
func NewHeaderValidator(config *ChainConfig, chain *HeaderChain, pow pow.PoW) HeaderValidator {
|
||||||
return &headerValidator{
|
return &headerValidator{
|
||||||
|
config: config,
|
||||||
Pow: pow,
|
Pow: pow,
|
||||||
hc: chain,
|
hc: chain,
|
||||||
}
|
}
|
||||||
@ -460,5 +465,5 @@ func (v *headerValidator) ValidateHeader(header, parent *types.Header, checkPow
|
|||||||
if v.hc.HasHeader(header.Hash()) {
|
if v.hc.HasHeader(header.Hash()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ValidateHeader(v.Pow, header, parent, checkPow, false)
|
return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false)
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,21 @@ var (
|
|||||||
big32 = big.NewInt(32)
|
big32 = big.NewInt(32)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StateProcessor is a basic Processor, which takes care of transitioning
|
||||||
|
// state from one point to another.
|
||||||
|
//
|
||||||
|
// StateProcessor implements Processor.
|
||||||
type StateProcessor struct {
|
type StateProcessor struct {
|
||||||
|
config *ChainConfig
|
||||||
bc *BlockChain
|
bc *BlockChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateProcessor(bc *BlockChain) *StateProcessor {
|
// NewStateProcessor initialises a new StateProcessor.
|
||||||
return &StateProcessor{bc}
|
func NewStateProcessor(config *ChainConfig, bc *BlockChain) *StateProcessor {
|
||||||
|
return &StateProcessor{
|
||||||
|
config: config,
|
||||||
|
bc: bc,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process processes the state changes according to the Ethereum rules by running
|
// Process processes the state changes according to the Ethereum rules by running
|
||||||
@ -31,7 +40,7 @@ func NewStateProcessor(bc *BlockChain) *StateProcessor {
|
|||||||
// Process returns the receipts and logs accumulated during the process and
|
// Process returns the receipts and logs accumulated during the process and
|
||||||
// returns the amount of gas that was used in the process. If any of the
|
// returns the amount of gas that was used in the process. If any of the
|
||||||
// transactions failed to execute due to insufficient gas it will return an error.
|
// transactions failed to execute due to insufficient gas it will return an error.
|
||||||
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg *vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
||||||
var (
|
var (
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
totalUsedGas = big.NewInt(0)
|
totalUsedGas = big.NewInt(0)
|
||||||
@ -43,7 +52,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
|
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
||||||
receipt, logs, _, err := ApplyTransaction(p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
|
receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, totalUsedGas, err
|
return nil, nil, totalUsedGas, err
|
||||||
}
|
}
|
||||||
@ -60,8 +69,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
//
|
//
|
||||||
// ApplyTransactions returns the generated receipts and vm logs during the
|
// ApplyTransactions returns the generated receipts and vm logs during the
|
||||||
// execution of the state transition phase.
|
// execution of the state transition phase.
|
||||||
func ApplyTransaction(bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg *vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
|
func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
|
||||||
_, gas, err := ApplyMessage(NewEnv(statedb, bc, tx, header, cfg), tx, gp)
|
_, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), tx, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,9 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
|
|||||||
return igas
|
return igas
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
|
// NewStateTransition initialises and returns a new state transition object.
|
||||||
var st = StateTransition{
|
func NewStateTransition(env vm.Environment, msg Message, gp *GasPool) *StateTransition {
|
||||||
|
return &StateTransition{
|
||||||
gp: gp,
|
gp: gp,
|
||||||
env: env,
|
env: env,
|
||||||
msg: msg,
|
msg: msg,
|
||||||
@ -116,7 +117,20 @@ func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.In
|
|||||||
data: msg.Data(),
|
data: msg.Data(),
|
||||||
state: env.Db(),
|
state: env.Db(),
|
||||||
}
|
}
|
||||||
return st.transitionDb()
|
}
|
||||||
|
|
||||||
|
// ApplyMessage computes the new state by applying the given message
|
||||||
|
// against the old state within the environment.
|
||||||
|
//
|
||||||
|
// ApplyMessage returns the bytes returned by any EVM execution (if it took place),
|
||||||
|
// the gas used (which includes gas refunds) and an error if it failed. An error always
|
||||||
|
// indicates a core error meaning that the message would always fail for that particular
|
||||||
|
// state and would never be accepted within a block.
|
||||||
|
func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
|
||||||
|
st := NewStateTransition(env, msg, gp)
|
||||||
|
|
||||||
|
ret, _, gasUsed, err := st.TransitionDb()
|
||||||
|
return ret, gasUsed, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) from() (vm.Account, error) {
|
func (self *StateTransition) from() (vm.Account, error) {
|
||||||
@ -124,7 +138,7 @@ func (self *StateTransition) from() (vm.Account, error) {
|
|||||||
f common.Address
|
f common.Address
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if params.IsHomestead(self.env.BlockNumber()) {
|
if self.env.RuleSet().IsHomestead(self.env.BlockNumber()) {
|
||||||
f, err = self.msg.From()
|
f, err = self.msg.From()
|
||||||
} else {
|
} else {
|
||||||
f, err = self.msg.FromFrontier()
|
f, err = self.msg.FromFrontier()
|
||||||
@ -209,18 +223,19 @@ func (self *StateTransition) preCheck() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err error) {
|
// TransitionDb will move the state by applying the message against the given environment.
|
||||||
|
func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, err error) {
|
||||||
if err = self.preCheck(); err != nil {
|
if err = self.preCheck(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
msg := self.msg
|
msg := self.msg
|
||||||
sender, _ := self.from() // err checked in preCheck
|
sender, _ := self.from() // err checked in preCheck
|
||||||
|
|
||||||
homestead := params.IsHomestead(self.env.BlockNumber())
|
homestead := self.env.RuleSet().IsHomestead(self.env.BlockNumber())
|
||||||
contractCreation := MessageCreatesContract(msg)
|
contractCreation := MessageCreatesContract(msg)
|
||||||
// Pay intrinsic gas
|
// Pay intrinsic gas
|
||||||
if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
|
if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
|
||||||
return nil, nil, InvalidTxError(err)
|
return nil, nil, nil, InvalidTxError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
vmenv := self.env
|
vmenv := self.env
|
||||||
@ -245,7 +260,7 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil && IsValueTransferErr(err) {
|
if err != nil && IsValueTransferErr(err) {
|
||||||
return nil, nil, InvalidTxError(err)
|
return nil, nil, nil, InvalidTxError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up
|
// We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up
|
||||||
@ -253,10 +268,12 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
|
|||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requiredGas = new(big.Int).Set(self.gasUsed())
|
||||||
|
|
||||||
self.refundGas()
|
self.refundGas()
|
||||||
self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice))
|
self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice))
|
||||||
|
|
||||||
return ret, self.gasUsed(), err
|
return ret, requiredGas, self.gasUsed(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) refundGas() {
|
func (self *StateTransition) refundGas() {
|
||||||
|
@ -30,7 +30,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -60,6 +59,7 @@ type stateFn func() (*state.StateDB, error)
|
|||||||
// current state) and future transactions. Transactions move between those
|
// current state) and future transactions. Transactions move between those
|
||||||
// two states over time as they are received and processed.
|
// two states over time as they are received and processed.
|
||||||
type TxPool struct {
|
type TxPool struct {
|
||||||
|
config *ChainConfig
|
||||||
quit chan bool // Quitting channel
|
quit chan bool // Quitting channel
|
||||||
currentState stateFn // The state function which will allow us to do some pre checks
|
currentState stateFn // The state function which will allow us to do some pre checks
|
||||||
pendingState *state.ManagedState
|
pendingState *state.ManagedState
|
||||||
@ -75,8 +75,9 @@ type TxPool struct {
|
|||||||
homestead bool
|
homestead bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
|
func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
|
||||||
pool := &TxPool{
|
pool := &TxPool{
|
||||||
|
config: config,
|
||||||
pending: make(map[common.Hash]*types.Transaction),
|
pending: make(map[common.Hash]*types.Transaction),
|
||||||
queue: make(map[common.Address]map[common.Hash]*types.Transaction),
|
queue: make(map[common.Address]map[common.Hash]*types.Transaction),
|
||||||
quit: make(chan bool),
|
quit: make(chan bool),
|
||||||
@ -102,7 +103,7 @@ func (pool *TxPool) eventLoop() {
|
|||||||
switch ev := ev.Data.(type) {
|
switch ev := ev.Data.(type) {
|
||||||
case ChainHeadEvent:
|
case ChainHeadEvent:
|
||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
if ev.Block != nil && params.IsHomestead(ev.Block.Number()) {
|
if ev.Block != nil && pool.config.IsHomestead(ev.Block.Number()) {
|
||||||
pool.homestead = true
|
pool.homestead = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
|||||||
|
|
||||||
var m event.TypeMux
|
var m event.TypeMux
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
newPool := NewTxPool(&m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
newPool := NewTxPool(testChainConfig(), &m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||||
newPool.resetState()
|
newPool.resetState()
|
||||||
return newPool, key
|
return newPool, key
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ type HeaderValidator interface {
|
|||||||
// of gas used in the process and return an error if any of the internal rules
|
// of gas used in the process and return an error if any of the internal rules
|
||||||
// failed.
|
// failed.
|
||||||
type Processor interface {
|
type Processor interface {
|
||||||
Process(block *types.Block, statedb *state.StateDB, cfg *vm.Config) (types.Receipts, vm.Logs, *big.Int, error)
|
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backend is an interface defining the basic functionality for an operable node
|
// Backend is an interface defining the basic functionality for an operable node
|
||||||
|
@ -22,9 +22,17 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RuleSet is an interface that defines the current rule set during the
|
||||||
|
// execution of the EVM instructions (e.g. whether it's homestead)
|
||||||
|
type RuleSet interface {
|
||||||
|
IsHomestead(*big.Int) bool
|
||||||
|
}
|
||||||
|
|
||||||
// Environment is an EVM requirement and helper which allows access to outside
|
// Environment is an EVM requirement and helper which allows access to outside
|
||||||
// information such as states.
|
// information such as states.
|
||||||
type Environment interface {
|
type Environment interface {
|
||||||
|
// The current ruleset
|
||||||
|
RuleSet() RuleSet
|
||||||
// The state database
|
// The state database
|
||||||
Db() Database
|
Db() Database
|
||||||
// Creates a restorable snapshot
|
// Creates a restorable snapshot
|
||||||
@ -53,10 +61,10 @@ type Environment interface {
|
|||||||
AddLog(*Log)
|
AddLog(*Log)
|
||||||
// Type of the VM
|
// Type of the VM
|
||||||
Vm() Vm
|
Vm() Vm
|
||||||
// Current calling depth
|
// Get the curret calling depth
|
||||||
Depth() int
|
Depth() int
|
||||||
|
// Set the current calling depth
|
||||||
SetDepth(i int)
|
SetDepth(i int)
|
||||||
|
|
||||||
// Call another contract
|
// Call another contract
|
||||||
Call(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
|
Call(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
|
||||||
// Take another's contract code and execute within our own context
|
// Take another's contract code and execute within our own context
|
||||||
|
@ -520,7 +520,7 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
|
|||||||
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
// homestead we must check for CodeStoreOutOfGasError (homestead only
|
||||||
// rule) and treat as an error, if the ruleset is frontier we must
|
// rule) and treat as an error, if the ruleset is frontier we must
|
||||||
// ignore this error and pretend the operation was successful.
|
// ignore this error and pretend the operation was successful.
|
||||||
if params.IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
|
if env.RuleSet().IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
|
||||||
stack.push(new(big.Int))
|
stack.push(new(big.Int))
|
||||||
} else if suberr != nil && suberr != CodeStoreOutOfGasError {
|
} else if suberr != nil && suberr != CodeStoreOutOfGasError {
|
||||||
stack.push(new(big.Int))
|
stack.push(new(big.Int))
|
||||||
|
@ -30,27 +30,24 @@ import (
|
|||||||
"github.com/hashicorp/golang-lru"
|
"github.com/hashicorp/golang-lru"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// progStatus is the type for the JIT program status.
|
||||||
type progStatus int32
|
type progStatus int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
progUnknown progStatus = iota
|
progUnknown progStatus = iota // unknown status
|
||||||
progCompile
|
progCompile // compile status
|
||||||
progReady
|
progReady // ready for use status
|
||||||
progError
|
progError // error status (usually caused during compilation)
|
||||||
|
|
||||||
defaultJitMaxCache int = 64
|
defaultJitMaxCache int = 64 // maximum amount of jit cached programs
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var MaxProgSize int // Max cache size for JIT programs
|
||||||
EnableJit bool // Enables the JIT VM
|
|
||||||
ForceJit bool // Force the JIT, skip byte VM
|
|
||||||
MaxProgSize int // Max cache size for JIT Programs
|
|
||||||
)
|
|
||||||
|
|
||||||
var programs *lru.Cache
|
var programs *lru.Cache // lru cache for the JIT programs.
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
programs, _ = lru.New(defaultJitMaxCache)
|
SetJITCacheSize(defaultJitMaxCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetJITCacheSize recreates the program cache with the max given size. Setting
|
// SetJITCacheSize recreates the program cache with the max given size. Setting
|
||||||
@ -322,7 +319,7 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
homestead := params.IsHomestead(env.BlockNumber())
|
homestead := env.RuleSet().IsHomestead(env.BlockNumber())
|
||||||
for pc < uint64(len(program.instructions)) {
|
for pc < uint64(len(program.instructions)) {
|
||||||
instrCount++
|
instrCount++
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ func TestCompiling(t *testing.T) {
|
|||||||
func TestResetInput(t *testing.T) {
|
func TestResetInput(t *testing.T) {
|
||||||
var sender account
|
var sender account
|
||||||
|
|
||||||
env := NewEnv()
|
env := NewEnv(false, true)
|
||||||
contract := NewContract(sender, sender, big.NewInt(100), big.NewInt(10000), big.NewInt(0))
|
contract := NewContract(sender, sender, big.NewInt(100), big.NewInt(10000), big.NewInt(0))
|
||||||
contract.CodeAddr = &common.Address{}
|
contract.CodeAddr = &common.Address{}
|
||||||
|
|
||||||
@ -143,10 +143,7 @@ func runVmBench(test vmBench, b *testing.B) {
|
|||||||
if test.precompile && !test.forcejit {
|
if test.precompile && !test.forcejit {
|
||||||
NewProgram(test.code)
|
NewProgram(test.code)
|
||||||
}
|
}
|
||||||
env := NewEnv()
|
env := NewEnv(test.nojit, test.forcejit)
|
||||||
|
|
||||||
EnableJit = !test.nojit
|
|
||||||
ForceJit = test.forcejit
|
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
@ -168,12 +165,16 @@ type Env struct {
|
|||||||
evm *EVM
|
evm *EVM
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEnv() *Env {
|
func NewEnv(noJit, forceJit bool) *Env {
|
||||||
env := &Env{gasLimit: big.NewInt(10000), depth: 0}
|
env := &Env{gasLimit: big.NewInt(10000), depth: 0}
|
||||||
env.evm = New(env, nil)
|
env.evm = New(env, Config{
|
||||||
|
EnableJit: !noJit,
|
||||||
|
ForceJit: forceJit,
|
||||||
|
})
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Env) RuleSet() RuleSet { return ruleSet{new(big.Int)} }
|
||||||
func (self *Env) Vm() Vm { return self.evm }
|
func (self *Env) Vm() Vm { return self.evm }
|
||||||
func (self *Env) Origin() common.Address { return common.Address{} }
|
func (self *Env) Origin() common.Address { return common.Address{} }
|
||||||
func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
|
func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import "math/big"
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
|
||||||
|
|
||||||
type jumpPtr struct {
|
type jumpPtr struct {
|
||||||
fn instrFn
|
fn instrFn
|
||||||
@ -13,12 +9,12 @@ type jumpPtr struct {
|
|||||||
|
|
||||||
type vmJumpTable [256]jumpPtr
|
type vmJumpTable [256]jumpPtr
|
||||||
|
|
||||||
func newJumpTable(blockNumber *big.Int) vmJumpTable {
|
func newJumpTable(ruleset RuleSet, blockNumber *big.Int) vmJumpTable {
|
||||||
var jumpTable vmJumpTable
|
var jumpTable vmJumpTable
|
||||||
|
|
||||||
// when initialising a new VM execution we must first check the homestead
|
// when initialising a new VM execution we must first check the homestead
|
||||||
// changes.
|
// changes.
|
||||||
if params.IsHomestead(blockNumber) {
|
if ruleset.IsHomestead(blockNumber) {
|
||||||
jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
|
jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,20 +3,16 @@ package vm
|
|||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInit(t *testing.T) {
|
func TestInit(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1)
|
jumpTable := newJumpTable(ruleSet{big.NewInt(1)}, big.NewInt(0))
|
||||||
|
|
||||||
jumpTable := newJumpTable(big.NewInt(0))
|
|
||||||
if jumpTable[DELEGATECALL].valid {
|
if jumpTable[DELEGATECALL].valid {
|
||||||
t.Error("Expected DELEGATECALL not to be present")
|
t.Error("Expected DELEGATECALL not to be present")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range []int64{1, 2, 100} {
|
for _, n := range []int64{1, 2, 100} {
|
||||||
jumpTable := newJumpTable(big.NewInt(n))
|
jumpTable := newJumpTable(ruleSet{big.NewInt(1)}, big.NewInt(n))
|
||||||
if !jumpTable[DELEGATECALL].valid {
|
if !jumpTable[DELEGATECALL].valid {
|
||||||
t.Error("Expected DELEGATECALL to be present for block", n)
|
t.Error("Expected DELEGATECALL to be present for block", n)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ func newLogger(cfg LogConfig, env Environment) *Logger {
|
|||||||
// captureState logs a new structured log message and pushes it out to the environment
|
// captureState logs a new structured log message and pushes it out to the environment
|
||||||
//
|
//
|
||||||
// captureState also tracks SSTORE ops to track dirty values.
|
// captureState also tracks SSTORE ops to track dirty values.
|
||||||
func (l *Logger) captureState(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, contract *Contract, err error) {
|
func (l *Logger) captureState(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, contract *Contract, depth int, err error) {
|
||||||
// short circuit if no log collector is present
|
// short circuit if no log collector is present
|
||||||
if l.cfg.Collector == nil {
|
if l.cfg.Collector == nil {
|
||||||
return
|
return
|
||||||
|
@ -47,7 +47,7 @@ type dummyEnv struct {
|
|||||||
|
|
||||||
func newDummyEnv(ref *dummyContractRef) *dummyEnv {
|
func newDummyEnv(ref *dummyContractRef) *dummyEnv {
|
||||||
return &dummyEnv{
|
return &dummyEnv{
|
||||||
Env: NewEnv(),
|
Env: NewEnv(true, false),
|
||||||
ref: ref,
|
ref: ref,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ func (d dummyEnv) AddStructLog(StructLog) {}
|
|||||||
|
|
||||||
func TestStoreCapture(t *testing.T) {
|
func TestStoreCapture(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEnv()
|
env = NewEnv(true, false)
|
||||||
logger = newLogger(LogConfig{Collector: env}, env)
|
logger = newLogger(LogConfig{Collector: env}, env)
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
@ -69,7 +69,7 @@ func TestStoreCapture(t *testing.T) {
|
|||||||
|
|
||||||
var index common.Hash
|
var index common.Hash
|
||||||
|
|
||||||
logger.captureState(0, SSTORE, new(big.Int), new(big.Int), mem, stack, contract, nil)
|
logger.captureState(0, SSTORE, new(big.Int), new(big.Int), mem, stack, contract, 0, nil)
|
||||||
if len(logger.changedValues[contract.Address()]) == 0 {
|
if len(logger.changedValues[contract.Address()]) == 0 {
|
||||||
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), len(logger.changedValues[contract.Address()]))
|
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), len(logger.changedValues[contract.Address()]))
|
||||||
}
|
}
|
||||||
@ -91,13 +91,13 @@ func TestStorageCapture(t *testing.T) {
|
|||||||
stack = newstack()
|
stack = newstack()
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, nil)
|
logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, 0, nil)
|
||||||
if ref.calledForEach {
|
if ref.calledForEach {
|
||||||
t.Error("didn't expect for each to be called")
|
t.Error("didn't expect for each to be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger = newLogger(LogConfig{Collector: env, FullStorage: true}, env)
|
logger = newLogger(LogConfig{Collector: env, FullStorage: true}, env)
|
||||||
logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, nil)
|
logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, 0, nil)
|
||||||
if !ref.calledForEach {
|
if !ref.calledForEach {
|
||||||
t.Error("expected for each to be called")
|
t.Error("expected for each to be called")
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
|
|
||||||
// Env is a basic runtime environment required for running the EVM.
|
// Env is a basic runtime environment required for running the EVM.
|
||||||
type Env struct {
|
type Env struct {
|
||||||
|
ruleSet vm.RuleSet
|
||||||
depth int
|
depth int
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ type Env struct {
|
|||||||
// NewEnv returns a new vm.Environment
|
// NewEnv returns a new vm.Environment
|
||||||
func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
|
func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
|
||||||
env := &Env{
|
env := &Env{
|
||||||
|
ruleSet: cfg.RuleSet,
|
||||||
state: state,
|
state: state,
|
||||||
origin: cfg.Origin,
|
origin: cfg.Origin,
|
||||||
coinbase: cfg.Coinbase,
|
coinbase: cfg.Coinbase,
|
||||||
@ -56,7 +58,7 @@ func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
|
|||||||
difficulty: cfg.Difficulty,
|
difficulty: cfg.Difficulty,
|
||||||
gasLimit: cfg.GasLimit,
|
gasLimit: cfg.GasLimit,
|
||||||
}
|
}
|
||||||
env.evm = vm.New(env, &vm.Config{
|
env.evm = vm.New(env, vm.Config{
|
||||||
Debug: cfg.Debug,
|
Debug: cfg.Debug,
|
||||||
EnableJit: !cfg.DisableJit,
|
EnableJit: !cfg.DisableJit,
|
||||||
ForceJit: !cfg.DisableJit,
|
ForceJit: !cfg.DisableJit,
|
||||||
@ -77,6 +79,7 @@ func (self *Env) AddStructLog(log vm.StructLog) {
|
|||||||
self.logs = append(self.logs, log)
|
self.logs = append(self.logs, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Env) RuleSet() vm.RuleSet { return self.ruleSet }
|
||||||
func (self *Env) Vm() vm.Vm { return self.evm }
|
func (self *Env) Vm() vm.Vm { return self.evm }
|
||||||
func (self *Env) Origin() common.Address { return self.origin }
|
func (self *Env) Origin() common.Address { return self.origin }
|
||||||
func (self *Env) BlockNumber() *big.Int { return self.number }
|
func (self *Env) BlockNumber() *big.Int { return self.number }
|
||||||
|
@ -22,13 +22,20 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The default, always homestead, rule set for the vm env
|
||||||
|
type ruleSet struct{}
|
||||||
|
|
||||||
|
func (ruleSet) IsHomestead(*big.Int) bool { return true }
|
||||||
|
|
||||||
// Config is a basic type specifying certain configuration flags for running
|
// Config is a basic type specifying certain configuration flags for running
|
||||||
// the EVM.
|
// the EVM.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
RuleSet vm.RuleSet
|
||||||
Difficulty *big.Int
|
Difficulty *big.Int
|
||||||
Origin common.Address
|
Origin common.Address
|
||||||
Coinbase common.Address
|
Coinbase common.Address
|
||||||
@ -46,6 +53,10 @@ type Config struct {
|
|||||||
|
|
||||||
// sets defaults on the config
|
// sets defaults on the config
|
||||||
func setDefaults(cfg *Config) {
|
func setDefaults(cfg *Config) {
|
||||||
|
if cfg.RuleSet == nil {
|
||||||
|
cfg.RuleSet = ruleSet{}
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.Difficulty == nil {
|
if cfg.Difficulty == nil {
|
||||||
cfg.Difficulty = new(big.Int)
|
cfg.Difficulty = new(big.Int)
|
||||||
}
|
}
|
||||||
|
9
core/vm/util_test.go
Normal file
9
core/vm/util_test.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package vm
|
||||||
|
|
||||||
|
import "math/big"
|
||||||
|
|
||||||
|
type ruleSet struct {
|
||||||
|
hs *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ruleSet) IsHomestead(n *big.Int) bool { return n.Cmp(r.hs) >= 0 }
|
@ -43,18 +43,13 @@ type Config struct {
|
|||||||
type EVM struct {
|
type EVM struct {
|
||||||
env Environment
|
env Environment
|
||||||
jumpTable vmJumpTable
|
jumpTable vmJumpTable
|
||||||
cfg *Config
|
cfg Config
|
||||||
|
|
||||||
logger *Logger
|
logger *Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new instance of the EVM.
|
// New returns a new instance of the EVM.
|
||||||
func New(env Environment, cfg *Config) *EVM {
|
func New(env Environment, cfg Config) *EVM {
|
||||||
// initialise a default config if none is present
|
|
||||||
if cfg == nil {
|
|
||||||
cfg = new(Config)
|
|
||||||
}
|
|
||||||
|
|
||||||
var logger *Logger
|
var logger *Logger
|
||||||
if cfg.Debug {
|
if cfg.Debug {
|
||||||
logger = newLogger(cfg.Logger, env)
|
logger = newLogger(cfg.Logger, env)
|
||||||
@ -62,7 +57,7 @@ func New(env Environment, cfg *Config) *EVM {
|
|||||||
|
|
||||||
return &EVM{
|
return &EVM{
|
||||||
env: env,
|
env: env,
|
||||||
jumpTable: newJumpTable(env.BlockNumber()),
|
jumpTable: newJumpTable(env.RuleSet(), env.BlockNumber()),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
}
|
}
|
||||||
@ -154,7 +149,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
|||||||
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
|
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil && evm.cfg.Debug {
|
if err != nil && evm.cfg.Debug {
|
||||||
evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, err)
|
evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -196,7 +191,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
|
|||||||
mem.Resize(newMemSize.Uint64())
|
mem.Resize(newMemSize.Uint64())
|
||||||
// Add a log message
|
// Add a log message
|
||||||
if evm.cfg.Debug {
|
if evm.cfg.Debug {
|
||||||
evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, nil)
|
evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opPtr := evm.jumpTable[op]; opPtr.valid {
|
if opPtr := evm.jumpTable[op]; opPtr.valid {
|
||||||
|
@ -22,5 +22,5 @@ import "fmt"
|
|||||||
|
|
||||||
func NewJitVm(env Environment) VirtualMachine {
|
func NewJitVm(env Environment) VirtualMachine {
|
||||||
fmt.Printf("Warning! EVM JIT not enabled.\n")
|
fmt.Printf("Warning! EVM JIT not enabled.\n")
|
||||||
return New(env, nil)
|
return New(env, Config{})
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ func GetHashFn(ref common.Hash, chain *BlockChain) func(n uint64) common.Hash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VMEnv struct {
|
type VMEnv struct {
|
||||||
|
chainConfig *ChainConfig // Chain configuration
|
||||||
state *state.StateDB // State to use for executing
|
state *state.StateDB // State to use for executing
|
||||||
evm *vm.EVM // The Ethereum Virtual Machine
|
evm *vm.EVM // The Ethereum Virtual Machine
|
||||||
depth int // Current execution depth
|
depth int // Current execution depth
|
||||||
@ -50,11 +51,11 @@ type VMEnv struct {
|
|||||||
chain *BlockChain // Blockchain handle
|
chain *BlockChain // Blockchain handle
|
||||||
logs []vm.StructLog // Logs for the custom structured logger
|
logs []vm.StructLog // Logs for the custom structured logger
|
||||||
getHashFn func(uint64) common.Hash // getHashFn callback is used to retrieve block hashes
|
getHashFn func(uint64) common.Hash // getHashFn callback is used to retrieve block hashes
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEnv(state *state.StateDB, chain *BlockChain, msg Message, header *types.Header, cfg *vm.Config) *VMEnv {
|
func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, msg Message, header *types.Header, cfg vm.Config) *VMEnv {
|
||||||
env := &VMEnv{
|
env := &VMEnv{
|
||||||
|
chainConfig: chainConfig,
|
||||||
chain: chain,
|
chain: chain,
|
||||||
state: state,
|
state: state,
|
||||||
header: header,
|
header: header,
|
||||||
@ -62,11 +63,6 @@ func NewEnv(state *state.StateDB, chain *BlockChain, msg Message, header *types.
|
|||||||
getHashFn: GetHashFn(header.ParentHash, chain),
|
getHashFn: GetHashFn(header.ParentHash, chain),
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise a default config if none present
|
|
||||||
if cfg == nil {
|
|
||||||
cfg = new(vm.Config)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no log collector is present set self as the collector
|
// if no log collector is present set self as the collector
|
||||||
if cfg.Logger.Collector == nil {
|
if cfg.Logger.Collector == nil {
|
||||||
cfg.Logger.Collector = env
|
cfg.Logger.Collector = env
|
||||||
@ -76,6 +72,7 @@ func NewEnv(state *state.StateDB, chain *BlockChain, msg Message, header *types.
|
|||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *VMEnv) RuleSet() vm.RuleSet { return self.chainConfig }
|
||||||
func (self *VMEnv) Vm() vm.Vm { return self.evm }
|
func (self *VMEnv) Vm() vm.Vm { return self.evm }
|
||||||
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
|
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
|
||||||
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
|
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
|
||||||
|
28
eth/api.go
28
eth/api.go
@ -456,6 +456,7 @@ func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
|
|||||||
// PublicBlockChainAPI provides an API to access the Ethereum blockchain.
|
// PublicBlockChainAPI provides an API to access the Ethereum blockchain.
|
||||||
// It offers only methods that operate on public data that is freely available to anyone.
|
// It offers only methods that operate on public data that is freely available to anyone.
|
||||||
type PublicBlockChainAPI struct {
|
type PublicBlockChainAPI struct {
|
||||||
|
config *core.ChainConfig
|
||||||
bc *core.BlockChain
|
bc *core.BlockChain
|
||||||
chainDb ethdb.Database
|
chainDb ethdb.Database
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
@ -464,8 +465,8 @@ type PublicBlockChainAPI struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewPublicBlockChainAPI creates a new Etheruem blockchain API.
|
// NewPublicBlockChainAPI creates a new Etheruem blockchain API.
|
||||||
func NewPublicBlockChainAPI(bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI {
|
func NewPublicBlockChainAPI(config *core.ChainConfig, bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI {
|
||||||
return &PublicBlockChainAPI{bc: bc, miner: m, chainDb: chainDb, eventMux: eventMux, am: am}
|
return &PublicBlockChainAPI{config: config, bc: bc, miner: m, chainDb: chainDb, eventMux: eventMux, am: am}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockNumber returns the block number of the chain head.
|
// BlockNumber returns the block number of the chain head.
|
||||||
@ -670,14 +671,14 @@ func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the call and return
|
// Execute the call and return
|
||||||
vmenv := core.NewEnv(stateDb, s.bc, msg, block.Header(), nil)
|
vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), s.config.VmConfig)
|
||||||
gp := new(core.GasPool).AddGas(common.MaxBig)
|
gp := new(core.GasPool).AddGas(common.MaxBig)
|
||||||
|
|
||||||
res, gas, err := core.ApplyMessage(vmenv, msg, gp)
|
res, requiredGas, _, err := core.NewStateTransition(vmenv, msg, gp).TransitionDb()
|
||||||
if len(res) == 0 { // backwards compatibility
|
if len(res) == 0 { // backwards compatibility
|
||||||
return "0x", gas, err
|
return "0x", requiredGas, err
|
||||||
}
|
}
|
||||||
return common.ToHex(res), gas, err
|
return common.ToHex(res), requiredGas, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call executes the given transaction on the state for the given block number.
|
// Call executes the given transaction on the state for the given block number.
|
||||||
@ -1501,13 +1502,14 @@ func (api *PublicDebugAPI) SeedHash(number uint64) (string, error) {
|
|||||||
// PrivateDebugAPI is the collection of Etheruem APIs exposed over the private
|
// PrivateDebugAPI is the collection of Etheruem APIs exposed over the private
|
||||||
// debugging endpoint.
|
// debugging endpoint.
|
||||||
type PrivateDebugAPI struct {
|
type PrivateDebugAPI struct {
|
||||||
|
config *core.ChainConfig
|
||||||
eth *Ethereum
|
eth *Ethereum
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPrivateDebugAPI creates a new API definition for the private debug methods
|
// NewPrivateDebugAPI creates a new API definition for the private debug methods
|
||||||
// of the Ethereum service.
|
// of the Ethereum service.
|
||||||
func NewPrivateDebugAPI(eth *Ethereum) *PrivateDebugAPI {
|
func NewPrivateDebugAPI(config *core.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
|
||||||
return &PrivateDebugAPI{eth: eth}
|
return &PrivateDebugAPI{config: config, eth: eth}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockTraceResults is the returned value when replaying a block to check for
|
// BlockTraceResults is the returned value when replaying a block to check for
|
||||||
@ -1601,7 +1603,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, config vm.Config) (bo
|
|||||||
config.Debug = true // make sure debug is set.
|
config.Debug = true // make sure debug is set.
|
||||||
config.Logger.Collector = collector
|
config.Logger.Collector = collector
|
||||||
|
|
||||||
if err := core.ValidateHeader(blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil {
|
if err := core.ValidateHeader(api.config, blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil {
|
||||||
return false, collector.traces, err
|
return false, collector.traces, err
|
||||||
}
|
}
|
||||||
statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), api.eth.ChainDb())
|
statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), api.eth.ChainDb())
|
||||||
@ -1609,7 +1611,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, config vm.Config) (bo
|
|||||||
return false, collector.traces, err
|
return false, collector.traces, err
|
||||||
}
|
}
|
||||||
|
|
||||||
receipts, _, usedGas, err := processor.Process(block, statedb, &config)
|
receipts, _, usedGas, err := processor.Process(block, statedb, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, collector.traces, err
|
return false, collector.traces, err
|
||||||
}
|
}
|
||||||
@ -1731,7 +1733,7 @@ func (s *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger vm.LogConf
|
|||||||
data: tx.Data(),
|
data: tx.Data(),
|
||||||
}
|
}
|
||||||
|
|
||||||
vmenv := core.NewEnv(stateDb, s.eth.BlockChain(), msg, block.Header(), &vm.Config{
|
vmenv := core.NewEnv(stateDb, s.config, s.eth.BlockChain(), msg, block.Header(), vm.Config{
|
||||||
Debug: true,
|
Debug: true,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
})
|
})
|
||||||
@ -1788,7 +1790,9 @@ func (s *PublicBlockChainAPI) TraceCall(args CallArgs, blockNr rpc.BlockNumber)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the call and return
|
// Execute the call and return
|
||||||
vmenv := core.NewEnv(stateDb, s.bc, msg, block.Header(), nil)
|
vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), vm.Config{
|
||||||
|
Debug: true,
|
||||||
|
})
|
||||||
gp := new(core.GasPool).AddGas(common.MaxBig)
|
gp := new(core.GasPool).AddGas(common.MaxBig)
|
||||||
|
|
||||||
ret, gas, err := core.ApplyMessage(vmenv, msg, gp)
|
ret, gas, err := core.ApplyMessage(vmenv, msg, gp)
|
||||||
|
@ -63,6 +63,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
ChainConfig *core.ChainConfig // chain configuration
|
||||||
|
|
||||||
NetworkId int // Network ID to use for selecting peers to connect to
|
NetworkId int // Network ID to use for selecting peers to connect to
|
||||||
Genesis string // Genesis JSON to seed the chain database with
|
Genesis string // Genesis JSON to seed the chain database with
|
||||||
FastSync bool // Enables the state download based fast synchronisation algorithm
|
FastSync bool // Enables the state download based fast synchronisation algorithm
|
||||||
@ -100,6 +102,7 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Ethereum struct {
|
type Ethereum struct {
|
||||||
|
chainConfig *core.ChainConfig
|
||||||
// Channel for shutting down the ethereum
|
// Channel for shutting down the ethereum
|
||||||
shutdownChan chan bool
|
shutdownChan chan bool
|
||||||
|
|
||||||
@ -166,12 +169,17 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||||||
|
|
||||||
// Load up any custom genesis block if requested
|
// Load up any custom genesis block if requested
|
||||||
if len(config.Genesis) > 0 {
|
if len(config.Genesis) > 0 {
|
||||||
|
// Using println instead of glog to make sure it **always** displays regardless of
|
||||||
|
// verbosity settings.
|
||||||
|
common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'")
|
||||||
|
|
||||||
block, err := core.WriteGenesisBlock(chainDb, strings.NewReader(config.Genesis))
|
block, err := core.WriteGenesisBlock(chainDb, strings.NewReader(config.Genesis))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
|
glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load up a test setup if directly injected
|
// Load up a test setup if directly injected
|
||||||
if config.TestGenesisState != nil {
|
if config.TestGenesisState != nil {
|
||||||
chainDb = config.TestGenesisState
|
chainDb = config.TestGenesisState
|
||||||
@ -227,26 +235,38 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||||||
default:
|
default:
|
||||||
eth.pow = ethash.New()
|
eth.pow = ethash.New()
|
||||||
}
|
}
|
||||||
//genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb)
|
|
||||||
eth.blockchain, err = core.NewBlockChain(chainDb, eth.pow, eth.EventMux())
|
// load the genesis block or write a new one if no genesis
|
||||||
eth.blockchain.SetConfig(&vm.Config{
|
// block is prenent in the database.
|
||||||
|
genesis := core.GetBlock(chainDb, core.GetCanonicalHash(chainDb, 0))
|
||||||
|
if genesis == nil {
|
||||||
|
genesis, err = core.WriteDefaultGenesisBlock(chainDb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
|
||||||
|
}
|
||||||
|
|
||||||
|
eth.chainConfig = config.ChainConfig
|
||||||
|
eth.chainConfig.VmConfig = vm.Config{
|
||||||
EnableJit: config.EnableJit,
|
EnableJit: config.EnableJit,
|
||||||
ForceJit: config.ForceJit,
|
ForceJit: config.ForceJit,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == core.ErrNoGenesis {
|
if err == core.ErrNoGenesis {
|
||||||
return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`)
|
return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
newPool := core.NewTxPool(eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
|
newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
|
||||||
eth.txPool = newPool
|
eth.txPool = newPool
|
||||||
|
|
||||||
if eth.protocolManager, err = NewProtocolManager(config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
|
if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
eth.miner = miner.New(eth, eth.EventMux(), eth.pow)
|
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow)
|
||||||
eth.miner.SetGasPrice(config.GasPrice)
|
eth.miner.SetGasPrice(config.GasPrice)
|
||||||
eth.miner.SetExtra(config.ExtraData)
|
eth.miner.SetExtra(config.ExtraData)
|
||||||
|
|
||||||
@ -275,7 +295,7 @@ func (s *Ethereum) APIs() []rpc.API {
|
|||||||
}, {
|
}, {
|
||||||
Namespace: "eth",
|
Namespace: "eth",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
Service: NewPublicBlockChainAPI(s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()),
|
Service: NewPublicBlockChainAPI(s.chainConfig, s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()),
|
||||||
Public: true,
|
Public: true,
|
||||||
}, {
|
}, {
|
||||||
Namespace: "eth",
|
Namespace: "eth",
|
||||||
@ -319,7 +339,7 @@ func (s *Ethereum) APIs() []rpc.API {
|
|||||||
}, {
|
}, {
|
||||||
Namespace: "debug",
|
Namespace: "debug",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
Service: NewPrivateDebugAPI(s),
|
Service: NewPrivateDebugAPI(s.chainConfig, s),
|
||||||
}, {
|
}, {
|
||||||
Namespace: "net",
|
Namespace: "net",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
@ -328,7 +348,7 @@ func (s *Ethereum) APIs() []rpc.API {
|
|||||||
}, {
|
}, {
|
||||||
Namespace: "admin",
|
Namespace: "admin",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
Service: ethreg.NewPrivateRegistarAPI(s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()),
|
Service: ethreg.NewPrivateRegistarAPI(s.chainConfig, s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ type ProtocolManager struct {
|
|||||||
|
|
||||||
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
|
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
|
||||||
// with the ethereum network.
|
// with the ethereum network.
|
||||||
func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
|
func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
|
||||||
// Figure out whether to allow fast sync or not
|
// Figure out whether to allow fast sync or not
|
||||||
if fastSync && blockchain.CurrentBlock().NumberU64() > 0 {
|
if fastSync && blockchain.CurrentBlock().NumberU64() > 0 {
|
||||||
glog.V(logger.Info).Infof("blockchain not empty, fast sync disabled")
|
glog.V(logger.Info).Infof("blockchain not empty, fast sync disabled")
|
||||||
@ -144,7 +144,7 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
|
|||||||
manager.removePeer)
|
manager.removePeer)
|
||||||
|
|
||||||
validator := func(block *types.Block, parent *types.Block) error {
|
validator := func(block *types.Block, parent *types.Block) error {
|
||||||
return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false)
|
return core.ValidateHeader(config, pow, block.Header(), parent.Header(), true, false)
|
||||||
}
|
}
|
||||||
heighter := func() uint64 {
|
heighter := func() uint64 {
|
||||||
return blockchain.CurrentBlock().NumberU64()
|
return blockchain.CurrentBlock().NumberU64()
|
||||||
|
@ -34,13 +34,15 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core
|
|||||||
pow = new(core.FakePow)
|
pow = new(core.FakePow)
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{testBankAddress, testBankFunds})
|
genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{testBankAddress, testBankFunds})
|
||||||
blockchain, _ = core.NewBlockChain(db, pow, evmux)
|
chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
|
||||||
|
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux)
|
||||||
)
|
)
|
||||||
chain, _ := core.GenerateChain(genesis, db, blocks, generator)
|
chain, _ := core.GenerateChain(genesis, db, blocks, generator)
|
||||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
pm, err := NewProtocolManager(fastSync, NetworkId, evmux, &testTxPool{added: newtx}, pow, blockchain, db)
|
|
||||||
|
pm, err := NewProtocolManager(chainConfig, fastSync, NetworkId, evmux, &testTxPool{added: newtx}, pow, blockchain, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ type Miner struct {
|
|||||||
shouldStart int32 // should start indicates whether we should start after sync
|
shouldStart int32 // should start indicates whether we should start after sync
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(eth core.Backend, mux *event.TypeMux, pow pow.PoW) *Miner {
|
func New(eth core.Backend, config *core.ChainConfig, mux *event.TypeMux, pow pow.PoW) *Miner {
|
||||||
miner := &Miner{eth: eth, mux: mux, pow: pow, worker: newWorker(common.Address{}, eth), canStart: 1}
|
miner := &Miner{eth: eth, mux: mux, pow: pow, worker: newWorker(config, common.Address{}, eth), canStart: 1}
|
||||||
go miner.update()
|
go miner.update()
|
||||||
|
|
||||||
return miner
|
return miner
|
||||||
|
@ -61,6 +61,7 @@ type uint64RingBuffer struct {
|
|||||||
// environment is the workers current environment and holds
|
// environment is the workers current environment and holds
|
||||||
// all of the current state information
|
// all of the current state information
|
||||||
type Work struct {
|
type Work struct {
|
||||||
|
config *core.ChainConfig
|
||||||
state *state.StateDB // apply state changes here
|
state *state.StateDB // apply state changes here
|
||||||
ancestors *set.Set // ancestor set (used for checking uncle parent validity)
|
ancestors *set.Set // ancestor set (used for checking uncle parent validity)
|
||||||
family *set.Set // family set (used for checking uncle invalidity)
|
family *set.Set // family set (used for checking uncle invalidity)
|
||||||
@ -89,6 +90,8 @@ type Result struct {
|
|||||||
|
|
||||||
// worker is the main object which takes care of applying messages to the new state
|
// worker is the main object which takes care of applying messages to the new state
|
||||||
type worker struct {
|
type worker struct {
|
||||||
|
config *core.ChainConfig
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
agents map[Agent]struct{}
|
agents map[Agent]struct{}
|
||||||
@ -122,8 +125,9 @@ type worker struct {
|
|||||||
fullValidation bool
|
fullValidation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWorker(coinbase common.Address, eth core.Backend) *worker {
|
func newWorker(config *core.ChainConfig, coinbase common.Address, eth core.Backend) *worker {
|
||||||
worker := &worker{
|
worker := &worker{
|
||||||
|
config: config,
|
||||||
eth: eth,
|
eth: eth,
|
||||||
mux: eth.EventMux(),
|
mux: eth.EventMux(),
|
||||||
chainDb: eth.ChainDb(),
|
chainDb: eth.ChainDb(),
|
||||||
@ -285,7 +289,7 @@ func (self *worker) wait() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auxValidator := self.eth.BlockChain().AuxValidator()
|
auxValidator := self.eth.BlockChain().AuxValidator()
|
||||||
if err := core.ValidateHeader(auxValidator, block.Header(), parent.Header(), true, false); err != nil && err != core.BlockFutureErr {
|
if err := core.ValidateHeader(self.config, auxValidator, block.Header(), parent.Header(), true, false); err != nil && err != core.BlockFutureErr {
|
||||||
glog.V(logger.Error).Infoln("Invalid header on mined block:", err)
|
glog.V(logger.Error).Infoln("Invalid header on mined block:", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -371,6 +375,7 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
work := &Work{
|
work := &Work{
|
||||||
|
config: self.config,
|
||||||
state: state,
|
state: state,
|
||||||
ancestors: set.New(),
|
ancestors: set.New(),
|
||||||
family: set.New(),
|
family: set.New(),
|
||||||
@ -470,7 +475,7 @@ func (self *worker) commitNewWork() {
|
|||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: parent.Hash(),
|
ParentHash: parent.Hash(),
|
||||||
Number: num.Add(num, common.Big1),
|
Number: num.Add(num, common.Big1),
|
||||||
Difficulty: core.CalcDifficulty(uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()),
|
Difficulty: core.CalcDifficulty(self.config, uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()),
|
||||||
GasLimit: core.CalcGasLimit(parent),
|
GasLimit: core.CalcGasLimit(parent),
|
||||||
GasUsed: new(big.Int),
|
GasUsed: new(big.Int),
|
||||||
Coinbase: self.coinbase,
|
Coinbase: self.coinbase,
|
||||||
@ -657,7 +662,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, transactions types.Trans
|
|||||||
|
|
||||||
func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, gp *core.GasPool) (error, vm.Logs) {
|
func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, gp *core.GasPool) (error, vm.Logs) {
|
||||||
snap := env.state.Copy()
|
snap := env.state.Copy()
|
||||||
receipt, logs, _, err := core.ApplyTransaction(bc, gp, env.state, env.header, tx, env.header.GasUsed, nil)
|
receipt, logs, _, err := core.ApplyTransaction(env.config, bc, gp, env.state, env.header, tx, env.header.GasUsed, env.config.VmConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
env.state.Set(snap)
|
env.state.Set(snap)
|
||||||
return err, nil
|
return err, nil
|
||||||
|
@ -42,6 +42,7 @@ var (
|
|||||||
|
|
||||||
MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
|
MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
|
||||||
GenesisGasLimit = big.NewInt(4712388) // Gas limit of the Genesis block.
|
GenesisGasLimit = big.NewInt(4712388) // Gas limit of the Genesis block.
|
||||||
|
TargetGasLimit = new(big.Int).Set(GenesisGasLimit) // The artificial target
|
||||||
|
|
||||||
Sha3Gas = big.NewInt(30) // Once per SHA3 operation.
|
Sha3Gas = big.NewInt(30) // Once per SHA3 operation.
|
||||||
Sha256Gas = big.NewInt(60) //
|
Sha256Gas = big.NewInt(60) //
|
||||||
|
@ -21,13 +21,4 @@ import "math/big"
|
|||||||
var (
|
var (
|
||||||
TestNetHomesteadBlock = big.NewInt(494000) // testnet homestead block
|
TestNetHomesteadBlock = big.NewInt(494000) // testnet homestead block
|
||||||
MainNetHomesteadBlock = big.NewInt(1150000) // mainnet homestead block
|
MainNetHomesteadBlock = big.NewInt(1150000) // mainnet homestead block
|
||||||
HomesteadBlock = MainNetHomesteadBlock // homestead block used to check against
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsHomestead(blockNumber *big.Int) bool {
|
|
||||||
// for unit tests TODO: flip to true after homestead is live
|
|
||||||
if blockNumber == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return blockNumber.Cmp(HomesteadBlock) >= 0
|
|
||||||
}
|
|
||||||
|
@ -20,77 +20,66 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBcValidBlockTests(t *testing.T) {
|
func TestBcValidBlockTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcUncleHeaderValidityTests(t *testing.T) {
|
func TestBcUncleHeaderValidityTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcUncleTests(t *testing.T) {
|
func TestBcUncleTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcForkUncleTests(t *testing.T) {
|
func TestBcForkUncleTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcInvalidHeaderTests(t *testing.T) {
|
func TestBcInvalidHeaderTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcInvalidRLPTests(t *testing.T) {
|
func TestBcInvalidRLPTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcRPCAPITests(t *testing.T) {
|
func TestBcRPCAPITests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcForkBlockTests(t *testing.T) {
|
func TestBcForkBlockTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcForkStress(t *testing.T) {
|
func TestBcForkStress(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -100,24 +89,21 @@ func TestBcTotalDifficulty(t *testing.T) {
|
|||||||
// skip because these will fail due to selfish mining fix
|
// skip because these will fail due to selfish mining fix
|
||||||
t.Skip()
|
t.Skip()
|
||||||
|
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcWallet(t *testing.T) {
|
func TestBcWallet(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcGasPricer(t *testing.T) {
|
func TestBcGasPricer(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -125,8 +111,7 @@ func TestBcGasPricer(t *testing.T) {
|
|||||||
|
|
||||||
// TODO: iterate over files once we got more than a few
|
// TODO: iterate over files once we got more than a few
|
||||||
func TestBcRandom(t *testing.T) {
|
func TestBcRandom(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -136,16 +121,14 @@ func TestBcMultiChain(t *testing.T) {
|
|||||||
// skip due to selfish mining
|
// skip due to selfish mining
|
||||||
t.Skip()
|
t.Skip()
|
||||||
|
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBcState(t *testing.T) {
|
func TestBcState(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -153,88 +136,77 @@ func TestBcState(t *testing.T) {
|
|||||||
|
|
||||||
// Homestead tests
|
// Homestead tests
|
||||||
func TestHomesteadBcValidBlockTests(t *testing.T) {
|
func TestHomesteadBcValidBlockTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
|
func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcUncleTests(t *testing.T) {
|
func TestHomesteadBcUncleTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
|
func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcRPCAPITests(t *testing.T) {
|
func TestHomesteadBcRPCAPITests(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcForkStress(t *testing.T) {
|
func TestHomesteadBcForkStress(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcTotalDifficulty(t *testing.T) {
|
func TestHomesteadBcTotalDifficulty(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcWallet(t *testing.T) {
|
func TestHomesteadBcWallet(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcGasPricer(t *testing.T) {
|
func TestHomesteadBcGasPricer(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcMultiChain(t *testing.T) {
|
func TestHomesteadBcMultiChain(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadBcState(t *testing.T) {
|
func TestHomesteadBcState(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
|
||||||
err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ type btTransaction struct {
|
|||||||
Value string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunBlockTestWithReader(r io.Reader, skipTests []string) error {
|
func RunBlockTestWithReader(homesteadBlock *big.Int, r io.Reader, skipTests []string) error {
|
||||||
btjs := make(map[string]*btJSON)
|
btjs := make(map[string]*btJSON)
|
||||||
if err := readJson(r, &btjs); err != nil {
|
if err := readJson(r, &btjs); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -119,13 +119,13 @@ func RunBlockTestWithReader(r io.Reader, skipTests []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runBlockTests(bt, skipTests); err != nil {
|
if err := runBlockTests(homesteadBlock, bt, skipTests); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunBlockTest(file string, skipTests []string) error {
|
func RunBlockTest(homesteadBlock *big.Int, file string, skipTests []string) error {
|
||||||
btjs := make(map[string]*btJSON)
|
btjs := make(map[string]*btJSON)
|
||||||
if err := readJsonFile(file, &btjs); err != nil {
|
if err := readJsonFile(file, &btjs); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -135,13 +135,13 @@ func RunBlockTest(file string, skipTests []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := runBlockTests(bt, skipTests); err != nil {
|
if err := runBlockTests(homesteadBlock, bt, skipTests); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
|
func runBlockTests(homesteadBlock *big.Int, bt map[string]*BlockTest, skipTests []string) error {
|
||||||
skipTest := make(map[string]bool, len(skipTests))
|
skipTest := make(map[string]bool, len(skipTests))
|
||||||
for _, name := range skipTests {
|
for _, name := range skipTests {
|
||||||
skipTest[name] = true
|
skipTest[name] = true
|
||||||
@ -153,7 +153,7 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// test the block
|
// test the block
|
||||||
if err := runBlockTest(test); err != nil {
|
if err := runBlockTest(homesteadBlock, test); err != nil {
|
||||||
return fmt.Errorf("%s: %v", name, err)
|
return fmt.Errorf("%s: %v", name, err)
|
||||||
}
|
}
|
||||||
glog.Infoln("Block test passed: ", name)
|
glog.Infoln("Block test passed: ", name)
|
||||||
@ -162,7 +162,7 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
|
|||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
func runBlockTest(test *BlockTest) error {
|
func runBlockTest(homesteadBlock *big.Int, test *BlockTest) error {
|
||||||
ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"), crypto.StandardScryptN, crypto.StandardScryptP)
|
ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"), crypto.StandardScryptN, crypto.StandardScryptP)
|
||||||
am := accounts.NewManager(ks)
|
am := accounts.NewManager(ks)
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
@ -174,6 +174,7 @@ func runBlockTest(test *BlockTest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg := ð.Config{
|
cfg := ð.Config{
|
||||||
|
ChainConfig: &core.ChainConfig{HomesteadBlock: homesteadBlock},
|
||||||
TestGenesisState: db,
|
TestGenesisState: db,
|
||||||
TestGenesisBlock: test.Genesis,
|
TestGenesisBlock: test.Genesis,
|
||||||
Etherbase: common.Address{},
|
Etherbase: common.Address{},
|
||||||
|
@ -21,18 +21,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
if os.Getenv("JITVM") == "true" {
|
|
||||||
vm.ForceJit = true
|
|
||||||
vm.EnableJit = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkStateCall1024(b *testing.B) {
|
func BenchmarkStateCall1024(b *testing.B) {
|
||||||
fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json")
|
fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json")
|
||||||
if err := BenchVmTest(fn, bconf{"Call1024BalanceTooLow", true, os.Getenv("JITVM") == "true"}, b); err != nil {
|
if err := BenchVmTest(fn, bconf{"Call1024BalanceTooLow", true, os.Getenv("JITVM") == "true"}, b); err != nil {
|
||||||
@ -41,188 +31,228 @@ func BenchmarkStateCall1024(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStateSystemOperations(t *testing.T) {
|
func TestStateSystemOperations(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json")
|
fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateExample(t *testing.T) {
|
func TestStateExample(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stExample.json")
|
fn := filepath.Join(stateTestDir, "stExample.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStatePreCompiledContracts(t *testing.T) {
|
func TestStatePreCompiledContracts(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stPreCompiledContracts.json")
|
fn := filepath.Join(stateTestDir, "stPreCompiledContracts.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateRecursiveCreate(t *testing.T) {
|
func TestStateRecursiveCreate(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stRecursiveCreate.json")
|
fn := filepath.Join(stateTestDir, "stRecursiveCreate.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateSpecial(t *testing.T) {
|
func TestStateSpecial(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stSpecialTest.json")
|
fn := filepath.Join(stateTestDir, "stSpecialTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateRefund(t *testing.T) {
|
func TestStateRefund(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stRefundTest.json")
|
fn := filepath.Join(stateTestDir, "stRefundTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateBlockHash(t *testing.T) {
|
func TestStateBlockHash(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stBlockHashTest.json")
|
fn := filepath.Join(stateTestDir, "stBlockHashTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateInitCode(t *testing.T) {
|
func TestStateInitCode(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stInitCodeTest.json")
|
fn := filepath.Join(stateTestDir, "stInitCodeTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateLog(t *testing.T) {
|
func TestStateLog(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stLogTests.json")
|
fn := filepath.Join(stateTestDir, "stLogTests.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateTransaction(t *testing.T) {
|
func TestStateTransaction(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stTransactionTest.json")
|
fn := filepath.Join(stateTestDir, "stTransactionTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateTransition(t *testing.T) {
|
func TestStateTransition(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stTransitionTest.json")
|
fn := filepath.Join(stateTestDir, "stTransitionTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCallCreateCallCode(t *testing.T) {
|
func TestCallCreateCallCode(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json")
|
fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCallCodes(t *testing.T) {
|
func TestCallCodes(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stCallCodes.json")
|
fn := filepath.Join(stateTestDir, "stCallCodes.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDelegateCall(t *testing.T) {
|
func TestDelegateCall(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stDelegatecallTest.json")
|
fn := filepath.Join(stateTestDir, "stDelegatecallTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMemory(t *testing.T) {
|
func TestMemory(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stMemoryTest.json")
|
fn := filepath.Join(stateTestDir, "stMemoryTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMemoryStress(t *testing.T) {
|
func TestMemoryStress(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
fn := filepath.Join(stateTestDir, "stMemoryStressTest.json")
|
fn := filepath.Join(stateTestDir, "stMemoryStressTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQuadraticComplexity(t *testing.T) {
|
func TestQuadraticComplexity(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
fn := filepath.Join(stateTestDir, "stQuadraticComplexityTest.json")
|
fn := filepath.Join(stateTestDir, "stQuadraticComplexityTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSolidity(t *testing.T) {
|
func TestSolidity(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stSolidityTest.json")
|
fn := filepath.Join(stateTestDir, "stSolidityTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWallet(t *testing.T) {
|
func TestWallet(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "stWalletTest.json")
|
fn := filepath.Join(stateTestDir, "stWalletTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateTestsRandom(t *testing.T) {
|
func TestStateTestsRandom(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(1000000)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: big.NewInt(1000000),
|
||||||
|
}
|
||||||
|
|
||||||
fns, _ := filepath.Glob("./files/StateTests/RandomTests/*")
|
fns, _ := filepath.Glob("./files/StateTests/RandomTests/*")
|
||||||
for _, fn := range fns {
|
for _, fn := range fns {
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,151 +260,172 @@ func TestStateTestsRandom(t *testing.T) {
|
|||||||
|
|
||||||
// homestead tests
|
// homestead tests
|
||||||
func TestHomesteadStateSystemOperations(t *testing.T) {
|
func TestHomesteadStateSystemOperations(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stSystemOperationsTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stSystemOperationsTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadStatePreCompiledContracts(t *testing.T) {
|
func TestHomesteadStatePreCompiledContracts(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stPreCompiledContracts.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stPreCompiledContracts.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadStateRecursiveCreate(t *testing.T) {
|
func TestHomesteadStateRecursiveCreate(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stRecursiveCreate.json")
|
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func TestHomesteadStateSpecial(t *testing.T) {
|
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stSpecialTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stSpecialTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadStateRefund(t *testing.T) {
|
func TestHomesteadStateRefund(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stRefundTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stRefundTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadStateInitCode(t *testing.T) {
|
func TestHomesteadStateInitCode(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stInitCodeTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stInitCodeTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadStateLog(t *testing.T) {
|
func TestHomesteadStateLog(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stLogTests.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stLogTests.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadStateTransaction(t *testing.T) {
|
func TestHomesteadStateTransaction(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stTransactionTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stTransactionTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadCallCreateCallCode(t *testing.T) {
|
func TestHomesteadCallCreateCallCode(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stCallCreateCallCodeTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stCallCreateCallCodeTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadCallCodes(t *testing.T) {
|
func TestHomesteadCallCodes(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stCallCodes.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stCallCodes.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadMemory(t *testing.T) {
|
func TestHomesteadMemory(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stMemoryTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stMemoryTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadMemoryStress(t *testing.T) {
|
func TestHomesteadMemoryStress(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stMemoryStressTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stMemoryStressTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadQuadraticComplexity(t *testing.T) {
|
func TestHomesteadQuadraticComplexity(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
if os.Getenv("TEST_VM_COMPLEX") == "" {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stQuadraticComplexityTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stQuadraticComplexityTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadWallet(t *testing.T) {
|
func TestHomesteadWallet(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stWalletTest.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stWalletTest.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadDelegateCodes(t *testing.T) {
|
func TestHomesteadDelegateCodes(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stCallDelegateCodes.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stCallDelegateCodes.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomesteadDelegateCodesCallCode(t *testing.T) {
|
func TestHomesteadDelegateCodesCallCode(t *testing.T) {
|
||||||
params.HomesteadBlock = big.NewInt(0)
|
ruleSet := RuleSet{
|
||||||
|
HomesteadBlock: new(big.Int),
|
||||||
|
}
|
||||||
|
|
||||||
fn := filepath.Join(stateTestDir, "Homestead", "stCallDelegateCodesCallCode.json")
|
fn := filepath.Join(stateTestDir, "Homestead", "stCallDelegateCodesCallCode.json")
|
||||||
if err := RunStateTest(fn, StateSkipTests); err != nil {
|
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,26 +34,26 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunStateTestWithReader(r io.Reader, skipTests []string) error {
|
func RunStateTestWithReader(ruleSet RuleSet, r io.Reader, skipTests []string) error {
|
||||||
tests := make(map[string]VmTest)
|
tests := make(map[string]VmTest)
|
||||||
if err := readJson(r, &tests); err != nil {
|
if err := readJson(r, &tests); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runStateTests(tests, skipTests); err != nil {
|
if err := runStateTests(ruleSet, tests, skipTests); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunStateTest(p string, skipTests []string) error {
|
func RunStateTest(ruleSet RuleSet, p string, skipTests []string) error {
|
||||||
tests := make(map[string]VmTest)
|
tests := make(map[string]VmTest)
|
||||||
if err := readJsonFile(p, &tests); err != nil {
|
if err := readJsonFile(p, &tests); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runStateTests(tests, skipTests); err != nil {
|
if err := runStateTests(ruleSet, tests, skipTests); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ func RunStateTest(p string, skipTests []string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchStateTest(p string, conf bconf, b *testing.B) error {
|
func BenchStateTest(ruleSet RuleSet, p string, conf bconf, b *testing.B) error {
|
||||||
tests := make(map[string]VmTest)
|
tests := make(map[string]VmTest)
|
||||||
if err := readJsonFile(p, &tests); err != nil {
|
if err := readJsonFile(p, &tests); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -71,11 +71,6 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
|
|||||||
return fmt.Errorf("test not found: %s", conf.name)
|
return fmt.Errorf("test not found: %s", conf.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pJit := vm.EnableJit
|
|
||||||
vm.EnableJit = conf.jit
|
|
||||||
pForceJit := vm.ForceJit
|
|
||||||
vm.ForceJit = conf.precomp
|
|
||||||
|
|
||||||
// XXX Yeah, yeah...
|
// XXX Yeah, yeah...
|
||||||
env := make(map[string]string)
|
env := make(map[string]string)
|
||||||
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
||||||
@ -91,16 +86,13 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
|
|||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
benchStateTest(test, env, b)
|
benchStateTest(ruleSet, test, env, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.EnableJit = pJit
|
|
||||||
vm.ForceJit = pForceJit
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func benchStateTest(test VmTest, env map[string]string, b *testing.B) {
|
func benchStateTest(ruleSet RuleSet, test VmTest, env map[string]string, b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, db)
|
statedb, _ := state.New(common.Hash{}, db)
|
||||||
@ -113,10 +105,10 @@ func benchStateTest(test VmTest, env map[string]string, b *testing.B) {
|
|||||||
}
|
}
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
RunState(statedb, env, test.Exec)
|
RunState(ruleSet, statedb, env, test.Exec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runStateTests(tests map[string]VmTest, skipTests []string) error {
|
func runStateTests(ruleSet RuleSet, tests map[string]VmTest, skipTests []string) error {
|
||||||
skipTest := make(map[string]bool, len(skipTests))
|
skipTest := make(map[string]bool, len(skipTests))
|
||||||
for _, name := range skipTests {
|
for _, name := range skipTests {
|
||||||
skipTest[name] = true
|
skipTest[name] = true
|
||||||
@ -129,7 +121,7 @@ func runStateTests(tests map[string]VmTest, skipTests []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//fmt.Println("StateTest:", name)
|
//fmt.Println("StateTest:", name)
|
||||||
if err := runStateTest(test); err != nil {
|
if err := runStateTest(ruleSet, test); err != nil {
|
||||||
return fmt.Errorf("%s: %s\n", name, err.Error())
|
return fmt.Errorf("%s: %s\n", name, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +132,7 @@ func runStateTests(tests map[string]VmTest, skipTests []string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runStateTest(test VmTest) error {
|
func runStateTest(ruleSet RuleSet, test VmTest) error {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, db)
|
statedb, _ := state.New(common.Hash{}, db)
|
||||||
for addr, account := range test.Pre {
|
for addr, account := range test.Pre {
|
||||||
@ -171,7 +163,7 @@ func runStateTest(test VmTest) error {
|
|||||||
logs vm.Logs
|
logs vm.Logs
|
||||||
)
|
)
|
||||||
|
|
||||||
ret, logs, _, _ = RunState(statedb, env, test.Transaction)
|
ret, logs, _, _ = RunState(ruleSet, statedb, env, test.Transaction)
|
||||||
|
|
||||||
// Compare expected and actual return
|
// Compare expected and actual return
|
||||||
rexp := common.FromHex(test.Out)
|
rexp := common.FromHex(test.Out)
|
||||||
@ -219,7 +211,7 @@ func runStateTest(test VmTest) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Logs, *big.Int, error) {
|
func RunState(ruleSet RuleSet, statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Logs, *big.Int, error) {
|
||||||
var (
|
var (
|
||||||
data = common.FromHex(tx["data"])
|
data = common.FromHex(tx["data"])
|
||||||
gas = common.Big(tx["gasLimit"])
|
gas = common.Big(tx["gasLimit"])
|
||||||
@ -241,7 +233,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Log
|
|||||||
key, _ := hex.DecodeString(tx["secretKey"])
|
key, _ := hex.DecodeString(tx["secretKey"])
|
||||||
addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey)
|
addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey)
|
||||||
message := NewMessage(addr, to, data, value, gas, price, nonce)
|
message := NewMessage(addr, to, data, value, gas, price, nonce)
|
||||||
vmenv := NewEnvFromMap(statedb, env, tx)
|
vmenv := NewEnvFromMap(ruleSet, statedb, env, tx)
|
||||||
vmenv.origin = addr
|
vmenv.origin = addr
|
||||||
ret, _, err := core.ApplyMessage(vmenv, message, gaspool)
|
ret, _, err := core.ApplyMessage(vmenv, message, gaspool)
|
||||||
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) {
|
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) {
|
||||||
|
@ -21,10 +21,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@ -91,8 +91,6 @@ func RunTransactionTests(file string, skipTests []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runTransactionTests(tests map[string]TransactionTest, skipTests []string) error {
|
func runTransactionTests(tests map[string]TransactionTest, skipTests []string) error {
|
||||||
params.HomesteadBlock = big.NewInt(900000)
|
|
||||||
|
|
||||||
skipTest := make(map[string]bool, len(skipTests))
|
skipTest := make(map[string]bool, len(skipTests))
|
||||||
for _, name := range skipTests {
|
for _, name := range skipTests {
|
||||||
skipTest[name] = true
|
skipTest[name] = true
|
||||||
@ -166,7 +164,8 @@ func verifyTxFields(txTest TransactionTest, decodedTx *types.Transaction) (err e
|
|||||||
decodedSender common.Address
|
decodedSender common.Address
|
||||||
)
|
)
|
||||||
|
|
||||||
if params.IsHomestead(common.String2Big(txTest.Blocknumber)) {
|
chainConfig := &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock}
|
||||||
|
if chainConfig.IsHomestead(common.String2Big(txTest.Blocknumber)) {
|
||||||
decodedSender, err = decodedTx.From()
|
decodedSender, err = decodedTx.From()
|
||||||
} else {
|
} else {
|
||||||
decodedSender, err = decodedTx.FromFrontier()
|
decodedSender, err = decodedTx.FromFrontier()
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
@ -31,8 +32,17 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ForceJit bool
|
||||||
|
EnableJit bool
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
glog.SetV(0)
|
glog.SetV(0)
|
||||||
|
if os.Getenv("JITVM") == "true" {
|
||||||
|
ForceJit = true
|
||||||
|
EnableJit = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkLogs(tlog []Log, logs vm.Logs) error {
|
func checkLogs(tlog []Log, logs vm.Logs) error {
|
||||||
@ -129,7 +139,16 @@ type VmTest struct {
|
|||||||
PostStateRoot string
|
PostStateRoot string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RuleSet struct {
|
||||||
|
HomesteadBlock *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r RuleSet) IsHomestead(n *big.Int) bool {
|
||||||
|
return n.Cmp(r.HomesteadBlock) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
type Env struct {
|
type Env struct {
|
||||||
|
ruleSet RuleSet
|
||||||
depth int
|
depth int
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
skipTransfer bool
|
skipTransfer bool
|
||||||
@ -152,8 +171,9 @@ type Env struct {
|
|||||||
evm *vm.EVM
|
evm *vm.EVM
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEnv(state *state.StateDB) *Env {
|
func NewEnv(ruleSet RuleSet, state *state.StateDB) *Env {
|
||||||
env := &Env{
|
env := &Env{
|
||||||
|
ruleSet: ruleSet,
|
||||||
state: state,
|
state: state,
|
||||||
}
|
}
|
||||||
return env
|
return env
|
||||||
@ -167,8 +187,8 @@ func (self *Env) AddStructLog(log vm.StructLog) {
|
|||||||
self.logs = append(self.logs, log)
|
self.logs = append(self.logs, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env {
|
func NewEnvFromMap(ruleSet RuleSet, state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env {
|
||||||
env := NewEnv(state)
|
env := NewEnv(ruleSet, state)
|
||||||
|
|
||||||
env.origin = common.HexToAddress(exeValues["caller"])
|
env.origin = common.HexToAddress(exeValues["caller"])
|
||||||
env.parent = common.HexToHash(envValues["previousHash"])
|
env.parent = common.HexToHash(envValues["previousHash"])
|
||||||
@ -179,11 +199,15 @@ func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues
|
|||||||
env.gasLimit = common.Big(envValues["currentGasLimit"])
|
env.gasLimit = common.Big(envValues["currentGasLimit"])
|
||||||
env.Gas = new(big.Int)
|
env.Gas = new(big.Int)
|
||||||
|
|
||||||
env.evm = vm.New(env, nil)
|
env.evm = vm.New(env, vm.Config{
|
||||||
|
EnableJit: EnableJit,
|
||||||
|
ForceJit: ForceJit,
|
||||||
|
})
|
||||||
|
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Env) RuleSet() vm.RuleSet { return self.ruleSet }
|
||||||
func (self *Env) Vm() vm.Vm { return self.evm }
|
func (self *Env) Vm() vm.Vm { return self.evm }
|
||||||
func (self *Env) Origin() common.Address { return self.origin }
|
func (self *Env) Origin() common.Address { return self.origin }
|
||||||
func (self *Env) BlockNumber() *big.Int { return self.number }
|
func (self *Env) BlockNumber() *big.Int { return self.number }
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunVmTestWithReader(r io.Reader, skipTests []string) error {
|
func RunVmTestWithReader(r io.Reader, skipTests []string) error {
|
||||||
@ -67,11 +68,6 @@ func BenchVmTest(p string, conf bconf, b *testing.B) error {
|
|||||||
return fmt.Errorf("test not found: %s", conf.name)
|
return fmt.Errorf("test not found: %s", conf.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pJit := vm.EnableJit
|
|
||||||
vm.EnableJit = conf.jit
|
|
||||||
pForceJit := vm.ForceJit
|
|
||||||
vm.ForceJit = conf.precomp
|
|
||||||
|
|
||||||
env := make(map[string]string)
|
env := make(map[string]string)
|
||||||
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
||||||
env["currentDifficulty"] = test.Env.CurrentDifficulty
|
env["currentDifficulty"] = test.Env.CurrentDifficulty
|
||||||
@ -99,9 +95,6 @@ func BenchVmTest(p string, conf bconf, b *testing.B) error {
|
|||||||
benchVmTest(test, env, b)
|
benchVmTest(test, env, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.EnableJit = pJit
|
|
||||||
vm.ForceJit = pForceJit
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +241,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs,
|
|||||||
|
|
||||||
caller := state.GetOrNewStateObject(from)
|
caller := state.GetOrNewStateObject(from)
|
||||||
|
|
||||||
vmenv := NewEnvFromMap(state, env, exec)
|
vmenv := NewEnvFromMap(RuleSet{params.MainNetHomesteadBlock}, state, env, exec)
|
||||||
vmenv.vmTest = true
|
vmenv.vmTest = true
|
||||||
vmenv.skipTransfer = true
|
vmenv.skipTransfer = true
|
||||||
vmenv.initial = true
|
vmenv.initial = true
|
||||||
|
Loading…
Reference in New Issue
Block a user