[slash][consensus] Notice double sign & broadcast, factor out tech debt of consensus (#2152)
* [slash] Remove dead interface, associated piping
* [slash] Expand out structs
* [consensus] Write to a chan when find a case of double-signing, remove dead code
* [slash] Broadcast the noticing of a double signing
* [rawdb] CRUD for slashing candidates
* [slashing][node][proto] Broadcast the slash record after receive from consensus, handle received proto message, persist in off-chain db while pending
* [slash][node][propose-block] Add verified slashes proposed into the header in block proposal
* [slash][shard] Factor out external validator as method on shard state, add double-signature field
* [slash][engine] Apply slash, name boolean expression for sorts, use stable sort
* [slash] Abstract Ballot results so keep track of both pre and post double sign event
* [slash] Fix type errors on test code
* [slash] Read from correct rawdb
* [slash] Add epoch based guards in CRUD of slashing
* [slash] Write to correct cache for slashing candidates
* [shard] Use explicit named type of BLS Signature, use convention
* [slash] Fix mistake done in refactor, improper header used. Factor out fromSlice to set
* [slash][node] Restore newblock to master, try again minimial change
* [cx-receipts] Break up one-liner, use SliceStable, not Slice
* [network] Finish refactor that makes network message headers once
* [network] Simplify creation further of headers write
* [slash] Adjust data structure of slash after offline discussion with RJ, Chao
* [slash] Still did need signature of the double signature
* [consensus] Prepare message does not have block header
* [consensus] Soft reset three files to 968517d~1
* [consensus] Begin factor consensus network intended message out with prepare first
* [consensus] Factor out Prepared message
* [consensus] Factor out announce message creation
* [consensus] Committed Message, branch on verify sender key for clearer log
* [consensus] Committed Message Factor out
* [consensus] Do jenkins MVP of signatures adjustment
* [main][slash] Provide YAML config as webhook config for double sign event
* [consensus] Adjust signatures, whitespace, lessen GC pressure
* [consensus] Remove dead code
* [consensus] Factor out commit overloaded message, give commit payload override in construct
* [consensus] Fix travis tests
* [consensus] Provide block bytes in SubmitVote(quorum.Commit)
* [consensus] Factor out noisy sanity checks in BFT, move existing commit check earlier as was before
* [quorum] Adjust signatures in quorum
* [staking] Adjust after merge from master
* [consensus] Finish refactor of consensus
* [node] Fix import
* [consensus] Fix travis
* [consensus] Use origin/master copy of block, fix mistake of pointer to empty byte
* [consensus] Less verbose bools
* [consensus] Remove unused trailing mutation hook in message construct
* [consensus] Address some TODOs on err, comment out double sign
5 years ago
|
|
|
package consensus
|
|
|
|
|
|
|
|
import (
|
|
|
|
msg_pb "github.com/harmony-one/harmony/api/proto/message"
|
|
|
|
"github.com/harmony-one/harmony/core/types"
|
|
|
|
"github.com/harmony-one/harmony/internal/chain"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (consensus *Consensus) validatorSanityChecks(msg *msg_pb.Message) bool {
|
|
|
|
senderKey, err := consensus.verifySenderKey(msg)
|
|
|
|
if err != nil {
|
|
|
|
if err == errValidNotInCommittee {
|
|
|
|
consensus.getLogger().Info().
|
|
|
|
Msg("sender key not in this slot's subcommittee")
|
|
|
|
} else {
|
|
|
|
consensus.getLogger().Error().Err(err).Msg("VerifySenderKey failed")
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if !senderKey.IsEqual(consensus.LeaderPubKey) &&
|
|
|
|
consensus.current.Mode() == Normal && !consensus.ignoreViewIDCheck {
|
|
|
|
consensus.getLogger().Warn().Msg("[OnPrepared] SenderKey not match leader PubKey")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := verifyMessageSig(senderKey, msg); err != nil {
|
|
|
|
consensus.getLogger().Error().Err(err).Msg(
|
|
|
|
"Failed to verify sender's signature",
|
|
|
|
)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (consensus *Consensus) leaderSanityChecks(msg *msg_pb.Message) bool {
|
|
|
|
senderKey, err := consensus.verifySenderKey(msg)
|
|
|
|
if err != nil {
|
|
|
|
if err == errValidNotInCommittee {
|
|
|
|
consensus.getLogger().Info().Msg(
|
|
|
|
"[OnAnnounce] sender key not in this slot's subcommittee",
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
consensus.getLogger().Error().Err(err).Msg("[OnAnnounce] erifySenderKey failed")
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if err = verifyMessageSig(senderKey, msg); err != nil {
|
|
|
|
consensus.getLogger().Error().Err(err).Msg(
|
|
|
|
"[OnPrepare] Failed to verify sender's signature",
|
|
|
|
)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (consensus *Consensus) onCommitSanityChecks(
|
|
|
|
recvMsg *FBFTMessage,
|
|
|
|
) bool {
|
|
|
|
if recvMsg.ViewID != consensus.viewID || recvMsg.BlockNum != consensus.blockNum {
|
|
|
|
consensus.getLogger().Debug().
|
|
|
|
Uint64("MsgViewID", recvMsg.ViewID).
|
|
|
|
Uint64("MsgBlockNum", recvMsg.BlockNum).
|
|
|
|
Uint64("blockNum", consensus.blockNum).
|
|
|
|
Str("ValidatorPubKey", recvMsg.SenderPubkey.SerializeToHexStr()).
|
|
|
|
Msg("[OnCommit] BlockNum/viewID not match")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if !consensus.FBFTLog.HasMatchingAnnounce(consensus.blockNum, recvMsg.BlockHash) {
|
|
|
|
consensus.getLogger().Debug().
|
|
|
|
Hex("MsgBlockHash", recvMsg.BlockHash[:]).
|
|
|
|
Uint64("MsgBlockNum", recvMsg.BlockNum).
|
|
|
|
Uint64("blockNum", consensus.blockNum).
|
|
|
|
Msg("[OnCommit] Cannot find matching blockhash")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if !consensus.FBFTLog.HasMatchingPrepared(consensus.blockNum, recvMsg.BlockHash) {
|
|
|
|
consensus.getLogger().Debug().
|
|
|
|
Hex("blockHash", recvMsg.BlockHash[:]).
|
|
|
|
Uint64("blockNum", consensus.blockNum).
|
|
|
|
Msg("[OnCommit] Cannot find matching prepared message")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (consensus *Consensus) onAnnounceSanityChecks(recvMsg *FBFTMessage) bool {
|
|
|
|
logMsgs := consensus.FBFTLog.GetMessagesByTypeSeqView(
|
|
|
|
msg_pb.MessageType_ANNOUNCE, recvMsg.BlockNum, recvMsg.ViewID,
|
|
|
|
)
|
|
|
|
if len(logMsgs) > 0 {
|
|
|
|
if logMsgs[0].BlockHash != recvMsg.BlockHash &&
|
|
|
|
logMsgs[0].SenderPubkey.IsEqual(recvMsg.SenderPubkey) {
|
|
|
|
consensus.getLogger().Debug().
|
|
|
|
Str("logMsgSenderKey", logMsgs[0].SenderPubkey.SerializeToHexStr()).
|
|
|
|
Str("logMsgBlockHash", logMsgs[0].BlockHash.Hex()).
|
|
|
|
Str("recvMsg.SenderPubkey", recvMsg.SenderPubkey.SerializeToHexStr()).
|
|
|
|
Uint64("recvMsg.BlockNum", recvMsg.BlockNum).
|
|
|
|
Uint64("recvMsg.ViewID", recvMsg.ViewID).
|
|
|
|
Str("recvMsgBlockHash", recvMsg.BlockHash.Hex()).
|
|
|
|
Str("LeaderKey", consensus.LeaderPubKey.SerializeToHexStr()).
|
|
|
|
Msg("[OnAnnounce] Leader is malicious")
|
|
|
|
if consensus.current.Mode() == ViewChanging {
|
|
|
|
viewID := consensus.current.ViewID()
|
|
|
|
consensus.startViewChange(viewID + 1)
|
|
|
|
} else {
|
|
|
|
consensus.startViewChange(consensus.viewID + 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
consensus.getLogger().Debug().
|
|
|
|
Str("leaderKey", consensus.LeaderPubKey.SerializeToHexStr()).
|
|
|
|
Msg("[OnAnnounce] Announce message received again")
|
|
|
|
}
|
|
|
|
return consensus.isRightBlockNumCheck(recvMsg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (consensus *Consensus) isRightBlockNumCheck(recvMsg *FBFTMessage) bool {
|
|
|
|
if recvMsg.BlockNum < consensus.blockNum {
|
|
|
|
consensus.getLogger().Debug().
|
|
|
|
Uint64("MsgBlockNum", recvMsg.BlockNum).
|
|
|
|
Msg("Wrong BlockNum Received, ignoring!")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
[slash][consensus] Notice double sign & broadcast, factor out tech debt of consensus (#2152)
* [slash] Remove dead interface, associated piping
* [slash] Expand out structs
* [consensus] Write to a chan when find a case of double-signing, remove dead code
* [slash] Broadcast the noticing of a double signing
* [rawdb] CRUD for slashing candidates
* [slashing][node][proto] Broadcast the slash record after receive from consensus, handle received proto message, persist in off-chain db while pending
* [slash][node][propose-block] Add verified slashes proposed into the header in block proposal
* [slash][shard] Factor out external validator as method on shard state, add double-signature field
* [slash][engine] Apply slash, name boolean expression for sorts, use stable sort
* [slash] Abstract Ballot results so keep track of both pre and post double sign event
* [slash] Fix type errors on test code
* [slash] Read from correct rawdb
* [slash] Add epoch based guards in CRUD of slashing
* [slash] Write to correct cache for slashing candidates
* [shard] Use explicit named type of BLS Signature, use convention
* [slash] Fix mistake done in refactor, improper header used. Factor out fromSlice to set
* [slash][node] Restore newblock to master, try again minimial change
* [cx-receipts] Break up one-liner, use SliceStable, not Slice
* [network] Finish refactor that makes network message headers once
* [network] Simplify creation further of headers write
* [slash] Adjust data structure of slash after offline discussion with RJ, Chao
* [slash] Still did need signature of the double signature
* [consensus] Prepare message does not have block header
* [consensus] Soft reset three files to 968517d~1
* [consensus] Begin factor consensus network intended message out with prepare first
* [consensus] Factor out Prepared message
* [consensus] Factor out announce message creation
* [consensus] Committed Message, branch on verify sender key for clearer log
* [consensus] Committed Message Factor out
* [consensus] Do jenkins MVP of signatures adjustment
* [main][slash] Provide YAML config as webhook config for double sign event
* [consensus] Adjust signatures, whitespace, lessen GC pressure
* [consensus] Remove dead code
* [consensus] Factor out commit overloaded message, give commit payload override in construct
* [consensus] Fix travis tests
* [consensus] Provide block bytes in SubmitVote(quorum.Commit)
* [consensus] Factor out noisy sanity checks in BFT, move existing commit check earlier as was before
* [quorum] Adjust signatures in quorum
* [staking] Adjust after merge from master
* [consensus] Finish refactor of consensus
* [node] Fix import
* [consensus] Fix travis
* [consensus] Use origin/master copy of block, fix mistake of pointer to empty byte
* [consensus] Less verbose bools
* [consensus] Remove unused trailing mutation hook in message construct
* [consensus] Address some TODOs on err, comment out double sign
5 years ago
|
|
|
func (consensus *Consensus) onPreparedSanityChecks(
|
|
|
|
blockObj *types.Block, recvMsg *FBFTMessage,
|
|
|
|
) bool {
|
|
|
|
if blockObj.NumberU64() != recvMsg.BlockNum ||
|
|
|
|
recvMsg.BlockNum < consensus.blockNum {
|
|
|
|
consensus.getLogger().Warn().
|
|
|
|
Uint64("MsgBlockNum", recvMsg.BlockNum).
|
|
|
|
Uint64("blockNum", blockObj.NumberU64()).
|
|
|
|
Msg("[OnPrepared] BlockNum not match")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if blockObj.Header().Hash() != recvMsg.BlockHash {
|
|
|
|
consensus.getLogger().Warn().
|
|
|
|
Uint64("MsgBlockNum", recvMsg.BlockNum).
|
|
|
|
Hex("MsgBlockHash", recvMsg.BlockHash[:]).
|
|
|
|
Str("blockObjHash", blockObj.Header().Hash().Hex()).
|
|
|
|
Msg("[OnPrepared] BlockHash not match")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if consensus.current.Mode() == Normal {
|
|
|
|
err := chain.Engine.VerifyHeader(consensus.ChainReader, blockObj.Header(), true)
|
|
|
|
if err != nil {
|
|
|
|
consensus.getLogger().Error().
|
|
|
|
Err(err).
|
|
|
|
Str("inChain", consensus.ChainReader.CurrentHeader().Number().String()).
|
|
|
|
Str("MsgBlockNum", blockObj.Header().Number().String()).
|
|
|
|
Msg("[OnPrepared] Block header is not verified successfully")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if consensus.BlockVerifier == nil {
|
|
|
|
// do nothing
|
|
|
|
} else if err := consensus.BlockVerifier(blockObj); err != nil {
|
|
|
|
consensus.getLogger().Error().Err(err).Msg("[OnPrepared] Block verification failed")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|