|
|
@ -21,11 +21,10 @@ var ( |
|
|
|
GasTx = big.NewInt(500) |
|
|
|
GasTx = big.NewInt(500) |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
func CalculateTxGas(initSize, scriptSize *big.Int) *big.Int { |
|
|
|
func CalculateTxGas(initSize *big.Int) *big.Int { |
|
|
|
totalGas := new(big.Int) |
|
|
|
totalGas := new(big.Int) |
|
|
|
totalGas.Add(totalGas, GasCreate) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
txTotalBytes := new(big.Int).Add(initSize, scriptSize) |
|
|
|
txTotalBytes := new(big.Int).Set(initSize) |
|
|
|
txTotalBytes.Div(txTotalBytes, ethutil.Big32) |
|
|
|
txTotalBytes.Div(txTotalBytes, ethutil.Big32) |
|
|
|
totalGas.Add(totalGas, new(big.Int).Mul(txTotalBytes, GasSStore)) |
|
|
|
totalGas.Add(totalGas, new(big.Int).Mul(txTotalBytes, GasSStore)) |
|
|
|
|
|
|
|
|
|
|
@ -92,12 +91,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
pc := big.NewInt(0) |
|
|
|
pc := big.NewInt(0) |
|
|
|
// Current step count
|
|
|
|
// Current step count
|
|
|
|
step := 0 |
|
|
|
step := 0 |
|
|
|
|
|
|
|
prevStep := 0 |
|
|
|
|
|
|
|
|
|
|
|
if ethutil.Config.Debug { |
|
|
|
if ethutil.Config.Debug { |
|
|
|
ethutil.Config.Log.Debugf("# op\n") |
|
|
|
ethutil.Config.Log.Debugf("# op\n") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for { |
|
|
|
for { |
|
|
|
|
|
|
|
prevStep = step |
|
|
|
// The base for all big integer arithmetic
|
|
|
|
// The base for all big integer arithmetic
|
|
|
|
base := new(big.Int) |
|
|
|
base := new(big.Int) |
|
|
|
|
|
|
|
|
|
|
@ -111,16 +112,16 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gas := new(big.Int) |
|
|
|
gas := new(big.Int) |
|
|
|
useGas := func(amount *big.Int) { |
|
|
|
setStepGasUsage := func(amount *big.Int) { |
|
|
|
gas.Add(gas, amount) |
|
|
|
gas.Add(gas, amount) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch op { |
|
|
|
switch op { |
|
|
|
case oSHA3: |
|
|
|
case SHA3: |
|
|
|
useGas(GasSha) |
|
|
|
setStepGasUsage(GasSha) |
|
|
|
case oSLOAD: |
|
|
|
case SLOAD: |
|
|
|
useGas(GasSLoad) |
|
|
|
setStepGasUsage(GasSLoad) |
|
|
|
case oSSTORE: |
|
|
|
case SSTORE: |
|
|
|
var mult *big.Int |
|
|
|
var mult *big.Int |
|
|
|
y, x := stack.Peekn() |
|
|
|
y, x := stack.Peekn() |
|
|
|
val := closure.GetMem(x) |
|
|
|
val := closure.GetMem(x) |
|
|
@ -131,67 +132,64 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
mult = ethutil.Big1 |
|
|
|
mult = ethutil.Big1 |
|
|
|
} |
|
|
|
} |
|
|
|
useGas(new(big.Int).Mul(mult, GasSStore)) |
|
|
|
setStepGasUsage(new(big.Int).Mul(mult, GasSStore)) |
|
|
|
case oBALANCE: |
|
|
|
case BALANCE: |
|
|
|
useGas(GasBalance) |
|
|
|
setStepGasUsage(GasBalance) |
|
|
|
case oCREATE: |
|
|
|
case CREATE: |
|
|
|
require(3) |
|
|
|
require(3) |
|
|
|
|
|
|
|
|
|
|
|
args := stack.Get(big.NewInt(3)) |
|
|
|
args := stack.Get(big.NewInt(3)) |
|
|
|
initSize := new(big.Int).Add(args[1], args[0]) |
|
|
|
initSize := new(big.Int).Add(args[1], args[0]) |
|
|
|
|
|
|
|
|
|
|
|
useGas(CalculateTxGas(initSize, ethutil.Big0)) |
|
|
|
setStepGasUsage(CalculateTxGas(initSize)) |
|
|
|
case oCALL: |
|
|
|
case CALL: |
|
|
|
useGas(GasCall) |
|
|
|
setStepGasUsage(GasCall) |
|
|
|
case oMLOAD, oMSIZE, oMSTORE8, oMSTORE: |
|
|
|
case MLOAD, MSIZE, MSTORE8, MSTORE: |
|
|
|
useGas(GasMemory) |
|
|
|
setStepGasUsage(GasMemory) |
|
|
|
default: |
|
|
|
default: |
|
|
|
useGas(GasStep) |
|
|
|
setStepGasUsage(GasStep) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if closure.Gas.Cmp(gas) < 0 { |
|
|
|
if !closure.UseGas(gas) { |
|
|
|
ethutil.Config.Log.Debugln("Insufficient gas", closure.Gas, gas) |
|
|
|
ethutil.Config.Log.Debugln("Insufficient gas", closure.Gas, gas) |
|
|
|
|
|
|
|
|
|
|
|
return closure.Return(nil), fmt.Errorf("insufficient gas %v %v", closure.Gas, gas) |
|
|
|
return closure.Return(nil), fmt.Errorf("insufficient gas %v %v", closure.Gas, gas) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Sub the amount of gas from the remaining
|
|
|
|
|
|
|
|
closure.Gas.Sub(closure.Gas, gas) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch op { |
|
|
|
switch op { |
|
|
|
case oLOG: |
|
|
|
case LOG: |
|
|
|
stack.Print() |
|
|
|
stack.Print() |
|
|
|
mem.Print() |
|
|
|
mem.Print() |
|
|
|
// 0x20 range
|
|
|
|
// 0x20 range
|
|
|
|
case oADD: |
|
|
|
case ADD: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// (x + y) % 2 ** 256
|
|
|
|
// (x + y) % 2 ** 256
|
|
|
|
base.Add(x, y) |
|
|
|
base.Add(x, y) |
|
|
|
// Pop result back on the stack
|
|
|
|
// Pop result back on the stack
|
|
|
|
stack.Push(base) |
|
|
|
stack.Push(base) |
|
|
|
case oSUB: |
|
|
|
case SUB: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// (x - y) % 2 ** 256
|
|
|
|
// (x - y) % 2 ** 256
|
|
|
|
base.Sub(x, y) |
|
|
|
base.Sub(x, y) |
|
|
|
// Pop result back on the stack
|
|
|
|
// Pop result back on the stack
|
|
|
|
stack.Push(base) |
|
|
|
stack.Push(base) |
|
|
|
case oMUL: |
|
|
|
case MUL: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// (x * y) % 2 ** 256
|
|
|
|
// (x * y) % 2 ** 256
|
|
|
|
base.Mul(x, y) |
|
|
|
base.Mul(x, y) |
|
|
|
// Pop result back on the stack
|
|
|
|
// Pop result back on the stack
|
|
|
|
stack.Push(base) |
|
|
|
stack.Push(base) |
|
|
|
case oDIV: |
|
|
|
case DIV: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// floor(x / y)
|
|
|
|
// floor(x / y)
|
|
|
|
base.Div(x, y) |
|
|
|
base.Div(x, y) |
|
|
|
// Pop result back on the stack
|
|
|
|
// Pop result back on the stack
|
|
|
|
stack.Push(base) |
|
|
|
stack.Push(base) |
|
|
|
case oSDIV: |
|
|
|
case SDIV: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// n > 2**255
|
|
|
|
// n > 2**255
|
|
|
@ -208,12 +206,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} |
|
|
|
} |
|
|
|
// Push result on to the stack
|
|
|
|
// Push result on to the stack
|
|
|
|
stack.Push(z) |
|
|
|
stack.Push(z) |
|
|
|
case oMOD: |
|
|
|
case MOD: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
base.Mod(x, y) |
|
|
|
base.Mod(x, y) |
|
|
|
stack.Push(base) |
|
|
|
stack.Push(base) |
|
|
|
case oSMOD: |
|
|
|
case SMOD: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// n > 2**255
|
|
|
|
// n > 2**255
|
|
|
@ -230,17 +228,17 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} |
|
|
|
} |
|
|
|
// Push result on to the stack
|
|
|
|
// Push result on to the stack
|
|
|
|
stack.Push(z) |
|
|
|
stack.Push(z) |
|
|
|
case oEXP: |
|
|
|
case EXP: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
base.Exp(x, y, Pow256) |
|
|
|
base.Exp(x, y, Pow256) |
|
|
|
|
|
|
|
|
|
|
|
stack.Push(base) |
|
|
|
stack.Push(base) |
|
|
|
case oNEG: |
|
|
|
case NEG: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
base.Sub(Pow256, stack.Pop()) |
|
|
|
base.Sub(Pow256, stack.Pop()) |
|
|
|
stack.Push(base) |
|
|
|
stack.Push(base) |
|
|
|
case oLT: |
|
|
|
case LT: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// x < y
|
|
|
|
// x < y
|
|
|
@ -249,7 +247,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
} |
|
|
|
} |
|
|
|
case oGT: |
|
|
|
case GT: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// x > y
|
|
|
|
// x > y
|
|
|
@ -258,7 +256,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
} |
|
|
|
} |
|
|
|
case oEQ: |
|
|
|
case EQ: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
// x == y
|
|
|
|
// x == y
|
|
|
@ -267,7 +265,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
} |
|
|
|
} |
|
|
|
case oNOT: |
|
|
|
case NOT: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
x := stack.Pop() |
|
|
|
x := stack.Pop() |
|
|
|
if x.Cmp(ethutil.BigFalse) == 0 { |
|
|
|
if x.Cmp(ethutil.BigFalse) == 0 { |
|
|
@ -277,7 +275,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 0x10 range
|
|
|
|
// 0x10 range
|
|
|
|
case oAND: |
|
|
|
case AND: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
if (x.Cmp(ethutil.BigTrue) >= 0) && (y.Cmp(ethutil.BigTrue) >= 0) { |
|
|
|
if (x.Cmp(ethutil.BigTrue) >= 0) && (y.Cmp(ethutil.BigTrue) >= 0) { |
|
|
@ -286,7 +284,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case oOR: |
|
|
|
case OR: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
if (x.Cmp(ethutil.BigInt0) >= 0) || (y.Cmp(ethutil.BigInt0) >= 0) { |
|
|
|
if (x.Cmp(ethutil.BigInt0) >= 0) || (y.Cmp(ethutil.BigInt0) >= 0) { |
|
|
@ -294,11 +292,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
} |
|
|
|
} |
|
|
|
case oXOR: |
|
|
|
case XOR: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
stack.Push(base.Xor(x, y)) |
|
|
|
stack.Push(base.Xor(x, y)) |
|
|
|
case oBYTE: |
|
|
|
case BYTE: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
val, th := stack.Popn() |
|
|
|
val, th := stack.Popn() |
|
|
|
if th.Cmp(big.NewInt(32)) < 0 { |
|
|
|
if th.Cmp(big.NewInt(32)) < 0 { |
|
|
@ -308,92 +306,92 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 0x20 range
|
|
|
|
// 0x20 range
|
|
|
|
case oSHA3: |
|
|
|
case SHA3: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
size, offset := stack.Popn() |
|
|
|
size, offset := stack.Popn() |
|
|
|
data := mem.Get(offset.Int64(), size.Int64()) |
|
|
|
data := mem.Get(offset.Int64(), size.Int64()) |
|
|
|
|
|
|
|
|
|
|
|
stack.Push(ethutil.BigD(data)) |
|
|
|
stack.Push(ethutil.BigD(data)) |
|
|
|
// 0x30 range
|
|
|
|
// 0x30 range
|
|
|
|
case oADDRESS: |
|
|
|
case ADDRESS: |
|
|
|
stack.Push(ethutil.BigD(closure.Object().Address())) |
|
|
|
stack.Push(ethutil.BigD(closure.Object().Address())) |
|
|
|
case oBALANCE: |
|
|
|
case BALANCE: |
|
|
|
stack.Push(closure.object.Amount) |
|
|
|
stack.Push(closure.object.Amount) |
|
|
|
case oORIGIN: |
|
|
|
case ORIGIN: |
|
|
|
stack.Push(ethutil.BigD(vm.vars.Origin)) |
|
|
|
stack.Push(ethutil.BigD(vm.vars.Origin)) |
|
|
|
case oCALLER: |
|
|
|
case CALLER: |
|
|
|
stack.Push(ethutil.BigD(closure.Callee().Address())) |
|
|
|
stack.Push(ethutil.BigD(closure.Callee().Address())) |
|
|
|
case oCALLVALUE: |
|
|
|
case CALLVALUE: |
|
|
|
stack.Push(vm.vars.Value) |
|
|
|
stack.Push(vm.vars.Value) |
|
|
|
case oCALLDATALOAD: |
|
|
|
case CALLDATALOAD: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
offset := stack.Pop().Int64() |
|
|
|
offset := stack.Pop().Int64() |
|
|
|
val := closure.Args[offset : offset+32] |
|
|
|
val := closure.Args[offset : offset+32] |
|
|
|
|
|
|
|
|
|
|
|
stack.Push(ethutil.BigD(val)) |
|
|
|
stack.Push(ethutil.BigD(val)) |
|
|
|
case oCALLDATASIZE: |
|
|
|
case CALLDATASIZE: |
|
|
|
stack.Push(big.NewInt(int64(len(closure.Args)))) |
|
|
|
stack.Push(big.NewInt(int64(len(closure.Args)))) |
|
|
|
case oGASPRICE: |
|
|
|
case GASPRICE: |
|
|
|
stack.Push(closure.Price) |
|
|
|
stack.Push(closure.Price) |
|
|
|
|
|
|
|
|
|
|
|
// 0x40 range
|
|
|
|
// 0x40 range
|
|
|
|
case oPREVHASH: |
|
|
|
case PREVHASH: |
|
|
|
stack.Push(ethutil.BigD(vm.vars.PrevHash)) |
|
|
|
stack.Push(ethutil.BigD(vm.vars.PrevHash)) |
|
|
|
case oCOINBASE: |
|
|
|
case COINBASE: |
|
|
|
stack.Push(ethutil.BigD(vm.vars.Coinbase)) |
|
|
|
stack.Push(ethutil.BigD(vm.vars.Coinbase)) |
|
|
|
case oTIMESTAMP: |
|
|
|
case TIMESTAMP: |
|
|
|
stack.Push(big.NewInt(vm.vars.Time)) |
|
|
|
stack.Push(big.NewInt(vm.vars.Time)) |
|
|
|
case oNUMBER: |
|
|
|
case NUMBER: |
|
|
|
stack.Push(big.NewInt(int64(vm.vars.BlockNumber))) |
|
|
|
stack.Push(big.NewInt(int64(vm.vars.BlockNumber))) |
|
|
|
case oDIFFICULTY: |
|
|
|
case DIFFICULTY: |
|
|
|
stack.Push(vm.vars.Diff) |
|
|
|
stack.Push(vm.vars.Diff) |
|
|
|
case oGASLIMIT: |
|
|
|
case GASLIMIT: |
|
|
|
// TODO
|
|
|
|
// TODO
|
|
|
|
stack.Push(big.NewInt(0)) |
|
|
|
stack.Push(big.NewInt(0)) |
|
|
|
|
|
|
|
|
|
|
|
// 0x50 range
|
|
|
|
// 0x50 range
|
|
|
|
case oPUSH1, oPUSH2, oPUSH3, oPUSH4, oPUSH5, oPUSH6, oPUSH7, oPUSH8, oPUSH9, oPUSH10, oPUSH11, oPUSH12, oPUSH13, oPUSH14, oPUSH15, oPUSH16, oPUSH17, oPUSH18, oPUSH19, oPUSH20, oPUSH21, oPUSH22, oPUSH23, oPUSH24, oPUSH25, oPUSH26, oPUSH27, oPUSH28, oPUSH29, oPUSH30, oPUSH31, oPUSH32: |
|
|
|
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) - int64(oPUSH1) + 1) |
|
|
|
a := big.NewInt(int64(op) - int64(PUSH1) + 1) |
|
|
|
pc.Add(pc, ethutil.Big1) |
|
|
|
pc.Add(pc, ethutil.Big1) |
|
|
|
data := closure.Gets(pc, a) |
|
|
|
data := closure.Gets(pc, a) |
|
|
|
val := ethutil.BigD(data.Bytes()) |
|
|
|
val := ethutil.BigD(data.Bytes()) |
|
|
|
// Push value to stack
|
|
|
|
// Push value to stack
|
|
|
|
stack.Push(val) |
|
|
|
stack.Push(val) |
|
|
|
pc.Add(pc, a.Sub(a, big.NewInt(1))) |
|
|
|
pc.Add(pc, a.Sub(a, big.NewInt(1))) |
|
|
|
step++ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case oPOP: |
|
|
|
step += int(op) - int(PUSH1) + 1 |
|
|
|
|
|
|
|
case POP: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
stack.Pop() |
|
|
|
stack.Pop() |
|
|
|
case oDUP: |
|
|
|
case DUP: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
stack.Push(stack.Peek()) |
|
|
|
stack.Push(stack.Peek()) |
|
|
|
case oSWAP: |
|
|
|
case SWAP: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
x, y := stack.Popn() |
|
|
|
x, y := stack.Popn() |
|
|
|
stack.Push(y) |
|
|
|
stack.Push(y) |
|
|
|
stack.Push(x) |
|
|
|
stack.Push(x) |
|
|
|
case oMLOAD: |
|
|
|
case MLOAD: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
offset := stack.Pop() |
|
|
|
offset := stack.Pop() |
|
|
|
stack.Push(ethutil.BigD(mem.Get(offset.Int64(), 32))) |
|
|
|
stack.Push(ethutil.BigD(mem.Get(offset.Int64(), 32))) |
|
|
|
case oMSTORE: // Store the value at stack top-1 in to memory at location stack top
|
|
|
|
case MSTORE: // Store the value at stack top-1 in to memory at location stack top
|
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
// Pop value of the stack
|
|
|
|
// Pop value of the stack
|
|
|
|
val, mStart := stack.Popn() |
|
|
|
val, mStart := stack.Popn() |
|
|
|
mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(val, 256)) |
|
|
|
mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(val, 256)) |
|
|
|
case oMSTORE8: |
|
|
|
case MSTORE8: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
val, mStart := stack.Popn() |
|
|
|
val, mStart := stack.Popn() |
|
|
|
base.And(val, new(big.Int).SetInt64(0xff)) |
|
|
|
base.And(val, new(big.Int).SetInt64(0xff)) |
|
|
|
mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(base, 256)) |
|
|
|
mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(base, 256)) |
|
|
|
case oSLOAD: |
|
|
|
case SLOAD: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
loc := stack.Pop() |
|
|
|
loc := stack.Pop() |
|
|
|
val := closure.GetMem(loc) |
|
|
|
val := closure.GetMem(loc) |
|
|
|
//fmt.Println("get", val.BigInt(), "@", loc)
|
|
|
|
//fmt.Println("get", val.BigInt(), "@", loc)
|
|
|
|
stack.Push(val.BigInt()) |
|
|
|
stack.Push(val.BigInt()) |
|
|
|
case oSSTORE: |
|
|
|
case SSTORE: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
val, loc := stack.Popn() |
|
|
|
val, loc := stack.Popn() |
|
|
|
//fmt.Println("storing", val, "@", loc)
|
|
|
|
//fmt.Println("storing", val, "@", loc)
|
|
|
@ -401,13 +399,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
|
|
|
|
|
|
|
|
// Add the change to manifest
|
|
|
|
// Add the change to manifest
|
|
|
|
vm.state.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val) |
|
|
|
vm.state.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val) |
|
|
|
case oJUMP: |
|
|
|
case JUMP: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
pc = stack.Pop() |
|
|
|
pc = stack.Pop() |
|
|
|
// Reduce pc by one because of the increment that's at the end of this for loop
|
|
|
|
// Reduce pc by one because of the increment that's at the end of this for loop
|
|
|
|
//pc.Sub(pc, ethutil.Big1)
|
|
|
|
//pc.Sub(pc, ethutil.Big1)
|
|
|
|
continue |
|
|
|
continue |
|
|
|
case oJUMPI: |
|
|
|
case JUMPI: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
cond, pos := stack.Popn() |
|
|
|
cond, pos := stack.Popn() |
|
|
|
if cond.Cmp(ethutil.BigTrue) == 0 { |
|
|
|
if cond.Cmp(ethutil.BigTrue) == 0 { |
|
|
@ -415,12 +413,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
//pc.Sub(pc, ethutil.Big1)
|
|
|
|
//pc.Sub(pc, ethutil.Big1)
|
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
case oPC: |
|
|
|
case PC: |
|
|
|
stack.Push(pc) |
|
|
|
stack.Push(pc) |
|
|
|
case oMSIZE: |
|
|
|
case MSIZE: |
|
|
|
stack.Push(big.NewInt(int64(mem.Len()))) |
|
|
|
stack.Push(big.NewInt(int64(mem.Len()))) |
|
|
|
// 0x60 range
|
|
|
|
// 0x60 range
|
|
|
|
case oCREATE: |
|
|
|
case CREATE: |
|
|
|
require(3) |
|
|
|
require(3) |
|
|
|
|
|
|
|
|
|
|
|
value := stack.Pop() |
|
|
|
value := stack.Pop() |
|
|
@ -439,9 +437,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
// Transfer all remaining gas to the new
|
|
|
|
// Transfer all remaining gas to the new
|
|
|
|
// contract so it may run the init script
|
|
|
|
// contract so it may run the init script
|
|
|
|
gas := new(big.Int).Set(closure.Gas) |
|
|
|
gas := new(big.Int).Set(closure.Gas) |
|
|
|
closure.Gas.Sub(closure.Gas, gas) |
|
|
|
closure.UseGas(gas) |
|
|
|
|
|
|
|
|
|
|
|
// Create the closure
|
|
|
|
// Create the closure
|
|
|
|
closure := NewClosure(closure.callee, |
|
|
|
c := NewClosure(closure.callee, |
|
|
|
closure.Object(), |
|
|
|
closure.Object(), |
|
|
|
contract.initScript, |
|
|
|
contract.initScript, |
|
|
|
vm.state, |
|
|
|
vm.state, |
|
|
@ -449,7 +448,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
closure.Price) |
|
|
|
closure.Price) |
|
|
|
// Call the closure and set the return value as
|
|
|
|
// Call the closure and set the return value as
|
|
|
|
// main script.
|
|
|
|
// main script.
|
|
|
|
closure.Script, err = closure.Call(vm, nil, hook) |
|
|
|
c.Script, _, err = c.Call(vm, nil, hook) |
|
|
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
|
|
|
|
|
|
|
@ -460,7 +460,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
|
|
|
|
|
|
|
|
vm.state.UpdateStateObject(contract) |
|
|
|
vm.state.UpdateStateObject(contract) |
|
|
|
} |
|
|
|
} |
|
|
|
case oCALL: |
|
|
|
case CALL: |
|
|
|
require(7) |
|
|
|
require(7) |
|
|
|
// Closure addr
|
|
|
|
// Closure addr
|
|
|
|
addr := stack.Pop() |
|
|
|
addr := stack.Pop() |
|
|
@ -492,7 +492,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
// Copy
|
|
|
|
// Copy
|
|
|
|
gas = new(big.Int).Set(closure.Gas) |
|
|
|
gas = new(big.Int).Set(closure.Gas) |
|
|
|
} |
|
|
|
} |
|
|
|
closure.Gas.Sub(closure.Gas, gas) |
|
|
|
closure.UseGas(gas) |
|
|
|
|
|
|
|
|
|
|
|
// Add the value to the state object
|
|
|
|
// Add the value to the state object
|
|
|
|
contract.AddAmount(value) |
|
|
|
contract.AddAmount(value) |
|
|
@ -500,7 +500,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
// Create a new callable closure
|
|
|
|
// Create a new callable closure
|
|
|
|
closure := NewClosure(closure.Object(), contract, contract.script, vm.state, gas, closure.Price) |
|
|
|
closure := NewClosure(closure.Object(), contract, contract.script, vm.state, gas, closure.Price) |
|
|
|
// Executer the closure and get the return value (if any)
|
|
|
|
// Executer the closure and get the return value (if any)
|
|
|
|
ret, err := closure.Call(vm, args, hook) |
|
|
|
ret, _, err := closure.Call(vm, args, hook) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
// Reset the changes applied this object
|
|
|
|
// Reset the changes applied this object
|
|
|
@ -516,13 +516,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes()) |
|
|
|
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes()) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
stack.Push(ethutil.BigFalse) |
|
|
|
} |
|
|
|
} |
|
|
|
case oRETURN: |
|
|
|
case RETURN: |
|
|
|
require(2) |
|
|
|
require(2) |
|
|
|
size, offset := stack.Popn() |
|
|
|
size, offset := stack.Popn() |
|
|
|
ret := mem.Get(offset.Int64(), size.Int64()) |
|
|
|
ret := mem.Get(offset.Int64(), size.Int64()) |
|
|
|
|
|
|
|
|
|
|
|
return closure.Return(ret), nil |
|
|
|
return closure.Return(ret), nil |
|
|
|
case oSUICIDE: |
|
|
|
case SUICIDE: |
|
|
|
require(1) |
|
|
|
require(1) |
|
|
|
|
|
|
|
|
|
|
|
receiver := vm.state.GetAccount(stack.Pop().Bytes()) |
|
|
|
receiver := vm.state.GetAccount(stack.Pop().Bytes()) |
|
|
@ -532,7 +532,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
closure.object.state.Purge() |
|
|
|
closure.object.state.Purge() |
|
|
|
|
|
|
|
|
|
|
|
fallthrough |
|
|
|
fallthrough |
|
|
|
case oSTOP: // Stop the closure
|
|
|
|
case STOP: // Stop the closure
|
|
|
|
return closure.Return(nil), nil |
|
|
|
return closure.Return(nil), nil |
|
|
|
default: |
|
|
|
default: |
|
|
|
ethutil.Config.Log.Debugf("Invalid opcode %x\n", op) |
|
|
|
ethutil.Config.Log.Debugf("Invalid opcode %x\n", op) |
|
|
@ -543,7 +543,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro |
|
|
|
pc.Add(pc, ethutil.Big1) |
|
|
|
pc.Add(pc, ethutil.Big1) |
|
|
|
|
|
|
|
|
|
|
|
if hook != nil { |
|
|
|
if hook != nil { |
|
|
|
if !hook(step-1, op, mem, stack, closure.Object()) { |
|
|
|
if !hook(prevStep, op, mem, stack, closure.Object()) { |
|
|
|
return nil, nil |
|
|
|
return nil, nil |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|