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  }