plugeth/cmd/evm/main.go

237 lines
6.5 KiB
Go
Raw Normal View History

2015-07-07 00:54:22 +00:00
// Copyright 2014 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-07 00:54:22 +00:00
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
2014-11-10 10:47:37 +00:00
2015-07-07 03:08:16 +00:00
// evm executes EVM code snippets.
2014-11-10 10:47:37 +00:00
package main
import (
"fmt"
"math/big"
"os"
"runtime"
"time"
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
2015-03-22 11:12:29 +00:00
"github.com/ethereum/go-ethereum/common"
2014-12-04 10:30:41 +00:00
"github.com/ethereum/go-ethereum/core"
2015-03-24 14:27:05 +00:00
"github.com/ethereum/go-ethereum/core/state"
2014-12-04 10:30:41 +00:00
"github.com/ethereum/go-ethereum/core/types"
2015-03-24 14:27:05 +00:00
"github.com/ethereum/go-ethereum/core/vm"
2014-11-10 11:42:16 +00:00
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger/glog"
2014-11-10 10:47:37 +00:00
)
var (
app *cli.App
DebugFlag = cli.BoolFlag{
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",
}
GasFlag = cli.StringFlag{
Name: "gas",
Usage: "gas limit for the evm",
Value: "10000000000",
}
PriceFlag = cli.StringFlag{
Name: "price",
Usage: "price set for the evm",
Value: "0",
}
ValueFlag = cli.StringFlag{
Name: "value",
Usage: "value set for the evm",
Value: "0",
}
DumpFlag = cli.BoolFlag{
Name: "dump",
Usage: "dumps the state after the run",
}
InputFlag = cli.StringFlag{
Name: "input",
Usage: "input for the EVM",
}
SysStatFlag = cli.BoolFlag{
Name: "sysstat",
Usage: "display system stats",
}
2014-11-10 10:47:37 +00:00
)
func init() {
app = utils.NewApp("0.2", "the evm command line interface")
app.Flags = []cli.Flag{
DebugFlag,
ForceJitFlag,
DisableJitFlag,
SysStatFlag,
CodeFlag,
GasFlag,
PriceFlag,
ValueFlag,
DumpFlag,
InputFlag,
}
app.Action = run
2014-11-10 10:47:37 +00:00
}
func run(ctx *cli.Context) {
vm.Debug = ctx.GlobalBool(DebugFlag.Name)
vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name)
vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name)
glog.SetToStderr(true)
2014-11-10 10:47:37 +00:00
2014-12-04 10:30:41 +00:00
db, _ := ethdb.NewMemDatabase()
2015-03-22 11:12:29 +00:00
statedb := state.New(common.Hash{}, db)
2015-04-01 09:42:02 +00:00
sender := statedb.CreateAccount(common.StringToAddress("sender"))
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
2014-12-04 10:30:41 +00:00
vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)))
2014-11-10 10:47:37 +00:00
tstart := time.Now()
ret, e := vmenv.Call(
sender,
receiver.Address(),
common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)),
common.Big(ctx.GlobalString(GasFlag.Name)),
common.Big(ctx.GlobalString(PriceFlag.Name)),
common.Big(ctx.GlobalString(ValueFlag.Name)),
)
vmdone := time.Since(tstart)
2014-11-10 10:47:37 +00:00
if ctx.GlobalBool(DumpFlag.Name) {
2014-12-04 10:30:41 +00:00
fmt.Println(string(statedb.Dump()))
2014-11-10 11:42:16 +00:00
}
vm.StdErrFormat(vmenv.StructLogs())
if ctx.GlobalBool(SysStatFlag.Name) {
var mem runtime.MemStats
runtime.ReadMemStats(&mem)
fmt.Printf("vm took %v\n", vmdone)
fmt.Printf(`alloc: %d
2014-11-10 10:47:37 +00:00
tot alloc: %d
no. malloc: %d
heap alloc: %d
heap objs: %d
num gc: %d
`, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC)
}
2014-11-10 10:47:37 +00:00
fmt.Printf("OUT: 0x%x", ret)
if e != nil {
fmt.Printf(" error: %v", e)
}
fmt.Println()
}
func main() {
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
2014-11-10 10:47:37 +00:00
}
2014-12-04 10:30:41 +00:00
type VMEnv struct {
2014-12-04 11:09:22 +00:00
state *state.StateDB
2014-12-04 10:30:41 +00:00
block *types.Block
2015-03-22 11:12:29 +00:00
transactor *common.Address
2014-12-04 10:30:41 +00:00
value *big.Int
depth int
Gas *big.Int
2015-06-30 07:13:16 +00:00
time uint64
2015-06-10 14:46:43 +00:00
logs []vm.StructLog
2014-11-10 10:47:37 +00:00
}
2015-03-22 11:12:29 +00:00
func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int) *VMEnv {
2014-12-04 10:30:41 +00:00
return &VMEnv{
state: state,
2015-03-22 11:12:29 +00:00
transactor: &transactor,
2014-12-04 10:30:41 +00:00
value: value,
2015-06-30 07:13:16 +00:00
time: uint64(time.Now().Unix()),
2014-12-04 10:30:41 +00:00
}
}
2015-03-22 11:12:29 +00:00
func (self *VMEnv) State() *state.StateDB { return self.state }
func (self *VMEnv) Origin() common.Address { return *self.transactor }
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
2015-06-30 07:13:16 +00:00
func (self *VMEnv) Time() uint64 { return self.time }
2015-03-22 11:12:29 +00:00
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
func (self *VMEnv) Depth() int { return 0 }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) common.Hash {
if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 {
return self.block.Hash()
}
2015-03-22 11:12:29 +00:00
return common.Hash{}
}
2015-06-10 14:46:43 +00:00
func (self *VMEnv) AddStructLog(log vm.StructLog) {
self.logs = append(self.logs, log)
}
func (self *VMEnv) StructLogs() []vm.StructLog {
return self.logs
}
2015-04-08 18:45:39 +00:00
func (self *VMEnv) AddLog(log *state.Log) {
2014-12-04 10:30:41 +00:00
self.state.AddLog(log)
}
func (self *VMEnv) CanTransfer(from vm.Account, balance *big.Int) bool {
return from.Balance().Cmp(balance) >= 0
}
2014-12-04 10:30:41 +00:00
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
return vm.Transfer(from, to, amount)
}
2015-03-22 11:12:29 +00:00
func (self *VMEnv) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution {
2014-12-21 14:13:06 +00:00
return core.NewExecution(self, addr, data, gas, price, value)
2014-12-04 10:30:41 +00:00
}
2015-03-22 11:12:29 +00:00
func (self *VMEnv) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
exe := self.vm(&addr, data, gas, price, value)
2014-12-04 10:30:41 +00:00
ret, err := exe.Call(addr, caller)
self.Gas = exe.Gas
return ret, err
}
2015-03-22 11:12:29 +00:00
func (self *VMEnv) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
a := caller.Address()
exe := self.vm(&a, data, gas, price, value)
2014-12-04 10:30:41 +00:00
return exe.Call(addr, caller)
2014-11-10 10:47:37 +00:00
}
2015-03-24 14:27:05 +00:00
func (self *VMEnv) Create(caller vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
exe := self.vm(nil, data, gas, price, value)
2014-12-04 10:30:41 +00:00
return exe.Create(caller)
2014-11-10 10:47:37 +00:00
}