@ -12,6 +12,7 @@ import (
consensus_proto "github.com/harmony-one/harmony/api/consensus"
consensus_proto "github.com/harmony-one/harmony/api/consensus"
"github.com/harmony-one/harmony/api/services/explorer"
"github.com/harmony-one/harmony/api/services/explorer"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/types"
bls_cosi "github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/internal/profiler"
"github.com/harmony-one/harmony/internal/profiler"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/p2p"
@ -94,7 +95,7 @@ func (consensus *Consensus) startConsensus(newBlock *types.Block) {
// Set state to AnnounceDone
// Set state to AnnounceDone
consensus . state = AnnounceDone
consensus . state = AnnounceDone
// Leader sign the multi-sig itself
// Leader sign the block hash itself
( * consensus . prepareSigs ) [ consensus . nodeID ] = consensus . priKey . SignHash ( consensus . blockHash [ : ] )
( * consensus . prepareSigs ) [ consensus . nodeID ] = consensus . priKey . SignHash ( consensus . blockHash [ : ] )
host . BroadcastMessageFromLeader ( consensus . host , consensus . GetValidatorPeers ( ) , msgToSend , consensus . OfflinePeers )
host . BroadcastMessageFromLeader ( consensus . host , consensus . GetValidatorPeers ( ) , msgToSend , consensus . OfflinePeers )
@ -144,41 +145,46 @@ func (consensus *Consensus) processPrepareMessage(message consensus_proto.Messag
// proceed only when the message is not received before
// proceed only when the message is not received before
_ , ok = ( * prepareSigs ) [ validatorID ]
_ , ok = ( * prepareSigs ) [ validatorID ]
shouldProcess := ! ok
if ok {
if len ( ( * prepareSigs ) ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) {
utils . GetLogInstance ( ) . Debug ( "Already received prepare message from the validator" , "validatorID" , validatorID )
shouldProcess = false
return
}
}
if shouldProcess {
if len ( ( * prepareSigs ) ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) {
var sign bls . Sign
utils . GetLogInstance ( ) . Debug ( "Received additional new prepare message" , "validatorID" , validatorID )
err := sign . Deserialize ( prepareSig )
return
if err != nil {
}
utils . GetLogInstance ( ) . Error ( "Failed to deserialize bls signature" , "validatorID" , validatorID )
}
// TODO: check bls signature
( * prepareSigs ) [ validatorID ] = & sign
utils . GetLogInstance ( ) . Debug ( "Received new prepare signature" , "numReceivedSoFar" , len ( * prepareSigs ) , "validatorID" , validatorID , "PublicKeys" , len ( consensus . PublicKeys ) )
// Set the bitmap indicate this validate signed.
// Check BLS signature for the multi-sig
prepareBitmap . SetKey ( value . PubKey , true )
var sign bls . Sign
err = sign . Deserialize ( prepareSig )
if err != nil {
utils . GetLogInstance ( ) . Error ( "Failed to deserialize bls signature" , "validatorID" , validatorID )
return
}
}
if ! shouldProcess {
if ! sign . VerifyHash ( value . PubKey , consensus . blockHash [ : ] ) {
utils . GetLogInstance ( ) . Debug ( "Received additional new commit message" , "validatorID" , validatorID )
utils . GetLogInstance ( ) . Error ( "Received invalid BLS signatur e", "validatorID" , validatorID )
return
return
}
}
( * prepareSigs ) [ validatorID ] = & sign
utils . GetLogInstance ( ) . Debug ( "Received new prepare signature" , "numReceivedSoFar" , len ( * prepareSigs ) , "validatorID" , validatorID , "PublicKeys" , len ( consensus . PublicKeys ) )
// Set the bitmap indicate this validate signed.
prepareBitmap . SetKey ( value . PubKey , true )
targetState := PreparedDone
targetState := PreparedDone
if len ( ( * prepareSigs ) ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) && consensus . state < targetState {
if len ( ( * prepareSigs ) ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) && consensus . state < targetState {
utils . GetLogInstance ( ) . Debug ( "Enough commitments received with signatures" , "num" , len ( * prepareSigs ) , "state" , consensus . state )
utils . GetLogInstance ( ) . Debug ( "Enough prepare s received with signatures" , "num" , len ( * prepareSigs ) , "state" , consensus . state )
// Construct prepared message
// Construct prepared message
msgToSend , aggSig := consensus . constructPreparedMessage ( )
msgToSend , aggSig := consensus . constructPreparedMessage ( )
consensus . aggregatedPrepareSig = aggSig
consensus . aggregatedPrepareSig = aggSig
// Leader sign the multi-sig itself
// Leader sign the multi-sig and bitmap
// TODO: sign on the prepared multi-sig, rather than the block hash
multiSigAndBitmap := append ( aggSig . Serialize ( ) , prepareBitmap . Bitmap ... )
( * consensus . commitSigs ) [ consensus . nodeID ] = consensus . priKey . SignHash ( consensus . blockHash [ : ] )
( * consensus . commitSigs ) [ consensus . nodeID ] = consensus . priKey . SignHash ( multiSigAndBitmap )
// Broadcast prepared message
// Broadcast prepared message
host . BroadcastMessageFromLeader ( consensus . host , consensus . GetValidatorPeers ( ) , msgToSend , consensus . OfflinePeers )
host . BroadcastMessageFromLeader ( consensus . host , consensus . GetValidatorPeers ( ) , msgToSend , consensus . OfflinePeers )
@ -195,14 +201,13 @@ func (consensus *Consensus) processCommitMessage(message consensus_proto.Message
validatorID := message . SenderId
validatorID := message . SenderId
commitSig := message . Payload
commitSig := message . Payload
shouldProcess := true
consensus . mutex . Lock ( )
consensus . mutex . Lock ( )
defer consensus . mutex . Unlock ( )
defer consensus . mutex . Unlock ( )
// check consensus Id
// check consensus Id
if consensusID != consensus . consensusID {
if consensusID != consensus . consensusID {
shouldProcess = false
utils . GetLogInstance ( ) . Warn ( "Received Commit with wrong consensus Id" , "myConsensusId" , consensus . consensusID , "theirConsensusId" , consensusID , "consensus" , consensus )
utils . GetLogInstance ( ) . Warn ( "Received Commit with wrong consensus Id" , "myConsensusId" , consensus . consensusID , "theirConsensusId" , consensusID , "consensus" , consensus )
return
}
}
if ! bytes . Equal ( blockHash , consensus . blockHash [ : ] ) {
if ! bytes . Equal ( blockHash , consensus . blockHash [ : ] ) {
@ -234,30 +239,34 @@ func (consensus *Consensus) processCommitMessage(message consensus_proto.Message
// proceed only when the message is not received before
// proceed only when the message is not received before
_ , ok = ( * commitSigs ) [ validatorID ]
_ , ok = ( * commitSigs ) [ validatorID ]
shouldProcess = shouldProcess && ! ok
if ok {
utils . GetLogInstance ( ) . Debug ( "Already received commit message from the validator" , "validatorID" , validatorID )
return
}
if len ( ( * commitSigs ) ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) {
if len ( ( * commitSigs ) ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) {
shouldProcess = false
utils . GetLogInstance ( ) . Debug ( "Received additional new commit message" , "validatorID" , strconv . Itoa ( int ( validatorID ) ) )
return
}
}
if shouldProcess {
var sign bls . Sign
var sign bls . Sign
err = sign . Deserialize ( commitSig )
err := sign . Deserialize ( commitSig )
if err != nil {
if err != nil {
utils . GetLogInstance ( ) . Debug ( "Failed to deserialize bls signature" , "validatorID" , validatorID )
utils . GetLogInstance ( ) . Debug ( "Failed to deserialize bls signature" , "validatorID" , validatorID )
return
}
// TODO: check bls signature
( * commitSigs ) [ validatorID ] = & sign
utils . GetLogInstance ( ) . Debug ( "Received new commit message" , "numReceivedSoFar" , len ( * commitSigs ) , "validatorID" , strconv . Itoa ( int ( validatorID ) ) )
// Set the bitmap indicate this validate signed.
commitBitmap . SetKey ( value . PubKey , true )
}
}
if ! shouldProcess {
// Verify the signature on prepare multi-sig and bitmap is correct
utils . GetLogInstance ( ) . Debug ( "Received additional new commit message" , "validatorID" , strconv . Itoa ( int ( validatorID ) ) )
aggSig := bls_cosi . AggregateSig ( consensus . GetPrepareSigsArray ( ) )
if ! sign . VerifyHash ( value . PubKey , append ( aggSig . Serialize ( ) , consensus . prepareBitmap . Bitmap ... ) ) {
utils . GetLogInstance ( ) . Error ( "Received invalid BLS signature" , "validatorID" , validatorID )
return
return
}
}
( * commitSigs ) [ validatorID ] = & sign
utils . GetLogInstance ( ) . Debug ( "Received new commit message" , "numReceivedSoFar" , len ( * commitSigs ) , "validatorID" , strconv . Itoa ( int ( validatorID ) ) )
// Set the bitmap indicate this validate signed.
commitBitmap . SetKey ( value . PubKey , true )
targetState := CommittedDone
targetState := CommittedDone
if len ( * commitSigs ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) && consensus . state != targetState {
if len ( * commitSigs ) >= ( ( len ( consensus . PublicKeys ) * 2 ) / 3 + 1 ) && consensus . state != targetState {
utils . GetLogInstance ( ) . Info ( "Enough commits received!" , "num" , len ( * commitSigs ) , "state" , consensus . state )
utils . GetLogInstance ( ) . Info ( "Enough commits received!" , "num" , len ( * commitSigs ) , "state" , consensus . state )