Merge conflicts
This commit is contained in:
commit
0a88010826
|
@ -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 {
|
// Indicates whether this tx is a contract creation transaction
|
||||||
tx := Transaction{Recipient: to, Value: value, Nonce: 0, Data: data}
|
contractCreation bool
|
||||||
|
|
||||||
return &tx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
peer.go
19
peer.go
|
@ -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…
Reference in New Issue