Implement 'block' and 'getdata' commands
This commit is contained in:
parent
9adb5fc139
commit
470adef2c3
|
@ -97,6 +97,11 @@ func NewBlockchain(nodeID string) *Blockchain {
|
|||
return &bc
|
||||
}
|
||||
|
||||
// Reset removes all blockchain data
|
||||
func (bc *Blockchain) Reset() {
|
||||
|
||||
}
|
||||
|
||||
// FindTransaction finds a transaction by its ID
|
||||
func (bc *Blockchain) FindTransaction(ID []byte) (Transaction, error) {
|
||||
bci := bc.Iterator()
|
||||
|
@ -169,6 +174,30 @@ func (bc *Blockchain) Iterator() *BlockchainIterator {
|
|||
return bci
|
||||
}
|
||||
|
||||
// GetBlock finds a block by its hash and returns it
|
||||
func (bc *Blockchain) GetBlock(blockHash []byte) (Block, error) {
|
||||
var block Block
|
||||
|
||||
err := bc.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(blocksBucket))
|
||||
|
||||
blockData := b.Get(blockHash)
|
||||
|
||||
if blockData == nil {
|
||||
return errors.New("Block is not found.")
|
||||
}
|
||||
|
||||
block = *DeserializeBlock(blockData)
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return block, err
|
||||
}
|
||||
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// GetBlockHashes returns a list of hashes of all the blocks in the chain
|
||||
func (bc *Blockchain) GetBlockHashes() [][]byte {
|
||||
var blocks [][]byte
|
||||
|
|
89
server.go
89
server.go
|
@ -22,13 +22,25 @@ type addr struct {
|
|||
AddrList []string
|
||||
}
|
||||
|
||||
type block struct {
|
||||
AddrFrom string
|
||||
Block []byte
|
||||
}
|
||||
|
||||
type getblocks struct {
|
||||
AddrFrom string
|
||||
}
|
||||
|
||||
type getdata struct {
|
||||
AddrFrom string
|
||||
Type string
|
||||
ID []byte
|
||||
}
|
||||
|
||||
type inv struct {
|
||||
Type string
|
||||
Items [][]byte
|
||||
AddrFrom string
|
||||
Type string
|
||||
Items [][]byte
|
||||
}
|
||||
|
||||
type verack struct {
|
||||
|
@ -81,6 +93,14 @@ func sendAddr(address string) {
|
|||
sendData(address, request)
|
||||
}
|
||||
|
||||
func sendBlock(addr string, b *Block) {
|
||||
data := block{nodeAddress, b.Serialize()}
|
||||
payload := gobEncode(data)
|
||||
request := append(commandToBytes("block"), payload...)
|
||||
|
||||
sendData(addr, request)
|
||||
}
|
||||
|
||||
func sendData(addr string, data []byte) {
|
||||
conn, err := net.Dial(protocol, addr)
|
||||
if err != nil {
|
||||
|
@ -95,7 +115,7 @@ func sendData(addr string, data []byte) {
|
|||
}
|
||||
|
||||
func sendInv(address, kind string, items [][]byte) {
|
||||
inventory := inv{kind, items}
|
||||
inventory := inv{nodeAddress, kind, items}
|
||||
payload := gobEncode(inventory)
|
||||
request := append(commandToBytes("inv"), payload...)
|
||||
|
||||
|
@ -109,6 +129,13 @@ func sendGetBlocks(address string) {
|
|||
sendData(address, request)
|
||||
}
|
||||
|
||||
func sendGetData(address, kind string, id []byte) {
|
||||
payload := gobEncode(getdata{nodeAddress, kind, id})
|
||||
request := append(commandToBytes("getdata"), payload...)
|
||||
|
||||
sendData(address, request)
|
||||
}
|
||||
|
||||
func sendVersion(addr string) {
|
||||
payload := gobEncode(verzion{nodeVersion, nodeAddress})
|
||||
|
||||
|
@ -141,7 +168,25 @@ func handleAddr(request []byte) {
|
|||
requestBlocks()
|
||||
}
|
||||
|
||||
func handleInv(request []byte) {
|
||||
func handleBlock(request []byte, bc *Blockchain) {
|
||||
var buff bytes.Buffer
|
||||
var payload block
|
||||
|
||||
buff.Write(request[commandLength:])
|
||||
dec := gob.NewDecoder(&buff)
|
||||
err := dec.Decode(&payload)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
blockData := payload.Block
|
||||
block := DeserializeBlock(blockData)
|
||||
|
||||
fmt.Println("Recevied a new block!")
|
||||
fmt.Println(block)
|
||||
}
|
||||
|
||||
func handleInv(request []byte, bc *Blockchain) {
|
||||
var buff bytes.Buffer
|
||||
var payload inv
|
||||
|
||||
|
@ -152,7 +197,14 @@ func handleInv(request []byte) {
|
|||
log.Panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Recevied %d %s\n", len(payload.Items), payload.Type)
|
||||
fmt.Printf("Recevied inventory with %d %s\n", len(payload.Items), payload.Type)
|
||||
blocks := bc.GetBlockHashes()
|
||||
|
||||
if len(blocks) < len(payload.Items) {
|
||||
for _, blockHash := range invResponse.Items {
|
||||
sendGetData(sourceNode, "block", blockHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetBlocks(request []byte, bc *Blockchain) {
|
||||
|
@ -170,6 +222,27 @@ func handleGetBlocks(request []byte, bc *Blockchain) {
|
|||
sendInv(payload.AddrFrom, "blocks", blocks)
|
||||
}
|
||||
|
||||
func handleGetData(request []byte, bc *Blockchain) {
|
||||
var buff bytes.Buffer
|
||||
var payload getdata
|
||||
|
||||
buff.Write(request[commandLength:])
|
||||
dec := gob.NewDecoder(&buff)
|
||||
err := dec.Decode(&payload)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
if payload.Type == "block" {
|
||||
block, err := bc.GetBlock([]byte(payload.ID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sendBlock(payload.AddrFrom, &block)
|
||||
}
|
||||
}
|
||||
|
||||
func handleVersion(request []byte) {
|
||||
var buff bytes.Buffer
|
||||
var payload verzion
|
||||
|
@ -197,10 +270,14 @@ func handleConnection(conn net.Conn, bc *Blockchain) {
|
|||
switch command {
|
||||
case "addr":
|
||||
handleAddr(request)
|
||||
case "block":
|
||||
handleBlock(request, bc)
|
||||
case "inv":
|
||||
handleInv(request)
|
||||
handleInv(request, bc)
|
||||
case "getblocks":
|
||||
handleGetBlocks(request, bc)
|
||||
case "getdata":
|
||||
handleGetData(request, bc)
|
||||
case "version":
|
||||
handleVersion(request)
|
||||
case "verack":
|
||||
|
|
Loading…
Reference in New Issue