github.com/ewagmig/fabric@v2.1.1+incompatible/gossip/protoext/msgcomparator.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package protoext 8 9 import ( 10 "bytes" 11 12 "github.com/hyperledger/fabric-protos-go/gossip" 13 "github.com/hyperledger/fabric/gossip/common" 14 ) 15 16 // NewGossipMessageComparator creates a MessageReplacingPolicy given a maximum number of blocks to hold 17 func NewGossipMessageComparator(dataBlockStorageSize int) common.MessageReplacingPolicy { 18 return (&msgComparator{dataBlockStorageSize: dataBlockStorageSize}).getMsgReplacingPolicy() 19 } 20 21 type msgComparator struct { 22 dataBlockStorageSize int 23 } 24 25 func (mc *msgComparator) getMsgReplacingPolicy() common.MessageReplacingPolicy { 26 return func(this interface{}, that interface{}) common.InvalidationResult { 27 return mc.invalidationPolicy(this, that) 28 } 29 } 30 31 func (mc *msgComparator) invalidationPolicy(this interface{}, that interface{}) common.InvalidationResult { 32 thisMsg := this.(*SignedGossipMessage) 33 thatMsg := that.(*SignedGossipMessage) 34 35 if IsAliveMsg(thisMsg.GossipMessage) && IsAliveMsg(thatMsg.GossipMessage) { 36 return aliveInvalidationPolicy(thisMsg.GetAliveMsg(), thatMsg.GetAliveMsg()) 37 } 38 39 if IsDataMsg(thisMsg.GossipMessage) && IsDataMsg(thatMsg.GossipMessage) { 40 return mc.dataInvalidationPolicy(thisMsg.GetDataMsg(), thatMsg.GetDataMsg()) 41 } 42 43 if IsStateInfoMsg(thisMsg.GossipMessage) && IsStateInfoMsg(thatMsg.GossipMessage) { 44 return mc.stateInvalidationPolicy(thisMsg.GetStateInfo(), thatMsg.GetStateInfo()) 45 } 46 47 if IsIdentityMsg(thisMsg.GossipMessage) && IsIdentityMsg(thatMsg.GossipMessage) { 48 return mc.identityInvalidationPolicy(thisMsg.GetPeerIdentity(), thatMsg.GetPeerIdentity()) 49 } 50 51 if IsLeadershipMsg(thisMsg.GossipMessage) && IsLeadershipMsg(thatMsg.GossipMessage) { 52 return leaderInvalidationPolicy(thisMsg.GetLeadershipMsg(), thatMsg.GetLeadershipMsg()) 53 } 54 55 return common.MessageNoAction 56 } 57 58 func (mc *msgComparator) stateInvalidationPolicy(thisStateMsg *gossip.StateInfo, thatStateMsg *gossip.StateInfo) common.InvalidationResult { 59 if !bytes.Equal(thisStateMsg.PkiId, thatStateMsg.PkiId) { 60 return common.MessageNoAction 61 } 62 return compareTimestamps(thisStateMsg.Timestamp, thatStateMsg.Timestamp) 63 } 64 65 func (mc *msgComparator) identityInvalidationPolicy(thisIdentityMsg *gossip.PeerIdentity, thatIdentityMsg *gossip.PeerIdentity) common.InvalidationResult { 66 if bytes.Equal(thisIdentityMsg.PkiId, thatIdentityMsg.PkiId) { 67 return common.MessageInvalidated 68 } 69 70 return common.MessageNoAction 71 } 72 73 func (mc *msgComparator) dataInvalidationPolicy(thisDataMsg *gossip.DataMessage, thatDataMsg *gossip.DataMessage) common.InvalidationResult { 74 if thisDataMsg.Payload.SeqNum == thatDataMsg.Payload.SeqNum { 75 return common.MessageInvalidated 76 } 77 78 diff := abs(thisDataMsg.Payload.SeqNum, thatDataMsg.Payload.SeqNum) 79 if diff <= uint64(mc.dataBlockStorageSize) { 80 return common.MessageNoAction 81 } 82 83 if thisDataMsg.Payload.SeqNum > thatDataMsg.Payload.SeqNum { 84 return common.MessageInvalidates 85 } 86 return common.MessageInvalidated 87 } 88 89 func aliveInvalidationPolicy(thisMsg *gossip.AliveMessage, thatMsg *gossip.AliveMessage) common.InvalidationResult { 90 if !bytes.Equal(thisMsg.Membership.PkiId, thatMsg.Membership.PkiId) { 91 return common.MessageNoAction 92 } 93 94 return compareTimestamps(thisMsg.Timestamp, thatMsg.Timestamp) 95 } 96 97 func leaderInvalidationPolicy(thisMsg *gossip.LeadershipMessage, thatMsg *gossip.LeadershipMessage) common.InvalidationResult { 98 if !bytes.Equal(thisMsg.PkiId, thatMsg.PkiId) { 99 return common.MessageNoAction 100 } 101 102 return compareTimestamps(thisMsg.Timestamp, thatMsg.Timestamp) 103 } 104 105 func compareTimestamps(thisTS *gossip.PeerTime, thatTS *gossip.PeerTime) common.InvalidationResult { 106 if thisTS.IncNum == thatTS.IncNum { 107 if thisTS.SeqNum > thatTS.SeqNum { 108 return common.MessageInvalidates 109 } 110 111 return common.MessageInvalidated 112 } 113 if thisTS.IncNum < thatTS.IncNum { 114 return common.MessageInvalidated 115 } 116 return common.MessageInvalidates 117 } 118 119 // abs returns abs(a-b) 120 func abs(a, b uint64) uint64 { 121 if a > b { 122 return a - b 123 } 124 return b - a 125 }