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