github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/core/prepare.go (about) 1 package core 2 3 import ( 4 "reflect" 5 6 bft "github.com/quickchainproject/quickchain/consensus/dbft" 7 ) 8 9 func (c *core) sendPrepare() { 10 logger := c.logger.New("state", c.state) 11 12 sub := c.current.Subject() 13 encodedSubject, err := Encode(sub) 14 if err != nil { 15 logger.Error("Failed to encode", "subject", sub) 16 return 17 } 18 c.broadcast(&message{ 19 Code: msgPrepare, 20 Msg: encodedSubject, 21 }) 22 } 23 24 func (c *core) handlePrepare(msg *message, src bft.Validator) error { 25 // Decode PREPARE message 26 var prepare *bft.Subject 27 err := msg.Decode(&prepare) 28 if err != nil { 29 return errFailedDecodePrepare 30 } 31 32 if err := c.checkMessage(msgPrepare, prepare.View); err != nil { 33 return err 34 } 35 36 // If it is locked, it can only process on the locked block. 37 // Passing verifyPrepare and checkMessage implies it is processing on the locked block since it was verified in the Preprepared state. 38 if err := c.verifyPrepare(prepare, src); err != nil { 39 return err 40 } 41 42 c.acceptPrepare(msg, src) 43 44 // Change to Prepared state if we've received enough PREPARE messages or it is locked 45 // and we are in earlier state before Prepared state. 46 if ((c.current.IsHashLocked() && prepare.Digest == c.current.GetLockedHash()) || c.current.GetPrepareOrCommitSize() > 2*c.valSet.F()) && 47 c.state.Cmp(StatePrepared) < 0 { 48 c.current.LockHash() 49 c.setState(StatePrepared) 50 c.sendCommit() 51 } 52 53 return nil 54 } 55 56 // verifyPrepare verifies if the received PREPARE message is equivalent to our subject 57 func (c *core) verifyPrepare(prepare *bft.Subject, src bft.Validator) error { 58 logger := c.logger.New("from", src, "state", c.state) 59 60 sub := c.current.Subject() 61 if !reflect.DeepEqual(prepare, sub) { 62 logger.Warn("Inconsistent subjects between PREPARE and proposal", "expected", sub, "got", prepare) 63 return errInconsistentSubject 64 } 65 66 return nil 67 } 68 69 func (c *core) acceptPrepare(msg *message, src bft.Validator) error { 70 logger := c.logger.New("from", src, "state", c.state) 71 72 // Add the PREPARE message to current round state 73 if err := c.current.Prepares.Add(msg); err != nil { 74 logger.Error("Failed to add PREPARE message to round state", "msg", msg, "err", err) 75 return err 76 } 77 78 return nil 79 }