github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/pbft/core/commit.go (about) 1 // Copyright 2020 The go-simplechain Authors 2 // This file is part of the go-simplechain library. 3 // 4 // The go-simplechain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-simplechain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-simplechain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "reflect" 21 "time" 22 23 "github.com/bigzoro/my_simplechain/common" 24 "github.com/bigzoro/my_simplechain/consensus/pbft" 25 ) 26 27 func (c *core) sendCommit() { 28 sub := c.current.Subject() 29 c.broadcastCommit(sub, true) 30 } 31 32 func (c *core) sendCommitForOldBlock(view *pbft.View, pending, digest common.Hash) { 33 sub := &pbft.Subject{ 34 View: view, 35 Pending: pending, 36 Digest: digest, 37 } 38 c.broadcastCommit(sub, false) 39 } 40 41 func (c *core) broadcastCommit(commit *pbft.Subject, fresh bool) { 42 logger := c.logger.New("state", c.state) 43 44 //logger.Error("send commit", "subject", commit, "fresh", fresh) 45 46 encodedSubject, err := Encode(commit) 47 if err != nil { 48 logger.Error("Failed to encode", "commit", commit) 49 return 50 } 51 52 commitMsg := &message{ 53 Code: msgCommit, 54 Msg: encodedSubject, 55 } 56 57 //c.broadcast(commitMsg, true) 58 c.broadcast(commitMsg, false) 59 60 // if commit is fresh, refresh current state 61 if fresh { 62 c.acceptCommit(commitMsg) 63 c.checkAndCommit(commit) 64 } 65 } 66 67 func (c *core) handleCommit(msg *message, src pbft.Validator) error { 68 c.commitTimestamp = time.Now() 69 70 // Decode COMMIT message 71 var commit *pbft.Subject 72 err := msg.Decode(&commit) 73 if err != nil { 74 return errFailedDecodeCommit 75 } 76 77 if err := c.checkMessage(msgCommit, commit.View); err != nil { 78 return err 79 } 80 81 if err := c.verifyCommit(commit, src); err != nil { 82 return err 83 } 84 85 c.acceptCommit(msg) 86 c.checkAndCommit(commit) 87 return nil 88 } 89 90 // verifyCommit verifies if the received COMMIT message is equivalent to our subject 91 func (c *core) verifyCommit(commit *pbft.Subject, src pbft.Validator) error { 92 logger := c.logger.New("from", src, "state", c.state) 93 94 sub := c.current.Subject() 95 if !reflect.DeepEqual(commit, sub) { 96 logger.Warn("Inconsistent subjects between commit and proposal", "expected", sub, "got", commit) 97 //return errInconsistentSubject 98 } 99 100 return nil 101 } 102 103 func (c *core) acceptCommit(msg *message) error { 104 logger := c.logger.New("from", msg.Address, "state", c.state) 105 logger.Trace("accept commit msg", "view", c.currentView(), "lockHash", c.current.lockedHash) 106 107 // Add the COMMIT message to current round state 108 if err := c.current.Commits.Add(msg); err != nil { 109 logger.Error("Failed to record commit message", "msg", msg, "err", err) 110 return err 111 } 112 113 return nil 114 } 115 116 func (c *core) checkAndCommit(commit *pbft.Subject) { 117 // Commit the proposal once we have enough COMMIT messages and we are not in the Committed state. 118 // 119 // If we already have a proposal, we may have chance to speed up the consensus process 120 // by committing the proposal without PREPARE messages. 121 if c.current.Commits.Size() >= c.Confirmations() && c.state.Cmp(StateCommitted) < 0 { 122 // Still need to call LockHash here since state can skip Prepared state and jump directly to the Committed state. 123 c.current.LockHash() 124 c.commit() 125 return 126 } 127 128 // Check and send commit-message, if state is not prepared 129 // Sometimes our node received a commit-message from another hashLocked node, 130 // the node cannot have enough prepare-messages to upgrade state to prepared or send commit-message 131 if c.state.Cmp(StatePrepared) < 0 { 132 c.checkAndPrepare(commit) 133 } 134 }