Implement 'getblocks' command

This commit is contained in:
Ivan Kuznetsov 2017-10-01 11:19:43 +07:00
parent 0c59d8cd52
commit 9adb5fc139
2 changed files with 82 additions and 0 deletions

View File

@ -169,6 +169,24 @@ func (bc *Blockchain) Iterator() *BlockchainIterator {
return bci return bci
} }
// GetBlockHashes returns a list of hashes of all the blocks in the chain
func (bc *Blockchain) GetBlockHashes() [][]byte {
var blocks [][]byte
bci := bc.Iterator()
for {
block := bci.Next()
blocks = append(blocks, block.Hash)
if len(block.PrevBlockHash) == 0 {
break
}
}
return blocks
}
// MineBlock mines a new block with the provided transactions // MineBlock mines a new block with the provided transactions
func (bc *Blockchain) MineBlock(transactions []*Transaction) *Block { func (bc *Blockchain) MineBlock(transactions []*Transaction) *Block {
var lastHash []byte var lastHash []byte

View File

@ -22,6 +22,15 @@ type addr struct {
AddrList []string AddrList []string
} }
type getblocks struct {
AddrFrom string
}
type inv struct {
Type string
Items [][]byte
}
type verack struct { type verack struct {
} }
@ -57,6 +66,12 @@ func extractCommand(request []byte) []byte {
return request[:commandLength] return request[:commandLength]
} }
func requestBlocks() {
for _, node := range knownNodes {
sendGetBlocks(node)
}
}
func sendAddr(address string) { func sendAddr(address string) {
nodes := addr{knownNodes} nodes := addr{knownNodes}
nodes.AddrList = append(nodes.AddrList, nodeAddress) nodes.AddrList = append(nodes.AddrList, nodeAddress)
@ -79,6 +94,21 @@ func sendData(addr string, data []byte) {
} }
} }
func sendInv(address, kind string, items [][]byte) {
inventory := inv{kind, items}
payload := gobEncode(inventory)
request := append(commandToBytes("inv"), payload...)
sendData(address, request)
}
func sendGetBlocks(address string) {
payload := gobEncode(getblocks{nodeAddress})
request := append(commandToBytes("getblocks"), payload...)
sendData(address, request)
}
func sendVersion(addr string) { func sendVersion(addr string) {
payload := gobEncode(verzion{nodeVersion, nodeAddress}) payload := gobEncode(verzion{nodeVersion, nodeAddress})
@ -108,6 +138,36 @@ func handleAddr(request []byte) {
knownNodes = append(knownNodes, payload.AddrList...) knownNodes = append(knownNodes, payload.AddrList...)
fmt.Printf("There are %d known nodes now!\n", len(knownNodes)) fmt.Printf("There are %d known nodes now!\n", len(knownNodes))
requestBlocks()
}
func handleInv(request []byte) {
var buff bytes.Buffer
var payload inv
buff.Write(request[commandLength:])
dec := gob.NewDecoder(&buff)
err := dec.Decode(&payload)
if err != nil {
log.Panic(err)
}
fmt.Printf("Recevied %d %s\n", len(payload.Items), payload.Type)
}
func handleGetBlocks(request []byte, bc *Blockchain) {
var buff bytes.Buffer
var payload getblocks
buff.Write(request[commandLength:])
dec := gob.NewDecoder(&buff)
err := dec.Decode(&payload)
if err != nil {
log.Panic(err)
}
blocks := bc.GetBlockHashes()
sendInv(payload.AddrFrom, "blocks", blocks)
} }
func handleVersion(request []byte) { func handleVersion(request []byte) {
@ -137,6 +197,10 @@ func handleConnection(conn net.Conn, bc *Blockchain) {
switch command { switch command {
case "addr": case "addr":
handleAddr(request) handleAddr(request)
case "inv":
handleInv(request)
case "getblocks":
handleGetBlocks(request, bc)
case "version": case "version":
handleVersion(request) handleVersion(request)
case "verack": case "verack":