quorum/core/vm/vm.go

909 lines
21 KiB
Go
Raw Normal View History

2014-10-18 04:31:20 -07:00
package vm
2015-01-19 02:18:34 -08:00
import (
"fmt"
"math/big"
2015-03-16 03:27:38 -07:00
"github.com/ethereum/go-ethereum/common"
2015-03-23 08:59:09 -07:00
"github.com/ethereum/go-ethereum/core/state"
2015-03-23 13:48:31 -07:00
"github.com/ethereum/go-ethereum/crypto"
2015-01-19 02:18:34 -08:00
)
2014-10-15 08:12:26 -07:00
type Vm struct {
2015-01-19 02:18:34 -08:00
env Environment
logTy byte
logStr string
err error
// For logging
debug bool
2015-01-19 02:18:34 -08:00
BreakPoints []int64
Stepping bool
Fn string
Recoverable bool
2015-03-28 12:03:25 -07:00
// Will be called before the vm returns
After func(*Context, error)
2015-01-19 02:18:34 -08:00
}
2015-01-20 06:49:12 -08:00
func New(env Environment) *Vm {
2015-01-19 02:18:34 -08:00
lt := LogTyPretty
return &Vm{debug: Debug, env: env, logTy: lt, Recoverable: true}
2015-01-19 02:18:34 -08:00
}
func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
2015-01-19 02:18:34 -08:00
self.env.SetDepth(self.env.Depth() + 1)
2015-03-23 13:48:31 -07:00
defer self.env.SetDepth(self.env.Depth() - 1)
var (
caller = context.caller
code = context.Code
value = context.value
price = context.Price
)
2015-01-19 02:18:34 -08:00
2015-03-16 10:42:18 -07:00
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()
2015-01-19 02:18:34 -08:00
2015-03-27 08:53:05 -07:00
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
2015-03-27 08:09:57 -07:00
defer func() {
2015-03-28 12:03:25 -07:00
if self.After != nil {
self.After(context, err)
}
2015-03-27 08:09:57 -07:00
if err != nil {
self.Printf(" %v", err).Endl()
// In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
context.UseGas(context.Gas)
ret = context.Return(nil)
}
}()
2015-01-19 02:18:34 -08:00
2015-03-17 03:19:23 -07:00
if context.CodeAddr != nil {
if p := Precompiled[context.CodeAddr.Str()]; p != nil {
return self.RunPrecompiled(p, callData, context)
}
2015-01-19 02:18:34 -08:00
}
var (
op OpCode
destinations = analyseJumpDests(context.Code)
mem = NewMemory()
stack = newStack()
pc = new(big.Int)
statedb = self.env.State()
jump = func(from *big.Int, to *big.Int) error {
nop := context.GetOp(to)
if !destinations.Has(to) {
return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
2015-01-19 02:18:34 -08:00
}
self.Printf(" ~> %v", to)
pc = to
2015-01-19 02:18:34 -08:00
self.Endl()
2015-03-27 08:09:57 -07:00
return nil
2015-01-19 02:18:34 -08:00
}
)
// 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)
// Get the memory location of pc
op = context.GetOp(pc)
2015-03-09 16:25:27 -07:00
self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.len())
2015-03-27 08:09:57 -07:00
newMemSize, gas, err := self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
if err != nil {
return nil, err
}
2015-01-19 02:18:34 -08:00
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:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
self.Printf(" %v + %v", y, x)
2015-03-09 16:25:27 -07:00
base.Add(x, y)
2015-01-19 02:18:34 -08:00
U256(base)
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
// pop result back on the stack
stack.push(base)
2015-01-19 02:18:34 -08:00
case SUB:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
self.Printf(" %v - %v", y, x)
2015-03-09 16:25:27 -07:00
base.Sub(x, y)
2015-01-19 02:18:34 -08:00
U256(base)
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
// pop result back on the stack
stack.push(base)
2015-01-19 02:18:34 -08:00
case MUL:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
self.Printf(" %v * %v", y, x)
2015-03-09 16:25:27 -07:00
base.Mul(x, y)
2015-01-19 02:18:34 -08:00
U256(base)
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
// pop result back on the stack
stack.push(base)
2015-01-19 02:18:34 -08:00
case DIV:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
self.Printf(" %v / %v", x, y)
2015-03-16 03:27:38 -07:00
if y.Cmp(common.Big0) != 0 {
2015-01-19 02:18:34 -08:00
base.Div(x, y)
}
U256(base)
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
// pop result back on the stack
stack.push(base)
2015-01-19 02:18:34 -08:00
case SDIV:
2015-03-09 16:25:27 -07:00
x, y := S256(stack.pop()), S256(stack.pop())
2015-01-19 02:18:34 -08:00
self.Printf(" %v / %v", x, y)
2015-03-16 03:27:38 -07:00
if y.Cmp(common.Big0) == 0 {
base.Set(common.Big0)
2015-01-19 02:18:34 -08:00
} else {
n := new(big.Int)
2015-03-16 03:27:38 -07:00
if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
2015-01-19 02:18:34 -08:00
n.SetInt64(-1)
} else {
n.SetInt64(1)
}
base.Div(x.Abs(x), y.Abs(y)).Mul(base, n)
U256(base)
}
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
stack.push(base)
2015-01-19 02:18:34 -08:00
case MOD:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
self.Printf(" %v %% %v", x, y)
2015-03-16 03:27:38 -07:00
if y.Cmp(common.Big0) == 0 {
base.Set(common.Big0)
2015-01-19 02:18:34 -08:00
} else {
base.Mod(x, y)
}
U256(base)
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
stack.push(base)
2015-01-19 02:18:34 -08:00
case SMOD:
2015-03-09 16:25:27 -07:00
x, y := S256(stack.pop()), S256(stack.pop())
2015-01-19 02:18:34 -08:00
self.Printf(" %v %% %v", x, y)
2015-03-16 03:27:38 -07:00
if y.Cmp(common.Big0) == 0 {
base.Set(common.Big0)
2015-01-19 02:18:34 -08:00
} else {
n := new(big.Int)
2015-03-16 03:27:38 -07:00
if x.Cmp(common.Big0) < 0 {
2015-01-19 02:18:34 -08:00
n.SetInt64(-1)
} else {
n.SetInt64(1)
}
base.Mod(x.Abs(x), y.Abs(y)).Mul(base, n)
U256(base)
}
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
stack.push(base)
2015-01-19 02:18:34 -08:00
case EXP:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
self.Printf(" %v ** %v", x, y)
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
base.Exp(x, y, Pow256)
2015-01-19 02:18:34 -08:00
U256(base)
self.Printf(" = %v", base)
2015-03-09 16:25:27 -07:00
stack.push(base)
2015-01-19 02:18:34 -08:00
case SIGNEXTEND:
2015-03-12 11:41:56 -07:00
back := stack.pop()
if back.Cmp(big.NewInt(31)) < 0 {
bit := uint(back.Uint64()*8 + 7)
2015-03-09 16:25:27 -07:00
num := stack.pop()
2015-03-16 03:27:38 -07:00
mask := new(big.Int).Lsh(common.Big1, bit)
mask.Sub(mask, common.Big1)
if common.BitTest(num, int(bit)) {
2015-01-19 02:18:34 -08:00
num.Or(num, mask.Not(mask))
} else {
num.And(num, mask)
}
num = U256(num)
self.Printf(" = %v", num)
2015-03-09 16:25:27 -07:00
stack.push(num)
2015-01-19 02:18:34 -08:00
}
case NOT:
2015-03-12 10:22:35 -07:00
stack.push(U256(new(big.Int).Not(stack.pop())))
2015-03-16 03:27:38 -07:00
//base.Sub(Pow256, stack.pop()).Sub(base, common.Big1)
2015-03-12 10:22:35 -07:00
//base = U256(base)
//stack.push(base)
2015-01-19 02:18:34 -08:00
case LT:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
self.Printf(" %v < %v", x, y)
2015-01-19 02:18:34 -08:00
// x < y
2015-03-09 16:25:27 -07:00
if x.Cmp(y) < 0 {
2015-03-16 03:27:38 -07:00
stack.push(common.BigTrue)
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
}
case GT:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
self.Printf(" %v > %v", x, y)
2015-01-19 02:18:34 -08:00
// x > y
2015-03-09 16:25:27 -07:00
if x.Cmp(y) > 0 {
2015-03-16 03:27:38 -07:00
stack.push(common.BigTrue)
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
}
case SLT:
2015-03-09 16:25:27 -07:00
x, y := S256(stack.pop()), S256(stack.pop())
self.Printf(" %v < %v", x, y)
2015-01-19 02:18:34 -08:00
// x < y
2015-03-09 16:25:27 -07:00
if x.Cmp(S256(y)) < 0 {
2015-03-16 03:27:38 -07:00
stack.push(common.BigTrue)
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
}
case SGT:
2015-03-09 16:25:27 -07:00
x, y := S256(stack.pop()), S256(stack.pop())
self.Printf(" %v > %v", x, y)
2015-01-19 02:18:34 -08:00
// x > y
2015-03-09 16:25:27 -07:00
if x.Cmp(y) > 0 {
2015-03-16 03:27:38 -07:00
stack.push(common.BigTrue)
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
}
case EQ:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
self.Printf(" %v == %v", y, x)
// x == y
if x.Cmp(y) == 0 {
2015-03-16 03:27:38 -07:00
stack.push(common.BigTrue)
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
}
case ISZERO:
2015-03-09 16:25:27 -07:00
x := stack.pop()
2015-03-16 03:27:38 -07:00
if x.Cmp(common.BigFalse) > 0 {
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.BigTrue)
2015-01-19 02:18:34 -08:00
}
// 0x10 range
case AND:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
self.Printf(" %v & %v", y, x)
2015-03-09 16:25:27 -07:00
stack.push(base.And(x, y))
2015-01-19 02:18:34 -08:00
case OR:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
self.Printf(" %v | %v", x, y)
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
stack.push(base.Or(x, y))
2015-01-19 02:18:34 -08:00
case XOR:
2015-03-09 16:25:27 -07:00
x, y := stack.pop(), stack.pop()
self.Printf(" %v ^ %v", x, y)
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
stack.push(base.Xor(x, y))
2015-01-19 02:18:34 -08:00
case BYTE:
2015-03-09 16:25:27 -07:00
th, val := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
if th.Cmp(big.NewInt(32)) < 0 {
2015-03-16 03:27:38 -07:00
byt := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
2015-01-19 02:18:34 -08:00
base.Set(byt)
} else {
2015-03-16 03:27:38 -07:00
base.Set(common.BigFalse)
2015-01-19 02:18:34 -08:00
}
self.Printf(" => 0x%x", base.Bytes())
2015-03-09 16:25:27 -07:00
stack.push(base)
2015-01-19 02:18:34 -08:00
case ADDMOD:
2015-03-09 16:25:27 -07:00
x := stack.pop()
y := stack.pop()
z := stack.pop()
2015-01-19 02:18:34 -08:00
2015-03-12 10:22:35 -07:00
if z.Cmp(Zero) > 0 {
add := new(big.Int).Add(x, y)
2015-01-19 02:18:34 -08:00
base.Mod(add, z)
2015-03-12 10:22:35 -07:00
base = U256(base)
2015-01-19 02:18:34 -08:00
}
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
2015-03-09 16:25:27 -07:00
stack.push(base)
2015-01-19 02:18:34 -08:00
case MULMOD:
2015-03-09 16:25:27 -07:00
x := stack.pop()
y := stack.pop()
z := stack.pop()
2015-01-19 02:18:34 -08:00
if z.Cmp(Zero) > 0 {
mul := new(big.Int).Mul(x, y)
2015-01-19 02:18:34 -08:00
base.Mod(mul, z)
U256(base)
}
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
2015-03-09 16:25:27 -07:00
stack.push(base)
2015-01-19 02:18:34 -08:00
// 0x20 range
case SHA3:
2015-03-12 15:26:58 -07:00
offset, size := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64()))
2015-03-16 03:27:38 -07:00
stack.push(common.BigD(data))
2015-01-19 02:18:34 -08:00
2015-03-03 02:56:43 -08:00
self.Printf(" => (%v) %x", size, data)
2015-01-19 02:18:34 -08:00
// 0x30 range
case ADDRESS:
2015-03-16 10:42:18 -07:00
stack.push(common.Bytes2Big(context.Address().Bytes()))
2015-01-19 02:18:34 -08:00
self.Printf(" => %x", context.Address())
case BALANCE:
2015-03-16 10:42:18 -07:00
addr := common.BigToAddress(stack.pop())
2015-03-12 14:29:10 -07:00
balance := statedb.GetBalance(addr)
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
stack.push(balance)
2015-01-19 02:18:34 -08:00
self.Printf(" => %v (%x)", balance, addr)
case ORIGIN:
origin := self.env.Origin()
2015-03-16 10:42:18 -07:00
stack.push(origin.Big())
2015-01-19 02:18:34 -08:00
self.Printf(" => %x", origin)
case CALLER:
caller := context.caller.Address()
2015-03-16 10:42:18 -07:00
stack.push(common.Bytes2Big(caller.Bytes()))
2015-01-19 02:18:34 -08:00
self.Printf(" => %x", caller)
case CALLVALUE:
2015-03-09 16:25:27 -07:00
stack.push(value)
2015-01-19 02:18:34 -08:00
self.Printf(" => %v", value)
case CALLDATALOAD:
data := getData(callData, stack.pop(), common.Big32)
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", data)
stack.push(common.Bytes2Big(data))
2015-01-19 02:18:34 -08:00
case CALLDATASIZE:
l := int64(len(callData))
2015-03-09 16:25:27 -07:00
stack.push(big.NewInt(l))
2015-01-19 02:18:34 -08:00
self.Printf(" => %d", l)
case CALLDATACOPY:
var (
2015-03-19 07:06:56 -07:00
mOff = stack.pop()
cOff = stack.pop()
l = stack.pop()
2015-01-19 02:18:34 -08:00
)
2015-03-19 14:45:03 -07:00
data := getData(callData, cOff, l)
2015-01-19 02:18:34 -08:00
2015-03-19 07:06:56 -07:00
mem.Set(mOff.Uint64(), l.Uint64(), data)
2015-01-19 02:18:34 -08:00
2015-03-19 14:45:03 -07:00
self.Printf(" => [%v, %v, %v]", mOff, cOff, l)
2015-01-19 02:18:34 -08:00
case CODESIZE, EXTCODESIZE:
var code []byte
if op == EXTCODESIZE {
2015-03-16 10:42:18 -07:00
addr := common.BigToAddress(stack.pop())
2015-01-19 02:18:34 -08:00
code = statedb.GetCode(addr)
} else {
code = context.Code
}
l := big.NewInt(int64(len(code)))
2015-03-09 16:25:27 -07:00
stack.push(l)
2015-01-19 02:18:34 -08:00
self.Printf(" => %d", l)
case CODECOPY, EXTCODECOPY:
var code []byte
if op == EXTCODECOPY {
2015-03-16 10:42:18 -07:00
addr := common.BigToAddress(stack.pop())
code = statedb.GetCode(addr)
2015-01-19 02:18:34 -08:00
} else {
code = context.Code
}
2015-03-19 07:06:56 -07:00
2015-01-19 02:18:34 -08:00
var (
2015-03-19 07:06:56 -07:00
mOff = stack.pop()
cOff = stack.pop()
l = stack.pop()
2015-01-19 02:18:34 -08:00
)
2015-03-19 14:45:03 -07:00
codeCopy := getData(code, cOff, l)
2015-03-19 07:06:56 -07:00
mem.Set(mOff.Uint64(), l.Uint64(), codeCopy)
2015-01-19 02:18:34 -08:00
self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, codeCopy)
case GASPRICE:
2015-03-09 16:25:27 -07:00
stack.push(context.Price)
2015-01-19 02:18:34 -08:00
2015-02-04 07:39:02 -08:00
self.Printf(" => %x", context.Price)
2015-01-19 02:18:34 -08:00
// 0x40 range
case BLOCKHASH:
2015-03-09 16:25:27 -07:00
num := stack.pop()
2015-01-19 02:18:34 -08:00
2015-03-16 03:27:38 -07:00
n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257)
2015-01-19 02:18:34 -08:00
if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
2015-03-17 03:19:23 -07:00
stack.push(self.env.GetHash(num.Uint64()).Big())
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.Big0)
2015-01-19 02:18:34 -08:00
}
2015-03-09 16:25:27 -07:00
self.Printf(" => 0x%x", stack.peek().Bytes())
2015-01-19 02:18:34 -08:00
case COINBASE:
coinbase := self.env.Coinbase()
2015-03-17 03:19:23 -07:00
stack.push(coinbase.Big())
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", coinbase)
case TIMESTAMP:
time := self.env.Time()
2015-03-09 16:25:27 -07:00
stack.push(big.NewInt(time))
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", time)
case NUMBER:
number := self.env.BlockNumber()
2015-03-09 16:25:27 -07:00
stack.push(U256(number))
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", number.Bytes())
case DIFFICULTY:
difficulty := self.env.Difficulty()
2015-03-09 16:25:27 -07:00
stack.push(difficulty)
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", difficulty.Bytes())
case GASLIMIT:
self.Printf(" => %v", self.env.GasLimit())
2015-03-09 16:25:27 -07:00
stack.push(self.env.GasLimit())
2015-01-19 02:18:34 -08:00
// 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 := big.NewInt(int64(op - PUSH1 + 1))
byts := getData(code, new(big.Int).Add(pc, big.NewInt(1)), a)
2015-03-09 16:25:27 -07:00
// push value to stack
stack.push(common.Bytes2Big(byts))
pc.Add(pc, a)
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", byts)
case POP:
2015-03-09 16:25:27 -07:00
stack.pop()
2015-01-19 02:18:34 -08:00
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
n := int(op - DUP1 + 1)
2015-03-09 16:25:27 -07:00
stack.dup(n)
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
self.Printf(" => [%d] 0x%x", n, stack.peek().Bytes())
2015-01-19 02:18:34 -08:00
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2)
2015-03-09 16:25:27 -07:00
stack.swap(n)
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
self.Printf(" => [%d]", n)
2015-01-19 02:18:34 -08:00
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
2015-03-16 15:10:26 -07:00
topics := make([]common.Hash, n)
2015-03-09 16:25:27 -07:00
mStart, mSize := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
for i := 0; i < n; i++ {
2015-03-16 15:10:26 -07:00
topics[i] = common.BigToHash(stack.pop()) //common.LeftPadBytes(stack.pop().Bytes(), 32)
2015-01-19 02:18:34 -08:00
}
data := mem.Get(mStart.Int64(), mSize.Int64())
2015-02-22 04:24:26 -08:00
log := &Log{context.Address(), topics, data, self.env.BlockNumber().Uint64()}
2015-01-19 02:18:34 -08:00
self.env.AddLog(log)
self.Printf(" => %v", log)
case MLOAD:
2015-03-09 16:25:27 -07:00
offset := stack.pop()
2015-03-16 03:27:38 -07:00
val := common.BigD(mem.Get(offset.Int64(), 32))
2015-03-09 16:25:27 -07:00
stack.push(val)
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", val.Bytes())
case MSTORE: // Store the value at stack top-1 in to memory at location stack top
2015-03-09 16:25:27 -07:00
// pop value of the stack
mStart, val := stack.pop(), stack.pop()
2015-03-16 03:27:38 -07:00
mem.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
2015-01-19 02:18:34 -08:00
self.Printf(" => 0x%x", val)
case MSTORE8:
2015-03-19 14:45:03 -07:00
off, val := stack.pop().Int64(), stack.pop().Int64()
2015-01-19 02:18:34 -08:00
2015-03-19 14:45:03 -07:00
mem.store[off] = byte(val & 0xff)
2015-01-19 02:18:34 -08:00
2015-03-19 14:45:03 -07:00
self.Printf(" => [%v] 0x%x", off, mem.store[off])
2015-01-19 02:18:34 -08:00
case SLOAD:
2015-03-16 10:42:18 -07:00
loc := common.BigToHash(stack.pop())
val := common.Bytes2Big(statedb.GetState(context.Address(), loc))
2015-03-09 16:25:27 -07:00
stack.push(val)
2015-01-19 02:18:34 -08:00
2015-03-16 10:42:18 -07:00
self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
2015-01-19 02:18:34 -08:00
case SSTORE:
2015-03-16 10:42:18 -07:00
loc := common.BigToHash(stack.pop())
val := stack.pop()
statedb.SetState(context.Address(), loc, val)
2015-01-19 02:18:34 -08:00
2015-03-16 10:42:18 -07:00
self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
2015-01-19 02:18:34 -08:00
case JUMP:
2015-03-27 08:09:57 -07:00
if err := jump(pc, stack.pop()); err != nil {
return nil, err
}
2015-01-19 02:18:34 -08:00
continue
case JUMPI:
2015-03-09 16:25:27 -07:00
pos, cond := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
2015-03-16 03:27:38 -07:00
if cond.Cmp(common.BigTrue) >= 0 {
2015-03-27 08:09:57 -07:00
if err := jump(pc, pos); err != nil {
return nil, err
}
2015-01-19 02:18:34 -08:00
continue
}
self.Printf(" ~> false")
2015-01-19 02:18:34 -08:00
case JUMPDEST:
case PC:
//stack.push(big.NewInt(int64(pc)))
stack.push(pc)
2015-01-19 02:18:34 -08:00
case MSIZE:
2015-03-09 16:25:27 -07:00
stack.push(big.NewInt(int64(mem.Len())))
2015-01-19 02:18:34 -08:00
case GAS:
2015-03-09 16:25:27 -07:00
stack.push(context.Gas)
2015-02-04 07:39:02 -08:00
self.Printf(" => %x", context.Gas)
2015-01-19 02:18:34 -08:00
// 0x60 range
case CREATE:
var (
2015-03-09 16:25:27 -07:00
value = stack.pop()
offset, size = stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
input = mem.Get(offset.Int64(), size.Int64())
gas = new(big.Int).Set(context.Gas)
2015-03-16 10:42:18 -07:00
addr common.Address
2015-01-19 02:18:34 -08:00
)
2015-02-04 07:39:02 -08:00
self.Endl()
2015-01-19 02:18:34 -08:00
context.UseGas(context.Gas)
2015-03-24 07:23:16 -07:00
ret, suberr, ref := self.env.Create(context, input, gas, price, value)
2015-01-19 02:18:34 -08:00
if suberr != nil {
2015-03-16 03:27:38 -07:00
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
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()
2015-03-16 10:42:18 -07:00
stack.push(addr.Big())
2015-01-19 02:18:34 -08:00
}
case CALL, CALLCODE:
2015-03-09 16:25:27 -07:00
gas := stack.pop()
// pop gas and value of the stack.
addr, value := stack.pop(), stack.pop()
2015-02-19 02:09:46 -08:00
value = U256(value)
2015-03-09 16:25:27 -07:00
// pop input size and offset
inOffset, inSize := stack.pop(), stack.pop()
// pop return size and offset
retOffset, retSize := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
2015-03-16 10:42:18 -07:00
address := common.BigToAddress(addr)
self.Printf(" => %x", address).Endl()
2015-01-19 02:18:34 -08:00
// Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64())
2015-03-03 02:56:43 -08:00
if len(value.Bytes()) > 0 {
gas.Add(gas, GasStipend)
}
2015-01-19 02:18:34 -08:00
var (
ret []byte
err error
)
if op == CALLCODE {
ret, err = self.env.CallCode(context, address, args, gas, price, value)
2015-01-19 02:18:34 -08:00
} else {
ret, err = self.env.Call(context, address, args, gas, price, value)
2015-01-19 02:18:34 -08:00
}
if err != nil {
2015-03-16 03:27:38 -07:00
stack.push(common.BigFalse)
2015-01-19 02:18:34 -08:00
2015-03-11 08:36:10 -07:00
self.Printf("%v").Endl()
2015-01-19 02:18:34 -08:00
} else {
2015-03-16 03:27:38 -07:00
stack.push(common.BigTrue)
2015-01-19 02:18:34 -08:00
mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
self.Printf("resume %x (%v)", context.Address(), context.Gas)
case RETURN:
2015-03-09 16:25:27 -07:00
offset, size := stack.pop(), stack.pop()
2015-01-19 02:18:34 -08:00
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:
2015-03-16 10:42:18 -07:00
receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop()))
2015-01-19 02:18:34 -08:00
balance := statedb.GetBalance(context.Address())
2015-03-16 10:42:18 -07:00
self.Printf(" => (%x) %v", receiver.Address().Bytes()[:4], balance)
2015-01-19 02:18:34 -08:00
receiver.AddBalance(balance)
2015-03-09 03:28:35 -07:00
2015-01-19 02:18:34 -08:00
statedb.Delete(context.Address())
fallthrough
case STOP: // Stop the context
self.Endl()
return context.Return(nil), nil
default:
2015-03-11 08:36:10 -07:00
self.Printf("(pc) %-3v Invalid opcode %x\n", pc, op).Endl()
2015-01-19 02:18:34 -08:00
2015-03-27 08:09:57 -07:00
return nil, fmt.Errorf("Invalid opcode %x", op)
2015-01-19 02:18:34 -08:00
}
pc.Add(pc, One)
2015-01-19 02:18:34 -08:00
self.Endl()
}
}
2015-03-27 08:09:57 -07:00
func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int, error) {
2015-03-02 07:32:02 -08:00
var (
gas = new(big.Int)
newMemSize *big.Int = new(big.Int)
)
2015-03-27 08:09:57 -07:00
err := baseCheck(op, stack, gas)
if err != nil {
return nil, nil, err
}
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
// stack Check, memory resize & gas phase
2015-01-19 02:18:34 -08:00
switch op {
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2)
2015-03-27 08:09:57 -07:00
err := stack.require(n)
if err != nil {
return nil, nil, err
}
2015-03-03 02:11:11 -08:00
gas.Set(GasFastestStep)
2015-01-19 02:18:34 -08:00
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
n := int(op - DUP1 + 1)
2015-03-27 08:09:57 -07:00
err := stack.require(n)
if err != nil {
return nil, nil, err
}
2015-03-03 02:11:11 -08:00
gas.Set(GasFastestStep)
2015-01-19 02:18:34 -08:00
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
2015-03-27 08:09:57 -07:00
err := stack.require(n + 2)
if err != nil {
return nil, nil, err
}
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
2015-03-02 07:32:02 -08:00
gas.Add(gas, GasLogBase)
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic))
2015-03-03 02:11:11 -08:00
gas.Add(gas, new(big.Int).Mul(mSize, GasLogByte))
2015-01-19 02:18:34 -08:00
newMemSize = calcMemSize(mStart, mSize)
case EXP:
2015-03-09 16:25:27 -07:00
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), GasExpByte))
2015-01-19 02:18:34 -08:00
case SSTORE:
2015-03-27 08:09:57 -07:00
err := stack.require(2)
if err != nil {
return nil, nil, err
}
2015-01-19 02:18:34 -08:00
2015-03-02 07:32:02 -08:00
var g *big.Int
2015-03-09 16:25:27 -07:00
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
2015-03-16 10:42:18 -07:00
val := statedb.GetState(context.Address(), common.BigToHash(x))
2015-01-19 02:18:34 -08:00
if len(val) == 0 && len(y.Bytes()) > 0 {
// 0 => non 0
2015-03-02 07:32:02 -08:00
g = GasStorageAdd
2015-01-19 02:18:34 -08:00
} else if len(val) > 0 && len(y.Bytes()) == 0 {
2015-03-02 07:32:02 -08:00
statedb.Refund(self.env.Origin(), RefundStorage)
2015-01-19 02:18:34 -08:00
2015-03-02 07:32:02 -08:00
g = GasStorageMod
2015-01-19 02:18:34 -08:00
} else {
// non 0 => non 0 (or 0 => 0)
2015-03-02 07:32:02 -08:00
g = GasStorageMod
2015-01-19 02:18:34 -08:00
}
2015-03-02 07:32:02 -08:00
gas.Set(g)
2015-03-09 03:28:35 -07:00
case SUICIDE:
if !statedb.IsDeleted(context.Address()) {
statedb.Refund(self.env.Origin(), RefundSuicide)
}
2015-01-19 02:18:34 -08:00
case MLOAD:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.peek(), u256(32))
2015-01-19 02:18:34 -08:00
case MSTORE8:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.peek(), u256(1))
2015-03-02 08:55:45 -08:00
case MSTORE:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.peek(), u256(32))
2015-01-19 02:18:34 -08:00
case RETURN:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
2015-01-19 02:18:34 -08:00
case SHA3:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
words := toWordSize(stack.data[stack.len()-2])
2015-03-02 07:32:02 -08:00
gas.Add(gas, words.Mul(words, GasSha3Word))
case CALLDATACOPY:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
words := toWordSize(stack.data[stack.len()-3])
2015-03-02 07:32:02 -08:00
gas.Add(gas, words.Mul(words, GasCopyWord))
case CODECOPY:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
words := toWordSize(stack.data[stack.len()-3])
2015-03-02 07:32:02 -08:00
gas.Add(gas, words.Mul(words, GasCopyWord))
case EXTCODECOPY:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
2015-03-02 07:32:02 -08:00
2015-03-09 16:25:27 -07:00
words := toWordSize(stack.data[stack.len()-4])
2015-03-02 07:32:02 -08:00
gas.Add(gas, words.Mul(words, GasCopyWord))
2015-03-03 04:29:52 -08:00
2015-03-02 07:32:02 -08:00
case CREATE:
2015-03-09 16:25:27 -07:00
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
2015-01-19 02:18:34 -08:00
case CALL, CALLCODE:
2015-03-09 16:25:27 -07:00
gas.Add(gas, stack.data[stack.len()-1])
2015-03-02 07:32:02 -08:00
if op == CALL {
2015-03-16 10:42:18 -07:00
if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
2015-03-02 07:32:02 -08:00
gas.Add(gas, GasCallNewAccount)
}
2015-03-03 04:29:52 -08:00
}
2015-03-02 07:32:02 -08:00
2015-03-09 16:25:27 -07:00
if len(stack.data[stack.len()-3].Bytes()) > 0 {
2015-03-03 04:29:52 -08:00
gas.Add(gas, GasCallValueTransfer)
2015-03-02 07:32:02 -08:00
}
2015-01-19 02:18:34 -08:00
2015-03-09 16:25:27 -07:00
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
2015-01-19 02:18:34 -08:00
2015-03-16 03:27:38 -07:00
newMemSize = common.BigMax(x, y)
2015-01-19 02:18:34 -08:00
}
2015-03-16 03:27:38 -07:00
if newMemSize.Cmp(common.Big0) > 0 {
2015-03-03 02:56:43 -08:00
newMemSizeWords := toWordSize(newMemSize)
newMemSize.Mul(newMemSizeWords, u256(32))
2015-01-19 02:18:34 -08:00
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
2015-03-03 02:11:11 -08:00
oldSize := toWordSize(big.NewInt(int64(mem.Len())))
2015-03-16 03:27:38 -07:00
pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
2015-03-03 02:11:11 -08:00
linCoef := new(big.Int).Mul(oldSize, GasMemWord)
quadCoef := new(big.Int).Div(pow, GasQuadCoeffDenom)
oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
2015-03-16 03:27:38 -07:00
pow.Exp(newMemSizeWords, common.Big2, Zero)
2015-03-03 02:56:43 -08:00
linCoef = new(big.Int).Mul(newMemSizeWords, GasMemWord)
2015-03-03 02:11:11 -08:00
quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom)
newTotalFee := new(big.Int).Add(linCoef, quadCoef)
fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
gas.Add(gas, fee)
2015-01-19 02:18:34 -08:00
}
}
2015-01-19 02:18:34 -08:00
2015-03-27 08:09:57 -07:00
return newMemSize, gas, nil
2014-09-14 16:11:01 -07:00
}
2015-01-19 02:18:34 -08:00
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)
2015-03-27 08:09:57 -07:00
return nil, OOG(gas, tmp)
2015-01-19 02:18:34 -08:00
}
}
2015-01-19 02:18:34 -08:00
func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine {
if self.debug {
if self.logTy == LogTyPretty {
self.logStr += fmt.Sprintf(format, v...)
}
2015-01-19 02:18:34 -08:00
}
return self
}
2015-01-19 02:18:34 -08:00
func (self *Vm) Endl() VirtualMachine {
if self.debug {
if self.logTy == LogTyPretty {
2015-03-11 08:36:10 -07:00
vmlogger.Infoln(self.logStr)
self.logStr = ""
}
2015-01-19 02:18:34 -08:00
}
return self
2014-09-19 04:19:19 -07:00
}
2014-10-14 04:37:26 -07:00
2015-01-19 02:18:34 -08:00
func (self *Vm) Env() Environment {
return self.env
}