Skip to content

Commit

Permalink
merge dev
Browse files Browse the repository at this point in the history
  • Loading branch information
chadlagore committed Jul 12, 2017
2 parents 3b1804f + 2fef206 commit c805f49
Show file tree
Hide file tree
Showing 23 changed files with 463 additions and 304 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ vendor

# Text Editors and IDEs
.vscode

# Log files
logfile
74 changes: 53 additions & 21 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package app

import (
"fmt"
"os"
"os/signal"
"syscall"

log "github.com/Sirupsen/logrus"
"github.com/google/uuid"
Expand All @@ -15,9 +18,9 @@ import (
)

var (
config *conf.Config
// TODO peer store once it's merged in
chain *blockchain.BlockChain
config *conf.Config
chain *blockchain.BlockChain
logFile = os.Stdout
// A reference to the transaction pool
tpool *pool.Pool
)
Expand All @@ -28,6 +31,24 @@ func Run(cfg conf.Config) {
log.Info("Starting Cumulus node")
config = &cfg

// Set logging level
if cfg.Verbose {
log.SetLevel(log.DebugLevel)
}

// Start a goroutine that waits for program termination. Before the program
// exits it will flush logs and save the blockchain.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
log.Info("Saving blockchain and flushing logs...")
// TODO
logFile.Sync()
logFile.Close()
os.Exit(0)
}()

// Below we'll connect to peers. After which, requests could begin to
// stream in. We should first initalize our pool, workers to handle
// incoming messages.
Expand All @@ -42,7 +63,7 @@ func Run(cfg conf.Config) {
// Start listening on the given interface and port so we can receive
// conenctions from other peers
log.Infof("Starting listener on %s:%d", cfg.Interface, cfg.Port)
peer.LocalAddr = fmt.Sprintf("%s:%d", cfg.Interface, cfg.Port)
peer.ListenAddr = fmt.Sprintf("%s:%d", cfg.Interface, cfg.Port)
go func() {
address := fmt.Sprintf("%s:%d", cfg.Interface, cfg.Port)
err := conn.Listen(address, peer.ConnectionHandler)
Expand All @@ -53,8 +74,21 @@ func Run(cfg conf.Config) {
}
}()

// Connect to the target and discover its peers.
ConnectAndDiscover(cfg.Target)
// If the console flag was passed, redirect logs to a file and run the console
if cfg.Console {
logFile, err := os.OpenFile("logfile", os.O_WRONLY|os.O_CREATE, 0755)
if err != nil {
log.WithError(err).Fatal("Failed to redirect logs to log file")
}
log.Warn("Redirecting logs to logfile")
log.SetOutput(logFile)
go RunConsole()
}

if len(config.Target) > 0 {
// Connect to the target and discover its peers.
ConnectAndDiscover(cfg.Target)
}

// Try maintain as close to peer.MaxPeers connections as possible while this
// peer is running
Expand All @@ -67,30 +101,28 @@ func Run(cfg conf.Config) {
}

// Return to command line.
select {}
select {} // Hang main thread. Everything happens in goroutines from here
}

// ConnectAndDiscover tries to connect to a target and discover its peers.
func ConnectAndDiscover(target string) {
if len(target) > 0 {
peerInfoRequest := msg.Request{
ID: uuid.New().String(),
ResourceType: msg.ResourcePeerInfo,
}
peerInfoRequest := msg.Request{
ID: uuid.New().String(),
ResourceType: msg.ResourcePeerInfo,
}

log.Infof("Dialing target %s", target)
c, err := conn.Dial(target)
if err != nil {
log.WithError(err).Fatalf("Failed to connect to target")
}
peer.ConnectionHandler(c)
p := peer.PStore.Get(c.RemoteAddr().String())
p.Request(peerInfoRequest, peer.PeerInfoHandler)
log.Infof("Dialing target %s", target)
c, err := conn.Dial(target)
if err != nil {
log.WithError(err).Fatalf("Failed to connect to target")
}
peer.ConnectionHandler(c)
p := peer.PStore.Get(c.RemoteAddr().String())
p.Request(peerInfoRequest, peer.PeerInfoHandler)
}

// RequestHandler is called every time a peer sends us a request message except
// on peers whos PushHandlers have been overridden.
// on peers whos RequestHandlers have been overridden.
func RequestHandler(req *msg.Request) msg.Response {
res := msg.Response{ID: req.ID}
typeErr := msg.NewProtocolError(msg.InvalidResourceType,
Expand Down
20 changes: 17 additions & 3 deletions app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestInitializeNode(t *testing.T) {

func TestPushHandlerNewBlock(t *testing.T) {
intializeQueues()
_, b := blockchain.NewValidChainAndBlock()
_, b := blockchain.NewValidTestChainAndBlock()
push := msg.Push{
ResourceType: msg.ResourceBlock,
Resource: b,
Expand All @@ -81,9 +81,9 @@ func TestPushHandlerNewBlock(t *testing.T) {
// Add more here...
}

func TestPushHandlerNewTransaction(t *testing.T) {
func TestPushHandlerNewTestTransaction(t *testing.T) {
intializeQueues()
txn := blockchain.NewTransaction()
txn := blockchain.NewTestTransaction()
push := msg.Push{
ResourceType: msg.ResourceTransaction,
Resource: txn,
Expand Down Expand Up @@ -117,6 +117,7 @@ func TestRequestHandlerNewBlockOK(t *testing.T) {
"block number should be "+string(blockNumber))
}

<<<<<<< HEAD
func TestRequestHandlerNewBlockBadParams(t *testing.T) {
initializeChain()

Expand Down Expand Up @@ -160,4 +161,17 @@ func TestRequestHandlerPeerInfo(t *testing.T) {
// Make sure request did not fail.
assert.NotNil(t, res, "resource should contain peer info")
// Assert peer address returned valid.
=======
func TestRequestHandlerNewTestTransaction(t *testing.T) {
intializeQueues()
push := msg.Request{ResourceType: msg.ResourceTransaction}
RequestHandler(&push)
select {
case _, ok := <-TransactionWorkQueue:
if !ok {
t.FailNow()
}
}
// Add more here...
>>>>>>> dev
}
111 changes: 111 additions & 0 deletions app/console.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package app

import (
"strconv"

"github.com/abiosoft/ishell"
"github.com/ubclaunchpad/cumulus/blockchain"
"github.com/ubclaunchpad/cumulus/conn"
"github.com/ubclaunchpad/cumulus/peer"
)

var shell *ishell.Shell

// RunConsole starts the Cumulus console. This should be run only once as a
// goroutine, and logging should be redirected away from stdout before it is run.
func RunConsole() {
shell = ishell.New()
shell.AddCmd(&ishell.Cmd{
Name: "create",
Help: "create a new wallet hash or transaction",
Func: create,
})
shell.AddCmd(&ishell.Cmd{
Name: "check",
Help: "check the status of a transaction or wallet",
Func: check,
})
shell.AddCmd(&ishell.Cmd{
Name: "listen-address",
Help: "show the address this host is listening on",
Func: listenAddr,
})
shell.AddCmd(&ishell.Cmd{
Name: "peers",
Help: "show the peers this host is connected to",
Func: peers,
})
shell.AddCmd(&ishell.Cmd{
Name: "connect",
Help: "connect to another peer",
Func: connect,
})

shell.Start()
shell.Println("Cumulus Console")
}

func create(ctx *ishell.Context) {
choice := ctx.MultiChoice([]string{
"Wallet",
"Transaction",
}, "What would you like to create?")
if choice == 0 {
ctx.Println("New Wallet:", blockchain.NewWallet().Public())
} else {
shell.Print("Sender wallet ID: ")
senderID := shell.ReadLine()
shell.Print("Recipient wallet ID: ")
recipientID := shell.ReadLine()
shell.Print("Amount to send: ")
amount, err := strconv.ParseFloat(shell.ReadLine(), 64)
if err != nil {
shell.Println("Invalid number format. Please enter an amount in decimal format.")
return
}

// TODO: make transaction, add it to the pool, broadcast it
ctx.Printf(`\nNew Transaction: \nSenderID: %s \nRecipiendID: %s\nAmount: %f"`,
senderID, recipientID, amount)
}
}

func check(ctx *ishell.Context) {
choice := ctx.MultiChoice([]string{
"Wallet",
"Transaction",
}, "What would you like to check the status of?")
if choice == 0 {
ctx.Println("Wallet status: ")
} else {
ctx.Println("Transaction status: ")
}
}

func listenAddr(ctx *ishell.Context) {
shell.Println("Listening on", peer.ListenAddr)
}

func peers(tcx *ishell.Context) {
shell.Println("Connected to", peer.PStore.Addrs())
}

func connect(ctx *ishell.Context) {
if len(ctx.Args) == 0 {
shell.Println("Usage: connect [IP address]:[TCP port]")
return
}

addr := ctx.Args[0]
c, err := conn.Dial(addr)
if err != nil {
shell.Println("Failed to dial peer", addr, ":", err)
return
}
peer.ConnectionHandler(c)
if peer.PStore.Get(addr) == nil {
shell.Println("Failed to extablish connection. See logs for details.")
} else {
shell.Println("Connected to", addr)
}
}
6 changes: 3 additions & 3 deletions app/worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ func (r *MockResponder) Unlock() {
}

func init() {
badTxn = bc.NewTransaction()
badBlk = bc.NewBlock()
badTxn = bc.NewTestTransaction()
badBlk = bc.NewTestBlock()
}

func reset() {
tpool = pool.New()
chain, legitBlock = bc.NewValidChainAndBlock()
chain, legitBlock = bc.NewValidTestChainAndBlock()
legitTransaction = legitBlock.Transactions[1]
realWorker = NewWorker(7)
mockResponder = MockResponder{
Expand Down
4 changes: 2 additions & 2 deletions blockchain/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

func TestEncodeDecodeBlock(t *testing.T) {
b1 := NewBlock()
b1 := NewTestBlock()

buf := bytes.NewBuffer(make([]byte, 0, b1.Len()))

Expand All @@ -19,7 +19,7 @@ func TestEncodeDecodeBlock(t *testing.T) {
}

func TestContainsTransaction(t *testing.T) {
b := NewBlock()
b := NewTestBlock()

if exists, _ := b.ContainsTransaction(b.Transactions[0]); !exists {
t.Fail()
Expand Down
2 changes: 1 addition & 1 deletion blockchain/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestMain(t *testing.T) {
}

func TestEncodeDecodeBlockChain(t *testing.T) {
b1 := NewBlockChain()
b1 := NewTestBlockChain()

buf := bytes.NewBuffer(make([]byte, 0, b1.Len()))

Expand Down
Loading

0 comments on commit c805f49

Please sign in to comment.