good morning!!!!

Skip to content
Snippets Groups Projects
vm.go 20.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    package vm
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    import (
    	"fmt"
    	"math/big"
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	"github.com/ethereum/go-ethereum/common"
    
    	"github.com/ethereum/go-ethereum/core/state"
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	"github.com/ethereum/go-ethereum/crypto"
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    )
    
    type Vm struct {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	env Environment
    
    	logTy  byte
    	logStr string
    
    	err error
    
    	// For logging
    	debug bool
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    	BreakPoints []int64
    	Stepping    bool
    	Fn          string
    
    	Recoverable bool
    }
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    func New(env Environment) *Vm {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	lt := LogTyPretty
    
    
    	return &Vm{debug: Debug, env: env, logTy: lt, Recoverable: true}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    }
    
    
    func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	self.env.SetDepth(self.env.Depth() + 1)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	defer self.env.SetDepth(self.env.Depth() - 1)
    
    
    	var (
    		caller = context.caller
    		code   = context.Code
    		value  = context.value
    		price  = context.Price
    	)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	self.Printf("(%d) (%x) %x (code=%d) gas: %v (d) %x", self.env.Depth(), caller.Address().Bytes()[:4], context.Address(), len(code), context.Gas, callData).Endl()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    	if self.Recoverable {
    		// Recover from any require exception
    		defer func() {
    			if r := recover(); r != nil {
    				self.Printf(" %v", r).Endl()
    
    				context.UseGas(context.Gas)
    
    				ret = context.Return(nil)
    
    				err = fmt.Errorf("%v", r)
    			}
    		}()
    	}
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	if context.CodeAddr != nil {
    		if p := Precompiled[context.CodeAddr.Str()]; p != nil {
    			return self.RunPrecompiled(p, callData, context)
    		}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	}
    
    	var (
    		op OpCode
    
    		destinations        = analyseJumpDests(context.Code)
    		mem                 = NewMemory()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		stack               = newStack()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		pc           uint64 = 0
    		step                = 0
    		statedb             = self.env.State()
    
    		jump = func(from uint64, to *big.Int) {
    			p := to.Uint64()
    
    			nop := context.GetOp(p)
    			if !destinations.Has(p) {
    				panic(fmt.Sprintf("invalid jump destination (%v) %v", nop, p))
    			}
    
    			self.Printf(" ~> %v", to)
    			pc = to.Uint64()
    
    			self.Endl()
    		}
    	)
    
    	// Don't bother with the execution if there's no code.
    	if len(code) == 0 {
    		return context.Return(nil), nil
    	}
    
    	for {
    		// The base for all big integer arithmetic
    		base := new(big.Int)
    
    		step++
    		// Get the memory location of pc
    		op = context.GetOp(pc)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.len())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize, gas := self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
    
    		self.Printf("(g) %-3v (%v)", gas, context.Gas)
    
    		if !context.UseGas(gas) {
    			self.Endl()
    
    			tmp := new(big.Int).Set(context.Gas)
    
    			context.UseGas(context.Gas)
    
    			return context.Return(nil), OOG(gas, tmp)
    		}
    
    		mem.Resize(newMemSize.Uint64())
    
    		switch op {
    		// 0x20 range
    		case ADD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" %v + %v", y, x)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			base.Add(x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			U256(base)
    
    			self.Printf(" = %v", base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// pop result back on the stack
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case SUB:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" %v - %v", y, x)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			base.Sub(x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			U256(base)
    
    			self.Printf(" = %v", base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// pop result back on the stack
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case MUL:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" %v * %v", y, x)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			base.Mul(x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			U256(base)
    
    			self.Printf(" = %v", base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// pop result back on the stack
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case DIV:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" %v / %v", x, y)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if y.Cmp(common.Big0) != 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				base.Div(x, y)
    			}
    
    			U256(base)
    
    			self.Printf(" = %v", base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// pop result back on the stack
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case SDIV:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := S256(stack.pop()), S256(stack.pop())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" %v / %v", x, y)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if y.Cmp(common.Big0) == 0 {
    				base.Set(common.Big0)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    				n := new(big.Int)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    					n.SetInt64(-1)
    				} else {
    					n.SetInt64(1)
    				}
    
    				base.Div(x.Abs(x), y.Abs(y)).Mul(base, n)
    
    				U256(base)
    			}
    
    			self.Printf(" = %v", base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case MOD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" %v %% %v", x, y)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if y.Cmp(common.Big0) == 0 {
    				base.Set(common.Big0)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    				base.Mod(x, y)
    			}
    
    			U256(base)
    
    			self.Printf(" = %v", base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case SMOD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := S256(stack.pop()), S256(stack.pop())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" %v %% %v", x, y)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if y.Cmp(common.Big0) == 0 {
    				base.Set(common.Big0)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    				n := new(big.Int)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				if x.Cmp(common.Big0) < 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    					n.SetInt64(-1)
    				} else {
    					n.SetInt64(1)
    				}
    
    				base.Mod(x.Abs(x), y.Abs(y)).Mul(base, n)
    
    				U256(base)
    			}
    
    			self.Printf(" = %v", base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    		case EXP:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" %v ** %v", x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			base.Exp(x, y, Pow256)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			U256(base)
    
    			self.Printf(" = %v", base)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case SIGNEXTEND:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			back := stack.pop()
    			if back.Cmp(big.NewInt(31)) < 0 {
    				bit := uint(back.Uint64()*8 + 7)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				num := stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				mask := new(big.Int).Lsh(common.Big1, bit)
    				mask.Sub(mask, common.Big1)
    				if common.BitTest(num, int(bit)) {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    					num.Or(num, mask.Not(mask))
    				} else {
    					num.And(num, mask)
    				}
    
    				num = U256(num)
    
    				self.Printf(" = %v", num)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(num)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    		case NOT:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(U256(new(big.Int).Not(stack.pop())))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			//base.Sub(Pow256, stack.pop()).Sub(base, common.Big1)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			//base = U256(base)
    			//stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case LT:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    			self.Printf(" %v < %v", x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// x < y
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if x.Cmp(y) < 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigTrue)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    		case GT:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    			self.Printf(" %v > %v", x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			// x > y
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if x.Cmp(y) > 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigTrue)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    
    		case SLT:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := S256(stack.pop()), S256(stack.pop())
    			self.Printf(" %v < %v", x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// x < y
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if x.Cmp(S256(y)) < 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigTrue)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    		case SGT:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := S256(stack.pop()), S256(stack.pop())
    			self.Printf(" %v > %v", x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			// x > y
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if x.Cmp(y) > 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigTrue)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    
    		case EQ:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" %v == %v", y, x)
    
    			// x == y
    			if x.Cmp(y) == 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigTrue)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    		case ISZERO:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x := stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if x.Cmp(common.BigFalse) > 0 {
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigTrue)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    
    			// 0x10 range
    		case AND:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" %v & %v", y, x)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base.And(x, y))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case OR:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    			self.Printf(" %v | %v", x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base.Or(x, y))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case XOR:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x, y := stack.pop(), stack.pop()
    			self.Printf(" %v ^ %v", x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base.Xor(x, y))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case BYTE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			th, val := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			if th.Cmp(big.NewInt(32)) < 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				byt := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    				base.Set(byt)
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				base.Set(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    
    			self.Printf(" => 0x%x", base.Bytes())
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case ADDMOD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x := stack.pop()
    			y := stack.pop()
    			z := stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if z.Cmp(Zero) > 0 {
    
    				add := new(big.Int).Add(x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				base.Mod(add, z)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				base = U256(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    
    			self.Printf(" %v + %v %% %v = %v", x, y, z, base)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case MULMOD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			x := stack.pop()
    			y := stack.pop()
    			z := stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    			if z.Cmp(Zero) > 0 {
    				mul := new(big.Int).Mul(x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				base.Mod(mul, z)
    
    				U256(base)
    			}
    
    			self.Printf(" %v + %v %% %v = %v", x, y, z, base)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(base)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			// 0x20 range
    		case SHA3:
    
    			offset, size := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64()))
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(common.BigD(data))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => (%v) %x", size, data)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// 0x30 range
    		case ADDRESS:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(common.Bytes2Big(context.Address().Bytes()))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %x", context.Address())
    		case BALANCE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			addr := common.BigToAddress(stack.pop())
    
    			balance := statedb.GetBalance(addr)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(balance)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %v (%x)", balance, addr)
    		case ORIGIN:
    			origin := self.env.Origin()
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(origin.Big())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %x", origin)
    		case CALLER:
    			caller := context.caller.Address()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(common.Bytes2Big(caller.Bytes()))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %x", caller)
    		case CALLVALUE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(value)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %v", value)
    		case CALLDATALOAD:
    			var (
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				offset  = stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				data    = make([]byte, 32)
    				lenData = big.NewInt(int64(len(callData)))
    			)
    
    			if lenData.Cmp(offset) >= 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				length := new(big.Int).Add(offset, common.Big32)
    				length = common.BigMin(length, lenData)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    				copy(data, callData[offset.Int64():length.Int64()])
    			}
    
    			self.Printf(" => 0x%x", data)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(common.BigD(data))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case CALLDATASIZE:
    			l := int64(len(callData))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(big.NewInt(l))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %d", l)
    		case CALLDATACOPY:
    			var (
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				mOff = stack.pop()
    				cOff = stack.pop()
    				l    = stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			data := getData(callData, cOff, l)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			mem.Set(mOff.Uint64(), l.Uint64(), data)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => [%v, %v, %v]", mOff, cOff, l)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case CODESIZE, EXTCODESIZE:
    			var code []byte
    			if op == EXTCODESIZE {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				addr := common.BigToAddress(stack.pop())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    				code = statedb.GetCode(addr)
    			} else {
    				code = context.Code
    			}
    
    			l := big.NewInt(int64(len(code)))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(l)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %d", l)
    		case CODECOPY, EXTCODECOPY:
    			var code []byte
    			if op == EXTCODECOPY {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				addr := common.BigToAddress(stack.pop())
    				code = statedb.GetCode(addr)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    				code = context.Code
    			}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			var (
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				mOff = stack.pop()
    				cOff = stack.pop()
    				l    = stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			codeCopy := getData(code, cOff, l)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			mem.Set(mOff.Uint64(), l.Uint64(), codeCopy)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, codeCopy)
    		case GASPRICE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(context.Price)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => %x", context.Price)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			// 0x40 range
    		case BLOCKHASH:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			num := stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(self.env.GetHash(num.Uint64()).Big())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.Big0)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => 0x%x", stack.peek().Bytes())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case COINBASE:
    			coinbase := self.env.Coinbase()
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(coinbase.Big())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => 0x%x", coinbase)
    		case TIMESTAMP:
    			time := self.env.Time()
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(big.NewInt(time))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => 0x%x", time)
    		case NUMBER:
    			number := self.env.BlockNumber()
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(U256(number))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => 0x%x", number.Bytes())
    		case DIFFICULTY:
    			difficulty := self.env.Difficulty()
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(difficulty)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => 0x%x", difficulty.Bytes())
    		case GASLIMIT:
    			self.Printf(" => %v", self.env.GasLimit())
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(self.env.GasLimit())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			// 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)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// push value to stack
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(common.BigD(byts))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			pc += a
    
    			step += int(op) - int(PUSH1) + 1
    
    			self.Printf(" => 0x%x", byts)
    		case POP:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
    			n := int(op - DUP1 + 1)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.dup(n)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => [%d] 0x%x", n, stack.peek().Bytes())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
    			n := int(op - SWAP1 + 2)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.swap(n)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => [%d]", n)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case LOG0, LOG1, LOG2, LOG3, LOG4:
    			n := int(op - LOG0)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			topics := make([]common.Hash, n)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			mStart, mSize := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			for i := 0; i < n; i++ {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				topics[i] = common.BigToHash(stack.pop()) //common.LeftPadBytes(stack.pop().Bytes(), 32)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    
    			data := mem.Get(mStart.Int64(), mSize.Int64())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			log := &Log{context.Address(), topics, data, self.env.BlockNumber().Uint64()}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.env.AddLog(log)
    
    			self.Printf(" => %v", log)
    		case MLOAD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			offset := stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			val := common.BigD(mem.Get(offset.Int64(), 32))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(val)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => 0x%x", val.Bytes())
    		case MSTORE: // Store the value at stack top-1 in to memory at location stack top
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// pop value of the stack
    			mStart, val := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			mem.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => 0x%x", val)
    		case MSTORE8:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			off, val := stack.pop().Int64(), stack.pop().Int64()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			mem.store[off] = byte(val & 0xff)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => [%v] 0x%x", off, mem.store[off])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case SLOAD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			loc := common.BigToHash(stack.pop())
    			val := common.Bytes2Big(statedb.GetState(context.Address(), loc))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(val)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case SSTORE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			loc := common.BigToHash(stack.pop())
    			val := stack.pop()
    
    			statedb.SetState(context.Address(), loc, val)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case JUMP:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			jump(pc, stack.pop())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			continue
    		case JUMPI:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			pos, cond := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if cond.Cmp(common.BigTrue) >= 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				jump(pc, pos)
    
    				continue
    			}
    
    
    			self.Printf(" ~> false")
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case JUMPDEST:
    		case PC:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(big.NewInt(int64(pc)))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case MSIZE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(big.NewInt(int64(mem.Len())))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		case GAS:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			stack.push(context.Gas)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			self.Printf(" => %x", context.Gas)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// 0x60 range
    		case CREATE:
    
    			var (
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				value        = stack.pop()
    				offset, size = stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				input        = mem.Get(offset.Int64(), size.Int64())
    				gas          = new(big.Int).Set(context.Gas)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				addr         common.Address
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Endl()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			context.UseGas(context.Gas)
    
    			ret, suberr, ref := self.env.Create(context, nil, input, gas, price, value)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if suberr != nil {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    				self.Printf(" (*) 0x0 %v", suberr)
    			} else {
    
    				// gas < len(ret) * CreateDataGas == NO_CODE
    				dataGas := big.NewInt(int64(len(ret)))
    				dataGas.Mul(dataGas, GasCreateByte)
    				if context.UseGas(dataGas) {
    					ref.SetCode(ret)
    				}
    				addr = ref.Address()
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(addr.Big())
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			}
    
    		case CALL, CALLCODE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			gas := stack.pop()
    			// pop gas and value of the stack.
    			addr, value := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			value = U256(value)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// pop input size and offset
    			inOffset, inSize := stack.pop(), stack.pop()
    			// pop return size and offset
    			retOffset, retSize := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			address := common.BigToAddress(addr)
    
    			self.Printf(" => %x", address).Endl()
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			// Get the arguments from the memory
    			args := mem.Get(inOffset.Int64(), inSize.Int64())
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if len(value.Bytes()) > 0 {
    				gas.Add(gas, GasStipend)
    			}
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			var (
    				ret []byte
    				err error
    			)
    			if op == CALLCODE {
    
    				ret, err = self.env.CallCode(context, address, args, gas, price, value)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    				ret, err = self.env.Call(context, address, args, gas, price, value)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			}
    
    			if err != nil {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigFalse)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    				self.Printf("%v").Endl()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			} else {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				stack.push(common.BigTrue)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    				mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
    			}
    			self.Printf("resume %x (%v)", context.Address(), context.Gas)
    		case RETURN:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			offset, size := stack.pop(), stack.pop()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			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:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop()))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			balance := statedb.GetBalance(context.Address())
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			self.Printf(" => (%x) %v", receiver.Address().Bytes()[:4], balance)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    			receiver.AddBalance(balance)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			statedb.Delete(context.Address())
    
    			fallthrough
    		case STOP: // Stop the context
    			self.Endl()
    
    			return context.Return(nil), nil
    		default:
    
    			self.Printf("(pc) %-3v Invalid opcode %x\n", pc, op).Endl()
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    			panic(fmt.Errorf("Invalid opcode %x", op))
    		}
    
    		pc++
    
    		self.Endl()
    	}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int) {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	var (
    		gas                 = new(big.Int)
    		newMemSize *big.Int = new(big.Int)
    	)
    	baseCheck(op, stack, gas)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	// stack Check, memory resize & gas phase
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	switch op {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	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)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
    		n := int(op - SWAP1 + 2)
    		stack.require(n)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Set(GasFastestStep)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
    		n := int(op - DUP1 + 1)
    		stack.require(n)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Set(GasFastestStep)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case LOG0, LOG1, LOG2, LOG3, LOG4:
    		n := int(op - LOG0)
    		stack.require(n + 2)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    		gas.Add(gas, GasLogBase)
    		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Add(gas, new(big.Int).Mul(mSize, GasLogByte))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    		newMemSize = calcMemSize(mStart, mSize)
    	case EXP:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), GasExpByte))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case SSTORE:
    		stack.require(2)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		var g *big.Int
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		val := statedb.GetState(context.Address(), common.BigToHash(x))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		if len(val) == 0 && len(y.Bytes()) > 0 {
    			// 0 => non 0
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			g = GasStorageAdd
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		} else if len(val) > 0 && len(y.Bytes()) == 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			statedb.Refund(self.env.Origin(), RefundStorage)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			g = GasStorageMod
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		} else {
    			// non 0 => non 0 (or 0 => 0)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			g = GasStorageMod
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Set(g)
    
    	case SUICIDE:
    		if !statedb.IsDeleted(context.Address()) {
    			statedb.Refund(self.env.Origin(), RefundSuicide)
    		}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case MLOAD:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.peek(), u256(32))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case MSTORE8:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.peek(), u256(1))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case MSTORE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.peek(), u256(32))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case RETURN:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case SHA3:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		words := toWordSize(stack.data[stack.len()-2])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Add(gas, words.Mul(words, GasSha3Word))
    	case CALLDATACOPY:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		words := toWordSize(stack.data[stack.len()-3])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Add(gas, words.Mul(words, GasCopyWord))
    	case CODECOPY:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		words := toWordSize(stack.data[stack.len()-3])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Add(gas, words.Mul(words, GasCopyWord))
    	case EXTCODECOPY:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		words := toWordSize(stack.data[stack.len()-4])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Add(gas, words.Mul(words, GasCopyWord))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case CREATE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	case CALL, CALLCODE:
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		gas.Add(gas, stack.data[stack.len()-1])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    		if op == CALL {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    				gas.Add(gas, GasCallNewAccount)
    			}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		if len(stack.data[stack.len()-3].Bytes()) > 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			gas.Add(gas, GasCallValueTransfer)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
    		y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSize = common.BigMax(x, y)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	if newMemSize.Cmp(common.Big0) > 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		newMemSizeWords := toWordSize(newMemSize)
    		newMemSize.Mul(newMemSizeWords, u256(32))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    		if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			oldSize := toWordSize(big.NewInt(int64(mem.Len())))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			linCoef := new(big.Int).Mul(oldSize, GasMemWord)
    			quadCoef := new(big.Int).Div(pow, GasQuadCoeffDenom)
    			oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			pow.Exp(newMemSizeWords, common.Big2, Zero)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			linCoef = new(big.Int).Mul(newMemSizeWords, GasMemWord)
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    			quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom)
    			newTotalFee := new(big.Int).Add(linCoef, quadCoef)
    
    			gas.Add(gas, new(big.Int).Sub(newTotalFee, oldTotalFee))
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    		}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    
    	return newMemSize, gas
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    }
    
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    func (self *Vm) RunPrecompiled(p *PrecompiledAccount, callData []byte, context *Context) (ret []byte, err error) {
    	gas := p.Gas(len(callData))
    	if context.UseGas(gas) {
    		ret = p.Call(callData)
    		self.Printf("NATIVE_FUNC => %x", ret)
    		self.Endl()
    
    		return context.Return(ret), nil
    	} else {
    		self.Printf("NATIVE_FUNC => failed").Endl()
    
    		tmp := new(big.Int).Set(context.Gas)
    
    		panic(OOG(gas, tmp).Error())
    	}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine {
    
    	if self.debug {
    		if self.logTy == LogTyPretty {
    			self.logStr += fmt.Sprintf(format, v...)
    		}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	}
    
    	return self
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    func (self *Vm) Endl() VirtualMachine {
    
    	if self.debug {
    		if self.logTy == LogTyPretty {
    
    			vmlogger.Infoln(self.logStr)
    
    			self.logStr = ""
    		}
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    	}
    
    	return self
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    }
    
    Jeffrey Wilcke's avatar
    Jeffrey Wilcke committed
    func (self *Vm) Env() Environment {
    	return self.env
    }