aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-04-12 01:29:57 +0800
committerobscuren <geffobscura@gmail.com>2014-04-12 01:29:57 +0800
commit116516158da637cde50d27d600db6661732fc402 (patch)
tree534568c2794911502058ff15e7176e2d84f29420
parentca747f268800590ee855b1ce593b61e95d073311 (diff)
downloaddexon-116516158da637cde50d27d600db6661732fc402.tar.gz
dexon-116516158da637cde50d27d600db6661732fc402.tar.zst
dexon-116516158da637cde50d27d600db6661732fc402.zip
Renamed
-rw-r--r--ethchain/closure.go4
-rw-r--r--ethchain/contract.go8
-rw-r--r--ethchain/stack.go8
-rw-r--r--ethchain/state_manager.go14
-rw-r--r--ethchain/vm.go98
-rw-r--r--ethchain/vm_test.go29
6 files changed, 124 insertions, 37 deletions
diff --git a/ethchain/closure.go b/ethchain/closure.go
index 3d15f2a99..de2196499 100644
--- a/ethchain/closure.go
+++ b/ethchain/closure.go
@@ -52,7 +52,7 @@ func (c *Closure) Get(x *big.Int) *ethutil.Value {
}
func (c *Closure) Gets(x, y *big.Int) *ethutil.Value {
- if x.Int64() > int64(len(c.Script)) || y.Int64() > int64(len(c.Script)) {
+ if x.Int64() >= int64(len(c.Script)) || y.Int64() >= int64(len(c.Script)) {
return ethutil.NewValue(0)
}
@@ -69,7 +69,7 @@ func (c *Closure) Address() []byte {
return c.object.Address()
}
-type DebugHook func(op OpCode)
+type DebugHook func(op OpCode, mem *Memory, stack *Stack)
func (c *Closure) Call(vm *Vm, args []byte, hook DebugHook) []byte {
c.Args = args
diff --git a/ethchain/contract.go b/ethchain/contract.go
index e99e413f7..af348667c 100644
--- a/ethchain/contract.go
+++ b/ethchain/contract.go
@@ -69,6 +69,14 @@ func (c *Contract) Address() []byte {
return c.address
}
+func (c *Contract) Script() []byte {
+ return c.script
+}
+
+func (c *Contract) Init() []byte {
+ return c.initScript
+}
+
func (c *Contract) RlpEncode() []byte {
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root, c.script, c.initScript})
}
diff --git a/ethchain/stack.go b/ethchain/stack.go
index d475f2f8e..2aca0a350 100644
--- a/ethchain/stack.go
+++ b/ethchain/stack.go
@@ -173,6 +173,10 @@ func NewStack() *Stack {
return &Stack{}
}
+func (st *Stack) Data() []*big.Int {
+ return st.data
+}
+
func (st *Stack) Pop() *big.Int {
str := st.data[len(st.data)-1]
@@ -246,6 +250,10 @@ func (m *Memory) Len() int {
return len(m.store)
}
+func (m *Memory) Data() []byte {
+ return m.store
+}
+
func (m *Memory) Print() {
fmt.Printf("### mem %d bytes ###\n", len(m.store))
if len(m.store) > 0 {
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 111d2c019..549d59959 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -318,14 +318,14 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
caller := sm.procState.GetAccount(tx.Sender())
closure := NewClosure(caller, contract, contract.script, sm.procState, tx.Gas, tx.Value)
vm := NewVm(sm.procState, RuntimeVars{
- origin: caller.Address(),
- blockNumber: block.BlockInfo().Number,
- prevHash: block.PrevHash,
- coinbase: block.Coinbase,
- time: block.Time,
- diff: block.Difficulty,
+ Origin: caller.Address(),
+ BlockNumber: block.BlockInfo().Number,
+ PrevHash: block.PrevHash,
+ Coinbase: block.Coinbase,
+ Time: block.Time,
+ Diff: block.Difficulty,
// XXX Tx data? Could be just an argument to the closure instead
- txData: nil,
+ TxData: nil,
})
closure.Call(vm, nil, nil)
diff --git a/ethchain/vm.go b/ethchain/vm.go
index dce972cc7..fbe0d0439 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -2,7 +2,7 @@ package ethchain
import (
_ "bytes"
- _ "fmt"
+ "fmt"
"github.com/ethereum/eth-go/ethutil"
_ "github.com/obscuren/secp256k1-go"
_ "math"
@@ -33,13 +33,13 @@ type Vm struct {
}
type RuntimeVars struct {
- origin []byte
- blockNumber uint64
- prevHash []byte
- coinbase []byte
- time int64
- diff *big.Int
- txData []string
+ Origin []byte
+ BlockNumber uint64
+ PrevHash []byte
+ Coinbase []byte
+ Time int64
+ Diff *big.Int
+ TxData []string
}
func NewVm(state *State, vars RuntimeVars) *Vm {
@@ -65,9 +65,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// The base for all big integer arithmetic
base := new(big.Int)
- if ethutil.Config.Debug {
- ethutil.Config.Log.Debugf("# op\n")
- }
+ /*
+ if ethutil.Config.Debug {
+ ethutil.Config.Log.Debugf("# op\n")
+ }
+ */
for {
step++
@@ -75,9 +77,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
val := closure.Get(pc)
// Get the opcode (it must be an opcode!)
op := OpCode(val.Uint())
- if ethutil.Config.Debug {
- ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
- }
+ /*
+ if ethutil.Config.Debug {
+ ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
+ }
+ */
// TODO Get each instruction cost properly
gas := new(big.Int)
@@ -270,7 +274,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
case oBALANCE:
stack.Push(closure.Value)
case oORIGIN:
- stack.Push(ethutil.BigD(vm.vars.origin))
+ stack.Push(ethutil.BigD(vm.vars.Origin))
case oCALLER:
stack.Push(ethutil.BigD(closure.Callee().Address()))
case oCALLVALUE:
@@ -286,15 +290,15 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
// 0x40 range
case oPREVHASH:
- stack.Push(ethutil.BigD(vm.vars.prevHash))
+ stack.Push(ethutil.BigD(vm.vars.PrevHash))
case oCOINBASE:
- stack.Push(ethutil.BigD(vm.vars.coinbase))
+ stack.Push(ethutil.BigD(vm.vars.Coinbase))
case oTIMESTAMP:
- stack.Push(big.NewInt(vm.vars.time))
+ stack.Push(big.NewInt(vm.vars.Time))
case oNUMBER:
- stack.Push(big.NewInt(int64(vm.vars.blockNumber)))
+ stack.Push(big.NewInt(int64(vm.vars.BlockNumber)))
case oDIFFICULTY:
- stack.Push(vm.vars.diff)
+ stack.Push(vm.vars.Diff)
case oGASLIMIT:
// TODO
@@ -406,7 +410,59 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) []byte {
pc.Add(pc, ethutil.Big1)
if hook != nil {
- hook(op)
+ hook(op, mem, stack)
+ }
+ }
+}
+
+func Disassemble(script []byte) (asm []string) {
+ pc := new(big.Int)
+ for {
+ if pc.Cmp(big.NewInt(int64(len(script)))) >= 0 {
+ return
+ }
+
+ // Get the memory location of pc
+ val := script[pc.Int64()]
+ // Get the opcode (it must be an opcode!)
+ op := OpCode(val)
+
+ asm = append(asm, fmt.Sprintf("%v", op))
+
+ switch op {
+ case oPUSH: // Push PC+1 on to the stack
+ pc.Add(pc, ethutil.Big1)
+ data := script[pc.Int64() : pc.Int64()+32]
+ val := ethutil.BigD(data)
+
+ var b []byte
+ if val.Int64() == 0 {
+ b = []byte{0}
+ } else {
+ b = val.Bytes()
+ }
+
+ asm = append(asm, fmt.Sprintf("0x%x", b))
+
+ pc.Add(pc, big.NewInt(31))
+ case oPUSH20:
+ pc.Add(pc, ethutil.Big1)
+ data := script[pc.Int64() : pc.Int64()+20]
+ val := ethutil.BigD(data)
+ var b []byte
+ if val.Int64() == 0 {
+ b = []byte{0}
+ } else {
+ b = val.Bytes()
+ }
+
+ asm = append(asm, fmt.Sprintf("0x%x", b))
+
+ pc.Add(pc, big.NewInt(19))
}
+
+ pc.Add(pc, ethutil.Big1)
}
+
+ return
}
diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go
index 5a1419c0f..a0add9532 100644
--- a/ethchain/vm_test.go
+++ b/ethchain/vm_test.go
@@ -130,14 +130,29 @@ func TestRun4(t *testing.T) {
callerClosure := NewClosure(account, c, c.script, 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),
+ 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,
+ TxData: nil,
})
callerClosure.Call(vm, nil, nil)
}
+
+func TestRun5(t *testing.T) {
+ ethutil.ReadConfig("")
+
+ asm, _ := mutan.Compile(strings.NewReader(`
+ int32 a = 10
+ int32 b = 20
+ if a > b {
+ int32 c = this.caller()
+ }
+ exit()
+ `), false)
+ script := ethutil.Assemble(asm...)
+ fmt.Println(Disassemble(script))
+}