Skip to content

Commit

Permalink
Update getLocalChain, update tests, add UpToDate for blockchain sync
Browse files Browse the repository at this point in the history
  • Loading branch information
bfbachmann committed Aug 13, 2017
1 parent a660454 commit 4fc353b
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 33 deletions.
28 changes: 14 additions & 14 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func Run(cfg conf.Config) {
a := App{
PeerStore: peer.NewPeerStore(addr),
CurrentUser: user,
Chain: getLocalChain(user),
Chain: createBlockchain(user),
Pool: getLocalPool(),
blockQueue: make(chan *blockchain.Block, blockQueueSize),
transactionQueue: make(chan *blockchain.Transaction, transactionQueueSize),
Expand Down Expand Up @@ -171,6 +171,8 @@ func (a *App) RequestHandler(req *msg.Request) msg.Response {
"Resource not found.")
badRequestErr := msg.NewProtocolError(msg.BadRequest,
"Bad request")
upToDateErr := msg.NewProtocolError(msg.UpToDate,
"The requested block has not yet been mined")

switch req.ResourceType {
case msg.ResourcePeerInfo:
Expand All @@ -190,6 +192,9 @@ func (a *App) RequestHandler(req *msg.Request) msg.Response {
if err != nil {
res.Error = badRequestErr
break
} else if len(a.Chain.Blocks) > 0 && hash == blockchain.HashSum(a.Chain.LastBlock()) {
res.Error = upToDateErr
break
}

block, err := a.Chain.GetBlockByLastBlockHash(hash)
Expand Down Expand Up @@ -230,19 +235,19 @@ func (a *App) PushHandler(push *msg.Push) {
}
}

// getLocalChain returns an instance of the blockchain.
func getLocalChain(user *User) *blockchain.BlockChain {
// TODO: Look for local chain on disk. If doesn't exist, go rummaging
// createBlockchain returns a new instance of a blockchain with only a genesis
// block.
func createBlockchain(user *User) *blockchain.BlockChain {
// around on the internets for one.
bc := blockchain.BlockChain{
Blocks: make([]*blockchain.Block, 0),
Head: blockchain.NilHash,
}

genisisBlock := blockchain.Genesis(user.Wallet.Public(),
genesisBlock := blockchain.Genesis(user.Wallet.Public(),
consensus.CurrentTarget(), consensus.StartingBlockReward, []byte{})

bc.AppendBlock(genisisBlock)
bc.AppendBlock(genesisBlock)
return &bc
}

Expand Down Expand Up @@ -344,7 +349,6 @@ func (a *App) Mine() {
// to any peers.
func (a *App) SyncBlockChain() (bool, error) {
var currentHeadHash blockchain.Hash
prevHead := a.Chain.LastBlock()
newBlockChan := make(chan *blockchain.Block)
errChan := make(chan *msg.ProtocolError)
changed := false
Expand All @@ -364,7 +368,6 @@ func (a *App) SyncBlockChain() (bool, error) {

block, err := blockchain.DecodeBlockJSON(blockBytes)
if err != nil {
log.WithError(err).Error("Error decoding block")
newBlockChan <- nil
return
}
Expand Down Expand Up @@ -424,17 +427,14 @@ func (a *App) SyncBlockChain() (bool, error) {
a.Chain.AppendBlock(newBlock)
changed = true

if (&newBlock.BlockHeader).Equal(&prevHead.BlockHeader) {
// Our blockchain is up to date
return changed, nil
}

case err := <-errChan:
if err.Code == msg.ResourceNotFound {
// Our chain might be out of sync, roll it back by one block
// and request the next block
prevHead = a.Chain.RollBack()
a.Chain.RollBack()
changed = true
} else if err.Code == msg.UpToDate {
return changed, nil
}

// Some other protocol error occurred. Try again
Expand Down
25 changes: 12 additions & 13 deletions app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,17 @@ func TestPushHandlerNewTestTransaction(t *testing.T) {
}
}

// TODO: Enable once block request by hash implemented.
// func TestRequestHandlerNewBlockOK(t *testing.T) {
// // Request a new block by hash and verify we get the right one.
// a := createNewTestApp()
func TestRequestHandlerNewBlockOK(t *testing.T) {
// Request a new block by hash and verify we get the right one.
a := createNewTestApp()

// req := createNewTestBlockRequest(a.Chain.Blocks[1].LastBlock)
// resp := a.RequestHandler(req)
// block, ok := resp.Resource.(*blockchain.Block)
req := createNewTestBlockRequest(a.Chain.Blocks[1].LastBlock)
resp := a.RequestHandler(req)
block, ok := resp.Resource.(*blockchain.Block)

// assert.True(t, ok, "resource should contain block")
// assert.Equal(t, block, a.Chain.Blocks[1])
// }
assert.True(t, ok, "resource should contain block")
assert.Equal(t, block, a.Chain.Blocks[1])
}

func TestRequestHandlerNewBlockBadParams(t *testing.T) {
a := createNewTestApp()
Expand All @@ -73,7 +72,7 @@ func TestRequestHandlerNewBlockBadParams(t *testing.T) {

// Make sure request failed.
assert.False(t, ok, "resource should not contain block")
assert.Equal(t, msg.ResourceNotFound, int(resp.Error.Code), resp.Error.Message)
assert.Equal(t, msg.BadRequest, int(resp.Error.Code), resp.Error.Message)
}

func TestRequestHandlerNewBlockBadType(t *testing.T) {
Expand Down Expand Up @@ -161,8 +160,8 @@ func TestGetLocalPool(t *testing.T) {
assert.NotNil(t, getLocalPool())
}

func TestGetLocalChain(t *testing.T) {
assert.NotNil(t, getLocalChain(NewUser()))
func TestCreateBlockchain(t *testing.T) {
assert.NotNil(t, createBlockchain(NewUser()))
}

func TestHandleBlock(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions app/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
"github.com/ubclaunchpad/cumulus/pool"
)

func createNewTestBlockRequest(lastBlock interface{}) *msg.Request {
func createNewTestBlockRequest(lastBlockHash interface{}) *msg.Request {
params := make(map[string]interface{}, 1)
params["lastBlock"] = lastBlock
params["lastBlockHash"] = lastBlockHash
return &msg.Request{
ResourceType: msg.ResourceBlock,
Params: params,
Expand Down
10 changes: 7 additions & 3 deletions msg/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,20 @@ const (
)

const (
// BadRequest occurs when a malformatted request is received
// BadRequest occurs when a malformatted request is received.
BadRequest = 400
// InvalidResourceType occurs when a request is received with an unknown
// ResourceType value.
InvalidResourceType = 401
// ResourceNotFound occurs when a node reports the requested resource missing.
ResourceNotFound = 404
// RequestTimeout occurs when a peer does not respond to a request within
// some predefined period of time (see peer.DefaultRequestTimeout)
RequestTimeout = 408
// ResourceNotFound occurs when a node reports the requested resource missing.
ResourceNotFound = 404
// UpToDate occurs when a block request is received for a block that has
// not yet been mined (i.e. the lastBlockHash param in the request is the
// hash of the latest block in the blockchain).
UpToDate = 416
// NotImplemented occurs when a message or request is received whos response
// requires functionality that does not yet exist.
NotImplemented = 501
Expand Down
2 changes: 1 addition & 1 deletion peer/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (p *Peer) Dispatch() {
res := message.(*msg.Response)
rh := p.getResponseHandler(res.ID)
if rh == nil {
log.Error("Dispatcher could not find response handler for response on peer",
log.Errorf("Dispatcher could not find response handler for response on peer %s",
p.ListenAddr)
} else {
rh(res)
Expand Down

0 comments on commit 4fc353b

Please sign in to comment.