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