github.com/Hnampk/fabric@v2.1.1+incompatible/gossip/discovery/discovery.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package discovery 8 9 import ( 10 "fmt" 11 12 protolib "github.com/golang/protobuf/proto" 13 proto "github.com/hyperledger/fabric-protos-go/gossip" 14 "github.com/hyperledger/fabric/gossip/common" 15 "github.com/hyperledger/fabric/gossip/protoext" 16 ) 17 18 // CryptoService is an interface that the discovery expects to be implemented and passed on creation 19 type CryptoService interface { 20 // ValidateAliveMsg validates that an Alive message is authentic 21 ValidateAliveMsg(message *protoext.SignedGossipMessage) bool 22 23 // SignMessage signs a message 24 SignMessage(m *proto.GossipMessage, internalEndpoint string) *proto.Envelope 25 } 26 27 // EnvelopeFilter may or may not remove part of the Envelope 28 // that the given SignedGossipMessage originates from. 29 type EnvelopeFilter func(message *protoext.SignedGossipMessage) *proto.Envelope 30 31 // Sieve defines the messages that are allowed to be sent to some remote peer, 32 // based on some criteria. 33 // Returns whether the sieve permits sending a given message. 34 type Sieve func(message *protoext.SignedGossipMessage) bool 35 36 // DisclosurePolicy defines which messages a given remote peer 37 // is eligible of knowing about, and also what is it eligible 38 // to know about out of a given SignedGossipMessage. 39 // Returns: 40 // 1) A Sieve for a given remote peer. 41 // The Sieve is applied for each peer in question and outputs 42 // whether the message should be disclosed to the remote peer. 43 // 2) A EnvelopeFilter for a given SignedGossipMessage, which may remove 44 // part of the Envelope the SignedGossipMessage originates from 45 type DisclosurePolicy func(remotePeer *NetworkMember) (Sieve, EnvelopeFilter) 46 47 // CommService is an interface that the discovery expects to be implemented and passed on creation 48 type CommService interface { 49 // Gossip gossips a message 50 Gossip(msg *protoext.SignedGossipMessage) 51 52 // SendToPeer sends to a given peer a message. 53 // The nonce can be anything since the communication module handles the nonce itself 54 SendToPeer(peer *NetworkMember, msg *protoext.SignedGossipMessage) 55 56 // Ping probes a remote peer and returns if it's responsive or not 57 Ping(peer *NetworkMember) bool 58 59 // Accept returns a read-only channel for membership messages sent from remote peers 60 Accept() <-chan protoext.ReceivedMessage 61 62 // PresumedDead returns a read-only channel for peers that are presumed to be dead 63 PresumedDead() <-chan common.PKIidType 64 65 // CloseConn orders to close the connection with a certain peer 66 CloseConn(peer *NetworkMember) 67 68 // Forward sends message to the next hop, excluding the hop 69 // from which message was initially received 70 Forward(msg protoext.ReceivedMessage) 71 72 // IdentitySwitch returns a read-only channel about identity change events 73 IdentitySwitch() <-chan common.PKIidType 74 } 75 76 // NetworkMember is a peer's representation 77 type NetworkMember struct { 78 Endpoint string 79 Metadata []byte 80 PKIid common.PKIidType 81 InternalEndpoint string 82 Properties *proto.Properties 83 *proto.Envelope 84 } 85 86 // Clone clones the NetworkMember 87 func (n NetworkMember) Clone() NetworkMember { 88 pkiIDClone := make(common.PKIidType, len(n.PKIid)) 89 copy(pkiIDClone, n.PKIid) 90 nmClone := NetworkMember{ 91 Endpoint: n.Endpoint, 92 Metadata: n.Metadata, 93 InternalEndpoint: n.InternalEndpoint, 94 PKIid: pkiIDClone, 95 } 96 97 if n.Properties != nil { 98 nmClone.Properties = protolib.Clone(n.Properties).(*proto.Properties) 99 } 100 101 if n.Envelope != nil { 102 nmClone.Envelope = protolib.Clone(n.Envelope).(*proto.Envelope) 103 } 104 105 return nmClone 106 } 107 108 // String returns a string representation of the NetworkMember 109 func (n NetworkMember) String() string { 110 return fmt.Sprintf("Endpoint: %s, InternalEndpoint: %s, PKI-ID: %s, Metadata: %x", n.Endpoint, n.InternalEndpoint, n.PKIid, n.Metadata) 111 } 112 113 // PreferredEndpoint computes the endpoint to connect to, 114 // while preferring internal endpoint over the standard 115 // endpoint 116 func (n NetworkMember) PreferredEndpoint() string { 117 if n.InternalEndpoint != "" { 118 return n.InternalEndpoint 119 } 120 return n.Endpoint 121 } 122 123 // PeerIdentification encompasses a remote peer's 124 // PKI-ID and whether its in the same org as the current 125 // peer or not 126 type PeerIdentification struct { 127 ID common.PKIidType 128 SelfOrg bool 129 } 130 131 type identifier func() (*PeerIdentification, error) 132 133 // Discovery is the interface that represents a discovery module 134 type Discovery interface { 135 // Lookup returns a network member, or nil if not found 136 Lookup(PKIID common.PKIidType) *NetworkMember 137 138 // Self returns this instance's membership information 139 Self() NetworkMember 140 141 // UpdateMetadata updates this instance's metadata 142 UpdateMetadata([]byte) 143 144 // UpdateEndpoint updates this instance's endpoint 145 UpdateEndpoint(string) 146 147 // Stops this instance 148 Stop() 149 150 // GetMembership returns the alive members in the view 151 GetMembership() []NetworkMember 152 153 // InitiateSync makes the instance ask a given number of peers 154 // for their membership information 155 InitiateSync(peerNum int) 156 157 // Connect makes this instance to connect to a remote instance 158 // The identifier param is a function that can be used to identify 159 // the peer, and to assert its PKI-ID, whether its in the peer's org or not, 160 // and whether the action was successful or not 161 Connect(member NetworkMember, id identifier) 162 } 163 164 // Members represents an aggregation of NetworkMembers 165 type Members []NetworkMember 166 167 // ByID returns a mapping from the PKI-IDs (in string form) 168 // to NetworkMember 169 func (members Members) ByID() map[string]NetworkMember { 170 res := make(map[string]NetworkMember, len(members)) 171 for _, peer := range members { 172 res[string(peer.PKIid)] = peer 173 } 174 return res 175 } 176 177 // Intersect returns the intersection of 2 Members 178 func (members Members) Intersect(otherMembers Members) Members { 179 var res Members 180 m := otherMembers.ByID() 181 for _, member := range members { 182 if _, exists := m[string(member.PKIid)]; exists { 183 res = append(res, member) 184 } 185 } 186 return res 187 } 188 189 // Filter returns only members that satisfy the given filter 190 func (members Members) Filter(filter func(member NetworkMember) bool) Members { 191 var res Members 192 for _, member := range members { 193 if filter(member) { 194 res = append(res, member) 195 } 196 } 197 return res 198 } 199 200 // Map invokes the given function to every NetworkMember among the Members 201 func (members Members) Map(f func(member NetworkMember) NetworkMember) Members { 202 var res Members 203 for _, m := range members { 204 res = append(res, f(m)) 205 } 206 return res 207 } 208 209 // HaveExternalEndpoints selects network members that have external endpoints 210 func HasExternalEndpoint(member NetworkMember) bool { 211 return member.Endpoint != "" 212 }