aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain/vm.go
diff options
context:
space:
mode:
Diffstat (limited to 'ethchain/vm.go')
-rw-r--r--ethchain/vm.go73
1 files changed, 63 insertions, 10 deletions
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 126592b25..98aaa603a 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -2,14 +2,24 @@ package ethchain
import (
_ "bytes"
- _ "fmt"
+ "fmt"
"github.com/ethereum/eth-go/ethutil"
_ "github.com/obscuren/secp256k1-go"
- "log"
_ "math"
"math/big"
)
+var (
+ GasStep = big.NewInt(1)
+ GasSha = big.NewInt(20)
+ GasSLoad = big.NewInt(20)
+ GasSStore = big.NewInt(100)
+ GasBalance = big.NewInt(20)
+ GasCreate = big.NewInt(100)
+ GasCall = big.NewInt(20)
+ GasMemory = big.NewInt(1)
+)
+
type Vm struct {
txPool *TxPool
// Stack for processing contracts
@@ -70,10 +80,43 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
}
// TODO Get each instruction cost properly
- fee := new(big.Int)
- fee.Add(fee, big.NewInt(1000))
+ gas := new(big.Int)
+ useGas := func(amount *big.Int) {
+ gas.Add(gas, amount)
+ }
+
+ switch op {
+ case oSHA3:
+ useGas(GasSha)
+ case oSLOAD:
+ useGas(GasSLoad)
+ case oSSTORE:
+ var mult *big.Int
+ y, x := stack.Peekn()
+ val := closure.GetMem(x)
+ if val.IsEmpty() && len(y.Bytes()) > 0 {
+ mult = ethutil.Big2
+ } else if !val.IsEmpty() && len(y.Bytes()) == 0 {
+ mult = ethutil.Big0
+ } else {
+ mult = ethutil.Big1
+ }
+ useGas(base.Mul(mult, GasSStore))
+ case oBALANCE:
+ useGas(GasBalance)
+ case oCREATE:
+ useGas(GasCreate)
+ case oCALL:
+ useGas(GasCall)
+ case oMLOAD, oMSIZE, oMSTORE8, oMSTORE:
+ useGas(GasMemory)
+ default:
+ useGas(GasStep)
+ }
+
+ if closure.Gas.Cmp(gas) < 0 {
+ ethutil.Config.Log.Debugln("Insufficient gas", closure.Gas, gas)
- if closure.Gas.Cmp(fee) < 0 {
return closure.Return(nil)
}
@@ -172,10 +215,17 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
} else {
stack.Push(ethutil.BigFalse)
}
- case oNOT:
+ case oEQ:
x, y := stack.Popn()
- // x != y
- if x.Cmp(y) != 0 {
+ // x == y
+ if x.Cmp(y) == 0 {
+ stack.Push(ethutil.BigTrue)
+ } else {
+ stack.Push(ethutil.BigFalse)
+ }
+ case oNOT:
+ x := stack.Pop()
+ if x.Cmp(ethutil.BigFalse) == 0 {
stack.Push(ethutil.BigTrue)
} else {
stack.Push(ethutil.BigFalse)
@@ -259,8 +309,8 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
case oJUMP:
pc = stack.Pop()
case oJUMPI:
- pos, cond := stack.Popn()
- if cond.Cmp(big.NewInt(0)) > 0 {
+ cond, pos := stack.Popn()
+ if cond.Cmp(ethutil.BigTrue) == 0 {
pc = pos
}
case oPC:
@@ -273,6 +323,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
retSize, retOffset := stack.Popn()
// Pop input size and offset
inSize, inOffset := stack.Popn()
+ fmt.Println(inSize, inOffset)
// Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64())
// Pop gas and value of the stack.
@@ -317,6 +368,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
}
}
+/*
func makeInlineTx(addr []byte, value, from, length *big.Int, contract *Contract, state *State) {
ethutil.Config.Log.Debugf(" => creating inline tx %x %v %v %v", addr, value, from, length)
j := int64(0)
@@ -353,3 +405,4 @@ func contractMemory(state *State, contractAddr []byte, memAddr *big.Int) *big.In
return decoder.BigInt()
}
+*/