Skip to content

Commit

Permalink
[FAB-6759] Selection Service (Static)
Browse files Browse the repository at this point in the history
 

Change-Id: I377cd948f962f5f6029988df2866204b6a75333a
Signed-off-by: Sandra Vrtikapa <sandra.vrtikapa@securekey.com>
  • Loading branch information
sandrask committed Oct 30, 2017
1 parent aafbea2 commit 2b9159f
Show file tree
Hide file tree
Showing 21 changed files with 367 additions and 253 deletions.
4 changes: 2 additions & 2 deletions api/apifabclient/discoveryprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ package apifabclient

// DiscoveryProvider is used to discover peers on the network
type DiscoveryProvider interface {
NewDiscoveryService(channel Channel) (DiscoveryService, error)
NewDiscoveryService(channelID string) (DiscoveryService, error)
}

// DiscoveryService is used to discover eligible peers on specific channel
type DiscoveryService interface {
GetPeers(chaincodeID string) ([]Peer, error)
GetPeers() ([]Peer, error)
}
6 changes: 0 additions & 6 deletions api/apifabclient/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ import (
type Peer interface {
txn.ProposalProcessor

// Events (need verb)
ConnectEventSource()
IsEventListened(event string, channel Channel) (bool, error)
AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error)
RemoveListener(eventListenerRef string) (bool, error)

// ECert Client (need verb)
EnrollmentCertificate() *pem.Block
SetEnrollmentCertificate(pem *pem.Block)
Expand Down
19 changes: 19 additions & 0 deletions api/apifabclient/selectionprovider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package apifabclient

// SelectionProvider is used to select peers for endorsement
type SelectionProvider interface {
NewSelectionService(channelID string) (SelectionService, error)
}

// SelectionService selects peers for endorsement and commit events
type SelectionService interface {
// GetEndorsersForChaincode returns a set of peers that should satisfy the endorsement
// policies of all of the given chaincodes
GetEndorsersForChaincode(channelPeers []Peer, chaincodeIDs ...string) ([]Peer, error)
}
1 change: 1 addition & 0 deletions def/fabapi/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type SDK interface {
StateStoreProvider() fab.KeyValueStore
ConfigProvider() apiconfig.Config
DiscoveryProvider() fab.DiscoveryProvider
SelectionProvider() fab.SelectionProvider
SigningManager() fab.SigningManager
}

Expand Down
7 changes: 6 additions & 1 deletion def/fabapi/context/defprovider/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import (
"github.com/hyperledger/fabric-sdk-go/pkg/errors"
kvs "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/keyvaluestore"
signingMgr "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/signingmgr"
discovery "github.com/hyperledger/fabric-sdk-go/pkg/fabric-txn/discovery"
discovery "github.com/hyperledger/fabric-sdk-go/pkg/fabric-txn/discovery/staticdiscovery"
selection "github.com/hyperledger/fabric-sdk-go/pkg/fabric-txn/selection/staticselection"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/bccsp"
bccspFactory "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/bccsp/factory"
)
Expand Down Expand Up @@ -66,5 +67,9 @@ func (f *DefaultProviderFactory) NewSigningManager(cryptoProvider bccsp.BCCSP, c
// NewDiscoveryProvider returns a new default implementation of discovery provider
func (f *DefaultProviderFactory) NewDiscoveryProvider(config apiconfig.Config) (fab.DiscoveryProvider, error) {
return discovery.NewDiscoveryProvider(config)
}

// NewSelectionProvider returns a new default implementation of selection service
func (f *DefaultProviderFactory) NewSelectionProvider(config apiconfig.Config) (fab.SelectionProvider, error) {
return selection.NewSelectionProvider(config)
}
17 changes: 12 additions & 5 deletions def/fabapi/context/defprovider/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,30 +41,37 @@ func (f *SessionClientFactory) NewSystemClient(sdk context.SDK, session context.
}

// NewChannelClient returns a client that can execute transactions on specified channel
func (f *SessionClientFactory) NewChannelClient(sdk context.SDK, session context.Session, config apiconfig.Config, channelName string) (apitxn.ChannelClient, error) {
func (f *SessionClientFactory) NewChannelClient(sdk context.SDK, session context.Session, config apiconfig.Config, channelID string) (apitxn.ChannelClient, error) {

// TODO: Add capablity to override sdk's selection and discovery provider

client := clientImpl.NewClient(sdk.ConfigProvider())
client.SetCryptoSuite(sdk.CryptoSuiteProvider())
client.SetStateStore(sdk.StateStoreProvider())
client.SetUserContext(session.Identity())
client.SetSigningManager(sdk.SigningManager())

channel, err := getChannel(client, channelName)
channel, err := getChannel(client, channelID)
if err != nil {
return nil, errors.WithMessage(err, "create channel failed")
}

discovery, err := sdk.DiscoveryProvider().NewDiscoveryService(channel)
discovery, err := sdk.DiscoveryProvider().NewDiscoveryService(channelID)
if err != nil {
return nil, errors.WithMessage(err, "create discovery service failed")
}

eventHub, err := getEventHub(client, channelName, session)
selection, err := sdk.SelectionProvider().NewSelectionService(channelID)
if err != nil {
return nil, errors.WithMessage(err, "create selection service failed")
}

eventHub, err := getEventHub(client, channelID, session)
if err != nil {
return nil, errors.WithMessage(err, "getEventHub failed")
}

return chImpl.NewChannelClient(client, channel, discovery, eventHub)
return chImpl.NewChannelClient(client, channel, discovery, selection, eventHub)
}

// getChannel is helper method to initializes and returns a channel based on config
Expand Down
3 changes: 2 additions & 1 deletion def/fabapi/context/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type SDKProviderFactory interface {
NewCryptoSuiteProvider(config *bccspFactory.FactoryOpts) (bccsp.BCCSP, error)
NewSigningManager(cryptoProvider bccsp.BCCSP, config apiconfig.Config) (fab.SigningManager, error)
NewDiscoveryProvider(config apiconfig.Config) (fab.DiscoveryProvider, error)
NewSelectionProvider(config apiconfig.Config) (fab.SelectionProvider, error)
}

// OrgClientFactory allows overriding default clients and providers of an organization
Expand All @@ -35,5 +36,5 @@ type OrgClientFactory interface {
// SessionClientFactory allows overriding default clients and providers of a session
type SessionClientFactory interface {
NewSystemClient(context SDK, session Session, config apiconfig.Config) (fab.FabricClient, error)
NewChannelClient(context SDK, session Session, config apiconfig.Config, channelName string) (txn.ChannelClient, error)
NewChannelClient(context SDK, session Session, config apiconfig.Config, channelID string) (txn.ChannelClient, error)
}
40 changes: 32 additions & 8 deletions def/fabapi/fabapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type FabricSDK struct {
stateStore apifabclient.KeyValueStore
cryptoSuite bccsp.BCCSP // TODO - maybe copy this interface into the API package
discoveryProvider apifabclient.DiscoveryProvider
selectionProvider apifabclient.SelectionProvider
signingManager apifabclient.SigningManager
}

Expand All @@ -55,6 +56,11 @@ type ChannelClientOpts struct {
ConfigProvider apiconfig.Config
}

// ProviderInit interface allows for initializing providers
type ProviderInit interface {
Initialize(sdk *FabricSDK) error
}

// NewSDK initializes default clients
func NewSDK(options Options) (*FabricSDK, error) {
// Construct SDK opts from the quick access options in setup
Expand Down Expand Up @@ -98,19 +104,32 @@ func NewSDK(options Options) (*FabricSDK, error) {
}
sdk.stateStore = store

// Initialize Signing Manager
signingMgr, err := sdk.ProviderFactory.NewSigningManager(sdk.CryptoSuiteProvider(), sdk.configProvider)
if err != nil {
return nil, errors.WithMessage(err, "failed to initialize signing manager")
}
sdk.signingManager = signingMgr

// Initialize discovery provider
discoveryProvider, err := sdk.ProviderFactory.NewDiscoveryProvider(sdk.configProvider)
if err != nil {
return nil, errors.WithMessage(err, "failed to initialize discovery provider")
}
if pi, ok := discoveryProvider.(ProviderInit); ok {
pi.Initialize(&sdk)
}
sdk.discoveryProvider = discoveryProvider

// Initialize Signing Manager
signingMgr, err := sdk.ProviderFactory.NewSigningManager(sdk.CryptoSuiteProvider(), sdk.configProvider)
// Initialize selection provider (for selecting endorsing peers)
selectionProvider, err := sdk.ProviderFactory.NewSelectionProvider(sdk.configProvider)
if err != nil {
return nil, errors.WithMessage(err, "failed to initialize signing manager")
return nil, errors.WithMessage(err, "failed to initialize selection provider")
}
sdk.signingManager = signingMgr
if pi, ok := selectionProvider.(ProviderInit); ok {
pi.Initialize(&sdk)
}
sdk.selectionProvider = selectionProvider

return &sdk, nil
}
Expand All @@ -135,6 +154,11 @@ func (sdk *FabricSDK) DiscoveryProvider() apifabclient.DiscoveryProvider {
return sdk.discoveryProvider
}

// SelectionProvider returns selection provider
func (sdk *FabricSDK) SelectionProvider() apifabclient.SelectionProvider {
return sdk.selectionProvider
}

// SigningManager returns signing manager
func (sdk *FabricSDK) SigningManager() apifabclient.SigningManager {
return sdk.signingManager
Expand Down Expand Up @@ -165,7 +189,7 @@ func (sdk *FabricSDK) NewSystemClient(s context.Session) (apifabclient.FabricCli
}

// NewChannelClient returns a new client for a channel
func (sdk *FabricSDK) NewChannelClient(channelName string, userName string) (apitxn.ChannelClient, error) {
func (sdk *FabricSDK) NewChannelClient(channelID string, userName string) (apitxn.ChannelClient, error) {

// Read default org name from configuration
client, err := sdk.configProvider.Client()
Expand All @@ -179,11 +203,11 @@ func (sdk *FabricSDK) NewChannelClient(channelName string, userName string) (api

opt := &ChannelClientOpts{OrgName: client.Organization, ConfigProvider: sdk.configProvider}

return sdk.NewChannelClientWithOpts(channelName, userName, opt)
return sdk.NewChannelClientWithOpts(channelID, userName, opt)
}

// NewChannelClientWithOpts returns a new client for a channel (user has to be pre-enrolled)
func (sdk *FabricSDK) NewChannelClientWithOpts(channelName string, userName string, opt *ChannelClientOpts) (apitxn.ChannelClient, error) {
func (sdk *FabricSDK) NewChannelClientWithOpts(channelID string, userName string, opt *ChannelClientOpts) (apitxn.ChannelClient, error) {

if opt == nil || opt.OrgName == "" {
return nil, errors.New("organization name must be provided")
Expand All @@ -199,7 +223,7 @@ func (sdk *FabricSDK) NewChannelClientWithOpts(channelName string, userName stri
configProvider = opt.ConfigProvider
}

client, err := sdk.SessionFactory.NewChannelClient(sdk, session, configProvider, channelName)
client, err := sdk.SessionFactory.NewChannelClient(sdk, session, configProvider, channelID)
if err != nil {
return nil, errors.WithMessage(err, "failed to created new channel client")
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/fabric-client/credentialmgr/credentialmgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestCredentialManager(t *testing.T) {

config, err := config.InitConfig("../../../test/fixtures/config/config_test.yaml")
if err != nil {
t.Log(err.Error())
t.Fatalf(err.Error())
}

credentialMgr, err := NewCredentialManager("Org1", config, &fcmocks.MockCryptoSuite{})
Expand Down Expand Up @@ -46,7 +46,7 @@ func TestInvalidOrgCredentialManager(t *testing.T) {

config, err := config.InitConfig("../../../test/fixtures/config/config_test.yaml")
if err != nil {
t.Log(err.Error())
t.Fatalf(err.Error())
}

// Invalid Org
Expand Down
29 changes: 7 additions & 22 deletions pkg/fabric-client/mocks/mockpeer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ package mocks
import (
"encoding/pem"

fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"

"github.com/hyperledger/fabric-sdk-go/pkg/errors"
)

// MockPeer is a mock fabricsdk.Peer.
Expand All @@ -24,26 +21,13 @@ type MockPeer struct {
MockRoles []string
MockCert *pem.Block
Payload []byte
MockMSP string
}

// ConnectEventSource does not connect anywhere
func (p *MockPeer) ConnectEventSource() {
// done.
}

// IsEventListened always returns true
func (p *MockPeer) IsEventListened(event string, chain fab.Channel) (bool, error) {
return true, nil
}

// AddListener is not implemented
func (p *MockPeer) AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error) {
return "", errors.New("Not implemented")
}

// RemoveListener is not implemented
func (p *MockPeer) RemoveListener(eventListenerRef string) (bool, error) {
return false, errors.New("Not implemented")
// NewMockPeer creates basic mock peer
func NewMockPeer(name string, url string) *MockPeer {
mp := &MockPeer{MockName: name, MockURL: url}
return mp
}

// Name returns the mock peer's mock name
Expand All @@ -58,11 +42,12 @@ func (p *MockPeer) SetName(name string) {

// MSPID gets the Peer mspID.
func (p *MockPeer) MSPID() string {
return ""
return p.MockMSP
}

// SetMSPID sets the Peer mspID.
func (p *MockPeer) SetMSPID(mspID string) {
p.MockMSP = mspID
}

// Roles returns the mock peer's mock roles
Expand Down
65 changes: 0 additions & 65 deletions pkg/fabric-client/peer/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,71 +119,6 @@ func (p *Peer) ProcessTransactionProposal(proposal apitxn.TransactionProposal) (
return p.processor.ProcessTransactionProposal(proposal)
}

//
// TODO: The following placeholders need to be examined - implement or delete.
//

// ConnectEventSource (placeholder)
/**
* Since practically all Peers are event producers, when constructing a Peer instance,
* an application can designate it as the event source for the application. Typically
* only one of the Peers on a Chain needs to be the event source, because all Peers on
* the Chain produce the same events. This method tells the SDK which Peer(s) to use as
* the event source for the client application. It is the responsibility of the SDK to
* manage the connection lifecycle to the Peer’s EventHub. It is the responsibility of
* the Client Application to understand and inform the selected Peer as to which event
* types it wants to receive and the call back functions to use.
* @returns {Future} This gives the app a handle to attach “success” and “error” listeners
*/
func (p *Peer) ConnectEventSource() {
//to do
}

// IsEventListened (placeholder)
/**
* A network call that discovers if at least one listener has been connected to the target
* Peer for a given event. This helps application instance to decide whether it needs to
* connect to the event source in a crash recovery or multiple instance deployment.
* @param {string} eventName required
* @param {Channel} channel optional
* @result {bool} Whether the said event has been listened on by some application instance on that chain.
*/
func (p *Peer) IsEventListened(event string, channel fab.Channel) (bool, error) {
//to do
return false, nil
}

// AddListener (placeholder)
/**
* For a Peer that is connected to eventSource, the addListener registers an EventCallBack for a
* set of event types. addListener can be invoked multiple times to support differing EventCallBack
* functions receiving different types of events.
*
* Note that the parameters below are optional in certain languages, like Java, that constructs an
* instance of a listener interface, and pass in that instance as the parameter.
* @param {string} eventType : ie. Block, Chaincode, Transaction
* @param {object} eventTypeData : Object Specific for event type as necessary, currently needed
* for “Chaincode” event type, specifying a matching pattern to the event name set in the chaincode(s)
* being executed on the target Peer, and for “Transaction” event type, specifying the transaction ID
* @param {struct} eventCallback Client Application class registering for the callback.
* @returns {string} An ID reference to the event listener.
*/
func (p *Peer) AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error) {
//to do
return "", nil
}

// RemoveListener (placeholder)
/**
* Unregisters a listener.
* @param {string} eventListenerRef Reference returned by SDK for event listener.
* @return {bool} Success / Failure status
*/
func (p *Peer) RemoveListener(eventListenerRef string) (bool, error) {
return false, nil
//to do
}

// PeersToTxnProcessors converts a slice of Peers to a slice of TxnProposalProcessors
func PeersToTxnProcessors(peers []fab.Peer) []apitxn.ProposalProcessor {
tpp := make([]apitxn.ProposalProcessor, len(peers))
Expand Down
Loading

0 comments on commit 2b9159f

Please sign in to comment.