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.
112 lines
3.3 KiB
112 lines
3.3 KiB
package consensus
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/harmony-one/bls/ffi/go/bls"
|
|
"github.com/harmony-one/harmony/api/proto"
|
|
msg_pb "github.com/harmony-one/harmony/api/proto/message"
|
|
"github.com/harmony-one/harmony/consensus/quorum"
|
|
"github.com/harmony-one/harmony/internal/utils"
|
|
)
|
|
|
|
// NetworkMessage is a message intended to be
|
|
// created only for distribution to
|
|
// all the other quorum members.
|
|
type NetworkMessage struct {
|
|
Phase msg_pb.MessageType
|
|
Bytes []byte
|
|
FBFTMsg *FBFTMessage
|
|
OptionalAggregateSignature *bls.Sign
|
|
}
|
|
|
|
// Populates the common basic fields for all consensus message.
|
|
func (consensus *Consensus) populateMessageFields(
|
|
request *msg_pb.ConsensusRequest, blockHash []byte, pubKey *bls.PublicKey,
|
|
) *msg_pb.ConsensusRequest {
|
|
request.ViewId = consensus.viewID
|
|
request.BlockNum = consensus.blockNum
|
|
request.ShardId = consensus.ShardID
|
|
// 32 byte block hash
|
|
request.BlockHash = blockHash
|
|
// sender address
|
|
request.SenderPubkey = pubKey.Serialize()
|
|
return request
|
|
}
|
|
|
|
// construct is the single creation point of messages intended for the wire.
|
|
func (consensus *Consensus) construct(
|
|
p msg_pb.MessageType, payloadForSign []byte, pubKey *bls.PublicKey, priKey *bls.SecretKey,
|
|
) (*NetworkMessage, error) {
|
|
message := &msg_pb.Message{
|
|
ServiceType: msg_pb.ServiceType_CONSENSUS,
|
|
Type: p,
|
|
Request: &msg_pb.Message_Consensus{
|
|
Consensus: &msg_pb.ConsensusRequest{},
|
|
},
|
|
}
|
|
var (
|
|
consensusMsg *msg_pb.ConsensusRequest
|
|
aggSig *bls.Sign
|
|
)
|
|
|
|
consensusMsg = consensus.populateMessageFields(
|
|
message.GetConsensus(), consensus.blockHash[:], pubKey,
|
|
)
|
|
|
|
// Do the signing, 96 byte of bls signature
|
|
switch p {
|
|
case msg_pb.MessageType_PREPARED:
|
|
consensusMsg.Block = consensus.block
|
|
// Payload
|
|
buffer := bytes.Buffer{}
|
|
// 96 bytes aggregated signature
|
|
aggSig = consensus.Decider.AggregateVotes(quorum.Prepare)
|
|
buffer.Write(aggSig.Serialize())
|
|
// Bitmap
|
|
buffer.Write(consensus.prepareBitmap.Bitmap)
|
|
consensusMsg.Payload = buffer.Bytes()
|
|
case msg_pb.MessageType_PREPARE:
|
|
if s := priKey.SignHash(consensusMsg.BlockHash); s != nil {
|
|
consensusMsg.Payload = s.Serialize()
|
|
}
|
|
case msg_pb.MessageType_COMMIT:
|
|
if s := priKey.SignHash(payloadForSign); s != nil {
|
|
consensusMsg.Payload = s.Serialize()
|
|
}
|
|
case msg_pb.MessageType_COMMITTED:
|
|
buffer := bytes.Buffer{}
|
|
// 96 bytes aggregated signature
|
|
aggSig = consensus.Decider.AggregateVotes(quorum.Commit)
|
|
buffer.Write(aggSig.Serialize())
|
|
// Bitmap
|
|
buffer.Write(consensus.commitBitmap.Bitmap)
|
|
consensusMsg.Payload = buffer.Bytes()
|
|
case msg_pb.MessageType_ANNOUNCE:
|
|
consensusMsg.Payload = consensus.blockHash[:]
|
|
}
|
|
|
|
marshaledMessage, err := consensus.signAndMarshalConsensusMessage(message, priKey)
|
|
if err != nil {
|
|
utils.Logger().Error().Err(err).
|
|
Str("phase", p.String()).
|
|
Msg("Failed to sign and marshal consensus message")
|
|
return nil, err
|
|
}
|
|
|
|
FBFTMsg, err2 := ParseFBFTMessage(message)
|
|
|
|
if err2 != nil {
|
|
utils.Logger().Error().Err(err).
|
|
Str("phase", p.String()).
|
|
Msg("failed to deal with the FBFT message")
|
|
return nil, err
|
|
}
|
|
|
|
return &NetworkMessage{
|
|
Phase: p,
|
|
Bytes: proto.ConstructConsensusMessage(marshaledMessage),
|
|
FBFTMsg: FBFTMsg,
|
|
OptionalAggregateSignature: aggSig,
|
|
}, nil
|
|
}
|
|
|