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 }