@@ -28,6 +28,7 @@ import (
28
28
"github.com/hyperledger/fabric/core/common/ccprovider"
29
29
ccintf "github.com/hyperledger/fabric/core/container/ccintf"
30
30
"github.com/hyperledger/fabric/core/ledger"
31
+ "github.com/hyperledger/fabric/core/peer"
31
32
pb "github.com/hyperledger/fabric/protos/peer"
32
33
"github.com/hyperledger/fabric/protos/utils"
33
34
"github.com/looplab/fsm"
@@ -114,14 +115,18 @@ func shorttxid(txid string) string {
114
115
//and suffix will just be absent (also note that LCCC reserves
115
116
//"/:[]${}" as special chars mainly for such namespace uses)
116
117
func (handler * Handler ) decomposeRegisteredName (cid * pb.ChaincodeID ) {
117
- handler .ccCompParts = & ccParts {}
118
- b := []byte (cid .Name )
118
+ handler .ccCompParts = chaincodeIDParts (cid .Name )
119
+ }
120
+
121
+ func chaincodeIDParts (ccName string ) * ccParts {
122
+ b := []byte (ccName )
123
+ p := & ccParts {}
119
124
120
125
//compute suffix (ie, chain name)
121
126
i := bytes .IndexByte (b , '/' )
122
127
if i >= 0 {
123
128
if i < len (b )- 1 {
124
- handler . ccCompParts .suffix = string (b [i + 1 :])
129
+ p .suffix = string (b [i + 1 :])
125
130
}
126
131
b = b [:i ]
127
132
}
@@ -130,14 +135,14 @@ func (handler *Handler) decomposeRegisteredName(cid *pb.ChaincodeID) {
130
135
i = bytes .IndexByte (b , ':' )
131
136
if i >= 0 {
132
137
if i < len (b )- 1 {
133
- handler . ccCompParts .version = string (b [i + 1 :])
138
+ p .version = string (b [i + 1 :])
134
139
}
135
140
b = b [:i ]
136
141
}
142
+ // remaining is the chaincode name
143
+ p .name = string (b )
137
144
138
- handler .ccCompParts .name = string (b )
139
-
140
- return
145
+ return p
141
146
}
142
147
143
148
func (handler * Handler ) getCCRootName () string {
@@ -221,6 +226,16 @@ func (handler *Handler) deleteQueryIterator(txContext *transactionContext, txid
221
226
delete (txContext .queryIteratorMap , txid )
222
227
}
223
228
229
+ // Check if the transactor is allow to call this chaincode on this channel
230
+ func (handler * Handler ) checkACL (proposal * pb.Proposal , calledCC * ccParts ) * pb.ChaincodeMessage {
231
+ // TODO: Decide what to pass in to verify that this transactor can access this
232
+ // channel (chID) and chaincode (ccID). Very likely we need the signedProposal
233
+ // which contains the sig and creator cert
234
+
235
+ // If error, return ChaincodeMessage with type ChaincodeMessage_ERROR
236
+ return nil
237
+ }
238
+
224
239
//THIS CAN BE REMOVED ONCE WE FULL SUPPORT (Invoke) CONFIDENTIALITY WITH CC-CALLING-CC
225
240
//Only invocation are allowed
226
241
func (handler * Handler ) canCallChaincode (txid string , isQuery bool ) * pb.ChaincodeMessage {
@@ -564,41 +579,50 @@ func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) {
564
579
}
565
580
566
581
var serialSendMsg * pb.ChaincodeMessage
582
+ var txContext * transactionContext
583
+ txContext , serialSendMsg = handler .isValidTxSim (msg .Txid ,
584
+ "[%s]No ledger context for GetState. Sending %s" , shorttxid (msg .Txid ), pb .ChaincodeMessage_ERROR )
567
585
568
586
defer func () {
569
587
handler .deleteTXIDEntry (msg .Txid )
570
- chaincodeLogger .Debugf ("[%s]handleGetState serial send %s" , shorttxid (serialSendMsg .Txid ), serialSendMsg .Type )
588
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
589
+ chaincodeLogger .Debugf ("[%s]handleGetState serial send %s" ,
590
+ shorttxid (serialSendMsg .Txid ), serialSendMsg .Type )
591
+ }
571
592
handler .serialSendAsync (serialSendMsg , nil )
572
593
}()
573
594
574
- key := string (msg .Payload )
595
+ if txContext == nil {
596
+ return
597
+ }
575
598
576
- // Invoke ledger to get state
599
+ key := string ( msg . Payload )
577
600
chaincodeID := handler .getCCRootName ()
601
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
602
+ chaincodeLogger .Debugf ("[%s] getting state for chaincode %s, key %s, channel %s" ,
603
+ shorttxid (msg .Txid ), chaincodeID , key , txContext .chainID )
604
+ }
578
605
579
606
var res []byte
580
607
var err error
581
- var txContext * transactionContext
582
-
583
- txContext , serialSendMsg = handler .isValidTxSim (msg .Txid , "[%s]No ledger context for GetState. Sending %s" , shorttxid (msg .Txid ), pb .ChaincodeMessage_ERROR )
584
- if txContext == nil {
585
- return
586
- }
587
-
588
608
res , err = txContext .txsimulator .GetState (chaincodeID , key )
589
609
590
610
if err != nil {
591
611
// Send error msg back to chaincode. GetState will not trigger event
592
612
payload := []byte (err .Error ())
593
- chaincodeLogger .Errorf ("[%s]Failed to get chaincode state(%s). Sending %s" , shorttxid (msg .Txid ), err , pb .ChaincodeMessage_ERROR )
613
+ chaincodeLogger .Errorf ("[%s]Failed to get chaincode state(%s). Sending %s" ,
614
+ shorttxid (msg .Txid ), err , pb .ChaincodeMessage_ERROR )
594
615
serialSendMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_ERROR , Payload : payload , Txid : msg .Txid }
595
616
} else if res == nil {
596
617
//The state object being requested does not exist
597
- chaincodeLogger .Debugf ("[%s]No state associated with key: %s. Sending %s with an empty payload" , shorttxid (msg .Txid ), key , pb .ChaincodeMessage_RESPONSE )
618
+ chaincodeLogger .Debugf ("[%s]No state associated with key: %s. Sending %s with an empty payload" ,
619
+ shorttxid (msg .Txid ), key , pb .ChaincodeMessage_RESPONSE )
598
620
serialSendMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_RESPONSE , Payload : res , Txid : msg .Txid }
599
621
} else {
600
622
// Send response msg back to chaincode. GetState will not trigger event
601
- chaincodeLogger .Debugf ("[%s]Got state. Sending %s" , shorttxid (msg .Txid ), pb .ChaincodeMessage_RESPONSE )
623
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
624
+ chaincodeLogger .Debugf ("[%s]Got state. Sending %s" , shorttxid (msg .Txid ), pb .ChaincodeMessage_RESPONSE )
625
+ }
602
626
serialSendMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_RESPONSE , Payload : res , Txid : msg .Txid }
603
627
}
604
628
@@ -677,7 +701,7 @@ func (handler *Handler) handleRangeQueryState(msg *pb.ChaincodeMessage) {
677
701
var i = uint32 (0 )
678
702
var qresult ledger.QueryResult
679
703
for ; i < maxRangeQueryStateLimit ; i ++ {
680
- qresult , err : = rangeIter .Next ()
704
+ qresult , err = rangeIter .Next ()
681
705
if err != nil {
682
706
chaincodeLogger .Errorf ("Failed to get query result from iterator. Sending %s" , pb .ChaincodeMessage_ERROR )
683
707
return
@@ -952,7 +976,7 @@ func (handler *Handler) handleExecuteQueryState(msg *pb.ChaincodeMessage) {
952
976
var i = uint32 (0 )
953
977
var qresult ledger.QueryResult
954
978
for ; i < maxExecuteQueryStateLimit ; i ++ {
955
- qresult , err : = executeIter .Next ()
979
+ qresult , err = executeIter .Next ()
956
980
if err != nil {
957
981
chaincodeLogger .Errorf ("Failed to get query result from iterator. Sending %s" , pb .ChaincodeMessage_ERROR )
958
982
return
@@ -970,8 +994,9 @@ func (handler *Handler) handleExecuteQueryState(msg *pb.ChaincodeMessage) {
970
994
handler .deleteQueryIterator (txContext , iterID )
971
995
}
972
996
997
+ var payloadBytes []byte
973
998
payload := & pb.QueryStateResponse {KeysAndValues : keysAndValues , HasMore : qresult != nil , ID : iterID }
974
- payloadBytes , err : = proto .Marshal (payload )
999
+ payloadBytes , err = proto .Marshal (payload )
975
1000
if err != nil {
976
1001
executeIter .Close ()
977
1002
handler .deleteQueryIterator (txContext , iterID )
@@ -1029,8 +1054,9 @@ func (handler *Handler) afterInvokeChaincode(e *fsm.Event, state string) {
1029
1054
func (handler * Handler ) enterBusyState (e * fsm.Event , state string ) {
1030
1055
go func () {
1031
1056
msg , _ := e .Args [0 ].(* pb.ChaincodeMessage )
1032
-
1033
- chaincodeLogger .Debugf ("[%s]state is %s" , shorttxid (msg .Txid ), state )
1057
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1058
+ chaincodeLogger .Debugf ("[%s]state is %s" , shorttxid (msg .Txid ), state )
1059
+ }
1034
1060
// Check if this is the unique request from this chaincode txid
1035
1061
uniqueReq := handler .createTXIDEntry (msg .Txid )
1036
1062
if ! uniqueReq {
@@ -1040,24 +1066,27 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
1040
1066
}
1041
1067
1042
1068
var triggerNextStateMsg * pb.ChaincodeMessage
1069
+ var txContext * transactionContext
1070
+ txContext , triggerNextStateMsg = handler .isValidTxSim (msg .Txid , "[%s]No ledger context for %s. Sending %s" ,
1071
+ shorttxid (msg .Txid ), msg .Type .String (), pb .ChaincodeMessage_ERROR )
1043
1072
1044
1073
defer func () {
1045
1074
handler .deleteTXIDEntry (msg .Txid )
1046
- chaincodeLogger .Debugf ("[%s]enterBusyState trigger event %s" , shorttxid (triggerNextStateMsg .Txid ), triggerNextStateMsg .Type )
1075
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1076
+ chaincodeLogger .Debugf ("[%s]enterBusyState trigger event %s" ,
1077
+ shorttxid (triggerNextStateMsg .Txid ), triggerNextStateMsg .Type )
1078
+ }
1047
1079
handler .triggerNextState (triggerNextStateMsg , true )
1048
1080
}()
1049
1081
1050
- chaincodeID := handler .getCCRootName ()
1051
- var err error
1052
- var res []byte
1053
-
1054
- var txContext * transactionContext
1055
-
1056
- txContext , triggerNextStateMsg = handler .isValidTxSim (msg .Txid , "[%s]No ledger context for %s. Sending %s" , shorttxid (msg .Txid ), msg .Type .String (), pb .ChaincodeMessage_ERROR )
1057
1082
if txContext == nil {
1058
1083
return
1059
1084
}
1060
1085
1086
+ chaincodeID := handler .getCCRootName ()
1087
+ var err error
1088
+ var res []byte
1089
+
1061
1090
if msg .Type .String () == pb .ChaincodeMessage_PUT_STATE .String () {
1062
1091
putStateInfo := & pb.PutStateInfo {}
1063
1092
unmarshalErr := proto .Unmarshal (msg .Payload , putStateInfo )
@@ -1074,11 +1103,8 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
1074
1103
key := string (msg .Payload )
1075
1104
err = txContext .txsimulator .DeleteState (chaincodeID , key )
1076
1105
} else if msg .Type .String () == pb .ChaincodeMessage_INVOKE_CHAINCODE .String () {
1077
- //check and prohibit C-call-C for CONFIDENTIAL txs
1078
- chaincodeLogger .Debugf ("[%s] C-call-C" , shorttxid (msg .Txid ))
1079
-
1080
- if triggerNextStateMsg = handler .canCallChaincode (msg .Txid , false ); triggerNextStateMsg != nil {
1081
- return
1106
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1107
+ chaincodeLogger .Debugf ("[%s] C-call-C" , shorttxid (msg .Txid ))
1082
1108
}
1083
1109
chaincodeSpec := & pb.ChaincodeSpec {}
1084
1110
unmarshalErr := proto .Unmarshal (msg .Payload , chaincodeSpec )
@@ -1089,31 +1115,76 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
1089
1115
return
1090
1116
}
1091
1117
1092
- // Get the chaincodeID to invoke
1093
- calledCCName := chaincodeSpec .ChaincodeID .Name
1094
- chaincodeLogger .Debugf ("[%s] C-call-C %s" , shorttxid (msg .Txid ), calledCCName )
1118
+ // Get the chaincodeID to invoke. The chaincodeID to be called may
1119
+ // contain composite info like "chaincode-name:version/channel-name"
1120
+ // We are not using version now but default to the latest
1121
+ calledCcParts := chaincodeIDParts (chaincodeSpec .ChaincodeID .Name )
1122
+ chaincodeSpec .ChaincodeID .Name = calledCcParts .name
1123
+ if calledCcParts .suffix == "" {
1124
+ // use caller's channel as the called chaincode is in the same channel
1125
+ calledCcParts .suffix = txContext .chainID
1126
+ }
1127
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1128
+ chaincodeLogger .Debugf ("[%s] C-call-C %s on channel %s" ,
1129
+ shorttxid (msg .Txid ), calledCcParts .name , calledCcParts .suffix )
1130
+ }
1131
+
1132
+ triggerNextStateMsg = handler .checkACL (txContext .proposal , calledCcParts )
1133
+ if triggerNextStateMsg != nil {
1134
+ return
1135
+ }
1095
1136
1137
+ // Set up a new context for the called chaincode if on a different channel
1138
+ // We grab the called channel's ledger simulator to hold the new state
1096
1139
ctxt := context .Background ()
1097
- ctxt = context .WithValue (ctxt , TXSimulatorKey , txContext .txsimulator )
1140
+ txsim := txContext .txsimulator
1141
+ if calledCcParts .suffix != txContext .chainID {
1142
+ lgr := peer .GetLedger (calledCcParts .suffix )
1143
+ if lgr == nil {
1144
+ payload := "Failed to find ledger for called channel " + calledCcParts .suffix
1145
+ triggerNextStateMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_ERROR ,
1146
+ Payload : []byte (payload ), Txid : msg .Txid }
1147
+ return
1148
+ }
1149
+ txsim2 , err2 := lgr .NewTxSimulator ()
1150
+ if err2 != nil {
1151
+ triggerNextStateMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_ERROR ,
1152
+ Payload : []byte (err2 .Error ()), Txid : msg .Txid }
1153
+ return
1154
+ }
1155
+ defer txsim2 .Done ()
1156
+ txsim = txsim2
1157
+ }
1158
+ ctxt = context .WithValue (ctxt , TXSimulatorKey , txsim )
1098
1159
1099
- // Create the invocation spec
1100
- chaincodeInvocationSpec := & pb.ChaincodeInvocationSpec {ChaincodeSpec : chaincodeSpec }
1160
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1161
+ chaincodeLogger .Debugf ("[%s] calling lccc to get chaincode data for %s on channel %s" ,
1162
+ shorttxid (msg .Txid ), calledCcParts .name , calledCcParts .suffix )
1163
+ }
1101
1164
1102
- //Get the latest version of calledCCName
1103
- cd , err := GetChaincodeDataFromLCCC (ctxt , msg .Txid , txContext .proposal , txContext .chainID , calledCCName )
1165
+ //Call LCCC to get the called chaincode artifacts
1166
+ var cd * ccprovider.ChaincodeData
1167
+ cd , err = GetChaincodeDataFromLCCC (ctxt , msg .Txid , txContext .proposal , calledCcParts .suffix , calledCcParts .name )
1104
1168
if err != nil {
1105
1169
payload := []byte (err .Error ())
1106
- chaincodeLogger .Debugf ("[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s" , shorttxid (msg .Txid ), err , pb .ChaincodeMessage_ERROR )
1170
+ chaincodeLogger .Debugf ("[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s" ,
1171
+ shorttxid (msg .Txid ), err , pb .ChaincodeMessage_ERROR )
1107
1172
triggerNextStateMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_ERROR , Payload : payload , Txid : msg .Txid }
1108
1173
return
1109
1174
}
1110
- cccid := ccprovider .NewCCContext (txContext . chainID , calledCCName , cd .Version , msg .Txid , false , txContext .proposal )
1175
+ cccid := ccprovider .NewCCContext (calledCcParts . suffix , calledCcParts . name , cd .Version , msg .Txid , false , txContext .proposal )
1111
1176
1112
1177
// Launch the new chaincode if not already running
1113
- _ , chaincodeInput , launchErr := handler .chaincodeSupport .Launch (ctxt , cccid , chaincodeInvocationSpec )
1178
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1179
+ chaincodeLogger .Debugf ("[%s] launching chaincode %s on channel %s" ,
1180
+ shorttxid (msg .Txid ), calledCcParts .name , calledCcParts .suffix )
1181
+ }
1182
+ cciSpec := & pb.ChaincodeInvocationSpec {ChaincodeSpec : chaincodeSpec }
1183
+ _ , chaincodeInput , launchErr := handler .chaincodeSupport .Launch (ctxt , cccid , cciSpec )
1114
1184
if launchErr != nil {
1115
1185
payload := []byte (launchErr .Error ())
1116
- chaincodeLogger .Debugf ("[%s]Failed to launch invoked chaincode. Sending %s" , shorttxid (msg .Txid ), pb .ChaincodeMessage_ERROR )
1186
+ chaincodeLogger .Debugf ("[%s]Failed to launch invoked chaincode. Sending %s" ,
1187
+ shorttxid (msg .Txid ), pb .ChaincodeMessage_ERROR )
1117
1188
triggerNextStateMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_ERROR , Payload : payload , Txid : msg .Txid }
1118
1189
return
1119
1190
}
@@ -1145,7 +1216,9 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
1145
1216
}
1146
1217
1147
1218
// Send response msg back to chaincode.
1148
- chaincodeLogger .Debugf ("[%s]Completed %s. Sending %s" , shorttxid (msg .Txid ), msg .Type .String (), pb .ChaincodeMessage_RESPONSE )
1219
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1220
+ chaincodeLogger .Debugf ("[%s]Completed %s. Sending %s" , shorttxid (msg .Txid ), msg .Type .String (), pb .ChaincodeMessage_RESPONSE )
1221
+ }
1149
1222
triggerNextStateMsg = & pb.ChaincodeMessage {Type : pb .ChaincodeMessage_RESPONSE , Payload : res , Txid : msg .Txid }
1150
1223
}()
1151
1224
}
@@ -1297,11 +1370,12 @@ func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string,
1297
1370
if err != nil {
1298
1371
return nil , err
1299
1372
}
1300
-
1301
- chaincodeLogger .Debugf ("[%s]Inside sendExecuteMessage. Message %s" , shorttxid (msg .Txid ), msg .Type .String ())
1373
+ if chaincodeLogger .IsEnabledFor (logging .DEBUG ) {
1374
+ chaincodeLogger .Debugf ("[%s]Inside sendExecuteMessage. Message %s" , shorttxid (msg .Txid ), msg .Type .String ())
1375
+ }
1302
1376
1303
1377
//if security is disabled the context elements will just be nil
1304
- if err : = handler .setChaincodeProposal (prop , msg ); err != nil {
1378
+ if err = handler .setChaincodeProposal (prop , msg ); err != nil {
1305
1379
return nil , err
1306
1380
}
1307
1381
0 commit comments