Merge branch 'develop' of github.com:ethereum/eth-go into develop

This commit is contained in:
Maran 2014-06-18 13:19:03 +02:00
commit fba6de834e
9 changed files with 128 additions and 71 deletions

View File

@ -28,7 +28,7 @@ func Disassemble(script []byte) (asm []string) {
if len(data) == 0 { if len(data) == 0 {
data = []byte{0} data = []byte{0}
} }
asm = append(asm, fmt.Sprintf("%#x", data)) asm = append(asm, fmt.Sprintf("0x%x", data))
pc.Add(pc, big.NewInt(a-1)) pc.Add(pc, big.NewInt(a-1))
} }

View File

@ -120,6 +120,8 @@ func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
} }
func (self *State) NewStateObject(addr []byte) *StateObject { func (self *State) NewStateObject(addr []byte) *StateObject {
ethutil.Config.Log.Printf(ethutil.LogLevelInfo, "(+) %x\n", addr)
stateObject := NewStateObject(addr) stateObject := NewStateObject(addr)
self.stateObjects[string(addr)] = stateObject self.stateObjects[string(addr)] = stateObject

View File

@ -97,7 +97,6 @@ func (self *StateTransition) BuyGas() error {
if err != nil { if err != nil {
return err return err
} }
//self.state.UpdateStateObject(coinbase)
self.AddGas(self.tx.Gas) self.AddGas(self.tx.Gas)
sender.SubAmount(self.tx.GasValue()) sender.SubAmount(self.tx.GasValue())
@ -115,7 +114,7 @@ func (self *StateTransition) RefundGas() {
} }
func (self *StateTransition) TransitionState() (err error) { func (self *StateTransition) TransitionState() (err error) {
//snapshot := st.state.Snapshot() ethutil.Config.Log.Printf(ethutil.LogLevelInfo, "(~) %x\n", self.tx.Hash())
/* /*
defer func() { defer func() {
@ -132,8 +131,6 @@ func (self *StateTransition) TransitionState() (err error) {
receiver *StateObject receiver *StateObject
) )
ethutil.Config.Log.Printf(ethutil.LogLevelInfo, "(~) %x\n", tx.Hash())
// Make sure this transaction's nonce is correct // Make sure this transaction's nonce is correct
if sender.Nonce != tx.Nonce { if sender.Nonce != tx.Nonce {
return NonceError(tx.Nonce, sender.Nonce) return NonceError(tx.Nonce, sender.Nonce)
@ -146,26 +143,11 @@ func (self *StateTransition) TransitionState() (err error) {
// XXX Transactions after this point are considered valid. // XXX Transactions after this point are considered valid.
defer func() { defer self.RefundGas()
self.RefundGas()
/*
if sender != nil {
self.state.UpdateStateObject(sender)
}
if receiver != nil {
self.state.UpdateStateObject(receiver)
}
self.state.UpdateStateObject(self.Coinbase())
*/
}()
// Increment the nonce for the next transaction // Increment the nonce for the next transaction
sender.Nonce += 1 sender.Nonce += 1
// Get the receiver (TODO fix this, if coinbase is the receiver we need to save/retrieve)
receiver = self.Receiver() receiver = self.Receiver()
// Transaction gas // Transaction gas
@ -254,6 +236,7 @@ func (self *StateTransition) Eval(script []byte, context *StateObject) (ret []by
Diff: block.Difficulty, Diff: block.Difficulty,
Value: tx.Value, Value: tx.Value,
}) })
vm.Verbose = true
ret, _, err = closure.Call(vm, tx.Data, nil) ret, _, err = closure.Call(vm, tx.Data, nil)
return return

View File

@ -65,7 +65,7 @@ func (tx *Transaction) CreatesContract() bool {
return tx.contractCreation return tx.contractCreation
} }
/* Depricated */ /* Deprecated */
func (tx *Transaction) IsContract() bool { func (tx *Transaction) IsContract() bool {
return tx.CreatesContract() return tx.CreatesContract()
} }

View File

@ -226,7 +226,7 @@ var opCodeToString = map[OpCode]string{
func (o OpCode) String() string { func (o OpCode) String() string {
str := opCodeToString[o] str := opCodeToString[o]
if len(str) == 0 { if len(str) == 0 {
return fmt.Sprintf("Missing opcode %#x", int(o)) return fmt.Sprintf("Missing opcode 0x%x", int(o))
} }
return str return str

View File

@ -45,6 +45,10 @@ type Vm struct {
state *State state *State
stateManager *StateManager stateManager *StateManager
Verbose bool
logStr string
} }
type RuntimeVars struct { type RuntimeVars struct {
@ -58,6 +62,23 @@ type RuntimeVars struct {
Value *big.Int Value *big.Int
} }
func (self *Vm) Printf(format string, v ...interface{}) *Vm {
if self.Verbose {
self.logStr += fmt.Sprintf(format, v...)
}
return self
}
func (self *Vm) Endl() *Vm {
if self.Verbose {
ethutil.Config.Log.Infoln(self.logStr)
self.logStr = ""
}
return self
}
func NewVm(state *State, stateManager *StateManager, vars RuntimeVars) *Vm { func NewVm(state *State, stateManager *StateManager, vars RuntimeVars) *Vm {
return &Vm{vars: vars, state: state, stateManager: stateManager} return &Vm{vars: vars, state: state, stateManager: stateManager}
} }
@ -76,7 +97,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
} }
}() }()
ethutil.Config.Log.Debugf("[VM] Running closure %x\n", closure.object.Address()) ethutil.Config.Log.Debugf("[VM] Running %x\n", closure.object.Address())
// Memory for the current closure // Memory for the current closure
mem := &Memory{} mem := &Memory{}
@ -95,8 +116,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
step := 0 step := 0
prevStep := 0 prevStep := 0
ethutil.Config.Log.Debugf("# op\n")
for { for {
prevStep = step prevStep = step
// The base for all big integer arithmetic // The base for all big integer arithmetic
@ -108,7 +127,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Get the opcode (it must be an opcode!) // Get the opcode (it must be an opcode!)
op := OpCode(val.Uint()) op := OpCode(val.Uint())
ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String()) vm.Printf("(pc) %-3d -o- %-14s", pc, op.String())
//ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
gas := new(big.Int) gas := new(big.Int)
addStepGasUsage := func(amount *big.Int) { addStepGasUsage := func(amount *big.Int) {
@ -120,7 +140,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
var newMemSize uint64 = 0 var newMemSize uint64 = 0
switch op { switch op {
case STOP: case STOP:
gas.Set(ethutil.Big0)
case SUICIDE: case SUICIDE:
gas.Set(ethutil.Big0)
case SLOAD: case SLOAD:
gas.Set(GasSLoad) gas.Set(GasSLoad)
case SSTORE: case SSTORE:
@ -191,6 +213,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
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)
} }
vm.Printf(" (g) %-3v (%v)", gas, closure.Gas)
mem.Resize(newMemSize) mem.Resize(newMemSize)
switch op { switch op {
@ -202,28 +226,28 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
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(y, x)
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case SUB: 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(y, x)
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case MUL: 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(y, x)
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case DIV: 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(y, x)
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case SDIV: case SDIV:
@ -246,7 +270,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case MOD: case MOD:
require(2) require(2)
x, y := stack.Popn() x, y := stack.Popn()
base.Mod(x, y) base.Mod(y, x)
stack.Push(base) stack.Push(base)
case SMOD: case SMOD:
require(2) require(2)
@ -268,7 +292,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case EXP: case EXP:
require(2) require(2)
x, y := stack.Popn() x, y := stack.Popn()
base.Exp(x, y, Pow256) base.Exp(y, x, Pow256)
stack.Push(base) stack.Push(base)
case NEG: case NEG:
@ -277,7 +301,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack.Push(base) stack.Push(base)
case LT: case LT:
require(2) require(2)
x, y := stack.Popn() y, x := stack.Popn()
vm.Printf(" %v < %v", x, y)
// x < y // x < y
if x.Cmp(y) < 0 { if x.Cmp(y) < 0 {
stack.Push(ethutil.BigTrue) stack.Push(ethutil.BigTrue)
@ -286,7 +311,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
} }
case GT: case GT:
require(2) require(2)
x, y := stack.Popn() y, x := stack.Popn()
vm.Printf(" %v > %v", x, y)
// x > y // x > y
if x.Cmp(y) > 0 { if x.Cmp(y) > 0 {
stack.Push(ethutil.BigTrue) stack.Push(ethutil.BigTrue)
@ -296,6 +323,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case EQ: case EQ:
require(2) require(2)
x, y := stack.Popn() x, y := stack.Popn()
vm.Printf(" %v == %v", y, x)
// x == y // x == y
if x.Cmp(y) == 0 { if x.Cmp(y) == 0 {
stack.Push(ethutil.BigTrue) stack.Push(ethutil.BigTrue)
@ -315,24 +344,21 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case AND: 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) { vm.Printf(" %v & %v", y, x)
stack.Push(ethutil.BigTrue)
} else {
stack.Push(ethutil.BigFalse)
}
stack.Push(base.And(y, x))
case OR: 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) { vm.Printf(" %v | %v", y, x)
stack.Push(ethutil.BigTrue)
} else { stack.Push(base.Or(y, x))
stack.Push(ethutil.BigFalse)
}
case XOR: case XOR:
require(2) require(2)
x, y := stack.Popn() x, y := stack.Popn()
stack.Push(base.Xor(x, y)) vm.Printf(" %v ^ %v", y, x)
stack.Push(base.Xor(y, x))
case BYTE: case BYTE:
require(2) require(2)
val, th := stack.Popn() val, th := stack.Popn()
@ -357,7 +383,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case ORIGIN: case ORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin)) stack.Push(ethutil.BigD(vm.vars.Origin))
case CALLER: case CALLER:
stack.Push(ethutil.BigD(closure.caller.Address())) caller := closure.caller.Address()
stack.Push(ethutil.BigD(caller))
vm.Printf(" => %x", caller)
case CALLVALUE: case CALLVALUE:
stack.Push(vm.vars.Value) stack.Push(vm.vars.Value)
case CALLDATALOAD: case CALLDATALOAD:
@ -365,15 +394,21 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
offset := stack.Pop().Int64() offset := stack.Pop().Int64()
var data []byte var data []byte
if len(closure.Args) >= int(offset+32) { if len(closure.Args) >= int(offset) {
data = closure.Args[offset : offset+32] l := int64(math.Min(float64(offset+32), float64(len(closure.Args))))
data = closure.Args[offset : offset+l]
} else { } else {
data = []byte{0} data = []byte{0}
} }
vm.Printf(" => 0x%x", data)
stack.Push(ethutil.BigD(data)) stack.Push(ethutil.BigD(data))
case CALLDATASIZE: case CALLDATASIZE:
stack.Push(big.NewInt(int64(len(closure.Args)))) l := int64(len(closure.Args))
stack.Push(big.NewInt(l))
vm.Printf(" => %d", l)
case CALLDATACOPY: case CALLDATACOPY:
case CODESIZE: case CODESIZE:
case CODECOPY: case CODECOPY:
@ -423,6 +458,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
pc.Add(pc, a.Sub(a, big.NewInt(1))) pc.Add(pc, a.Sub(a, big.NewInt(1)))
step += int(op) - int(PUSH1) + 1 step += int(op) - int(PUSH1) + 1
vm.Printf(" => 0x%x", data.Bytes())
case POP: case POP:
require(1) require(1)
stack.Pop() stack.Pop()
@ -443,38 +480,50 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// 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))
vm.Printf(" => 0x%x", val)
case MSTORE8: 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))
vm.Printf(" => 0x%x", val)
case SLOAD: 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)
stack.Push(val.BigInt()) stack.Push(val.BigInt())
vm.Printf(" {} 0x%x", val)
case SSTORE: case SSTORE:
require(2) require(2)
val, loc := stack.Popn() val, loc := stack.Popn()
//fmt.Println("storing", val, "@", loc) fmt.Println("storing", string(val.Bytes()), "@", string(loc.Bytes()))
closure.SetStorage(loc, ethutil.NewValue(val)) closure.SetStorage(loc, ethutil.NewValue(val))
// 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)
vm.Printf(" => 0x%x", val)
case JUMP: 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) vm.Printf(" ~> %v", pc).Endl()
continue continue
case JUMPI: 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 {
pc = pos pc = pos
//pc.Sub(pc, ethutil.Big1)
vm.Printf(" (t) ~> %v", pc).Endl()
continue continue
} else {
vm.Printf(" (f)")
} }
case PC: case PC:
stack.Push(pc) stack.Push(pc)
@ -599,6 +648,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
pc.Add(pc, ethutil.Big1) pc.Add(pc, ethutil.Big1)
vm.Endl()
if hook != nil { if hook != nil {
if !hook(prevStep, op, mem, stack, closure.Object()) { if !hook(prevStep, op, mem, stack, closure.Object()) {
return nil, nil return nil, nil

View File

@ -170,11 +170,6 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, sc
tx = ethchain.NewContractCreationTx(value, gas, gasPrice, script) tx = ethchain.NewContractCreationTx(value, gas, gasPrice, script)
} else { } else {
// Just in case it was submitted as a 0x prefixed string
if len(scriptStr) > 0 && scriptStr[0:2] == "0x" {
scriptStr = scriptStr[2:len(scriptStr)]
}
data := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) { data := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
slice := strings.Split(s, "\n") slice := strings.Split(s, "\n")
for _, dataItem := range slice { for _, dataItem := range slice {

View File

@ -5,6 +5,7 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/big" "math/big"
"strings"
) )
// Number to bytes // Number to bytes
@ -91,7 +92,7 @@ func IsHex(str string) bool {
} }
func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) { func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
if len(str) > 1 && str[0:2] == "0x" { if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
ret = FromHex(str[2:]) ret = FromHex(str[2:])
} else { } else {
ret = cb(str) ret = cb(str)

View File

@ -1,7 +1,12 @@
package ethutil package ethutil
import ( import (
"bytes"
"encoding/json"
"fmt" "fmt"
"io"
"io/ioutil"
"net/http"
"reflect" "reflect"
"testing" "testing"
) )
@ -171,14 +176,34 @@ func TestTriePurge(t *testing.T) {
} }
} }
func TestTrieIt(t *testing.T) { type TestItem struct {
_, trie := New() Name string
trie.Update("c", LONG_WORD) Inputs [][]string
trie.Update("ca", LONG_WORD) Expectations string
trie.Update("cat", LONG_WORD) }
it := trie.NewIterator() func TestTrieIt(t *testing.T) {
it.Each(func(key string, node *Value) { //_, trie := New()
fmt.Println(key, ":", node.Str()) resp, err := http.Get("https://raw.githubusercontent.com/ethereum/tests/master/trietest.json")
}) if err != nil {
t.Fail()
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fail()
}
dec := json.NewDecoder(bytes.NewReader(body))
for {
var test TestItem
if err := dec.Decode(&test); err == io.EOF {
break
} else if err != nil {
t.Error("Fail something", err)
break
}
fmt.Println(test)
}
} }