Official Go implementation of the Ethereum protocol
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-ethereum/core/vm/vm.go

913 lines
21 KiB

10 years ago
package vm
10 years ago
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
10 years ago
"github.com/ethereum/go-ethereum/crypto"
10 years ago
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
10 years ago
)
type log struct {
op OpCode
gas *big.Int
memory []byte
stack []*big.Int
}
type Vm struct {
10 years ago
env Environment
// structured logging
Logs []log
10 years ago
logStr string
err error
// For logging
debug bool
10 years ago
BreakPoints []int64
Stepping bool
Fn string
Recoverable bool
10 years ago
// Will be called before the vm returns
After func(*Context, error)
10 years ago
}
10 years ago
func New(env Environment) *Vm {
return &Vm{env: env, Recoverable: true}
10 years ago
}
func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
10 years ago
self.env.SetDepth(self.env.Depth() + 1)
10 years ago
defer self.env.SetDepth(self.env.Depth() - 1)
var (
caller = context.caller
code = context.Code
value = context.value
price = context.Price
)
10 years ago
10 years ago
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()
10 years ago
10 years ago
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
defer func() {
10 years ago
if self.After != nil {
self.After(context, err)
}
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)
}
}()
10 years ago
10 years ago
if context.CodeAddr != nil {
if p := Precompiled[context.CodeAddr.Str()]; p != nil {
return self.RunPrecompiled(p, callData, context)
}
10 years ago
}
// Don't bother with the execution if there's no code.
if len(code) == 0 {
return context.Return(nil), nil
}
10 years ago
var (
op OpCode
codehash = crypto.Sha3Hash(code)
mem = NewMemory()
stack = newStack()
pc = uint64(0)
statedb = self.env.State()
jump = func(from uint64, to *big.Int) error {
if !context.jumpdests.has(codehash, code, to) {
nop := context.GetOp(to.Uint64())
return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
10 years ago
}
self.Printf(" ~> %v", to)
pc = to.Uint64()
10 years ago
self.Endl()
return nil
10 years ago
}
)
for {
// The base for all big integer arithmetic
base := new(big.Int)
// Get the memory location of pc
op = context.GetOp(pc)
self.Log(op, context.Gas, mem, stack)
10 years ago
self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.len())
newMemSize, gas, err := self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
if err != nil {
return nil, err
}
10 years ago
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 {
case ADD:
10 years ago
x, y := stack.pop(), stack.pop()
10 years ago
self.Printf(" %v + %v", y, x)
10 years ago
base.Add(x, y)
10 years ago
U256(base)
self.Printf(" = %v", base)
10 years ago
// pop result back on the stack
stack.push(base)
10 years ago
case SUB:
10 years ago
x, y := stack.pop(), stack.pop()
self.Printf(" %v - %v", x, y)
10 years ago
10 years ago
base.Sub(x, y)
10 years ago
U256(base)
self.Printf(" = %v", base)
10 years ago
// pop result back on the stack
stack.push(base)
10 years ago
case MUL:
10 years ago
x, y := stack.pop(), stack.pop()
10 years ago
self.Printf(" %v * %v", y, x)
10 years ago
base.Mul(x, y)
10 years ago
U256(base)
self.Printf(" = %v", base)
10 years ago
// pop result back on the stack
stack.push(base)
10 years ago
case DIV:
10 years ago
x, y := stack.pop(), stack.pop()
10 years ago
self.Printf(" %v / %v", x, y)
if y.Cmp(common.Big0) != 0 {
10 years ago
base.Div(x, y)
}
U256(base)
self.Printf(" = %v", base)
10 years ago
// pop result back on the stack
stack.push(base)
10 years ago
case SDIV:
10 years ago
x, y := S256(stack.pop()), S256(stack.pop())
10 years ago
self.Printf(" %v / %v", x, y)
if y.Cmp(common.Big0) == 0 {
base.Set(common.Big0)
10 years ago
} else {
n := new(big.Int)
if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
10 years ago
n.SetInt64(-1)
} else {
n.SetInt64(1)
}
base.Div(x.Abs(x), y.Abs(y)).Mul(base, n)
U256(base)
}
self.Printf(" = %v", base)
10 years ago
stack.push(base)
10 years ago
case MOD:
10 years ago
x, y := stack.pop(), stack.pop()
10 years ago
self.Printf(" %v %% %v", x, y)
if y.Cmp(common.Big0) == 0 {
base.Set(common.Big0)
10 years ago
} else {
base.Mod(x, y)
}
U256(base)
self.Printf(" = %v", base)
10 years ago
stack.push(base)
10 years ago
case SMOD:
10 years ago
x, y := S256(stack.pop()), S256(stack.pop())
10 years ago
self.Printf(" %v %% %v", x, y)
if y.Cmp(common.Big0) == 0 {
base.Set(common.Big0)
10 years ago
} else {
n := new(big.Int)
if x.Cmp(common.Big0) < 0 {
10 years ago
n.SetInt64(-1)
} else {
n.SetInt64(1)
}
base.Mod(x.Abs(x), y.Abs(y)).Mul(base, n)
U256(base)
}
self.Printf(" = %v", base)
10 years ago
stack.push(base)
10 years ago
case EXP:
10 years ago
x, y := stack.pop(), stack.pop()
10 years ago
10 years ago
self.Printf(" %v ** %v", x, y)
10 years ago
10 years ago
base.Exp(x, y, Pow256)
10 years ago
U256(base)
self.Printf(" = %v", base)
10 years ago
stack.push(base)
10 years ago
case SIGNEXTEND:
10 years ago
back := stack.pop()
if back.Cmp(big.NewInt(31)) < 0 {
bit := uint(back.Uint64()*8 + 7)
10 years ago
num := stack.pop()
mask := new(big.Int).Lsh(common.Big1, bit)
mask.Sub(mask, common.Big1)
if common.BitTest(num, int(bit)) {
10 years ago
num.Or(num, mask.Not(mask))
} else {
num.And(num, mask)
}
num = U256(num)
self.Printf(" = %v", num)
10 years ago
stack.push(num)
10 years ago
}
case NOT:
stack.push(U256(new(big.Int).Not(stack.pop())))
10 years ago
case LT:
10 years ago
x, y := stack.pop(), stack.pop()
self.Printf(" %v < %v", x, y)
10 years ago
// x < y
10 years ago
if x.Cmp(y) < 0 {
stack.push(common.BigTrue)
10 years ago
} else {
stack.push(common.BigFalse)
10 years ago
}
case GT:
10 years ago
x, y := stack.pop(), stack.pop()
self.Printf(" %v > %v", x, y)
10 years ago
// x > y
10 years ago
if x.Cmp(y) > 0 {
stack.push(common.BigTrue)
10 years ago
} else {
stack.push(common.BigFalse)
10 years ago
}
case SLT:
10 years ago
x, y := S256(stack.pop()), S256(stack.pop())
self.Printf(" %v < %v", x, y)
10 years ago
// x < y
10 years ago
if x.Cmp(S256(y)) < 0 {
stack.push(common.BigTrue)
10 years ago
} else {
stack.push(common.BigFalse)
10 years ago
}
case SGT:
10 years ago
x, y := S256(stack.pop()), S256(stack.pop())
self.Printf(" %v > %v", x, y)
10 years ago
// x > y
10 years ago
if x.Cmp(y) > 0 {
stack.push(common.BigTrue)
10 years ago
} else {
stack.push(common.BigFalse)
10 years ago
}
case EQ:
10 years ago
x, y := stack.pop(), stack.pop()
10 years ago
self.Printf(" %v == %v", y, x)
// x == y
if x.Cmp(y) == 0 {
stack.push(common.BigTrue)
10 years ago
} else {
stack.push(common.BigFalse)
10 years ago
}
case ISZERO:
10 years ago
x := stack.pop()
if x.Cmp(common.BigFalse) > 0 {
stack.push(common.BigFalse)
10 years ago
} else {
stack.push(common.BigTrue)
10 years ago
}
case AND:
10 years ago
x, y := stack.pop(), stack.pop()
10 years ago
self.Printf(" %v & %v", y, x)
10 years ago
stack.push(base.And(x, y))
10 years ago
case OR:
10 years ago
x, y := stack.pop(), stack.pop()
self.Printf(" %v | %v", x, y)
10 years ago
10 years ago
stack.push(base.Or(x, y))
10 years ago
case XOR:
10 years ago
x, y := stack.pop(), stack.pop()
self.Printf(" %v ^ %v", x, y)
10 years ago
10 years ago
stack.push(base.Xor(x, y))
10 years ago
case BYTE:
10 years ago
th, val := stack.pop(), stack.pop()
10 years ago
if th.Cmp(big.NewInt(32)) < 0 {
byt := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
10 years ago
base.Set(byt)
} else {
base.Set(common.BigFalse)
10 years ago
}
self.Printf(" => 0x%x", base.Bytes())
10 years ago
stack.push(base)
10 years ago
case ADDMOD:
10 years ago
x := stack.pop()
y := stack.pop()
z := stack.pop()
10 years ago
if z.Cmp(Zero) > 0 {
add := new(big.Int).Add(x, y)
10 years ago
base.Mod(add, z)
base = U256(base)
10 years ago
}
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
10 years ago
stack.push(base)
10 years ago
case MULMOD:
10 years ago
x := stack.pop()
y := stack.pop()
z := stack.pop()
10 years ago
if z.Cmp(Zero) > 0 {
mul := new(big.Int).Mul(x, y)
10 years ago
base.Mod(mul, z)
U256(base)
}
self.Printf(" %v + %v %% %v = %v", x, y, z, base)
10 years ago
stack.push(base)
10 years ago
case SHA3:
offset, size := stack.pop(), stack.pop()
10 years ago
data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64()))
stack.push(common.BigD(data))
10 years ago
self.Printf(" => (%v) %x", size, data)
10 years ago
case ADDRESS:
10 years ago
stack.push(common.Bytes2Big(context.Address().Bytes()))
10 years ago
self.Printf(" => %x", context.Address())
case BALANCE:
10 years ago
addr := common.BigToAddress(stack.pop())
balance := statedb.GetBalance(addr)
10 years ago
10 years ago
stack.push(balance)
10 years ago
self.Printf(" => %v (%x)", balance, addr)
case ORIGIN:
origin := self.env.Origin()
10 years ago
stack.push(origin.Big())
10 years ago
self.Printf(" => %x", origin)
case CALLER:
caller := context.caller.Address()
10 years ago
stack.push(common.Bytes2Big(caller.Bytes()))
10 years ago
self.Printf(" => %x", caller)
case CALLVALUE:
10 years ago
stack.push(value)
10 years ago
self.Printf(" => %v", value)
case CALLDATALOAD:
data := getData(callData, stack.pop(), common.Big32)
10 years ago
self.Printf(" => 0x%x", data)
stack.push(common.Bytes2Big(data))
10 years ago
case CALLDATASIZE:
l := int64(len(callData))
10 years ago
stack.push(big.NewInt(l))
10 years ago
self.Printf(" => %d", l)
case CALLDATACOPY:
var (
mOff = stack.pop()
cOff = stack.pop()
l = stack.pop()
10 years ago
)
data := getData(callData, cOff, l)
10 years ago
mem.Set(mOff.Uint64(), l.Uint64(), data)
10 years ago
self.Printf(" => [%v, %v, %v]", mOff, cOff, l)
10 years ago
case CODESIZE, EXTCODESIZE:
var code []byte
if op == EXTCODESIZE {
10 years ago
addr := common.BigToAddress(stack.pop())
10 years ago
code = statedb.GetCode(addr)
} else {
code = context.Code
}
l := big.NewInt(int64(len(code)))
10 years ago
stack.push(l)
10 years ago
self.Printf(" => %d", l)
case CODECOPY, EXTCODECOPY:
var code []byte
if op == EXTCODECOPY {
10 years ago
addr := common.BigToAddress(stack.pop())
code = statedb.GetCode(addr)
10 years ago
} else {
code = context.Code
}
10 years ago
var (
mOff = stack.pop()
cOff = stack.pop()
l = stack.pop()
10 years ago
)
codeCopy := getData(code, cOff, l)
mem.Set(mOff.Uint64(), l.Uint64(), codeCopy)
10 years ago
self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, codeCopy)
case GASPRICE:
10 years ago
stack.push(context.Price)
10 years ago
10 years ago
self.Printf(" => %x", context.Price)
10 years ago
case BLOCKHASH:
10 years ago
num := stack.pop()
10 years ago
n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257)
10 years ago
if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
10 years ago
stack.push(self.env.GetHash(num.Uint64()).Big())
10 years ago
} else {
stack.push(common.Big0)
10 years ago
}
10 years ago
self.Printf(" => 0x%x", stack.peek().Bytes())
10 years ago
case COINBASE:
coinbase := self.env.Coinbase()
10 years ago
stack.push(coinbase.Big())
10 years ago
self.Printf(" => 0x%x", coinbase)
case TIMESTAMP:
time := self.env.Time()
10 years ago
stack.push(big.NewInt(time))
10 years ago
self.Printf(" => 0x%x", time)
case NUMBER:
number := self.env.BlockNumber()
10 years ago
stack.push(U256(number))
10 years ago
self.Printf(" => 0x%x", number.Bytes())
case DIFFICULTY:
difficulty := self.env.Difficulty()
10 years ago
stack.push(difficulty)
10 years ago
self.Printf(" => 0x%x", difficulty.Bytes())
case GASLIMIT:
self.Printf(" => %v", self.env.GasLimit())
10 years ago
stack.push(self.env.GasLimit())
10 years ago
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:
size := uint64(op - PUSH1 + 1)
byts := getData(code, new(big.Int).SetUint64(pc+1), new(big.Int).SetUint64(size))
10 years ago
// push value to stack
stack.push(common.Bytes2Big(byts))
pc += size
10 years ago
self.Printf(" => 0x%x", byts)
case POP:
10 years ago
stack.pop()
10 years ago
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
n := int(op - DUP1 + 1)
10 years ago
stack.dup(n)
10 years ago
10 years ago
self.Printf(" => [%d] 0x%x", n, stack.peek().Bytes())
10 years ago
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2)
10 years ago
stack.swap(n)
10 years ago
10 years ago
self.Printf(" => [%d]", n)
10 years ago
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
10 years ago
topics := make([]common.Hash, n)
10 years ago
mStart, mSize := stack.pop(), stack.pop()
10 years ago
for i := 0; i < n; i++ {
topics[i] = common.BigToHash(stack.pop())
10 years ago
}
data := mem.Get(mStart.Int64(), mSize.Int64())
log := state.NewLog(context.Address(), topics, data, self.env.BlockNumber().Uint64())
10 years ago
self.env.AddLog(log)
self.Printf(" => %v", log)
case MLOAD:
10 years ago
offset := stack.pop()
val := common.BigD(mem.Get(offset.Int64(), 32))
10 years ago
stack.push(val)
10 years ago
self.Printf(" => 0x%x", val.Bytes())
case MSTORE:
10 years ago
// pop value of the stack
mStart, val := stack.pop(), stack.pop()
mem.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
10 years ago
self.Printf(" => 0x%x", val)
case MSTORE8:
off, val := stack.pop().Int64(), stack.pop().Int64()
10 years ago
mem.store[off] = byte(val & 0xff)
10 years ago
self.Printf(" => [%v] 0x%x", off, mem.store[off])
10 years ago
case SLOAD:
10 years ago
loc := common.BigToHash(stack.pop())
val := common.Bytes2Big(statedb.GetState(context.Address(), loc))
10 years ago
stack.push(val)
10 years ago
10 years ago
self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
10 years ago
case SSTORE:
10 years ago
loc := common.BigToHash(stack.pop())
val := stack.pop()
statedb.SetState(context.Address(), loc, val)
10 years ago
10 years ago
self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
10 years ago
case JUMP:
if err := jump(pc, stack.pop()); err != nil {
return nil, err
}
10 years ago
continue
case JUMPI:
10 years ago
pos, cond := stack.pop(), stack.pop()
10 years ago
if cond.Cmp(common.BigTrue) >= 0 {
if err := jump(pc, pos); err != nil {
return nil, err
}
10 years ago
continue
}
self.Printf(" ~> false")
10 years ago
case JUMPDEST:
case PC:
stack.push(new(big.Int).SetUint64(pc))
10 years ago
case MSIZE:
10 years ago
stack.push(big.NewInt(int64(mem.Len())))
10 years ago
case GAS:
10 years ago
stack.push(context.Gas)
10 years ago
self.Printf(" => %x", context.Gas)
10 years ago
case CREATE:
var (
10 years ago
value = stack.pop()
offset, size = stack.pop(), stack.pop()
10 years ago
input = mem.Get(offset.Int64(), size.Int64())
gas = new(big.Int).Set(context.Gas)
10 years ago
addr common.Address
10 years ago
)
10 years ago
self.Endl()
10 years ago
context.UseGas(context.Gas)
ret, suberr, ref := self.env.Create(context, input, gas, price, value)
10 years ago
if suberr != nil {
stack.push(common.BigFalse)
10 years ago
self.Printf(" (*) 0x0 %v", suberr)
} else {
// gas < len(ret) * CreateDataGas == NO_CODE
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, params.CreateDataGas)
10 years ago
if context.UseGas(dataGas) {
ref.SetCode(ret)
}
addr = ref.Address()
10 years ago
stack.push(addr.Big())
10 years ago
}
case CALL, CALLCODE:
10 years ago
gas := stack.pop()
// pop gas and value of the stack.
addr, value := stack.pop(), stack.pop()
10 years ago
value = U256(value)
10 years ago
// pop input size and offset
inOffset, inSize := stack.pop(), stack.pop()
// pop return size and offset
retOffset, retSize := stack.pop(), stack.pop()
10 years ago
10 years ago
address := common.BigToAddress(addr)
self.Printf(" => %x", address).Endl()
10 years ago
// Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64())
if len(value.Bytes()) > 0 {
gas.Add(gas, params.CallStipend)
}
10 years ago
var (
ret []byte
err error
)
if op == CALLCODE {
ret, err = self.env.CallCode(context, address, args, gas, price, value)
10 years ago
} else {
ret, err = self.env.Call(context, address, args, gas, price, value)
10 years ago
}
if err != nil {
stack.push(common.BigFalse)
10 years ago
self.Printf("%v").Endl()
10 years ago
} else {
stack.push(common.BigTrue)
10 years ago
mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
self.Printf("resume %x (%v)", context.Address(), context.Gas)
case RETURN:
10 years ago
offset, size := stack.pop(), stack.pop()
ret := mem.GetPtr(offset.Int64(), size.Int64())
10 years ago
self.Printf(" => [%v, %v] (%d) 0x%x", offset, size, len(ret), ret).Endl()
return context.Return(ret), nil
case SUICIDE:
10 years ago
receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop()))
10 years ago
balance := statedb.GetBalance(context.Address())
10 years ago
self.Printf(" => (%x) %v", receiver.Address().Bytes()[:4], balance)
10 years ago
receiver.AddBalance(balance)
10 years ago
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()
10 years ago
return nil, fmt.Errorf("Invalid opcode %x", op)
10 years ago
}
pc++
10 years ago
self.Endl()
}
}
func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int, error) {
var (
gas = new(big.Int)
newMemSize *big.Int = new(big.Int)
)
err := baseCheck(op, stack, gas)
if err != nil {
return nil, nil, err
}
10 years ago
10 years ago
// stack Check, memory resize & gas phase
10 years ago
switch op {
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2)
err := stack.require(n)
if err != nil {
return nil, nil, err
}
10 years ago
gas.Set(GasFastestStep)
10 years ago
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
n := int(op - DUP1 + 1)
err := stack.require(n)
if err != nil {
return nil, nil, err
}
10 years ago
gas.Set(GasFastestStep)
10 years ago
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
err := stack.require(n + 2)
if err != nil {
return nil, nil, err
}
10 years ago
10 years ago
mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
gas.Add(gas, params.LogGas)
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas))
gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
10 years ago
newMemSize = calcMemSize(mStart, mSize)
case EXP:
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
10 years ago
case SSTORE:
err := stack.require(2)
if err != nil {
return nil, nil, err
}
10 years ago
var g *big.Int
10 years ago
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
10 years ago
val := statedb.GetState(context.Address(), common.BigToHash(x))
10 years ago
if len(val) == 0 && len(y.Bytes()) > 0 {
// 0 => non 0
g = params.SstoreSetGas
10 years ago
} else if len(val) > 0 && len(y.Bytes()) == 0 {
statedb.Refund(self.env.Origin(), params.SstoreRefundGas)
10 years ago
g = params.SstoreClearGas
10 years ago
} else {
// non 0 => non 0 (or 0 => 0)
g = params.SstoreClearGas
10 years ago
}
gas.Set(g)
case SUICIDE:
if !statedb.IsDeleted(context.Address()) {
statedb.Refund(self.env.Origin(), params.SuicideRefundGas)
}
10 years ago
case MLOAD:
10 years ago
newMemSize = calcMemSize(stack.peek(), u256(32))
10 years ago
case MSTORE8:
10 years ago
newMemSize = calcMemSize(stack.peek(), u256(1))
10 years ago
case MSTORE:
10 years ago
newMemSize = calcMemSize(stack.peek(), u256(32))
10 years ago
case RETURN:
10 years ago
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
10 years ago
case SHA3:
10 years ago
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
10 years ago
10 years ago
words := toWordSize(stack.data[stack.len()-2])
gas.Add(gas, words.Mul(words, params.Sha3WordGas))
case CALLDATACOPY:
10 years ago
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
10 years ago
10 years ago
words := toWordSize(stack.data[stack.len()-3])
gas.Add(gas, words.Mul(words, params.CopyGas))
case CODECOPY:
10 years ago
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
10 years ago
10 years ago
words := toWordSize(stack.data[stack.len()-3])
gas.Add(gas, words.Mul(words, params.CopyGas))
case EXTCODECOPY:
10 years ago
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
10 years ago
words := toWordSize(stack.data[stack.len()-4])
gas.Add(gas, words.Mul(words, params.CopyGas))
case CREATE:
10 years ago
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
10 years ago
case CALL, CALLCODE:
10 years ago
gas.Add(gas, stack.data[stack.len()-1])
if op == CALL {
10 years ago
if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
gas.Add(gas, params.CallNewAccountGas)
}
}
10 years ago
if len(stack.data[stack.len()-3].Bytes()) > 0 {
gas.Add(gas, params.CallValueTransferGas)
}
10 years ago
10 years ago
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
10 years ago
newMemSize = common.BigMax(x, y)
10 years ago
}
if newMemSize.Cmp(common.Big0) > 0 {
newMemSizeWords := toWordSize(newMemSize)
newMemSize.Mul(newMemSizeWords, u256(32))
10 years ago
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
10 years ago
oldSize := toWordSize(big.NewInt(int64(mem.Len())))
pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
linCoef := new(big.Int).Mul(oldSize, params.MemoryGas)
quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv)
10 years ago
oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
pow.Exp(newMemSizeWords, common.Big2, Zero)
linCoef = new(big.Int).Mul(newMemSizeWords, params.MemoryGas)
quadCoef = new(big.Int).Div(pow, params.QuadCoeffDiv)
10 years ago
newTotalFee := new(big.Int).Add(linCoef, quadCoef)
fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
gas.Add(gas, fee)
10 years ago
}
}
10 years ago
return newMemSize, gas, nil
10 years ago
}
func (vm *Vm) Log(op OpCode, gas *big.Int, memory *Memory, stack *stack) {
if vm.debug {
mem := make([]byte, len(memory.store))
copy(mem, memory.store)
stck := make([]*big.Int, len(stack.data))
copy(stck, stack.data)
vm.Logs = append(vm.Logs, log{op, new(big.Int).Set(gas), mem, stck})
}
}
10 years ago
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)
return nil, OOG(gas, tmp)
10 years ago
}
}
10 years ago
func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine {
if self.debug {
10 years ago
self.logStr += fmt.Sprintf(format, v...)
10 years ago
}
return self
}
10 years ago
func (self *Vm) Endl() VirtualMachine {
if self.debug {
10 years ago
glog.V(0).Infoln(self.logStr)
self.logStr = ""
10 years ago
}
return self
10 years ago
}
10 years ago
func (self *Vm) Env() Environment {
return self.env
}