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