aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ethchain/stack.go8
-rw-r--r--ethchain/vm.go48
-rw-r--r--ethchain/vm_test.go147
-rw-r--r--ethutil/common.go1
-rw-r--r--ethutil/parsing.go2
-rw-r--r--ethutil/rlp_test.go6
-rw-r--r--ethutil/trie_test.go2
7 files changed, 103 insertions, 111 deletions
diff --git a/ethchain/stack.go b/ethchain/stack.go
index 3c2899e62..57165c432 100644
--- a/ethchain/stack.go
+++ b/ethchain/stack.go
@@ -202,7 +202,7 @@ func (st *Stack) Push(d *big.Int) {
st.data = append(st.data, d)
}
func (st *Stack) Print() {
- fmt.Println("### STACK ###")
+ fmt.Println("### stack ###")
if len(st.data) > 0 {
for i, val := range st.data {
fmt.Printf("%-3d %v\n", i, val)
@@ -242,15 +242,15 @@ func (m *Memory) Len() int {
}
func (m *Memory) Print() {
- fmt.Println("### MEM ###")
+ fmt.Printf("### mem %d bytes ###\n", len(m.store))
if len(m.store) > 0 {
addr := 0
- for i := 0; i+32 < len(m.store); i += 32 {
+ for i := 0; i+32 <= len(m.store); i += 32 {
fmt.Printf("%03d %v\n", addr, m.store[i:i+32])
addr++
}
} else {
fmt.Println("-- empty --")
}
- fmt.Println("###########")
+ fmt.Println("####################")
}
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 126592b25..9b6807925 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -10,6 +10,17 @@ import (
"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 +81,41 @@ 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(fee) < 0 {
+ if closure.Gas.Cmp(gas) < 0 {
return closure.Return(nil)
}
diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go
index 047531e09..308a65432 100644
--- a/ethchain/vm_test.go
+++ b/ethchain/vm_test.go
@@ -2,113 +2,15 @@ package ethchain
import (
"bytes"
+ "fmt"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil"
+ "github.com/obscuren/mutan"
"math/big"
+ "strings"
"testing"
)
-/*
-
-func TestRun(t *testing.T) {
- InitFees()
-
- ethutil.ReadConfig("")
-
- db, _ := ethdb.NewMemDatabase()
- state := NewState(ethutil.NewTrie(db, ""))
-
- script := Compile([]string{
- "TXSENDER",
- "SUICIDE",
- })
-
- tx := NewTransaction(ContractAddr, big.NewInt(1e17), script)
- fmt.Printf("contract addr %x\n", tx.Hash()[12:])
- contract := MakeContract(tx, state)
- vm := &Vm{}
-
- vm.Process(contract, state, RuntimeVars{
- address: tx.Hash()[12:],
- blockNumber: 1,
- sender: ethutil.FromHex("cd1722f3947def4cf144679da39c4c32bdc35681"),
- prevHash: ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
- coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
- time: 1,
- diff: big.NewInt(256),
- txValue: tx.Value,
- txData: tx.Data,
- })
-}
-
-func TestRun1(t *testing.T) {
- ethutil.ReadConfig("")
-
- db, _ := ethdb.NewMemDatabase()
- state := NewState(ethutil.NewTrie(db, ""))
-
- script := Compile([]string{
- "PUSH", "0",
- "PUSH", "0",
- "TXSENDER",
- "PUSH", "10000000",
- "MKTX",
- })
- fmt.Println(ethutil.NewValue(script))
-
- tx := NewTransaction(ContractAddr, ethutil.Big("100000000000000000000000000000000000000000000000000"), script)
- fmt.Printf("contract addr %x\n", tx.Hash()[12:])
- contract := MakeContract(tx, state)
- vm := &Vm{}
-
- vm.Process(contract, state, RuntimeVars{
- address: tx.Hash()[12:],
- blockNumber: 1,
- sender: ethutil.FromHex("cd1722f3947def4cf144679da39c4c32bdc35681"),
- prevHash: ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
- coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
- time: 1,
- diff: big.NewInt(256),
- txValue: tx.Value,
- txData: tx.Data,
- })
-}
-
-func TestRun2(t *testing.T) {
- ethutil.ReadConfig("")
-
- db, _ := ethdb.NewMemDatabase()
- state := NewState(ethutil.NewTrie(db, ""))
-
- script := Compile([]string{
- "PUSH", "0",
- "PUSH", "0",
- "TXSENDER",
- "PUSH", "10000000",
- "MKTX",
- })
- fmt.Println(ethutil.NewValue(script))
-
- tx := NewTransaction(ContractAddr, ethutil.Big("100000000000000000000000000000000000000000000000000"), script)
- fmt.Printf("contract addr %x\n", tx.Hash()[12:])
- contract := MakeContract(tx, state)
- vm := &Vm{}
-
- vm.Process(contract, state, RuntimeVars{
- address: tx.Hash()[12:],
- blockNumber: 1,
- sender: ethutil.FromHex("cd1722f3947def4cf144679da39c4c32bdc35681"),
- prevHash: ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
- coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
- time: 1,
- diff: big.NewInt(256),
- txValue: tx.Value,
- txData: tx.Data,
- })
-}
-*/
-
-// XXX Full stack test
func TestRun3(t *testing.T) {
ethutil.ReadConfig("")
@@ -132,7 +34,7 @@ func TestRun3(t *testing.T) {
contract := MakeContract(tx, state)
state.UpdateContract(contract)
- callerScript := ethutil.Compile(
+ callerScript := ethutil.Assemble(
"PUSH", 1337, // Argument
"PUSH", 65, // argument mem offset
"MSTORE",
@@ -172,3 +74,44 @@ func TestRun3(t *testing.T) {
t.Errorf("expected return value to be %v, got %v", exp, ret)
}
}
+
+func TestRun4(t *testing.T) {
+ ethutil.ReadConfig("")
+
+ db, _ := ethdb.NewMemDatabase()
+ state := NewState(ethutil.NewTrie(db, ""))
+
+ mutan.NewCompiler().Compile(strings.NewReader(`
+a = 1337
+c = 1
+[0] = 50
+d = [0]
+`))
+
+ asm := mutan.NewCompiler().Compile(strings.NewReader(`
+ a = 3 + 3
+ [1000] = a
+ [1000]
+`))
+ asm = append(asm, "LOG")
+ fmt.Println(asm)
+
+ callerScript := ethutil.Assemble(asm...)
+ callerTx := NewTransaction(ContractAddr, ethutil.Big("100000000000000000000000000000000000000000000000000"), callerScript)
+
+ // Contract addr as test address
+ account := NewAccount(ContractAddr, big.NewInt(10000000))
+ callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))
+
+ vm := NewVm(state, RuntimeVars{
+ origin: account.Address(),
+ blockNumber: 1,
+ prevHash: ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
+ coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
+ time: 1,
+ diff: big.NewInt(256),
+ // XXX Tx data? Could be just an argument to the closure instead
+ txData: nil,
+ })
+ callerClosure.Call(vm, nil)
+}
diff --git a/ethutil/common.go b/ethutil/common.go
index f15b10e6d..c63af29a6 100644
--- a/ethutil/common.go
+++ b/ethutil/common.go
@@ -36,6 +36,7 @@ func CurrencyToString(num *big.Int) string {
var (
Big1 = big.NewInt(1)
+ Big2 = big.NewInt(1)
Big0 = big.NewInt(0)
Big256 = big.NewInt(0xff)
)
diff --git a/ethutil/parsing.go b/ethutil/parsing.go
index 8929f0829..16ed2d06d 100644
--- a/ethutil/parsing.go
+++ b/ethutil/parsing.go
@@ -131,7 +131,7 @@ func Instr(instr string) (int, []string, error) {
// Script compilation functions
// Compiles strings to machine code
-func Compile(instructions ...interface{}) (script []string) {
+func Assemble(instructions ...interface{}) (script []string) {
script = make([]string, len(instructions))
for i, val := range instructions {
diff --git a/ethutil/rlp_test.go b/ethutil/rlp_test.go
index 2a58bfc0f..dc10db632 100644
--- a/ethutil/rlp_test.go
+++ b/ethutil/rlp_test.go
@@ -2,6 +2,7 @@ package ethutil
import (
"bytes"
+ "fmt"
"math/big"
"reflect"
"testing"
@@ -119,6 +120,11 @@ func TestEncodeDecodeBytes(t *testing.T) {
}
}
+func TestEncodeZero(t *testing.T) {
+ b := NewValue(0).Encode()
+ fmt.Println(b)
+}
+
func BenchmarkEncodeDecode(b *testing.B) {
for i := 0; i < b.N; i++ {
bytes := Encode([]interface{}{"dog", "god", "cat"})
diff --git a/ethutil/trie_test.go b/ethutil/trie_test.go
index 79e5de921..0be512d9f 100644
--- a/ethutil/trie_test.go
+++ b/ethutil/trie_test.go
@@ -1,7 +1,7 @@
package ethutil
import (
- "fmt"
+ _ "fmt"
"reflect"
"testing"
)