github.com/yimialmonte/fabric@v2.1.1+incompatible/core/chaincode/handler.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package chaincode 8 9 import ( 10 "fmt" 11 "io" 12 "strconv" 13 "strings" 14 "sync" 15 "time" 16 17 "github.com/golang/protobuf/proto" 18 pb "github.com/hyperledger/fabric-protos-go/peer" 19 "github.com/hyperledger/fabric/common/channelconfig" 20 "github.com/hyperledger/fabric/common/flogging" 21 commonledger "github.com/hyperledger/fabric/common/ledger" 22 "github.com/hyperledger/fabric/core/aclmgmt/resources" 23 "github.com/hyperledger/fabric/core/common/ccprovider" 24 "github.com/hyperledger/fabric/core/common/privdata" 25 "github.com/hyperledger/fabric/core/common/sysccprovider" 26 "github.com/hyperledger/fabric/core/container/ccintf" 27 "github.com/hyperledger/fabric/core/ledger" 28 "github.com/hyperledger/fabric/core/scc" 29 "github.com/pkg/errors" 30 ) 31 32 var chaincodeLogger = flogging.MustGetLogger("chaincode") 33 34 // An ACLProvider performs access control checks when invoking 35 // chaincode. 36 type ACLProvider interface { 37 CheckACL(resName string, channelID string, idinfo interface{}) error 38 } 39 40 // A Registry is responsible for tracking handlers. 41 type Registry interface { 42 Register(*Handler) error 43 Ready(string) 44 Failed(string, error) 45 Deregister(string) error 46 } 47 48 // An Invoker invokes chaincode. 49 type Invoker interface { 50 Invoke(txParams *ccprovider.TransactionParams, chaincodeName string, spec *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) 51 } 52 53 // TransactionRegistry tracks active transactions for each channel. 54 type TransactionRegistry interface { 55 Add(channelID, txID string) bool 56 Remove(channelID, txID string) 57 } 58 59 // A ContextRegistry is responsible for managing transaction contexts. 60 type ContextRegistry interface { 61 Create(txParams *ccprovider.TransactionParams) (*TransactionContext, error) 62 Get(chainID, txID string) *TransactionContext 63 Delete(chainID, txID string) 64 Close() 65 } 66 67 // QueryResponseBuilder is responsible for building QueryResponse messages for query 68 // transactions initiated by chaincode. 69 type QueryResponseBuilder interface { 70 BuildQueryResponse(txContext *TransactionContext, iter commonledger.ResultsIterator, 71 iterID string, isPaginated bool, totalReturnLimit int32) (*pb.QueryResponse, error) 72 } 73 74 // LedgerGetter is used to get ledgers for chaincode. 75 type LedgerGetter interface { 76 GetLedger(cid string) ledger.PeerLedger 77 } 78 79 // UUIDGenerator is responsible for creating unique query identifiers. 80 type UUIDGenerator interface { 81 New() string 82 } 83 type UUIDGeneratorFunc func() string 84 85 func (u UUIDGeneratorFunc) New() string { return u() } 86 87 // ApplicationConfigRetriever to retrieve the application configuration for a channel 88 type ApplicationConfigRetriever interface { 89 // GetApplicationConfig returns the channelconfig.Application for the channel 90 // and whether the Application config exists 91 GetApplicationConfig(cid string) (channelconfig.Application, bool) 92 } 93 94 // Handler implements the peer side of the chaincode stream. 95 type Handler struct { 96 // Keepalive specifies the interval at which keep-alive messages are sent. 97 Keepalive time.Duration 98 // TotalQueryLimit specifies the maximum number of results to return for 99 // chaincode queries. 100 TotalQueryLimit int 101 // Invoker is used to invoke chaincode. 102 Invoker Invoker 103 // Registry is used to track active handlers. 104 Registry Registry 105 // ACLProvider is used to check if a chaincode invocation should be allowed. 106 ACLProvider ACLProvider 107 // TXContexts is a collection of TransactionContext instances 108 // that are accessed by channel name and transaction ID. 109 TXContexts ContextRegistry 110 // activeTransactions holds active transaction identifiers. 111 ActiveTransactions TransactionRegistry 112 // BuiltinSCCs can be used to determine if a name is associated with a system chaincode 113 BuiltinSCCs scc.BuiltinSCCs 114 // QueryResponseBuilder is used to build query responses 115 QueryResponseBuilder QueryResponseBuilder 116 // LedgerGetter is used to get the ledger associated with a channel 117 LedgerGetter LedgerGetter 118 // DeployedCCInfoProvider is used to initialize the Collection Store 119 DeployedCCInfoProvider ledger.DeployedChaincodeInfoProvider 120 // UUIDGenerator is used to generate UUIDs 121 UUIDGenerator UUIDGenerator 122 // AppConfig is used to retrieve the application config for a channel 123 AppConfig ApplicationConfigRetriever 124 // Metrics holds chaincode handler metrics 125 Metrics *HandlerMetrics 126 127 // state holds the current handler state. It will be created, established, or 128 // ready. 129 state State 130 // chaincodeID holds the ID of the chaincode that registered with the peer. 131 chaincodeID string 132 133 // serialLock is used to serialize sends across the grpc chat stream. 134 serialLock sync.Mutex 135 // chatStream is the bidirectional grpc stream used to communicate with the 136 // chaincode instance. 137 chatStream ccintf.ChaincodeStream 138 // errChan is used to communicate errors from the async send to the receive loop 139 errChan chan error 140 // mutex is used to serialze the stream closed chan. 141 mutex sync.Mutex 142 // streamDoneChan is closed when the chaincode stream terminates. 143 streamDoneChan chan struct{} 144 } 145 146 // handleMessage is called by ProcessStream to dispatch messages. 147 func (h *Handler) handleMessage(msg *pb.ChaincodeMessage) error { 148 chaincodeLogger.Debugf("[%s] Fabric side handling ChaincodeMessage of type: %s in state %s", shorttxid(msg.Txid), msg.Type, h.state) 149 150 if msg.Type == pb.ChaincodeMessage_KEEPALIVE { 151 return nil 152 } 153 154 switch h.state { 155 case Created: 156 return h.handleMessageCreatedState(msg) 157 case Ready: 158 return h.handleMessageReadyState(msg) 159 default: 160 return errors.Errorf("handle message: invalid state %s for transaction %s", h.state, msg.Txid) 161 } 162 } 163 164 func (h *Handler) handleMessageCreatedState(msg *pb.ChaincodeMessage) error { 165 switch msg.Type { 166 case pb.ChaincodeMessage_REGISTER: 167 h.HandleRegister(msg) 168 default: 169 return fmt.Errorf("[%s] Fabric side handler cannot handle message (%s) while in created state", msg.Txid, msg.Type) 170 } 171 return nil 172 } 173 174 func (h *Handler) handleMessageReadyState(msg *pb.ChaincodeMessage) error { 175 switch msg.Type { 176 case pb.ChaincodeMessage_COMPLETED, pb.ChaincodeMessage_ERROR: 177 h.Notify(msg) 178 179 case pb.ChaincodeMessage_PUT_STATE: 180 go h.HandleTransaction(msg, h.HandlePutState) 181 case pb.ChaincodeMessage_DEL_STATE: 182 go h.HandleTransaction(msg, h.HandleDelState) 183 case pb.ChaincodeMessage_INVOKE_CHAINCODE: 184 go h.HandleTransaction(msg, h.HandleInvokeChaincode) 185 case pb.ChaincodeMessage_GET_STATE: 186 go h.HandleTransaction(msg, h.HandleGetState) 187 case pb.ChaincodeMessage_GET_STATE_BY_RANGE: 188 go h.HandleTransaction(msg, h.HandleGetStateByRange) 189 case pb.ChaincodeMessage_GET_QUERY_RESULT: 190 go h.HandleTransaction(msg, h.HandleGetQueryResult) 191 case pb.ChaincodeMessage_GET_HISTORY_FOR_KEY: 192 go h.HandleTransaction(msg, h.HandleGetHistoryForKey) 193 case pb.ChaincodeMessage_QUERY_STATE_NEXT: 194 go h.HandleTransaction(msg, h.HandleQueryStateNext) 195 case pb.ChaincodeMessage_QUERY_STATE_CLOSE: 196 go h.HandleTransaction(msg, h.HandleQueryStateClose) 197 case pb.ChaincodeMessage_GET_PRIVATE_DATA_HASH: 198 go h.HandleTransaction(msg, h.HandleGetPrivateDataHash) 199 case pb.ChaincodeMessage_GET_STATE_METADATA: 200 go h.HandleTransaction(msg, h.HandleGetStateMetadata) 201 case pb.ChaincodeMessage_PUT_STATE_METADATA: 202 go h.HandleTransaction(msg, h.HandlePutStateMetadata) 203 default: 204 return fmt.Errorf("[%s] Fabric side handler cannot handle message (%s) while in ready state", msg.Txid, msg.Type) 205 } 206 207 return nil 208 } 209 210 type MessageHandler interface { 211 Handle(*pb.ChaincodeMessage, *TransactionContext) (*pb.ChaincodeMessage, error) 212 } 213 214 type handleFunc func(*pb.ChaincodeMessage, *TransactionContext) (*pb.ChaincodeMessage, error) 215 216 // HandleTransaction is a middleware function that obtains and verifies a transaction 217 // context prior to forwarding the message to the provided delegate. Response messages 218 // returned by the delegate are sent to the chat stream. Any errors returned by the 219 // delegate are packaged as chaincode error messages. 220 func (h *Handler) HandleTransaction(msg *pb.ChaincodeMessage, delegate handleFunc) { 221 chaincodeLogger.Debugf("[%s] handling %s from chaincode", shorttxid(msg.Txid), msg.Type.String()) 222 if !h.registerTxid(msg) { 223 return 224 } 225 226 startTime := time.Now() 227 var txContext *TransactionContext 228 var err error 229 if msg.Type == pb.ChaincodeMessage_INVOKE_CHAINCODE { 230 txContext, err = h.getTxContextForInvoke(msg.ChannelId, msg.Txid, msg.Payload, "") 231 } else { 232 txContext, err = h.isValidTxSim(msg.ChannelId, msg.Txid, "no ledger context") 233 } 234 235 meterLabels := []string{ 236 "type", msg.Type.String(), 237 "channel", msg.ChannelId, 238 "chaincode", h.chaincodeID, 239 } 240 h.Metrics.ShimRequestsReceived.With(meterLabels...).Add(1) 241 242 var resp *pb.ChaincodeMessage 243 if err == nil { 244 resp, err = delegate(msg, txContext) 245 } 246 247 if err != nil { 248 err = errors.Wrapf(err, "%s failed: transaction ID: %s", msg.Type, msg.Txid) 249 chaincodeLogger.Errorf("[%s] Failed to handle %s. error: %+v", shorttxid(msg.Txid), msg.Type, err) 250 resp = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(err.Error()), Txid: msg.Txid, ChannelId: msg.ChannelId} 251 } 252 253 chaincodeLogger.Debugf("[%s] Completed %s. Sending %s", shorttxid(msg.Txid), msg.Type, resp.Type) 254 h.ActiveTransactions.Remove(msg.ChannelId, msg.Txid) 255 h.serialSendAsync(resp) 256 257 meterLabels = append(meterLabels, "success", strconv.FormatBool(resp.Type != pb.ChaincodeMessage_ERROR)) 258 h.Metrics.ShimRequestDuration.With(meterLabels...).Observe(time.Since(startTime).Seconds()) 259 h.Metrics.ShimRequestsCompleted.With(meterLabels...).Add(1) 260 } 261 262 func shorttxid(txid string) string { 263 if len(txid) < 8 { 264 return txid 265 } 266 return txid[0:8] 267 } 268 269 // ParseName parses a chaincode name into a ChaincodeInstance. The name should 270 // be of the form "chaincode-name:version/channel-name" with optional elements. 271 func ParseName(ccName string) *sysccprovider.ChaincodeInstance { 272 ci := &sysccprovider.ChaincodeInstance{} 273 274 z := strings.SplitN(ccName, "/", 2) 275 if len(z) == 2 { 276 ci.ChannelID = z[1] 277 } 278 z = strings.SplitN(z[0], ":", 2) 279 if len(z) == 2 { 280 ci.ChaincodeVersion = z[1] 281 } 282 ci.ChaincodeName = z[0] 283 284 return ci 285 } 286 287 // serialSend serializes msgs so gRPC will be happy 288 func (h *Handler) serialSend(msg *pb.ChaincodeMessage) error { 289 h.serialLock.Lock() 290 defer h.serialLock.Unlock() 291 292 if err := h.chatStream.Send(msg); err != nil { 293 err = errors.WithMessagef(err, "[%s] error sending %s", shorttxid(msg.Txid), msg.Type) 294 chaincodeLogger.Errorf("%+v", err) 295 return err 296 } 297 298 return nil 299 } 300 301 // serialSendAsync serves the same purpose as serialSend (serialize msgs so gRPC will 302 // be happy). In addition, it is also asynchronous so send-remoterecv--localrecv loop 303 // can be nonblocking. Only errors need to be handled and these are handled by 304 // communication on supplied error channel. A typical use will be a non-blocking or 305 // nil channel 306 func (h *Handler) serialSendAsync(msg *pb.ChaincodeMessage) { 307 go func() { 308 if err := h.serialSend(msg); err != nil { 309 // provide an error response to the caller 310 resp := &pb.ChaincodeMessage{ 311 Type: pb.ChaincodeMessage_ERROR, 312 Payload: []byte(err.Error()), 313 Txid: msg.Txid, 314 ChannelId: msg.ChannelId, 315 } 316 h.Notify(resp) 317 318 // surface send error to stream processing 319 h.errChan <- err 320 } 321 }() 322 } 323 324 // Check if the transactor is allow to call this chaincode on this channel 325 func (h *Handler) checkACL(signedProp *pb.SignedProposal, proposal *pb.Proposal, ccIns *sysccprovider.ChaincodeInstance) error { 326 // if we are here, all we know is that the invoked chaincode is either 327 // - a system chaincode that *is* invokable through a cc2cc 328 // (but we may still have to determine whether the invoker can perform this invocation) 329 // - an application chaincode 330 // (and we still need to determine whether the invoker can invoke it) 331 332 if h.BuiltinSCCs.IsSysCC(ccIns.ChaincodeName) { 333 // Allow this call 334 return nil 335 } 336 337 // A Nil signedProp will be rejected for non-system chaincodes 338 if signedProp == nil { 339 return errors.Errorf("signed proposal must not be nil from caller [%s]", ccIns.String()) 340 } 341 342 return h.ACLProvider.CheckACL(resources.Peer_ChaincodeToChaincode, ccIns.ChannelID, signedProp) 343 } 344 345 func (h *Handler) deregister() { 346 h.Registry.Deregister(h.chaincodeID) 347 } 348 349 func (h *Handler) streamDone() <-chan struct{} { 350 h.mutex.Lock() 351 defer h.mutex.Unlock() 352 return h.streamDoneChan 353 } 354 355 func (h *Handler) ProcessStream(stream ccintf.ChaincodeStream) error { 356 defer h.deregister() 357 358 h.mutex.Lock() 359 h.streamDoneChan = make(chan struct{}) 360 h.mutex.Unlock() 361 defer close(h.streamDoneChan) 362 363 h.chatStream = stream 364 h.errChan = make(chan error, 1) 365 366 var keepaliveCh <-chan time.Time 367 if h.Keepalive != 0 { 368 ticker := time.NewTicker(h.Keepalive) 369 defer ticker.Stop() 370 keepaliveCh = ticker.C 371 } 372 373 // holds return values from gRPC Recv below 374 type recvMsg struct { 375 msg *pb.ChaincodeMessage 376 err error 377 } 378 msgAvail := make(chan *recvMsg, 1) 379 380 receiveMessage := func() { 381 in, err := h.chatStream.Recv() 382 msgAvail <- &recvMsg{in, err} 383 } 384 385 go receiveMessage() 386 for { 387 select { 388 case rmsg := <-msgAvail: 389 switch { 390 // Defer the deregistering of the this handler. 391 case rmsg.err == io.EOF: 392 chaincodeLogger.Debugf("received EOF, ending chaincode support stream: %s", rmsg.err) 393 return rmsg.err 394 case rmsg.err != nil: 395 err := errors.Wrap(rmsg.err, "receive from chaincode support stream failed") 396 chaincodeLogger.Debugf("%+v", err) 397 return err 398 case rmsg.msg == nil: 399 err := errors.New("received nil message, ending chaincode support stream") 400 chaincodeLogger.Debugf("%+v", err) 401 return err 402 default: 403 err := h.handleMessage(rmsg.msg) 404 if err != nil { 405 err = errors.WithMessage(err, "error handling message, ending stream") 406 chaincodeLogger.Errorf("[%s] %+v", shorttxid(rmsg.msg.Txid), err) 407 return err 408 } 409 410 go receiveMessage() 411 } 412 413 case sendErr := <-h.errChan: 414 err := errors.Wrapf(sendErr, "received error while sending message, ending chaincode support stream") 415 chaincodeLogger.Errorf("%s", err) 416 return err 417 case <-keepaliveCh: 418 // if no error message from serialSend, KEEPALIVE happy, and don't care about error 419 // (maybe it'll work later) 420 h.serialSendAsync(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_KEEPALIVE}) 421 continue 422 } 423 } 424 } 425 426 // sendReady sends READY to chaincode serially (just like REGISTER) 427 func (h *Handler) sendReady() error { 428 chaincodeLogger.Debugf("sending READY for chaincode %s", h.chaincodeID) 429 ccMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY} 430 431 // if error in sending tear down the h 432 if err := h.serialSend(ccMsg); err != nil { 433 chaincodeLogger.Errorf("error sending READY (%s) for chaincode %s", err, h.chaincodeID) 434 return err 435 } 436 437 h.state = Ready 438 439 chaincodeLogger.Debugf("Changed to state ready for chaincode %s", h.chaincodeID) 440 441 return nil 442 } 443 444 // notifyRegistry will send ready on registration success and 445 // update the launch state of the chaincode in the handler registry. 446 func (h *Handler) notifyRegistry(err error) { 447 if err == nil { 448 err = h.sendReady() 449 } 450 451 if err != nil { 452 h.Registry.Failed(h.chaincodeID, err) 453 chaincodeLogger.Errorf("failed to start %s -- %s", h.chaincodeID, err) 454 return 455 } 456 457 h.Registry.Ready(h.chaincodeID) 458 } 459 460 // handleRegister is invoked when chaincode tries to register. 461 func (h *Handler) HandleRegister(msg *pb.ChaincodeMessage) { 462 chaincodeLogger.Debugf("Received %s in state %s", msg.Type, h.state) 463 chaincodeID := &pb.ChaincodeID{} 464 err := proto.Unmarshal(msg.Payload, chaincodeID) 465 if err != nil { 466 chaincodeLogger.Errorf("Error in received %s, could NOT unmarshal registration info: %s", pb.ChaincodeMessage_REGISTER, err) 467 return 468 } 469 470 // Now register with the chaincodeSupport 471 // Note: chaincodeID.Name is actually of the form name:version for older chaincodes, and 472 // of the form label:hash for newer chaincodes. Either way, it is the handle by which 473 // we track the chaincode's registration. 474 if chaincodeID.Name == "" { 475 h.notifyRegistry(errors.New("error in handling register chaincode, chaincodeID name is empty")) 476 return 477 } 478 h.chaincodeID = chaincodeID.Name 479 err = h.Registry.Register(h) 480 if err != nil { 481 h.notifyRegistry(err) 482 return 483 } 484 485 chaincodeLogger.Debugf("Got %s for chaincodeID = %s, sending back %s", pb.ChaincodeMessage_REGISTER, h.chaincodeID, pb.ChaincodeMessage_REGISTERED) 486 if err := h.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}); err != nil { 487 chaincodeLogger.Errorf("error sending %s: %s", pb.ChaincodeMessage_REGISTERED, err) 488 h.notifyRegistry(err) 489 return 490 } 491 492 h.state = Established 493 494 chaincodeLogger.Debugf("Changed state to established for %s", h.chaincodeID) 495 496 // for dev mode this will also move to ready automatically 497 h.notifyRegistry(nil) 498 } 499 500 func (h *Handler) Notify(msg *pb.ChaincodeMessage) { 501 tctx := h.TXContexts.Get(msg.ChannelId, msg.Txid) 502 if tctx == nil { 503 chaincodeLogger.Debugf("notifier Txid:%s, channelID:%s does not exist for handling message %s", msg.Txid, msg.ChannelId, msg.Type) 504 return 505 } 506 507 chaincodeLogger.Debugf("[%s] notifying Txid:%s, channelID:%s", shorttxid(msg.Txid), msg.Txid, msg.ChannelId) 508 tctx.ResponseNotifier <- msg 509 tctx.CloseQueryIterators() 510 } 511 512 // is this a txid for which there is a valid txsim 513 func (h *Handler) isValidTxSim(channelID string, txid string, fmtStr string, args ...interface{}) (*TransactionContext, error) { 514 txContext := h.TXContexts.Get(channelID, txid) 515 if txContext == nil || txContext.TXSimulator == nil { 516 err := errors.Errorf(fmtStr, args...) 517 chaincodeLogger.Errorf("no ledger context: %s %s\n\n %+v", channelID, txid, err) 518 return nil, err 519 } 520 return txContext, nil 521 } 522 523 // register Txid to prevent overlapping handle messages from chaincode 524 func (h *Handler) registerTxid(msg *pb.ChaincodeMessage) bool { 525 // Check if this is the unique state request from this chaincode txid 526 if h.ActiveTransactions.Add(msg.ChannelId, msg.Txid) { 527 return true 528 } 529 530 // Log the issue and drop the request 531 chaincodeLogger.Errorf("[%s] Another request pending for this CC: %s, Txid: %s, ChannelID: %s. Cannot process.", shorttxid(msg.Txid), h.chaincodeID, msg.Txid, msg.ChannelId) 532 return false 533 } 534 535 func (h *Handler) checkMetadataCap(msg *pb.ChaincodeMessage) error { 536 ac, exists := h.AppConfig.GetApplicationConfig(msg.ChannelId) 537 if !exists { 538 return errors.Errorf("application config does not exist for %s", msg.ChannelId) 539 } 540 541 if !ac.Capabilities().KeyLevelEndorsement() { 542 return errors.New("key level endorsement is not enabled, channel application capability of V1_3 or later is required") 543 } 544 return nil 545 } 546 547 func errorIfCreatorHasNoReadPermission(chaincodeName, collection string, txContext *TransactionContext) error { 548 rwPermission, err := getReadWritePermission(chaincodeName, collection, txContext) 549 if err != nil { 550 return err 551 } 552 if !rwPermission.read { 553 return errors.Errorf("tx creator does not have read access permission on privatedata in chaincodeName:%s collectionName: %s", 554 chaincodeName, collection) 555 } 556 return nil 557 } 558 559 func errorIfCreatorHasNoWritePermission(chaincodeName, collection string, txContext *TransactionContext) error { 560 rwPermission, err := getReadWritePermission(chaincodeName, collection, txContext) 561 if err != nil { 562 return err 563 } 564 if !rwPermission.write { 565 return errors.Errorf("tx creator does not have write access permission on privatedata in chaincodeName:%s collectionName: %s", 566 chaincodeName, collection) 567 } 568 return nil 569 } 570 571 func getReadWritePermission(chaincodeName, collection string, txContext *TransactionContext) (*readWritePermission, error) { 572 // check to see if read access has already been checked in the scope of this chaincode simulation 573 if rwPermission := txContext.CollectionACLCache.get(collection); rwPermission != nil { 574 return rwPermission, nil 575 } 576 577 cc := privdata.CollectionCriteria{ 578 Channel: txContext.ChannelID, 579 Namespace: chaincodeName, 580 Collection: collection, 581 } 582 583 readP, writeP, err := txContext.CollectionStore.RetrieveReadWritePermission(cc, txContext.SignedProp, txContext.TXSimulator) 584 if err != nil { 585 return nil, err 586 } 587 rwPermission := &readWritePermission{read: readP, write: writeP} 588 txContext.CollectionACLCache.put(collection, rwPermission) 589 590 return rwPermission, nil 591 } 592 593 // Handles query to ledger to get state 594 func (h *Handler) HandleGetState(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 595 getState := &pb.GetState{} 596 err := proto.Unmarshal(msg.Payload, getState) 597 if err != nil { 598 return nil, errors.Wrap(err, "unmarshal failed") 599 } 600 601 var res []byte 602 namespaceID := txContext.NamespaceID 603 collection := getState.Collection 604 chaincodeLogger.Debugf("[%s] getting state for chaincode %s, key %s, channel %s", shorttxid(msg.Txid), namespaceID, getState.Key, txContext.ChannelID) 605 606 if isCollectionSet(collection) { 607 if txContext.IsInitTransaction { 608 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 609 } 610 if err := errorIfCreatorHasNoReadPermission(namespaceID, collection, txContext); err != nil { 611 return nil, err 612 } 613 res, err = txContext.TXSimulator.GetPrivateData(namespaceID, collection, getState.Key) 614 } else { 615 res, err = txContext.TXSimulator.GetState(namespaceID, getState.Key) 616 } 617 if err != nil { 618 return nil, errors.WithStack(err) 619 } 620 if res == nil { 621 chaincodeLogger.Debugf("[%s] No state associated with key: %s. Sending %s with an empty payload", shorttxid(msg.Txid), getState.Key, pb.ChaincodeMessage_RESPONSE) 622 } 623 624 // Send response msg back to chaincode. GetState will not trigger event 625 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 626 } 627 628 func (h *Handler) HandleGetPrivateDataHash(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 629 getState := &pb.GetState{} 630 err := proto.Unmarshal(msg.Payload, getState) 631 if err != nil { 632 return nil, errors.Wrap(err, "unmarshal failed") 633 } 634 635 var res []byte 636 namespaceID := txContext.NamespaceID 637 collection := getState.Collection 638 chaincodeLogger.Debugf("[%s] getting private data hash for chaincode %s, key %s, channel %s", shorttxid(msg.Txid), namespaceID, getState.Key, txContext.ChannelID) 639 if txContext.IsInitTransaction { 640 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 641 } 642 res, err = txContext.TXSimulator.GetPrivateDataHash(namespaceID, collection, getState.Key) 643 if err != nil { 644 return nil, errors.WithStack(err) 645 } 646 if res == nil { 647 chaincodeLogger.Debugf("[%s] No state associated with key: %s. Sending %s with an empty payload", shorttxid(msg.Txid), getState.Key, pb.ChaincodeMessage_RESPONSE) 648 } 649 // Send response msg back to chaincode. GetState will not trigger event 650 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 651 } 652 653 // Handles query to ledger to get state metadata 654 func (h *Handler) HandleGetStateMetadata(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 655 err := h.checkMetadataCap(msg) 656 if err != nil { 657 return nil, err 658 } 659 660 getStateMetadata := &pb.GetStateMetadata{} 661 err = proto.Unmarshal(msg.Payload, getStateMetadata) 662 if err != nil { 663 return nil, errors.Wrap(err, "unmarshal failed") 664 } 665 666 namespaceID := txContext.NamespaceID 667 collection := getStateMetadata.Collection 668 chaincodeLogger.Debugf("[%s] getting state metadata for chaincode %s, key %s, channel %s", shorttxid(msg.Txid), namespaceID, getStateMetadata.Key, txContext.ChannelID) 669 670 var metadata map[string][]byte 671 if isCollectionSet(collection) { 672 if txContext.IsInitTransaction { 673 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 674 } 675 if err := errorIfCreatorHasNoReadPermission(namespaceID, collection, txContext); err != nil { 676 return nil, err 677 } 678 metadata, err = txContext.TXSimulator.GetPrivateDataMetadata(namespaceID, collection, getStateMetadata.Key) 679 } else { 680 metadata, err = txContext.TXSimulator.GetStateMetadata(namespaceID, getStateMetadata.Key) 681 } 682 if err != nil { 683 return nil, errors.WithStack(err) 684 } 685 var metadataResult pb.StateMetadataResult 686 for metakey := range metadata { 687 md := &pb.StateMetadata{Metakey: metakey, Value: metadata[metakey]} 688 metadataResult.Entries = append(metadataResult.Entries, md) 689 } 690 res, err := proto.Marshal(&metadataResult) 691 if err != nil { 692 return nil, errors.WithStack(err) 693 } 694 695 // Send response msg back to chaincode. GetState will not trigger event 696 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 697 } 698 699 // Handles query to ledger to rage query state 700 func (h *Handler) HandleGetStateByRange(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 701 getStateByRange := &pb.GetStateByRange{} 702 err := proto.Unmarshal(msg.Payload, getStateByRange) 703 if err != nil { 704 return nil, errors.Wrap(err, "unmarshal failed") 705 } 706 707 metadata, err := getQueryMetadataFromBytes(getStateByRange.Metadata) 708 if err != nil { 709 return nil, err 710 } 711 712 totalReturnLimit := h.calculateTotalReturnLimit(metadata) 713 714 iterID := h.UUIDGenerator.New() 715 716 var rangeIter commonledger.ResultsIterator 717 var paginationInfo map[string]interface{} 718 719 isPaginated := false 720 721 namespaceID := txContext.NamespaceID 722 collection := getStateByRange.Collection 723 if isCollectionSet(collection) { 724 if txContext.IsInitTransaction { 725 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 726 } 727 if err := errorIfCreatorHasNoReadPermission(namespaceID, collection, txContext); err != nil { 728 return nil, err 729 } 730 rangeIter, err = txContext.TXSimulator.GetPrivateDataRangeScanIterator(namespaceID, collection, 731 getStateByRange.StartKey, getStateByRange.EndKey) 732 } else if isMetadataSetForPagination(metadata) { 733 paginationInfo, err = createPaginationInfoFromMetadata(metadata, totalReturnLimit, pb.ChaincodeMessage_GET_STATE_BY_RANGE) 734 if err != nil { 735 return nil, err 736 } 737 isPaginated = true 738 739 startKey := getStateByRange.StartKey 740 741 if isMetadataSetForPagination(metadata) { 742 if metadata.Bookmark != "" { 743 startKey = metadata.Bookmark 744 } 745 } 746 rangeIter, err = txContext.TXSimulator.GetStateRangeScanIteratorWithMetadata(namespaceID, 747 startKey, getStateByRange.EndKey, paginationInfo) 748 } else { 749 rangeIter, err = txContext.TXSimulator.GetStateRangeScanIterator(namespaceID, getStateByRange.StartKey, getStateByRange.EndKey) 750 } 751 if err != nil { 752 return nil, errors.WithStack(err) 753 } 754 txContext.InitializeQueryContext(iterID, rangeIter) 755 756 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, rangeIter, iterID, isPaginated, totalReturnLimit) 757 if err != nil { 758 txContext.CleanupQueryContext(iterID) 759 return nil, errors.WithStack(err) 760 } 761 762 payloadBytes, err := proto.Marshal(payload) 763 if err != nil { 764 txContext.CleanupQueryContext(iterID) 765 return nil, errors.Wrap(err, "marshal failed") 766 } 767 768 chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) 769 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 770 } 771 772 // Handles query to ledger for query state next 773 func (h *Handler) HandleQueryStateNext(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 774 queryStateNext := &pb.QueryStateNext{} 775 err := proto.Unmarshal(msg.Payload, queryStateNext) 776 if err != nil { 777 return nil, errors.Wrap(err, "unmarshal failed") 778 } 779 780 queryIter := txContext.GetQueryIterator(queryStateNext.Id) 781 if queryIter == nil { 782 return nil, errors.New("query iterator not found") 783 } 784 785 totalReturnLimit := h.calculateTotalReturnLimit(nil) 786 787 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, queryIter, queryStateNext.Id, false, totalReturnLimit) 788 if err != nil { 789 txContext.CleanupQueryContext(queryStateNext.Id) 790 return nil, errors.WithStack(err) 791 } 792 793 payloadBytes, err := proto.Marshal(payload) 794 if err != nil { 795 txContext.CleanupQueryContext(queryStateNext.Id) 796 return nil, errors.Wrap(err, "marshal failed") 797 } 798 799 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 800 } 801 802 // Handles the closing of a state iterator 803 func (h *Handler) HandleQueryStateClose(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 804 queryStateClose := &pb.QueryStateClose{} 805 err := proto.Unmarshal(msg.Payload, queryStateClose) 806 if err != nil { 807 return nil, errors.Wrap(err, "unmarshal failed") 808 } 809 810 iter := txContext.GetQueryIterator(queryStateClose.Id) 811 if iter != nil { 812 txContext.CleanupQueryContext(queryStateClose.Id) 813 } 814 815 payload := &pb.QueryResponse{HasMore: false, Id: queryStateClose.Id} 816 payloadBytes, err := proto.Marshal(payload) 817 if err != nil { 818 return nil, errors.Wrap(err, "marshal failed") 819 } 820 821 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 822 } 823 824 // Handles query to ledger to execute query state 825 func (h *Handler) HandleGetQueryResult(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 826 iterID := h.UUIDGenerator.New() 827 828 getQueryResult := &pb.GetQueryResult{} 829 err := proto.Unmarshal(msg.Payload, getQueryResult) 830 if err != nil { 831 return nil, errors.Wrap(err, "unmarshal failed") 832 } 833 834 metadata, err := getQueryMetadataFromBytes(getQueryResult.Metadata) 835 if err != nil { 836 return nil, err 837 } 838 839 totalReturnLimit := h.calculateTotalReturnLimit(metadata) 840 isPaginated := false 841 842 var executeIter commonledger.ResultsIterator 843 var paginationInfo map[string]interface{} 844 845 namespaceID := txContext.NamespaceID 846 collection := getQueryResult.Collection 847 if isCollectionSet(collection) { 848 if txContext.IsInitTransaction { 849 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 850 } 851 if err := errorIfCreatorHasNoReadPermission(namespaceID, collection, txContext); err != nil { 852 return nil, err 853 } 854 executeIter, err = txContext.TXSimulator.ExecuteQueryOnPrivateData(namespaceID, collection, getQueryResult.Query) 855 } else if isMetadataSetForPagination(metadata) { 856 paginationInfo, err = createPaginationInfoFromMetadata(metadata, totalReturnLimit, pb.ChaincodeMessage_GET_QUERY_RESULT) 857 if err != nil { 858 return nil, err 859 } 860 isPaginated = true 861 executeIter, err = txContext.TXSimulator.ExecuteQueryWithMetadata(namespaceID, 862 getQueryResult.Query, paginationInfo) 863 864 } else { 865 executeIter, err = txContext.TXSimulator.ExecuteQuery(namespaceID, getQueryResult.Query) 866 } 867 if err != nil { 868 return nil, errors.WithStack(err) 869 } 870 871 txContext.InitializeQueryContext(iterID, executeIter) 872 873 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, executeIter, iterID, isPaginated, totalReturnLimit) 874 if err != nil { 875 txContext.CleanupQueryContext(iterID) 876 return nil, errors.WithStack(err) 877 } 878 879 payloadBytes, err := proto.Marshal(payload) 880 if err != nil { 881 txContext.CleanupQueryContext(iterID) 882 return nil, errors.Wrap(err, "marshal failed") 883 } 884 885 chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) 886 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 887 } 888 889 // Handles query to ledger history db 890 func (h *Handler) HandleGetHistoryForKey(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 891 if txContext.HistoryQueryExecutor == nil { 892 return nil, errors.New("history database is not enabled") 893 } 894 iterID := h.UUIDGenerator.New() 895 namespaceID := txContext.NamespaceID 896 897 getHistoryForKey := &pb.GetHistoryForKey{} 898 err := proto.Unmarshal(msg.Payload, getHistoryForKey) 899 if err != nil { 900 return nil, errors.Wrap(err, "unmarshal failed") 901 } 902 903 historyIter, err := txContext.HistoryQueryExecutor.GetHistoryForKey(namespaceID, getHistoryForKey.Key) 904 if err != nil { 905 return nil, errors.WithStack(err) 906 } 907 908 totalReturnLimit := h.calculateTotalReturnLimit(nil) 909 910 txContext.InitializeQueryContext(iterID, historyIter) 911 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, historyIter, iterID, false, totalReturnLimit) 912 if err != nil { 913 txContext.CleanupQueryContext(iterID) 914 return nil, errors.WithStack(err) 915 } 916 917 payloadBytes, err := proto.Marshal(payload) 918 if err != nil { 919 txContext.CleanupQueryContext(iterID) 920 return nil, errors.Wrap(err, "marshal failed") 921 } 922 923 chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) 924 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 925 } 926 927 func isCollectionSet(collection string) bool { 928 return collection != "" 929 } 930 931 func isMetadataSetForPagination(metadata *pb.QueryMetadata) bool { 932 if metadata == nil { 933 return false 934 } 935 936 if metadata.PageSize == 0 && metadata.Bookmark == "" { 937 return false 938 } 939 940 return true 941 } 942 943 func getQueryMetadataFromBytes(metadataBytes []byte) (*pb.QueryMetadata, error) { 944 if metadataBytes != nil { 945 metadata := &pb.QueryMetadata{} 946 err := proto.Unmarshal(metadataBytes, metadata) 947 if err != nil { 948 return nil, errors.Wrap(err, "unmarshal failed") 949 } 950 return metadata, nil 951 } 952 return nil, nil 953 } 954 955 func createPaginationInfoFromMetadata(metadata *pb.QueryMetadata, totalReturnLimit int32, queryType pb.ChaincodeMessage_Type) (map[string]interface{}, error) { 956 paginationInfoMap := make(map[string]interface{}) 957 958 switch queryType { 959 case pb.ChaincodeMessage_GET_QUERY_RESULT: 960 paginationInfoMap["bookmark"] = metadata.Bookmark 961 case pb.ChaincodeMessage_GET_STATE_BY_RANGE: 962 // this is a no-op for range query 963 default: 964 return nil, errors.New("query type must be either GetQueryResult or GetStateByRange") 965 } 966 967 paginationInfoMap["limit"] = totalReturnLimit 968 return paginationInfoMap, nil 969 } 970 971 func (h *Handler) calculateTotalReturnLimit(metadata *pb.QueryMetadata) int32 { 972 totalReturnLimit := int32(h.TotalQueryLimit) 973 if metadata != nil { 974 pageSize := int32(metadata.PageSize) 975 if pageSize > 0 && pageSize < totalReturnLimit { 976 totalReturnLimit = pageSize 977 } 978 } 979 return totalReturnLimit 980 } 981 982 func (h *Handler) getTxContextForInvoke(channelID string, txid string, payload []byte, format string, args ...interface{}) (*TransactionContext, error) { 983 // if we have a channelID, just get the txsim from isValidTxSim 984 if channelID != "" { 985 return h.isValidTxSim(channelID, txid, "could not get valid transaction") 986 } 987 988 chaincodeSpec := &pb.ChaincodeSpec{} 989 err := proto.Unmarshal(payload, chaincodeSpec) 990 if err != nil { 991 return nil, errors.Wrap(err, "unmarshal failed") 992 } 993 994 // Get the chaincodeID to invoke. The chaincodeID to be called may 995 // contain composite info like "chaincode-name:version/channel-name" 996 // We are not using version now but default to the latest 997 targetInstance := ParseName(chaincodeSpec.ChaincodeId.Name) 998 999 // If targetInstance is not an SCC, isValidTxSim should be called which will return an err. 1000 // We do not want to propagate calls to user CCs when the original call was to a SCC 1001 // without a channel context (ie, no ledger context). 1002 if !h.BuiltinSCCs.IsSysCC(targetInstance.ChaincodeName) { 1003 // normal path - UCC invocation with an empty ("") channel: isValidTxSim will return an error 1004 return h.isValidTxSim("", txid, "could not get valid transaction") 1005 } 1006 1007 // Calling SCC without a ChainID, then the assumption this is an external SCC called by the client (special case) and no UCC involved, 1008 // so no Transaction Simulator validation needed as there are no commits to the ledger, get the txContext directly if it is not nil 1009 txContext := h.TXContexts.Get(channelID, txid) 1010 if txContext == nil { 1011 return nil, errors.New("failed to get transaction context") 1012 } 1013 1014 return txContext, nil 1015 } 1016 1017 func (h *Handler) HandlePutState(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 1018 putState := &pb.PutState{} 1019 err := proto.Unmarshal(msg.Payload, putState) 1020 if err != nil { 1021 return nil, errors.Wrap(err, "unmarshal failed") 1022 } 1023 1024 namespaceID := txContext.NamespaceID 1025 collection := putState.Collection 1026 if isCollectionSet(collection) { 1027 if txContext.IsInitTransaction { 1028 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 1029 } 1030 if err := errorIfCreatorHasNoWritePermission(namespaceID, collection, txContext); err != nil { 1031 return nil, err 1032 } 1033 err = txContext.TXSimulator.SetPrivateData(namespaceID, collection, putState.Key, putState.Value) 1034 } else { 1035 err = txContext.TXSimulator.SetState(namespaceID, putState.Key, putState.Value) 1036 } 1037 if err != nil { 1038 return nil, errors.WithStack(err) 1039 } 1040 1041 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1042 } 1043 1044 func (h *Handler) HandlePutStateMetadata(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 1045 err := h.checkMetadataCap(msg) 1046 if err != nil { 1047 return nil, err 1048 } 1049 1050 putStateMetadata := &pb.PutStateMetadata{} 1051 err = proto.Unmarshal(msg.Payload, putStateMetadata) 1052 if err != nil { 1053 return nil, errors.Wrap(err, "unmarshal failed") 1054 } 1055 1056 metadata := make(map[string][]byte) 1057 metadata[putStateMetadata.Metadata.Metakey] = putStateMetadata.Metadata.Value 1058 1059 namespaceID := txContext.NamespaceID 1060 collection := putStateMetadata.Collection 1061 if isCollectionSet(collection) { 1062 if txContext.IsInitTransaction { 1063 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 1064 } 1065 if err := errorIfCreatorHasNoWritePermission(namespaceID, collection, txContext); err != nil { 1066 return nil, err 1067 } 1068 err = txContext.TXSimulator.SetPrivateDataMetadata(namespaceID, collection, putStateMetadata.Key, metadata) 1069 } else { 1070 err = txContext.TXSimulator.SetStateMetadata(namespaceID, putStateMetadata.Key, metadata) 1071 } 1072 if err != nil { 1073 return nil, errors.WithStack(err) 1074 } 1075 1076 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1077 } 1078 1079 func (h *Handler) HandleDelState(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 1080 delState := &pb.DelState{} 1081 err := proto.Unmarshal(msg.Payload, delState) 1082 if err != nil { 1083 return nil, errors.Wrap(err, "unmarshal failed") 1084 } 1085 1086 namespaceID := txContext.NamespaceID 1087 collection := delState.Collection 1088 if isCollectionSet(collection) { 1089 if txContext.IsInitTransaction { 1090 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 1091 } 1092 if err := errorIfCreatorHasNoWritePermission(namespaceID, collection, txContext); err != nil { 1093 return nil, err 1094 } 1095 err = txContext.TXSimulator.DeletePrivateData(namespaceID, collection, delState.Key) 1096 } else { 1097 err = txContext.TXSimulator.DeleteState(namespaceID, delState.Key) 1098 } 1099 if err != nil { 1100 return nil, errors.WithStack(err) 1101 } 1102 1103 // Send response msg back to chaincode. 1104 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1105 } 1106 1107 // Handles requests that modify ledger state 1108 func (h *Handler) HandleInvokeChaincode(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 1109 chaincodeLogger.Debugf("[%s] C-call-C", shorttxid(msg.Txid)) 1110 1111 chaincodeSpec := &pb.ChaincodeSpec{} 1112 err := proto.Unmarshal(msg.Payload, chaincodeSpec) 1113 if err != nil { 1114 return nil, errors.Wrap(err, "unmarshal failed") 1115 } 1116 1117 // Get the chaincodeID to invoke. The chaincodeID to be called may 1118 // contain composite info like "chaincode-name:version/channel-name". 1119 // We are not using version now but default to the latest. 1120 targetInstance := ParseName(chaincodeSpec.ChaincodeId.Name) 1121 chaincodeSpec.ChaincodeId.Name = targetInstance.ChaincodeName 1122 if targetInstance.ChannelID == "" { 1123 // use caller's channel as the called chaincode is in the same channel 1124 targetInstance.ChannelID = txContext.ChannelID 1125 } 1126 chaincodeLogger.Debugf("[%s] C-call-C %s on channel %s", shorttxid(msg.Txid), targetInstance.ChaincodeName, targetInstance.ChannelID) 1127 1128 err = h.checkACL(txContext.SignedProp, txContext.Proposal, targetInstance) 1129 if err != nil { 1130 chaincodeLogger.Errorf( 1131 "[%s] C-call-C %s on channel %s failed check ACL [%v]: [%s]", 1132 shorttxid(msg.Txid), 1133 targetInstance.ChaincodeName, 1134 targetInstance.ChannelID, 1135 txContext.SignedProp, 1136 err, 1137 ) 1138 return nil, errors.WithStack(err) 1139 } 1140 1141 // Set up a new context for the called chaincode if on a different channel 1142 // We grab the called channel's ledger simulator to hold the new state 1143 txParams := &ccprovider.TransactionParams{ 1144 TxID: msg.Txid, 1145 ChannelID: targetInstance.ChannelID, 1146 SignedProp: txContext.SignedProp, 1147 Proposal: txContext.Proposal, 1148 TXSimulator: txContext.TXSimulator, 1149 HistoryQueryExecutor: txContext.HistoryQueryExecutor, 1150 } 1151 1152 if targetInstance.ChannelID != txContext.ChannelID { 1153 lgr := h.LedgerGetter.GetLedger(targetInstance.ChannelID) 1154 if lgr == nil { 1155 return nil, errors.Errorf("failed to find ledger for channel: %s", targetInstance.ChannelID) 1156 } 1157 1158 sim, err := lgr.NewTxSimulator(msg.Txid) 1159 if err != nil { 1160 return nil, errors.WithStack(err) 1161 } 1162 defer sim.Done() 1163 1164 hqe, err := lgr.NewHistoryQueryExecutor() 1165 if err != nil { 1166 return nil, errors.WithStack(err) 1167 } 1168 1169 txParams.TXSimulator = sim 1170 txParams.HistoryQueryExecutor = hqe 1171 } 1172 1173 // Execute the chaincode... this CANNOT be an init at least for now 1174 responseMessage, err := h.Invoker.Invoke(txParams, targetInstance.ChaincodeName, chaincodeSpec.Input) 1175 if err != nil { 1176 return nil, errors.Wrap(err, "execute failed") 1177 } 1178 1179 // payload is marshalled and sent to the calling chaincode's shim which unmarshals and 1180 // sends it to chaincode 1181 res, err := proto.Marshal(responseMessage) 1182 if err != nil { 1183 return nil, errors.Wrap(err, "marshal failed") 1184 } 1185 1186 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1187 } 1188 1189 func (h *Handler) Execute(txParams *ccprovider.TransactionParams, namespace string, msg *pb.ChaincodeMessage, timeout time.Duration) (*pb.ChaincodeMessage, error) { 1190 chaincodeLogger.Debugf("Entry") 1191 defer chaincodeLogger.Debugf("Exit") 1192 1193 txParams.CollectionStore = h.getCollectionStore(msg.ChannelId) 1194 txParams.IsInitTransaction = (msg.Type == pb.ChaincodeMessage_INIT) 1195 txParams.NamespaceID = namespace 1196 1197 txctx, err := h.TXContexts.Create(txParams) 1198 if err != nil { 1199 return nil, err 1200 } 1201 defer h.TXContexts.Delete(msg.ChannelId, msg.Txid) 1202 1203 if err := h.setChaincodeProposal(txParams.SignedProp, txParams.Proposal, msg); err != nil { 1204 return nil, err 1205 } 1206 1207 h.serialSendAsync(msg) 1208 1209 var ccresp *pb.ChaincodeMessage 1210 select { 1211 case ccresp = <-txctx.ResponseNotifier: 1212 // response is sent to user or calling chaincode. ChaincodeMessage_ERROR 1213 // are typically treated as error 1214 case <-time.After(timeout): 1215 err = errors.New("timeout expired while executing transaction") 1216 h.Metrics.ExecuteTimeouts.With("chaincode", h.chaincodeID).Add(1) 1217 case <-h.streamDone(): 1218 err = errors.New("chaincode stream terminated") 1219 } 1220 1221 return ccresp, err 1222 } 1223 1224 func (h *Handler) setChaincodeProposal(signedProp *pb.SignedProposal, prop *pb.Proposal, msg *pb.ChaincodeMessage) error { 1225 if prop != nil && signedProp == nil { 1226 return errors.New("failed getting proposal context. Signed proposal is nil") 1227 } 1228 // TODO: This doesn't make a lot of sense. Feels like both are required or 1229 // neither should be set. Check with a knowledgeable expert. 1230 if prop != nil { 1231 msg.Proposal = signedProp 1232 } 1233 return nil 1234 } 1235 1236 func (h *Handler) getCollectionStore(channelID string) privdata.CollectionStore { 1237 return privdata.NewSimpleCollectionStore( 1238 h.LedgerGetter.GetLedger(channelID), 1239 h.DeployedCCInfoProvider, 1240 ) 1241 } 1242 1243 func (h *Handler) State() State { return h.state } 1244 func (h *Handler) Close() { h.TXContexts.Close() } 1245 1246 type State int 1247 1248 const ( 1249 Created State = iota 1250 Established 1251 Ready 1252 ) 1253 1254 func (s State) String() string { 1255 switch s { 1256 case Created: 1257 return "created" 1258 case Established: 1259 return "established" 1260 case Ready: 1261 return "ready" 1262 default: 1263 return "UNKNOWN" 1264 } 1265 }