github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/fabric/common/channelconfig" 20 "github.com/osdi23p228/fabric/common/flogging" 21 commonledger "github.com/osdi23p228/fabric/common/ledger" 22 "github.com/osdi23p228/fabric/core/aclmgmt/resources" 23 "github.com/osdi23p228/fabric/core/common/ccprovider" 24 "github.com/osdi23p228/fabric/core/common/privdata" 25 "github.com/osdi23p228/fabric/core/common/sysccprovider" 26 "github.com/osdi23p228/fabric/core/container/ccintf" 27 "github.com/osdi23p228/fabric/core/ledger" 28 "github.com/osdi23p228/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(channelID, txID string) *TransactionContext 63 Delete(channelID, 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 iterID := h.UUIDGenerator.New() 714 var rangeIter commonledger.ResultsIterator 715 isPaginated := false 716 namespaceID := txContext.NamespaceID 717 collection := getStateByRange.Collection 718 if isCollectionSet(collection) { 719 if txContext.IsInitTransaction { 720 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 721 } 722 if err := errorIfCreatorHasNoReadPermission(namespaceID, collection, txContext); err != nil { 723 return nil, err 724 } 725 rangeIter, err = txContext.TXSimulator.GetPrivateDataRangeScanIterator(namespaceID, collection, 726 getStateByRange.StartKey, getStateByRange.EndKey) 727 } else if isMetadataSetForPagination(metadata) { 728 isPaginated = true 729 startKey := getStateByRange.StartKey 730 if isMetadataSetForPagination(metadata) { 731 if metadata.Bookmark != "" { 732 startKey = metadata.Bookmark 733 } 734 } 735 rangeIter, err = txContext.TXSimulator.GetStateRangeScanIteratorWithPagination(namespaceID, 736 startKey, getStateByRange.EndKey, metadata.PageSize) 737 } else { 738 rangeIter, err = txContext.TXSimulator.GetStateRangeScanIterator(namespaceID, getStateByRange.StartKey, getStateByRange.EndKey) 739 } 740 if err != nil { 741 return nil, errors.WithStack(err) 742 } 743 txContext.InitializeQueryContext(iterID, rangeIter) 744 745 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, rangeIter, iterID, isPaginated, totalReturnLimit) 746 if err != nil { 747 txContext.CleanupQueryContext(iterID) 748 return nil, errors.WithStack(err) 749 } 750 751 payloadBytes, err := proto.Marshal(payload) 752 if err != nil { 753 txContext.CleanupQueryContext(iterID) 754 return nil, errors.Wrap(err, "marshal failed") 755 } 756 757 chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) 758 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 759 } 760 761 // Handles query to ledger for query state next 762 func (h *Handler) HandleQueryStateNext(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 763 queryStateNext := &pb.QueryStateNext{} 764 err := proto.Unmarshal(msg.Payload, queryStateNext) 765 if err != nil { 766 return nil, errors.Wrap(err, "unmarshal failed") 767 } 768 769 queryIter := txContext.GetQueryIterator(queryStateNext.Id) 770 if queryIter == nil { 771 return nil, errors.New("query iterator not found") 772 } 773 774 totalReturnLimit := h.calculateTotalReturnLimit(nil) 775 776 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, queryIter, queryStateNext.Id, false, totalReturnLimit) 777 if err != nil { 778 txContext.CleanupQueryContext(queryStateNext.Id) 779 return nil, errors.WithStack(err) 780 } 781 782 payloadBytes, err := proto.Marshal(payload) 783 if err != nil { 784 txContext.CleanupQueryContext(queryStateNext.Id) 785 return nil, errors.Wrap(err, "marshal failed") 786 } 787 788 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 789 } 790 791 // Handles the closing of a state iterator 792 func (h *Handler) HandleQueryStateClose(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 793 queryStateClose := &pb.QueryStateClose{} 794 err := proto.Unmarshal(msg.Payload, queryStateClose) 795 if err != nil { 796 return nil, errors.Wrap(err, "unmarshal failed") 797 } 798 799 iter := txContext.GetQueryIterator(queryStateClose.Id) 800 if iter != nil { 801 txContext.CleanupQueryContext(queryStateClose.Id) 802 } 803 804 payload := &pb.QueryResponse{HasMore: false, Id: queryStateClose.Id} 805 payloadBytes, err := proto.Marshal(payload) 806 if err != nil { 807 return nil, errors.Wrap(err, "marshal failed") 808 } 809 810 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 811 } 812 813 // Handles query to ledger to execute query state 814 func (h *Handler) HandleGetQueryResult(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 815 iterID := h.UUIDGenerator.New() 816 817 getQueryResult := &pb.GetQueryResult{} 818 err := proto.Unmarshal(msg.Payload, getQueryResult) 819 if err != nil { 820 return nil, errors.Wrap(err, "unmarshal failed") 821 } 822 823 metadata, err := getQueryMetadataFromBytes(getQueryResult.Metadata) 824 if err != nil { 825 return nil, err 826 } 827 828 totalReturnLimit := h.calculateTotalReturnLimit(metadata) 829 isPaginated := false 830 var executeIter commonledger.ResultsIterator 831 namespaceID := txContext.NamespaceID 832 collection := getQueryResult.Collection 833 if isCollectionSet(collection) { 834 if txContext.IsInitTransaction { 835 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 836 } 837 if err := errorIfCreatorHasNoReadPermission(namespaceID, collection, txContext); err != nil { 838 return nil, err 839 } 840 executeIter, err = txContext.TXSimulator.ExecuteQueryOnPrivateData(namespaceID, collection, getQueryResult.Query) 841 } else if isMetadataSetForPagination(metadata) { 842 isPaginated = true 843 executeIter, err = txContext.TXSimulator.ExecuteQueryWithPagination(namespaceID, 844 getQueryResult.Query, metadata.Bookmark, metadata.PageSize) 845 846 } else { 847 executeIter, err = txContext.TXSimulator.ExecuteQuery(namespaceID, getQueryResult.Query) 848 } 849 if err != nil { 850 return nil, errors.WithStack(err) 851 } 852 853 txContext.InitializeQueryContext(iterID, executeIter) 854 855 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, executeIter, iterID, isPaginated, totalReturnLimit) 856 if err != nil { 857 txContext.CleanupQueryContext(iterID) 858 return nil, errors.WithStack(err) 859 } 860 861 payloadBytes, err := proto.Marshal(payload) 862 if err != nil { 863 txContext.CleanupQueryContext(iterID) 864 return nil, errors.Wrap(err, "marshal failed") 865 } 866 867 chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) 868 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 869 } 870 871 // Handles query to ledger history db 872 func (h *Handler) HandleGetHistoryForKey(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 873 if txContext.HistoryQueryExecutor == nil { 874 return nil, errors.New("history database is not enabled") 875 } 876 iterID := h.UUIDGenerator.New() 877 namespaceID := txContext.NamespaceID 878 879 getHistoryForKey := &pb.GetHistoryForKey{} 880 err := proto.Unmarshal(msg.Payload, getHistoryForKey) 881 if err != nil { 882 return nil, errors.Wrap(err, "unmarshal failed") 883 } 884 885 historyIter, err := txContext.HistoryQueryExecutor.GetHistoryForKey(namespaceID, getHistoryForKey.Key) 886 if err != nil { 887 return nil, errors.WithStack(err) 888 } 889 890 totalReturnLimit := h.calculateTotalReturnLimit(nil) 891 892 txContext.InitializeQueryContext(iterID, historyIter) 893 payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, historyIter, iterID, false, totalReturnLimit) 894 if err != nil { 895 txContext.CleanupQueryContext(iterID) 896 return nil, errors.WithStack(err) 897 } 898 899 payloadBytes, err := proto.Marshal(payload) 900 if err != nil { 901 txContext.CleanupQueryContext(iterID) 902 return nil, errors.Wrap(err, "marshal failed") 903 } 904 905 chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) 906 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 907 } 908 909 func isCollectionSet(collection string) bool { 910 return collection != "" 911 } 912 913 func isMetadataSetForPagination(metadata *pb.QueryMetadata) bool { 914 if metadata == nil { 915 return false 916 } 917 918 if metadata.PageSize == 0 && metadata.Bookmark == "" { 919 return false 920 } 921 922 return true 923 } 924 925 func getQueryMetadataFromBytes(metadataBytes []byte) (*pb.QueryMetadata, error) { 926 if metadataBytes != nil { 927 metadata := &pb.QueryMetadata{} 928 err := proto.Unmarshal(metadataBytes, metadata) 929 if err != nil { 930 return nil, errors.Wrap(err, "unmarshal failed") 931 } 932 return metadata, nil 933 } 934 return nil, nil 935 } 936 937 func (h *Handler) calculateTotalReturnLimit(metadata *pb.QueryMetadata) int32 { 938 totalReturnLimit := int32(h.TotalQueryLimit) 939 if metadata != nil { 940 pageSize := int32(metadata.PageSize) 941 if pageSize > 0 && pageSize < totalReturnLimit { 942 totalReturnLimit = pageSize 943 } 944 } 945 return totalReturnLimit 946 } 947 948 func (h *Handler) getTxContextForInvoke(channelID string, txid string, payload []byte, format string, args ...interface{}) (*TransactionContext, error) { 949 // if we have a channelID, just get the txsim from isValidTxSim 950 if channelID != "" { 951 return h.isValidTxSim(channelID, txid, "could not get valid transaction") 952 } 953 954 chaincodeSpec := &pb.ChaincodeSpec{} 955 err := proto.Unmarshal(payload, chaincodeSpec) 956 if err != nil { 957 return nil, errors.Wrap(err, "unmarshal failed") 958 } 959 960 // Get the chaincodeID to invoke. The chaincodeID to be called may 961 // contain composite info like "chaincode-name:version/channel-name" 962 // We are not using version now but default to the latest 963 targetInstance := ParseName(chaincodeSpec.ChaincodeId.Name) 964 965 // If targetInstance is not an SCC, isValidTxSim should be called which will return an err. 966 // We do not want to propagate calls to user CCs when the original call was to a SCC 967 // without a channel context (ie, no ledger context). 968 if !h.BuiltinSCCs.IsSysCC(targetInstance.ChaincodeName) { 969 // normal path - UCC invocation with an empty ("") channel: isValidTxSim will return an error 970 return h.isValidTxSim("", txid, "could not get valid transaction") 971 } 972 973 // Calling SCC without a ChannelID, then the assumption this is an external SCC called by the client (special case) and no UCC involved, 974 // so no Transaction Simulator validation needed as there are no commits to the ledger, get the txContext directly if it is not nil 975 txContext := h.TXContexts.Get(channelID, txid) 976 if txContext == nil { 977 return nil, errors.New("failed to get transaction context") 978 } 979 980 return txContext, nil 981 } 982 983 func (h *Handler) HandlePutState(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 984 putState := &pb.PutState{} 985 err := proto.Unmarshal(msg.Payload, putState) 986 if err != nil { 987 return nil, errors.Wrap(err, "unmarshal failed") 988 } 989 990 namespaceID := txContext.NamespaceID 991 collection := putState.Collection 992 if isCollectionSet(collection) { 993 if txContext.IsInitTransaction { 994 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 995 } 996 if err := errorIfCreatorHasNoWritePermission(namespaceID, collection, txContext); err != nil { 997 return nil, err 998 } 999 err = txContext.TXSimulator.SetPrivateData(namespaceID, collection, putState.Key, putState.Value) 1000 } else { 1001 err = txContext.TXSimulator.SetState(namespaceID, putState.Key, putState.Value) 1002 } 1003 if err != nil { 1004 return nil, errors.WithStack(err) 1005 } 1006 1007 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1008 } 1009 1010 func (h *Handler) HandlePutStateMetadata(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 1011 err := h.checkMetadataCap(msg) 1012 if err != nil { 1013 return nil, err 1014 } 1015 1016 putStateMetadata := &pb.PutStateMetadata{} 1017 err = proto.Unmarshal(msg.Payload, putStateMetadata) 1018 if err != nil { 1019 return nil, errors.Wrap(err, "unmarshal failed") 1020 } 1021 1022 metadata := make(map[string][]byte) 1023 metadata[putStateMetadata.Metadata.Metakey] = putStateMetadata.Metadata.Value 1024 1025 namespaceID := txContext.NamespaceID 1026 collection := putStateMetadata.Collection 1027 if isCollectionSet(collection) { 1028 if txContext.IsInitTransaction { 1029 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 1030 } 1031 if err := errorIfCreatorHasNoWritePermission(namespaceID, collection, txContext); err != nil { 1032 return nil, err 1033 } 1034 err = txContext.TXSimulator.SetPrivateDataMetadata(namespaceID, collection, putStateMetadata.Key, metadata) 1035 } else { 1036 err = txContext.TXSimulator.SetStateMetadata(namespaceID, putStateMetadata.Key, metadata) 1037 } 1038 if err != nil { 1039 return nil, errors.WithStack(err) 1040 } 1041 1042 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1043 } 1044 1045 func (h *Handler) HandleDelState(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 1046 delState := &pb.DelState{} 1047 err := proto.Unmarshal(msg.Payload, delState) 1048 if err != nil { 1049 return nil, errors.Wrap(err, "unmarshal failed") 1050 } 1051 1052 namespaceID := txContext.NamespaceID 1053 collection := delState.Collection 1054 if isCollectionSet(collection) { 1055 if txContext.IsInitTransaction { 1056 return nil, errors.New("private data APIs are not allowed in chaincode Init()") 1057 } 1058 if err := errorIfCreatorHasNoWritePermission(namespaceID, collection, txContext); err != nil { 1059 return nil, err 1060 } 1061 err = txContext.TXSimulator.DeletePrivateData(namespaceID, collection, delState.Key) 1062 } else { 1063 err = txContext.TXSimulator.DeleteState(namespaceID, delState.Key) 1064 } 1065 if err != nil { 1066 return nil, errors.WithStack(err) 1067 } 1068 1069 // Send response msg back to chaincode. 1070 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1071 } 1072 1073 // Handles requests that modify ledger state 1074 func (h *Handler) HandleInvokeChaincode(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) { 1075 chaincodeLogger.Debugf("[%s] C-call-C", shorttxid(msg.Txid)) 1076 1077 chaincodeSpec := &pb.ChaincodeSpec{} 1078 err := proto.Unmarshal(msg.Payload, chaincodeSpec) 1079 if err != nil { 1080 return nil, errors.Wrap(err, "unmarshal failed") 1081 } 1082 1083 // Get the chaincodeID to invoke. The chaincodeID to be called may 1084 // contain composite info like "chaincode-name:version/channel-name". 1085 // We are not using version now but default to the latest. 1086 targetInstance := ParseName(chaincodeSpec.ChaincodeId.Name) 1087 chaincodeSpec.ChaincodeId.Name = targetInstance.ChaincodeName 1088 if targetInstance.ChannelID == "" { 1089 // use caller's channel as the called chaincode is in the same channel 1090 targetInstance.ChannelID = txContext.ChannelID 1091 } 1092 chaincodeLogger.Debugf("[%s] C-call-C %s on channel %s", shorttxid(msg.Txid), targetInstance.ChaincodeName, targetInstance.ChannelID) 1093 1094 err = h.checkACL(txContext.SignedProp, txContext.Proposal, targetInstance) 1095 if err != nil { 1096 chaincodeLogger.Errorf( 1097 "[%s] C-call-C %s on channel %s failed check ACL [%v]: [%s]", 1098 shorttxid(msg.Txid), 1099 targetInstance.ChaincodeName, 1100 targetInstance.ChannelID, 1101 txContext.SignedProp, 1102 err, 1103 ) 1104 return nil, errors.WithStack(err) 1105 } 1106 1107 // Set up a new context for the called chaincode if on a different channel 1108 // We grab the called channel's ledger simulator to hold the new state 1109 txParams := &ccprovider.TransactionParams{ 1110 TxID: msg.Txid, 1111 ChannelID: targetInstance.ChannelID, 1112 SignedProp: txContext.SignedProp, 1113 Proposal: txContext.Proposal, 1114 TXSimulator: txContext.TXSimulator, 1115 HistoryQueryExecutor: txContext.HistoryQueryExecutor, 1116 } 1117 1118 if targetInstance.ChannelID != txContext.ChannelID { 1119 lgr := h.LedgerGetter.GetLedger(targetInstance.ChannelID) 1120 if lgr == nil { 1121 return nil, errors.Errorf("failed to find ledger for channel: %s", targetInstance.ChannelID) 1122 } 1123 1124 sim, err := lgr.NewTxSimulator(msg.Txid) 1125 if err != nil { 1126 return nil, errors.WithStack(err) 1127 } 1128 defer sim.Done() 1129 1130 hqe, err := lgr.NewHistoryQueryExecutor() 1131 if err != nil { 1132 return nil, errors.WithStack(err) 1133 } 1134 1135 txParams.TXSimulator = sim 1136 txParams.HistoryQueryExecutor = hqe 1137 } 1138 1139 // Execute the chaincode... this CANNOT be an init at least for now 1140 responseMessage, err := h.Invoker.Invoke(txParams, targetInstance.ChaincodeName, chaincodeSpec.Input) 1141 if err != nil { 1142 return nil, errors.Wrap(err, "execute failed") 1143 } 1144 1145 // payload is marshalled and sent to the calling chaincode's shim which unmarshals and 1146 // sends it to chaincode 1147 res, err := proto.Marshal(responseMessage) 1148 if err != nil { 1149 return nil, errors.Wrap(err, "marshal failed") 1150 } 1151 1152 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil 1153 } 1154 1155 func (h *Handler) Execute(txParams *ccprovider.TransactionParams, namespace string, msg *pb.ChaincodeMessage, timeout time.Duration) (*pb.ChaincodeMessage, error) { 1156 chaincodeLogger.Debugf("Entry") 1157 defer chaincodeLogger.Debugf("Exit") 1158 1159 txParams.CollectionStore = h.getCollectionStore(msg.ChannelId) 1160 txParams.IsInitTransaction = (msg.Type == pb.ChaincodeMessage_INIT) 1161 txParams.NamespaceID = namespace 1162 1163 txctx, err := h.TXContexts.Create(txParams) 1164 if err != nil { 1165 return nil, err 1166 } 1167 defer h.TXContexts.Delete(msg.ChannelId, msg.Txid) 1168 1169 if err := h.setChaincodeProposal(txParams.SignedProp, txParams.Proposal, msg); err != nil { 1170 return nil, err 1171 } 1172 1173 h.serialSendAsync(msg) 1174 1175 var ccresp *pb.ChaincodeMessage 1176 select { 1177 case ccresp = <-txctx.ResponseNotifier: 1178 // response is sent to user or calling chaincode. ChaincodeMessage_ERROR 1179 // are typically treated as error 1180 case <-time.After(timeout): 1181 err = errors.New("timeout expired while executing transaction") 1182 h.Metrics.ExecuteTimeouts.With("chaincode", h.chaincodeID).Add(1) 1183 case <-h.streamDone(): 1184 err = errors.New("chaincode stream terminated") 1185 } 1186 1187 return ccresp, err 1188 } 1189 1190 func (h *Handler) setChaincodeProposal(signedProp *pb.SignedProposal, prop *pb.Proposal, msg *pb.ChaincodeMessage) error { 1191 if prop != nil && signedProp == nil { 1192 return errors.New("failed getting proposal context. Signed proposal is nil") 1193 } 1194 // TODO: This doesn't make a lot of sense. Feels like both are required or 1195 // neither should be set. Check with a knowledgeable expert. 1196 if prop != nil { 1197 msg.Proposal = signedProp 1198 } 1199 return nil 1200 } 1201 1202 func (h *Handler) getCollectionStore(channelID string) privdata.CollectionStore { 1203 return privdata.NewSimpleCollectionStore( 1204 h.LedgerGetter.GetLedger(channelID), 1205 h.DeployedCCInfoProvider, 1206 ) 1207 } 1208 1209 func (h *Handler) State() State { return h.state } 1210 func (h *Handler) Close() { h.TXContexts.Close() } 1211 1212 type State int 1213 1214 const ( 1215 Created State = iota 1216 Established 1217 Ready 1218 ) 1219 1220 func (s State) String() string { 1221 switch s { 1222 case Created: 1223 return "created" 1224 case Established: 1225 return "established" 1226 case Ready: 1227 return "ready" 1228 default: 1229 return "UNKNOWN" 1230 } 1231 }