From 7620fce07466a6b5d7b933129b3ef48826f71799 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Mon, 5 Oct 2020 09:00:46 +0000 Subject: [PATCH] [viewchange] fix InitPayload func Signed-off-by: Leo Chen --- consensus/view_change.go | 10 ++- consensus/view_change_construct.go | 104 +++++++++++++++++------------ 2 files changed, 69 insertions(+), 45 deletions(-) diff --git a/consensus/view_change.go b/consensus/view_change.go index b38952f45..84a37fd3b 100644 --- a/consensus/view_change.go +++ b/consensus/view_change.go @@ -138,6 +138,15 @@ func (consensus *Consensus) startViewChange(viewID uint64) { consensus.consensusTimeout[timeoutViewChange].SetDuration(duration) defer consensus.consensusTimeout[timeoutViewChange].Start() + // init my own payload + if err := consensus.vc.InitPayload( + consensus.FBFTLog, + viewID, + consensus.blockNum, + consensus.priKey); err != nil { + consensus.getLogger().Error().Err(err).Msg("Init Payload Error") + } + // for view change, send separate view change per public key // do not do multi-sign of view change message for _, key := range consensus.priKey { @@ -196,7 +205,6 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) { if err := consensus.vc.InitPayload(consensus.FBFTLog, recvMsg.ViewID, recvMsg.BlockNum, - newLeaderKey.Bytes.Hex(), consensus.priKey); err != nil { consensus.getLogger().Error().Err(err).Msg("Init Payload Error") return diff --git a/consensus/view_change_construct.go b/consensus/view_change_construct.go index 9e6113324..46775fbe5 100644 --- a/consensus/view_change_construct.go +++ b/consensus/view_change_construct.go @@ -51,7 +51,6 @@ type viewChange struct { bhpBitmap map[uint64]*bls_cosi.Mask nilBitmap map[uint64]*bls_cosi.Mask viewIDBitmap map[uint64]*bls_cosi.Mask - viewIDCount map[uint64]map[string]int newViewMsg map[uint64]map[string]uint64 m1Payload []byte // message payload for type m1 := |vcBlockHash|prepared_agg_sigs|prepared_bitmap|, new leader only need one @@ -318,74 +317,91 @@ func (vc *viewChange) VerifyViewChangeMsg(recvMsg *FBFTMessage, members multibls } // InitPayload do it once when validator received view change message -// TODO: if I start the view change message, I should init my payload already func (vc *viewChange) InitPayload( fbftlog *FBFTLog, viewID uint64, blockNum uint64, - myPubKey string, privKeys multibls.PrivateKeys, ) error { vc.vcLock.Lock() defer vc.vcLock.Unlock() - // add my own M2 type message signature and bitmap - _, ok := vc.nilSigs[viewID][myPubKey] + // m1 or m2 init once per viewID/key. + // m1 and m2 are mutually exclusive. + // If the node has valid prepared block, it will add m1 signature. + // If not, the node will add m2 signature. + // Honest node should have only one kind of m1/m2 signature. + + inited := false + for _, key := range privKeys { + _, ok1 := vc.bhpSigs[viewID][key.Pub.Bytes.Hex()] + _, ok2 := vc.nilSigs[viewID][key.Pub.Bytes.Hex()] + if ok1 || ok2 { + inited = true + break + } + } - if !ok { - vc.getLogger().Info().Uint64("viewID", viewID).Uint64("blockNum", blockNum).Msg("[InitPayload] add my M2 (NIL) type messaage") - for i, key := range privKeys { - if err := vc.nilBitmap[viewID].SetKey(key.Pub.Bytes, true); err != nil { - vc.getLogger().Warn().Int("index", i).Msg("[InitPayload] nilBitmap setkey failed") - continue + // add my own M1/M2 type message signature and bitmap + if !inited { + preparedMsgs := fbftlog.GetMessagesByTypeSeq(msg_pb.MessageType_PREPARED, blockNum) + preparedMsg := fbftlog.FindMessageByMaxViewID(preparedMsgs) + hasBlock := false + if preparedMsg != nil { + if preparedBlock := fbftlog.GetBlockByHash(preparedMsg.BlockHash); preparedBlock != nil { + if err := vc.blockVerifier(preparedBlock); err == nil { + vc.getLogger().Info().Uint64("viewID", viewID).Uint64("blockNum", blockNum).Msg("[InitPayload] add my M1 (prepared) type messaage") + msgToSign := append(preparedMsg.BlockHash[:], preparedMsg.Payload...) + for _, key := range privKeys { + if err := vc.bhpBitmap[viewID].SetKey(key.Pub.Bytes, true); err != nil { + vc.getLogger().Warn().Str("key", key.Pub.Bytes.Hex()).Msg("[InitPayload] bhpBitmap setkey failed") + continue + } + vc.bhpSigs[viewID][key.Pub.Bytes.Hex()] = key.Pri.SignHash(msgToSign) + } + hasBlock = true + // if m1Payload is empty, we just add one + if vc.isM1PayloadEmpty() { + vc.m1Payload = append(preparedMsg.BlockHash[:], preparedMsg.Payload...) + } + } + } + } + if !hasBlock { + vc.getLogger().Info().Uint64("viewID", viewID).Uint64("blockNum", blockNum).Msg("[InitPayload] add my M2 (NIL) type messaage") + for _, key := range privKeys { + if err := vc.nilBitmap[viewID].SetKey(key.Pub.Bytes, true); err != nil { + vc.getLogger().Warn().Str("key", key.Pub.Bytes.Hex()).Msg("[InitPayload] nilBitmap setkey failed") + continue + } + vc.nilSigs[viewID][key.Pub.Bytes.Hex()] = key.Pri.SignHash(NIL) } - vc.nilSigs[viewID][key.Pub.Bytes.Hex()] = key.Pri.SignHash(NIL) } } - // add my own M3 type message signature and bitmap - _, ok = vc.viewIDSigs[viewID][myPubKey] + inited = false + for _, key := range privKeys { + _, ok3 := vc.viewIDSigs[viewID][key.Pub.Bytes.Hex()] + if ok3 { + inited = true + break + } + } - if !ok { + // add my own M3 type message signature and bitmap + if !inited { viewIDBytes := make([]byte, 8) binary.LittleEndian.PutUint64(viewIDBytes, viewID) vc.getLogger().Info().Uint64("viewID", viewID).Uint64("blockNum", blockNum).Msg("[InitPayload] add my M3 (ViewID) type messaage") - for i, key := range privKeys { + for _, key := range privKeys { if err := vc.viewIDBitmap[viewID].SetKey(key.Pub.Bytes, true); err != nil { - vc.getLogger().Warn().Int("index", i).Msg("[InitPayload] viewIDBitmap setkey failed") + vc.getLogger().Warn().Str("key", key.Pub.Bytes.Hex()).Msg("[InitPayload] viewIDBitmap setkey failed") continue } vc.viewIDSigs[viewID][key.Pub.Bytes.Hex()] = key.Pri.SignHash(viewIDBytes) } } - // add my own M1 type message signature and bitmap - _, ok = vc.bhpSigs[viewID][myPubKey] - - if !ok { - preparedMsgs := fbftlog.GetMessagesByTypeSeq(msg_pb.MessageType_PREPARED, blockNum) - preparedMsg := fbftlog.FindMessageByMaxViewID(preparedMsgs) - if preparedMsg != nil { - if preparedBlock := fbftlog.GetBlockByHash(preparedMsg.BlockHash); preparedBlock != nil { - if err := vc.blockVerifier(preparedBlock); err != nil { - return err - } - vc.getLogger().Info().Uint64("viewID", viewID).Uint64("blockNum", blockNum).Msg("[InitPayload] add my M1 (prepared) type messaage") - msgToSign := append(preparedMsg.BlockHash[:], preparedMsg.Payload...) - for i, key := range privKeys { - if err := vc.bhpBitmap[viewID].SetKey(key.Pub.Bytes, true); err != nil { - vc.getLogger().Warn().Int("index", i).Msg("[InitPayload] bhpBitmap setkey failed") - continue - } - vc.bhpSigs[viewID][key.Pub.Bytes.Hex()] = key.Pri.SignHash(msgToSign) - } - // if m1Payload is empty, we just add one - if vc.isM1PayloadEmpty() { - vc.m1Payload = append(preparedMsg.BlockHash[:], preparedMsg.Payload...) - } - } - } - } return nil }