github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/gossip/discovery/discovery.go (about) 1 /* 2 Copyright hechain. 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 "github.com/hechain20/hechain/gossip/common" 14 "github.com/hechain20/hechain/gossip/protoext" 15 proto "github.com/hyperledger/fabric-protos-go/gossip" 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 // AnchorPeerTracker is an interface that is passed to discovery to check if an endpoint is an anchor peer 77 type AnchorPeerTracker interface { 78 IsAnchorPeer(endpoint string) bool 79 } 80 81 // NetworkMember is a peer's representation 82 type NetworkMember struct { 83 Endpoint string 84 Metadata []byte 85 PKIid common.PKIidType 86 InternalEndpoint string 87 Properties *proto.Properties 88 *proto.Envelope 89 } 90 91 // Clone clones the NetworkMember 92 func (n NetworkMember) Clone() NetworkMember { 93 pkiIDClone := make(common.PKIidType, len(n.PKIid)) 94 copy(pkiIDClone, n.PKIid) 95 nmClone := NetworkMember{ 96 Endpoint: n.Endpoint, 97 Metadata: n.Metadata, 98 InternalEndpoint: n.InternalEndpoint, 99 PKIid: pkiIDClone, 100 } 101 102 if n.Properties != nil { 103 nmClone.Properties = protolib.Clone(n.Properties).(*proto.Properties) 104 } 105 106 if n.Envelope != nil { 107 nmClone.Envelope = protolib.Clone(n.Envelope).(*proto.Envelope) 108 } 109 110 return nmClone 111 } 112 113 // String returns a string representation of the NetworkMember 114 func (n NetworkMember) String() string { 115 return fmt.Sprintf("Endpoint: %s, InternalEndpoint: %s, PKI-ID: %s, Metadata: %x", n.Endpoint, n.InternalEndpoint, n.PKIid, n.Metadata) 116 } 117 118 // PreferredEndpoint computes the endpoint to connect to, 119 // while preferring internal endpoint over the standard 120 // endpoint 121 func (n NetworkMember) PreferredEndpoint() string { 122 if n.InternalEndpoint != "" { 123 return n.InternalEndpoint 124 } 125 return n.Endpoint 126 } 127 128 // PeerIdentification encompasses a remote peer's 129 // PKI-ID and whether its in the same org as the current 130 // peer or not 131 type PeerIdentification struct { 132 ID common.PKIidType 133 SelfOrg bool 134 } 135 136 type identifier func() (*PeerIdentification, error) 137 138 // Discovery is the interface that represents a discovery module 139 type Discovery interface { 140 // Lookup returns a network member, or nil if not found 141 Lookup(PKIID common.PKIidType) *NetworkMember 142 143 // Self returns this instance's membership information 144 Self() NetworkMember 145 146 // UpdateMetadata updates this instance's metadata 147 UpdateMetadata([]byte) 148 149 // UpdateEndpoint updates this instance's endpoint 150 UpdateEndpoint(string) 151 152 // Stops this instance 153 Stop() 154 155 // GetMembership returns the alive members in the view 156 GetMembership() []NetworkMember 157 158 // InitiateSync makes the instance ask a given number of peers 159 // for their membership information 160 InitiateSync(peerNum int) 161 162 // Connect makes this instance to connect to a remote instance 163 // The identifier param is a function that can be used to identify 164 // the peer, and to assert its PKI-ID, whether its in the peer's org or not, 165 // and whether the action was successful or not 166 Connect(member NetworkMember, id identifier) 167 } 168 169 // Members represents an aggregation of NetworkMembers 170 type Members []NetworkMember 171 172 // ByID returns a mapping from the PKI-IDs (in string form) 173 // to NetworkMember 174 func (members Members) ByID() map[string]NetworkMember { 175 res := make(map[string]NetworkMember, len(members)) 176 for _, peer := range members { 177 res[string(peer.PKIid)] = peer 178 } 179 return res 180 } 181 182 // Intersect returns the intersection of 2 Members 183 func (members Members) Intersect(otherMembers Members) Members { 184 var res Members 185 m := otherMembers.ByID() 186 for _, member := range members { 187 if _, exists := m[string(member.PKIid)]; exists { 188 res = append(res, member) 189 } 190 } 191 return res 192 } 193 194 // Filter returns only members that satisfy the given filter 195 func (members Members) Filter(filter func(member NetworkMember) bool) Members { 196 var res Members 197 for _, member := range members { 198 if filter(member) { 199 res = append(res, member) 200 } 201 } 202 return res 203 } 204 205 // Map invokes the given function to every NetworkMember among the Members 206 func (members Members) Map(f func(member NetworkMember) NetworkMember) Members { 207 var res Members 208 for _, m := range members { 209 res = append(res, f(m)) 210 } 211 return res 212 } 213 214 // HaveExternalEndpoints selects network members that have external endpoints 215 func HasExternalEndpoint(member NetworkMember) bool { 216 return member.Endpoint != "" 217 }