Add block verification in validator node; link verification function from Node obj to Consensus obj

pull/8/head
Rongjian Lan 6 years ago
parent cb983ce484
commit de988ef76a
  1. 2
      benchmark_main.go
  2. 2
      consensus/consensus.go
  3. 41
      consensus/consensus_leader.go
  4. 11
      consensus/consensus_leader_test.go
  5. 52
      consensus/consensus_validator.go
  6. 4
      consensus/consensus_validator_test.go
  7. 5
      node/node_handler.go

@ -76,6 +76,8 @@ func main() {
consensus := consensus.NewConsensus(*ip, *port, shardId, peers, leader)
node := node.NewNode(&consensus)
consensus.BlockVerifier = node.VerifyNewBlock // Assign block verifier to the consensus
// Temporary testing code, to be removed.
node.AddMoreFakeTransactions()

@ -8,6 +8,7 @@ import (
"harmony-benchmark/p2p"
"regexp"
"strconv"
"harmony-benchmark/blockchain"
)
// Consensus data containing all info related to one consensus process
@ -40,6 +41,7 @@ type Consensus struct {
// Signal channel for starting a new consensus process
ReadySignal chan int
BlockVerifier func(*blockchain.Block)bool
//// Network related fields
msgCategory byte

@ -6,11 +6,10 @@ import (
"bytes"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"harmony-benchmark/blockchain"
"harmony-benchmark/p2p"
"strings"
"encoding/gob"
)
var mutex = &sync.Mutex{}
@ -63,21 +62,23 @@ func (consensus *Consensus) processStartConsensusMessage(payload []byte) {
func (consensus *Consensus) startConsensus(newBlock *blockchain.Block) {
// prepare message and broadcast to validators
// Construct new block
//newBlock := constructNewBlock()
copy(newBlock.Hash[:32], consensus.blockHash[:])
msgToSend, err := consensus.constructAnnounceMessage()
if err != nil {
return
}
// Copy over block hash and block header data
copy(consensus.blockHash[:], newBlock.Hash[:])
byteBuffer := bytes.NewBuffer([]byte{})
encoder := gob.NewEncoder(byteBuffer)
encoder.Encode(newBlock)
consensus.blockHeader = byteBuffer.Bytes()
msgToSend := consensus.constructAnnounceMessage()
// Set state to ANNOUNCE_DONE
consensus.state = ANNOUNCE_DONE
p2p.BroadcastMessage(consensus.validators, msgToSend)
}
// Construct the announce message to send to validators
func (consensus Consensus) constructAnnounceMessage() ([]byte, error) {
func (consensus Consensus) constructAnnounceMessage() []byte {
buffer := bytes.NewBuffer([]byte{})
// 4 byte consensus id
@ -86,9 +87,6 @@ func (consensus Consensus) constructAnnounceMessage() ([]byte, error) {
buffer.Write(fourBytes)
// 32 byte block hash
if len(consensus.blockHash) != 32 {
return buffer.Bytes(), errors.New(fmt.Sprintf("Block Hash size is %d bytes", len(consensus.blockHash)))
}
buffer.Write(consensus.blockHash[:])
// 2 byte leader id
@ -97,11 +95,10 @@ func (consensus Consensus) constructAnnounceMessage() ([]byte, error) {
buffer.Write(twoBytes)
// n byte of block header
blockHeader := getBlockHeader()
buffer.Write(blockHeader)
buffer.Write(consensus.blockHeader)
// 4 byte of payload size
sizeOfPayload := uint32(len(blockHeader))
sizeOfPayload := uint32(len(consensus.blockHeader))
binary.BigEndian.PutUint32(fourBytes, sizeOfPayload)
buffer.Write(fourBytes)
@ -109,17 +106,7 @@ func (consensus Consensus) constructAnnounceMessage() ([]byte, error) {
signature := signMessage(buffer.Bytes())
buffer.Write(signature)
return consensus.ConstructConsensusMessage(ANNOUNCE, buffer.Bytes()), nil
}
// Get the hash of a block's byte stream
func getBlockHash(block []byte) [32]byte {
return sha256.Sum256(block)
}
// TODO: fill in this function
func getBlockHeader() []byte {
return make([]byte, 200)
return consensus.ConstructConsensusMessage(ANNOUNCE, buffer.Bytes())
}
func signMessage(message []byte) []byte {

@ -6,16 +6,13 @@ import (
)
func TestConstructAnnounceMessage(test *testing.T) {
header := getBlockHeader()
leader := p2p.Peer{Ip: "1", Port: "2"}
validator := p2p.Peer{Ip: "3", Port: "5"}
consensus := NewConsensus("1", "2", "0", []p2p.Peer{leader, validator}, leader)
consensus.blockHash = getBlockHash(make([]byte, 10))
msg, err := consensus.constructAnnounceMessage()
consensus.blockHash = [32]byte{}
header := consensus.blockHeader
msg := consensus.constructAnnounceMessage()
if err != nil {
test.Error("Annouce message is not constructed successfully")
}
if len(msg) != 1+1+1+4+32+2+4+64+len(header) {
test.Errorf("Annouce message is not constructed in the correct size: %d", len(msg))
}
@ -25,7 +22,7 @@ func TestConstructChallengeMessage(test *testing.T) {
leader := p2p.Peer{Ip: "1", Port: "2"}
validator := p2p.Peer{Ip: "3", Port: "5"}
consensus := NewConsensus("1", "2", "0", []p2p.Peer{leader, validator}, leader)
consensus.blockHash = getBlockHash(make([]byte, 10))
consensus.blockHash = [32]byte{}
msg := consensus.constructChallengeMessage()
if len(msg) != 1+1+1+4+32+2+33+33+32+64 {

@ -4,6 +4,10 @@ import (
"bytes"
"encoding/binary"
"harmony-benchmark/p2p"
"strconv"
"regexp"
"encoding/gob"
"harmony-benchmark/blockchain"
)
// Validator's consensus message dispatcher
@ -43,8 +47,8 @@ func (consensus *Consensus) processAnnounceMessage(payload []byte) {
blockHash := payload[offset : offset+32]
offset += 32
// 2 byte validator id
leaderId := string(payload[offset : offset+2])
// 2 byte leader id
leaderId := binary.BigEndian.Uint16(payload[offset : offset+2])
offset += 2
// n byte of block header
@ -63,18 +67,54 @@ func (consensus *Consensus) processAnnounceMessage(payload []byte) {
// TODO: make use of the data. This is just to avoid the unused variable warning
_ = consensusId
_ = blockHash
_ = leaderId
_ = blockHeader
_ = blockHeaderSize
_ = signature
copy(blockHash[:32], consensus.blockHash[:])
// verify block data
copy(consensus.blockHash[:], blockHash[:])
// Verify block data
// check consensus Id
if consensusId != consensus.consensusId {
consensus.Log.Debug("Received message", "fromConsensus", consensus)
consensus.Log.Debug("[ERROR] Received message with wrong consensus Id", "myConsensusId", consensus.consensusId, "theirConsensusId", consensusId)
return
}
// check leader Id
leaderPrivKey := consensus.leader.Ip + consensus.leader.Port
reg, _ := regexp.Compile("[^0-9]+")
socketId := reg.ReplaceAllString(leaderPrivKey, "")
value, _ := strconv.Atoi(socketId)
if leaderId != uint16(value) {
consensus.Log.Debug("[ERROR] Received message from wrong leader", "myLeaderId", consensus.consensusId, "receivedLeaderId", consensusId)
return
}
// check block header is valid
txDecoder := gob.NewDecoder(bytes.NewReader(blockHeader)) // skip the SEND messge type
var blockHeaderObj blockchain.Block // TODO: separate header from block
err := txDecoder.Decode(&blockHeaderObj)
if err != nil {
consensus.Log.Debug("[ERROR] Unparseable block header data")
return
}
// check block hash
if bytes.Compare(blockHash[:], blockHeaderObj.HashTransactions()[:]) != 0 || bytes.Compare(blockHeaderObj.Hash[:], blockHeaderObj.HashTransactions()[:]) != 0 {
consensus.Log.Debug("[ERROR] Block hash doesn't match")
return
}
// check block data (transactions
if !consensus.BlockVerifier(&blockHeaderObj) {
consensus.Log.Debug("[ERROR] Block content is not verified successfully")
return
}
// sign block
// TODO: return the signature(commit) to leader

@ -9,7 +9,7 @@ func TestConstructCommitMessage(test *testing.T) {
leader := p2p.Peer{Ip: "1", Port: "2"}
validator := p2p.Peer{Ip: "3", Port: "5"}
consensus := NewConsensus("1", "2", "0", []p2p.Peer{leader, validator}, leader)
consensus.blockHash = getBlockHash(make([]byte, 10))
consensus.blockHash = [32]byte{}
msg := consensus.constructCommitMessage()
if len(msg) != 1+1+1+4+32+2+33+64 {
@ -21,7 +21,7 @@ func TestConstructResponseMessage(test *testing.T) {
leader := p2p.Peer{Ip: "1", Port: "2"}
validator := p2p.Peer{Ip: "3", Port: "5"}
consensus := NewConsensus("1", "2", "0", []p2p.Peer{leader, validator}, leader)
consensus.blockHash = getBlockHash(make([]byte, 10))
consensus.blockHash = [32]byte{}
msg := consensus.constructResponseMessage()
if len(msg) != 1+1+1+4+32+2+32+64 {

@ -148,3 +148,8 @@ func (node *Node) WaitForConsensusReady(readySignal chan int) {
node.BlockChannel <- *newBlock
}
}
func (node *Node) VerifyNewBlock(block *blockchain.Block) bool {
// TODO: fill in this function
return true
}
Loading…
Cancel
Save