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