Commit 3616080d authored by obscuren's avatar obscuren

Added synchronisation of transactions across remote pools

parent e47230f8
...@@ -12,15 +12,16 @@ import ( ...@@ -12,15 +12,16 @@ import (
) )
type Console struct { type Console struct {
db *ethdb.MemDatabase db *ethdb.MemDatabase
trie *ethutil.Trie trie *ethutil.Trie
server *Server
} }
func NewConsole() *Console { func NewConsole(s *Server) *Console {
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
trie := ethutil.NewTrie(db, "") 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 { func (i *Console) ValidateInput(action string, argumentLength int) error {
...@@ -43,6 +44,9 @@ 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: case action == "encode" && argumentLength != 1:
err = true err = true
expArgCount = 1 expArgCount = 1
case action == "tx" && argumentLength != 2:
err = true
expArgCount = 2
} }
if err { if err {
...@@ -105,6 +109,10 @@ func (i *Console) ParseInput(input string) bool { ...@@ -105,6 +109,10 @@ func (i *Console) ParseInput(input string) bool {
fmt.Printf("%q\n", d) fmt.Printf("%q\n", d)
case "encode": case "encode":
fmt.Printf("%q\n", ethutil.Encode(tokens[1])) 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": case "exit", "quit", "q":
return false return false
case "help": case "help":
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"log" "log"
"os" "os"
"os/signal" "os/signal"
"path"
"runtime" "runtime"
) )
...@@ -44,36 +45,54 @@ func main() { ...@@ -44,36 +45,54 @@ func main() {
Init() Init()
ethutil.ReadConfig()
server, err := NewServer()
if err != nil {
log.Println(err)
return
}
if StartConsole { if StartConsole {
console := NewConsole() err := os.Mkdir(ethutil.Config.ExecPath, os.ModePerm)
console.Start() // Error is OK if the error is ErrExist
} else { if err != nil && !os.IsExist(err) {
log.Println("Starting Ethereum") log.Panic("Unable to create EXECPATH. Exiting")
server, err := NewServer() }
// 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 { if err != nil {
log.Println(err) log.Panic("Unable to set proper logger", err)
return
} }
RegisterInterupts(server) ethutil.Config.Log = log.New(file, "", 0)
if StartMining { console := NewConsole(server)
log.Println("Mining started") go console.Start()
dagger := &Dagger{} }
go func() { log.Println("Starting Ethereum")
for {
res := dagger.Search(ethutil.Big("01001"), ethutil.BigPow(2, 36)) RegisterInterupts(server)
log.Println("Res dagger", res)
//server.Broadcast("blockmine", ethutil.Encode(res.String()))
}
}()
}
server.Start() if StartMining {
log.Println("Mining started")
dagger := &Dagger{}
// Wait for shutdown go func() {
server.WaitForShutdown() 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 { ...@@ -62,7 +62,7 @@ func NewOutboundPeer(addr string, server *Server) *Peer {
server: server, server: server,
inbound: false, inbound: false,
connected: 0, connected: 0,
disconnect: 1, disconnect: 0,
} }
// Set up the connection in another goroutine so we don't block the main thread // Set up the connection in another goroutine so we don't block the main thread
...@@ -169,12 +169,12 @@ out: ...@@ -169,12 +169,12 @@ out:
// Version message // Version message
p.handleHandshake(msg) p.handleHandshake(msg)
case ethwire.MsgBlockTy: 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 { if err != nil {
log.Println(err) log.Println(err)
} }
case ethwire.MsgTxTy: 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.MsgInvTy:
case ethwire.MsgGetPeersTy: case ethwire.MsgGetPeersTy:
p.requestedPeerList = true p.requestedPeerList = true
......
...@@ -48,7 +48,7 @@ func NewServer() (*Server, error) { ...@@ -48,7 +48,7 @@ func NewServer() (*Server, error) {
return nil, err return nil, err
} }
ethutil.SetConfig(db) ethutil.Config.Db = db
nonce, _ := ethutil.RandomUint64() nonce, _ := ethutil.RandomUint64()
server := &Server{ server := &Server{
...@@ -152,28 +152,30 @@ func (s *Server) Start() { ...@@ -152,28 +152,30 @@ func (s *Server) Start() {
s.Stop() s.Stop()
} }
return
} else { } else {
log.Fatal(err) 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 // Start the reaping processes
go s.ReapDeadPeers() go s.ReapDeadPeers()
go func() { // Start the tx pool
for { s.txPool.Start()
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go s.AddPeer(conn)
}
}()
// TMP // TMP
/* /*
...@@ -196,6 +198,8 @@ func (s *Server) Stop() { ...@@ -196,6 +198,8 @@ func (s *Server) Stop() {
}) })
s.shutdownChan <- true s.shutdownChan <- true
s.txPool.Stop()
} }
// This function will wait for a shutdown and resumes main thread execution // This function will wait for a shutdown and resumes main thread execution
......
package main package main
import ( import (
"bytes"
"container/list" "container/list"
"errors" "errors"
"github.com/ethereum/ethutil-go" "github.com/ethereum/ethutil-go"
"github.com/ethereum/ethwire-go"
"log" "log"
"math/big" "math/big"
"sync" "sync"
...@@ -56,9 +58,11 @@ func NewTxPool(s *Server) *TxPool { ...@@ -56,9 +58,11 @@ func NewTxPool(s *Server) *TxPool {
// Blocking function. Don't use directly. Use QueueTransaction instead // Blocking function. Don't use directly. Use QueueTransaction instead
func (pool *TxPool) addTransaction(tx *ethutil.Transaction) { func (pool *TxPool) addTransaction(tx *ethutil.Transaction) {
pool.mutex.Lock() pool.mutex.Lock()
defer pool.mutex.Unlock()
pool.pool.PushBack(tx) 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 // Process transaction validates the Tx and processes funds from the
...@@ -89,7 +93,12 @@ func (pool *TxPool) processTransaction(tx *ethutil.Transaction) error { ...@@ -89,7 +93,12 @@ func (pool *TxPool) processTransaction(tx *ethutil.Transaction) error {
// Make sure there's enough in the sender's account. Having insufficient // Make sure there's enough in the sender's account. Having insufficient
// funds won't invalidate this transaction but simple ignores it. // funds won't invalidate this transaction but simple ignores it.
if sender.Amount.Cmp(tx.Value) < 0 { 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 // Subtract the amount from the senders account
...@@ -121,6 +130,15 @@ out: ...@@ -121,6 +130,15 @@ out:
for { for {
select { select {
case tx := <-pool.queueChan: 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 // Process the transaction
err := pool.processTransaction(tx) err := pool.processTransaction(tx)
if err != nil { if err != nil {
...@@ -144,8 +162,6 @@ func (pool *TxPool) Flush() { ...@@ -144,8 +162,6 @@ func (pool *TxPool) Flush() {
pool.mutex.Lock() pool.mutex.Lock()
defer pool.mutex.Unlock() defer pool.mutex.Unlock()
pool.mutex.Unlock()
} }
func (pool *TxPool) Start() { func (pool *TxPool) Start() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment