Skip to content

Commit

Permalink
[FAB-9661] Selection based on Fabric's Discovery
Browse files Browse the repository at this point in the history
Selection Service implementation using Fabric's
Discovery Service.

Change-Id: I11ebac5ddb397ead8fb5bec01e461697bd5a7d41
Signed-off-by: Bob Stasyszyn <[email protected]>
  • Loading branch information
bstasyszyn committed Jun 11, 2018
1 parent aedc226 commit 1fed320
Show file tree
Hide file tree
Showing 13 changed files with 951 additions and 46 deletions.
10 changes: 5 additions & 5 deletions pkg/client/common/discovery/dynamicdiscovery/chservice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"testing"
"time"

dyndiscmocks "github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/dynamicdiscovery/mocks"
clientmocks "github.com/hyperledger/fabric-sdk-go/pkg/client/common/mocks"
contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
pfab "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
discmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/discovery/mocks"
Expand Down Expand Up @@ -49,9 +49,9 @@ func TestDiscoveryService(t *testing.T) {
}
ctx.SetEndpointConfig(config)

discClient := dyndiscmocks.NewMockDiscoveryClient()
discClient := clientmocks.NewMockDiscoveryClient()
discClient.SetResponses(
&dyndiscmocks.MockDiscoverEndpointResponse{
&clientmocks.MockDiscoverEndpointResponse{
PeerEndpoints: []*discmocks.MockDiscoveryPeerEndpoint{},
},
)
Expand All @@ -73,7 +73,7 @@ func TestDiscoveryService(t *testing.T) {
assert.Equal(t, 0, len(peers))

discClient.SetResponses(
&dyndiscmocks.MockDiscoverEndpointResponse{
&clientmocks.MockDiscoverEndpointResponse{
PeerEndpoints: []*discmocks.MockDiscoveryPeerEndpoint{
{
MSPID: mspID1,
Expand All @@ -91,7 +91,7 @@ func TestDiscoveryService(t *testing.T) {
assert.Equalf(t, 1, len(peers), "Expected 1 peer")

discClient.SetResponses(
&dyndiscmocks.MockDiscoverEndpointResponse{
&clientmocks.MockDiscoverEndpointResponse{
PeerEndpoints: []*discmocks.MockDiscoveryPeerEndpoint{
{
MSPID: mspID1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"testing"
"time"

dyndiscmocks "github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/dynamicdiscovery/mocks"
clientmocks "github.com/hyperledger/fabric-sdk-go/pkg/client/common/mocks"
contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
pfab "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
discmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/discovery/mocks"
Expand Down Expand Up @@ -38,9 +38,9 @@ func TestLocalDiscoveryService(t *testing.T) {
}
config.SetCustomNetworkPeerCfg([]pfab.NetworkPeer{peer1})

discClient := dyndiscmocks.NewMockDiscoveryClient()
discClient := clientmocks.NewMockDiscoveryClient()
discClient.SetResponses(
&dyndiscmocks.MockDiscoverEndpointResponse{
&clientmocks.MockDiscoverEndpointResponse{
PeerEndpoints: []*discmocks.MockDiscoveryPeerEndpoint{},
},
)
Expand Down Expand Up @@ -72,7 +72,7 @@ func TestLocalDiscoveryService(t *testing.T) {
assert.Equal(t, 0, len(peers))

discClient.SetResponses(
&dyndiscmocks.MockDiscoverEndpointResponse{
&clientmocks.MockDiscoverEndpointResponse{
PeerEndpoints: []*discmocks.MockDiscoveryPeerEndpoint{
{
MSPID: mspID1,
Expand All @@ -90,7 +90,7 @@ func TestLocalDiscoveryService(t *testing.T) {
assert.Equal(t, 1, len(peers), "Expecting 1 peer")

discClient.SetResponses(
&dyndiscmocks.MockDiscoverEndpointResponse{
&clientmocks.MockDiscoverEndpointResponse{
PeerEndpoints: []*discmocks.MockDiscoveryPeerEndpoint{
{
MSPID: mspID1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package mocks

import (
reqcontext "context"
"sort"
"sync"

discclient "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/discovery/client"
Expand All @@ -24,11 +25,9 @@ type MockDiscoveryClient struct {
lock sync.RWMutex
}

// MockDiscoverEndpointResponse contains a mock response for the discover client
type MockDiscoverEndpointResponse struct {
Target string
PeerEndpoints []*discmocks.MockDiscoveryPeerEndpoint
Error error
// MockResponseBuilder builds a mock discovery response
type MockResponseBuilder interface {
Build() fabdiscovery.Response
}

// NewMockDiscoveryClient returns a new mock Discover service
Expand All @@ -42,25 +41,14 @@ func (m *MockDiscoveryClient) Send(ctx reqcontext.Context, req *discclient.Reque
}

// SetResponses sets the responses that the mock client should return from the Send function
func (m *MockDiscoveryClient) SetResponses(responses ...*MockDiscoverEndpointResponse) {
func (m *MockDiscoveryClient) SetResponses(responses ...MockResponseBuilder) {
m.lock.Lock()
defer m.lock.Unlock()

m.resp = nil

for _, resp := range responses {
var peers []*discclient.Peer
for _, endpoint := range resp.PeerEndpoints {
peer := &discclient.Peer{
MSPID: endpoint.MSPID,
AliveMessage: newAliveMessage(endpoint),
StateInfoMessage: newStateInfoMessage(endpoint),
}
peers = append(peers, peer)
}
m.resp = append(m.resp, &mockDiscoverResponse{
Response: &response{peers: peers}, target: resp.Target, err: resp.Error,
})
m.resp = append(m.resp, resp.Build())
}
}

Expand All @@ -73,24 +61,21 @@ func (m *MockDiscoveryClient) responses() []fabdiscovery.Response {
type mockDiscoverResponse struct {
discclient.Response
target string
err error
}

func (r *mockDiscoverResponse) Target() string {
return r.target
}

func (r *mockDiscoverResponse) Error() error {
return r.err
}

type response struct {
peers []*discclient.Peer
err error
}

func (r *response) ForChannel(string) discclient.ChannelResponse {
return &channelResponse{
peers: r.peers,
err: r.err,
}
}

Expand All @@ -102,6 +87,7 @@ func (r *response) ForLocal() discclient.LocalResponse {

type channelResponse struct {
peers []*discclient.Peer
err error
}

// Config returns a response for a config query, or error if something went wrong
Expand All @@ -111,12 +97,25 @@ func (cr *channelResponse) Config() (*discovery.ConfigResult, error) {

// Peers returns a response for a peer membership query, or error if something went wrong
func (cr *channelResponse) Peers() ([]*discclient.Peer, error) {
return cr.peers, nil
return cr.peers, cr.err
}

// Endorsers returns the response for an endorser query
func (cr *channelResponse) Endorsers(invocationChain discclient.InvocationChain, ps discclient.PrioritySelector, ef discclient.ExclusionFilter) (discclient.Endorsers, error) {
panic("not implemented")
if cr.err != nil {
return nil, cr.err
}

var endorsers discclient.Endorsers
for _, endorser := range cr.peers {
if !ef.Exclude(*endorser) {
endorsers = append(endorsers, endorser)
}
}

sortEndorsers(endorsers, ps)

return endorsers, nil
}

type localResponse struct {
Expand All @@ -128,6 +127,33 @@ func (cr *localResponse) Peers() ([]*discclient.Peer, error) {
return cr.peers, nil
}

// MockDiscoverEndpointResponse contains a mock response for the discover client
type MockDiscoverEndpointResponse struct {
Target string
PeerEndpoints []*discmocks.MockDiscoveryPeerEndpoint
Error error
}

// Build builds a mock discovery response
func (b *MockDiscoverEndpointResponse) Build() fabdiscovery.Response {
var peers []*discclient.Peer
for _, endpoint := range b.PeerEndpoints {
peer := &discclient.Peer{
MSPID: endpoint.MSPID,
AliveMessage: newAliveMessage(endpoint),
StateInfoMessage: newStateInfoMessage(endpoint),
}
peers = append(peers, peer)
}
return &mockDiscoverResponse{
Response: &response{
peers: peers,
err: b.Error,
},
target: b.Target,
}
}

func newAliveMessage(endpoint *discmocks.MockDiscoveryPeerEndpoint) *gossip.SignedGossipMessage {
return &gossip.SignedGossipMessage{
GossipMessage: &gossip.GossipMessage{
Expand Down Expand Up @@ -155,3 +181,31 @@ func newStateInfoMessage(endpoint *discmocks.MockDiscoveryPeerEndpoint) *gossip.
},
}
}

func sortEndorsers(endorsers discclient.Endorsers, ps discclient.PrioritySelector) discclient.Endorsers {
sort.Sort(&endorserSort{
Endorsers: endorsers,
PrioritySelector: ps,
})
return endorsers
}

type endorserSort struct {
discclient.Endorsers
discclient.PrioritySelector
}

func (es *endorserSort) Len() int {
return len(es.Endorsers)
}

func (es *endorserSort) Less(i, j int) bool {
e1 := es.Endorsers[i]
e2 := es.Endorsers[j]
less := es.Compare(*e1, *e2)
return less > discclient.Priority(0)
}

func (es *endorserSort) Swap(i, j int) {
es.Endorsers[i], es.Endorsers[j] = es.Endorsers[j], es.Endorsers[i]
}
27 changes: 27 additions & 0 deletions pkg/client/common/selection/fabricselection/cachekey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package fabricselection

import "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
import "encoding/json"

type cacheKey struct {
chaincodes []*fab.ChaincodeCall
}

func newCacheKey(chaincodes []*fab.ChaincodeCall) *cacheKey {
return &cacheKey{chaincodes: chaincodes}
}

func (k *cacheKey) String() string {
bytes, err := json.Marshal(k.chaincodes)
if err != nil {
logger.Errorf("unexpected error marshalling chaincodes: %s", err)
return ""
}
return string(bytes)
}
Loading

0 comments on commit 1fed320

Please sign in to comment.