Test fixes and removed old code. Added VM gas fees

This commit is contained in:
obscuren 2014-03-24 13:20:34 +01:00
parent 6a86c517c4
commit e0b6091d7e
7 changed files with 103 additions and 111 deletions

View File

@ -202,7 +202,7 @@ func (st *Stack) Push(d *big.Int) {
st.data = append(st.data, d) st.data = append(st.data, d)
} }
func (st *Stack) Print() { func (st *Stack) Print() {
fmt.Println("### STACK ###") fmt.Println("### stack ###")
if len(st.data) > 0 { if len(st.data) > 0 {
for i, val := range st.data { for i, val := range st.data {
fmt.Printf("%-3d %v\n", i, val) fmt.Printf("%-3d %v\n", i, val)
@ -242,15 +242,15 @@ func (m *Memory) Len() int {
} }
func (m *Memory) Print() { func (m *Memory) Print() {
fmt.Println("### MEM ###") fmt.Printf("### mem %d bytes ###\n", len(m.store))
if len(m.store) > 0 { if len(m.store) > 0 {
addr := 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]) fmt.Printf("%03d %v\n", addr, m.store[i:i+32])
addr++ addr++
} }
} else { } else {
fmt.Println("-- empty --") fmt.Println("-- empty --")
} }
fmt.Println("###########") fmt.Println("####################")
} }

View File

@ -10,6 +10,17 @@ import (
"math/big" "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 { type Vm struct {
txPool *TxPool txPool *TxPool
// Stack for processing contracts // Stack for processing contracts
@ -70,10 +81,41 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
} }
// TODO Get each instruction cost properly // TODO Get each instruction cost properly
fee := new(big.Int) gas := new(big.Int)
fee.Add(fee, big.NewInt(1000)) useGas := func(amount *big.Int) {
gas.Add(gas, amount)
}
if closure.Gas.Cmp(fee) < 0 { 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 {
return closure.Return(nil) return closure.Return(nil)
} }

View File

@ -2,113 +2,15 @@ package ethchain
import ( import (
"bytes" "bytes"
"fmt"
"github.com/ethereum/eth-go/ethdb" "github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/mutan"
"math/big" "math/big"
"strings"
"testing" "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) { func TestRun3(t *testing.T) {
ethutil.ReadConfig("") ethutil.ReadConfig("")
@ -132,7 +34,7 @@ func TestRun3(t *testing.T) {
contract := MakeContract(tx, state) contract := MakeContract(tx, state)
state.UpdateContract(contract) state.UpdateContract(contract)
callerScript := ethutil.Compile( callerScript := ethutil.Assemble(
"PUSH", 1337, // Argument "PUSH", 1337, // Argument
"PUSH", 65, // argument mem offset "PUSH", 65, // argument mem offset
"MSTORE", "MSTORE",
@ -172,3 +74,44 @@ func TestRun3(t *testing.T) {
t.Errorf("expected return value to be %v, got %v", exp, ret) 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)
}

View File

@ -36,6 +36,7 @@ func CurrencyToString(num *big.Int) string {
var ( var (
Big1 = big.NewInt(1) Big1 = big.NewInt(1)
Big2 = big.NewInt(1)
Big0 = big.NewInt(0) Big0 = big.NewInt(0)
Big256 = big.NewInt(0xff) Big256 = big.NewInt(0xff)
) )

View File

@ -131,7 +131,7 @@ func Instr(instr string) (int, []string, error) {
// Script compilation functions // Script compilation functions
// Compiles strings to machine code // Compiles strings to machine code
func Compile(instructions ...interface{}) (script []string) { func Assemble(instructions ...interface{}) (script []string) {
script = make([]string, len(instructions)) script = make([]string, len(instructions))
for i, val := range instructions { for i, val := range instructions {

View File

@ -2,6 +2,7 @@ package ethutil
import ( import (
"bytes" "bytes"
"fmt"
"math/big" "math/big"
"reflect" "reflect"
"testing" "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) { func BenchmarkEncodeDecode(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
bytes := Encode([]interface{}{"dog", "god", "cat"}) bytes := Encode([]interface{}{"dog", "god", "cat"})

View File

@ -1,7 +1,7 @@
package ethutil package ethutil
import ( import (
"fmt" _ "fmt"
"reflect" "reflect"
"testing" "testing"
) )