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