Merge conflicts

poc8
Maran 11 years ago
commit 0a88010826
  1. 3
      ethchain/keypair.go
  2. 22
      ethchain/stack.go
  3. 34
      ethchain/state_manager.go
  4. 81
      ethchain/transaction.go
  5. 8
      ethchain/transaction_pool.go
  6. 73
      ethchain/vm.go
  7. 157
      ethchain/vm_test.go
  8. 1
      ethutil/common.go
  9. 2
      ethutil/parsing.go
  10. 2
      ethutil/rlp.go
  11. 5
      ethutil/rlp_test.go
  12. 9
      ethutil/value.go
  13. 2
      ethwire/messaging.go
  14. 19
      peer.go

@ -34,6 +34,7 @@ func (k *KeyPair) Account() *Account {
// Create transaction, creates a new and signed transaction, ready for processing // Create transaction, creates a new and signed transaction, ready for processing
func (k *KeyPair) CreateTx(receiver []byte, value *big.Int, data []string) *Transaction { func (k *KeyPair) CreateTx(receiver []byte, value *big.Int, data []string) *Transaction {
/* TODO
tx := NewTransaction(receiver, value, data) tx := NewTransaction(receiver, value, data)
tx.Nonce = k.account.Nonce tx.Nonce = k.account.Nonce
@ -41,6 +42,8 @@ func (k *KeyPair) CreateTx(receiver []byte, value *big.Int, data []string) *Tran
tx.Sign(k.PrivateKey) tx.Sign(k.PrivateKey)
return tx return tx
*/
return nil
} }
func (k *KeyPair) RlpEncode() []byte { func (k *KeyPair) RlpEncode() []byte {

@ -173,21 +173,25 @@ func NewStack() *Stack {
} }
func (st *Stack) Pop() *big.Int { func (st *Stack) Pop() *big.Int {
str := st.data[0] str := st.data[len(st.data)-1]
st.data = st.data[1:]
copy(st.data[:len(st.data)-1], st.data[:len(st.data)-1])
st.data = st.data[:len(st.data)-1]
return str return str
} }
func (st *Stack) Popn() (*big.Int, *big.Int) { func (st *Stack) Popn() (*big.Int, *big.Int) {
ints := st.data[:2] ints := st.data[len(st.data)-2:]
st.data = st.data[2:]
copy(st.data[:len(st.data)-2], st.data[:len(st.data)-2])
st.data = st.data[:len(st.data)-2]
return ints[0], ints[1] return ints[0], ints[1]
} }
func (st *Stack) Peek() *big.Int { func (st *Stack) Peek() *big.Int {
str := st.data[0] str := st.data[len(st.data)-1]
return str return str
} }
@ -202,7 +206,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 +246,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("####################")
} }

@ -80,7 +80,7 @@ func (sm *StateManager) WatchAddr(addr []byte) *AccountState {
func (sm *StateManager) GetAddrState(addr []byte) *AccountState { func (sm *StateManager) GetAddrState(addr []byte) *AccountState {
account := sm.addrStateStore.Get(addr) account := sm.addrStateStore.Get(addr)
if account == nil { if account == nil {
a := sm.bc.CurrentBlock.state.GetAccount(addr) a := sm.procState.GetAccount(addr)
account = &AccountState{Nonce: a.Nonce, Account: a} account = &AccountState{Nonce: a.Nonce, Account: a}
} }
@ -98,16 +98,21 @@ func (sm *StateManager) MakeContract(tx *Transaction) {
} }
} }
// Apply transactions uses the transaction passed to it and applies them onto
// the current processing state.
func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) { func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) {
// Process each transaction/contract // Process each transaction/contract
for _, tx := range txs { for _, tx := range txs {
// If there's no recipient, it's a contract // If there's no recipient, it's a contract
// Check if this is a contract creation traction and if so
// create a contract of this tx.
if tx.IsContract() { if tx.IsContract() {
sm.MakeContract(tx) sm.MakeContract(tx)
//XXX block.MakeContract(tx)
} else { } else {
// Figure out if the address this transaction was sent to is a
// contract or an actual account. In case of a contract, we process that
// contract instead of moving funds between accounts.
if contract := sm.procState.GetContract(tx.Recipient); contract != nil { if contract := sm.procState.GetContract(tx.Recipient); contract != nil {
//XXX if contract := block.state.GetContract(tx.Recipient); contract != nil {
sm.ProcessContract(contract, tx, block) sm.ProcessContract(contract, tx, block)
} else { } else {
err := sm.Ethereum.TxPool().ProcessTransaction(tx, block) err := sm.Ethereum.TxPool().ProcessTransaction(tx, block)
@ -121,9 +126,9 @@ func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) {
// The prepare function, prepares the state manager for the next // The prepare function, prepares the state manager for the next
// "ProcessBlock" action. // "ProcessBlock" action.
func (sm *StateManager) Prepare(processer *State, comparative *State) { func (sm *StateManager) Prepare(processor *State, comparative *State) {
sm.compState = comparative sm.compState = comparative
sm.procState = processer sm.procState = processor
} }
// Default prepare function // Default prepare function
@ -172,14 +177,12 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
// if !sm.compState.Cmp(sm.procState) // if !sm.compState.Cmp(sm.procState)
if !sm.compState.Cmp(sm.procState) { if !sm.compState.Cmp(sm.procState) {
//XXX return fmt.Errorf("Invalid merkle root. Expected %x, got %x", block.State().trie.Root, sm.bc.CurrentBlock.State().trie.Root)
return fmt.Errorf("Invalid merkle root. Expected %x, got %x", sm.compState.trie.Root, sm.procState.trie.Root) return fmt.Errorf("Invalid merkle root. Expected %x, got %x", sm.compState.trie.Root, sm.procState.trie.Root)
} }
// Calculate the new total difficulty and sync back to the db // Calculate the new total difficulty and sync back to the db
if sm.CalculateTD(block) { if sm.CalculateTD(block) {
// Sync the current block's state to the database and cancelling out the deferred Undo // Sync the current block's state to the database and cancelling out the deferred Undo
//XXX sm.bc.CurrentBlock.Sync()
sm.procState.Sync() sm.procState.Sync()
// Broadcast the valid block back to the wire // Broadcast the valid block back to the wire
@ -276,14 +279,14 @@ func CalculateUncleReward(block *Block) *big.Int {
func (sm *StateManager) AccumelateRewards(block *Block) error { func (sm *StateManager) AccumelateRewards(block *Block) error {
// Get the coinbase rlp data // Get the coinbase rlp data
//XXX addr := processor.state.GetAccount(block.Coinbase)
addr := sm.procState.GetAccount(block.Coinbase) addr := sm.procState.GetAccount(block.Coinbase)
// Reward amount of ether to the coinbase address // Reward amount of ether to the coinbase address
addr.AddFee(CalculateBlockReward(block, len(block.Uncles))) addr.AddFee(CalculateBlockReward(block, len(block.Uncles)))
//XXX processor.state.UpdateAccount(block.Coinbase, addr)
var acc []byte var acc []byte
copy(acc, block.Coinbase) copy(acc, block.Coinbase)
sm.procState.UpdateAccount(acc, addr) sm.procState.UpdateAccount(acc, addr)
for _, uncle := range block.Uncles { for _, uncle := range block.Uncles {
uncleAddr := sm.procState.GetAccount(uncle.Coinbase) uncleAddr := sm.procState.GetAccount(uncle.Coinbase)
uncleAddr.AddFee(CalculateUncleReward(uncle)) uncleAddr.AddFee(CalculateUncleReward(uncle))
@ -301,13 +304,12 @@ func (sm *StateManager) Stop() {
func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, block *Block) { func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, block *Block) {
// Recovering function in case the VM had any errors // Recovering function in case the VM had any errors
/* defer func() {
defer func() { if r := recover(); r != nil {
if r := recover(); r != nil { fmt.Println("Recovered from VM execution with err =", r)
fmt.Println("Recovered from VM execution with err =", r) }
} }()
}()
*/
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, sm.procState, tx.Gas, tx.Value)
vm := NewVm(sm.procState, RuntimeVars{ vm := NewVm(sm.procState, RuntimeVars{

@ -1,7 +1,6 @@
package ethchain package ethchain
import ( import (
"bytes"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/secp256k1-go" "github.com/obscuren/secp256k1-go"
"math/big" "math/big"
@ -18,31 +17,19 @@ type Transaction struct {
Data []string Data []string
v byte v byte
r, s []byte r, s []byte
}
func NewTransaction(to []byte, value *big.Int, data []string) *Transaction {
tx := Transaction{Recipient: to, Value: value, Nonce: 0, Data: data}
return &tx // Indicates whether this tx is a contract creation transaction
contractCreation bool
} }
func NewContractCreationTx(value, gasprice *big.Int, data []string) *Transaction { func NewContractCreationTx(value, gasprice *big.Int, data []string) *Transaction {
return &Transaction{Value: value, Gasprice: gasprice, Data: data} return &Transaction{Value: value, Gasprice: gasprice, Data: data, contractCreation: true}
} }
func NewContractMessageTx(to []byte, value, gasprice, gas *big.Int, data []string) *Transaction { func NewTransactionMessage(to []byte, value, gasprice, gas *big.Int, data []string) *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}
} }
func NewTx(to []byte, value *big.Int, data []string) *Transaction {
return &Transaction{Recipient: to, Value: value, Gasprice: big.NewInt(0), Gas: big.NewInt(0), Nonce: 0, Data: data}
}
// XXX Deprecated
func NewTransactionFromData(data []byte) *Transaction {
return NewTransactionFromBytes(data)
}
func NewTransactionFromBytes(data []byte) *Transaction { func NewTransactionFromBytes(data []byte) *Transaction {
tx := &Transaction{} tx := &Transaction{}
tx.RlpDecode(data) tx.RlpDecode(data)
@ -74,7 +61,7 @@ func (tx *Transaction) Hash() []byte {
} }
func (tx *Transaction) IsContract() bool { func (tx *Transaction) IsContract() bool {
return bytes.Compare(tx.Recipient, ContractAddr) == 0 return tx.contractCreation
} }
func (tx *Transaction) Signature(key []byte) []byte { func (tx *Transaction) Signature(key []byte) []byte {
@ -124,16 +111,14 @@ func (tx *Transaction) Sign(privk []byte) error {
} }
func (tx *Transaction) RlpData() interface{} { func (tx *Transaction) RlpData() interface{} {
// Prepare the transaction for serialization data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice}
return []interface{}{
tx.Nonce, if !tx.contractCreation {
tx.Recipient, data = append(data, tx.Recipient, tx.Gas)
tx.Value,
ethutil.NewSliceValue(tx.Data).Slice(),
tx.v,
tx.r,
tx.s,
} }
d := ethutil.NewSliceValue(tx.Data).Slice()
return append(data, d, tx.v, tx.r, tx.s)
} }
func (tx *Transaction) RlpValue() *ethutil.Value { func (tx *Transaction) RlpValue() *ethutil.Value {
@ -150,17 +135,35 @@ func (tx *Transaction) RlpDecode(data []byte) {
func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) { func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
tx.Nonce = decoder.Get(0).Uint() tx.Nonce = decoder.Get(0).Uint()
tx.Recipient = decoder.Get(1).Bytes() tx.Value = decoder.Get(1).BigInt()
tx.Value = decoder.Get(2).BigInt() tx.Gasprice = decoder.Get(2).BigInt()
d := decoder.Get(3) // If the 4th item is a list(slice) this tx
tx.Data = make([]string, d.Len()) // is a contract creation tx
for i := 0; i < d.Len(); i++ { if decoder.Get(3).IsList() {
tx.Data[i] = d.Get(i).Str() 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
} 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.r = decoder.Get(7).Bytes()
tx.s = decoder.Get(8).Bytes()
} }
// TODO something going wrong here
tx.v = byte(decoder.Get(4).Uint())
tx.r = decoder.Get(5).Bytes()
tx.s = decoder.Get(6).Bytes()
} }

@ -208,7 +208,7 @@ func (pool *TxPool) QueueTransaction(tx *Transaction) {
pool.queueChan <- tx pool.queueChan <- tx
} }
func (pool *TxPool) Flush() []*Transaction { func (pool *TxPool) CurrentTransactions() []*Transaction {
pool.mutex.Lock() pool.mutex.Lock()
defer pool.mutex.Unlock() defer pool.mutex.Unlock()
@ -222,6 +222,12 @@ func (pool *TxPool) Flush() []*Transaction {
i++ i++
} }
return txList
}
func (pool *TxPool) Flush() []*Transaction {
txList := pool.CurrentTransactions()
// Recreate a new list all together // Recreate a new list all together
// XXX Is this the fastest way? // XXX Is this the fastest way?
pool.pool = list.New() pool.pool = list.New()

@ -2,14 +2,24 @@ 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"
"log"
_ "math" _ "math"
"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 +80,43 @@ 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)
}
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 {
ethutil.Config.Log.Debugln("Insufficient gas", closure.Gas, gas)
if closure.Gas.Cmp(fee) < 0 {
return closure.Return(nil) return closure.Return(nil)
} }
@ -172,10 +215,17 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
} else { } else {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
} }
case oNOT: case oEQ:
x, y := stack.Popn() x, y := stack.Popn()
// x != y // x == y
if x.Cmp(y) != 0 { if x.Cmp(y) == 0 {
stack.Push(ethutil.BigTrue)
} else {
stack.Push(ethutil.BigFalse)
}
case oNOT:
x := stack.Pop()
if x.Cmp(ethutil.BigFalse) == 0 {
stack.Push(ethutil.BigTrue) stack.Push(ethutil.BigTrue)
} else { } else {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
@ -259,8 +309,8 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
case oJUMP: case oJUMP:
pc = stack.Pop() pc = stack.Pop()
case oJUMPI: case oJUMPI:
pos, cond := stack.Popn() cond, pos := stack.Popn()
if cond.Cmp(big.NewInt(0)) > 0 { if cond.Cmp(ethutil.BigTrue) == 0 {
pc = pos pc = pos
} }
case oPC: case oPC:
@ -273,6 +323,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
retSize, retOffset := stack.Popn() retSize, retOffset := stack.Popn()
// Pop input size and offset // Pop input size and offset
inSize, inOffset := stack.Popn() inSize, inOffset := stack.Popn()
fmt.Println(inSize, inOffset)
// Get the arguments from the memory // Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64()) args := mem.Get(inOffset.Int64(), inSize.Int64())
// Pop gas and value of the stack. // Pop gas and value of the stack.
@ -317,6 +368,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte {
} }
} }
/*
func makeInlineTx(addr []byte, value, from, length *big.Int, contract *Contract, state *State) { func makeInlineTx(addr []byte, value, from, length *big.Int, contract *Contract, state *State) {
ethutil.Config.Log.Debugf(" => creating inline tx %x %v %v %v", addr, value, from, length) ethutil.Config.Log.Debugf(" => creating inline tx %x %v %v %v", addr, value, from, length)
j := int64(0) j := int64(0)
@ -353,3 +405,4 @@ func contractMemory(state *State, contractAddr []byte, memAddr *big.Int) *big.In
return decoder.BigInt() return decoder.BigInt()
} }
*/

@ -1,114 +1,17 @@
package ethchain 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("")
@ -127,12 +30,12 @@ func TestRun3(t *testing.T) {
"PUSH", "0", "PUSH", "0",
"RETURN", "RETURN",
}) })
tx := NewTransaction(ContractAddr, ethutil.Big("100000000000000000000000000000000000000000000000000"), script) tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script)
addr := tx.Hash()[12:] addr := tx.Hash()[12:]
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",
@ -149,7 +52,7 @@ func TestRun3(t *testing.T) {
"PUSH", 0, "PUSH", 0,
"RETURN", "RETURN",
) )
callerTx := NewTransaction(ContractAddr, ethutil.Big("100000000000000000000000000000000000000000000000000"), callerScript) callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript)
// Contract addr as test address // Contract addr as test address
account := NewAccount(ContractAddr, big.NewInt(10000000)) account := NewAccount(ContractAddr, big.NewInt(10000000))
@ -171,4 +74,50 @@ func TestRun3(t *testing.T) {
if bytes.Compare(ret, exp) != 0 { if bytes.Compare(ret, exp) != 0 {
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, ""))
asm, err := mutan.Compile(strings.NewReader(`
a = 10
b = 10
if a == b {
c = 10
if c == 10 {
d = 1000
e = 10
}
}
store[0] = 20
store[a] = 20
`), false)
if err != nil {
fmt.Println(err)
}
//asm = append(asm, "LOG")
fmt.Println(asm)
callerScript := ethutil.Assemble(asm...)
callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), 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)
} }

@ -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)
) )

@ -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 {

@ -57,7 +57,7 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} {
switch { switch {
case char == 0: case char == 0:
return nil return nil
case char <= 0x7c: case char <= 0x7f:
return char return char
case char <= 0xb7: case char <= 0xb7:

@ -129,6 +129,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"})

@ -149,6 +149,15 @@ func (val *Value) IsStr() bool {
return val.Type() == reflect.String return val.Type() == reflect.String
} }
// Special list checking function. Something is considered
// a list if it's of type []interface{}. The list is usually
// used in conjunction with rlp decoded streams.
func (val *Value) IsList() bool {
_, ok := val.Val.([]interface{})
return ok
}
func (val *Value) IsEmpty() bool { func (val *Value) IsEmpty() bool {
return val.Val == nil || ((val.IsSlice() || val.IsStr()) && val.Len() == 0) return val.Val == nil || ((val.IsSlice() || val.IsStr()) && val.Len() == 0)
} }

@ -32,6 +32,7 @@ const (
MsgBlockTy = 0x13 MsgBlockTy = 0x13
MsgGetChainTy = 0x14 MsgGetChainTy = 0x14
MsgNotInChainTy = 0x15 MsgNotInChainTy = 0x15
MsgGetTxsTy = 0x16
MsgTalkTy = 0xff MsgTalkTy = 0xff
) )
@ -46,6 +47,7 @@ var msgTypeToString = map[MsgType]string{
MsgTxTy: "Transactions", MsgTxTy: "Transactions",
MsgBlockTy: "Blocks", MsgBlockTy: "Blocks",
MsgGetChainTy: "Get chain", MsgGetChainTy: "Get chain",
MsgGetTxsTy: "Get Txs",
MsgNotInChainTy: "Not in chain", MsgNotInChainTy: "Not in chain",
} }

@ -396,7 +396,8 @@ func (p *Peer) HandleInbound() {
// in the TxPool where it will undergo validation and // in the TxPool where it will undergo validation and
// processing when a new block is found // processing when a new block is found
for i := 0; i < msg.Data.Len(); i++ { for i := 0; i < msg.Data.Len(); i++ {
p.ethereum.TxPool().QueueTransaction(ethchain.NewTransactionFromData(msg.Data.Get(i).Encode())) tx := ethchain.NewTransactionFromValue(msg.Data.Get(i))
p.ethereum.TxPool().QueueTransaction(tx)
} }
case ethwire.MsgGetPeersTy: case ethwire.MsgGetPeersTy:
// Flag this peer as a 'requested of new peers' this to // Flag this peer as a 'requested of new peers' this to
@ -462,6 +463,16 @@ func (p *Peer) HandleInbound() {
case ethwire.MsgNotInChainTy: case ethwire.MsgNotInChainTy:
ethutil.Config.Log.Infof("Not in chain %x\n", msg.Data) ethutil.Config.Log.Infof("Not in chain %x\n", msg.Data)
// TODO // TODO
case ethwire.MsgGetTxsTy:
// Get the current transactions of the pool
txs := p.ethereum.TxPool().CurrentTransactions()
// Get the RlpData values from the txs
txsInterface := make([]interface{}, len(txs))
for i, tx := range txs {
txsInterface[i] = tx.RlpData()
}
// Broadcast it back to the peer
p.QueueMessage(ethwire.NewMessage(ethwire.MsgTxTy, txsInterface))
// Unofficial but fun nonetheless // Unofficial but fun nonetheless
case ethwire.MsgTalkTy: case ethwire.MsgTalkTy:
@ -649,7 +660,11 @@ func (p *Peer) CatchupWithPeer(blockHash []byte) {
msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(50)}) msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(50)})
p.QueueMessage(msg) p.QueueMessage(msg)
ethutil.Config.Log.Debugf("Requesting blockchain %x...\n", blockHash[:4]) ethutil.Config.Log.Debugf("Requesting blockchain %x...\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4])
msg = ethwire.NewMessage(ethwire.MsgGetTxsTy, []interface{}{})
p.QueueMessage(msg)
ethutil.Config.Log.Debugln("Requested transactions")
} }
} }

Loading…
Cancel
Save