Use map<nodeId, validatorPeer> instead of array; verify validator's signature in commit message processing

pull/55/head
Rongjian Lan 6 years ago
parent 94a9a52cab
commit 189f0e8bb1
  1. 2
      benchmark.go
  2. 27
      consensus/consensus.go
  3. 25
      consensus/consensus_leader.go
  4. 5
      consensus/consensus_validator.go

@ -48,7 +48,7 @@ func getLeader(myShardId string, config *[][]string) p2p.Peer {
}
socketId := reg.ReplaceAllString(ip+port, "") // A integer Id formed by unique IP/PORT pair
value, _ := strconv.Atoi(socketId)
priKey := crypto.Ed25519Curve.Scalar().SetInt64(int64(value))
priKey := crypto.Ed25519Curve.Scalar().SetInt64(int64(value)) // TODO: figure out why using a random hash value doesn't work for private key (schnorr)
leaderPeer.PubKey = crypto.GetPublicKeyFromScalar(crypto.Ed25519Curve, priKey)
}
}

@ -23,8 +23,8 @@ type Consensus struct {
bitmap *crypto.Mask
// Signatures collected from validators
responses map[string]string
// List of validators
validators []p2p.Peer
// map of nodeId to validator Peer object
validators map[uint16]p2p.Peer
// Leader
leader p2p.Peer
// private/public keys of current node
@ -88,10 +88,19 @@ func NewConsensus(ip, port, ShardID string, peers []p2p.Peer, leader p2p.Peer) *
}
consensus.commitments = make(map[uint16]kyber.Point)
consensus.validators = make(map[uint16]p2p.Peer)
consensus.responses = make(map[string]string)
consensus.leader = leader
consensus.validators = peers
reg, err := regexp.Compile("[^0-9]+")
if err != nil {
log.Crit("Regex Compilation Failed", "err", err)
}
for _, peer := range peers {
socketId := reg.ReplaceAllString(peer.Ip+peer.Port, "") // A integer Id formed by unique IP/PORT pair
value, _ := strconv.Atoi(socketId)
consensus.validators[uint16(value)] = peer
}
// Initialize cosign bitmap
allPublics := make([]kyber.Point, 0)
@ -106,10 +115,6 @@ func NewConsensus(ip, port, ShardID string, peers []p2p.Peer, leader p2p.Peer) *
consensus.bitmap = mask
// Set private key for myself so that I can sign messages.
reg, err := regexp.Compile("[^0-9]+")
if err != nil {
log.Crit("Regex Compilation Failed", "err", err)
}
socketId := reg.ReplaceAllString(ip+port, "") // A integer Id formed by unique IP/PORT pair
value, _ := strconv.Atoi(socketId)
consensus.priKey = crypto.Ed25519Curve.Scalar().SetInt64(int64(value))
@ -151,6 +156,14 @@ func (consensus *Consensus) signMessage(message []byte) []byte {
return signature
}
func (consensus *Consensus) getValidatorPeers() []p2p.Peer {
validatorPeers := make([]p2p.Peer, 0)
for _, validatorPeer := range consensus.validators {
validatorPeers = append(validatorPeers, validatorPeer)
}
return validatorPeers
}
// Reset the state of the consensus
func (consensus *Consensus) ResetState() {
consensus.state = FINISHED

@ -5,6 +5,7 @@ import (
"encoding/binary"
"encoding/gob"
"github.com/dedis/kyber"
"github.com/dedis/kyber/sign/schnorr"
"harmony-benchmark/blockchain"
"harmony-benchmark/crypto"
"harmony-benchmark/p2p"
@ -78,9 +79,10 @@ func (consensus *Consensus) startConsensus(newBlock *blockchain.Block) {
consensus.blockHeader = byteBuffer.Bytes()
msgToSend := consensus.constructAnnounceMessage()
p2p.BroadcastMessage(consensus.validators, msgToSend)
p2p.BroadcastMessage(consensus.getValidatorPeers(), msgToSend)
// Set state to ANNOUNCE_DONE
consensus.state = ANNOUNCE_DONE
// Generate leader's own commitment
secret, commitment := crypto.Commit(crypto.Ed25519Curve)
consensus.secret = secret
@ -117,7 +119,7 @@ func (consensus *Consensus) constructAnnounceMessage() []byte {
// Processes the commit message sent from validators
func (consensus *Consensus) processCommitMessage(payload []byte) {
//#### Read payload data
// Read payload data
offset := 0
// 4 byte consensus id
consensusId := binary.BigEndian.Uint32(payload[offset : offset+4])
@ -135,13 +137,20 @@ func (consensus *Consensus) processCommitMessage(payload []byte) {
commitment := payload[offset : offset+32]
offset += 32
// 64 byte of signature on previous data
// 64 byte of signature on all above data
signature := payload[offset : offset+64]
offset += 64
//#### END: Read payload data
// TODO: make use of the data. This is just to avoid the unused variable warning
_ = signature
// Verify signature
value, ok := consensus.validators[validatorId]
if !ok {
consensus.Log.Warn("Received message from unrecognized validator", "validatorId", validatorId, "consensus", consensus)
return
}
if schnorr.Verify(crypto.Ed25519Curve, value.PubKey, payload[:offset-64], signature) != nil {
consensus.Log.Warn("Received message with invalid signature", "validatorKey", consensus.leader.PubKey, "consensus", consensus)
return
}
// check consensus Id
consensus.mutex.Lock()
@ -157,7 +166,7 @@ func (consensus *Consensus) processCommitMessage(payload []byte) {
}
// proceed only when the message is not received before
_, ok := consensus.commitments[validatorId]
_, ok = consensus.commitments[validatorId]
shouldProcess := !ok
if shouldProcess {
point := crypto.Ed25519Curve.Point()
@ -174,7 +183,7 @@ func (consensus *Consensus) processCommitMessage(payload []byte) {
// Broadcast challenge
msgToSend := consensus.constructChallengeMessage()
p2p.BroadcastMessage(consensus.validators, msgToSend)
p2p.BroadcastMessage(consensus.getValidatorPeers(), msgToSend)
// Set state to CHALLENGE_DONE
consensus.state = CHALLENGE_DONE

@ -124,13 +124,10 @@ func (consensus *Consensus) processAnnounceMessage(payload []byte) {
return
}
// TODO: return the signature(commit) to leader
// For now, simply return the private key of this node.
secret, msgToSend := consensus.constructCommitMessage()
// Store the commitment secret
consensus.secret = secret
// consensus.Log.Debug("SENDING COMMIT", "consensusId", consensus.consensusId, "consensus", consensus)
p2p.SendMessage(consensus.leader, msgToSend)
// Set state to COMMIT_DONE
@ -154,7 +151,7 @@ func (consensus *Consensus) constructCommitMessage() (secret kyber.Scalar, commi
binary.BigEndian.PutUint16(twoBytes, consensus.nodeId)
buffer.Write(twoBytes)
// 32 byte of commit (Note it's different than Zilliqa's ECPoint which takes 33 bytes: https://crypto.stackexchange.com/questions/51703/how-to-convert-from-curve25519-33-byte-to-32-byte-representation)
// 32 byte of commit (TODO: figure out why it's different than Zilliqa's ECPoint which takes 33 bytes: https://crypto.stackexchange.com/questions/51703/how-to-convert-from-curve25519-33-byte-to-32-byte-representation)
secret, commitment := crypto.Commit(crypto.Ed25519Curve)
commitment.MarshalTo(buffer)

Loading…
Cancel
Save