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 new blocks
newBlock := <- blockChannel
// TODO: think about potential race condition
dRand . init ( newBlock )
case <- stopChan :
return
}
}
} ( )
}
func ( dRand * DRand ) init ( epochBlock * types . Block ) {
// 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
}
// Verify message signature
err := verifyMessageSig ( dRand . leader . 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
validatorID := message . SenderId
validatorPeer := dRand . getValidatorPeerByID ( validatorID )
vrfs := dRand . vrfs
utils . GetLogInstance ( ) . Debug ( "Received new prepare signature" , "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
}
}