The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
woop/drand/drand_leader.go

100 lines
3.2 KiB

package drand
import (
protobuf "github.com/golang/protobuf/proto"
drand_proto "github.com/harmony-one/harmony/api/drand"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p/host"
)
// WaitForEpochBlock waits for the first epoch block to run DRG on
func (dRand *DRand) WaitForEpochBlock(blockChannel chan *types.Block, stopChan chan struct{}, stoppedChan chan struct{}) {
go func() {
defer close(stoppedChan)
for {
select {
default:
// keep waiting for epoch block
newBlock := <-blockChannel
dRand.init(newBlock)
case <-stopChan:
return
}
}
}()
}
func (dRand *DRand) init(epochBlock *types.Block) {
utils.GetLogInstance().Debug("INITING DRAND")
dRand.ResetState()
// Copy over block hash and block header data
blockHash := epochBlock.Hash()
copy(dRand.blockHash[:], blockHash[:])
msgToSend := dRand.constructInitMessage()
// Leader commit vrf itself
rand, proof := dRand.vrf(dRand.blockHash)
(*dRand.vrfs)[dRand.nodeID] = append(rand[:], proof...)
host.BroadcastMessageFromLeader(dRand.host, dRand.GetValidatorPeers(), msgToSend, nil)
}
// ProcessMessageLeader dispatches messages for the leader to corresponding processors.
func (dRand *DRand) ProcessMessageLeader(payload []byte) {
message := drand_proto.Message{}
err := protobuf.Unmarshal(payload, &message)
if err != nil {
utils.GetLogInstance().Error("Failed to unmarshal message payload.", "err", err, "dRand", dRand)
}
switch message.Type {
case drand_proto.MessageType_COMMIT:
dRand.processCommitMessage(message)
default:
utils.GetLogInstance().Error("Unexpected message type", "msgType", message.Type, "dRand", dRand)
}
}
// ProcessMessageValidator dispatches validator's consensus message.
func (dRand *DRand) processCommitMessage(message drand_proto.Message) {
if message.Type != drand_proto.MessageType_COMMIT {
utils.GetLogInstance().Error("Wrong message type received", "expected", drand_proto.MessageType_COMMIT, "got", message.Type)
return
}
validatorID := message.SenderId
validatorPeer := dRand.getValidatorPeerByID(validatorID)
vrfs := dRand.vrfs
if len((*vrfs)) >= ((len(dRand.PublicKeys))/3 + 1) {
utils.GetLogInstance().Debug("Received additional randomness commit message", "validatorID", validatorID)
return
}
// Verify message signature
err := verifyMessageSig(validatorPeer.PubKey, message)
if err != nil {
utils.GetLogInstance().Warn("Failed to verify the message signature", "Error", err)
return
}
rand := message.Payload[:32]
proof := message.Payload[32:]
_ = rand
_ = proof
// TODO: check the validity of the vrf commit
utils.GetLogInstance().Debug("Received new commit", "numReceivedSoFar", len((*vrfs)), "validatorID", validatorID, "PublicKeys", len(dRand.PublicKeys))
(*vrfs)[validatorID] = message.Payload
dRand.bitmap.SetKey(validatorPeer.PubKey, true) // Set the bitmap indicating that this validator signed.
if len((*vrfs)) >= ((len(dRand.PublicKeys))/3 + 1) {
// Construct pRand and initiate consensus on it
utils.GetLogInstance().Debug("Received enough randomness commit", "numReceivedSoFar", len((*vrfs)), "validatorID", validatorID, "PublicKeys", len(dRand.PublicKeys))
// TODO: communicate the pRand to consensus
}
}