github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/casper/auth_verification.go (about) 1 package casper 2 3 import ( 4 "fmt" 5 6 log "github.com/sirupsen/logrus" 7 8 "github.com/bytom/bytom/errors" 9 "github.com/bytom/bytom/protocol/bc" 10 "github.com/bytom/bytom/protocol/state" 11 ) 12 13 // AuthVerification verify whether the Verification is legal. 14 // the status of source checkpoint must justified, and an individual validator ν must not publish two distinct Verification 15 // ⟨ν,s1,t1,h(s1),h(t1)⟩ and ⟨ν,s2,t2,h(s2),h(t2)⟩, such that either: 16 // h(t1) = h(t2) OR h(s1) < h(s2) < h(t2) < h(t1) 17 func (c *Casper) AuthVerification(msg *ValidCasperSignMsg) error { 18 c.mu.Lock() 19 defer c.mu.Unlock() 20 targetNode := c.tree.nodeByHash(msg.TargetHash) 21 if targetNode == nil { 22 c.verificationCache.Add(verificationCacheKey(msg.TargetHash, msg.PubKey), msg) 23 return nil 24 } 25 26 source, err := c.store.GetCheckpoint(&msg.SourceHash) 27 if err != nil { 28 return err 29 } 30 31 v, err := convertVerification(source, targetNode.Checkpoint, msg) 32 if err != nil { 33 return err 34 } 35 36 if targetNode.ContainsVerification(v.order, &v.SourceHash) { 37 return nil 38 } 39 40 oldBestHash := c.bestChain() 41 if err := c.authVerification(v, targetNode.Checkpoint); err != nil { 42 return err 43 } 44 45 return c.tryRollback(oldBestHash) 46 } 47 48 func (c *Casper) authVerification(v *verification, target *state.Checkpoint) error { 49 if err := c.verifyVerification(v); err != nil { 50 return err 51 } 52 53 checkpoints, err := c.addVerificationToCheckpoint(target, v) 54 if err != nil { 55 return err 56 } 57 58 if err := c.msgQueue.Post(v.toValidCasperSignMsg()); err != nil { 59 return err 60 } 61 62 if err := c.store.SaveCheckpoints(checkpoints); err != nil { 63 return err 64 } 65 66 return c.saveVerificationToHeader(v) 67 } 68 69 func (c *Casper) addVerificationToCheckpoint(target *state.Checkpoint, verifications ...*verification) ([]*state.Checkpoint, error) { 70 validatorSize := len(target.Parent.EffectiveValidators()) 71 affectedCheckpoints := []*state.Checkpoint{target} 72 for _, v := range verifications { 73 source, err := c.store.GetCheckpoint(&v.SourceHash) 74 if err != nil { 75 return nil, err 76 } 77 78 supLink := target.AddVerification(v.SourceHash, v.SourceHeight, v.order, v.Signature) 79 if target.Status != state.Unjustified || !supLink.IsMajority(validatorSize) || source.Status == state.Finalized { 80 continue 81 } 82 83 c.setJustified(source, target) 84 affectedCheckpoints = append(affectedCheckpoints, source) 85 } 86 return affectedCheckpoints, nil 87 } 88 89 func (c *Casper) saveVerificationToHeader(v *verification) error { 90 blockHeader, err := c.store.GetBlockHeader(&v.TargetHash) 91 if err != nil { 92 return err 93 } 94 95 blockHeader.SupLinks.AddSupLink(v.SourceHeight, v.SourceHash, v.Signature, v.order) 96 return c.store.SaveBlockHeader(blockHeader) 97 } 98 99 // source status is justified, and exist a super majority link from source to target 100 func (c *Casper) setJustified(source, target *state.Checkpoint) { 101 target.Status = state.Justified 102 // must direct child 103 if target.ParentHash == source.Hash { 104 c.setFinalized(source) 105 } 106 } 107 108 func (c *Casper) setFinalized(checkpoint *state.Checkpoint) { 109 checkpoint.Status = state.Finalized 110 newRoot := c.tree.nodeByHash(checkpoint.Hash) 111 if newRoot == nil { 112 log.WithFields(log.Fields{"module": logModule, "hash": checkpoint.Hash}).Warn("source checkpoint before the last finalized checkpoint") 113 return 114 } 115 116 // update the checkpoint state in memory 117 newRoot.Status = state.Finalized 118 newRoot.Parent = nil 119 c.tree = newRoot 120 } 121 122 func (c *Casper) tryRollback(oldBestHash bc.Hash) error { 123 if newBestHash := c.bestChain(); oldBestHash != newBestHash { 124 msg := &RollbackMsg{BestHash: newBestHash, Reply: make(chan error)} 125 c.rollbackCh <- msg 126 return <-msg.Reply 127 } 128 return nil 129 } 130 131 func (c *Casper) authVerificationLoop() { 132 for blockHash := range c.newEpochCh { 133 validators, err := c.validators(&blockHash) 134 if err != nil { 135 log.WithFields(log.Fields{"err": err, "module": logModule}).Error("get validators when auth verification") 136 continue 137 } 138 139 for _, validator := range validators { 140 key := verificationCacheKey(blockHash, validator.PubKey) 141 data, ok := c.verificationCache.Get(key) 142 if !ok { 143 continue 144 } 145 146 if err := c.authCachedMsg(data.(*ValidCasperSignMsg), key); err != nil { 147 log.WithFields(log.Fields{"err": err, "module": logModule}).Error("auth cached message") 148 } 149 } 150 } 151 } 152 153 func (c *Casper) authCachedMsg(msg *ValidCasperSignMsg, msgKey string) error { 154 defer c.verificationCache.Remove(msgKey) 155 156 source, err := c.store.GetCheckpoint(&msg.SourceHash) 157 if err != nil { 158 return errors.Wrap(err, "get source checkpoint") 159 } 160 161 targetNode := c.tree.nodeByHash(msg.TargetHash) 162 if targetNode == nil { 163 return errors.New("get target checkpoint") 164 } 165 166 target := targetNode.Checkpoint 167 v, err := convertVerification(source, target, msg) 168 if err != nil { 169 return errors.Wrap(err, "authVerificationLoop fail on newVerification") 170 } 171 172 c.mu.Lock() 173 defer c.mu.Unlock() 174 return c.authVerification(v, target) 175 } 176 177 func (c *Casper) verifyVerification(v *verification) error { 178 if err := v.valid(); err != nil { 179 return err 180 } 181 182 if err := c.verifySameHeight(v); err != nil { 183 return err 184 } 185 186 return c.verifySpanHeight(v) 187 } 188 189 // a validator must not publish two distinct votes for the same target height 190 func (c *Casper) verifySameHeight(v *verification) error { 191 checkpoints, err := c.store.GetCheckpointsByHeight(v.TargetHeight) 192 if err != nil { 193 return err 194 } 195 196 for _, checkpoint := range checkpoints { 197 for _, supLink := range checkpoint.SupLinks { 198 if len(supLink.Signatures[v.order]) != 0 && checkpoint.Hash != v.TargetHash { 199 return errSameHeightInVerification 200 } 201 } 202 } 203 return nil 204 } 205 206 // a validator must not vote within the span of its other votes. 207 func (c *Casper) verifySpanHeight(v *verification) error { 208 if c.tree.findOnlyOne(func(checkpoint *state.Checkpoint) bool { 209 if checkpoint.Height == v.TargetHeight { 210 return false 211 } 212 213 for _, supLink := range checkpoint.SupLinks { 214 if len(supLink.Signatures[v.order]) != 0 { 215 if (checkpoint.Height < v.TargetHeight && supLink.SourceHeight > v.SourceHeight) || 216 (checkpoint.Height > v.TargetHeight && supLink.SourceHeight < v.SourceHeight) { 217 return true 218 } 219 } 220 } 221 return false 222 }) != nil { 223 return errSpanHeightInVerification 224 } 225 return nil 226 } 227 228 func verificationCacheKey(blockHash bc.Hash, pubKey string) string { 229 return fmt.Sprintf("%s:%s", blockHash.String(), pubKey) 230 }