/
peerfilter.go
112 lines (94 loc) · 3.59 KB
/
peerfilter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package handler
import (
"time"
"github.com/hyperledger/fabric-sdk-go/pkg/client/common/selection/sorter/blockheightsorter"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke"
selectopts "github.com/hyperledger/fabric-sdk-go/pkg/client/common/selection/options"
logging "github.com/hyperledger/fabric-sdk-go/pkg/common/logging"
"github.com/hyperledger/fabric-sdk-go/pkg/common/options"
fabApi "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/pkg/errors"
"github.com/securekey/fabric-snaps/transactionsnap/api"
)
var logger = logging.NewLogger("txnsnap")
var peerSorter = blockheightsorter.New() // TODO: Configurable options
//NewPeerFilterHandler returns a handler that filter peers
func NewPeerFilterHandler(chaincodeIDs []string, config api.Config, next ...invoke.Handler) *PeerFilterHandler {
return &PeerFilterHandler{chaincodeIDs: chaincodeIDs, config: config, next: getNext(next)}
}
//PeerFilterHandler for handling peers filter
type PeerFilterHandler struct {
next invoke.Handler
chaincodeIDs []string
config api.Config
}
//Handle selects proposal processors
func (p *PeerFilterHandler) Handle(requestContext *invoke.RequestContext, clientContext *invoke.ClientContext) {
//Get proposal processor, if not supplied then use selection service to get available peers as endorser
if len(requestContext.Opts.Targets) == 0 {
remainingAttempts := p.config.GetEndorserSelectionMaxAttempts()
logger.Debugf("Attempting to get endorsers - [%d] attempts...", remainingAttempts)
var endorsers []fabApi.Peer
for len(endorsers) == 0 && remainingAttempts > 0 {
var err error
endorsers, err = p.getEndorsers(requestContext, clientContext)
if err != nil {
requestContext.Error = errors.WithMessage(err, "Failed to get endorsing peers")
return
}
if len(endorsers) == 0 {
remainingAttempts--
logger.Warnf("No endorsers. [%d] remaining attempts...", remainingAttempts)
time.Sleep(p.config.GetEndorserSelectionInterval())
}
}
requestContext.Opts.Targets = endorsers
}
//Delegate to next step if any
if p.next != nil {
p.next.Handle(requestContext, clientContext)
}
}
func (p *PeerFilterHandler) getEndorsers(requestContext *invoke.RequestContext, clientContext *invoke.ClientContext) ([]fabApi.Peer, error) {
var selectionOpts []options.Opt
if requestContext.SelectionFilter != nil {
selectionOpts = append(selectionOpts, selectopts.WithPeerFilter(requestContext.SelectionFilter))
}
if requestContext.PeerSorter != nil {
selectionOpts = append(selectionOpts, selectopts.WithPeerSorter(requestContext.PeerSorter))
} else {
selectionOpts = append(selectionOpts, selectopts.WithPeerSorter(peerSorter))
}
if len(p.chaincodeIDs) == 0 {
p.chaincodeIDs = make([]string, 1)
p.chaincodeIDs[0] = requestContext.Request.ChaincodeID
}
ccCalls := make([]*fabApi.ChaincodeCall, len(p.chaincodeIDs))
for i, cid := range p.chaincodeIDs {
ccCalls[i] = &fabApi.ChaincodeCall{ID: cid}
}
return clientContext.Selection.GetEndorsersForChaincode(ccCalls, selectionOpts...)
}
// filterTargets is helper method to filter peers
func (p *PeerFilterHandler) filterTargets(peers []fabApi.Peer, filter api.PeerFilter) []fabApi.Peer {
if filter == nil {
return peers
}
filteredPeers := []fabApi.Peer{}
for _, peer := range peers {
if filter.Accept(peer) {
filteredPeers = append(filteredPeers, peer)
}
}
return filteredPeers
}
func getNext(next []invoke.Handler) invoke.Handler {
if len(next) > 0 {
return next[0]
}
return nil
}