github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/core/chaincode/handler.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package chaincode
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"io"
    23  	"sync"
    24  	"time"
    25  
    26  	"github.com/golang/protobuf/proto"
    27  	"github.com/hyperledger/fabric/common/flogging"
    28  	commonledger "github.com/hyperledger/fabric/common/ledger"
    29  	"github.com/hyperledger/fabric/common/policies"
    30  	"github.com/hyperledger/fabric/common/util"
    31  	"github.com/hyperledger/fabric/core/common/ccprovider"
    32  	"github.com/hyperledger/fabric/core/common/sysccprovider"
    33  	"github.com/hyperledger/fabric/core/container/ccintf"
    34  	"github.com/hyperledger/fabric/core/ledger"
    35  	"github.com/hyperledger/fabric/core/peer"
    36  	"github.com/hyperledger/fabric/core/policy"
    37  	"github.com/hyperledger/fabric/msp/mgmt"
    38  	pb "github.com/hyperledger/fabric/protos/peer"
    39  	"github.com/looplab/fsm"
    40  	logging "github.com/op/go-logging"
    41  	"golang.org/x/net/context"
    42  )
    43  
    44  const (
    45  	createdstate     = "created"     //start state
    46  	establishedstate = "established" //in: CREATED, rcv:  REGISTER, send: REGISTERED, INIT
    47  	readystate       = "ready"       //in:ESTABLISHED,TRANSACTION, rcv:COMPLETED
    48  	endstate         = "end"         //in:INIT,ESTABLISHED, rcv: error, terminate container
    49  
    50  )
    51  
    52  var chaincodeLogger = flogging.MustGetLogger("chaincode")
    53  
    54  // MessageHandler interface for handling chaincode messages (common between Peer chaincode support and chaincode)
    55  type MessageHandler interface {
    56  	HandleMessage(msg *pb.ChaincodeMessage) error
    57  	SendMessage(msg *pb.ChaincodeMessage) error
    58  }
    59  
    60  type transactionContext struct {
    61  	chainID          string
    62  	signedProp       *pb.SignedProposal
    63  	proposal         *pb.Proposal
    64  	responseNotifier chan *pb.ChaincodeMessage
    65  
    66  	// tracks open iterators used for range queries
    67  	queryIteratorMap map[string]commonledger.ResultsIterator
    68  
    69  	txsimulator          ledger.TxSimulator
    70  	historyQueryExecutor ledger.HistoryQueryExecutor
    71  }
    72  
    73  type nextStateInfo struct {
    74  	msg      *pb.ChaincodeMessage
    75  	sendToCC bool
    76  
    77  	//the only time we need to send synchronously is
    78  	//when launching the chaincode to take it to ready
    79  	//state (look for the panic when sending serial)
    80  	sendSync bool
    81  }
    82  
    83  // Handler responsible for management of Peer's side of chaincode stream
    84  type Handler struct {
    85  	sync.RWMutex
    86  	//peer to shim grpc serializer. User only in serialSend
    87  	serialLock  sync.Mutex
    88  	ChatStream  ccintf.ChaincodeStream
    89  	FSM         *fsm.FSM
    90  	ChaincodeID *pb.ChaincodeID
    91  	ccInstance  *sysccprovider.ChaincodeInstance
    92  
    93  	chaincodeSupport *ChaincodeSupport
    94  	registered       bool
    95  	readyNotify      chan bool
    96  	// Map of tx txid to either invoke tx. Each tx will be
    97  	// added prior to execute and remove when done execute
    98  	txCtxs map[string]*transactionContext
    99  
   100  	txidMap map[string]bool
   101  
   102  	// used to do Send after making sure the state transition is complete
   103  	nextState chan *nextStateInfo
   104  
   105  	policyChecker policy.PolicyChecker
   106  }
   107  
   108  func shorttxid(txid string) string {
   109  	if len(txid) < 8 {
   110  		return txid
   111  	}
   112  	return txid[0:8]
   113  }
   114  
   115  //gets chaincode instance from the canonical name of the chaincode.
   116  //Called exactly once per chaincode when registering chaincode.
   117  //This is needed for the "one-instance-per-chain" model when
   118  //starting up the chaincode for each chain. It will still
   119  //work for the "one-instance-for-all-chains" as the version
   120  //and suffix will just be absent (also note that LSCC reserves
   121  //"/:[]${}" as special chars mainly for such namespace uses)
   122  func (handler *Handler) decomposeRegisteredName(cid *pb.ChaincodeID) {
   123  	handler.ccInstance = getChaincodeInstance(cid.Name)
   124  }
   125  
   126  func getChaincodeInstance(ccName string) *sysccprovider.ChaincodeInstance {
   127  	b := []byte(ccName)
   128  	ci := &sysccprovider.ChaincodeInstance{}
   129  
   130  	//compute suffix (ie, chain name)
   131  	i := bytes.IndexByte(b, '/')
   132  	if i >= 0 {
   133  		if i < len(b)-1 {
   134  			ci.ChainID = string(b[i+1:])
   135  		}
   136  		b = b[:i]
   137  	}
   138  
   139  	//compute version
   140  	i = bytes.IndexByte(b, ':')
   141  	if i >= 0 {
   142  		if i < len(b)-1 {
   143  			ci.ChaincodeVersion = string(b[i+1:])
   144  		}
   145  		b = b[:i]
   146  	}
   147  	// remaining is the chaincode name
   148  	ci.ChaincodeName = string(b)
   149  
   150  	return ci
   151  }
   152  
   153  func (handler *Handler) getCCRootName() string {
   154  	return handler.ccInstance.ChaincodeName
   155  }
   156  
   157  //serialSend serializes msgs so gRPC will be happy
   158  func (handler *Handler) serialSend(msg *pb.ChaincodeMessage) error {
   159  	handler.serialLock.Lock()
   160  	defer handler.serialLock.Unlock()
   161  
   162  	var err error
   163  	if err = handler.ChatStream.Send(msg); err != nil {
   164  		err = fmt.Errorf("[%s]Error sending %s: %s", shorttxid(msg.Txid), msg.Type.String(), err)
   165  		chaincodeLogger.Errorf("%s", err)
   166  	}
   167  	return err
   168  }
   169  
   170  //serialSendAsync serves the same purpose as serialSend (serializ msgs so gRPC will
   171  //be happy). In addition, it is also asynchronous so send-remoterecv--localrecv loop
   172  //can be nonblocking. Only errors need to be handled and these are handled by
   173  //communication on supplied error channel. A typical use will be a non-blocking or
   174  //nil channel
   175  func (handler *Handler) serialSendAsync(msg *pb.ChaincodeMessage, errc chan error) {
   176  	go func() {
   177  		err := handler.serialSend(msg)
   178  		if errc != nil {
   179  			errc <- err
   180  		}
   181  	}()
   182  }
   183  
   184  func (handler *Handler) createTxContext(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (*transactionContext, error) {
   185  	if handler.txCtxs == nil {
   186  		return nil, fmt.Errorf("cannot create notifier for txid:%s", txid)
   187  	}
   188  	handler.Lock()
   189  	defer handler.Unlock()
   190  	if handler.txCtxs[txid] != nil {
   191  		return nil, fmt.Errorf("txid:%s exists", txid)
   192  	}
   193  	txctx := &transactionContext{chainID: chainID, signedProp: signedProp,
   194  		proposal: prop, responseNotifier: make(chan *pb.ChaincodeMessage, 1),
   195  		queryIteratorMap: make(map[string]commonledger.ResultsIterator)}
   196  	handler.txCtxs[txid] = txctx
   197  	txctx.txsimulator = getTxSimulator(ctxt)
   198  	txctx.historyQueryExecutor = getHistoryQueryExecutor(ctxt)
   199  
   200  	return txctx, nil
   201  }
   202  
   203  func (handler *Handler) getTxContext(txid string) *transactionContext {
   204  	handler.Lock()
   205  	defer handler.Unlock()
   206  	return handler.txCtxs[txid]
   207  }
   208  
   209  func (handler *Handler) deleteTxContext(txid string) {
   210  	handler.Lock()
   211  	defer handler.Unlock()
   212  	if handler.txCtxs != nil {
   213  		delete(handler.txCtxs, txid)
   214  	}
   215  }
   216  
   217  func (handler *Handler) putQueryIterator(txContext *transactionContext, txid string,
   218  	queryIterator commonledger.ResultsIterator) {
   219  	handler.Lock()
   220  	defer handler.Unlock()
   221  	txContext.queryIteratorMap[txid] = queryIterator
   222  }
   223  
   224  func (handler *Handler) getQueryIterator(txContext *transactionContext, txid string) commonledger.ResultsIterator {
   225  	handler.Lock()
   226  	defer handler.Unlock()
   227  	return txContext.queryIteratorMap[txid]
   228  }
   229  
   230  func (handler *Handler) deleteQueryIterator(txContext *transactionContext, txid string) {
   231  	handler.Lock()
   232  	defer handler.Unlock()
   233  	delete(txContext.queryIteratorMap, txid)
   234  }
   235  
   236  // Check if the transactor is allow to call this chaincode on this channel
   237  func (handler *Handler) checkACL(signedProp *pb.SignedProposal, proposal *pb.Proposal, ccIns *sysccprovider.ChaincodeInstance) error {
   238  	// ensure that we don't invoke a system chaincode
   239  	// that is not invokable through a cc2cc invocation
   240  	if sysccprovider.GetSystemChaincodeProvider().IsSysCCAndNotInvokableCC2CC(ccIns.ChaincodeName) {
   241  		return fmt.Errorf("System chaincode %s cannot be invoked with a cc2cc invocation", ccIns.ChaincodeName)
   242  	}
   243  
   244  	// if we are here, all we know is that the invoked chaincode is either
   245  	// - a system chaincode that *is* invokable through a cc2cc
   246  	//   (but we may still have to determine whether the invoker
   247  	//   can perform this invocation)
   248  	// - an application chaincode (and we still need to determine
   249  	//   whether the invoker can invoke it)
   250  
   251  	if sysccprovider.GetSystemChaincodeProvider().IsSysCC(ccIns.ChaincodeName) {
   252  		// Allow this call
   253  		return nil
   254  	}
   255  
   256  	// A Nil signedProp will be rejected for non-system chaincodes
   257  	if signedProp == nil {
   258  		return fmt.Errorf("Signed Proposal must not be nil from caller [%s]", ccIns.String())
   259  	}
   260  
   261  	return handler.policyChecker.CheckPolicy(ccIns.ChainID, policies.ChannelApplicationWriters, signedProp)
   262  }
   263  
   264  func (handler *Handler) deregister() error {
   265  	if handler.registered {
   266  		handler.chaincodeSupport.deregisterHandler(handler)
   267  	}
   268  	return nil
   269  }
   270  
   271  func (handler *Handler) triggerNextState(msg *pb.ChaincodeMessage, send bool) {
   272  	//this will send Async
   273  	handler.nextState <- &nextStateInfo{msg: msg, sendToCC: send, sendSync: false}
   274  }
   275  
   276  func (handler *Handler) triggerNextStateSync(msg *pb.ChaincodeMessage) {
   277  	//this will send sync
   278  	handler.nextState <- &nextStateInfo{msg: msg, sendToCC: true, sendSync: true}
   279  }
   280  
   281  func (handler *Handler) waitForKeepaliveTimer() <-chan time.Time {
   282  	if handler.chaincodeSupport.keepalive > 0 {
   283  		c := time.After(handler.chaincodeSupport.keepalive)
   284  		return c
   285  	}
   286  	//no one will signal this channel, listner blocks forever
   287  	c := make(chan time.Time, 1)
   288  	return c
   289  }
   290  
   291  func (handler *Handler) processStream() error {
   292  	defer handler.deregister()
   293  	msgAvail := make(chan *pb.ChaincodeMessage)
   294  	var nsInfo *nextStateInfo
   295  	var in *pb.ChaincodeMessage
   296  	var err error
   297  
   298  	//recv is used to spin Recv routine after previous received msg
   299  	//has been processed
   300  	recv := true
   301  
   302  	//catch send errors and bail now that sends aren't synchronous
   303  	errc := make(chan error, 1)
   304  	for {
   305  		in = nil
   306  		err = nil
   307  		nsInfo = nil
   308  		if recv {
   309  			recv = false
   310  			go func() {
   311  				var in2 *pb.ChaincodeMessage
   312  				in2, err = handler.ChatStream.Recv()
   313  				msgAvail <- in2
   314  			}()
   315  		}
   316  		select {
   317  		case sendErr := <-errc:
   318  			if sendErr != nil {
   319  				return sendErr
   320  			}
   321  			//send was successful, just continue
   322  			continue
   323  		case in = <-msgAvail:
   324  			// Defer the deregistering of the this handler.
   325  			if err == io.EOF {
   326  				chaincodeLogger.Debugf("Received EOF, ending chaincode support stream, %s", err)
   327  				return err
   328  			} else if err != nil {
   329  				chaincodeLogger.Errorf("Error handling chaincode support stream: %s", err)
   330  				return err
   331  			} else if in == nil {
   332  				err = fmt.Errorf("Received nil message, ending chaincode support stream")
   333  				chaincodeLogger.Debug("Received nil message, ending chaincode support stream")
   334  				return err
   335  			}
   336  			chaincodeLogger.Debugf("[%s]Received message %s from shim", shorttxid(in.Txid), in.Type.String())
   337  			if in.Type.String() == pb.ChaincodeMessage_ERROR.String() {
   338  				chaincodeLogger.Errorf("Got error: %s", string(in.Payload))
   339  			}
   340  
   341  			// we can spin off another Recv again
   342  			recv = true
   343  
   344  			if in.Type == pb.ChaincodeMessage_KEEPALIVE {
   345  				chaincodeLogger.Debug("Received KEEPALIVE Response")
   346  				// Received a keep alive message, we don't do anything with it for now
   347  				// and it does not touch the state machine
   348  				continue
   349  			}
   350  		case nsInfo = <-handler.nextState:
   351  			in = nsInfo.msg
   352  			if in == nil {
   353  				err = fmt.Errorf("Next state nil message, ending chaincode support stream")
   354  				chaincodeLogger.Debug("Next state nil message, ending chaincode support stream")
   355  				return err
   356  			}
   357  			chaincodeLogger.Debugf("[%s]Move state message %s", shorttxid(in.Txid), in.Type.String())
   358  		case <-handler.waitForKeepaliveTimer():
   359  			if handler.chaincodeSupport.keepalive <= 0 {
   360  				chaincodeLogger.Errorf("Invalid select: keepalive not on (keepalive=%d)", handler.chaincodeSupport.keepalive)
   361  				continue
   362  			}
   363  
   364  			//if no error message from serialSend, KEEPALIVE happy, and don't care about error
   365  			//(maybe it'll work later)
   366  			handler.serialSendAsync(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_KEEPALIVE}, nil)
   367  			continue
   368  		}
   369  
   370  		err = handler.HandleMessage(in)
   371  		if err != nil {
   372  			chaincodeLogger.Errorf("[%s]Error handling message, ending stream: %s", shorttxid(in.Txid), err)
   373  			return fmt.Errorf("Error handling message, ending stream: %s", err)
   374  		}
   375  
   376  		if nsInfo != nil && nsInfo.sendToCC {
   377  			chaincodeLogger.Debugf("[%s]sending state message %s", shorttxid(in.Txid), in.Type.String())
   378  			//ready messages are sent sync
   379  			if nsInfo.sendSync {
   380  				if in.Type.String() != pb.ChaincodeMessage_READY.String() {
   381  					panic(fmt.Sprintf("[%s]Sync send can only be for READY state %s\n", shorttxid(in.Txid), in.Type.String()))
   382  				}
   383  				if err = handler.serialSend(in); err != nil {
   384  					return fmt.Errorf("[%s]Error sending ready  message, ending stream: %s", shorttxid(in.Txid), err)
   385  				}
   386  			} else {
   387  				//if error bail in select
   388  				handler.serialSendAsync(in, errc)
   389  			}
   390  		}
   391  	}
   392  }
   393  
   394  // HandleChaincodeStream Main loop for handling the associated Chaincode stream
   395  func HandleChaincodeStream(chaincodeSupport *ChaincodeSupport, ctxt context.Context, stream ccintf.ChaincodeStream) error {
   396  	deadline, ok := ctxt.Deadline()
   397  	chaincodeLogger.Debugf("Current context deadline = %s, ok = %v", deadline, ok)
   398  	handler := newChaincodeSupportHandler(chaincodeSupport, stream)
   399  	return handler.processStream()
   400  }
   401  
   402  func newChaincodeSupportHandler(chaincodeSupport *ChaincodeSupport, peerChatStream ccintf.ChaincodeStream) *Handler {
   403  	v := &Handler{
   404  		ChatStream: peerChatStream,
   405  	}
   406  	v.chaincodeSupport = chaincodeSupport
   407  	//we want this to block
   408  	v.nextState = make(chan *nextStateInfo)
   409  
   410  	v.FSM = fsm.NewFSM(
   411  		createdstate,
   412  		fsm.Events{
   413  			//Send REGISTERED, then, if deploy { trigger INIT(via INIT) } else { trigger READY(via COMPLETED) }
   414  			{Name: pb.ChaincodeMessage_REGISTER.String(), Src: []string{createdstate}, Dst: establishedstate},
   415  			{Name: pb.ChaincodeMessage_READY.String(), Src: []string{establishedstate}, Dst: readystate},
   416  			{Name: pb.ChaincodeMessage_PUT_STATE.String(), Src: []string{readystate}, Dst: readystate},
   417  			{Name: pb.ChaincodeMessage_DEL_STATE.String(), Src: []string{readystate}, Dst: readystate},
   418  			{Name: pb.ChaincodeMessage_INVOKE_CHAINCODE.String(), Src: []string{readystate}, Dst: readystate},
   419  			{Name: pb.ChaincodeMessage_COMPLETED.String(), Src: []string{readystate}, Dst: readystate},
   420  			{Name: pb.ChaincodeMessage_GET_STATE.String(), Src: []string{readystate}, Dst: readystate},
   421  			{Name: pb.ChaincodeMessage_GET_STATE_BY_RANGE.String(), Src: []string{readystate}, Dst: readystate},
   422  			{Name: pb.ChaincodeMessage_GET_QUERY_RESULT.String(), Src: []string{readystate}, Dst: readystate},
   423  			{Name: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY.String(), Src: []string{readystate}, Dst: readystate},
   424  			{Name: pb.ChaincodeMessage_QUERY_STATE_NEXT.String(), Src: []string{readystate}, Dst: readystate},
   425  			{Name: pb.ChaincodeMessage_QUERY_STATE_CLOSE.String(), Src: []string{readystate}, Dst: readystate},
   426  			{Name: pb.ChaincodeMessage_ERROR.String(), Src: []string{readystate}, Dst: readystate},
   427  			{Name: pb.ChaincodeMessage_RESPONSE.String(), Src: []string{readystate}, Dst: readystate},
   428  			{Name: pb.ChaincodeMessage_INIT.String(), Src: []string{readystate}, Dst: readystate},
   429  			{Name: pb.ChaincodeMessage_TRANSACTION.String(), Src: []string{readystate}, Dst: readystate},
   430  		},
   431  		fsm.Callbacks{
   432  			"before_" + pb.ChaincodeMessage_REGISTER.String():           func(e *fsm.Event) { v.beforeRegisterEvent(e, v.FSM.Current()) },
   433  			"before_" + pb.ChaincodeMessage_COMPLETED.String():          func(e *fsm.Event) { v.beforeCompletedEvent(e, v.FSM.Current()) },
   434  			"after_" + pb.ChaincodeMessage_GET_STATE.String():           func(e *fsm.Event) { v.afterGetState(e, v.FSM.Current()) },
   435  			"after_" + pb.ChaincodeMessage_GET_STATE_BY_RANGE.String():  func(e *fsm.Event) { v.afterGetStateByRange(e, v.FSM.Current()) },
   436  			"after_" + pb.ChaincodeMessage_GET_QUERY_RESULT.String():    func(e *fsm.Event) { v.afterGetQueryResult(e, v.FSM.Current()) },
   437  			"after_" + pb.ChaincodeMessage_GET_HISTORY_FOR_KEY.String(): func(e *fsm.Event) { v.afterGetHistoryForKey(e, v.FSM.Current()) },
   438  			"after_" + pb.ChaincodeMessage_QUERY_STATE_NEXT.String():    func(e *fsm.Event) { v.afterQueryStateNext(e, v.FSM.Current()) },
   439  			"after_" + pb.ChaincodeMessage_QUERY_STATE_CLOSE.String():   func(e *fsm.Event) { v.afterQueryStateClose(e, v.FSM.Current()) },
   440  			"after_" + pb.ChaincodeMessage_PUT_STATE.String():           func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) },
   441  			"after_" + pb.ChaincodeMessage_DEL_STATE.String():           func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) },
   442  			"after_" + pb.ChaincodeMessage_INVOKE_CHAINCODE.String():    func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) },
   443  			"enter_" + establishedstate:                                 func(e *fsm.Event) { v.enterEstablishedState(e, v.FSM.Current()) },
   444  			"enter_" + readystate:                                       func(e *fsm.Event) { v.enterReadyState(e, v.FSM.Current()) },
   445  			"enter_" + endstate:                                         func(e *fsm.Event) { v.enterEndState(e, v.FSM.Current()) },
   446  		},
   447  	)
   448  
   449  	v.policyChecker = policy.NewPolicyChecker(
   450  		peer.NewChannelPolicyManagerGetter(),
   451  		mgmt.GetLocalMSP(),
   452  		mgmt.NewLocalMSPPrincipalGetter(),
   453  	)
   454  
   455  	return v
   456  }
   457  
   458  func (handler *Handler) createTXIDEntry(txid string) bool {
   459  	if handler.txidMap == nil {
   460  		return false
   461  	}
   462  	handler.Lock()
   463  	defer handler.Unlock()
   464  	if handler.txidMap[txid] {
   465  		return false
   466  	}
   467  	handler.txidMap[txid] = true
   468  	return handler.txidMap[txid]
   469  }
   470  
   471  func (handler *Handler) deleteTXIDEntry(txid string) {
   472  	handler.Lock()
   473  	defer handler.Unlock()
   474  	if handler.txidMap != nil {
   475  		delete(handler.txidMap, txid)
   476  	} else {
   477  		chaincodeLogger.Warningf("TXID %s not found!", txid)
   478  	}
   479  }
   480  
   481  func (handler *Handler) notifyDuringStartup(val bool) {
   482  	//if USER_RUNS_CC readyNotify will be nil
   483  	if handler.readyNotify != nil {
   484  		chaincodeLogger.Debug("Notifying during startup")
   485  		handler.readyNotify <- val
   486  	} else {
   487  		chaincodeLogger.Debug("nothing to notify (dev mode ?)")
   488  		//In theory, we don't even need a devmode flag in the peer anymore
   489  		//as the chaincode is brought up without any context (ledger context
   490  		//in particular). What this means is we can have - in theory - a nondev
   491  		//environment where we can attach a chaincode manually. This could be
   492  		//useful .... but for now lets just be conservative and allow manual
   493  		//chaincode only in dev mode (ie, peer started with --peer-chaincodedev=true)
   494  		if handler.chaincodeSupport.userRunsCC {
   495  			if val {
   496  				chaincodeLogger.Debug("sending READY")
   497  				ccMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY}
   498  				go handler.triggerNextState(ccMsg, true)
   499  			} else {
   500  				chaincodeLogger.Errorf("Error during startup .. not sending READY")
   501  			}
   502  		} else {
   503  			chaincodeLogger.Warningf("trying to manually run chaincode when not in devmode ?")
   504  		}
   505  	}
   506  }
   507  
   508  // beforeRegisterEvent is invoked when chaincode tries to register.
   509  func (handler *Handler) beforeRegisterEvent(e *fsm.Event, state string) {
   510  	chaincodeLogger.Debugf("Received %s in state %s", e.Event, state)
   511  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
   512  	if !ok {
   513  		e.Cancel(fmt.Errorf("Received unexpected message type"))
   514  		return
   515  	}
   516  	chaincodeID := &pb.ChaincodeID{}
   517  	err := proto.Unmarshal(msg.Payload, chaincodeID)
   518  	if err != nil {
   519  		e.Cancel(fmt.Errorf("Error in received %s, could NOT unmarshal registration info: %s", pb.ChaincodeMessage_REGISTER, err))
   520  		return
   521  	}
   522  
   523  	// Now register with the chaincodeSupport
   524  	handler.ChaincodeID = chaincodeID
   525  	err = handler.chaincodeSupport.registerHandler(handler)
   526  	if err != nil {
   527  		e.Cancel(err)
   528  		handler.notifyDuringStartup(false)
   529  		return
   530  	}
   531  
   532  	//get the component parts so we can use the root chaincode
   533  	//name in keys
   534  	handler.decomposeRegisteredName(handler.ChaincodeID)
   535  
   536  	chaincodeLogger.Debugf("Got %s for chaincodeID = %s, sending back %s", e.Event, chaincodeID, pb.ChaincodeMessage_REGISTERED)
   537  	if err := handler.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}); err != nil {
   538  		e.Cancel(fmt.Errorf("Error sending %s: %s", pb.ChaincodeMessage_REGISTERED, err))
   539  		handler.notifyDuringStartup(false)
   540  		return
   541  	}
   542  }
   543  
   544  func (handler *Handler) notify(msg *pb.ChaincodeMessage) {
   545  	handler.Lock()
   546  	defer handler.Unlock()
   547  	tctx := handler.txCtxs[msg.Txid]
   548  	if tctx == nil {
   549  		chaincodeLogger.Debugf("notifier Txid:%s does not exist", msg.Txid)
   550  	} else {
   551  		chaincodeLogger.Debugf("notifying Txid:%s", msg.Txid)
   552  		tctx.responseNotifier <- msg
   553  
   554  		// clean up queryIteratorMap
   555  		for _, v := range tctx.queryIteratorMap {
   556  			v.Close()
   557  		}
   558  	}
   559  }
   560  
   561  // beforeCompletedEvent is invoked when chaincode has completed execution of init, invoke.
   562  func (handler *Handler) beforeCompletedEvent(e *fsm.Event, state string) {
   563  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
   564  	if !ok {
   565  		e.Cancel(fmt.Errorf("Received unexpected message type"))
   566  		return
   567  	}
   568  	// Notify on channel once into READY state
   569  	chaincodeLogger.Debugf("[%s]beforeCompleted - not in ready state will notify when in readystate", shorttxid(msg.Txid))
   570  	return
   571  }
   572  
   573  // afterGetState handles a GET_STATE request from the chaincode.
   574  func (handler *Handler) afterGetState(e *fsm.Event, state string) {
   575  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
   576  	if !ok {
   577  		e.Cancel(fmt.Errorf("Received unexpected message type"))
   578  		return
   579  	}
   580  	chaincodeLogger.Debugf("[%s]Received %s, invoking get state from ledger", shorttxid(msg.Txid), pb.ChaincodeMessage_GET_STATE)
   581  
   582  	// Query ledger for state
   583  	handler.handleGetState(msg)
   584  }
   585  
   586  // is this a txid for which there is a valid txsim
   587  func (handler *Handler) isValidTxSim(txid string, fmtStr string, args ...interface{}) (*transactionContext, *pb.ChaincodeMessage) {
   588  	txContext := handler.getTxContext(txid)
   589  	if txContext == nil || txContext.txsimulator == nil {
   590  		// Send error msg back to chaincode. No ledger context
   591  		errStr := fmt.Sprintf(fmtStr, args...)
   592  		chaincodeLogger.Errorf(errStr)
   593  		return nil, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(errStr), Txid: txid}
   594  	}
   595  	return txContext, nil
   596  }
   597  
   598  // Handles query to ledger to get state
   599  func (handler *Handler) handleGetState(msg *pb.ChaincodeMessage) {
   600  	// The defer followed by triggering a go routine dance is needed to ensure that the previous state transition
   601  	// is completed before the next one is triggered. The previous state transition is deemed complete only when
   602  	// the afterGetState function is exited. Interesting bug fix!!
   603  	go func() {
   604  		// Check if this is the unique state request from this chaincode txid
   605  		uniqueReq := handler.createTXIDEntry(msg.Txid)
   606  		if !uniqueReq {
   607  			// Drop this request
   608  			chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.")
   609  			return
   610  		}
   611  
   612  		var serialSendMsg *pb.ChaincodeMessage
   613  		var txContext *transactionContext
   614  		txContext, serialSendMsg = handler.isValidTxSim(msg.Txid,
   615  			"[%s]No ledger context for GetState. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
   616  
   617  		defer func() {
   618  			handler.deleteTXIDEntry(msg.Txid)
   619  			if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
   620  				chaincodeLogger.Debugf("[%s]handleGetState serial send %s",
   621  					shorttxid(serialSendMsg.Txid), serialSendMsg.Type)
   622  			}
   623  			handler.serialSendAsync(serialSendMsg, nil)
   624  		}()
   625  
   626  		if txContext == nil {
   627  			return
   628  		}
   629  
   630  		key := string(msg.Payload)
   631  		chaincodeID := handler.getCCRootName()
   632  		if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
   633  			chaincodeLogger.Debugf("[%s] getting state for chaincode %s, key %s, channel %s",
   634  				shorttxid(msg.Txid), chaincodeID, key, txContext.chainID)
   635  		}
   636  
   637  		var res []byte
   638  		var err error
   639  		res, err = txContext.txsimulator.GetState(chaincodeID, key)
   640  
   641  		if err != nil {
   642  			// Send error msg back to chaincode. GetState will not trigger event
   643  			payload := []byte(err.Error())
   644  			chaincodeLogger.Errorf("[%s]Failed to get chaincode state(%s). Sending %s",
   645  				shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR)
   646  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
   647  		} else if res == nil {
   648  			//The state object being requested does not exist
   649  			chaincodeLogger.Debugf("[%s]No state associated with key: %s. Sending %s with an empty payload",
   650  				shorttxid(msg.Txid), key, pb.ChaincodeMessage_RESPONSE)
   651  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid}
   652  		} else {
   653  			// Send response msg back to chaincode. GetState will not trigger event
   654  			if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
   655  				chaincodeLogger.Debugf("[%s]Got state. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_RESPONSE)
   656  			}
   657  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid}
   658  		}
   659  
   660  	}()
   661  }
   662  
   663  // afterGetStateByRange handles a GET_STATE_BY_RANGE request from the chaincode.
   664  func (handler *Handler) afterGetStateByRange(e *fsm.Event, state string) {
   665  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
   666  	if !ok {
   667  		e.Cancel(fmt.Errorf("Received unexpected message type"))
   668  		return
   669  	}
   670  	chaincodeLogger.Debugf("Received %s, invoking get state from ledger", pb.ChaincodeMessage_GET_STATE_BY_RANGE)
   671  
   672  	// Query ledger for state
   673  	handler.handleGetStateByRange(msg)
   674  	chaincodeLogger.Debug("Exiting GET_STATE_BY_RANGE")
   675  }
   676  
   677  // Handles query to ledger to rage query state
   678  func (handler *Handler) handleGetStateByRange(msg *pb.ChaincodeMessage) {
   679  	// The defer followed by triggering a go routine dance is needed to ensure that the previous state transition
   680  	// is completed before the next one is triggered. The previous state transition is deemed complete only when
   681  	// the afterGetStateByRange function is exited. Interesting bug fix!!
   682  	go func() {
   683  		// Check if this is the unique state request from this chaincode txid
   684  		uniqueReq := handler.createTXIDEntry(msg.Txid)
   685  		if !uniqueReq {
   686  			// Drop this request
   687  			chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.")
   688  			return
   689  		}
   690  
   691  		var serialSendMsg *pb.ChaincodeMessage
   692  
   693  		defer func() {
   694  			handler.deleteTXIDEntry(msg.Txid)
   695  			chaincodeLogger.Debugf("[%s]handleGetStateByRange serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type)
   696  			handler.serialSendAsync(serialSendMsg, nil)
   697  		}()
   698  
   699  		getStateByRange := &pb.GetStateByRange{}
   700  		unmarshalErr := proto.Unmarshal(msg.Payload, getStateByRange)
   701  		if unmarshalErr != nil {
   702  			payload := []byte(unmarshalErr.Error())
   703  			chaincodeLogger.Errorf("Failed to unmarshall range query request. Sending %s", pb.ChaincodeMessage_ERROR)
   704  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
   705  			return
   706  		}
   707  
   708  		iterID := util.GenerateUUID()
   709  
   710  		var txContext *transactionContext
   711  
   712  		txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for GetStateByRange. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
   713  		if txContext == nil {
   714  			return
   715  		}
   716  		chaincodeID := handler.getCCRootName()
   717  
   718  		errHandler := func(err error, iter commonledger.ResultsIterator, errFmt string, errArgs ...interface{}) {
   719  			if iter != nil {
   720  				iter.Close()
   721  				handler.deleteQueryIterator(txContext, iterID)
   722  			}
   723  			payload := []byte(err.Error())
   724  			chaincodeLogger.Errorf(errFmt, errArgs)
   725  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
   726  		}
   727  
   728  		rangeIter, err := txContext.txsimulator.GetStateRangeScanIterator(chaincodeID, getStateByRange.StartKey, getStateByRange.EndKey)
   729  		if err != nil {
   730  			errHandler(err, nil, "Failed to get ledger scan iterator. Sending %s", pb.ChaincodeMessage_ERROR)
   731  			return
   732  		}
   733  
   734  		handler.putQueryIterator(txContext, iterID, rangeIter)
   735  		var payload *pb.QueryResponse
   736  		payload, err = getQueryResponse(handler, txContext, rangeIter, iterID)
   737  		if err != nil {
   738  			errHandler(err, rangeIter, "Failed to get query result. Sending %s", pb.ChaincodeMessage_ERROR)
   739  			return
   740  		}
   741  
   742  		var payloadBytes []byte
   743  		payloadBytes, err = proto.Marshal(payload)
   744  		if err != nil {
   745  			errHandler(err, rangeIter, "Failed to marshal response. Sending %s", pb.ChaincodeMessage_ERROR)
   746  			return
   747  		}
   748  		chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE)
   749  		serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid}
   750  
   751  	}()
   752  }
   753  
   754  const maxResultLimit = 100
   755  
   756  //getQueryResponse takes an iterator and fetch state to construct QueryResponse
   757  func getQueryResponse(handler *Handler, txContext *transactionContext, iter commonledger.ResultsIterator,
   758  	iterID string) (*pb.QueryResponse, error) {
   759  
   760  	var err error
   761  	var queryResult commonledger.QueryResult
   762  	var queryResultsBytes []*pb.QueryResultBytes
   763  
   764  	for i := 0; i < maxResultLimit; i++ {
   765  		queryResult, err = iter.Next()
   766  		if err != nil {
   767  			chaincodeLogger.Errorf("Failed to get query result from iterator")
   768  			break
   769  		}
   770  		if queryResult == nil {
   771  			break
   772  		}
   773  		var resultBytes []byte
   774  		resultBytes, err = proto.Marshal(queryResult.(proto.Message))
   775  		if err != nil {
   776  			chaincodeLogger.Errorf("Failed to get encode query result as bytes")
   777  			break
   778  		}
   779  
   780  		qresultBytes := pb.QueryResultBytes{ResultBytes: resultBytes}
   781  		queryResultsBytes = append(queryResultsBytes, &qresultBytes)
   782  	}
   783  
   784  	if queryResult == nil || err != nil {
   785  		iter.Close()
   786  		handler.deleteQueryIterator(txContext, iterID)
   787  		if err != nil {
   788  			return nil, err
   789  		}
   790  	}
   791  	return &pb.QueryResponse{Results: queryResultsBytes, HasMore: queryResult != nil, Id: iterID}, nil
   792  }
   793  
   794  // afterQueryStateNext handles a QUERY_STATE_NEXT request from the chaincode.
   795  func (handler *Handler) afterQueryStateNext(e *fsm.Event, state string) {
   796  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
   797  	if !ok {
   798  		e.Cancel(fmt.Errorf("Received unexpected message type"))
   799  		return
   800  	}
   801  	chaincodeLogger.Debugf("Received %s, invoking query state next from ledger", pb.ChaincodeMessage_QUERY_STATE_NEXT)
   802  
   803  	// Query ledger for state
   804  	handler.handleQueryStateNext(msg)
   805  	chaincodeLogger.Debug("Exiting QUERY_STATE_NEXT")
   806  }
   807  
   808  // Handles query to ledger for query state next
   809  func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) {
   810  	// The defer followed by triggering a go routine dance is needed to ensure that the previous state transition
   811  	// is completed before the next one is triggered. The previous state transition is deemed complete only when
   812  	// the afterGetStateByRange function is exited. Interesting bug fix!!
   813  	go func() {
   814  		// Check if this is the unique state request from this chaincode txid
   815  		uniqueReq := handler.createTXIDEntry(msg.Txid)
   816  		if !uniqueReq {
   817  			// Drop this request
   818  			chaincodeLogger.Debug("Another state request pending for this Txid. Cannot process.")
   819  			return
   820  		}
   821  
   822  		var serialSendMsg *pb.ChaincodeMessage
   823  
   824  		defer func() {
   825  			handler.deleteTXIDEntry(msg.Txid)
   826  			chaincodeLogger.Debugf("[%s]handleQueryStateNext serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type)
   827  			handler.serialSendAsync(serialSendMsg, nil)
   828  		}()
   829  
   830  		var txContext *transactionContext
   831  		var queryStateNext *pb.QueryStateNext
   832  
   833  		errHandler := func(payload []byte, iter commonledger.ResultsIterator, errFmt string, errArgs ...interface{}) {
   834  			if iter != nil {
   835  				iter.Close()
   836  				handler.deleteQueryIterator(txContext, queryStateNext.Id)
   837  			}
   838  			chaincodeLogger.Errorf(errFmt, errArgs)
   839  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
   840  		}
   841  
   842  		queryStateNext = &pb.QueryStateNext{}
   843  
   844  		unmarshalErr := proto.Unmarshal(msg.Payload, queryStateNext)
   845  		if unmarshalErr != nil {
   846  			errHandler([]byte(unmarshalErr.Error()), nil, "Failed to unmarshall state next query request. Sending %s", pb.ChaincodeMessage_ERROR)
   847  			return
   848  		}
   849  
   850  		txContext = handler.getTxContext(msg.Txid)
   851  		if txContext == nil {
   852  			errHandler([]byte("transaction context not found (timed out ?)"), nil, "[%s]Failed to get transaction context. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
   853  			return
   854  		}
   855  
   856  		queryIter := handler.getQueryIterator(txContext, queryStateNext.Id)
   857  
   858  		if queryIter == nil {
   859  			errHandler([]byte("query iterator not found"), nil, "query iterator not found. Sending %s", pb.ChaincodeMessage_ERROR)
   860  			return
   861  		}
   862  
   863  		payload, err := getQueryResponse(handler, txContext, queryIter, queryStateNext.Id)
   864  		if err != nil {
   865  			errHandler([]byte(err.Error()), queryIter, "Failed to get query result. Sending %s", pb.ChaincodeMessage_ERROR)
   866  			return
   867  		}
   868  		payloadBytes, err := proto.Marshal(payload)
   869  		if err != nil {
   870  			errHandler([]byte(err.Error()), queryIter, "Failed to marshal response. Sending %s", pb.ChaincodeMessage_ERROR)
   871  			return
   872  		}
   873  		chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE)
   874  		serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid}
   875  
   876  	}()
   877  }
   878  
   879  // afterQueryStateClose handles a QUERY_STATE_CLOSE request from the chaincode.
   880  func (handler *Handler) afterQueryStateClose(e *fsm.Event, state string) {
   881  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
   882  	if !ok {
   883  		e.Cancel(fmt.Errorf("Received unexpected message type"))
   884  		return
   885  	}
   886  	chaincodeLogger.Debugf("Received %s, invoking query state close from ledger", pb.ChaincodeMessage_QUERY_STATE_CLOSE)
   887  
   888  	// Query ledger for state
   889  	handler.handleQueryStateClose(msg)
   890  	chaincodeLogger.Debug("Exiting QUERY_STATE_CLOSE")
   891  }
   892  
   893  // Handles the closing of a state iterator
   894  func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) {
   895  	// The defer followed by triggering a go routine dance is needed to ensure that the previous state transition
   896  	// is completed before the next one is triggered. The previous state transition is deemed complete only when
   897  	// the afterGetStateByRange function is exited. Interesting bug fix!!
   898  	go func() {
   899  		// Check if this is the unique state request from this chaincode txid
   900  		uniqueReq := handler.createTXIDEntry(msg.Txid)
   901  		if !uniqueReq {
   902  			// Drop this request
   903  			chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.")
   904  			return
   905  		}
   906  
   907  		var serialSendMsg *pb.ChaincodeMessage
   908  
   909  		defer func() {
   910  			handler.deleteTXIDEntry(msg.Txid)
   911  			chaincodeLogger.Debugf("[%s]handleQueryStateClose serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type)
   912  			handler.serialSendAsync(serialSendMsg, nil)
   913  		}()
   914  
   915  		errHandler := func(payload []byte, errFmt string, errArgs ...interface{}) {
   916  			chaincodeLogger.Errorf(errFmt, errArgs)
   917  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
   918  		}
   919  
   920  		queryStateClose := &pb.QueryStateClose{}
   921  		unmarshalErr := proto.Unmarshal(msg.Payload, queryStateClose)
   922  		if unmarshalErr != nil {
   923  			errHandler([]byte(unmarshalErr.Error()), "Failed to unmarshall state query close request. Sending %s", pb.ChaincodeMessage_ERROR)
   924  			return
   925  		}
   926  
   927  		txContext := handler.getTxContext(msg.Txid)
   928  		if txContext == nil {
   929  			errHandler([]byte("transaction context not found (timed out ?)"), "[%s]Failed to get transaction context. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
   930  			return
   931  		}
   932  
   933  		iter := handler.getQueryIterator(txContext, queryStateClose.Id)
   934  		if iter != nil {
   935  			iter.Close()
   936  			handler.deleteQueryIterator(txContext, queryStateClose.Id)
   937  		}
   938  
   939  		payload := &pb.QueryResponse{HasMore: false, Id: queryStateClose.Id}
   940  		payloadBytes, err := proto.Marshal(payload)
   941  		if err != nil {
   942  			errHandler([]byte(err.Error()), "Failed marshall resopnse. Sending %s", pb.ChaincodeMessage_ERROR)
   943  			return
   944  		}
   945  
   946  		chaincodeLogger.Debugf("Closed. Sending %s", pb.ChaincodeMessage_RESPONSE)
   947  		serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid}
   948  
   949  	}()
   950  }
   951  
   952  // afterGetQueryResult handles a GET_QUERY_RESULT request from the chaincode.
   953  func (handler *Handler) afterGetQueryResult(e *fsm.Event, state string) {
   954  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
   955  	if !ok {
   956  		e.Cancel(fmt.Errorf("Received unexpected message type"))
   957  		return
   958  	}
   959  	chaincodeLogger.Debugf("Received %s, invoking get state from ledger", pb.ChaincodeMessage_GET_QUERY_RESULT)
   960  
   961  	// Query ledger for state
   962  	handler.handleGetQueryResult(msg)
   963  	chaincodeLogger.Debug("Exiting GET_QUERY_RESULT")
   964  }
   965  
   966  // Handles query to ledger to execute query state
   967  func (handler *Handler) handleGetQueryResult(msg *pb.ChaincodeMessage) {
   968  	// The defer followed by triggering a go routine dance is needed to ensure that the previous state transition
   969  	// is completed before the next one is triggered. The previous state transition is deemed complete only when
   970  	// the afterQueryState function is exited. Interesting bug fix!!
   971  	go func() {
   972  		// Check if this is the unique state request from this chaincode txid
   973  		uniqueReq := handler.createTXIDEntry(msg.Txid)
   974  		if !uniqueReq {
   975  			// Drop this request
   976  			chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.")
   977  			return
   978  		}
   979  
   980  		var serialSendMsg *pb.ChaincodeMessage
   981  
   982  		defer func() {
   983  			handler.deleteTXIDEntry(msg.Txid)
   984  			chaincodeLogger.Debugf("[%s]handleGetQueryResult serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type)
   985  			handler.serialSendAsync(serialSendMsg, nil)
   986  		}()
   987  
   988  		var txContext *transactionContext
   989  		var iterID string
   990  
   991  		errHandler := func(payload []byte, iter commonledger.ResultsIterator, errFmt string, errArgs ...interface{}) {
   992  			if iter != nil {
   993  				iter.Close()
   994  				handler.deleteQueryIterator(txContext, iterID)
   995  			}
   996  			chaincodeLogger.Errorf(errFmt, errArgs)
   997  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
   998  		}
   999  
  1000  		getQueryResult := &pb.GetQueryResult{}
  1001  		unmarshalErr := proto.Unmarshal(msg.Payload, getQueryResult)
  1002  		if unmarshalErr != nil {
  1003  			errHandler([]byte(unmarshalErr.Error()), nil, "Failed to unmarshall query request. Sending %s", pb.ChaincodeMessage_ERROR)
  1004  			return
  1005  		}
  1006  
  1007  		iterID = util.GenerateUUID()
  1008  
  1009  		txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for GetQueryResult. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
  1010  		if txContext == nil {
  1011  			return
  1012  		}
  1013  
  1014  		chaincodeID := handler.getCCRootName()
  1015  
  1016  		executeIter, err := txContext.txsimulator.ExecuteQuery(chaincodeID, getQueryResult.Query)
  1017  		if err != nil {
  1018  			errHandler([]byte(err.Error()), nil, "Failed to get ledger query iterator. Sending %s", pb.ChaincodeMessage_ERROR)
  1019  			return
  1020  		}
  1021  
  1022  		handler.putQueryIterator(txContext, iterID, executeIter)
  1023  		var payload *pb.QueryResponse
  1024  		payload, err = getQueryResponse(handler, txContext, executeIter, iterID)
  1025  		if err != nil {
  1026  			errHandler([]byte(err.Error()), executeIter, "Failed to get query result. Sending %s", pb.ChaincodeMessage_ERROR)
  1027  			return
  1028  		}
  1029  
  1030  		var payloadBytes []byte
  1031  		payloadBytes, err = proto.Marshal(payload)
  1032  		if err != nil {
  1033  			errHandler([]byte(err.Error()), executeIter, "Failed marshall response. Sending %s", pb.ChaincodeMessage_ERROR)
  1034  			return
  1035  		}
  1036  
  1037  		chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE)
  1038  		serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid}
  1039  
  1040  	}()
  1041  }
  1042  
  1043  // afterGetHistoryForKey handles a GET_HISTORY_FOR_KEY request from the chaincode.
  1044  func (handler *Handler) afterGetHistoryForKey(e *fsm.Event, state string) {
  1045  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
  1046  	if !ok {
  1047  		e.Cancel(fmt.Errorf("Received unexpected message type"))
  1048  		return
  1049  	}
  1050  	chaincodeLogger.Debugf("Received %s, invoking get state from ledger", pb.ChaincodeMessage_GET_HISTORY_FOR_KEY)
  1051  
  1052  	// Query ledger history db
  1053  	handler.handleGetHistoryForKey(msg)
  1054  	chaincodeLogger.Debug("Exiting GET_HISTORY_FOR_KEY")
  1055  }
  1056  
  1057  // Handles query to ledger history db
  1058  func (handler *Handler) handleGetHistoryForKey(msg *pb.ChaincodeMessage) {
  1059  	// The defer followed by triggering a go routine dance is needed to ensure that the previous state transition
  1060  	// is completed before the next one is triggered. The previous state transition is deemed complete only when
  1061  	// the afterQueryState function is exited. Interesting bug fix!!
  1062  	go func() {
  1063  		// Check if this is the unique state request from this chaincode txid
  1064  		uniqueReq := handler.createTXIDEntry(msg.Txid)
  1065  		if !uniqueReq {
  1066  			// Drop this request
  1067  			chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.")
  1068  			return
  1069  		}
  1070  
  1071  		var serialSendMsg *pb.ChaincodeMessage
  1072  
  1073  		defer func() {
  1074  			handler.deleteTXIDEntry(msg.Txid)
  1075  			chaincodeLogger.Debugf("[%s]handleGetHistoryForKey serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type)
  1076  			handler.serialSendAsync(serialSendMsg, nil)
  1077  		}()
  1078  
  1079  		var iterID string
  1080  		var txContext *transactionContext
  1081  
  1082  		errHandler := func(payload []byte, iter commonledger.ResultsIterator, errFmt string, errArgs ...interface{}) {
  1083  			if iter != nil {
  1084  				iter.Close()
  1085  				handler.deleteQueryIterator(txContext, iterID)
  1086  			}
  1087  			chaincodeLogger.Errorf(errFmt, errArgs)
  1088  			serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
  1089  		}
  1090  
  1091  		getHistoryForKey := &pb.GetHistoryForKey{}
  1092  		unmarshalErr := proto.Unmarshal(msg.Payload, getHistoryForKey)
  1093  		if unmarshalErr != nil {
  1094  			errHandler([]byte(unmarshalErr.Error()), nil, "Failed to unmarshall query request. Sending %s", pb.ChaincodeMessage_ERROR)
  1095  			return
  1096  		}
  1097  
  1098  		iterID = util.GenerateUUID()
  1099  
  1100  		txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for GetHistoryForKey. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
  1101  		if txContext == nil {
  1102  			return
  1103  		}
  1104  		chaincodeID := handler.getCCRootName()
  1105  
  1106  		historyIter, err := txContext.historyQueryExecutor.GetHistoryForKey(chaincodeID, getHistoryForKey.Key)
  1107  		if err != nil {
  1108  			errHandler([]byte(err.Error()), nil, "Failed to get ledger history iterator. Sending %s", pb.ChaincodeMessage_ERROR)
  1109  			return
  1110  		}
  1111  
  1112  		handler.putQueryIterator(txContext, iterID, historyIter)
  1113  
  1114  		var payload *pb.QueryResponse
  1115  		payload, err = getQueryResponse(handler, txContext, historyIter, iterID)
  1116  
  1117  		if err != nil {
  1118  			errHandler([]byte(err.Error()), historyIter, "Failed to get query result. Sending %s", pb.ChaincodeMessage_ERROR)
  1119  			return
  1120  		}
  1121  
  1122  		var payloadBytes []byte
  1123  		payloadBytes, err = proto.Marshal(payload)
  1124  		if err != nil {
  1125  			errHandler([]byte(err.Error()), historyIter, "Failed marshal response. Sending %s", pb.ChaincodeMessage_ERROR)
  1126  			return
  1127  		}
  1128  
  1129  		chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE)
  1130  		serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid}
  1131  
  1132  	}()
  1133  }
  1134  
  1135  // Handles request to ledger to put state
  1136  func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
  1137  	go func() {
  1138  		msg, _ := e.Args[0].(*pb.ChaincodeMessage)
  1139  		if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1140  			chaincodeLogger.Debugf("[%s]state is %s", shorttxid(msg.Txid), state)
  1141  		}
  1142  		// Check if this is the unique request from this chaincode txid
  1143  		uniqueReq := handler.createTXIDEntry(msg.Txid)
  1144  		if !uniqueReq {
  1145  			// Drop this request
  1146  			chaincodeLogger.Debug("Another request pending for this Txid. Cannot process.")
  1147  			return
  1148  		}
  1149  
  1150  		var triggerNextStateMsg *pb.ChaincodeMessage
  1151  		var txContext *transactionContext
  1152  		txContext, triggerNextStateMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for %s. Sending %s",
  1153  			shorttxid(msg.Txid), msg.Type.String(), pb.ChaincodeMessage_ERROR)
  1154  
  1155  		defer func() {
  1156  			handler.deleteTXIDEntry(msg.Txid)
  1157  			if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1158  				chaincodeLogger.Debugf("[%s]enterBusyState trigger event %s",
  1159  					shorttxid(triggerNextStateMsg.Txid), triggerNextStateMsg.Type)
  1160  			}
  1161  			handler.triggerNextState(triggerNextStateMsg, true)
  1162  		}()
  1163  
  1164  		if txContext == nil {
  1165  			return
  1166  		}
  1167  
  1168  		errHandler := func(payload []byte, errFmt string, errArgs ...interface{}) {
  1169  			chaincodeLogger.Errorf(errFmt, errArgs)
  1170  			triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
  1171  		}
  1172  
  1173  		chaincodeID := handler.getCCRootName()
  1174  		var err error
  1175  		var res []byte
  1176  
  1177  		if msg.Type.String() == pb.ChaincodeMessage_PUT_STATE.String() {
  1178  			putStateInfo := &pb.PutStateInfo{}
  1179  			unmarshalErr := proto.Unmarshal(msg.Payload, putStateInfo)
  1180  			if unmarshalErr != nil {
  1181  				errHandler([]byte(unmarshalErr.Error()), "[%s]Unable to decipher payload. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
  1182  				return
  1183  			}
  1184  
  1185  			err = txContext.txsimulator.SetState(chaincodeID, putStateInfo.Key, putStateInfo.Value)
  1186  		} else if msg.Type.String() == pb.ChaincodeMessage_DEL_STATE.String() {
  1187  			// Invoke ledger to delete state
  1188  			key := string(msg.Payload)
  1189  			err = txContext.txsimulator.DeleteState(chaincodeID, key)
  1190  		} else if msg.Type.String() == pb.ChaincodeMessage_INVOKE_CHAINCODE.String() {
  1191  			if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1192  				chaincodeLogger.Debugf("[%s] C-call-C", shorttxid(msg.Txid))
  1193  			}
  1194  			chaincodeSpec := &pb.ChaincodeSpec{}
  1195  			unmarshalErr := proto.Unmarshal(msg.Payload, chaincodeSpec)
  1196  			if unmarshalErr != nil {
  1197  				errHandler([]byte(unmarshalErr.Error()), "[%s]Unable to decipher payload. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
  1198  				return
  1199  			}
  1200  
  1201  			// Get the chaincodeID to invoke. The chaincodeID to be called may
  1202  			// contain composite info like "chaincode-name:version/channel-name"
  1203  			// We are not using version now but default to the latest
  1204  			calledCcIns := getChaincodeInstance(chaincodeSpec.ChaincodeId.Name)
  1205  			chaincodeSpec.ChaincodeId.Name = calledCcIns.ChaincodeName
  1206  			if calledCcIns.ChainID == "" {
  1207  				// use caller's channel as the called chaincode is in the same channel
  1208  				calledCcIns.ChainID = txContext.chainID
  1209  			}
  1210  			if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1211  				chaincodeLogger.Debugf("[%s] C-call-C %s on channel %s",
  1212  					shorttxid(msg.Txid), calledCcIns.ChaincodeName, calledCcIns.ChainID)
  1213  			}
  1214  
  1215  			err := handler.checkACL(txContext.signedProp, txContext.proposal, calledCcIns)
  1216  			if err != nil {
  1217  				errHandler([]byte(err.Error()), "[%s] C-call-C %s on channel %s failed check ACL [%v]: [%s]", shorttxid(msg.Txid), calledCcIns.ChaincodeName, calledCcIns.ChainID, txContext.signedProp, err)
  1218  				return
  1219  			}
  1220  
  1221  			// Set up a new context for the called chaincode if on a different channel
  1222  			// We grab the called channel's ledger simulator to hold the new state
  1223  			ctxt := context.Background()
  1224  			txsim := txContext.txsimulator
  1225  			historyQueryExecutor := txContext.historyQueryExecutor
  1226  			if calledCcIns.ChainID != txContext.chainID {
  1227  				lgr := peer.GetLedger(calledCcIns.ChainID)
  1228  				if lgr == nil {
  1229  					payload := "Failed to find ledger for called channel " + calledCcIns.ChainID
  1230  					triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR,
  1231  						Payload: []byte(payload), Txid: msg.Txid}
  1232  					return
  1233  				}
  1234  				txsim2, err2 := lgr.NewTxSimulator()
  1235  				if err2 != nil {
  1236  					triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR,
  1237  						Payload: []byte(err2.Error()), Txid: msg.Txid}
  1238  					return
  1239  				}
  1240  				defer txsim2.Done()
  1241  				txsim = txsim2
  1242  			}
  1243  			ctxt = context.WithValue(ctxt, TXSimulatorKey, txsim)
  1244  			ctxt = context.WithValue(ctxt, HistoryQueryExecutorKey, historyQueryExecutor)
  1245  
  1246  			if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1247  				chaincodeLogger.Debugf("[%s] calling lscc to get chaincode data for %s on channel %s",
  1248  					shorttxid(msg.Txid), calledCcIns.ChaincodeName, calledCcIns.ChainID)
  1249  			}
  1250  
  1251  			//Call LSCC to get the called chaincode artifacts
  1252  
  1253  			//is the chaincode a system chaincode ?
  1254  			isscc := sysccprovider.GetSystemChaincodeProvider().IsSysCC(calledCcIns.ChaincodeName)
  1255  
  1256  			var cd *ccprovider.ChaincodeData
  1257  			if !isscc {
  1258  				//if its a user chaincode, get the details from LSCC
  1259  				//Call LSCC to get the called chaincode artifacts
  1260  				cd, err = GetChaincodeDataFromLSCC(ctxt, msg.Txid, txContext.signedProp, txContext.proposal, calledCcIns.ChainID, calledCcIns.ChaincodeName)
  1261  				if err != nil {
  1262  					errHandler([]byte(err.Error()), "[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s", shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR)
  1263  					return
  1264  				}
  1265  
  1266  				err = ccprovider.CheckInsantiationPolicy(calledCcIns.ChaincodeName, cd.Version, cd)
  1267  				if err != nil {
  1268  					errHandler([]byte(err.Error()), "[%s]CheckInsantiationPolicy, error %s. Sending %s", shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR)
  1269  					return
  1270  				}
  1271  			} else {
  1272  				//this is a system cc, just call it directly
  1273  				cd = &ccprovider.ChaincodeData{Name: calledCcIns.ChaincodeName, Version: util.GetSysCCVersion()}
  1274  			}
  1275  
  1276  			cccid := ccprovider.NewCCContext(calledCcIns.ChainID, calledCcIns.ChaincodeName, cd.Version, msg.Txid, false, txContext.signedProp, txContext.proposal)
  1277  
  1278  			// Launch the new chaincode if not already running
  1279  			if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1280  				chaincodeLogger.Debugf("[%s] launching chaincode %s on channel %s",
  1281  					shorttxid(msg.Txid), calledCcIns.ChaincodeName, calledCcIns.ChainID)
  1282  			}
  1283  			cciSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: chaincodeSpec}
  1284  			_, chaincodeInput, launchErr := handler.chaincodeSupport.Launch(ctxt, cccid, cciSpec)
  1285  			if launchErr != nil {
  1286  				errHandler([]byte(launchErr.Error()), "[%s]Failed to launch invoked chaincode. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR)
  1287  				return
  1288  			}
  1289  
  1290  			// TODO: Need to handle timeout correctly
  1291  			timeout := time.Duration(30000) * time.Millisecond
  1292  
  1293  			ccMsg, _ := createCCMessage(pb.ChaincodeMessage_TRANSACTION, msg.Txid, chaincodeInput)
  1294  
  1295  			// Execute the chaincode... this CANNOT be an init at least for now
  1296  			response, execErr := handler.chaincodeSupport.Execute(ctxt, cccid, ccMsg, timeout)
  1297  
  1298  			//payload is marshalled and send to the calling chaincode's shim which unmarshals and
  1299  			//sends it to chaincode
  1300  			res = nil
  1301  			if execErr != nil {
  1302  				err = execErr
  1303  			} else {
  1304  				res, err = proto.Marshal(response)
  1305  			}
  1306  		}
  1307  
  1308  		if err != nil {
  1309  			errHandler([]byte(err.Error()), "[%s]Failed to handle %s. Sending %s", shorttxid(msg.Txid), msg.Type.String(), pb.ChaincodeMessage_ERROR)
  1310  			return
  1311  		}
  1312  
  1313  		// Send response msg back to chaincode.
  1314  		if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1315  			chaincodeLogger.Debugf("[%s]Completed %s. Sending %s", shorttxid(msg.Txid), msg.Type.String(), pb.ChaincodeMessage_RESPONSE)
  1316  		}
  1317  		triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: res, Txid: msg.Txid}
  1318  	}()
  1319  }
  1320  
  1321  func (handler *Handler) enterEstablishedState(e *fsm.Event, state string) {
  1322  	handler.notifyDuringStartup(true)
  1323  }
  1324  
  1325  func (handler *Handler) enterReadyState(e *fsm.Event, state string) {
  1326  	// Now notify
  1327  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
  1328  	if !ok {
  1329  		e.Cancel(fmt.Errorf("Received unexpected message type"))
  1330  		return
  1331  	}
  1332  	chaincodeLogger.Debugf("[%s]Entered state %s", shorttxid(msg.Txid), state)
  1333  	handler.notify(msg)
  1334  }
  1335  
  1336  func (handler *Handler) enterEndState(e *fsm.Event, state string) {
  1337  	defer handler.deregister()
  1338  	// Now notify
  1339  	msg, ok := e.Args[0].(*pb.ChaincodeMessage)
  1340  	if !ok {
  1341  		e.Cancel(fmt.Errorf("Received unexpected message type"))
  1342  		return
  1343  	}
  1344  	chaincodeLogger.Debugf("[%s]Entered state %s", shorttxid(msg.Txid), state)
  1345  	handler.notify(msg)
  1346  	e.Cancel(fmt.Errorf("Entered end state"))
  1347  }
  1348  
  1349  func (handler *Handler) setChaincodeProposal(signedProp *pb.SignedProposal, prop *pb.Proposal, msg *pb.ChaincodeMessage) error {
  1350  	chaincodeLogger.Debug("Setting chaincode proposal context...")
  1351  	if prop != nil {
  1352  		chaincodeLogger.Debug("Proposal different from nil. Creating chaincode proposal context...")
  1353  
  1354  		// Check that also signedProp is different from nil
  1355  		if signedProp == nil {
  1356  			return fmt.Errorf("Failed getting proposal context. Signed proposal is nil.")
  1357  		}
  1358  
  1359  		msg.Proposal = signedProp
  1360  	}
  1361  	return nil
  1362  }
  1363  
  1364  //move to ready
  1365  func (handler *Handler) ready(ctxt context.Context, chainID string, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) {
  1366  	txctx, funcErr := handler.createTxContext(ctxt, chainID, txid, signedProp, prop)
  1367  	if funcErr != nil {
  1368  		return nil, funcErr
  1369  	}
  1370  
  1371  	chaincodeLogger.Debug("sending READY")
  1372  	ccMsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: txid}
  1373  
  1374  	//if security is disabled the context elements will just be nil
  1375  	if err := handler.setChaincodeProposal(signedProp, prop, ccMsg); err != nil {
  1376  		return nil, err
  1377  	}
  1378  
  1379  	//send the ready synchronously as the
  1380  	//ready message is during launch and needs
  1381  	//to happen before any init/invokes can sneak in
  1382  	handler.triggerNextStateSync(ccMsg)
  1383  
  1384  	return txctx.responseNotifier, nil
  1385  }
  1386  
  1387  // HandleMessage implementation of MessageHandler interface.  Peer's handling of Chaincode messages.
  1388  func (handler *Handler) HandleMessage(msg *pb.ChaincodeMessage) error {
  1389  	chaincodeLogger.Debugf("[%s]Fabric side Handling ChaincodeMessage of type: %s in state %s", shorttxid(msg.Txid), msg.Type, handler.FSM.Current())
  1390  
  1391  	if (msg.Type == pb.ChaincodeMessage_COMPLETED || msg.Type == pb.ChaincodeMessage_ERROR) && handler.FSM.Current() == "ready" {
  1392  		chaincodeLogger.Debugf("[%s]HandleMessage- COMPLETED. Notify", msg.Txid)
  1393  		handler.notify(msg)
  1394  		return nil
  1395  	}
  1396  	if handler.FSM.Cannot(msg.Type.String()) {
  1397  		// Other errors
  1398  		return fmt.Errorf("[%s]Chaincode handler validator FSM cannot handle message (%s) with payload size (%d) while in state: %s", msg.Txid, msg.Type.String(), len(msg.Payload), handler.FSM.Current())
  1399  	}
  1400  	eventErr := handler.FSM.Event(msg.Type.String(), msg)
  1401  	filteredErr := filterError(eventErr)
  1402  	if filteredErr != nil {
  1403  		chaincodeLogger.Errorf("[%s]Failed to trigger FSM event %s: %s", msg.Txid, msg.Type.String(), filteredErr)
  1404  	}
  1405  
  1406  	return filteredErr
  1407  }
  1408  
  1409  // Filter the Errors to allow NoTransitionError and CanceledError to not propagate for cases where embedded Err == nil
  1410  func filterError(errFromFSMEvent error) error {
  1411  	if errFromFSMEvent != nil {
  1412  		if noTransitionErr, ok := errFromFSMEvent.(*fsm.NoTransitionError); ok {
  1413  			if noTransitionErr.Err != nil {
  1414  				// Squash the NoTransitionError
  1415  				return errFromFSMEvent
  1416  			}
  1417  			chaincodeLogger.Debugf("Ignoring NoTransitionError: %s", noTransitionErr)
  1418  		}
  1419  		if canceledErr, ok := errFromFSMEvent.(*fsm.CanceledError); ok {
  1420  			if canceledErr.Err != nil {
  1421  				// Squash the CanceledError
  1422  				return canceledErr
  1423  			}
  1424  			chaincodeLogger.Debugf("Ignoring CanceledError: %s", canceledErr)
  1425  		}
  1426  	}
  1427  	return nil
  1428  }
  1429  
  1430  func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *pb.ChaincodeMessage, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) {
  1431  	txctx, err := handler.createTxContext(ctxt, chainID, msg.Txid, signedProp, prop)
  1432  	if err != nil {
  1433  		return nil, err
  1434  	}
  1435  	if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
  1436  		chaincodeLogger.Debugf("[%s]Inside sendExecuteMessage. Message %s", shorttxid(msg.Txid), msg.Type.String())
  1437  	}
  1438  
  1439  	//if security is disabled the context elements will just be nil
  1440  	if err = handler.setChaincodeProposal(signedProp, prop, msg); err != nil {
  1441  		return nil, err
  1442  	}
  1443  
  1444  	chaincodeLogger.Debugf("[%s]sendExecuteMsg trigger event %s", shorttxid(msg.Txid), msg.Type)
  1445  	handler.triggerNextState(msg, true)
  1446  
  1447  	return txctx.responseNotifier, nil
  1448  }
  1449  
  1450  func (handler *Handler) isRunning() bool {
  1451  	switch handler.FSM.Current() {
  1452  	case createdstate:
  1453  		fallthrough
  1454  	case establishedstate:
  1455  		fallthrough
  1456  	default:
  1457  		return true
  1458  	}
  1459  }