Merge branch 'develop' into rpcfrontier
This commit is contained in:
		@@ -168,7 +168,7 @@ func main() {
 | 
			
		||||
		logger.Flush()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	utils.HandleInterrupt()
 | 
			
		||||
	//utils.HandleInterrupt()
 | 
			
		||||
 | 
			
		||||
	utils.InitConfig(VmType, ConfigFile, Datadir, "ethblocktest")
 | 
			
		||||
 | 
			
		||||
@@ -190,12 +190,17 @@ func main() {
 | 
			
		||||
		MinerThreads: MinerThreads,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	utils.StartEthereumForTest(ethereum)
 | 
			
		||||
	utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
 | 
			
		||||
	utils.StartEthereum(ethereum)
 | 
			
		||||
 | 
			
		||||
	ethereum.ChainManager().ResetWithGenesisBlock(blocks[0])
 | 
			
		||||
	// bph := ethereum.ChainManager().GetBlock(blocks[1].Header().ParentHash)
 | 
			
		||||
	// fmt.Println("bph: ", bph)
 | 
			
		||||
 | 
			
		||||
	// fmt.Println("HURR: ", hex.EncodeToString(ethutil.Encode(blocks[0].RlpData())))
 | 
			
		||||
	//fmt.Println("b0: ", hex.EncodeToString(ethutil.Encode(blocks[0].RlpData())))
 | 
			
		||||
	//fmt.Println("b0: ", hex.EncodeToString(blocks[0].Hash()))
 | 
			
		||||
	//fmt.Println("b1: ", hex.EncodeToString(ethutil.Encode(blocks[1].RlpData())))
 | 
			
		||||
	//fmt.Println("b1: ", hex.EncodeToString(blocks[1].Hash()))
 | 
			
		||||
 | 
			
		||||
	go ethereum.ChainManager().InsertChain(types.Blocks{blocks[1]})
 | 
			
		||||
	fmt.Println("OK! ")
 | 
			
		||||
@@ -254,6 +259,9 @@ func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gb := types.NewBlockWithHeader(gbh)
 | 
			
		||||
	//gb.uncles = *new([]*types.Header)
 | 
			
		||||
	//gb.transactions = *new(types.Transactions)
 | 
			
		||||
	gb.Td = new(big.Int)
 | 
			
		||||
	gb.Reward = new(big.Int)
 | 
			
		||||
 | 
			
		||||
	testBlock := new(types.Block)
 | 
			
		||||
 
 | 
			
		||||
@@ -87,6 +87,11 @@ runtime will execute the file and exit.
 | 
			
		||||
			Name:   "import",
 | 
			
		||||
			Usage:  `import a blockchain file`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Action: exportchain,
 | 
			
		||||
			Name:   "export",
 | 
			
		||||
			Usage:  `export blockchain into file`,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	app.Author = ""
 | 
			
		||||
	app.Email = ""
 | 
			
		||||
@@ -171,25 +176,39 @@ func importchain(ctx *cli.Context) {
 | 
			
		||||
	if len(ctx.Args()) != 1 {
 | 
			
		||||
		utils.Fatalf("This command requires an argument.")
 | 
			
		||||
	}
 | 
			
		||||
	chain, _, _ := utils.GetChain(ctx)
 | 
			
		||||
	chainmgr, _, _ := utils.GetChain(ctx)
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	err := utils.ImportChain(chain, ctx.Args().First())
 | 
			
		||||
	err := utils.ImportChain(chainmgr, ctx.Args().First())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		utils.Fatalf("Import error: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Import done in", time.Since(start))
 | 
			
		||||
	fmt.Printf("Import done in %v", time.Since(start))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func exportchain(ctx *cli.Context) {
 | 
			
		||||
	if len(ctx.Args()) != 1 {
 | 
			
		||||
		utils.Fatalf("This command requires an argument.")
 | 
			
		||||
	}
 | 
			
		||||
	chainmgr, _, _ := utils.GetChain(ctx)
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	err := utils.ExportChain(chainmgr, ctx.Args().First())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		utils.Fatalf("Export error: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Export done in %v", time.Since(start))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func dump(ctx *cli.Context) {
 | 
			
		||||
	chain, _, stateDb := utils.GetChain(ctx)
 | 
			
		||||
	chainmgr, _, stateDb := utils.GetChain(ctx)
 | 
			
		||||
	for _, arg := range ctx.Args() {
 | 
			
		||||
		var block *types.Block
 | 
			
		||||
		if hashish(arg) {
 | 
			
		||||
			block = chain.GetBlock(ethutil.Hex2Bytes(arg))
 | 
			
		||||
			block = chainmgr.GetBlock(ethutil.Hex2Bytes(arg))
 | 
			
		||||
		} else {
 | 
			
		||||
			num, _ := strconv.Atoi(arg)
 | 
			
		||||
			block = chain.GetBlockByNumber(uint64(num))
 | 
			
		||||
			block = chainmgr.GetBlockByNumber(uint64(num))
 | 
			
		||||
		}
 | 
			
		||||
		if block == nil {
 | 
			
		||||
			fmt.Println("{}")
 | 
			
		||||
@@ -209,11 +228,13 @@ func hashish(x string) bool {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func version(c *cli.Context) {
 | 
			
		||||
	fmt.Printf(`%v %v
 | 
			
		||||
PV=%d
 | 
			
		||||
GOOS=%s
 | 
			
		||||
GO=%s
 | 
			
		||||
	fmt.Printf(`%v
 | 
			
		||||
Version: %v
 | 
			
		||||
Protocol Version: %d
 | 
			
		||||
Network Id: %d
 | 
			
		||||
GO: %s
 | 
			
		||||
OS: %s
 | 
			
		||||
GOPATH=%s
 | 
			
		||||
GOROOT=%s
 | 
			
		||||
`, ClientIdentifier, Version, eth.ProtocolVersion, runtime.GOOS, runtime.Version(), os.Getenv("GOPATH"), runtime.GOROOT())
 | 
			
		||||
`, ClientIdentifier, Version, eth.ProtocolVersion, eth.NetworkId, runtime.Version(), runtime.GOOS, os.Getenv("GOPATH"), runtime.GOROOT())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -194,13 +194,6 @@ ApplicationWindow {
 | 
			
		||||
 | 
			
		||||
        Menu {
 | 
			
		||||
            title: "Developer"
 | 
			
		||||
            MenuItem {
 | 
			
		||||
                iconSource: "../icecream.png"
 | 
			
		||||
                text: "Debugger"
 | 
			
		||||
                shortcut: "Ctrl+d"
 | 
			
		||||
                onTriggered: eth.startDebugger()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            MenuItem {
 | 
			
		||||
                text: "Import Tx"
 | 
			
		||||
                onTriggered: {
 | 
			
		||||
@@ -756,24 +749,6 @@ ApplicationWindow {
 | 
			
		||||
                     }
 | 
			
		||||
                 }
 | 
			
		||||
 | 
			
		||||
                 Rectangle {
 | 
			
		||||
                     height: 55
 | 
			
		||||
                     color: "transparent"
 | 
			
		||||
                     visible: true
 | 
			
		||||
                     Text {
 | 
			
		||||
                         text: "DEBUG"
 | 
			
		||||
                         font.family: sourceSansPro.name 
 | 
			
		||||
                         font.weight: Font.DemiBold
 | 
			
		||||
                         anchors {
 | 
			
		||||
                             left: parent.left
 | 
			
		||||
                             top: parent.verticalCenter
 | 
			
		||||
                             leftMargin: 16
 | 
			
		||||
                         }
 | 
			
		||||
                         color: "#AAA0A0"
 | 
			
		||||
                     }
 | 
			
		||||
                 }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                 ColumnLayout {
 | 
			
		||||
                     id: menuLegacy
 | 
			
		||||
                     visible: true
 | 
			
		||||
 
 | 
			
		||||
@@ -178,7 +178,6 @@ Rectangle {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		function showContractData(tx) {
 | 
			
		||||
			txDetailsDebugButton.tx = tx
 | 
			
		||||
			if(tx.createsContract) {
 | 
			
		||||
				contractData.text = tx.data
 | 
			
		||||
				contractLabel.text = "<h4> Transaction created contract " + tx.address + "</h4>"
 | 
			
		||||
@@ -202,22 +201,6 @@ Rectangle {
 | 
			
		||||
				id: contractLabel
 | 
			
		||||
				anchors.leftMargin: 10
 | 
			
		||||
			}
 | 
			
		||||
			Button {
 | 
			
		||||
				property var tx
 | 
			
		||||
				id: txDetailsDebugButton
 | 
			
		||||
				anchors.right: parent.right
 | 
			
		||||
				anchors.rightMargin: 10
 | 
			
		||||
				anchors.top: parent.top
 | 
			
		||||
				anchors.topMargin: 10
 | 
			
		||||
				text: "Debug contract"
 | 
			
		||||
				onClicked: {
 | 
			
		||||
					if(tx && tx.createsContract){
 | 
			
		||||
						eth.startDbWithCode(tx.rawData)
 | 
			
		||||
					}else {
 | 
			
		||||
						eth.startDbWithContractAndData(tx.address, tx.rawData)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			TextArea {
 | 
			
		||||
				id: contractData
 | 
			
		||||
				text: "Contract"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,367 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
	This file is part of go-ethereum
 | 
			
		||||
 | 
			
		||||
	go-ethereum is free software: you can redistribute it and/or modify
 | 
			
		||||
	it under the terms of the GNU General Public License as published by
 | 
			
		||||
	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
	(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
	go-ethereum is distributed in the hope that it will be useful,
 | 
			
		||||
	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
	GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
	You should have received a copy of the GNU General Public License
 | 
			
		||||
	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
/**
 | 
			
		||||
 * @authors
 | 
			
		||||
 * 	Jeffrey Wilcke <i@jev.io>
 | 
			
		||||
 */
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/cmd/utils"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/core"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/ethutil"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/state"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/vm"
 | 
			
		||||
	"github.com/obscuren/qml"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DebuggerWindow struct {
 | 
			
		||||
	win    *qml.Window
 | 
			
		||||
	engine *qml.Engine
 | 
			
		||||
	lib    *UiLib
 | 
			
		||||
 | 
			
		||||
	vm *vm.Vm
 | 
			
		||||
	Db *Debugger
 | 
			
		||||
 | 
			
		||||
	state *state.StateDB
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
 | 
			
		||||
	engine := qml.NewEngine()
 | 
			
		||||
	component, err := engine.LoadFile(lib.AssetPath("debugger/debugger.qml"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err)
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	win := component.CreateWindow(nil)
 | 
			
		||||
 | 
			
		||||
	w := &DebuggerWindow{engine: engine, win: win, lib: lib, vm: &vm.Vm{}}
 | 
			
		||||
	w.Db = NewDebugger(w)
 | 
			
		||||
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Show() {
 | 
			
		||||
	context := self.engine.Context()
 | 
			
		||||
	context.SetVar("dbg", self)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		self.win.Show()
 | 
			
		||||
		self.win.Wait()
 | 
			
		||||
	}()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) SetCode(code string) {
 | 
			
		||||
	self.win.Set("codeText", code)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) SetData(data string) {
 | 
			
		||||
	self.win.Set("dataText", data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) SetAsm(data []byte) {
 | 
			
		||||
	self.win.Root().Call("clearAsm")
 | 
			
		||||
 | 
			
		||||
	dis := core.Disassemble(data)
 | 
			
		||||
	for _, str := range dis {
 | 
			
		||||
		self.win.Root().Call("setAsm", str)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Compile(code string) {
 | 
			
		||||
	var err error
 | 
			
		||||
	script := ethutil.StringToByteFunc(code, func(s string) (ret []byte) {
 | 
			
		||||
		ret, err = ethutil.Compile(s, true)
 | 
			
		||||
		return
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		self.SetAsm(script)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Used by QML
 | 
			
		||||
func (self *DebuggerWindow) AutoComp(code string) {
 | 
			
		||||
	if self.Db.done {
 | 
			
		||||
		self.Compile(code)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) ClearLog() {
 | 
			
		||||
	self.win.Root().Call("clearLog")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, dataStr string) {
 | 
			
		||||
	self.Stop()
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if r := recover(); r != nil {
 | 
			
		||||
			self.Logf("compile FAULT: %v", r)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	data := utils.FormatTransactionData(dataStr)
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
 | 
			
		||||
		ret, err = ethutil.Compile(s, false)
 | 
			
		||||
		return
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		self.Logln(err)
 | 
			
		||||
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		gas      = ethutil.Big(gasStr)
 | 
			
		||||
		gasPrice = ethutil.Big(gasPriceStr)
 | 
			
		||||
		value    = ethutil.Big(valueStr)
 | 
			
		||||
		// Contract addr as test address
 | 
			
		||||
		keyPair = self.lib.eth.KeyManager().KeyPair()
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	statedb := self.lib.eth.ChainManager().TransState()
 | 
			
		||||
	account := self.lib.eth.ChainManager().TransState().GetAccount(keyPair.Address())
 | 
			
		||||
	contract := statedb.NewStateObject([]byte{0})
 | 
			
		||||
	contract.SetCode(script)
 | 
			
		||||
	contract.SetBalance(value)
 | 
			
		||||
 | 
			
		||||
	self.SetAsm(script)
 | 
			
		||||
 | 
			
		||||
	block := self.lib.eth.ChainManager().CurrentBlock()
 | 
			
		||||
 | 
			
		||||
	msg := types.NewTransactionMessage(nil, value, gas, gasPrice, data)
 | 
			
		||||
	env := core.NewEnv(statedb, self.lib.eth.ChainManager(), msg, block)
 | 
			
		||||
 | 
			
		||||
	self.Logf("callsize %d", len(script))
 | 
			
		||||
	go func() {
 | 
			
		||||
		pgas := new(big.Int).Set(gas)
 | 
			
		||||
		ret, err := env.Call(account, contract.Address(), data, gas, gasPrice, ethutil.Big0)
 | 
			
		||||
 | 
			
		||||
		rgas := new(big.Int).Sub(pgas, gas)
 | 
			
		||||
		tot := new(big.Int).Mul(rgas, gasPrice)
 | 
			
		||||
		self.Logf("gas usage %v total price = %v (%v)", rgas, tot, ethutil.CurrencyToString(tot))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			self.Logln("exited with errors:", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			if len(ret) > 0 {
 | 
			
		||||
				self.Logf("exited: % x", ret)
 | 
			
		||||
			} else {
 | 
			
		||||
				self.Logf("exited: nil")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		statedb.Reset()
 | 
			
		||||
 | 
			
		||||
		if !self.Db.interrupt {
 | 
			
		||||
			self.Db.done = true
 | 
			
		||||
		} else {
 | 
			
		||||
			self.Db.interrupt = false
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Logf(format string, v ...interface{}) {
 | 
			
		||||
	self.win.Root().Call("setLog", fmt.Sprintf(format, v...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Logln(v ...interface{}) {
 | 
			
		||||
	str := fmt.Sprintln(v...)
 | 
			
		||||
	self.Logf("%s", str[:len(str)-1])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Next() {
 | 
			
		||||
	self.Db.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Continue() {
 | 
			
		||||
	self.vm.Stepping = false
 | 
			
		||||
	self.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) Stop() {
 | 
			
		||||
	if !self.Db.done {
 | 
			
		||||
		self.Db.Q <- true
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *DebuggerWindow) ExecCommand(command string) {
 | 
			
		||||
	if len(command) > 0 {
 | 
			
		||||
		cmd := strings.Split(command, " ")
 | 
			
		||||
		switch cmd[0] {
 | 
			
		||||
		case "help":
 | 
			
		||||
			self.Logln("Debugger commands:")
 | 
			
		||||
			self.Logln("break, bp                 Set breakpoint on instruction")
 | 
			
		||||
			self.Logln("clear [log, break, bp]    Clears previous set sub-command(s)")
 | 
			
		||||
		case "break", "bp":
 | 
			
		||||
			if len(cmd) > 1 {
 | 
			
		||||
				lineNo, err := strconv.Atoi(cmd[1])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					self.Logln(err)
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				self.Db.breakPoints = append(self.Db.breakPoints, int64(lineNo))
 | 
			
		||||
				self.Logf("break point set on instruction %d", lineNo)
 | 
			
		||||
			} else {
 | 
			
		||||
				self.Logf("'%s' requires line number", cmd[0])
 | 
			
		||||
			}
 | 
			
		||||
		case "clear":
 | 
			
		||||
			if len(cmd) > 1 {
 | 
			
		||||
				switch cmd[1] {
 | 
			
		||||
				case "break", "bp":
 | 
			
		||||
					self.Db.breakPoints = nil
 | 
			
		||||
 | 
			
		||||
					self.Logln("Breakpoints cleared")
 | 
			
		||||
				case "log":
 | 
			
		||||
					self.ClearLog()
 | 
			
		||||
				default:
 | 
			
		||||
					self.Logf("clear '%s' is not valid", cmd[1])
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				self.Logln("'clear' requires sub command")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			self.Logf("Unknown command %s", cmd[0])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Debugger struct {
 | 
			
		||||
	N               chan bool
 | 
			
		||||
	Q               chan bool
 | 
			
		||||
	done, interrupt bool
 | 
			
		||||
	breakPoints     []int64
 | 
			
		||||
	main            *DebuggerWindow
 | 
			
		||||
	win             *qml.Window
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewDebugger(main *DebuggerWindow) *Debugger {
 | 
			
		||||
	db := &Debugger{make(chan bool), make(chan bool), true, false, nil, main, main.win}
 | 
			
		||||
 | 
			
		||||
	return db
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type storeVal struct {
 | 
			
		||||
	Key, Value string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Debugger) Step(evm vm.VirtualMachine, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, context *vm.Context) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Debugger) BreakHook(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, stateObject *state.StateObject) bool {
 | 
			
		||||
	self.main.Logln("break on instr:", pc)
 | 
			
		||||
 | 
			
		||||
	return self.halting(pc, op, mem, stack, stateObject)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Debugger) StepHook(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, stateObject *state.StateObject) bool {
 | 
			
		||||
	return self.halting(pc, op, mem, stack, stateObject)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Debugger) SetCode(byteCode []byte) {
 | 
			
		||||
	self.main.SetAsm(byteCode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Debugger) BreakPoints() []int64 {
 | 
			
		||||
	return self.breakPoints
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Debugger) halting(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, stateObject *state.StateObject) bool {
 | 
			
		||||
	d.win.Root().Call("setInstruction", pc)
 | 
			
		||||
	d.win.Root().Call("clearMem")
 | 
			
		||||
	d.win.Root().Call("clearStack")
 | 
			
		||||
	d.win.Root().Call("clearStorage")
 | 
			
		||||
 | 
			
		||||
	addr := 0
 | 
			
		||||
	for i := 0; i+16 <= mem.Len(); i += 16 {
 | 
			
		||||
		dat := mem.Data()[i : i+16]
 | 
			
		||||
		var str string
 | 
			
		||||
 | 
			
		||||
		for _, d := range dat {
 | 
			
		||||
			if unicode.IsGraphic(rune(d)) {
 | 
			
		||||
				str += string(d)
 | 
			
		||||
			} else {
 | 
			
		||||
				str += "?"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("%s  % x", str, dat)})
 | 
			
		||||
		addr += 16
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, val := range stack.Data() {
 | 
			
		||||
		d.win.Root().Call("setStack", val.String())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	it := stateObject.Trie().Iterator()
 | 
			
		||||
	for it.Next() {
 | 
			
		||||
		d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", it.Key), fmt.Sprintf("% x", it.Value)})
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stackFrameAt := new(big.Int).SetBytes(mem.Get(0, 32))
 | 
			
		||||
	psize := mem.Len() - int(new(big.Int).SetBytes(mem.Get(0, 32)).Uint64())
 | 
			
		||||
	d.win.Root().ObjectByName("stackFrame").Set("text", fmt.Sprintf(`<b>stack ptr</b>: %v`, stackFrameAt))
 | 
			
		||||
	d.win.Root().ObjectByName("stackSize").Set("text", fmt.Sprintf(`<b>stack size</b>: %d`, psize))
 | 
			
		||||
	d.win.Root().ObjectByName("memSize").Set("text", fmt.Sprintf(`<b>mem size</b>: %v`, mem.Len()))
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-d.N:
 | 
			
		||||
			break out
 | 
			
		||||
		case <-d.Q:
 | 
			
		||||
			d.interrupt = true
 | 
			
		||||
			d.clearBuffers()
 | 
			
		||||
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Debugger) clearBuffers() {
 | 
			
		||||
out:
 | 
			
		||||
	// drain
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-d.N:
 | 
			
		||||
		case <-d.Q:
 | 
			
		||||
		default:
 | 
			
		||||
			break out
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Debugger) Next() {
 | 
			
		||||
	if !d.done {
 | 
			
		||||
		d.N <- true
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -47,9 +47,7 @@ type UiLib struct {
 | 
			
		||||
	connected bool
 | 
			
		||||
	assetPath string
 | 
			
		||||
	// The main application window
 | 
			
		||||
	win      *qml.Window
 | 
			
		||||
	Db       *Debugger
 | 
			
		||||
	DbWindow *DebuggerWindow
 | 
			
		||||
	win *qml.Window
 | 
			
		||||
 | 
			
		||||
	jsEngine *javascript.JSRE
 | 
			
		||||
 | 
			
		||||
@@ -126,29 +124,6 @@ func (ui *UiLib) AssetPath(p string) string {
 | 
			
		||||
	return path.Join(ui.assetPath, p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
 | 
			
		||||
	dbWindow := NewDebuggerWindow(self)
 | 
			
		||||
	object := self.eth.ChainManager().State().GetStateObject(ethutil.Hex2Bytes(contractHash))
 | 
			
		||||
	if len(object.Code()) > 0 {
 | 
			
		||||
		dbWindow.SetCode(ethutil.Bytes2Hex(object.Code()))
 | 
			
		||||
	}
 | 
			
		||||
	dbWindow.SetData(data)
 | 
			
		||||
 | 
			
		||||
	dbWindow.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *UiLib) StartDbWithCode(code string) {
 | 
			
		||||
	dbWindow := NewDebuggerWindow(self)
 | 
			
		||||
	dbWindow.SetCode(code)
 | 
			
		||||
	dbWindow.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *UiLib) StartDebugger() {
 | 
			
		||||
	dbWindow := NewDebuggerWindow(self)
 | 
			
		||||
 | 
			
		||||
	dbWindow.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
 | 
			
		||||
	object := mapToTxParams(params)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,6 @@ import (
 | 
			
		||||
	"github.com/ethereum/go-ethereum/logger"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rlp"
 | 
			
		||||
	rpchttp "github.com/ethereum/go-ethereum/rpc/http"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/state"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/xeth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -134,6 +133,15 @@ func StartEthereum(ethereum *eth.Ethereum) {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StartEthereumForTest(ethereum *eth.Ethereum) {
 | 
			
		||||
	clilogger.Infoln("Starting ", ethereum.Name())
 | 
			
		||||
	ethereum.StartForTest()
 | 
			
		||||
	RegisterInterrupt(func(sig os.Signal) {
 | 
			
		||||
		ethereum.Stop()
 | 
			
		||||
		logger.Flush()
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
 | 
			
		||||
	var err error
 | 
			
		||||
	switch {
 | 
			
		||||
@@ -188,27 +196,8 @@ func FormatTransactionData(data string) []byte {
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Replay block
 | 
			
		||||
func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
 | 
			
		||||
	block := ethereum.ChainManager().GetBlock(hash)
 | 
			
		||||
	if block == nil {
 | 
			
		||||
		return fmt.Errorf("unknown block %x", hash)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parent := ethereum.ChainManager().GetBlock(block.ParentHash())
 | 
			
		||||
 | 
			
		||||
	statedb := state.New(parent.Root(), ethereum.StateDb())
 | 
			
		||||
	_, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ImportChain(chain *core.ChainManager, fn string) error {
 | 
			
		||||
	fmt.Printf("importing chain '%s'\n", fn)
 | 
			
		||||
func ImportChain(chainmgr *core.ChainManager, fn string) error {
 | 
			
		||||
	fmt.Printf("importing blockchain '%s'\n", fn)
 | 
			
		||||
	fh, err := os.OpenFile(fn, os.O_RDONLY, os.ModePerm)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@@ -220,11 +209,24 @@ func ImportChain(chain *core.ChainManager, fn string) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	chain.Reset()
 | 
			
		||||
	if err := chain.InsertChain(blocks); err != nil {
 | 
			
		||||
	chainmgr.Reset()
 | 
			
		||||
	if err := chainmgr.InsertChain(blocks); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("imported %d blocks\n", len(blocks))
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ExportChain(chainmgr *core.ChainManager, fn string) error {
 | 
			
		||||
	fmt.Printf("exporting blockchain '%s'\n", fn)
 | 
			
		||||
 | 
			
		||||
	data := chainmgr.Export()
 | 
			
		||||
 | 
			
		||||
	if err := ethutil.WriteFile(fn, data); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("exported blockchain\n")
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -261,7 +261,7 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if block.Time <= parent.Time {
 | 
			
		||||
		return ValidationError("Block timestamp not after or equal to prev block (%v - %v)", block.Time, parent.Time)
 | 
			
		||||
		return ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if int64(block.Time) > time.Now().Unix() {
 | 
			
		||||
 
 | 
			
		||||
@@ -275,6 +275,17 @@ func (s *Ethereum) Start() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Ethereum) StartForTest() {
 | 
			
		||||
		jsonlogger.LogJson(&logger.LogStarting{
 | 
			
		||||
		ClientString:    s.net.Name,
 | 
			
		||||
		ProtocolVersion: ProtocolVersion,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// Start services
 | 
			
		||||
	s.txPool.Start()
 | 
			
		||||
	s.blockPool.Start()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Ethereum) SuggestPeer(nodeURL string) error {
 | 
			
		||||
	n, err := discover.ParseNode(nodeURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +1,21 @@
 | 
			
		||||
package natspec
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/obscuren/otto"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type NatSpec struct {
 | 
			
		||||
	jsvm *otto.Otto
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewNATSpec(transaction string) (self *NatSpec, err error) {
 | 
			
		||||
// TODO: should initialise with abi and userdoc jsons
 | 
			
		||||
func New() (self *NatSpec, err error) {
 | 
			
		||||
 | 
			
		||||
	self = new(NatSpec)
 | 
			
		||||
	self.jsvm = otto.New()
 | 
			
		||||
	code, err := ioutil.ReadFile("natspec.js")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = self.jsvm.Run(string(code))
 | 
			
		||||
	_, err = self.jsvm.Run(natspecJS)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
@@ -27,39 +24,40 @@ func NewNATSpec(transaction string) (self *NatSpec, err error) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	self.jsvm.Run("var transaction = " + transaction + ";")
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *NatSpec) SetDescription(desc string) (err error) {
 | 
			
		||||
func (self *NatSpec) Notice(transaction, abi, method, expression string) (string, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	if _, err = self.jsvm.Run("var transaction = " + transaction + ";"); err != nil {
 | 
			
		||||
		return "", fmt.Errorf("natspec.js error setting transaction: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = self.jsvm.Run("var expression = \"" + desc + "\";")
 | 
			
		||||
	return
 | 
			
		||||
	if _, err = self.jsvm.Run("var abi = " + abi + ";"); err != nil {
 | 
			
		||||
		return "", fmt.Errorf("natspec.js error setting abi: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
	if _, err = self.jsvm.Run("var method = '" + method + "';"); err != nil {
 | 
			
		||||
		return "", fmt.Errorf("natspec.js error setting method: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
func (self *NatSpec) SetABI(abi string) (err error) {
 | 
			
		||||
 | 
			
		||||
	_, err = self.jsvm.Run("var abi = " + abi + ";")
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *NatSpec) SetMethod(method string) (err error) {
 | 
			
		||||
 | 
			
		||||
	_, err = self.jsvm.Run("var method = '" + method + "';")
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *NatSpec) Parse() string {
 | 
			
		||||
	if _, err = self.jsvm.Run("var expression = \"" + expression + "\";"); err != nil {
 | 
			
		||||
		return "", fmt.Errorf("natspec.js error setting expression: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	self.jsvm.Run("var call = {method: method,abi: abi,transaction: transaction};")
 | 
			
		||||
	value, err := self.jsvm.Run("natspec.evaluateExpression(expression, call);")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err.Error()
 | 
			
		||||
		return "", fmt.Errorf("natspec.js error evaluating expression: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return value.String()
 | 
			
		||||
	evalError := "Natspec evaluation failed, wrong input params"
 | 
			
		||||
	if value.String() == evalError {
 | 
			
		||||
		return "", fmt.Errorf("natspec.js error evaluating expression: wrong input params in expression '%s'", expression)
 | 
			
		||||
	}
 | 
			
		||||
	if len(value.String()) == 0 {
 | 
			
		||||
		return "", fmt.Errorf("natspec.js error evaluating expression")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return value.String(), nil
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
 | 
			
		||||
package natspec
 | 
			
		||||
 | 
			
		||||
const natspecJS = `require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
 | 
			
		||||
 | 
			
		||||
},{}],2:[function(require,module,exports){
 | 
			
		||||
// shim for using process in browser
 | 
			
		||||
@@ -291,26 +293,26 @@ if (process.env.NODE_ENV !== 'build') {
 | 
			
		||||
    var BigNumber = require('bignumber.js'); // jshint ignore:line
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var ETH_UNITS = [ 
 | 
			
		||||
    'wei', 
 | 
			
		||||
    'Kwei', 
 | 
			
		||||
    'Mwei', 
 | 
			
		||||
    'Gwei', 
 | 
			
		||||
    'szabo', 
 | 
			
		||||
    'finney', 
 | 
			
		||||
    'ether', 
 | 
			
		||||
    'grand', 
 | 
			
		||||
    'Mether', 
 | 
			
		||||
    'Gether', 
 | 
			
		||||
    'Tether', 
 | 
			
		||||
    'Pether', 
 | 
			
		||||
    'Eether', 
 | 
			
		||||
    'Zether', 
 | 
			
		||||
    'Yether', 
 | 
			
		||||
    'Nether', 
 | 
			
		||||
    'Dether', 
 | 
			
		||||
    'Vether', 
 | 
			
		||||
    'Uether' 
 | 
			
		||||
var ETH_UNITS = [
 | 
			
		||||
    'wei',
 | 
			
		||||
    'Kwei',
 | 
			
		||||
    'Mwei',
 | 
			
		||||
    'Gwei',
 | 
			
		||||
    'szabo',
 | 
			
		||||
    'finney',
 | 
			
		||||
    'ether',
 | 
			
		||||
    'grand',
 | 
			
		||||
    'Mether',
 | 
			
		||||
    'Gether',
 | 
			
		||||
    'Tether',
 | 
			
		||||
    'Pether',
 | 
			
		||||
    'Eether',
 | 
			
		||||
    'Zether',
 | 
			
		||||
    'Yether',
 | 
			
		||||
    'Nether',
 | 
			
		||||
    'Dether',
 | 
			
		||||
    'Vether',
 | 
			
		||||
    'Uether'
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
@@ -375,7 +377,7 @@ var formatInputInt = function (value) {
 | 
			
		||||
        BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);
 | 
			
		||||
        value = value.round();
 | 
			
		||||
 | 
			
		||||
        if (value.lessThan(0)) 
 | 
			
		||||
        if (value.lessThan(0))
 | 
			
		||||
            value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1);
 | 
			
		||||
        value = value.toString(16);
 | 
			
		||||
    }
 | 
			
		||||
@@ -404,7 +406,7 @@ var formatInputBool = function (value) {
 | 
			
		||||
/// Values are multiplied by 2^m and encoded as integers
 | 
			
		||||
/// @returns byte representation of real
 | 
			
		||||
var formatInputReal = function (value) {
 | 
			
		||||
    return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128))); 
 | 
			
		||||
    return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -436,12 +438,12 @@ var formatOutputUInt = function (value) {
 | 
			
		||||
 | 
			
		||||
/// @returns input bytes formatted to real
 | 
			
		||||
var formatOutputReal = function (value) {
 | 
			
		||||
    return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128)); 
 | 
			
		||||
    return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// @returns input bytes formatted to ureal
 | 
			
		||||
var formatOutputUReal = function (value) {
 | 
			
		||||
    return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128)); 
 | 
			
		||||
    return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// @returns right-aligned input bytes formatted to hex
 | 
			
		||||
@@ -524,14 +526,14 @@ var namedType = function (name) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Setups input formatters for solidity types
 | 
			
		||||
/// @returns an array of input formatters 
 | 
			
		||||
/// @returns an array of input formatters
 | 
			
		||||
var inputTypes = function () {
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    return [
 | 
			
		||||
        { type: prefixedType('uint'), format: f.formatInputInt },
 | 
			
		||||
        { type: prefixedType('int'), format: f.formatInputInt },
 | 
			
		||||
        { type: prefixedType('hash'), format: f.formatInputInt },
 | 
			
		||||
        { type: prefixedType('string'), format: f.formatInputString }, 
 | 
			
		||||
        { type: prefixedType('string'), format: f.formatInputString },
 | 
			
		||||
        { type: prefixedType('real'), format: f.formatInputReal },
 | 
			
		||||
        { type: prefixedType('ureal'), format: f.formatInputReal },
 | 
			
		||||
        { type: namedType('address'), format: f.formatInputInt },
 | 
			
		||||
@@ -620,7 +622,7 @@ var toAscii = function(hex) {
 | 
			
		||||
 | 
			
		||||
    return str;
 | 
			
		||||
};
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
var toHex = function(str) {
 | 
			
		||||
    var hex = "";
 | 
			
		||||
    for(var i = 0; i < str.length; i++) {
 | 
			
		||||
@@ -642,7 +644,7 @@ var fromAscii = function(str, pad) {
 | 
			
		||||
 | 
			
		||||
/// @returns display name for function/event eg. multiply(uint256) -> multiply
 | 
			
		||||
var extractDisplayName = function (name) {
 | 
			
		||||
    var length = name.indexOf('('); 
 | 
			
		||||
    var length = name.indexOf('(');
 | 
			
		||||
    return length !== -1 ? name.substr(0, length) : name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -657,8 +659,8 @@ var extractTypeName = function (name) {
 | 
			
		||||
/// @returns abi array with filtered objects of type 'function'
 | 
			
		||||
var filterFunctions = function (json) {
 | 
			
		||||
    return json.filter(function (current) {
 | 
			
		||||
        return current.type === 'function'; 
 | 
			
		||||
    }); 
 | 
			
		||||
        return current.type === 'function';
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Filters all events form input abi
 | 
			
		||||
@@ -3404,7 +3406,7 @@ module.exports = {
 | 
			
		||||
 * @date 2015
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
var abi = require('./node_modules/ethereum.js/lib/abi.js'); 
 | 
			
		||||
var abi = require('./node_modules/ethereum.js/lib/abi.js');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This object should be used to evaluate natspec expression
 | 
			
		||||
@@ -3418,7 +3420,7 @@ var natspec = (function () {
 | 
			
		||||
            context[key] = obj[key];
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /// generate codes, which will be evaluated
 | 
			
		||||
    var generateCode = function (obj) {
 | 
			
		||||
        return Object.keys(obj).reduce(function (acc, key) {
 | 
			
		||||
@@ -3440,20 +3442,20 @@ var natspec = (function () {
 | 
			
		||||
    /// @returns hashmap with all contract's method input variables
 | 
			
		||||
    var getMethodInputParams = function (method, transaction) {
 | 
			
		||||
        // do it with output formatter (cause we have to decode)
 | 
			
		||||
        var params = abi.formatOutput(method.inputs, '0x' + transaction.params[0].data.slice(10)); 
 | 
			
		||||
        var params = abi.formatOutput(method.inputs, '0x' + transaction.params[0].data.slice(10));
 | 
			
		||||
 | 
			
		||||
        return method.inputs.reduce(function (acc, current, index) {
 | 
			
		||||
            acc[current.name] = params[index];
 | 
			
		||||
            return acc;
 | 
			
		||||
        }, {});
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /// Should be called to evaluate expression
 | 
			
		||||
    var mapExpressionsToEvaluate = function (expression, cb) {
 | 
			
		||||
        var evaluatedExpression = "";
 | 
			
		||||
 | 
			
		||||
        // match everything in `` quotes
 | 
			
		||||
        var pattern = /\`(?:\\.|[^`\\])*\`/gim
 | 
			
		||||
        // match everything in backtick
 | 
			
		||||
        var pattern = /\` + "`" + `(?:\\.|[^` + "`" + `\\])*\` + "`" + `/gim
 | 
			
		||||
        var match;
 | 
			
		||||
        var lastIndex = 0;
 | 
			
		||||
        while ((match = pattern.exec(expression)) !== null) {
 | 
			
		||||
@@ -3464,9 +3466,9 @@ var natspec = (function () {
 | 
			
		||||
            evaluatedExpression += evaluatedPart;
 | 
			
		||||
            lastIndex = pattern.lastIndex;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        evaluatedExpression += expression.slice(lastIndex);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
        return evaluatedExpression;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -3478,11 +3480,11 @@ var natspec = (function () {
 | 
			
		||||
    var evaluateExpression = function (expression, call) {
 | 
			
		||||
        //var self = this;
 | 
			
		||||
        var context = {};
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if (!!call) {
 | 
			
		||||
            try {
 | 
			
		||||
                var method = getMethodWithName(call.abi, call.method);
 | 
			
		||||
                var params = getMethodInputParams(method, call.transaction); 
 | 
			
		||||
                var params = getMethodInputParams(method, call.transaction);
 | 
			
		||||
                copyToContext(params, context);
 | 
			
		||||
            }
 | 
			
		||||
            catch (err) {
 | 
			
		||||
@@ -3498,7 +3500,7 @@ var natspec = (function () {
 | 
			
		||||
                return fn(context).toString();
 | 
			
		||||
            }
 | 
			
		||||
            catch (err) {
 | 
			
		||||
                return 'undefined'; 
 | 
			
		||||
                return 'undefined';
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -3511,7 +3513,8 @@ var natspec = (function () {
 | 
			
		||||
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
module.exports = natspec; 
 | 
			
		||||
module.exports = natspec;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
},{"./node_modules/ethereum.js/lib/abi.js":3}]},{},[]);
 | 
			
		||||
`
 | 
			
		||||
@@ -6,41 +6,48 @@ import (
 | 
			
		||||
 | 
			
		||||
func TestNotice(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	ns, err := NewNATSpec(`
 | 
			
		||||
	tx := `
 | 
			
		||||
	{
 | 
			
		||||
            "jsonrpc": "2.0",
 | 
			
		||||
            "method": "eth_call",
 | 
			
		||||
            "params": [{
 | 
			
		||||
                "to": "0x8521742d3f456bd237e312d6e30724960f72517a",
 | 
			
		||||
                "data": "0xc6888fa1000000000000000000000000000000000000000000000000000000000000007a"
 | 
			
		||||
            }],
 | 
			
		||||
            "id": 6
 | 
			
		||||
        }
 | 
			
		||||
	`)
 | 
			
		||||
    "jsonrpc": "2.0",
 | 
			
		||||
    "method": "eth_call",
 | 
			
		||||
    "params": [{
 | 
			
		||||
        "to": "0x8521742d3f456bd237e312d6e30724960f72517a",
 | 
			
		||||
        "data": "0xc6888fa1000000000000000000000000000000000000000000000000000000000000007a"
 | 
			
		||||
    }],
 | 
			
		||||
    "id": 6
 | 
			
		||||
  }
 | 
			
		||||
	`
 | 
			
		||||
 | 
			
		||||
	abi := `
 | 
			
		||||
	[{
 | 
			
		||||
    "name": "multiply",
 | 
			
		||||
    "constant": false,
 | 
			
		||||
    "type": "function",
 | 
			
		||||
    "inputs": [{
 | 
			
		||||
      "name": "a",
 | 
			
		||||
      "type": "uint256"
 | 
			
		||||
    }],
 | 
			
		||||
    "outputs": [{
 | 
			
		||||
      "name": "d",
 | 
			
		||||
      "type": "uint256"
 | 
			
		||||
    }]
 | 
			
		||||
  }]
 | 
			
		||||
	`
 | 
			
		||||
 | 
			
		||||
	desc := "Will multiply `a` by 7 and return `a * 7`."
 | 
			
		||||
 | 
			
		||||
	method := "multiply"
 | 
			
		||||
 | 
			
		||||
	ns, err := New()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("NewNATSpec error %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ns.SetABI(`
 | 
			
		||||
	[{
 | 
			
		||||
            "name": "multiply",
 | 
			
		||||
            "constant": false,
 | 
			
		||||
            "type": "function",
 | 
			
		||||
            "inputs": [{
 | 
			
		||||
                "name": "a",
 | 
			
		||||
                "type": "uint256"
 | 
			
		||||
            }],
 | 
			
		||||
            "outputs": [{
 | 
			
		||||
                "name": "d",
 | 
			
		||||
                "type": "uint256"
 | 
			
		||||
            }]
 | 
			
		||||
        }]
 | 
			
		||||
	`)
 | 
			
		||||
	ns.SetDescription("Will multiply `a` by 7 and return `a * 7`.")
 | 
			
		||||
	ns.SetMethod("multiply")
 | 
			
		||||
	notice, err := ns.Notice(tx, abi, method, desc)
 | 
			
		||||
 | 
			
		||||
	notice := ns.Parse()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("expected no error got %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expected := "Will multiply 122 by 7 and return 854."
 | 
			
		||||
	if notice != expected {
 | 
			
		||||
@@ -48,4 +55,43 @@ func TestNotice(t *testing.T) {
 | 
			
		||||
	} else {
 | 
			
		||||
		t.Logf("returned notice \"%v\"", notice)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	notice, err = ns.Notice(tx, abi, method, "Will multiply 122 by \"7\" and return 854.")
 | 
			
		||||
 | 
			
		||||
	expected = "natspec.js error setting expression: (anonymous): Line 1:41 Unexpected number"
 | 
			
		||||
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Errorf("expected error, got nothing (notice: '%v')", err, notice)
 | 
			
		||||
	} else {
 | 
			
		||||
		if err.Error() != expected {
 | 
			
		||||
			t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// https://github.com/ethereum/natspec.js/issues/1
 | 
			
		||||
	// badDesc := "Will multiply `e` by 7 and return `a * 7`."
 | 
			
		||||
	// notice, err = ns.Notice(tx, abi, method, badDesc)
 | 
			
		||||
 | 
			
		||||
	// expected = "natspec.js error evaluating expression: wrong input param in expression ''"
 | 
			
		||||
 | 
			
		||||
	// if err == nil {
 | 
			
		||||
	// 	t.Errorf("expected error, got nothing (notice: '%v')", notice)
 | 
			
		||||
	// } else {
 | 
			
		||||
	// 	if err.Error() != expected {
 | 
			
		||||
	// 		t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
 | 
			
		||||
	// 	}
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	notice, err = ns.Notice(tx, abi, "missing_method", desc)
 | 
			
		||||
 | 
			
		||||
	expected = "natspec.js error evaluating expression: wrong input params in expression 'Will multiply `a` by 7 and return `a * 7`.'"
 | 
			
		||||
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Errorf("expected error, got nothing (notice: '%v')", notice)
 | 
			
		||||
	} else {
 | 
			
		||||
		if err.Error() != expected {
 | 
			
		||||
			t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -80,13 +80,6 @@ func RunVmTest(p string, t *testing.T) {
 | 
			
		||||
	helper.CreateFileTests(t, p, &tests)
 | 
			
		||||
 | 
			
		||||
	for name, test := range tests {
 | 
			
		||||
		/*
 | 
			
		||||
			vm.Debug = true
 | 
			
		||||
			helper.Logger.SetLogLevel(4)
 | 
			
		||||
			if name != "refund_CallToSuicideTwice" {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		*/
 | 
			
		||||
		db, _ := ethdb.NewMemDatabase()
 | 
			
		||||
		statedb := state.New(nil, db)
 | 
			
		||||
		for addr, account := range test.Pre {
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ func (c *Context) GetRangeValue(x, size uint64) []byte {
 | 
			
		||||
	x = uint64(math.Min(float64(x), float64(len(c.Code))))
 | 
			
		||||
	y := uint64(math.Min(float64(x+size), float64(len(c.Code))))
 | 
			
		||||
 | 
			
		||||
	return ethutil.LeftPadBytes(c.Code[x:y], int(size))
 | 
			
		||||
	return ethutil.RightPadBytes(c.Code[x:y], int(size))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Context) GetCode(x, size uint64) []byte {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
package vm
 | 
			
		||||
 | 
			
		||||
import "github.com/ethereum/go-ethereum/state"
 | 
			
		||||
 | 
			
		||||
type Debugger interface {
 | 
			
		||||
	BreakHook(step int, op OpCode, mem *Memory, stack *Stack, object *state.StateObject) bool
 | 
			
		||||
	StepHook(step int, op OpCode, mem *Memory, stack *Stack, object *state.StateObject) bool
 | 
			
		||||
	BreakPoints() []int64
 | 
			
		||||
	SetCode(byteCode []byte)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								vm/gas.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								vm/gas.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
package vm
 | 
			
		||||
 | 
			
		||||
import "math/big"
 | 
			
		||||
 | 
			
		||||
type req struct {
 | 
			
		||||
	stack int
 | 
			
		||||
	gas   *big.Int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _baseCheck = map[OpCode]req{
 | 
			
		||||
	//       Req stack  Gas price
 | 
			
		||||
	ADD:          {2, GasFastestStep},
 | 
			
		||||
	LT:           {2, GasFastestStep},
 | 
			
		||||
	GT:           {2, GasFastestStep},
 | 
			
		||||
	SLT:          {2, GasFastestStep},
 | 
			
		||||
	SGT:          {2, GasFastestStep},
 | 
			
		||||
	EQ:           {2, GasFastestStep},
 | 
			
		||||
	ISZERO:       {1, GasFastestStep},
 | 
			
		||||
	SUB:          {2, GasFastestStep},
 | 
			
		||||
	AND:          {2, GasFastestStep},
 | 
			
		||||
	OR:           {2, GasFastestStep},
 | 
			
		||||
	XOR:          {2, GasFastestStep},
 | 
			
		||||
	NOT:          {1, GasFastestStep},
 | 
			
		||||
	BYTE:         {2, GasFastestStep},
 | 
			
		||||
	CALLDATALOAD: {1, GasFastestStep},
 | 
			
		||||
	CALLDATACOPY: {3, GasFastestStep},
 | 
			
		||||
	MLOAD:        {1, GasFastestStep},
 | 
			
		||||
	MSTORE:       {2, GasFastestStep},
 | 
			
		||||
	MSTORE8:      {2, GasFastestStep},
 | 
			
		||||
	CODECOPY:     {3, GasFastestStep},
 | 
			
		||||
	MUL:          {2, GasFastStep},
 | 
			
		||||
	DIV:          {2, GasFastStep},
 | 
			
		||||
	SDIV:         {2, GasFastStep},
 | 
			
		||||
	MOD:          {2, GasFastStep},
 | 
			
		||||
	SMOD:         {2, GasFastStep},
 | 
			
		||||
	SIGNEXTEND:   {2, GasFastStep},
 | 
			
		||||
	ADDMOD:       {3, GasMidStep},
 | 
			
		||||
	MULMOD:       {3, GasMidStep},
 | 
			
		||||
	JUMP:         {1, GasMidStep},
 | 
			
		||||
	JUMPI:        {2, GasSlowStep},
 | 
			
		||||
	EXP:          {2, GasSlowStep},
 | 
			
		||||
	ADDRESS:      {0, GasQuickStep},
 | 
			
		||||
	ORIGIN:       {0, GasQuickStep},
 | 
			
		||||
	CALLER:       {0, GasQuickStep},
 | 
			
		||||
	CALLVALUE:    {0, GasQuickStep},
 | 
			
		||||
	CODESIZE:     {0, GasQuickStep},
 | 
			
		||||
	GASPRICE:     {0, GasQuickStep},
 | 
			
		||||
	COINBASE:     {0, GasQuickStep},
 | 
			
		||||
	TIMESTAMP:    {0, GasQuickStep},
 | 
			
		||||
	NUMBER:       {0, GasQuickStep},
 | 
			
		||||
	CALLDATASIZE: {0, GasQuickStep},
 | 
			
		||||
	DIFFICULTY:   {0, GasQuickStep},
 | 
			
		||||
	GASLIMIT:     {0, GasQuickStep},
 | 
			
		||||
	POP:          {0, GasQuickStep},
 | 
			
		||||
	PC:           {0, GasQuickStep},
 | 
			
		||||
	MSIZE:        {0, GasQuickStep},
 | 
			
		||||
	GAS:          {0, GasQuickStep},
 | 
			
		||||
	BLOCKHASH:    {1, GasExtStep},
 | 
			
		||||
	BALANCE:      {0, GasExtStep},
 | 
			
		||||
	EXTCODESIZE:  {1, GasExtStep},
 | 
			
		||||
	EXTCODECOPY:  {4, GasExtStep},
 | 
			
		||||
	SLOAD:        {1, GasStorageGet},
 | 
			
		||||
	SSTORE:       {2, Zero},
 | 
			
		||||
	SHA3:         {1, GasSha3Base},
 | 
			
		||||
	CREATE:       {3, GasCreate},
 | 
			
		||||
	CALL:         {7, GasCall},
 | 
			
		||||
	CALLCODE:     {7, GasCall},
 | 
			
		||||
	JUMPDEST:     {0, GasJumpDest},
 | 
			
		||||
	SUICIDE:      {1, Zero},
 | 
			
		||||
	RETURN:       {2, Zero},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func baseCheck(op OpCode, stack *stack, gas *big.Int) {
 | 
			
		||||
	if r, ok := _baseCheck[op]; ok {
 | 
			
		||||
		stack.require(r.stack)
 | 
			
		||||
 | 
			
		||||
		gas.Add(gas, r.gas)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toWordSize(size *big.Int) *big.Int {
 | 
			
		||||
	tmp := new(big.Int)
 | 
			
		||||
	tmp.Add(size, u256(31))
 | 
			
		||||
	tmp.Div(tmp, u256(32))
 | 
			
		||||
	return tmp
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								vm/memory.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								vm/memory.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
package vm
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
type Memory struct {
 | 
			
		||||
	store []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMemory() *Memory {
 | 
			
		||||
	return &Memory{nil}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Set(offset, size uint64, value []byte) {
 | 
			
		||||
	if len(value) > 0 {
 | 
			
		||||
		totSize := offset + size
 | 
			
		||||
		lenSize := uint64(len(m.store) - 1)
 | 
			
		||||
		if totSize > lenSize {
 | 
			
		||||
			// Calculate the diff between the sizes
 | 
			
		||||
			diff := totSize - lenSize
 | 
			
		||||
			if diff > 0 {
 | 
			
		||||
				// Create a new empty slice and append it
 | 
			
		||||
				newSlice := make([]byte, diff-1)
 | 
			
		||||
				// Resize slice
 | 
			
		||||
				m.store = append(m.store, newSlice...)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		copy(m.store[offset:offset+size], value)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Resize(size uint64) {
 | 
			
		||||
	if uint64(m.Len()) < size {
 | 
			
		||||
		m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Memory) Get(offset, size int64) (cpy []byte) {
 | 
			
		||||
	if size == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(self.store) > int(offset) {
 | 
			
		||||
		cpy = make([]byte, size)
 | 
			
		||||
		copy(cpy, self.store[offset:offset+size])
 | 
			
		||||
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Len() int {
 | 
			
		||||
	return len(m.store)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Data() []byte {
 | 
			
		||||
	return m.store
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Print() {
 | 
			
		||||
	fmt.Printf("### mem %d bytes ###\n", len(m.store))
 | 
			
		||||
	if len(m.store) > 0 {
 | 
			
		||||
		addr := 0
 | 
			
		||||
		for i := 0; i+32 <= len(m.store); i += 32 {
 | 
			
		||||
			fmt.Printf("%03d: % x\n", addr, m.store[i:i+32])
 | 
			
		||||
			addr++
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Println("-- empty --")
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println("####################")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										188
									
								
								vm/stack.go
									
									
									
									
									
								
							
							
						
						
									
										188
									
								
								vm/stack.go
									
									
									
									
									
								
							@@ -5,98 +5,53 @@ import (
 | 
			
		||||
	"math/big"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type OpType int
 | 
			
		||||
func newStack() *stack {
 | 
			
		||||
	return &stack{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	tNorm = iota
 | 
			
		||||
	tData
 | 
			
		||||
	tExtro
 | 
			
		||||
	tCrypto
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TxCallback func(opType OpType) bool
 | 
			
		||||
 | 
			
		||||
// Simple push/pop stack mechanism
 | 
			
		||||
type Stack struct {
 | 
			
		||||
type stack struct {
 | 
			
		||||
	data []*big.Int
 | 
			
		||||
	ptr  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStack() *Stack {
 | 
			
		||||
	return &Stack{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Data() []*big.Int {
 | 
			
		||||
	return st.data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Len() int {
 | 
			
		||||
	return len(st.data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Pop() *big.Int {
 | 
			
		||||
	str := st.data[len(st.data)-1]
 | 
			
		||||
 | 
			
		||||
	copy(st.data[:len(st.data)-1], st.data[:len(st.data)-1])
 | 
			
		||||
	st.data = st.data[:len(st.data)-1]
 | 
			
		||||
 | 
			
		||||
	return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Popn() (*big.Int, *big.Int) {
 | 
			
		||||
	ints := st.data[len(st.data)-2:]
 | 
			
		||||
 | 
			
		||||
	copy(st.data[:len(st.data)-2], st.data[:len(st.data)-2])
 | 
			
		||||
	st.data = st.data[:len(st.data)-2]
 | 
			
		||||
 | 
			
		||||
	return ints[0], ints[1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Peek() *big.Int {
 | 
			
		||||
	str := st.data[len(st.data)-1]
 | 
			
		||||
 | 
			
		||||
	return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Peekn() (*big.Int, *big.Int) {
 | 
			
		||||
	ints := st.data[len(st.data)-2:]
 | 
			
		||||
 | 
			
		||||
	return ints[0], ints[1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Swapn(n int) (*big.Int, *big.Int) {
 | 
			
		||||
	st.data[len(st.data)-n], st.data[len(st.data)-1] = st.data[len(st.data)-1], st.data[len(st.data)-n]
 | 
			
		||||
 | 
			
		||||
	return st.data[len(st.data)-n], st.data[len(st.data)-1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Dupn(n int) *big.Int {
 | 
			
		||||
	st.Push(st.data[len(st.data)-n])
 | 
			
		||||
 | 
			
		||||
	return st.Peek()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Push(d *big.Int) {
 | 
			
		||||
	st.data = append(st.data, new(big.Int).Set(d))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Get(amount *big.Int) []*big.Int {
 | 
			
		||||
	// offset + size <= len(data)
 | 
			
		||||
	length := big.NewInt(int64(len(st.data)))
 | 
			
		||||
	if amount.Cmp(length) <= 0 {
 | 
			
		||||
		start := new(big.Int).Sub(length, amount)
 | 
			
		||||
		return st.data[start.Int64():length.Int64()]
 | 
			
		||||
func (st *stack) push(d *big.Int) {
 | 
			
		||||
	if len(st.data) > st.ptr {
 | 
			
		||||
		st.data[st.ptr] = d
 | 
			
		||||
	} else {
 | 
			
		||||
		st.data = append(st.data, d)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
	st.ptr++
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) require(n int) {
 | 
			
		||||
	if st.Len() < n {
 | 
			
		||||
		panic(fmt.Sprintf("stack underflow (%d <=> %d)", st.Len(), n))
 | 
			
		||||
func (st *stack) pop() (ret *big.Int) {
 | 
			
		||||
	st.ptr--
 | 
			
		||||
	ret = st.data[st.ptr]
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *stack) len() int {
 | 
			
		||||
	return st.ptr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *stack) swap(n int) {
 | 
			
		||||
	st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *stack) dup(n int) {
 | 
			
		||||
	st.push(st.data[st.len()-n])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *stack) peek() *big.Int {
 | 
			
		||||
	return st.data[st.len()-1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *stack) require(n int) {
 | 
			
		||||
	if st.len() < n {
 | 
			
		||||
		panic(fmt.Sprintf("stack underflow (%d <=> %d)", len(st.data), n))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (st *Stack) Print() {
 | 
			
		||||
func (st *stack) Print() {
 | 
			
		||||
	fmt.Println("### stack ###")
 | 
			
		||||
	if len(st.data) > 0 {
 | 
			
		||||
		for i, val := range st.data {
 | 
			
		||||
@@ -107,72 +62,3 @@ func (st *Stack) Print() {
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println("#############")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Memory struct {
 | 
			
		||||
	store []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMemory() *Memory {
 | 
			
		||||
	return &Memory{nil}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Set(offset, size uint64, value []byte) {
 | 
			
		||||
	if len(value) > 0 {
 | 
			
		||||
		totSize := offset + size
 | 
			
		||||
		lenSize := uint64(len(m.store) - 1)
 | 
			
		||||
		if totSize > lenSize {
 | 
			
		||||
			// Calculate the diff between the sizes
 | 
			
		||||
			diff := totSize - lenSize
 | 
			
		||||
			if diff > 0 {
 | 
			
		||||
				// Create a new empty slice and append it
 | 
			
		||||
				newSlice := make([]byte, diff-1)
 | 
			
		||||
				// Resize slice
 | 
			
		||||
				m.store = append(m.store, newSlice...)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		copy(m.store[offset:offset+size], value)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Resize(size uint64) {
 | 
			
		||||
	if uint64(m.Len()) < size {
 | 
			
		||||
		m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Memory) Get(offset, size int64) (cpy []byte) {
 | 
			
		||||
	if size == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(self.store) > int(offset) {
 | 
			
		||||
		cpy = make([]byte, size)
 | 
			
		||||
		copy(cpy, self.store[offset:offset+size])
 | 
			
		||||
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Len() int {
 | 
			
		||||
	return len(m.store)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Data() []byte {
 | 
			
		||||
	return m.store
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Memory) Print() {
 | 
			
		||||
	fmt.Printf("### mem %d bytes ###\n", len(m.store))
 | 
			
		||||
	if len(m.store) > 0 {
 | 
			
		||||
		addr := 0
 | 
			
		||||
		for i := 0; i+32 <= len(m.store); i += 32 {
 | 
			
		||||
			fmt.Printf("%03d: % x\n", addr, m.store[i:i+32])
 | 
			
		||||
			addr++
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Println("-- empty --")
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println("####################")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										451
									
								
								vm/vm.go
									
									
									
									
									
								
							
							
						
						
									
										451
									
								
								vm/vm.go
									
									
									
									
									
								
							@@ -19,8 +19,6 @@ type Vm struct {
 | 
			
		||||
	// For logging
 | 
			
		||||
	debug bool
 | 
			
		||||
 | 
			
		||||
	Dbg Debugger
 | 
			
		||||
 | 
			
		||||
	BreakPoints []int64
 | 
			
		||||
	Stepping    bool
 | 
			
		||||
	Fn          string
 | 
			
		||||
@@ -66,10 +64,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
		destinations        = analyseJumpDests(context.Code)
 | 
			
		||||
		mem                 = NewMemory()
 | 
			
		||||
		stack               = NewStack()
 | 
			
		||||
		stack               = newStack()
 | 
			
		||||
		pc           uint64 = 0
 | 
			
		||||
		step                = 0
 | 
			
		||||
		prevStep            = 0
 | 
			
		||||
		statedb             = self.env.State()
 | 
			
		||||
 | 
			
		||||
		jump = func(from uint64, to *big.Int) {
 | 
			
		||||
@@ -93,7 +90,6 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		prevStep = step
 | 
			
		||||
		// The base for all big integer arithmetic
 | 
			
		||||
		base := new(big.Int)
 | 
			
		||||
 | 
			
		||||
@@ -101,11 +97,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
		// Get the memory location of pc
 | 
			
		||||
		op = context.GetOp(pc)
 | 
			
		||||
 | 
			
		||||
		self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.Len())
 | 
			
		||||
		if self.Dbg != nil {
 | 
			
		||||
			//self.Dbg.Step(self, op, mem, stack, context)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.len())
 | 
			
		||||
		newMemSize, gas := self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
 | 
			
		||||
 | 
			
		||||
		self.Printf("(g) %-3v (%v)", gas, context.Gas)
 | 
			
		||||
@@ -125,40 +117,40 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
		switch op {
 | 
			
		||||
		// 0x20 range
 | 
			
		||||
		case ADD:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v + %v", y, x)
 | 
			
		||||
 | 
			
		||||
			base.Add(y, x)
 | 
			
		||||
			base.Add(x, y)
 | 
			
		||||
 | 
			
		||||
			U256(base)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
			// Pop result back on the stack
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			// pop result back on the stack
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case SUB:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v - %v", y, x)
 | 
			
		||||
 | 
			
		||||
			base.Sub(y, x)
 | 
			
		||||
			base.Sub(x, y)
 | 
			
		||||
 | 
			
		||||
			U256(base)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
			// Pop result back on the stack
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			// pop result back on the stack
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case MUL:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v * %v", y, x)
 | 
			
		||||
 | 
			
		||||
			base.Mul(y, x)
 | 
			
		||||
			base.Mul(x, y)
 | 
			
		||||
 | 
			
		||||
			U256(base)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
			// Pop result back on the stack
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			// pop result back on the stack
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case DIV:
 | 
			
		||||
			x, y := stack.Pop(), stack.Pop()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v / %v", x, y)
 | 
			
		||||
 | 
			
		||||
			if y.Cmp(ethutil.Big0) != 0 {
 | 
			
		||||
@@ -168,10 +160,10 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
			U256(base)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
			// Pop result back on the stack
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			// pop result back on the stack
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case SDIV:
 | 
			
		||||
			x, y := S256(stack.Pop()), S256(stack.Pop())
 | 
			
		||||
			x, y := S256(stack.pop()), S256(stack.pop())
 | 
			
		||||
 | 
			
		||||
			self.Printf(" %v / %v", x, y)
 | 
			
		||||
 | 
			
		||||
@@ -191,9 +183,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case MOD:
 | 
			
		||||
			x, y := stack.Pop(), stack.Pop()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
 | 
			
		||||
			self.Printf(" %v %% %v", x, y)
 | 
			
		||||
 | 
			
		||||
@@ -206,9 +198,9 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
			U256(base)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case SMOD:
 | 
			
		||||
			x, y := S256(stack.Pop()), S256(stack.Pop())
 | 
			
		||||
			x, y := S256(stack.pop()), S256(stack.pop())
 | 
			
		||||
 | 
			
		||||
			self.Printf(" %v %% %v", x, y)
 | 
			
		||||
 | 
			
		||||
@@ -228,25 +220,25 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
 | 
			
		||||
		case EXP:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
 | 
			
		||||
			self.Printf(" %v ** %v", y, x)
 | 
			
		||||
			self.Printf(" %v ** %v", x, y)
 | 
			
		||||
 | 
			
		||||
			base.Exp(y, x, Pow256)
 | 
			
		||||
			base.Exp(x, y, Pow256)
 | 
			
		||||
 | 
			
		||||
			U256(base)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" = %v", base)
 | 
			
		||||
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case SIGNEXTEND:
 | 
			
		||||
			back := stack.Pop().Uint64()
 | 
			
		||||
			back := stack.pop().Uint64()
 | 
			
		||||
			if back < 31 {
 | 
			
		||||
				bit := uint(back*8 + 7)
 | 
			
		||||
				num := stack.Pop()
 | 
			
		||||
				num := stack.pop()
 | 
			
		||||
				mask := new(big.Int).Lsh(ethutil.Big1, bit)
 | 
			
		||||
				mask.Sub(mask, ethutil.Big1)
 | 
			
		||||
				if ethutil.BitTest(num, int(bit)) {
 | 
			
		||||
@@ -259,91 +251,91 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
				self.Printf(" = %v", num)
 | 
			
		||||
 | 
			
		||||
				stack.Push(num)
 | 
			
		||||
				stack.push(num)
 | 
			
		||||
			}
 | 
			
		||||
		case NOT:
 | 
			
		||||
			base.Sub(Pow256, stack.Pop()).Sub(base, ethutil.Big1)
 | 
			
		||||
			base.Sub(Pow256, stack.pop()).Sub(base, ethutil.Big1)
 | 
			
		||||
 | 
			
		||||
			// Not needed
 | 
			
		||||
			base = U256(base)
 | 
			
		||||
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case LT:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			self.Printf(" %v < %v", y, x)
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v < %v", x, y)
 | 
			
		||||
			// x < y
 | 
			
		||||
			if y.Cmp(x) < 0 {
 | 
			
		||||
				stack.Push(ethutil.BigTrue)
 | 
			
		||||
			if x.Cmp(y) < 0 {
 | 
			
		||||
				stack.push(ethutil.BigTrue)
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
			}
 | 
			
		||||
		case GT:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			self.Printf(" %v > %v", y, x)
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v > %v", x, y)
 | 
			
		||||
 | 
			
		||||
			// x > y
 | 
			
		||||
			if y.Cmp(x) > 0 {
 | 
			
		||||
				stack.Push(ethutil.BigTrue)
 | 
			
		||||
			if x.Cmp(y) > 0 {
 | 
			
		||||
				stack.push(ethutil.BigTrue)
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case SLT:
 | 
			
		||||
			y, x := S256(stack.Pop()), S256(stack.Pop())
 | 
			
		||||
			self.Printf(" %v < %v", y, x)
 | 
			
		||||
			x, y := S256(stack.pop()), S256(stack.pop())
 | 
			
		||||
			self.Printf(" %v < %v", x, y)
 | 
			
		||||
			// x < y
 | 
			
		||||
			if y.Cmp(S256(x)) < 0 {
 | 
			
		||||
				stack.Push(ethutil.BigTrue)
 | 
			
		||||
			if x.Cmp(S256(y)) < 0 {
 | 
			
		||||
				stack.push(ethutil.BigTrue)
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
			}
 | 
			
		||||
		case SGT:
 | 
			
		||||
			y, x := S256(stack.Pop()), S256(stack.Pop())
 | 
			
		||||
			self.Printf(" %v > %v", y, x)
 | 
			
		||||
			x, y := S256(stack.pop()), S256(stack.pop())
 | 
			
		||||
			self.Printf(" %v > %v", x, y)
 | 
			
		||||
 | 
			
		||||
			// x > y
 | 
			
		||||
			if y.Cmp(x) > 0 {
 | 
			
		||||
				stack.Push(ethutil.BigTrue)
 | 
			
		||||
			if x.Cmp(y) > 0 {
 | 
			
		||||
				stack.push(ethutil.BigTrue)
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case EQ:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v == %v", y, x)
 | 
			
		||||
 | 
			
		||||
			// x == y
 | 
			
		||||
			if x.Cmp(y) == 0 {
 | 
			
		||||
				stack.Push(ethutil.BigTrue)
 | 
			
		||||
				stack.push(ethutil.BigTrue)
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
			}
 | 
			
		||||
		case ISZERO:
 | 
			
		||||
			x := stack.Pop()
 | 
			
		||||
			x := stack.pop()
 | 
			
		||||
			if x.Cmp(ethutil.BigFalse) > 0 {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.BigTrue)
 | 
			
		||||
				stack.push(ethutil.BigTrue)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// 0x10 range
 | 
			
		||||
		case AND:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v & %v", y, x)
 | 
			
		||||
 | 
			
		||||
			stack.Push(base.And(y, x))
 | 
			
		||||
			stack.push(base.And(x, y))
 | 
			
		||||
		case OR:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			self.Printf(" %v | %v", y, x)
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v | %v", x, y)
 | 
			
		||||
 | 
			
		||||
			stack.Push(base.Or(y, x))
 | 
			
		||||
			stack.push(base.Or(x, y))
 | 
			
		||||
		case XOR:
 | 
			
		||||
			x, y := stack.Popn()
 | 
			
		||||
			self.Printf(" %v ^ %v", y, x)
 | 
			
		||||
			x, y := stack.pop(), stack.pop()
 | 
			
		||||
			self.Printf(" %v ^ %v", x, y)
 | 
			
		||||
 | 
			
		||||
			stack.Push(base.Xor(y, x))
 | 
			
		||||
			stack.push(base.Xor(x, y))
 | 
			
		||||
		case BYTE:
 | 
			
		||||
			val, th := stack.Popn()
 | 
			
		||||
			th, val := stack.pop(), stack.pop()
 | 
			
		||||
 | 
			
		||||
			if th.Cmp(big.NewInt(32)) < 0 {
 | 
			
		||||
				byt := big.NewInt(int64(ethutil.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
 | 
			
		||||
@@ -355,12 +347,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", base.Bytes())
 | 
			
		||||
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case ADDMOD:
 | 
			
		||||
 | 
			
		||||
			x := stack.Pop()
 | 
			
		||||
			y := stack.Pop()
 | 
			
		||||
			z := stack.Pop()
 | 
			
		||||
			x := stack.pop()
 | 
			
		||||
			y := stack.pop()
 | 
			
		||||
			z := stack.pop()
 | 
			
		||||
 | 
			
		||||
			add := new(big.Int).Add(x, y)
 | 
			
		||||
			if len(z.Bytes()) > 0 { // NOT 0x0
 | 
			
		||||
@@ -371,12 +363,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
			self.Printf(" %v + %v %% %v = %v", x, y, z, base)
 | 
			
		||||
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
		case MULMOD:
 | 
			
		||||
 | 
			
		||||
			x := stack.Pop()
 | 
			
		||||
			y := stack.Pop()
 | 
			
		||||
			z := stack.Pop()
 | 
			
		||||
			x := stack.pop()
 | 
			
		||||
			y := stack.pop()
 | 
			
		||||
			z := stack.pop()
 | 
			
		||||
 | 
			
		||||
			mul := new(big.Int).Mul(x, y)
 | 
			
		||||
			if len(z.Bytes()) > 0 { // NOT 0x0
 | 
			
		||||
@@ -387,24 +379,24 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
			self.Printf(" %v + %v %% %v = %v", x, y, z, base)
 | 
			
		||||
 | 
			
		||||
			stack.Push(base)
 | 
			
		||||
			stack.push(base)
 | 
			
		||||
 | 
			
		||||
			// 0x20 range
 | 
			
		||||
		case SHA3:
 | 
			
		||||
			size, offset := stack.Popn()
 | 
			
		||||
			size, offset := stack.pop(), stack.pop()
 | 
			
		||||
			data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64()))
 | 
			
		||||
 | 
			
		||||
			stack.Push(ethutil.BigD(data))
 | 
			
		||||
			stack.push(ethutil.BigD(data))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => (%v) %x", size, data)
 | 
			
		||||
			// 0x30 range
 | 
			
		||||
		case ADDRESS:
 | 
			
		||||
			stack.Push(ethutil.BigD(context.Address()))
 | 
			
		||||
			stack.push(ethutil.BigD(context.Address()))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %x", context.Address())
 | 
			
		||||
		case BALANCE:
 | 
			
		||||
 | 
			
		||||
			addr := stack.Pop().Bytes()
 | 
			
		||||
			addr := stack.pop().Bytes()
 | 
			
		||||
			var balance *big.Int
 | 
			
		||||
			if statedb.GetStateObject(addr) != nil {
 | 
			
		||||
				balance = statedb.GetBalance(addr)
 | 
			
		||||
@@ -412,27 +404,27 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
				balance = base
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			stack.Push(balance)
 | 
			
		||||
			stack.push(balance)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %v (%x)", balance, addr)
 | 
			
		||||
		case ORIGIN:
 | 
			
		||||
			origin := self.env.Origin()
 | 
			
		||||
 | 
			
		||||
			stack.Push(ethutil.BigD(origin))
 | 
			
		||||
			stack.push(ethutil.BigD(origin))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %x", origin)
 | 
			
		||||
		case CALLER:
 | 
			
		||||
			caller := context.caller.Address()
 | 
			
		||||
			stack.Push(ethutil.BigD(caller))
 | 
			
		||||
			stack.push(ethutil.BigD(caller))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %x", caller)
 | 
			
		||||
		case CALLVALUE:
 | 
			
		||||
			stack.Push(value)
 | 
			
		||||
			stack.push(value)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %v", value)
 | 
			
		||||
		case CALLDATALOAD:
 | 
			
		||||
			var (
 | 
			
		||||
				offset  = stack.Pop()
 | 
			
		||||
				offset  = stack.pop()
 | 
			
		||||
				data    = make([]byte, 32)
 | 
			
		||||
				lenData = big.NewInt(int64(len(callData)))
 | 
			
		||||
			)
 | 
			
		||||
@@ -446,18 +438,18 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", data)
 | 
			
		||||
 | 
			
		||||
			stack.Push(ethutil.BigD(data))
 | 
			
		||||
			stack.push(ethutil.BigD(data))
 | 
			
		||||
		case CALLDATASIZE:
 | 
			
		||||
			l := int64(len(callData))
 | 
			
		||||
			stack.Push(big.NewInt(l))
 | 
			
		||||
			stack.push(big.NewInt(l))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %d", l)
 | 
			
		||||
		case CALLDATACOPY:
 | 
			
		||||
			var (
 | 
			
		||||
				size = uint64(len(callData))
 | 
			
		||||
				mOff = stack.Pop().Uint64()
 | 
			
		||||
				cOff = stack.Pop().Uint64()
 | 
			
		||||
				l    = stack.Pop().Uint64()
 | 
			
		||||
				mOff = stack.pop().Uint64()
 | 
			
		||||
				cOff = stack.pop().Uint64()
 | 
			
		||||
				l    = stack.pop().Uint64()
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
			if cOff > size {
 | 
			
		||||
@@ -475,7 +467,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
		case CODESIZE, EXTCODESIZE:
 | 
			
		||||
			var code []byte
 | 
			
		||||
			if op == EXTCODESIZE {
 | 
			
		||||
				addr := stack.Pop().Bytes()
 | 
			
		||||
				addr := stack.pop().Bytes()
 | 
			
		||||
 | 
			
		||||
				code = statedb.GetCode(addr)
 | 
			
		||||
			} else {
 | 
			
		||||
@@ -483,21 +475,21 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			l := big.NewInt(int64(len(code)))
 | 
			
		||||
			stack.Push(l)
 | 
			
		||||
			stack.push(l)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %d", l)
 | 
			
		||||
		case CODECOPY, EXTCODECOPY:
 | 
			
		||||
			var code []byte
 | 
			
		||||
			if op == EXTCODECOPY {
 | 
			
		||||
				code = statedb.GetCode(stack.Pop().Bytes())
 | 
			
		||||
				code = statedb.GetCode(stack.pop().Bytes())
 | 
			
		||||
			} else {
 | 
			
		||||
				code = context.Code
 | 
			
		||||
			}
 | 
			
		||||
			context := NewContext(nil, nil, code, ethutil.Big0, ethutil.Big0)
 | 
			
		||||
			var (
 | 
			
		||||
				mOff = stack.Pop().Uint64()
 | 
			
		||||
				cOff = stack.Pop().Uint64()
 | 
			
		||||
				l    = stack.Pop().Uint64()
 | 
			
		||||
				mOff = stack.pop().Uint64()
 | 
			
		||||
				cOff = stack.pop().Uint64()
 | 
			
		||||
				l    = stack.pop().Uint64()
 | 
			
		||||
			)
 | 
			
		||||
			codeCopy := context.GetCode(cOff, l)
 | 
			
		||||
 | 
			
		||||
@@ -505,80 +497,80 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, codeCopy)
 | 
			
		||||
		case GASPRICE:
 | 
			
		||||
			stack.Push(context.Price)
 | 
			
		||||
			stack.push(context.Price)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %x", context.Price)
 | 
			
		||||
 | 
			
		||||
			// 0x40 range
 | 
			
		||||
		case BLOCKHASH:
 | 
			
		||||
			num := stack.Pop()
 | 
			
		||||
			num := stack.pop()
 | 
			
		||||
 | 
			
		||||
			n := new(big.Int).Sub(self.env.BlockNumber(), ethutil.Big257)
 | 
			
		||||
			if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
 | 
			
		||||
				stack.Push(ethutil.BigD(self.env.GetHash(num.Uint64())))
 | 
			
		||||
				stack.push(ethutil.BigD(self.env.GetHash(num.Uint64())))
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.Big0)
 | 
			
		||||
				stack.push(ethutil.Big0)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", stack.Peek().Bytes())
 | 
			
		||||
			self.Printf(" => 0x%x", stack.peek().Bytes())
 | 
			
		||||
		case COINBASE:
 | 
			
		||||
			coinbase := self.env.Coinbase()
 | 
			
		||||
 | 
			
		||||
			stack.Push(ethutil.BigD(coinbase))
 | 
			
		||||
			stack.push(ethutil.BigD(coinbase))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", coinbase)
 | 
			
		||||
		case TIMESTAMP:
 | 
			
		||||
			time := self.env.Time()
 | 
			
		||||
 | 
			
		||||
			stack.Push(big.NewInt(time))
 | 
			
		||||
			stack.push(big.NewInt(time))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", time)
 | 
			
		||||
		case NUMBER:
 | 
			
		||||
			number := self.env.BlockNumber()
 | 
			
		||||
 | 
			
		||||
			stack.Push(U256(number))
 | 
			
		||||
			stack.push(U256(number))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", number.Bytes())
 | 
			
		||||
		case DIFFICULTY:
 | 
			
		||||
			difficulty := self.env.Difficulty()
 | 
			
		||||
 | 
			
		||||
			stack.Push(difficulty)
 | 
			
		||||
			stack.push(difficulty)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", difficulty.Bytes())
 | 
			
		||||
		case GASLIMIT:
 | 
			
		||||
			self.Printf(" => %v", self.env.GasLimit())
 | 
			
		||||
 | 
			
		||||
			stack.Push(self.env.GasLimit())
 | 
			
		||||
			stack.push(self.env.GasLimit())
 | 
			
		||||
 | 
			
		||||
			// 0x50 range
 | 
			
		||||
		case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
 | 
			
		||||
			a := uint64(op - PUSH1 + 1)
 | 
			
		||||
			byts := context.GetRangeValue(pc+1, a)
 | 
			
		||||
			// Push value to stack
 | 
			
		||||
			stack.Push(ethutil.BigD(byts))
 | 
			
		||||
			// push value to stack
 | 
			
		||||
			stack.push(ethutil.BigD(byts))
 | 
			
		||||
			pc += a
 | 
			
		||||
 | 
			
		||||
			step += int(op) - int(PUSH1) + 1
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", byts)
 | 
			
		||||
		case POP:
 | 
			
		||||
			stack.Pop()
 | 
			
		||||
			stack.pop()
 | 
			
		||||
		case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
 | 
			
		||||
			n := int(op - DUP1 + 1)
 | 
			
		||||
			stack.Dupn(n)
 | 
			
		||||
			stack.dup(n)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => [%d] 0x%x", n, stack.Peek().Bytes())
 | 
			
		||||
			self.Printf(" => [%d] 0x%x", n, stack.peek().Bytes())
 | 
			
		||||
		case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
 | 
			
		||||
			n := int(op - SWAP1 + 2)
 | 
			
		||||
			x, y := stack.Swapn(n)
 | 
			
		||||
			stack.swap(n)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes())
 | 
			
		||||
			self.Printf(" => [%d]", n)
 | 
			
		||||
		case LOG0, LOG1, LOG2, LOG3, LOG4:
 | 
			
		||||
			n := int(op - LOG0)
 | 
			
		||||
			topics := make([][]byte, n)
 | 
			
		||||
			mSize, mStart := stack.Popn()
 | 
			
		||||
			mStart, mSize := stack.pop(), stack.pop()
 | 
			
		||||
			for i := 0; i < n; i++ {
 | 
			
		||||
				topics[i] = ethutil.LeftPadBytes(stack.Pop().Bytes(), 32)
 | 
			
		||||
				topics[i] = ethutil.LeftPadBytes(stack.pop().Bytes(), 32)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			data := mem.Get(mStart.Int64(), mSize.Int64())
 | 
			
		||||
@@ -587,41 +579,40 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %v", log)
 | 
			
		||||
		case MLOAD:
 | 
			
		||||
			offset := stack.Pop()
 | 
			
		||||
			offset := stack.pop()
 | 
			
		||||
			val := ethutil.BigD(mem.Get(offset.Int64(), 32))
 | 
			
		||||
			stack.Push(val)
 | 
			
		||||
			stack.push(val)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", val.Bytes())
 | 
			
		||||
		case MSTORE: // Store the value at stack top-1 in to memory at location stack top
 | 
			
		||||
			// Pop value of the stack
 | 
			
		||||
			val, mStart := stack.Popn()
 | 
			
		||||
			// pop value of the stack
 | 
			
		||||
			mStart, val := stack.pop(), stack.pop()
 | 
			
		||||
			mem.Set(mStart.Uint64(), 32, ethutil.BigToBytes(val, 256))
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => 0x%x", val)
 | 
			
		||||
		case MSTORE8:
 | 
			
		||||
			off := stack.Pop()
 | 
			
		||||
			val := stack.Pop()
 | 
			
		||||
			off, val := stack.pop(), stack.pop()
 | 
			
		||||
 | 
			
		||||
			mem.store[off.Int64()] = byte(val.Int64() & 0xff)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => [%v] 0x%x", off, val)
 | 
			
		||||
		case SLOAD:
 | 
			
		||||
			loc := stack.Pop()
 | 
			
		||||
			loc := stack.pop()
 | 
			
		||||
			val := ethutil.BigD(statedb.GetState(context.Address(), loc.Bytes()))
 | 
			
		||||
			stack.Push(val)
 | 
			
		||||
			stack.push(val)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
 | 
			
		||||
		case SSTORE:
 | 
			
		||||
			val, loc := stack.Popn()
 | 
			
		||||
			loc, val := stack.pop(), stack.pop()
 | 
			
		||||
			statedb.SetState(context.Address(), loc.Bytes(), val)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
 | 
			
		||||
		case JUMP:
 | 
			
		||||
			jump(pc, stack.Pop())
 | 
			
		||||
			jump(pc, stack.pop())
 | 
			
		||||
 | 
			
		||||
			continue
 | 
			
		||||
		case JUMPI:
 | 
			
		||||
			cond, pos := stack.Popn()
 | 
			
		||||
			pos, cond := stack.pop(), stack.pop()
 | 
			
		||||
 | 
			
		||||
			if cond.Cmp(ethutil.BigTrue) >= 0 {
 | 
			
		||||
				jump(pc, pos)
 | 
			
		||||
@@ -633,19 +624,19 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
 | 
			
		||||
		case JUMPDEST:
 | 
			
		||||
		case PC:
 | 
			
		||||
			stack.Push(big.NewInt(int64(pc)))
 | 
			
		||||
			stack.push(big.NewInt(int64(pc)))
 | 
			
		||||
		case MSIZE:
 | 
			
		||||
			stack.Push(big.NewInt(int64(mem.Len())))
 | 
			
		||||
			stack.push(big.NewInt(int64(mem.Len())))
 | 
			
		||||
		case GAS:
 | 
			
		||||
			stack.Push(context.Gas)
 | 
			
		||||
			stack.push(context.Gas)
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => %x", context.Gas)
 | 
			
		||||
			// 0x60 range
 | 
			
		||||
		case CREATE:
 | 
			
		||||
 | 
			
		||||
			var (
 | 
			
		||||
				value        = stack.Pop()
 | 
			
		||||
				size, offset = stack.Popn()
 | 
			
		||||
				value        = stack.pop()
 | 
			
		||||
				offset, size = stack.pop(), stack.pop()
 | 
			
		||||
				input        = mem.Get(offset.Int64(), size.Int64())
 | 
			
		||||
				gas          = new(big.Int).Set(context.Gas)
 | 
			
		||||
				addr         []byte
 | 
			
		||||
@@ -655,7 +646,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
			context.UseGas(context.Gas)
 | 
			
		||||
			ret, suberr, ref := self.env.Create(context, nil, input, gas, price, value)
 | 
			
		||||
			if suberr != nil {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
 | 
			
		||||
				self.Printf(" (*) 0x0 %v", suberr)
 | 
			
		||||
			} else {
 | 
			
		||||
@@ -668,23 +659,19 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
				}
 | 
			
		||||
				addr = ref.Address()
 | 
			
		||||
 | 
			
		||||
				stack.Push(ethutil.BigD(addr))
 | 
			
		||||
				stack.push(ethutil.BigD(addr))
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Debug hook
 | 
			
		||||
			if self.Dbg != nil {
 | 
			
		||||
				self.Dbg.SetCode(context.Code)
 | 
			
		||||
			}
 | 
			
		||||
		case CALL, CALLCODE:
 | 
			
		||||
			gas := stack.Pop()
 | 
			
		||||
			// Pop gas and value of the stack.
 | 
			
		||||
			value, addr := stack.Popn()
 | 
			
		||||
			gas := stack.pop()
 | 
			
		||||
			// pop gas and value of the stack.
 | 
			
		||||
			addr, value := stack.pop(), stack.pop()
 | 
			
		||||
			value = U256(value)
 | 
			
		||||
			// Pop input size and offset
 | 
			
		||||
			inSize, inOffset := stack.Popn()
 | 
			
		||||
			// Pop return size and offset
 | 
			
		||||
			retSize, retOffset := stack.Popn()
 | 
			
		||||
			// pop input size and offset
 | 
			
		||||
			inOffset, inSize := stack.pop(), stack.pop()
 | 
			
		||||
			// pop return size and offset
 | 
			
		||||
			retOffset, retSize := stack.pop(), stack.pop()
 | 
			
		||||
 | 
			
		||||
			address := ethutil.Address(addr.Bytes())
 | 
			
		||||
			self.Printf(" => %x", address).Endl()
 | 
			
		||||
@@ -707,30 +694,24 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				stack.Push(ethutil.BigFalse)
 | 
			
		||||
				stack.push(ethutil.BigFalse)
 | 
			
		||||
 | 
			
		||||
				vmlogger.Debugln(err)
 | 
			
		||||
			} else {
 | 
			
		||||
				stack.Push(ethutil.BigTrue)
 | 
			
		||||
				stack.push(ethutil.BigTrue)
 | 
			
		||||
 | 
			
		||||
				mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
 | 
			
		||||
			}
 | 
			
		||||
			self.Printf("resume %x (%v)", context.Address(), context.Gas)
 | 
			
		||||
 | 
			
		||||
			// Debug hook
 | 
			
		||||
			if self.Dbg != nil {
 | 
			
		||||
				self.Dbg.SetCode(context.Code)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case RETURN:
 | 
			
		||||
			size, offset := stack.Popn()
 | 
			
		||||
			offset, size := stack.pop(), stack.pop()
 | 
			
		||||
			ret := mem.Get(offset.Int64(), size.Int64())
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => [%v, %v] (%d) 0x%x", offset, size, len(ret), ret).Endl()
 | 
			
		||||
 | 
			
		||||
			return context.Return(ret), nil
 | 
			
		||||
		case SUICIDE:
 | 
			
		||||
			receiver := statedb.GetOrNewStateObject(stack.Pop().Bytes())
 | 
			
		||||
			receiver := statedb.GetOrNewStateObject(stack.pop().Bytes())
 | 
			
		||||
			balance := statedb.GetBalance(context.Address())
 | 
			
		||||
 | 
			
		||||
			self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
 | 
			
		||||
@@ -753,117 +734,17 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
 | 
			
		||||
		pc++
 | 
			
		||||
 | 
			
		||||
		self.Endl()
 | 
			
		||||
 | 
			
		||||
		if self.Dbg != nil {
 | 
			
		||||
			for _, instrNo := range self.Dbg.BreakPoints() {
 | 
			
		||||
				if pc == uint64(instrNo) {
 | 
			
		||||
					self.Stepping = true
 | 
			
		||||
 | 
			
		||||
					if !self.Dbg.BreakHook(prevStep, op, mem, stack, statedb.GetStateObject(context.Address())) {
 | 
			
		||||
						return nil, nil
 | 
			
		||||
					}
 | 
			
		||||
				} else if self.Stepping {
 | 
			
		||||
					if !self.Dbg.StepHook(prevStep, op, mem, stack, statedb.GetStateObject(context.Address())) {
 | 
			
		||||
						return nil, nil
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type req struct {
 | 
			
		||||
	stack int
 | 
			
		||||
	gas   *big.Int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _baseCheck = map[OpCode]req{
 | 
			
		||||
	//       Req Stack  Gas price
 | 
			
		||||
	ADD:          {2, GasFastestStep},
 | 
			
		||||
	LT:           {2, GasFastestStep},
 | 
			
		||||
	GT:           {2, GasFastestStep},
 | 
			
		||||
	SLT:          {2, GasFastestStep},
 | 
			
		||||
	SGT:          {2, GasFastestStep},
 | 
			
		||||
	EQ:           {2, GasFastestStep},
 | 
			
		||||
	ISZERO:       {1, GasFastestStep},
 | 
			
		||||
	SUB:          {2, GasFastestStep},
 | 
			
		||||
	AND:          {2, GasFastestStep},
 | 
			
		||||
	OR:           {2, GasFastestStep},
 | 
			
		||||
	XOR:          {2, GasFastestStep},
 | 
			
		||||
	NOT:          {1, GasFastestStep},
 | 
			
		||||
	BYTE:         {2, GasFastestStep},
 | 
			
		||||
	CALLDATALOAD: {1, GasFastestStep},
 | 
			
		||||
	CALLDATACOPY: {3, GasFastestStep},
 | 
			
		||||
	MLOAD:        {1, GasFastestStep},
 | 
			
		||||
	MSTORE:       {2, GasFastestStep},
 | 
			
		||||
	MSTORE8:      {2, GasFastestStep},
 | 
			
		||||
	CODECOPY:     {3, GasFastestStep},
 | 
			
		||||
	MUL:          {2, GasFastStep},
 | 
			
		||||
	DIV:          {2, GasFastStep},
 | 
			
		||||
	SDIV:         {2, GasFastStep},
 | 
			
		||||
	MOD:          {2, GasFastStep},
 | 
			
		||||
	SMOD:         {2, GasFastStep},
 | 
			
		||||
	SIGNEXTEND:   {2, GasFastStep},
 | 
			
		||||
	ADDMOD:       {3, GasMidStep},
 | 
			
		||||
	MULMOD:       {3, GasMidStep},
 | 
			
		||||
	JUMP:         {1, GasMidStep},
 | 
			
		||||
	JUMPI:        {2, GasSlowStep},
 | 
			
		||||
	EXP:          {2, GasSlowStep},
 | 
			
		||||
	ADDRESS:      {0, GasQuickStep},
 | 
			
		||||
	ORIGIN:       {0, GasQuickStep},
 | 
			
		||||
	CALLER:       {0, GasQuickStep},
 | 
			
		||||
	CALLVALUE:    {0, GasQuickStep},
 | 
			
		||||
	CODESIZE:     {0, GasQuickStep},
 | 
			
		||||
	GASPRICE:     {0, GasQuickStep},
 | 
			
		||||
	COINBASE:     {0, GasQuickStep},
 | 
			
		||||
	TIMESTAMP:    {0, GasQuickStep},
 | 
			
		||||
	NUMBER:       {0, GasQuickStep},
 | 
			
		||||
	CALLDATASIZE: {0, GasQuickStep},
 | 
			
		||||
	DIFFICULTY:   {0, GasQuickStep},
 | 
			
		||||
	GASLIMIT:     {0, GasQuickStep},
 | 
			
		||||
	POP:          {0, GasQuickStep},
 | 
			
		||||
	PC:           {0, GasQuickStep},
 | 
			
		||||
	MSIZE:        {0, GasQuickStep},
 | 
			
		||||
	GAS:          {0, GasQuickStep},
 | 
			
		||||
	BLOCKHASH:    {1, GasExtStep},
 | 
			
		||||
	BALANCE:      {0, GasExtStep},
 | 
			
		||||
	EXTCODESIZE:  {1, GasExtStep},
 | 
			
		||||
	EXTCODECOPY:  {4, GasExtStep},
 | 
			
		||||
	SLOAD:        {1, GasStorageGet},
 | 
			
		||||
	SSTORE:       {2, Zero},
 | 
			
		||||
	SHA3:         {1, GasSha3Base},
 | 
			
		||||
	CREATE:       {3, GasCreate},
 | 
			
		||||
	CALL:         {7, GasCall},
 | 
			
		||||
	CALLCODE:     {7, GasCall},
 | 
			
		||||
	JUMPDEST:     {0, GasJumpDest},
 | 
			
		||||
	SUICIDE:      {1, Zero},
 | 
			
		||||
	RETURN:       {2, Zero},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func baseCheck(op OpCode, stack *Stack, gas *big.Int) {
 | 
			
		||||
	if r, ok := _baseCheck[op]; ok {
 | 
			
		||||
		stack.require(r.stack)
 | 
			
		||||
 | 
			
		||||
		gas.Add(gas, r.gas)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toWordSize(size *big.Int) *big.Int {
 | 
			
		||||
	tmp := new(big.Int)
 | 
			
		||||
	tmp.Add(size, u256(31))
 | 
			
		||||
	tmp.Div(tmp, u256(32))
 | 
			
		||||
	return tmp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *Stack) (*big.Int, *big.Int) {
 | 
			
		||||
func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int) {
 | 
			
		||||
	var (
 | 
			
		||||
		gas                 = new(big.Int)
 | 
			
		||||
		newMemSize *big.Int = new(big.Int)
 | 
			
		||||
	)
 | 
			
		||||
	baseCheck(op, stack, gas)
 | 
			
		||||
 | 
			
		||||
	// Stack Check, memory resize & gas phase
 | 
			
		||||
	// stack Check, memory resize & gas phase
 | 
			
		||||
	switch op {
 | 
			
		||||
	case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
 | 
			
		||||
		gas.Set(GasFastestStep)
 | 
			
		||||
@@ -879,7 +760,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
 | 
			
		||||
		n := int(op - LOG0)
 | 
			
		||||
		stack.require(n + 2)
 | 
			
		||||
 | 
			
		||||
		mSize, mStart := stack.Peekn()
 | 
			
		||||
		mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
 | 
			
		||||
 | 
			
		||||
		gas.Add(gas, GasLogBase)
 | 
			
		||||
		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic))
 | 
			
		||||
@@ -887,12 +768,12 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
 | 
			
		||||
 | 
			
		||||
		newMemSize = calcMemSize(mStart, mSize)
 | 
			
		||||
	case EXP:
 | 
			
		||||
		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes()))), GasExpByte))
 | 
			
		||||
		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), GasExpByte))
 | 
			
		||||
	case SSTORE:
 | 
			
		||||
		stack.require(2)
 | 
			
		||||
 | 
			
		||||
		var g *big.Int
 | 
			
		||||
		y, x := stack.Peekn()
 | 
			
		||||
		y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
 | 
			
		||||
		val := statedb.GetState(context.Address(), x.Bytes())
 | 
			
		||||
		if len(val) == 0 && len(y.Bytes()) > 0 {
 | 
			
		||||
			// 0 => non 0
 | 
			
		||||
@@ -911,51 +792,51 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
 | 
			
		||||
			statedb.Refund(self.env.Origin(), RefundSuicide)
 | 
			
		||||
		}
 | 
			
		||||
	case MLOAD:
 | 
			
		||||
		newMemSize = calcMemSize(stack.Peek(), u256(32))
 | 
			
		||||
		newMemSize = calcMemSize(stack.peek(), u256(32))
 | 
			
		||||
	case MSTORE8:
 | 
			
		||||
		newMemSize = calcMemSize(stack.Peek(), u256(1))
 | 
			
		||||
		newMemSize = calcMemSize(stack.peek(), u256(1))
 | 
			
		||||
	case MSTORE:
 | 
			
		||||
		newMemSize = calcMemSize(stack.Peek(), u256(32))
 | 
			
		||||
		newMemSize = calcMemSize(stack.peek(), u256(32))
 | 
			
		||||
	case RETURN:
 | 
			
		||||
		newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
 | 
			
		||||
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
 | 
			
		||||
	case SHA3:
 | 
			
		||||
		newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
 | 
			
		||||
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
 | 
			
		||||
 | 
			
		||||
		words := toWordSize(stack.data[stack.Len()-2])
 | 
			
		||||
		words := toWordSize(stack.data[stack.len()-2])
 | 
			
		||||
		gas.Add(gas, words.Mul(words, GasSha3Word))
 | 
			
		||||
	case CALLDATACOPY:
 | 
			
		||||
		newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
 | 
			
		||||
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
 | 
			
		||||
 | 
			
		||||
		words := toWordSize(stack.data[stack.Len()-3])
 | 
			
		||||
		words := toWordSize(stack.data[stack.len()-3])
 | 
			
		||||
		gas.Add(gas, words.Mul(words, GasCopyWord))
 | 
			
		||||
	case CODECOPY:
 | 
			
		||||
		newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
 | 
			
		||||
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
 | 
			
		||||
 | 
			
		||||
		words := toWordSize(stack.data[stack.Len()-3])
 | 
			
		||||
		words := toWordSize(stack.data[stack.len()-3])
 | 
			
		||||
		gas.Add(gas, words.Mul(words, GasCopyWord))
 | 
			
		||||
	case EXTCODECOPY:
 | 
			
		||||
		newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4])
 | 
			
		||||
		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
 | 
			
		||||
 | 
			
		||||
		words := toWordSize(stack.data[stack.Len()-4])
 | 
			
		||||
		words := toWordSize(stack.data[stack.len()-4])
 | 
			
		||||
		gas.Add(gas, words.Mul(words, GasCopyWord))
 | 
			
		||||
 | 
			
		||||
	case CREATE:
 | 
			
		||||
		newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3])
 | 
			
		||||
		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
 | 
			
		||||
	case CALL, CALLCODE:
 | 
			
		||||
		gas.Add(gas, stack.data[stack.Len()-1])
 | 
			
		||||
		gas.Add(gas, stack.data[stack.len()-1])
 | 
			
		||||
 | 
			
		||||
		if op == CALL {
 | 
			
		||||
			if self.env.State().GetStateObject(stack.data[stack.Len()-2].Bytes()) == nil {
 | 
			
		||||
			if self.env.State().GetStateObject(stack.data[stack.len()-2].Bytes()) == nil {
 | 
			
		||||
				gas.Add(gas, GasCallNewAccount)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(stack.data[stack.Len()-3].Bytes()) > 0 {
 | 
			
		||||
		if len(stack.data[stack.len()-3].Bytes()) > 0 {
 | 
			
		||||
			gas.Add(gas, GasCallValueTransfer)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
 | 
			
		||||
		y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5])
 | 
			
		||||
		x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
 | 
			
		||||
		y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
 | 
			
		||||
 | 
			
		||||
		newMemSize = ethutil.BigMax(x, y)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user