aboutsummaryrefslogtreecommitdiffstats
path: root/core/consensus.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/consensus.go')
-rw-r--r--core/consensus.go135
1 files changed, 93 insertions, 42 deletions
diff --git a/core/consensus.go b/core/consensus.go
index 2b0d5a4..5a331d2 100644
--- a/core/consensus.go
+++ b/core/consensus.go
@@ -54,6 +54,8 @@ var (
"Configuration not ready")
ErrIncorrectBlockRandomness = fmt.Errorf(
"randomness of block is incorrect")
+ ErrCannotVerifyBlockRandomness = fmt.Errorf(
+ "cannot verify block randomness")
)
// consensusBAReceiver implements agreementReceiver.
@@ -225,44 +227,59 @@ func (recv *consensusBAReceiver) ConfirmBlock(
}
}
- voteList := make([]types.Vote, 0, len(votes))
- IDs := make(cryptoDKG.IDs, 0, len(votes))
- psigs := make([]cryptoDKG.PartialSignature, 0, len(votes))
- for _, vote := range votes {
- if vote.BlockHash != hash {
- continue
- }
- if recv.round() >= DKGDelayRound {
- ID, exist := recv.npks.IDMap[vote.ProposerID]
- if !exist {
+ if len(votes) == 0 && len(block.Finalization.Randomness) == 0 {
+ recv.consensus.logger.Error("No votes to recover randomness",
+ "block", block)
+ } else if votes != nil {
+ voteList := make([]types.Vote, 0, len(votes))
+ IDs := make(cryptoDKG.IDs, 0, len(votes))
+ psigs := make([]cryptoDKG.PartialSignature, 0, len(votes))
+ for _, vote := range votes {
+ if vote.BlockHash != hash {
continue
}
- IDs = append(IDs, ID)
- psigs = append(psigs, vote.PartialSignature)
+ if recv.round() >= DKGDelayRound {
+ ID, exist := recv.npks.IDMap[vote.ProposerID]
+ if !exist {
+ continue
+ }
+ IDs = append(IDs, ID)
+ psigs = append(psigs, vote.PartialSignature)
+ }
+ voteList = append(voteList, *vote)
}
- voteList = append(voteList, *vote)
- }
- if recv.round() >= DKGDelayRound {
- rand, err := cryptoDKG.RecoverSignature(psigs, IDs)
- if err != nil {
- recv.consensus.logger.Warn("Unable to recover randomness",
- "block", block,
- "error", err)
- } else {
- block.Finalization.Randomness = rand.Signature[:]
+ if recv.round() >= DKGDelayRound {
+ rand, err := cryptoDKG.RecoverSignature(psigs, IDs)
+ if err != nil {
+ recv.consensus.logger.Warn("Unable to recover randomness",
+ "block", block,
+ "error", err)
+ } else {
+ block.Finalization.Randomness = rand.Signature[:]
+ }
}
- }
- if recv.isNotary {
- result := &types.AgreementResult{
- BlockHash: block.Hash,
- Position: block.Position,
- Votes: voteList,
- Randomness: block.Finalization.Randomness,
- IsEmptyBlock: isEmptyBlockConfirmed,
+ // It's a workaround, the height for application is one-based.
+ block.Finalization.Height = block.Position.Height + 1
+
+ if recv.isNotary {
+ if block.Position.Round < DKGDelayRound {
+ result := &types.AgreementResult{
+ BlockHash: block.Hash,
+ Position: block.Position,
+ Votes: voteList,
+ FinalizationHeight: block.Finalization.Height,
+ IsEmptyBlock: isEmptyBlockConfirmed,
+ }
+ recv.consensus.logger.Debug("Propose AgreementResult",
+ "result", result)
+ recv.consensus.msgChan <- result
+ } else {
+ recv.consensus.logger.Debug(
+ "Propose AgreementResult as finalized block",
+ "block", block)
+ recv.consensus.network.BroadcastBlock(block)
+ }
}
- recv.consensus.logger.Debug("Propose AgreementResult",
- "result", result)
- recv.consensus.msgChan <- result
}
if block.Position.Height != 0 &&
@@ -300,6 +317,11 @@ func (recv *consensusBAReceiver) ConfirmBlock(
recv.consensus.logger.Info("Receive parent block",
"parent-hash", block.ParentHash.String()[:6],
"cur-position", block.Position)
+ if block.Finalization.Height == 0 {
+ // TODO(jimmy): use a seperate message to pull finalized
+ // block. Here, we pull it again as workaround.
+ continue
+ }
recv.consensus.processBlockChan <- block
parentHash = block.ParentHash
if block.Position.Height == 0 ||
@@ -1135,6 +1157,12 @@ MessageLoop:
delete(con.baConfirmedBlock, val.Hash)
ch <- val
}()
+ } else if val.IsFinalized() {
+ if err := con.processFinalizedBlock(val); err != nil {
+ con.logger.Error("Failed to process finalized block",
+ "block", val,
+ "error", err)
+ }
} else {
if err := con.preProcessBlock(val); err != nil {
con.logger.Error("Failed to pre process block",
@@ -1179,17 +1207,11 @@ func (con *Consensus) ProcessVote(vote *types.Vote) (err error) {
// ProcessAgreementResult processes the randomness request.
func (con *Consensus) ProcessAgreementResult(
rand *types.AgreementResult) error {
- if !con.baMgr.touchAgreementResult(rand) {
+ if rand.Position.Round >= DKGDelayRound {
return nil
}
- // TODO(jimmy): merge tsig check to VerifyAgreementResult
- ok, err := con.bcModule.verifyRandomness(
- rand.BlockHash, rand.Position.Round, rand.Randomness)
- if err != nil {
- return err
- }
- if !ok {
- return ErrIncorrectBlockRandomness
+ if !con.baMgr.touchAgreementResult(rand) {
+ return nil
}
// Sanity Check.
if err := VerifyAgreementResult(rand, con.nodeSetCache); err != nil {
@@ -1217,6 +1239,35 @@ func (con *Consensus) preProcessBlock(b *types.Block) (err error) {
return
}
+func (con *Consensus) processFinalizedBlock(b *types.Block) (err error) {
+ if b.Position.Round < DKGDelayRound {
+ return
+ }
+ if err = utils.VerifyBlockSignature(b); err != nil {
+ return
+ }
+ verifier, ok, err := con.tsigVerifierCache.UpdateAndGet(b.Position.Round)
+ if err != nil {
+ return
+ }
+ if !ok {
+ err = ErrCannotVerifyBlockRandomness
+ return
+ }
+ if !verifier.VerifySignature(b.Hash, crypto.Signature{
+ Type: "bls",
+ Signature: b.Finalization.Randomness,
+ }) {
+ err = ErrIncorrectBlockRandomness
+ return
+ }
+ err = con.baMgr.processFinalizedBlock(b)
+ if err == nil && con.debugApp != nil {
+ con.debugApp.BlockReceived(b.Hash)
+ }
+ return
+}
+
func (con *Consensus) deliveryGuard() {
defer con.waitGroup.Done()
select {