Skip to content

Commit ced4490

Browse files
committed
[FAB-6734] Define discovery service support interface
The discovery service requires certain capabilities from the peer layers such as message, identity verification, peer enumeration, etc. This change set defines the interface. Change-Id: I4888cdcea659ff40bc7c7b2e49f135093888ea1d Signed-off-by: yacovm <yacovm@il.ibm.com>
1 parent df2cdd7 commit ced4490

File tree

5 files changed

+159
-3
lines changed

5 files changed

+159
-3
lines changed

discovery/api.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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+
"github.com/hyperledger/fabric/gossip/api"
11+
"github.com/hyperledger/fabric/gossip/common"
12+
"github.com/hyperledger/fabric/gossip/discovery"
13+
common2 "github.com/hyperledger/fabric/protos/common"
14+
discovery2 "github.com/hyperledger/fabric/protos/discovery"
15+
)
16+
17+
// support defines an interface that allows the discovery service
18+
// to obtain information that other peer components have
19+
type support interface {
20+
// IdentityInfo returns identity information about peers
21+
IdentityInfo() api.PeerIdentitySet
22+
23+
// ChannelExists returns whether a given channel exists or not
24+
ChannelExists(channel string) bool
25+
26+
// PeersOfChannel returns the NetworkMembers considered alive
27+
// and also subscribed to the channel given
28+
PeersOfChannel(common.ChainID) discovery.Members
29+
30+
// Peers returns the NetworkMembers considered alive
31+
Peers() discovery.Members
32+
33+
// PeersForEndorsement returns an EndorsementDescriptor for a given set of peers, channel, and chaincode
34+
PeersForEndorsement(chaincode string, channel common.ChainID) (*discovery2.EndorsementDescriptor, error)
35+
36+
// Eligible returns whether the given peer is eligible for receiving
37+
// service from the discovery service for a given channel
38+
EligibleForService(channel string, data common2.SignedData) error
39+
40+
// Config returns the channel's configuration
41+
Config(channel string) (*discovery2.ConfigResult, error)
42+
}

gossip/api/api_test.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,26 @@ SPDX-License-Identifier: Apache-2.0
66

77
package api
88

9-
import "testing"
9+
import (
10+
"testing"
1011

11-
func TestNoop(t *testing.T) {
12-
// This is just to make this package included in the code-coverage statistics
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestPeerIdentitySetByOrg(t *testing.T) {
16+
p1 := PeerIdentityInfo{
17+
Organization: OrgIdentityType("ORG1"),
18+
Identity: PeerIdentityType("Peer1"),
19+
}
20+
p2 := PeerIdentityInfo{
21+
Organization: OrgIdentityType("ORG2"),
22+
Identity: PeerIdentityType("Peer2"),
23+
}
24+
is := PeerIdentitySet{
25+
p1, p2,
26+
}
27+
m := is.ByOrg()
28+
assert.Len(t, m, 2)
29+
assert.Equal(t, PeerIdentitySet{p1}, m["ORG1"])
30+
assert.Equal(t, PeerIdentitySet{p2}, m["ORG2"])
1331
}

gossip/api/crypto.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,26 @@ type MessageCryptoService interface {
6060
Expiration(peerIdentity PeerIdentityType) (time.Time, error)
6161
}
6262

63+
// PeerIdentityInfo aggregates a peer's identity,
64+
// and also additional metadata about it
65+
type PeerIdentityInfo struct {
66+
PKIId common.PKIidType
67+
Identity PeerIdentityType
68+
Organization OrgIdentityType
69+
}
70+
71+
// PeerIdentitySet aggregates a PeerIdentityInfo slice
72+
type PeerIdentitySet []PeerIdentityInfo
73+
74+
// ByOrg sorts the PeerIdentitySet by organizations of its peers
75+
func (pis PeerIdentitySet) ByOrg() map[string]PeerIdentitySet {
76+
m := make(map[string]PeerIdentitySet)
77+
for _, id := range pis {
78+
m[string(id.Organization)] = append(m[string(id.Organization)], id)
79+
}
80+
return m
81+
}
82+
6383
// PeerIdentityType is the peer's certificate
6484
type PeerIdentityType []byte
6585

gossip/discovery/discovery.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type NetworkMember struct {
7575
PKIid common.PKIidType
7676
InternalEndpoint string
7777
Properties *proto.Properties
78+
*proto.Envelope
7879
}
7980

8081
// String returns a string representation of the NetworkMember
@@ -133,3 +134,39 @@ type Discovery interface {
133134
// and whether the action was successful or not
134135
Connect(member NetworkMember, id identifier)
135136
}
137+
138+
// Members represents an aggregation of NetworkMembers
139+
type Members []NetworkMember
140+
141+
// ByID returns a mapping from the PKI-IDs (in string form)
142+
// to NetworkMember
143+
func (members Members) ByID() map[string]NetworkMember {
144+
res := make(map[string]NetworkMember, len(members))
145+
for _, peer := range members {
146+
res[string(peer.PKIid)] = peer
147+
}
148+
return res
149+
}
150+
151+
// Intersect returns the intersection of 2 Members
152+
func (members Members) Intersect(otherMembers Members) Members {
153+
var res Members
154+
m := otherMembers.ByID()
155+
for _, member := range members {
156+
if _, exists := m[string(member.PKIid)]; exists {
157+
res = append(res, member)
158+
}
159+
}
160+
return res
161+
}
162+
163+
// Filter returns only members that satisfy the given filter
164+
func (members Members) Filter(filter func(member NetworkMember) bool) Members {
165+
var res Members
166+
for _, member := range members {
167+
if filter(member) {
168+
res = append(res, member)
169+
}
170+
}
171+
return res
172+
}

gossip/discovery/discovery_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,45 @@ func TestMemRespDisclosurePol(t *testing.T) {
12321232
assert.NotZero(t, d2.sentMsgCount())
12331233
}
12341234

1235+
func TestMembersByID(t *testing.T) {
1236+
members := Members{
1237+
{PKIid: common.PKIidType("p0"), Endpoint: "p0"},
1238+
{PKIid: common.PKIidType("p1"), Endpoint: "p1"},
1239+
}
1240+
byID := members.ByID()
1241+
assert.Len(t, byID, 2)
1242+
assert.Equal(t, "p0", byID["p0"].Endpoint)
1243+
assert.Equal(t, "p1", byID["p1"].Endpoint)
1244+
}
1245+
1246+
func TestFilter(t *testing.T) {
1247+
members := Members{
1248+
{PKIid: common.PKIidType("p0"), Endpoint: "p0", Properties: &proto.Properties{
1249+
Chaincodes: []*proto.Chaincode{{Name: "cc", Version: "1.0"}},
1250+
}},
1251+
{PKIid: common.PKIidType("p1"), Endpoint: "p1", Properties: &proto.Properties{
1252+
Chaincodes: []*proto.Chaincode{{Name: "cc", Version: "2.0"}},
1253+
}},
1254+
}
1255+
res := members.Filter(func(member NetworkMember) bool {
1256+
cc := member.Properties.Chaincodes[0]
1257+
return cc.Version == "2.0" && cc.Name == "cc"
1258+
})
1259+
assert.Equal(t, Members{members[1]}, res)
1260+
}
1261+
1262+
func TestMembersIntersect(t *testing.T) {
1263+
members1 := Members{
1264+
{PKIid: common.PKIidType("p0"), Endpoint: "p0"},
1265+
{PKIid: common.PKIidType("p1"), Endpoint: "p1"},
1266+
}
1267+
members2 := Members{
1268+
{PKIid: common.PKIidType("p1"), Endpoint: "p1"},
1269+
{PKIid: common.PKIidType("p2"), Endpoint: "p2"},
1270+
}
1271+
assert.Equal(t, Members{{PKIid: common.PKIidType("p1"), Endpoint: "p1"}}, members1.Intersect(members2))
1272+
}
1273+
12351274
func waitUntilOrFail(t *testing.T, pred func() bool) {
12361275
waitUntilTimeoutOrFail(t, pred, timeout)
12371276
}

0 commit comments

Comments
 (0)