Skip to content

Commit

Permalink
Update getLocalChain, update SyncBlockchain, refactor peer tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bfbachmann committed Jul 30, 2017
1 parent 0832026 commit 03de519
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 265 deletions.
53 changes: 34 additions & 19 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ func Run(cfg conf.Config) {
config := &cfg

addr := fmt.Sprintf("%s:%d", config.Interface, config.Port)
user := getCurrentUser()
a := App{
PeerStore: peer.NewPeerStore(addr),
CurrentUser: getCurrentUser(),
Chain: getLocalChain(),
CurrentUser: user,
Chain: getLocalChain(user),
Pool: getLocalPool(),
}

Expand Down Expand Up @@ -206,11 +207,21 @@ func (a *App) PushHandler(push *msg.Push) {
}

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

genisisBlock := blockchain.Genesis(user.HotWallet.Wallet.Public(),
consensus.CurrentTarget(), consensus.StartingBlockReward,
make([]byte, 0))

bc.Blocks = append(bc.Blocks, genisisBlock)
bc.Head = blockchain.HashSum(genisisBlock)
return &bc
}

// getLocalPool returns an instance of the pool.
Expand Down Expand Up @@ -264,6 +275,7 @@ func (a *App) HandleBlock(blk *blockchain.Block) {
// SyncBlockchain updates the local copy of the blockchain by requesting missing
// blocks from peers. Returns error if we are not connected to any peers.
func (a *App) SyncBlockchain() error {
prevHead := a.Chain.Blocks[len(a.Chain.Blocks)-1]
newBlockChan := make(chan *blockchain.Block)
errChan := make(chan *msg.ProtocolError)

Expand All @@ -286,8 +298,10 @@ func (a *App) SyncBlockchain() error {
// Continually request the block after the latest block in our chain until
// we are totally up to date
for {
lastBlock := a.Chain.Blocks[len(a.Chain.Blocks)-1]

reqParams := map[string]interface{}{
"blockNumber": len(a.Chain.Blocks) - 1,
"lastBlockHash": blockchain.HashSum(lastBlock),
}

blockRequest := msg.Request{
Expand All @@ -304,24 +318,20 @@ func (a *App) SyncBlockchain() error {
}

// Pick a peer to send the request to (this won't always be the same one)
p := a.PeerStore.Get(a.PeerStore.Addrs()[0])
p := a.PeerStore.Get(peerAddrs[0])
p.Request(blockRequest, blockResponseHandler)

// Wait for response
select {
case block := <-newBlockChan:
if block == nil {
case newBlock := <-newBlockChan:
if newBlock == nil {
// We received a response with no error but an invalid resource
// Try again
continue
}

valid, validationCode := consensus.VerifyBlock(a.Chain, block)
valid, validationCode := consensus.VerifyBlock(a.Chain, newBlock)
if !valid {
if validationCode == msg.ResourceNotFound {
// We are up to date
return nil
}
// There is something wrong with this block. Try again
fields := log.Fields{"validationCode": validationCode}
log.WithFields(fields).Debug(
Expand All @@ -330,14 +340,19 @@ func (a *App) SyncBlockchain() error {
}

// Valid block. Append it to the chain
a.Chain.AppendBlock(block)
a.Chain.AppendBlock(newBlock)

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

case err := <-errChan:
if err.Code == msg.ResourceNotFound {
// We are up to date
return nil
} else if err.Code == msg.RequestTimeout {
log.Debug("SyncBlockchain timed out waiting for a response")
// Our chain might be out of sync, roll it back by one block
// and request the next block
prevHead = lastBlock
a.Chain.Blocks = a.Chain.Blocks[:len(a.Chain.Blocks)-1]
}

// Some other protocol error occurred. Try again
Expand Down
2 changes: 1 addition & 1 deletion app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func TestGetLocalPool(t *testing.T) {
}

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

func TestHandleBlock(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions blockchain/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ func (bh *BlockHeader) Marshal() []byte {
return buf
}

// Equal returns true if all the fields (other than ExtraData) in each of
// the BlockHeaders match, and false otherwise.
func (bh *BlockHeader) Equal(otherHeader *BlockHeader) bool {
return bh.BlockNumber == otherHeader.BlockNumber &&
bh.LastBlock == otherHeader.LastBlock &&
bh.Target == otherHeader.Target &&
bh.Time == otherHeader.Time &&
bh.Nonce == otherHeader.Nonce
}

// Len returns the length in bytes of the BlockHeader.
func (bh *BlockHeader) Len() int {
return len(bh.Marshal())
Expand Down
2 changes: 1 addition & 1 deletion blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (bc *BlockChain) ContainsTransaction(t *Transaction, start, stop uint32) (b
return false, 0, 0
}

// CopyLocalBlockByIndex returns a copy of a block in the local chain by index.
// CopyBlockByIndex returns a copy of a block in the local chain by index.
func (bc *BlockChain) CopyBlockByIndex(i uint32) (*Block, error) {
if i >= 0 && i < uint32(len(bc.Blocks)) {
blk := bc.Blocks[i]
Expand Down
1 change: 0 additions & 1 deletion peer/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const (
)

// ResponseHandler is any function that handles a response to a request.
// NOTE: implementations of this function must handle timeouts!
type ResponseHandler func(*msg.Response)

// PushHandler is any function that handles a push message.
Expand Down
Loading

0 comments on commit 03de519

Please sign in to comment.