forked from cerc-io/plugeth
Merge branch 'split' into develop
This commit is contained in:
commit
7d6ba88d2b
@ -12,7 +12,7 @@ type Callee interface {
|
|||||||
Address() []byte
|
Address() []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClosureBody interface {
|
type Reference interface {
|
||||||
Callee
|
Callee
|
||||||
ethutil.RlpEncodable
|
ethutil.RlpEncodable
|
||||||
GetMem(*big.Int) *ethutil.Value
|
GetMem(*big.Int) *ethutil.Value
|
||||||
@ -22,7 +22,8 @@ type ClosureBody interface {
|
|||||||
// Basic inline closure object which implement the 'closure' interface
|
// Basic inline closure object which implement the 'closure' interface
|
||||||
type Closure struct {
|
type Closure struct {
|
||||||
callee Callee
|
callee Callee
|
||||||
object ClosureBody
|
object Reference
|
||||||
|
Script []byte
|
||||||
State *State
|
State *State
|
||||||
|
|
||||||
Gas *big.Int
|
Gas *big.Int
|
||||||
@ -32,8 +33,8 @@ type Closure struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new closure for the given data items
|
// Create a new closure for the given data items
|
||||||
func NewClosure(callee Callee, object ClosureBody, state *State, gas, val *big.Int) *Closure {
|
func NewClosure(callee Callee, object Reference, script []byte, state *State, gas, val *big.Int) *Closure {
|
||||||
return &Closure{callee, object, state, gas, val, nil}
|
return &Closure{callee, object, script, state, gas, val, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retuns the x element in data slice
|
// Retuns the x element in data slice
|
||||||
@ -46,6 +47,20 @@ func (c *Closure) GetMem(x *big.Int) *ethutil.Value {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Closure) Get(x *big.Int) *ethutil.Value {
|
||||||
|
return c.Gets(x, big.NewInt(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Closure) Gets(x, y *big.Int) *ethutil.Value {
|
||||||
|
if x.Int64() > int64(len(c.Script)) || y.Int64() > int64(len(c.Script)) {
|
||||||
|
return ethutil.NewValue(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
partial := c.Script[x.Int64() : x.Int64()+y.Int64()]
|
||||||
|
|
||||||
|
return ethutil.NewValue(partial)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) {
|
func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) {
|
||||||
c.object.SetMem(x, val)
|
c.object.SetMem(x, val)
|
||||||
}
|
}
|
||||||
@ -81,7 +96,7 @@ func (c *Closure) ReturnGas(gas *big.Int, state *State) {
|
|||||||
c.Gas.Add(c.Gas, gas)
|
c.Gas.Add(c.Gas, gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Closure) Object() ClosureBody {
|
func (c *Closure) Object() Reference {
|
||||||
return c.object
|
return c.object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,10 @@ type Contract struct {
|
|||||||
Amount *big.Int
|
Amount *big.Int
|
||||||
Nonce uint64
|
Nonce uint64
|
||||||
//state *ethutil.Trie
|
//state *ethutil.Trie
|
||||||
state *State
|
state *State
|
||||||
address []byte
|
address []byte
|
||||||
|
script []byte
|
||||||
|
initScript []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContract(address []byte, Amount *big.Int, root []byte) *Contract {
|
func NewContract(address []byte, Amount *big.Int, root []byte) *Contract {
|
||||||
@ -45,6 +47,14 @@ func (c *Contract) GetMem(num *big.Int) *ethutil.Value {
|
|||||||
return c.Addr(nb)
|
return c.Addr(nb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Contract) GetInstr(pc *big.Int) *ethutil.Value {
|
||||||
|
if int64(len(c.script)-1) < pc.Int64() {
|
||||||
|
return ethutil.NewValue(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ethutil.NewValueFromBytes([]byte{c.script[pc.Int64()]})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Contract) SetMem(num *big.Int, val *ethutil.Value) {
|
func (c *Contract) SetMem(num *big.Int, val *ethutil.Value) {
|
||||||
addr := ethutil.BigToBytes(num, 256)
|
addr := ethutil.BigToBytes(num, 256)
|
||||||
c.state.trie.Update(string(addr), string(val.Encode()))
|
c.state.trie.Update(string(addr), string(val.Encode()))
|
||||||
@ -60,7 +70,7 @@ func (c *Contract) Address() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Contract) RlpEncode() []byte {
|
func (c *Contract) RlpEncode() []byte {
|
||||||
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root})
|
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root, c.script, c.initScript})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Contract) RlpDecode(data []byte) {
|
func (c *Contract) RlpDecode(data []byte) {
|
||||||
@ -69,6 +79,8 @@ func (c *Contract) RlpDecode(data []byte) {
|
|||||||
c.Amount = decoder.Get(0).BigInt()
|
c.Amount = decoder.Get(0).BigInt()
|
||||||
c.Nonce = decoder.Get(1).Uint()
|
c.Nonce = decoder.Get(1).Uint()
|
||||||
c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
|
c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
|
||||||
|
c.script = decoder.Get(3).Bytes()
|
||||||
|
c.initScript = decoder.Get(4).Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeContract(tx *Transaction, state *State) *Contract {
|
func MakeContract(tx *Transaction, state *State) *Contract {
|
||||||
@ -79,12 +91,17 @@ func MakeContract(tx *Transaction, state *State) *Contract {
|
|||||||
value := tx.Value
|
value := tx.Value
|
||||||
contract := NewContract(addr, value, []byte(""))
|
contract := NewContract(addr, value, []byte(""))
|
||||||
state.trie.Update(string(addr), string(contract.RlpEncode()))
|
state.trie.Update(string(addr), string(contract.RlpEncode()))
|
||||||
for i, val := range tx.Data {
|
contract.script = tx.Data
|
||||||
if len(val) > 0 {
|
contract.initScript = tx.Init
|
||||||
bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256)
|
|
||||||
contract.state.trie.Update(string(bytNum), string(ethutil.Encode(val)))
|
/*
|
||||||
|
for i, val := range tx.Data {
|
||||||
|
if len(val) > 0 {
|
||||||
|
bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256)
|
||||||
|
contract.state.trie.Update(string(bytNum), string(ethutil.Encode(val)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
state.trie.Update(string(addr), string(contract.RlpEncode()))
|
state.trie.Update(string(addr), string(contract.RlpEncode()))
|
||||||
|
|
||||||
return contract
|
return contract
|
||||||
|
@ -55,6 +55,7 @@ const (
|
|||||||
|
|
||||||
// 0x50 range - 'storage' and execution
|
// 0x50 range - 'storage' and execution
|
||||||
oPUSH = 0x50
|
oPUSH = 0x50
|
||||||
|
oPUSH20 = 0x80
|
||||||
oPOP = 0x51
|
oPOP = 0x51
|
||||||
oDUP = 0x52
|
oDUP = 0x52
|
||||||
oSWAP = 0x53
|
oSWAP = 0x53
|
||||||
@ -250,7 +251,7 @@ func (m *Memory) Print() {
|
|||||||
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: % x\n", addr, m.store[i:i+32])
|
||||||
addr++
|
addr++
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -316,7 +316,7 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
caller := sm.procState.GetAccount(tx.Sender())
|
caller := sm.procState.GetAccount(tx.Sender())
|
||||||
closure := NewClosure(caller, contract, sm.procState, tx.Gas, tx.Value)
|
closure := NewClosure(caller, contract, contract.script, sm.procState, tx.Gas, tx.Value)
|
||||||
vm := NewVm(sm.procState, RuntimeVars{
|
vm := NewVm(sm.procState, RuntimeVars{
|
||||||
origin: caller.Address(),
|
origin: caller.Address(),
|
||||||
blockNumber: block.BlockInfo().Number,
|
blockNumber: block.BlockInfo().Number,
|
||||||
|
@ -14,7 +14,8 @@ type Transaction struct {
|
|||||||
Value *big.Int
|
Value *big.Int
|
||||||
Gas *big.Int
|
Gas *big.Int
|
||||||
Gasprice *big.Int
|
Gasprice *big.Int
|
||||||
Data []string
|
Data []byte
|
||||||
|
Init []byte
|
||||||
v byte
|
v byte
|
||||||
r, s []byte
|
r, s []byte
|
||||||
|
|
||||||
@ -22,11 +23,11 @@ type Transaction struct {
|
|||||||
contractCreation bool
|
contractCreation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContractCreationTx(value, gasprice *big.Int, data []string) *Transaction {
|
func NewContractCreationTx(value, gasprice *big.Int, data []byte) *Transaction {
|
||||||
return &Transaction{Value: value, Gasprice: gasprice, Data: data, contractCreation: true}
|
return &Transaction{Value: value, Gasprice: gasprice, Data: data, contractCreation: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransactionMessage(to []byte, value, gasprice, gas *big.Int, data []string) *Transaction {
|
func NewTransactionMessage(to []byte, value, gasprice, gas *big.Int, data []byte) *Transaction {
|
||||||
return &Transaction{Recipient: to, Value: value, Gasprice: gasprice, Gas: gas, Data: data}
|
return &Transaction{Recipient: to, Value: value, Gasprice: gasprice, Gas: gas, Data: data}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,19 +46,12 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) Hash() []byte {
|
func (tx *Transaction) Hash() []byte {
|
||||||
data := make([]interface{}, len(tx.Data))
|
data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice, tx.Gas, tx.Recipient, string(tx.Data)}
|
||||||
for i, val := range tx.Data {
|
if tx.contractCreation {
|
||||||
data[i] = val
|
data = append(data, string(tx.Init))
|
||||||
}
|
}
|
||||||
|
|
||||||
preEnc := []interface{}{
|
return ethutil.Sha3Bin(ethutil.NewValue(data).Encode())
|
||||||
tx.Nonce,
|
|
||||||
tx.Recipient,
|
|
||||||
tx.Value,
|
|
||||||
data,
|
|
||||||
}
|
|
||||||
|
|
||||||
return ethutil.Sha3Bin(ethutil.Encode(preEnc))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) IsContract() bool {
|
func (tx *Transaction) IsContract() bool {
|
||||||
@ -110,15 +104,17 @@ func (tx *Transaction) Sign(privk []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ]
|
||||||
|
// [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ]
|
||||||
func (tx *Transaction) RlpData() interface{} {
|
func (tx *Transaction) RlpData() interface{} {
|
||||||
data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice}
|
data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice, tx.Gas, tx.Recipient, tx.Data}
|
||||||
|
|
||||||
if !tx.contractCreation {
|
if tx.contractCreation {
|
||||||
data = append(data, tx.Recipient, tx.Gas)
|
data = append(data, tx.Init)
|
||||||
}
|
}
|
||||||
d := ethutil.NewSliceValue(tx.Data).Slice()
|
//d := ethutil.NewSliceValue(tx.Data).Slice()
|
||||||
|
|
||||||
return append(data, d, tx.v, tx.r, tx.s)
|
return append(data, tx.v, tx.r, tx.s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) RlpValue() *ethutil.Value {
|
func (tx *Transaction) RlpValue() *ethutil.Value {
|
||||||
@ -137,31 +133,19 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
|
|||||||
tx.Nonce = decoder.Get(0).Uint()
|
tx.Nonce = decoder.Get(0).Uint()
|
||||||
tx.Value = decoder.Get(1).BigInt()
|
tx.Value = decoder.Get(1).BigInt()
|
||||||
tx.Gasprice = decoder.Get(2).BigInt()
|
tx.Gasprice = decoder.Get(2).BigInt()
|
||||||
|
tx.Gas = decoder.Get(3).BigInt()
|
||||||
|
tx.Recipient = decoder.Get(4).Bytes()
|
||||||
|
tx.Data = decoder.Get(5).Bytes()
|
||||||
|
|
||||||
// If the 4th item is a list(slice) this tx
|
// If the list is of length 10 it's a contract creation tx
|
||||||
// is a contract creation tx
|
if decoder.Len() == 10 {
|
||||||
if decoder.Get(3).IsList() {
|
|
||||||
d := decoder.Get(3)
|
|
||||||
tx.Data = make([]string, d.Len())
|
|
||||||
for i := 0; i < d.Len(); i++ {
|
|
||||||
tx.Data[i] = d.Get(i).Str()
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.v = byte(decoder.Get(4).Uint())
|
|
||||||
tx.r = decoder.Get(5).Bytes()
|
|
||||||
tx.s = decoder.Get(6).Bytes()
|
|
||||||
|
|
||||||
tx.contractCreation = true
|
tx.contractCreation = true
|
||||||
|
tx.Init = decoder.Get(6).Bytes()
|
||||||
|
|
||||||
|
tx.v = byte(decoder.Get(7).Uint())
|
||||||
|
tx.r = decoder.Get(8).Bytes()
|
||||||
|
tx.s = decoder.Get(9).Bytes()
|
||||||
} else {
|
} else {
|
||||||
tx.Recipient = decoder.Get(3).Bytes()
|
|
||||||
tx.Gas = decoder.Get(4).BigInt()
|
|
||||||
|
|
||||||
d := decoder.Get(5)
|
|
||||||
tx.Data = make([]string, d.Len())
|
|
||||||
for i := 0; i < d.Len(); i++ {
|
|
||||||
tx.Data[i] = d.Get(i).Str()
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.v = byte(decoder.Get(6).Uint())
|
tx.v = byte(decoder.Get(6).Uint())
|
||||||
tx.r = decoder.Get(7).Bytes()
|
tx.r = decoder.Get(7).Bytes()
|
||||||
tx.s = decoder.Get(8).Bytes()
|
tx.s = decoder.Get(8).Bytes()
|
||||||
|
@ -1,54 +1 @@
|
|||||||
package ethchain
|
package ethchain
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAddressRetrieval(t *testing.T) {
|
|
||||||
// TODO
|
|
||||||
// 88f9b82462f6c4bf4a0fb15e5c3971559a316e7f
|
|
||||||
key, _ := hex.DecodeString("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4")
|
|
||||||
|
|
||||||
tx := &Transaction{
|
|
||||||
Nonce: 0,
|
|
||||||
Recipient: ZeroHash160,
|
|
||||||
Value: big.NewInt(0),
|
|
||||||
Data: nil,
|
|
||||||
}
|
|
||||||
//fmt.Printf("rlp %x\n", tx.RlpEncode())
|
|
||||||
//fmt.Printf("sha rlp %x\n", tx.Hash())
|
|
||||||
|
|
||||||
tx.Sign(key)
|
|
||||||
|
|
||||||
//fmt.Printf("hex tx key %x\n", tx.PublicKey())
|
|
||||||
//fmt.Printf("seder %x\n", tx.Sender())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddressRetrieval2(t *testing.T) {
|
|
||||||
// TODO
|
|
||||||
// 88f9b82462f6c4bf4a0fb15e5c3971559a316e7f
|
|
||||||
key, _ := hex.DecodeString("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4")
|
|
||||||
addr, _ := hex.DecodeString("944400f4b88ac9589a0f17ed4671da26bddb668b")
|
|
||||||
tx := &Transaction{
|
|
||||||
Nonce: 0,
|
|
||||||
Recipient: addr,
|
|
||||||
Value: big.NewInt(1000),
|
|
||||||
Data: nil,
|
|
||||||
}
|
|
||||||
tx.Sign(key)
|
|
||||||
//data, _ := hex.DecodeString("f85d8094944400f4b88ac9589a0f17ed4671da26bddb668b8203e8c01ca0363b2a410de00bc89be40f468d16e70e543b72191fbd8a684a7c5bef51dc451fa02d8ecf40b68f9c64ed623f6ee24c9c878943b812e1e76bd73ccb2bfef65579e7")
|
|
||||||
//tx := NewTransactionFromData(data)
|
|
||||||
/*
|
|
||||||
fmt.Println(tx.RlpValue())
|
|
||||||
|
|
||||||
fmt.Printf("rlp %x\n", tx.RlpEncode())
|
|
||||||
fmt.Printf("sha rlp %x\n", tx.Hash())
|
|
||||||
|
|
||||||
//tx.Sign(key)
|
|
||||||
|
|
||||||
fmt.Printf("hex tx key %x\n", tx.PublicKey())
|
|
||||||
fmt.Printf("seder %x\n", tx.Sender())
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,7 @@ package ethchain
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "bytes"
|
_ "bytes"
|
||||||
"fmt"
|
_ "fmt"
|
||||||
"github.com/ethereum/eth-go/ethutil"
|
"github.com/ethereum/eth-go/ethutil"
|
||||||
_ "github.com/obscuren/secp256k1-go"
|
_ "github.com/obscuren/secp256k1-go"
|
||||||
_ "math"
|
_ "math"
|
||||||
@ -72,7 +72,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
|
|||||||
for {
|
for {
|
||||||
step++
|
step++
|
||||||
// Get the memory location of pc
|
// Get the memory location of pc
|
||||||
val := closure.GetMem(pc)
|
val := closure.Get(pc)
|
||||||
// Get the opcode (it must be an opcode!)
|
// Get the opcode (it must be an opcode!)
|
||||||
op := OpCode(val.Uint())
|
op := OpCode(val.Uint())
|
||||||
if ethutil.Config.Debug {
|
if ethutil.Config.Debug {
|
||||||
@ -233,13 +233,37 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
|
|||||||
|
|
||||||
// 0x10 range
|
// 0x10 range
|
||||||
case oAND:
|
case oAND:
|
||||||
|
x, y := stack.Popn()
|
||||||
|
if (x.Cmp(ethutil.BigTrue) >= 0) && (y.Cmp(ethutil.BigTrue) >= 0) {
|
||||||
|
stack.Push(ethutil.BigTrue)
|
||||||
|
} else {
|
||||||
|
stack.Push(ethutil.BigFalse)
|
||||||
|
}
|
||||||
|
|
||||||
case oOR:
|
case oOR:
|
||||||
|
x, y := stack.Popn()
|
||||||
|
if (x.Cmp(ethutil.BigInt0) >= 0) || (y.Cmp(ethutil.BigInt0) >= 0) {
|
||||||
|
stack.Push(ethutil.BigTrue)
|
||||||
|
} else {
|
||||||
|
stack.Push(ethutil.BigFalse)
|
||||||
|
}
|
||||||
case oXOR:
|
case oXOR:
|
||||||
|
x, y := stack.Popn()
|
||||||
|
stack.Push(base.Xor(x, y))
|
||||||
case oBYTE:
|
case oBYTE:
|
||||||
|
val, th := stack.Popn()
|
||||||
|
if th.Cmp(big.NewInt(32)) < 0 {
|
||||||
|
stack.Push(big.NewInt(int64(len(val.Bytes())-1) - th.Int64()))
|
||||||
|
} else {
|
||||||
|
stack.Push(ethutil.BigFalse)
|
||||||
|
}
|
||||||
|
|
||||||
// 0x20 range
|
// 0x20 range
|
||||||
case oSHA3:
|
case oSHA3:
|
||||||
|
size, offset := stack.Popn()
|
||||||
|
data := mem.Get(offset.Int64(), size.Int64())
|
||||||
|
|
||||||
|
stack.Push(ethutil.BigD(data))
|
||||||
// 0x30 range
|
// 0x30 range
|
||||||
case oADDRESS:
|
case oADDRESS:
|
||||||
stack.Push(ethutil.BigD(closure.Object().Address()))
|
stack.Push(ethutil.BigD(closure.Object().Address()))
|
||||||
@ -277,9 +301,23 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
|
|||||||
// 0x50 range
|
// 0x50 range
|
||||||
case oPUSH: // Push PC+1 on to the stack
|
case oPUSH: // Push PC+1 on to the stack
|
||||||
pc.Add(pc, ethutil.Big1)
|
pc.Add(pc, ethutil.Big1)
|
||||||
|
data := closure.Gets(pc, big.NewInt(32))
|
||||||
|
val := ethutil.BigD(data.Bytes())
|
||||||
|
|
||||||
val := closure.GetMem(pc).BigInt()
|
// Push value to stack
|
||||||
stack.Push(val)
|
stack.Push(val)
|
||||||
|
|
||||||
|
pc.Add(pc, big.NewInt(31))
|
||||||
|
case oPUSH20:
|
||||||
|
pc.Add(pc, ethutil.Big1)
|
||||||
|
data := closure.Gets(pc, big.NewInt(20))
|
||||||
|
val := ethutil.BigD(data.Bytes())
|
||||||
|
|
||||||
|
// Push value to stack
|
||||||
|
stack.Push(val)
|
||||||
|
|
||||||
|
pc.Add(pc, big.NewInt(19))
|
||||||
|
|
||||||
case oPOP:
|
case oPOP:
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
case oDUP:
|
case oDUP:
|
||||||
@ -319,21 +357,20 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
|
|||||||
stack.Push(big.NewInt(int64(mem.Len())))
|
stack.Push(big.NewInt(int64(mem.Len())))
|
||||||
// 0x60 range
|
// 0x60 range
|
||||||
case oCALL:
|
case oCALL:
|
||||||
// Pop return size and offset
|
|
||||||
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.
|
|
||||||
gas, value := stack.Popn()
|
|
||||||
// Closure addr
|
// Closure addr
|
||||||
addr := stack.Pop()
|
addr := stack.Pop()
|
||||||
|
// Pop gas and value of the stack.
|
||||||
|
gas, value := stack.Popn()
|
||||||
|
// Pop input size and offset
|
||||||
|
inSize, inOffset := stack.Popn()
|
||||||
|
// Pop return size and offset
|
||||||
|
retSize, retOffset := stack.Popn()
|
||||||
|
// Get the arguments from the memory
|
||||||
|
args := mem.Get(inOffset.Int64(), inSize.Int64())
|
||||||
// Fetch the contract which will serve as the closure body
|
// Fetch the contract which will serve as the closure body
|
||||||
contract := vm.state.GetContract(addr.Bytes())
|
contract := vm.state.GetContract(addr.Bytes())
|
||||||
// Create a new callable closure
|
// Create a new callable closure
|
||||||
closure := NewClosure(closure, contract, vm.state, gas, value)
|
closure := NewClosure(closure, contract, contract.script, vm.state, gas, value)
|
||||||
// Executer the closure and get the return value (if any)
|
// Executer the closure and get the return value (if any)
|
||||||
ret := closure.Call(vm, args)
|
ret := closure.Call(vm, args)
|
||||||
|
|
||||||
@ -361,7 +398,9 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
|
|||||||
break out
|
break out
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
ethutil.Config.Log.Debugln("Invalid opcode", op)
|
ethutil.Config.Log.Debugf("Invalid opcode %x\n", op)
|
||||||
|
|
||||||
|
return closure.Return(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
pc.Add(pc, ethutil.Big1)
|
pc.Add(pc, ethutil.Big1)
|
||||||
|
@ -84,27 +84,41 @@ func TestRun4(t *testing.T) {
|
|||||||
|
|
||||||
asm, err := mutan.Compile(strings.NewReader(`
|
asm, err := mutan.Compile(strings.NewReader(`
|
||||||
int32 a = 10
|
int32 a = 10
|
||||||
int32 b = 10
|
int32 b = 20
|
||||||
if a == b {
|
if a > b {
|
||||||
int32 c = 10
|
int32 c = this.caller()
|
||||||
if c == 10 {
|
}
|
||||||
int32 d = 1000
|
exit()
|
||||||
int32 e = 10
|
`), false)
|
||||||
}
|
script := ethutil.Assemble(asm...)
|
||||||
|
tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script)
|
||||||
|
addr := tx.Hash()[12:]
|
||||||
|
contract := MakeContract(tx, state)
|
||||||
|
state.UpdateContract(contract)
|
||||||
|
fmt.Printf("%x\n", addr)
|
||||||
|
|
||||||
|
asm, err = mutan.Compile(strings.NewReader(`
|
||||||
|
// Check if there's any cash in the initial store
|
||||||
|
if store[1000] == 0 {
|
||||||
|
store[1000] = 10^20
|
||||||
}
|
}
|
||||||
|
|
||||||
store[0] = 20
|
store[1001] = this.value() * 20
|
||||||
store[a] = 20
|
store[this.origin()] = store[this.origin()] + 1000
|
||||||
store[b] = this.caller()
|
|
||||||
|
|
||||||
int8[10] ret
|
if store[1001] > 20 {
|
||||||
int8[10] arg
|
store[1001] = 10^50
|
||||||
call(1234, 0, 100000000, arg, ret)
|
}
|
||||||
|
|
||||||
|
int8 ret = 0
|
||||||
|
int8 arg = 10
|
||||||
|
store[1002] = "a46df28529eb8aa8b8c025b0b413c5f4b688352f"
|
||||||
|
call(store[1002], 0, 100000000, arg, ret)
|
||||||
`), false)
|
`), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
//asm = append(asm, "LOG")
|
asm = append(asm, "LOG")
|
||||||
fmt.Println(asm)
|
fmt.Println(asm)
|
||||||
|
|
||||||
callerScript := ethutil.Assemble(asm...)
|
callerScript := ethutil.Assemble(asm...)
|
||||||
@ -112,7 +126,8 @@ func TestRun4(t *testing.T) {
|
|||||||
|
|
||||||
// Contract addr as test address
|
// Contract addr as test address
|
||||||
account := NewAccount(ContractAddr, big.NewInt(10000000))
|
account := NewAccount(ContractAddr, big.NewInt(10000000))
|
||||||
callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))
|
c := MakeContract(callerTx, state)
|
||||||
|
callerClosure := NewClosure(account, c, c.script, state, big.NewInt(1000000000), new(big.Int))
|
||||||
|
|
||||||
vm := NewVm(state, RuntimeVars{
|
vm := NewVm(state, RuntimeVars{
|
||||||
origin: account.Address(),
|
origin: account.Address(),
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package ethutil
|
package ethutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Op codes
|
// Op codes
|
||||||
@ -51,7 +51,10 @@ var OpCodes = map[string]byte{
|
|||||||
"GASLIMIT": 0x45,
|
"GASLIMIT": 0x45,
|
||||||
|
|
||||||
// 0x50 range - 'storage' and execution
|
// 0x50 range - 'storage' and execution
|
||||||
"PUSH": 0x50,
|
"PUSH": 0x50,
|
||||||
|
|
||||||
|
"PUSH20": 0x80,
|
||||||
|
|
||||||
"POP": 0x51,
|
"POP": 0x51,
|
||||||
"DUP": 0x52,
|
"DUP": 0x52,
|
||||||
"SWAP": 0x53,
|
"SWAP": 0x53,
|
||||||
@ -98,11 +101,16 @@ func CompileInstr(s interface{}) ([]byte, error) {
|
|||||||
// Assume regular bytes during compilation
|
// Assume regular bytes during compilation
|
||||||
if !success {
|
if !success {
|
||||||
num.SetBytes([]byte(str))
|
num.SetBytes([]byte(str))
|
||||||
|
} else {
|
||||||
|
// tmp fix for 32 bytes
|
||||||
|
n := BigToBytes(num, 256)
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return num.Bytes(), nil
|
return num.Bytes(), nil
|
||||||
case int:
|
case int:
|
||||||
return big.NewInt(int64(s.(int))).Bytes(), nil
|
num := BigToBytes(big.NewInt(int64(s.(int))), 256)
|
||||||
|
return num, nil
|
||||||
case []byte:
|
case []byte:
|
||||||
return BigD(s.([]byte)).Bytes(), nil
|
return BigD(s.([]byte)).Bytes(), nil
|
||||||
}
|
}
|
||||||
@ -110,34 +118,16 @@ func CompileInstr(s interface{}) ([]byte, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Instr(instr string) (int, []string, error) {
|
|
||||||
|
|
||||||
base := new(big.Int)
|
|
||||||
base.SetString(instr, 0)
|
|
||||||
|
|
||||||
args := make([]string, 7)
|
|
||||||
for i := 0; i < 7; i++ {
|
|
||||||
// int(int(val) / int(math.Pow(256,float64(i)))) % 256
|
|
||||||
exp := BigPow(256, i)
|
|
||||||
num := new(big.Int)
|
|
||||||
num.Div(base, exp)
|
|
||||||
|
|
||||||
args[i] = num.Mod(num, big.NewInt(256)).String()
|
|
||||||
}
|
|
||||||
op, _ := strconv.Atoi(args[0])
|
|
||||||
|
|
||||||
return op, args[1:7], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Script compilation functions
|
// Script compilation functions
|
||||||
// Compiles strings to machine code
|
// Compiles strings to machine code
|
||||||
func Assemble(instructions ...interface{}) (script []string) {
|
func Assemble(instructions ...interface{}) (script []byte) {
|
||||||
script = make([]string, len(instructions))
|
//script = make([]string, len(instructions))
|
||||||
|
|
||||||
for i, val := range instructions {
|
for _, val := range instructions {
|
||||||
instr, _ := CompileInstr(val)
|
instr, _ := CompileInstr(val)
|
||||||
|
|
||||||
script[i] = string(instr)
|
//script[i] = string(instr)
|
||||||
|
script = append(script, instr...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -186,7 +186,12 @@ func Encode(object interface{}) []byte {
|
|||||||
case byte:
|
case byte:
|
||||||
buff.Write(Encode(big.NewInt(int64(t))))
|
buff.Write(Encode(big.NewInt(int64(t))))
|
||||||
case *big.Int:
|
case *big.Int:
|
||||||
buff.Write(Encode(t.Bytes()))
|
// Not sure how this is possible while we check for
|
||||||
|
if t == nil {
|
||||||
|
buff.WriteByte(0xc0)
|
||||||
|
} else {
|
||||||
|
buff.Write(Encode(t.Bytes()))
|
||||||
|
}
|
||||||
case []byte:
|
case []byte:
|
||||||
if len(t) == 1 && t[0] <= 0x7f {
|
if len(t) == 1 && t[0] <= 0x7f {
|
||||||
buff.Write(t)
|
buff.Write(t)
|
||||||
|
Loading…
Reference in New Issue
Block a user