github.com/hyperledger-labs/bdls@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  }