@@ -27,27 +27,6 @@ import (
27
27
"golang.org/x/net/context"
28
28
)
29
29
30
- type state int
31
-
32
- const (
33
- created state = iota
34
- established
35
- ready
36
- )
37
-
38
- func (s state ) String () string {
39
- switch s {
40
- case created :
41
- return "created"
42
- case established :
43
- return "established"
44
- case ready :
45
- return "ready"
46
- default :
47
- return "UNKNOWN"
48
- }
49
- }
50
-
51
30
var chaincodeLogger = flogging .MustGetLogger ("chaincode" )
52
31
53
32
// ACLProvider is responsible for performing access control checks when invoking
@@ -56,20 +35,41 @@ type ACLProvider interface {
56
35
CheckACL (resName string , channelID string , idinfo interface {}) error
57
36
}
58
37
38
+ // Registry is responsible for tracking handlers.
59
39
type Registry interface {
60
40
Register (* Handler ) error
61
41
Ready (cname string )
62
42
Deregister (cname string ) error
63
43
}
64
44
45
+ // SystemCCProvider provides system chaincode metadata.
46
+ type SystemCCProvider interface {
47
+ IsSysCC (name string ) bool
48
+ IsSysCCAndNotInvokableCC2CC (name string ) bool
49
+ }
50
+
51
+ // PolicyChecker is used to evaluate instantiation policies.
52
+ type PolicyChecker interface {
53
+ CheckInstantiationPolicy (name , version string , cd * ccprovider.ChaincodeData ) error
54
+ }
55
+
56
+ // Adapter from function to PolicyChecker interface.
57
+ type CheckInstantiationPolicyFunc func (name , version string , cd * ccprovider.ChaincodeData ) error
58
+
59
+ func (c CheckInstantiationPolicyFunc ) CheckInstantiationPolicy (name , version string , cd * ccprovider.ChaincodeData ) error {
60
+ return c (name , version , cd )
61
+ }
62
+
65
63
// Handler implements the peer side of the chaincode stream.
66
64
type Handler struct {
65
+ // Keepalive specifies the interval at which keep-alive messages are sent.
66
+ Keepalive time.Duration
67
+ // SystemCCVersion specifies the current system chaincode version
68
+ SystemCCVersion string
67
69
// Lifecycle is used to access the Lifecycle System Chaincode.
68
70
Lifecycle * Lifecycle
69
71
// Executor is used to invoke chaincode.
70
72
Executor Executor
71
- // Keepalive specifies the interval at which keep-alive messages are sent.
72
- Keepalive time.Duration
73
73
// Registry is used to track active handlers.
74
74
Registry Registry
75
75
// ACLProvider is used to check if a chaincode invocation should be allowed.
@@ -79,15 +79,27 @@ type Handler struct {
79
79
TXContexts * TransactionContexts
80
80
// activeTransactions holds active transaction identifiers.
81
81
ActiveTransactions * ActiveTransactions
82
-
83
- sccp sysccprovider.SystemChaincodeProvider
84
-
85
- state state
82
+ // SystemCCProvider provides access to system chaincode metadata
83
+ SystemCCProvider SystemCCProvider
84
+ // PolicyChecker is used to evaluate the chaincode instantiation policies.
85
+ PolicyChecker PolicyChecker
86
+
87
+ // state holds the current handler state. It will be created, established, or
88
+ // ready.
89
+ state state
90
+ // chaincodeID holds the ID of the chaincode that registered with the peer.
86
91
chaincodeID * pb.ChaincodeID
87
- ccInstance * sysccprovider.ChaincodeInstance
88
- serialLock sync.Mutex // serialLock is used to serialize sends across the grpc chat stream.
89
- chatStream ccintf.ChaincodeStream
90
- errChan chan error // chan to pass error in sync and nonsync mode
92
+ // ccInstances holds information about the chaincode instance associated with
93
+ // the peer.
94
+ ccInstance * sysccprovider.ChaincodeInstance
95
+
96
+ // serialLock is used to serialize sends across the grpc chat stream.
97
+ serialLock sync.Mutex
98
+ // chatStream is the bidirectional grpc stream used to communicate with the
99
+ // chaincode instance.
100
+ chatStream ccintf.ChaincodeStream
101
+ // errChan is used to communicate errors from the async send to the receive loop
102
+ errChan chan error
91
103
}
92
104
93
105
// HandleMessage is the entry point Chaincode messages.
@@ -239,7 +251,7 @@ func (h *Handler) serialSendAsync(msg *pb.ChaincodeMessage, sendErr bool) {
239
251
func (h * Handler ) checkACL (signedProp * pb.SignedProposal , proposal * pb.Proposal , ccIns * sysccprovider.ChaincodeInstance ) error {
240
252
// ensure that we don't invoke a system chaincode
241
253
// that is not invokable through a cc2cc invocation
242
- if h .sccp .IsSysCCAndNotInvokableCC2CC (ccIns .ChaincodeName ) {
254
+ if h .SystemCCProvider .IsSysCCAndNotInvokableCC2CC (ccIns .ChaincodeName ) {
243
255
return errors .Errorf ("system chaincode %s cannot be invoked with a cc2cc invocation" , ccIns .ChaincodeName )
244
256
}
245
257
@@ -250,7 +262,7 @@ func (h *Handler) checkACL(signedProp *pb.SignedProposal, proposal *pb.Proposal,
250
262
// - an application chaincode (and we still need to determine
251
263
// whether the invoker can invoke it)
252
264
253
- if h .sccp .IsSysCC (ccIns .ChaincodeName ) {
265
+ if h .SystemCCProvider .IsSysCC (ccIns .ChaincodeName ) {
254
266
// Allow this call
255
267
return nil
256
268
}
@@ -717,7 +729,7 @@ func (h *Handler) getTxContextForInvoke(channelID string, txid string, payload [
717
729
// If targetInstance is not an SCC, isValidTxSim should be called which will return an err.
718
730
// We do not want to propagate calls to user CCs when the original call was to a SCC
719
731
// without a channel context (ie, no ledger context).
720
- if isscc := h .sccp .IsSysCC (targetInstance .ChaincodeName ); ! isscc {
732
+ if isscc := h .SystemCCProvider .IsSysCC (targetInstance .ChaincodeName ); ! isscc {
721
733
// normal path - UCC invocation with an empty ("") channel: isValidTxSim will return an error
722
734
return h .isValidTxSim ("" , txid , "could not get valid transaction" )
723
735
}
@@ -831,11 +843,8 @@ func (h *Handler) handleInvokeChaincode(msg *pb.ChaincodeMessage, txContext *Tra
831
843
832
844
chaincodeLogger .Debugf ("[%s] getting chaincode data for %s on channel %s" , shorttxid (msg .Txid ), targetInstance .ChaincodeName , targetInstance .ChainID )
833
845
834
- // is the chaincode a system chaincode ?
835
- isscc := h .sccp .IsSysCC (targetInstance .ChaincodeName )
836
-
837
- var version string
838
- if ! isscc {
846
+ version := h .SystemCCVersion
847
+ if ! h .SystemCCProvider .IsSysCC (targetInstance .ChaincodeName ) {
839
848
// if its a user chaincode, get the details
840
849
cd , err := h .Lifecycle .GetChaincodeDefinition (ctxt , msg .Txid , txContext .signedProp , txContext .proposal , targetInstance .ChainID , targetInstance .ChaincodeName )
841
850
if err != nil {
@@ -844,13 +853,10 @@ func (h *Handler) handleInvokeChaincode(msg *pb.ChaincodeMessage, txContext *Tra
844
853
845
854
version = cd .CCVersion ()
846
855
847
- err = ccprovider .CheckInstantiationPolicy (targetInstance .ChaincodeName , version , cd .(* ccprovider.ChaincodeData ))
856
+ err = h . PolicyChecker .CheckInstantiationPolicy (targetInstance .ChaincodeName , version , cd .(* ccprovider.ChaincodeData ))
848
857
if err != nil {
849
858
return nil , errors .WithStack (err )
850
859
}
851
- } else {
852
- // this is a system cc, just call it directly
853
- version = util .GetSysCCVersion ()
854
860
}
855
861
856
862
// Launch the new chaincode if not already running
@@ -935,3 +941,24 @@ func (h *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *
935
941
func (h * Handler ) Close () {
936
942
h .TXContexts .Close ()
937
943
}
944
+
945
+ type state int
946
+
947
+ const (
948
+ created state = iota
949
+ established
950
+ ready
951
+ )
952
+
953
+ func (s state ) String () string {
954
+ switch s {
955
+ case created :
956
+ return "created"
957
+ case established :
958
+ return "established"
959
+ case ready :
960
+ return "ready"
961
+ default :
962
+ return "UNKNOWN"
963
+ }
964
+ }
0 commit comments