Added synchronisation of transactions across remote pools

This commit is contained in:
obscuren 2014-01-21 23:27:08 +01:00
parent e47230f82d
commit 3616080db4
5 changed files with 103 additions and 56 deletions

@ -12,15 +12,16 @@ import (
)
type Console struct {
db *ethdb.MemDatabase
trie *ethutil.Trie
db *ethdb.MemDatabase
trie *ethutil.Trie
server *Server
}
func NewConsole() *Console {
func NewConsole(s *Server) *Console {
db, _ := ethdb.NewMemDatabase()
trie := ethutil.NewTrie(db, "")
return &Console{db: db, trie: trie}
return &Console{db: db, trie: trie, server: s}
}
func (i *Console) ValidateInput(action string, argumentLength int) error {
@ -43,6 +44,9 @@ func (i *Console) ValidateInput(action string, argumentLength int) error {
case action == "encode" && argumentLength != 1:
err = true
expArgCount = 1
case action == "tx" && argumentLength != 2:
err = true
expArgCount = 2
}
if err {
@ -105,6 +109,10 @@ func (i *Console) ParseInput(input string) bool {
fmt.Printf("%q\n", d)
case "encode":
fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
case "tx":
tx := ethutil.NewTransaction(tokens[1], ethutil.Big(tokens[2]), []string{""})
i.server.txPool.QueueTransaction(tx)
case "exit", "quit", "q":
return false
case "help":

@ -7,6 +7,7 @@ import (
"log"
"os"
"os/signal"
"path"
"runtime"
)
@ -44,36 +45,54 @@ func main() {
Init()
if StartConsole {
console := NewConsole()
console.Start()
} else {
log.Println("Starting Ethereum")
server, err := NewServer()
ethutil.ReadConfig()
if err != nil {
log.Println(err)
return
}
server, err := NewServer()
RegisterInterupts(server)
if StartMining {
log.Println("Mining started")
dagger := &Dagger{}
go func() {
for {
res := dagger.Search(ethutil.Big("01001"), ethutil.BigPow(2, 36))
log.Println("Res dagger", res)
//server.Broadcast("blockmine", ethutil.Encode(res.String()))
}
}()
}
server.Start()
// Wait for shutdown
server.WaitForShutdown()
if err != nil {
log.Println(err)
return
}
if StartConsole {
err := os.Mkdir(ethutil.Config.ExecPath, os.ModePerm)
// Error is OK if the error is ErrExist
if err != nil && !os.IsExist(err) {
log.Panic("Unable to create EXECPATH. Exiting")
}
// TODO The logger will eventually be a non blocking logger. Logging is a expensive task
// Log to file only
file, err := os.OpenFile(path.Join(ethutil.Config.ExecPath, "debug.log"), os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
log.Panic("Unable to set proper logger", err)
}
ethutil.Config.Log = log.New(file, "", 0)
console := NewConsole(server)
go console.Start()
}
log.Println("Starting Ethereum")
RegisterInterupts(server)
if StartMining {
log.Println("Mining started")
dagger := &Dagger{}
go func() {
for {
res := dagger.Search(ethutil.Big("01001"), ethutil.BigPow(2, 36))
log.Println("Res dagger", res)
//server.Broadcast("blockmine", ethutil.Encode(res.String()))
}
}()
}
server.Start()
// Wait for shutdown
server.WaitForShutdown()
}

@ -62,7 +62,7 @@ func NewOutboundPeer(addr string, server *Server) *Peer {
server: server,
inbound: false,
connected: 0,
disconnect: 1,
disconnect: 0,
}
// Set up the connection in another goroutine so we don't block the main thread
@ -169,12 +169,12 @@ out:
// Version message
p.handleHandshake(msg)
case ethwire.MsgBlockTy:
err := p.server.blockManager.ProcessBlock(ethutil.NewBlock(ethutil.Encode(msg.Data)))
err := p.server.blockManager.ProcessBlock(ethutil.NewBlock(msg.Data))
if err != nil {
log.Println(err)
}
case ethwire.MsgTxTy:
p.server.txPool.QueueTransaction(ethutil.NewTransactionFromData(ethutil.Encode(msg.Data)))
p.server.txPool.QueueTransaction(ethutil.NewTransactionFromData(msg.Data))
case ethwire.MsgInvTy:
case ethwire.MsgGetPeersTy:
p.requestedPeerList = true

@ -48,7 +48,7 @@ func NewServer() (*Server, error) {
return nil, err
}
ethutil.SetConfig(db)
ethutil.Config.Db = db
nonce, _ := ethutil.RandomUint64()
server := &Server{
@ -152,28 +152,30 @@ func (s *Server) Start() {
s.Stop()
}
return
} else {
log.Fatal(err)
}
} else {
// Starting accepting connections
go func() {
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go s.AddPeer(conn)
}
}()
}
// Start the reaping processes
go s.ReapDeadPeers()
go func() {
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go s.AddPeer(conn)
}
}()
// Start the tx pool
s.txPool.Start()
// TMP
/*
@ -196,6 +198,8 @@ func (s *Server) Stop() {
})
s.shutdownChan <- true
s.txPool.Stop()
}
// This function will wait for a shutdown and resumes main thread execution

@ -1,9 +1,11 @@
package main
import (
"bytes"
"container/list"
"errors"
"github.com/ethereum/ethutil-go"
"github.com/ethereum/ethwire-go"
"log"
"math/big"
"sync"
@ -56,9 +58,11 @@ func NewTxPool(s *Server) *TxPool {
// Blocking function. Don't use directly. Use QueueTransaction instead
func (pool *TxPool) addTransaction(tx *ethutil.Transaction) {
pool.mutex.Lock()
defer pool.mutex.Unlock()
pool.pool.PushBack(tx)
pool.mutex.Unlock()
// Broadcast the transaction to the rest of the peers
pool.server.Broadcast(ethwire.MsgTxTy, tx.RlpEncode())
}
// Process transaction validates the Tx and processes funds from the
@ -89,7 +93,12 @@ func (pool *TxPool) processTransaction(tx *ethutil.Transaction) error {
// Make sure there's enough in the sender's account. Having insufficient
// funds won't invalidate this transaction but simple ignores it.
if sender.Amount.Cmp(tx.Value) < 0 {
return errors.New("Insufficient amount in sender's account")
if Debug {
log.Println("Insufficient amount in sender's account. Adding 1 ETH for debug")
sender.Amount = ethutil.BigPow(10, 18)
} else {
return errors.New("Insufficient amount in sender's account")
}
}
// Subtract the amount from the senders account
@ -121,6 +130,15 @@ out:
for {
select {
case tx := <-pool.queueChan:
hash := tx.Hash()
foundTx := FindTx(pool.pool, func(tx *ethutil.Transaction, e *list.Element) bool {
return bytes.Compare(tx.Hash(), hash) == 0
})
if foundTx != nil {
break
}
// Process the transaction
err := pool.processTransaction(tx)
if err != nil {
@ -144,8 +162,6 @@ func (pool *TxPool) Flush() {
pool.mutex.Lock()
defer pool.mutex.Unlock()
pool.mutex.Unlock()
}
func (pool *TxPool) Start() {