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
|
return &bc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset removes all blockchain data
|
||||||
|
func (bc *Blockchain) Reset() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// FindTransaction finds a transaction by its ID
|
// FindTransaction finds a transaction by its ID
|
||||||
func (bc *Blockchain) FindTransaction(ID []byte) (Transaction, error) {
|
func (bc *Blockchain) FindTransaction(ID []byte) (Transaction, error) {
|
||||||
bci := bc.Iterator()
|
bci := bc.Iterator()
|
||||||
|
@ -169,6 +174,30 @@ func (bc *Blockchain) Iterator() *BlockchainIterator {
|
||||||
return bci
|
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
|
// GetBlockHashes returns a list of hashes of all the blocks in the chain
|
||||||
func (bc *Blockchain) GetBlockHashes() [][]byte {
|
func (bc *Blockchain) GetBlockHashes() [][]byte {
|
||||||
var blocks [][]byte
|
var blocks [][]byte
|
||||||
|
|
89
server.go
89
server.go
|
@ -22,13 +22,25 @@ type addr struct {
|
||||||
AddrList []string
|
AddrList []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type block struct {
|
||||||
|
AddrFrom string
|
||||||
|
Block []byte
|
||||||
|
}
|
||||||
|
|
||||||
type getblocks struct {
|
type getblocks struct {
|
||||||
AddrFrom string
|
AddrFrom string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type getdata struct {
|
||||||
|
AddrFrom string
|
||||||
|
Type string
|
||||||
|
ID []byte
|
||||||
|
}
|
||||||
|
|
||||||
type inv struct {
|
type inv struct {
|
||||||
Type string
|
AddrFrom string
|
||||||
Items [][]byte
|
Type string
|
||||||
|
Items [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type verack struct {
|
type verack struct {
|
||||||
|
@ -81,6 +93,14 @@ func sendAddr(address string) {
|
||||||
sendData(address, request)
|
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) {
|
func sendData(addr string, data []byte) {
|
||||||
conn, err := net.Dial(protocol, addr)
|
conn, err := net.Dial(protocol, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -95,7 +115,7 @@ func sendData(addr string, data []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendInv(address, kind string, items [][]byte) {
|
func sendInv(address, kind string, items [][]byte) {
|
||||||
inventory := inv{kind, items}
|
inventory := inv{nodeAddress, kind, items}
|
||||||
payload := gobEncode(inventory)
|
payload := gobEncode(inventory)
|
||||||
request := append(commandToBytes("inv"), payload...)
|
request := append(commandToBytes("inv"), payload...)
|
||||||
|
|
||||||
|
@ -109,6 +129,13 @@ func sendGetBlocks(address string) {
|
||||||
sendData(address, request)
|
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) {
|
func sendVersion(addr string) {
|
||||||
payload := gobEncode(verzion{nodeVersion, nodeAddress})
|
payload := gobEncode(verzion{nodeVersion, nodeAddress})
|
||||||
|
|
||||||
|
@ -141,7 +168,25 @@ func handleAddr(request []byte) {
|
||||||
requestBlocks()
|
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 buff bytes.Buffer
|
||||||
var payload inv
|
var payload inv
|
||||||
|
|
||||||
|
@ -152,7 +197,14 @@ func handleInv(request []byte) {
|
||||||
log.Panic(err)
|
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) {
|
func handleGetBlocks(request []byte, bc *Blockchain) {
|
||||||
|
@ -170,6 +222,27 @@ func handleGetBlocks(request []byte, bc *Blockchain) {
|
||||||
sendInv(payload.AddrFrom, "blocks", blocks)
|
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) {
|
func handleVersion(request []byte) {
|
||||||
var buff bytes.Buffer
|
var buff bytes.Buffer
|
||||||
var payload verzion
|
var payload verzion
|
||||||
|
@ -197,10 +270,14 @@ func handleConnection(conn net.Conn, bc *Blockchain) {
|
||||||
switch command {
|
switch command {
|
||||||
case "addr":
|
case "addr":
|
||||||
handleAddr(request)
|
handleAddr(request)
|
||||||
|
case "block":
|
||||||
|
handleBlock(request, bc)
|
||||||
case "inv":
|
case "inv":
|
||||||
handleInv(request)
|
handleInv(request, bc)
|
||||||
case "getblocks":
|
case "getblocks":
|
||||||
handleGetBlocks(request, bc)
|
handleGetBlocks(request, bc)
|
||||||
|
case "getdata":
|
||||||
|
handleGetData(request, bc)
|
||||||
case "version":
|
case "version":
|
||||||
handleVersion(request)
|
handleVersion(request)
|
||||||
case "verack":
|
case "verack":
|
||||||
|
|
Loading…
Reference in New Issue