Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
# with Go source code. If you know what GOPATH is then you probably
# don't need to bother with make.

.PHONY: geth mist all test travis-test-with-coverage clean
.PHONY: geth evm mist all test travis-test-with-coverage clean
GOBIN = build/bin

geth:
build/env.sh go install -v $(shell build/ldflags.sh) ./cmd/geth
@echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth."

evm:
build/env.sh $(GOROOT)/bin/go install -v $(shell build/ldflags.sh) ./cmd/evm
@echo "Done building."
@echo "Run \"$(GOBIN)/evm to start the evm."
mist:
build/env.sh go install -v $(shell build/ldflags.sh) ./cmd/mist
@echo "Done building."
Expand Down
29 changes: 23 additions & 6 deletions cmd/evm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger/glog"
)

var (
Expand All @@ -40,6 +41,14 @@ var (
Name: "debug",
Usage: "output full trace logs",
}
ForceJitFlag = cli.BoolFlag{
Name: "forcejit",
Usage: "forces jit compilation",
}
DisableJitFlag = cli.BoolFlag{
Name: "nojit",
Usage: "disabled jit compilation",
}
CodeFlag = cli.StringFlag{
Name: "code",
Usage: "EVM code",
Expand Down Expand Up @@ -77,6 +86,8 @@ func init() {
app = utils.NewApp("0.2", "the evm command line interface")
app.Flags = []cli.Flag{
DebugFlag,
ForceJitFlag,
DisableJitFlag,
SysStatFlag,
CodeFlag,
GasFlag,
Expand All @@ -90,6 +101,10 @@ func init() {

func run(ctx *cli.Context) {
vm.Debug = ctx.GlobalBool(DebugFlag.Name)
vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name)
vm.DisableJit = ctx.GlobalBool(DisableJitFlag.Name)

glog.SetToStderr(true)

db, _ := ethdb.NewMemDatabase()
statedb := state.New(common.Hash{}, db)
Expand All @@ -110,11 +125,6 @@ func run(ctx *cli.Context) {
)
vmdone := time.Since(tstart)

if e != nil {
fmt.Println(e)
os.Exit(1)
}

if ctx.GlobalBool(DumpFlag.Name) {
fmt.Println(string(statedb.Dump()))
}
Expand All @@ -133,7 +143,11 @@ num gc: %d
`, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC)
}

fmt.Printf("OUT: 0x%x\n", ret)
fmt.Printf("OUT: 0x%x", ret)
if e != nil {
fmt.Printf(" error: %v", e)
}
fmt.Println()
}

func main() {
Expand Down Expand Up @@ -192,6 +206,9 @@ func (self *VMEnv) StructLogs() []vm.StructLog {
func (self *VMEnv) AddLog(log *state.Log) {
self.state.AddLog(log)
}
func (self *VMEnv) CanTransfer(from vm.Account, balance *big.Int) bool {
return from.Balance().Cmp(balance) >= 0
}
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
return vm.Transfer(from, to, amount)
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.ExecFlag,
utils.WhisperEnabledFlag,
utils.VMDebugFlag,
utils.VMForceJitFlag,
utils.VMJitCacheFlag,
utils.VMEnableJitFlag,
utils.NetworkIdFlag,
utils.RPCCORSDomainFlag,
utils.VerbosityFlag,
Expand Down
31 changes: 27 additions & 4 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"runtime"
"strconv"

"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/metrics"

"github.com/codegangsta/cli"
Expand Down Expand Up @@ -172,6 +173,25 @@ var (
Value: "",
}

// vm flags
VMDebugFlag = cli.BoolFlag{
Name: "vmdebug",
Usage: "Virtual Machine debug output",
}
VMForceJitFlag = cli.BoolFlag{
Name: "forcejit",
Usage: "Force the JIT VM to take precedence",
}
VMJitCacheFlag = cli.IntFlag{
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT should be in caps.

Name: "jitcache",
Usage: "Amount of cached JIT VM programs",
Value: 64,
}
VMEnableJitFlag = cli.BoolFlag{
Name: "jitvm",
Usage: "Enable the JIT VM",
}

// logging and debug settings
LogFileFlag = cli.StringFlag{
Name: "logfile",
Expand All @@ -196,10 +216,6 @@ var (
Usage: "The syntax of the argument is a comma-separated list of pattern=N, where pattern is a literal file name (minus the \".go\" suffix) or \"glob\" pattern and N is a log verbosity level.",
Value: glog.GetVModule(),
}
VMDebugFlag = cli.BoolFlag{
Name: "vmdebug",
Usage: "Virtual Machine debug output",
}
BacktraceAtFlag = cli.GenericFlag{
Name: "backtrace_at",
Usage: "If set to a file and line number (e.g., \"block.go:271\") holding a logging statement, a stack trace will be logged",
Expand Down Expand Up @@ -434,6 +450,13 @@ func SetupLogger(ctx *cli.Context) {
glog.SetLogDir(ctx.GlobalString(LogFileFlag.Name))
}

// SetupVM configured the VM package's global settings
func SetupVM(ctx *cli.Context) {
vm.DisableJit = !ctx.GlobalBool(VMEnableJitFlag.Name)
vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name)
vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
}

// MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context) (chain *core.ChainManager, blockDB, stateDB, extraDB common.Database) {
datadir := ctx.GlobalString(DataDirFlag.Name)
Expand Down
2 changes: 0 additions & 2 deletions core/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
}

func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
// If we are mining this block and validating we want to set the logs back to 0

cb := statedb.GetStateObject(coinbase.Address())
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, cb)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion core/chain_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
switch status {
case CanonStatTy:
if glog.V(logger.Debug) {
glog.Infof("[%v] inserted block #%d (%d TXs %d UNCs) (%x...). Took %v\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart))
glog.Infof("[%v] inserted block #%d (%d TXs %v G %d UNCs) (%x...). Took %v\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), block.GasUsed(), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart))
}
queue[i] = ChainEvent{block, block.Hash(), logs}
queueEvent.canonicalCount++
Expand Down
27 changes: 17 additions & 10 deletions core/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/params"
)

// Execution is the execution environment for the given call or create action.
type Execution struct {
env vm.Environment
address *common.Address
Expand All @@ -35,19 +36,25 @@ type Execution struct {
Gas, price, value *big.Int
}

// NewExecution returns a new execution environment that handles all calling
// and creation logic defined by the YP.
func NewExecution(env vm.Environment, address *common.Address, input []byte, gas, gasPrice, value *big.Int) *Execution {
exe := &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value}
exe.evm = vm.NewVm(env)
return exe
}

// Call executes within the given context
func (self *Execution) Call(codeAddr common.Address, caller vm.ContextRef) ([]byte, error) {
// Retrieve the executing code
code := self.env.State().GetCode(codeAddr)

return self.exec(&codeAddr, code, caller)
}

// Create creates a new contract and runs the initialisation procedure of the
// contract. This returns the returned code for the contract and is stored
// elsewhere.
func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) {
// Input must be nil for create
code := self.input
Expand All @@ -63,16 +70,24 @@ func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, acco
return
}

// exec executes the given code and executes within the contextAddr context.
func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) {
env := self.env
evm := self.evm
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(self.Gas, self.price)

return nil, vm.DepthError
}

vsnapshot := env.State().Copy()
if !env.CanTransfer(env.State().GetStateObject(caller.Address()), self.value) {
caller.ReturnGas(self.Gas, self.price)

return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", self.value, env.State().GetBalance(caller.Address()))
}

var createAccount bool
if self.address == nil {
// Generate a new address
Expand All @@ -95,15 +110,7 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.
} else {
to = env.State().GetOrNewStateObject(*self.address)
}

err = env.Transfer(from, to, self.value)
if err != nil {
env.State().Set(vsnapshot)

caller.ReturnGas(self.Gas, self.price)

return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", self.value, from.Balance())
}
vm.Transfer(from, to, self.value)

context := vm.NewContext(caller, to, self.value, self.Gas, self.price)
context.SetCallCode(contextAddr, code)
Expand Down
1 change: 1 addition & 0 deletions core/vm/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Context struct {
jumpdests destinations // result of JUMPDEST analysis.

Code []byte
Input []byte
CodeAddr *common.Address

value, Gas, UsedGas, Price *big.Int
Expand Down
2 changes: 1 addition & 1 deletion core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func ecrecoverFunc(in []byte) []byte {
v := byte(vbig.Uint64())

if !crypto.ValidateSignatureValues(v, r, s) {
glog.V(logger.Error).Infof("EC RECOVER FAIL: v, r or s value invalid")
glog.V(logger.Debug).Infof("EC RECOVER FAIL: v, r or s value invalid")
return nil
}

Expand Down
1 change: 1 addition & 0 deletions core/vm/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Environment interface {
Time() uint64
Difficulty() *big.Int
GasLimit() *big.Int
CanTransfer(from Account, balance *big.Int) bool
Transfer(from, to Account, amount *big.Int) error
AddLog(*state.Log)
AddStructLog(StructLog)
Expand Down
4 changes: 2 additions & 2 deletions core/vm/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ func baseCheck(op OpCode, stack *stack, gas *big.Int) error {
return err
}

if r.stackPush > 0 && len(stack.data)-r.stackPop+r.stackPush > int(params.StackLimit.Int64())+1 {
return fmt.Errorf("stack limit reached %d (%d)", len(stack.data), params.StackLimit.Int64())
if r.stackPush > 0 && stack.len()-r.stackPop+r.stackPush > int(params.StackLimit.Int64()) {
return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
}

gas.Add(gas, r.gas)
Expand Down
Loading