github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/chaincode/shim/chaincode.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 shim provides APIs for the chaincode to access its state 18 // variables, transaction context and call other chaincodes. 19 package shim 20 21 import ( 22 "errors" 23 "flag" 24 "fmt" 25 "io" 26 "os" 27 "strings" 28 "unicode/utf8" 29 30 "github.com/golang/protobuf/proto" 31 "github.com/golang/protobuf/ptypes/timestamp" 32 "github.com/hyperledger/fabric/bccsp/factory" 33 "github.com/hyperledger/fabric/common/flogging" 34 commonledger "github.com/hyperledger/fabric/common/ledger" 35 "github.com/hyperledger/fabric/core/comm" 36 "github.com/hyperledger/fabric/protos/ledger/queryresult" 37 pb "github.com/hyperledger/fabric/protos/peer" 38 "github.com/hyperledger/fabric/protos/utils" 39 "github.com/op/go-logging" 40 "github.com/spf13/viper" 41 "golang.org/x/net/context" 42 "google.golang.org/grpc" 43 ) 44 45 // Logger for the shim package. 46 var chaincodeLogger = logging.MustGetLogger("shim") 47 var logOutput = os.Stderr 48 49 const ( 50 minUnicodeRuneValue = 0 //U+0000 51 maxUnicodeRuneValue = utf8.MaxRune //U+10FFFF - maximum (and unallocated) code point 52 compositeKeyNamespace = "\x00" 53 emptyKeySubstitute = "\x01" 54 ) 55 56 // ChaincodeStub is an object passed to chaincode for shim side handling of 57 // APIs. 58 type ChaincodeStub struct { 59 TxID string 60 chaincodeEvent *pb.ChaincodeEvent 61 args [][]byte 62 handler *Handler 63 signedProposal *pb.SignedProposal 64 proposal *pb.Proposal 65 66 // Additional fields extracted from the signedProposal 67 creator []byte 68 transient map[string][]byte 69 binding []byte 70 } 71 72 // Peer address derived from command line or env var 73 var peerAddress string 74 75 //this separates the chaincode stream interface establishment 76 //so we can replace it with a mock peer stream 77 type peerStreamGetter func(name string) (PeerChaincodeStream, error) 78 79 //UTs to setup mock peer stream getter 80 var streamGetter peerStreamGetter 81 82 //the non-mock user CC stream establishment func 83 func userChaincodeStreamGetter(name string) (PeerChaincodeStream, error) { 84 flag.StringVar(&peerAddress, "peer.address", "", "peer address") 85 86 flag.Parse() 87 88 chaincodeLogger.Debugf("Peer address: %s", getPeerAddress()) 89 90 // Establish connection with validating peer 91 clientConn, err := newPeerClientConnection() 92 if err != nil { 93 chaincodeLogger.Errorf("Error trying to connect to local peer: %s", err) 94 return nil, fmt.Errorf("Error trying to connect to local peer: %s", err) 95 } 96 97 chaincodeLogger.Debugf("os.Args returns: %s", os.Args) 98 99 chaincodeSupportClient := pb.NewChaincodeSupportClient(clientConn) 100 101 // Establish stream with validating peer 102 stream, err := chaincodeSupportClient.Register(context.Background()) 103 if err != nil { 104 return nil, fmt.Errorf("Error chatting with leader at address=%s: %s", getPeerAddress(), err) 105 } 106 107 return stream, nil 108 } 109 110 // chaincodes. 111 func Start(cc Chaincode) error { 112 // If Start() is called, we assume this is a standalone chaincode and set 113 // up formatted logging. 114 SetupChaincodeLogging() 115 116 chaincodename := viper.GetString("chaincode.id.name") 117 if chaincodename == "" { 118 return fmt.Errorf("Error chaincode id not provided") 119 } 120 121 err := factory.InitFactories(factory.GetDefaultOpts()) 122 if err != nil { 123 return fmt.Errorf("Internal error, BCCSP could not be initialized with default options: %s", err) 124 } 125 126 //mock stream not set up ... get real stream 127 if streamGetter == nil { 128 streamGetter = userChaincodeStreamGetter 129 } 130 131 stream, err := streamGetter(chaincodename) 132 if err != nil { 133 return err 134 } 135 136 err = chatWithPeer(chaincodename, stream, cc) 137 138 return err 139 } 140 141 // IsEnabledForLogLevel checks to see if the chaincodeLogger is enabled for a specific logging level 142 // used primarily for testing 143 func IsEnabledForLogLevel(logLevel string) bool { 144 lvl, _ := logging.LogLevel(logLevel) 145 return chaincodeLogger.IsEnabledFor(lvl) 146 } 147 148 // SetupChaincodeLogging sets the chaincode logging format and the level 149 // to the values of CORE_CHAINCODE_LOGFORMAT and CORE_CHAINCODE_LOGLEVEL set 150 // from core.yaml by chaincode_support.go 151 func SetupChaincodeLogging() { 152 viper.SetEnvPrefix("CORE") 153 viper.AutomaticEnv() 154 replacer := strings.NewReplacer(".", "_") 155 viper.SetEnvKeyReplacer(replacer) 156 157 // setup system-wide logging backend 158 logFormat := flogging.SetFormat(viper.GetString("chaincode.logging.format")) 159 flogging.InitBackend(logFormat, logOutput) 160 161 // set default log level for all modules 162 chaincodeLogLevelString := viper.GetString("chaincode.logging.level") 163 if chaincodeLogLevelString == "" { 164 chaincodeLogger.Infof("Chaincode log level not provided; defaulting to: %s", flogging.DefaultLevel()) 165 flogging.InitFromSpec(flogging.DefaultLevel()) 166 } else { 167 _, err := LogLevel(chaincodeLogLevelString) 168 if err == nil { 169 flogging.InitFromSpec(chaincodeLogLevelString) 170 } else { 171 chaincodeLogger.Warningf("Error: '%s' for chaincode log level: %s; defaulting to %s", err, chaincodeLogLevelString, flogging.DefaultLevel()) 172 flogging.InitFromSpec(flogging.DefaultLevel()) 173 } 174 } 175 176 // override the log level for the shim logging module - note: if this value is 177 // blank or an invalid log level, then the above call to 178 // `flogging.InitFromSpec` already set the default log level so no action 179 // is required here. 180 shimLogLevelString := viper.GetString("chaincode.logging.shim") 181 if shimLogLevelString != "" { 182 shimLogLevel, err := LogLevel(shimLogLevelString) 183 if err == nil { 184 SetLoggingLevel(shimLogLevel) 185 } else { 186 chaincodeLogger.Warningf("Error: %s for shim log level: %s", err, shimLogLevelString) 187 } 188 } 189 190 //now that logging is setup, print build level. This will help making sure 191 //chaincode is matched with peer. 192 buildLevel := viper.GetString("chaincode.buildlevel") 193 chaincodeLogger.Infof("Chaincode (build level: %s) starting up ...", buildLevel) 194 } 195 196 // StartInProc is an entry point for system chaincodes bootstrap. It is not an 197 // API for chaincodes. 198 func StartInProc(env []string, args []string, cc Chaincode, recv <-chan *pb.ChaincodeMessage, send chan<- *pb.ChaincodeMessage) error { 199 chaincodeLogger.Debugf("in proc %v", args) 200 201 var chaincodename string 202 for _, v := range env { 203 if strings.Index(v, "CORE_CHAINCODE_ID_NAME=") == 0 { 204 p := strings.SplitAfter(v, "CORE_CHAINCODE_ID_NAME=") 205 chaincodename = p[1] 206 break 207 } 208 } 209 if chaincodename == "" { 210 return fmt.Errorf("Error chaincode id not provided") 211 } 212 213 stream := newInProcStream(recv, send) 214 chaincodeLogger.Debugf("starting chat with peer using name=%s", chaincodename) 215 err := chatWithPeer(chaincodename, stream, cc) 216 return err 217 } 218 219 func getPeerAddress() string { 220 if peerAddress != "" { 221 return peerAddress 222 } 223 224 if peerAddress = viper.GetString("peer.address"); peerAddress == "" { 225 chaincodeLogger.Fatalf("peer.address not configured, can't connect to peer") 226 } 227 228 return peerAddress 229 } 230 231 func newPeerClientConnection() (*grpc.ClientConn, error) { 232 var peerAddress = getPeerAddress() 233 if comm.TLSEnabled() { 234 return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer()) 235 } 236 return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil) 237 } 238 239 func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode) error { 240 241 // Create the shim handler responsible for all control logic 242 handler := newChaincodeHandler(stream, cc) 243 244 defer stream.CloseSend() 245 // Send the ChaincodeID during register. 246 chaincodeID := &pb.ChaincodeID{Name: chaincodename} 247 payload, err := proto.Marshal(chaincodeID) 248 if err != nil { 249 return fmt.Errorf("Error marshalling chaincodeID during chaincode registration: %s", err) 250 } 251 // Register on the stream 252 chaincodeLogger.Debugf("Registering.. sending %s", pb.ChaincodeMessage_REGISTER) 253 if err = handler.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: payload}); err != nil { 254 return fmt.Errorf("Error sending chaincode REGISTER: %s", err) 255 } 256 waitc := make(chan struct{}) 257 errc := make(chan error) 258 go func() { 259 defer close(waitc) 260 msgAvail := make(chan *pb.ChaincodeMessage) 261 var nsInfo *nextStateInfo 262 var in *pb.ChaincodeMessage 263 recv := true 264 for { 265 in = nil 266 err = nil 267 nsInfo = nil 268 if recv { 269 recv = false 270 go func() { 271 var in2 *pb.ChaincodeMessage 272 in2, err = stream.Recv() 273 msgAvail <- in2 274 }() 275 } 276 select { 277 case sendErr := <-errc: 278 //serialSendAsync successful? 279 if sendErr == nil { 280 continue 281 } 282 //no, bail 283 err = fmt.Errorf("Error sending %s: %s", in.Type.String(), sendErr) 284 return 285 case in = <-msgAvail: 286 if err == io.EOF { 287 chaincodeLogger.Debugf("Received EOF, ending chaincode stream, %s", err) 288 return 289 } else if err != nil { 290 chaincodeLogger.Errorf("Received error from server: %s, ending chaincode stream", err) 291 return 292 } else if in == nil { 293 err = fmt.Errorf("Received nil message, ending chaincode stream") 294 chaincodeLogger.Debug("Received nil message, ending chaincode stream") 295 return 296 } 297 chaincodeLogger.Debugf("[%s]Received message %s from shim", shorttxid(in.Txid), in.Type.String()) 298 recv = true 299 case nsInfo = <-handler.nextState: 300 in = nsInfo.msg 301 if in == nil { 302 panic("nil msg") 303 } 304 chaincodeLogger.Debugf("[%s]Move state message %s", shorttxid(in.Txid), in.Type.String()) 305 } 306 307 // Call FSM.handleMessage() 308 err = handler.handleMessage(in) 309 if err != nil { 310 err = fmt.Errorf("Error handling message: %s", err) 311 return 312 } 313 314 //keepalive messages are PONGs to the fabric's PINGs 315 if in.Type == pb.ChaincodeMessage_KEEPALIVE { 316 chaincodeLogger.Debug("Sending KEEPALIVE response") 317 //ignore any errors, maybe next KEEPALIVE will work 318 handler.serialSendAsync(in, nil) 319 } else if nsInfo != nil && nsInfo.sendToCC { 320 chaincodeLogger.Debugf("[%s]send state message %s", shorttxid(in.Txid), in.Type.String()) 321 handler.serialSendAsync(in, errc) 322 } 323 } 324 }() 325 <-waitc 326 return err 327 } 328 329 // -- init stub --- 330 // ChaincodeInvocation functionality 331 332 func (stub *ChaincodeStub) init(handler *Handler, txid string, input *pb.ChaincodeInput, signedProposal *pb.SignedProposal) error { 333 stub.TxID = txid 334 stub.args = input.Args 335 stub.handler = handler 336 stub.signedProposal = signedProposal 337 338 // TODO: sanity check: verify that every call to init with a nil 339 // signedProposal is a legitimate one, meaning it is an internal call 340 // to system chaincodes. 341 if signedProposal != nil { 342 var err error 343 344 stub.proposal, err = utils.GetProposal(signedProposal.ProposalBytes) 345 if err != nil { 346 return fmt.Errorf("Failed extracting signedProposal from signed signedProposal. [%s]", err) 347 } 348 349 // Extract creator, transient, binding... 350 stub.creator, stub.transient, err = utils.GetChaincodeProposalContext(stub.proposal) 351 if err != nil { 352 return fmt.Errorf("Failed extracting signedProposal fields. [%s]", err) 353 } 354 355 stub.binding, err = utils.ComputeProposalBinding(stub.proposal) 356 if err != nil { 357 return fmt.Errorf("Failed computing binding from signedProposal. [%s]", err) 358 } 359 } 360 361 return nil 362 } 363 364 // GetTxID returns the transaction ID 365 func (stub *ChaincodeStub) GetTxID() string { 366 return stub.TxID 367 } 368 369 // --------- Security functions ---------- 370 //CHAINCODE SEC INTERFACE FUNCS TOBE IMPLEMENTED BY ANGELO 371 372 // ------------- Call Chaincode functions --------------- 373 374 // InvokeChaincode documentation can be found in interfaces.go 375 func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response { 376 // Internally we handle chaincode name as a composite name 377 if channel != "" { 378 chaincodeName = chaincodeName + "/" + channel 379 } 380 return stub.handler.handleInvokeChaincode(chaincodeName, args, stub.TxID) 381 } 382 383 // --------- State functions ---------- 384 385 // GetState documentation can be found in interfaces.go 386 func (stub *ChaincodeStub) GetState(key string) ([]byte, error) { 387 return stub.handler.handleGetState(key, stub.TxID) 388 } 389 390 // PutState documentation can be found in interfaces.go 391 func (stub *ChaincodeStub) PutState(key string, value []byte) error { 392 if key == "" { 393 return fmt.Errorf("key must not be an empty string") 394 } 395 return stub.handler.handlePutState(key, value, stub.TxID) 396 } 397 398 // DelState documentation can be found in interfaces.go 399 func (stub *ChaincodeStub) DelState(key string) error { 400 return stub.handler.handleDelState(key, stub.TxID) 401 } 402 403 // CommonIterator documentation can be found in interfaces.go 404 type CommonIterator struct { 405 handler *Handler 406 uuid string 407 response *pb.QueryResponse 408 currentLoc int 409 } 410 411 // StateQueryIterator documentation can be found in interfaces.go 412 type StateQueryIterator struct { 413 *CommonIterator 414 } 415 416 // HistoryQueryIterator documentation can be found in interfaces.go 417 type HistoryQueryIterator struct { 418 *CommonIterator 419 } 420 421 type resultType uint8 422 423 const ( 424 STATE_QUERY_RESULT resultType = iota + 1 425 HISTORY_QUERY_RESULT 426 ) 427 428 func (stub *ChaincodeStub) handleGetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) { 429 response, err := stub.handler.handleGetStateByRange(startKey, endKey, stub.TxID) 430 if err != nil { 431 return nil, err 432 } 433 return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil 434 } 435 436 // GetStateByRange documentation can be found in interfaces.go 437 func (stub *ChaincodeStub) GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) { 438 if startKey == "" { 439 startKey = emptyKeySubstitute 440 } 441 if err := validateSimpleKeys(startKey, endKey); err != nil { 442 return nil, err 443 } 444 return stub.handleGetStateByRange(startKey, endKey) 445 } 446 447 // GetQueryResult documentation can be found in interfaces.go 448 func (stub *ChaincodeStub) GetQueryResult(query string) (StateQueryIteratorInterface, error) { 449 response, err := stub.handler.handleGetQueryResult(query, stub.TxID) 450 if err != nil { 451 return nil, err 452 } 453 return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil 454 } 455 456 // GetHistoryForKey documentation can be found in interfaces.go 457 func (stub *ChaincodeStub) GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error) { 458 response, err := stub.handler.handleGetHistoryForKey(key, stub.TxID) 459 if err != nil { 460 return nil, err 461 } 462 return &HistoryQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil 463 } 464 465 //CreateCompositeKey documentation can be found in interfaces.go 466 func (stub *ChaincodeStub) CreateCompositeKey(objectType string, attributes []string) (string, error) { 467 return createCompositeKey(objectType, attributes) 468 } 469 470 //SplitCompositeKey documentation can be found in interfaces.go 471 func (stub *ChaincodeStub) SplitCompositeKey(compositeKey string) (string, []string, error) { 472 return splitCompositeKey(compositeKey) 473 } 474 475 func createCompositeKey(objectType string, attributes []string) (string, error) { 476 if err := validateCompositeKeyAttribute(objectType); err != nil { 477 return "", err 478 } 479 ck := compositeKeyNamespace + objectType + string(minUnicodeRuneValue) 480 for _, att := range attributes { 481 if err := validateCompositeKeyAttribute(att); err != nil { 482 return "", err 483 } 484 ck += att + string(minUnicodeRuneValue) 485 } 486 return ck, nil 487 } 488 489 func splitCompositeKey(compositeKey string) (string, []string, error) { 490 componentIndex := 1 491 components := []string{} 492 for i := 1; i < len(compositeKey); i++ { 493 if compositeKey[i] == minUnicodeRuneValue { 494 components = append(components, compositeKey[componentIndex:i]) 495 componentIndex = i + 1 496 } 497 } 498 return components[0], components[1:], nil 499 } 500 501 func validateCompositeKeyAttribute(str string) error { 502 if !utf8.ValidString(str) { 503 return fmt.Errorf("Not a valid utf8 string: [%x]", str) 504 } 505 for index, runeValue := range str { 506 if runeValue == minUnicodeRuneValue || runeValue == maxUnicodeRuneValue { 507 return fmt.Errorf(`Input contain unicode %#U starting at position [%d]. %#U and %#U are not allowed in the input attribute of a composite key`, 508 runeValue, index, minUnicodeRuneValue, maxUnicodeRuneValue) 509 } 510 } 511 return nil 512 } 513 514 //To ensure that simple keys do not go into composite key namespace, 515 //we validate simplekey to check whether the key starts with 0x00 (which 516 //is the namespace for compositeKey). This helps in avoding simple/composite 517 //key collisions. 518 func validateSimpleKeys(simpleKeys ...string) error { 519 for _, key := range simpleKeys { 520 if len(key) > 0 && key[0] == compositeKeyNamespace[0] { 521 return fmt.Errorf(`First character of the key [%s] contains a null character which is not allowed`, key) 522 } 523 } 524 return nil 525 } 526 527 //GetStateByPartialCompositeKey function can be invoked by a chaincode to query the 528 //state based on a given partial composite key. This function returns an 529 //iterator which can be used to iterate over all composite keys whose prefix 530 //matches the given partial composite key. This function should be used only for 531 //a partial composite key. For a full composite key, an iter with empty response 532 //would be returned. 533 func (stub *ChaincodeStub) GetStateByPartialCompositeKey(objectType string, attributes []string) (StateQueryIteratorInterface, error) { 534 if partialCompositeKey, err := stub.CreateCompositeKey(objectType, attributes); err == nil { 535 return stub.handleGetStateByRange(partialCompositeKey, partialCompositeKey+string(maxUnicodeRuneValue)) 536 } else { 537 return nil, err 538 } 539 } 540 541 func (iter *StateQueryIterator) Next() (*queryresult.KV, error) { 542 if result, err := iter.nextResult(STATE_QUERY_RESULT); err == nil { 543 return result.(*queryresult.KV), err 544 } else { 545 return nil, err 546 } 547 } 548 549 func (iter *HistoryQueryIterator) Next() (*queryresult.KeyModification, error) { 550 if result, err := iter.nextResult(HISTORY_QUERY_RESULT); err == nil { 551 return result.(*queryresult.KeyModification), err 552 } else { 553 return nil, err 554 } 555 } 556 557 // HasNext documentation can be found in interfaces.go 558 func (iter *CommonIterator) HasNext() bool { 559 if iter.currentLoc < len(iter.response.Results) || iter.response.HasMore { 560 return true 561 } 562 return false 563 } 564 565 // getResultsFromBytes deserializes QueryResult and return either a KV struct 566 // or KeyModification depending on the result type (i.e., state (range/execute) 567 // query, history query). Note that commonledger.QueryResult is an empty golang 568 // interface that can hold values of any type. 569 func (iter *CommonIterator) getResultFromBytes(queryResultBytes *pb.QueryResultBytes, 570 rType resultType) (commonledger.QueryResult, error) { 571 572 if rType == STATE_QUERY_RESULT { 573 stateQueryResult := &queryresult.KV{} 574 if err := proto.Unmarshal(queryResultBytes.ResultBytes, stateQueryResult); err != nil { 575 return nil, err 576 } 577 return stateQueryResult, nil 578 579 } else if rType == HISTORY_QUERY_RESULT { 580 historyQueryResult := &queryresult.KeyModification{} 581 if err := proto.Unmarshal(queryResultBytes.ResultBytes, historyQueryResult); err != nil { 582 return nil, err 583 } 584 return historyQueryResult, nil 585 } 586 return nil, errors.New("Wrong result type") 587 } 588 589 func (iter *CommonIterator) fetchNextQueryResult() error { 590 if response, err := iter.handler.handleQueryStateNext(iter.response.Id, iter.uuid); err == nil { 591 iter.currentLoc = 0 592 iter.response = response 593 return nil 594 } else { 595 return err 596 } 597 } 598 599 // nextResult returns the next QueryResult (i.e., either a KV struct or KeyModification) 600 // from the state or history query iterator. Note that commonledger.QueryResult is an 601 // empty golang interface that can hold values of any type. 602 func (iter *CommonIterator) nextResult(rType resultType) (commonledger.QueryResult, error) { 603 if iter.currentLoc < len(iter.response.Results) { 604 // On valid access of an element from cached results 605 queryResult, err := iter.getResultFromBytes(iter.response.Results[iter.currentLoc], rType) 606 if err != nil { 607 chaincodeLogger.Errorf("Failed to decode query results [%s]", err) 608 return nil, err 609 } 610 iter.currentLoc++ 611 612 if iter.currentLoc == len(iter.response.Results) && iter.response.HasMore { 613 // On access of last item, pre-fetch to update HasMore flag 614 if err = iter.fetchNextQueryResult(); err != nil { 615 chaincodeLogger.Errorf("Failed to fetch next results [%s]", err) 616 return nil, err 617 } 618 } 619 620 return queryResult, err 621 } else if !iter.response.HasMore { 622 // On call to Next() without check of HasMore 623 return nil, errors.New("No such key") 624 } 625 626 // should not fall through here 627 // case: no cached results but HasMore is true. 628 return nil, errors.New("Invalid iterator state") 629 } 630 631 // Close documentation can be found in interfaces.go 632 func (iter *CommonIterator) Close() error { 633 _, err := iter.handler.handleQueryStateClose(iter.response.Id, iter.uuid) 634 return err 635 } 636 637 // GetArgs documentation can be found in interfaces.go 638 func (stub *ChaincodeStub) GetArgs() [][]byte { 639 return stub.args 640 } 641 642 // GetStringArgs documentation can be found in interfaces.go 643 func (stub *ChaincodeStub) GetStringArgs() []string { 644 args := stub.GetArgs() 645 strargs := make([]string, 0, len(args)) 646 for _, barg := range args { 647 strargs = append(strargs, string(barg)) 648 } 649 return strargs 650 } 651 652 // GetFunctionAndParameters documentation can be found in interfaces.go 653 func (stub *ChaincodeStub) GetFunctionAndParameters() (function string, params []string) { 654 allargs := stub.GetStringArgs() 655 function = "" 656 params = []string{} 657 if len(allargs) >= 1 { 658 function = allargs[0] 659 params = allargs[1:] 660 } 661 return 662 } 663 664 // GetCreator documentation can be found in interfaces.go 665 func (stub *ChaincodeStub) GetCreator() ([]byte, error) { 666 return stub.creator, nil 667 } 668 669 // GetTransient documentation can be found in interfaces.go 670 func (stub *ChaincodeStub) GetTransient() (map[string][]byte, error) { 671 return stub.transient, nil 672 } 673 674 // GetBinding documentation can be found in interfaces.go 675 func (stub *ChaincodeStub) GetBinding() ([]byte, error) { 676 return stub.binding, nil 677 } 678 679 // GetSignedProposal documentation can be found in interfaces.go 680 func (stub *ChaincodeStub) GetSignedProposal() (*pb.SignedProposal, error) { 681 return stub.signedProposal, nil 682 } 683 684 // GetArgsSlice documentation can be found in interfaces.go 685 func (stub *ChaincodeStub) GetArgsSlice() ([]byte, error) { 686 args := stub.GetArgs() 687 res := []byte{} 688 for _, barg := range args { 689 res = append(res, barg...) 690 } 691 return res, nil 692 } 693 694 // GetTxTimestamp documentation can be found in interfaces.go 695 func (stub *ChaincodeStub) GetTxTimestamp() (*timestamp.Timestamp, error) { 696 hdr, err := utils.GetHeader(stub.proposal.Header) 697 if err != nil { 698 return nil, err 699 } 700 chdr, err := utils.UnmarshalChannelHeader(hdr.ChannelHeader) 701 if err != nil { 702 return nil, err 703 } 704 705 return chdr.GetTimestamp(), nil 706 } 707 708 // ------------- ChaincodeEvent API ---------------------- 709 710 // SetEvent documentation can be found in interfaces.go 711 func (stub *ChaincodeStub) SetEvent(name string, payload []byte) error { 712 if name == "" { 713 return errors.New("Event name can not be nil string.") 714 } 715 stub.chaincodeEvent = &pb.ChaincodeEvent{EventName: name, Payload: payload} 716 return nil 717 } 718 719 // ------------- Logging Control and Chaincode Loggers --------------- 720 721 // As independent programs, Go language chaincodes can use any logging 722 // methodology they choose, from simple fmt.Printf() to os.Stdout, to 723 // decorated logs created by the author's favorite logging package. The 724 // chaincode "shim" interface, however, is defined by the Hyperledger fabric 725 // and implements its own logging methodology. This methodology currently 726 // includes severity-based logging control and a standard way of decorating 727 // the logs. 728 // 729 // The facilities defined here allow a Go language chaincode to control the 730 // logging level of its shim, and to create its own logs formatted 731 // consistently with, and temporally interleaved with the shim logs without 732 // any knowledge of the underlying implementation of the shim, and without any 733 // other package requirements. The lack of package requirements is especially 734 // important because even if the chaincode happened to explicitly use the same 735 // logging package as the shim, unless the chaincode is physically included as 736 // part of the hyperledger fabric source code tree it could actually end up 737 // using a distinct binary instance of the logging package, with different 738 // formats and severity levels than the binary package used by the shim. 739 // 740 // Another approach that might have been taken, and could potentially be taken 741 // in the future, would be for the chaincode to supply a logging object for 742 // the shim to use, rather than the other way around as implemented 743 // here. There would be some complexities associated with that approach, so 744 // for the moment we have chosen the simpler implementation below. The shim 745 // provides one or more abstract logging objects for the chaincode to use via 746 // the NewLogger() API, and allows the chaincode to control the severity level 747 // of shim logs using the SetLoggingLevel() API. 748 749 // LoggingLevel is an enumerated type of severity levels that control 750 // chaincode logging. 751 type LoggingLevel logging.Level 752 753 // These constants comprise the LoggingLevel enumeration 754 const ( 755 LogDebug = LoggingLevel(logging.DEBUG) 756 LogInfo = LoggingLevel(logging.INFO) 757 LogNotice = LoggingLevel(logging.NOTICE) 758 LogWarning = LoggingLevel(logging.WARNING) 759 LogError = LoggingLevel(logging.ERROR) 760 LogCritical = LoggingLevel(logging.CRITICAL) 761 ) 762 763 var shimLoggingLevel = LogInfo // Necessary for correct initialization; See Start() 764 765 // SetLoggingLevel allows a Go language chaincode to set the logging level of 766 // its shim. 767 func SetLoggingLevel(level LoggingLevel) { 768 shimLoggingLevel = level 769 logging.SetLevel(logging.Level(level), "shim") 770 } 771 772 // LogLevel converts a case-insensitive string chosen from CRITICAL, ERROR, 773 // WARNING, NOTICE, INFO or DEBUG into an element of the LoggingLevel 774 // type. In the event of errors the level returned is LogError. 775 func LogLevel(levelString string) (LoggingLevel, error) { 776 l, err := logging.LogLevel(levelString) 777 level := LoggingLevel(l) 778 if err != nil { 779 level = LogError 780 } 781 return level, err 782 } 783 784 // ------------- Chaincode Loggers --------------- 785 786 // ChaincodeLogger is an abstraction of a logging object for use by 787 // chaincodes. These objects are created by the NewLogger API. 788 type ChaincodeLogger struct { 789 logger *logging.Logger 790 } 791 792 // NewLogger allows a Go language chaincode to create one or more logging 793 // objects whose logs will be formatted consistently with, and temporally 794 // interleaved with the logs created by the shim interface. The logs created 795 // by this object can be distinguished from shim logs by the name provided, 796 // which will appear in the logs. 797 func NewLogger(name string) *ChaincodeLogger { 798 return &ChaincodeLogger{logging.MustGetLogger(name)} 799 } 800 801 // SetLevel sets the logging level for a chaincode logger. Note that currently 802 // the levels are actually controlled by the name given when the logger is 803 // created, so loggers should be given unique names other than "shim". 804 func (c *ChaincodeLogger) SetLevel(level LoggingLevel) { 805 logging.SetLevel(logging.Level(level), c.logger.Module) 806 } 807 808 // IsEnabledFor returns true if the logger is enabled to creates logs at the 809 // given logging level. 810 func (c *ChaincodeLogger) IsEnabledFor(level LoggingLevel) bool { 811 return c.logger.IsEnabledFor(logging.Level(level)) 812 } 813 814 // Debug logs will only appear if the ChaincodeLogger LoggingLevel is set to 815 // LogDebug. 816 func (c *ChaincodeLogger) Debug(args ...interface{}) { 817 c.logger.Debug(args...) 818 } 819 820 // Info logs will appear if the ChaincodeLogger LoggingLevel is set to 821 // LogInfo or LogDebug. 822 func (c *ChaincodeLogger) Info(args ...interface{}) { 823 c.logger.Info(args...) 824 } 825 826 // Notice logs will appear if the ChaincodeLogger LoggingLevel is set to 827 // LogNotice, LogInfo or LogDebug. 828 func (c *ChaincodeLogger) Notice(args ...interface{}) { 829 c.logger.Notice(args...) 830 } 831 832 // Warning logs will appear if the ChaincodeLogger LoggingLevel is set to 833 // LogWarning, LogNotice, LogInfo or LogDebug. 834 func (c *ChaincodeLogger) Warning(args ...interface{}) { 835 c.logger.Warning(args...) 836 } 837 838 // Error logs will appear if the ChaincodeLogger LoggingLevel is set to 839 // LogError, LogWarning, LogNotice, LogInfo or LogDebug. 840 func (c *ChaincodeLogger) Error(args ...interface{}) { 841 c.logger.Error(args...) 842 } 843 844 // Critical logs always appear; They can not be disabled. 845 func (c *ChaincodeLogger) Critical(args ...interface{}) { 846 c.logger.Critical(args...) 847 } 848 849 // Debugf logs will only appear if the ChaincodeLogger LoggingLevel is set to 850 // LogDebug. 851 func (c *ChaincodeLogger) Debugf(format string, args ...interface{}) { 852 c.logger.Debugf(format, args...) 853 } 854 855 // Infof logs will appear if the ChaincodeLogger LoggingLevel is set to 856 // LogInfo or LogDebug. 857 func (c *ChaincodeLogger) Infof(format string, args ...interface{}) { 858 c.logger.Infof(format, args...) 859 } 860 861 // Noticef logs will appear if the ChaincodeLogger LoggingLevel is set to 862 // LogNotice, LogInfo or LogDebug. 863 func (c *ChaincodeLogger) Noticef(format string, args ...interface{}) { 864 c.logger.Noticef(format, args...) 865 } 866 867 // Warningf logs will appear if the ChaincodeLogger LoggingLevel is set to 868 // LogWarning, LogNotice, LogInfo or LogDebug. 869 func (c *ChaincodeLogger) Warningf(format string, args ...interface{}) { 870 c.logger.Warningf(format, args...) 871 } 872 873 // Errorf logs will appear if the ChaincodeLogger LoggingLevel is set to 874 // LogError, LogWarning, LogNotice, LogInfo or LogDebug. 875 func (c *ChaincodeLogger) Errorf(format string, args ...interface{}) { 876 c.logger.Errorf(format, args...) 877 } 878 879 // Criticalf logs always appear; They can not be disabled. 880 func (c *ChaincodeLogger) Criticalf(format string, args ...interface{}) { 881 c.logger.Criticalf(format, args...) 882 }