github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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/core/comm"
    34  	pb "github.com/hyperledger/fabric/protos/peer"
    35  	"github.com/hyperledger/fabric/protos/utils"
    36  	"github.com/op/go-logging"
    37  	"github.com/spf13/viper"
    38  	"golang.org/x/net/context"
    39  	"google.golang.org/grpc"
    40  )
    41  
    42  // Logger for the shim package.
    43  var chaincodeLogger = logging.MustGetLogger("shim")
    44  
    45  const (
    46  	minUnicodeRuneValue = 0            //U+0000
    47  	maxUnicodeRuneValue = utf8.MaxRune //U+10FFFF - maximum (and unallocated) code point
    48  )
    49  
    50  // ChaincodeStub is an object passed to chaincode for shim side handling of
    51  // APIs.
    52  type ChaincodeStub struct {
    53  	TxID           string
    54  	chaincodeEvent *pb.ChaincodeEvent
    55  	args           [][]byte
    56  	handler        *Handler
    57  	proposal       *pb.Proposal
    58  
    59  	// Additional fields extracted from the proposal
    60  	creator   []byte
    61  	transient map[string][]byte
    62  	binding   []byte
    63  }
    64  
    65  // Peer address derived from command line or env var
    66  var peerAddress string
    67  
    68  // Start is the entry point for chaincodes bootstrap. It is not an API for
    69  // chaincodes.
    70  func Start(cc Chaincode) error {
    71  	// If Start() is called, we assume this is a standalone chaincode and set
    72  	// up formatted logging.
    73  	format := logging.MustStringFormatter("%{time:15:04:05.000} [%{module}] %{level:.4s} : %{message}")
    74  	backend := logging.NewLogBackend(os.Stderr, "", 0)
    75  	backendFormatter := logging.NewBackendFormatter(backend, format)
    76  	logging.SetBackend(backendFormatter).SetLevel(logging.Level(shimLoggingLevel), "shim")
    77  
    78  	SetChaincodeLoggingLevel()
    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  // SetChaincodeLoggingLevel sets the chaincode logging level to the value
   125  // of CORE_LOGGING_CHAINCODE set from core.yaml by chaincode_support.go
   126  func SetChaincodeLoggingLevel() {
   127  	viper.SetEnvPrefix("CORE")
   128  	viper.AutomaticEnv()
   129  	replacer := strings.NewReplacer(".", "_")
   130  	viper.SetEnvKeyReplacer(replacer)
   131  
   132  	chaincodeLogLevelString := viper.GetString("logging.chaincode")
   133  	if chaincodeLogLevelString == "" {
   134  		shimLogLevelDefault := logging.Level(shimLoggingLevel)
   135  		chaincodeLogger.Infof("Chaincode log level not provided; defaulting to: %s", shimLogLevelDefault)
   136  	} else {
   137  		chaincodeLogLevel, err := LogLevel(chaincodeLogLevelString)
   138  		if err == nil {
   139  			SetLoggingLevel(chaincodeLogLevel)
   140  		} else {
   141  			chaincodeLogger.Warningf("Error: %s for chaincode log level: %s", err, chaincodeLogLevelString)
   142  		}
   143  	}
   144  
   145  }
   146  
   147  // StartInProc is an entry point for system chaincodes bootstrap. It is not an
   148  // API for chaincodes.
   149  func StartInProc(env []string, args []string, cc Chaincode, recv <-chan *pb.ChaincodeMessage, send chan<- *pb.ChaincodeMessage) error {
   150  	chaincodeLogger.Debugf("in proc %v", args)
   151  
   152  	var chaincodename string
   153  	for _, v := range env {
   154  		if strings.Index(v, "CORE_CHAINCODE_ID_NAME=") == 0 {
   155  			p := strings.SplitAfter(v, "CORE_CHAINCODE_ID_NAME=")
   156  			chaincodename = p[1]
   157  			break
   158  		}
   159  	}
   160  	if chaincodename == "" {
   161  		return fmt.Errorf("Error chaincode id not provided")
   162  	}
   163  	chaincodeLogger.Debugf("starting chat with peer using name=%s", chaincodename)
   164  	stream := newInProcStream(recv, send)
   165  	err := chatWithPeer(chaincodename, stream, cc)
   166  	return err
   167  }
   168  
   169  func getPeerAddress() string {
   170  	if peerAddress != "" {
   171  		return peerAddress
   172  	}
   173  
   174  	if peerAddress = viper.GetString("peer.address"); peerAddress == "" {
   175  		chaincodeLogger.Fatalf("peer.address not configured, can't connect to peer")
   176  	}
   177  
   178  	return peerAddress
   179  }
   180  
   181  func newPeerClientConnection() (*grpc.ClientConn, error) {
   182  	var peerAddress = getPeerAddress()
   183  	if comm.TLSEnabled() {
   184  		return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer())
   185  	}
   186  	return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil)
   187  }
   188  
   189  func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode) error {
   190  
   191  	// Create the shim handler responsible for all control logic
   192  	handler := newChaincodeHandler(stream, cc)
   193  
   194  	defer stream.CloseSend()
   195  	// Send the ChaincodeID during register.
   196  	chaincodeID := &pb.ChaincodeID{Name: chaincodename}
   197  	payload, err := proto.Marshal(chaincodeID)
   198  	if err != nil {
   199  		return fmt.Errorf("Error marshalling chaincodeID during chaincode registration: %s", err)
   200  	}
   201  	// Register on the stream
   202  	chaincodeLogger.Debugf("Registering.. sending %s", pb.ChaincodeMessage_REGISTER)
   203  	if err = handler.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: payload}); err != nil {
   204  		return fmt.Errorf("Error sending chaincode REGISTER: %s", err)
   205  	}
   206  	waitc := make(chan struct{})
   207  	errc := make(chan error)
   208  	go func() {
   209  		defer close(waitc)
   210  		msgAvail := make(chan *pb.ChaincodeMessage)
   211  		var nsInfo *nextStateInfo
   212  		var in *pb.ChaincodeMessage
   213  		recv := true
   214  		for {
   215  			in = nil
   216  			err = nil
   217  			nsInfo = nil
   218  			if recv {
   219  				recv = false
   220  				go func() {
   221  					var in2 *pb.ChaincodeMessage
   222  					in2, err = stream.Recv()
   223  					msgAvail <- in2
   224  				}()
   225  			}
   226  			select {
   227  			case sendErr := <-errc:
   228  				//serialSendAsync successful?
   229  				if sendErr == nil {
   230  					continue
   231  				}
   232  				//no, bail
   233  				err = fmt.Errorf("Error sending %s: %s", in.Type.String(), sendErr)
   234  				return
   235  			case in = <-msgAvail:
   236  				if err == io.EOF {
   237  					chaincodeLogger.Debugf("Received EOF, ending chaincode stream, %s", err)
   238  					return
   239  				} else if err != nil {
   240  					chaincodeLogger.Errorf("Received error from server: %s, ending chaincode stream", err)
   241  					return
   242  				} else if in == nil {
   243  					err = fmt.Errorf("Received nil message, ending chaincode stream")
   244  					chaincodeLogger.Debug("Received nil message, ending chaincode stream")
   245  					return
   246  				}
   247  				chaincodeLogger.Debugf("[%s]Received message %s from shim", shorttxid(in.Txid), in.Type.String())
   248  				recv = true
   249  			case nsInfo = <-handler.nextState:
   250  				in = nsInfo.msg
   251  				if in == nil {
   252  					panic("nil msg")
   253  				}
   254  				chaincodeLogger.Debugf("[%s]Move state message %s", shorttxid(in.Txid), in.Type.String())
   255  			}
   256  
   257  			// Call FSM.handleMessage()
   258  			err = handler.handleMessage(in)
   259  			if err != nil {
   260  				err = fmt.Errorf("Error handling message: %s", err)
   261  				return
   262  			}
   263  
   264  			//keepalive messages are PONGs to the fabric's PINGs
   265  			if (nsInfo != nil && nsInfo.sendToCC) || (in.Type == pb.ChaincodeMessage_KEEPALIVE) {
   266  				if in.Type == pb.ChaincodeMessage_KEEPALIVE {
   267  					chaincodeLogger.Debug("Sending KEEPALIVE response")
   268  					//ignore any errors, maybe next KEEPALIVE will work
   269  					handler.serialSendAsync(in, nil)
   270  				} else {
   271  					chaincodeLogger.Debugf("[%s]send state message %s", shorttxid(in.Txid), in.Type.String())
   272  					handler.serialSendAsync(in, errc)
   273  				}
   274  			}
   275  		}
   276  	}()
   277  	<-waitc
   278  	return err
   279  }
   280  
   281  // -- init stub ---
   282  // ChaincodeInvocation functionality
   283  
   284  func (stub *ChaincodeStub) init(handler *Handler, txid string, input *pb.ChaincodeInput, proposal *pb.Proposal) error {
   285  	stub.TxID = txid
   286  	stub.args = input.Args
   287  	stub.handler = handler
   288  	stub.proposal = proposal
   289  
   290  	// TODO: sanity check: verify that every call to init with a nil
   291  	// proposal is a legitimate one, meaning it is an internal call
   292  	// to system chaincodes.
   293  	if proposal != nil {
   294  		// Extract creator, transient, binding...
   295  		var err error
   296  		stub.creator, stub.transient, err = utils.GetChaincodeProposalContext(proposal)
   297  		if err != nil {
   298  			return fmt.Errorf("Failed extracting proposal fields. [%s]", err)
   299  		}
   300  
   301  		// TODO: txid must uniquely identity the transaction.
   302  		// Remove this comment once replay attack protection will be in place
   303  		stub.binding, err = utils.ComputeProposalBinding(proposal)
   304  		if err != nil {
   305  			return fmt.Errorf("Failed computing binding from proposal. [%s]", err)
   306  		}
   307  	}
   308  
   309  	return nil
   310  }
   311  
   312  // GetTxID returns the transaction ID
   313  func (stub *ChaincodeStub) GetTxID() string {
   314  	return stub.TxID
   315  }
   316  
   317  // --------- Security functions ----------
   318  //CHAINCODE SEC INTERFACE FUNCS TOBE IMPLEMENTED BY ANGELO
   319  
   320  // ------------- Call Chaincode functions ---------------
   321  
   322  // InvokeChaincode locally calls the specified chaincode `Invoke` using the
   323  // same transaction context; that is, chaincode calling chaincode doesn't
   324  // create a new transaction message.
   325  func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response {
   326  	// Internally we handle chaincode name as a composite name
   327  	if channel != "" {
   328  		chaincodeName = chaincodeName + "/" + channel
   329  	}
   330  	return stub.handler.handleInvokeChaincode(chaincodeName, args, stub.TxID)
   331  }
   332  
   333  // --------- State functions ----------
   334  
   335  // GetState returns the byte array value specified by the `key`.
   336  func (stub *ChaincodeStub) GetState(key string) ([]byte, error) {
   337  	return stub.handler.handleGetState(key, stub.TxID)
   338  }
   339  
   340  // PutState writes the specified `value` and `key` into the ledger.
   341  func (stub *ChaincodeStub) PutState(key string, value []byte) error {
   342  	return stub.handler.handlePutState(key, value, stub.TxID)
   343  }
   344  
   345  // DelState removes the specified `key` and its value from the ledger.
   346  func (stub *ChaincodeStub) DelState(key string) error {
   347  	return stub.handler.handleDelState(key, stub.TxID)
   348  }
   349  
   350  // StateQueryIterator allows a chaincode to iterate over a set of
   351  // key/value pairs in the state.
   352  type StateQueryIterator struct {
   353  	handler    *Handler
   354  	uuid       string
   355  	response   *pb.QueryStateResponse
   356  	currentLoc int
   357  }
   358  
   359  // GetStateByRange function can be invoked by a chaincode to query of a range
   360  // of keys in the state. Assuming the startKey and endKey are in lexical order,
   361  // an iterator will be returned that can be used to iterate over all keys
   362  // between the startKey and endKey, inclusive. The order in which keys are
   363  // returned by the iterator is random.
   364  func (stub *ChaincodeStub) GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) {
   365  	response, err := stub.handler.handleGetStateByRange(startKey, endKey, stub.TxID)
   366  	if err != nil {
   367  		return nil, err
   368  	}
   369  	return &StateQueryIterator{stub.handler, stub.TxID, response, 0}, nil
   370  }
   371  
   372  // GetQueryResult function can be invoked by a chaincode to perform a
   373  // rich query against state database.  Only supported by state database implementations
   374  // that support rich query.  The query string is in the syntax of the underlying
   375  // state database. An iterator is returned which can be used to iterate (next) over
   376  // the query result set
   377  func (stub *ChaincodeStub) GetQueryResult(query string) (StateQueryIteratorInterface, error) {
   378  	response, err := stub.handler.handleGetQueryResult(query, stub.TxID)
   379  	if err != nil {
   380  		return nil, err
   381  	}
   382  	return &StateQueryIterator{stub.handler, stub.TxID, response, 0}, nil
   383  }
   384  
   385  // GetHistoryForKey function can be invoked by a chaincode to return a history of
   386  // key values across time. GetHistoryForKey is intended to be used for read-only queries.
   387  func (stub *ChaincodeStub) GetHistoryForKey(key string) (StateQueryIteratorInterface, error) {
   388  	response, err := stub.handler.handleGetHistoryForKey(key, stub.TxID)
   389  	if err != nil {
   390  		return nil, err
   391  	}
   392  	return &StateQueryIterator{stub.handler, stub.TxID, response, 0}, nil
   393  }
   394  
   395  //CreateCompositeKey combines the given attributes to form a composite key.
   396  func (stub *ChaincodeStub) CreateCompositeKey(objectType string, attributes []string) (string, error) {
   397  	return createCompositeKey(objectType, attributes)
   398  }
   399  
   400  //SplitCompositeKey splits the key into attributes on which the composite key was formed.
   401  func (stub *ChaincodeStub) SplitCompositeKey(compositeKey string) (string, []string, error) {
   402  	return splitCompositeKey(compositeKey)
   403  }
   404  
   405  func createCompositeKey(objectType string, attributes []string) (string, error) {
   406  	if err := validateCompositeKeyAttribute(objectType); err != nil {
   407  		return "", err
   408  	}
   409  	ck := objectType + string(minUnicodeRuneValue)
   410  	for _, att := range attributes {
   411  		if err := validateCompositeKeyAttribute(att); err != nil {
   412  			return "", err
   413  		}
   414  		ck += att + string(minUnicodeRuneValue)
   415  	}
   416  	return ck, nil
   417  }
   418  
   419  func splitCompositeKey(compositeKey string) (string, []string, error) {
   420  	componentIndex := 0
   421  	components := []string{}
   422  	for i := 0; i < len(compositeKey); i++ {
   423  		if compositeKey[i] == minUnicodeRuneValue {
   424  			components = append(components, compositeKey[componentIndex:i])
   425  			componentIndex = i + 1
   426  		}
   427  	}
   428  	return components[0], components[1:], nil
   429  }
   430  
   431  func validateCompositeKeyAttribute(str string) error {
   432  	if !utf8.ValidString(str) {
   433  		return fmt.Errorf("Not a valid utf8 string: [%x]", str)
   434  	}
   435  	for index, runeValue := range str {
   436  		if runeValue == minUnicodeRuneValue || runeValue == maxUnicodeRuneValue {
   437  			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`,
   438  				runeValue, index, minUnicodeRuneValue, maxUnicodeRuneValue)
   439  		}
   440  	}
   441  	return nil
   442  }
   443  
   444  //GetStateByPartialCompositeKey function can be invoked by a chaincode to query the
   445  //state based on a given partial composite key. This function returns an
   446  //iterator which can be used to iterate over all composite keys whose prefix
   447  //matches the given partial composite key. This function should be used only for
   448  //a partial composite key. For a full composite key, an iter with empty response
   449  //would be returned.
   450  func (stub *ChaincodeStub) GetStateByPartialCompositeKey(objectType string, attributes []string) (StateQueryIteratorInterface, error) {
   451  	return getStateByPartialCompositeKey(stub, objectType, attributes)
   452  }
   453  
   454  func getStateByPartialCompositeKey(stub ChaincodeStubInterface, objectType string, attributes []string) (StateQueryIteratorInterface, error) {
   455  	partialCompositeKey, _ := stub.CreateCompositeKey(objectType, attributes)
   456  	keysIter, err := stub.GetStateByRange(partialCompositeKey, partialCompositeKey+string(maxUnicodeRuneValue))
   457  	if err != nil {
   458  		return nil, fmt.Errorf("Error fetching rows: %s", err)
   459  	}
   460  	return keysIter, nil
   461  }
   462  
   463  // HasNext returns true if the range query iterator contains additional keys
   464  // and values.
   465  func (iter *StateQueryIterator) HasNext() bool {
   466  	if iter.currentLoc < len(iter.response.KeysAndValues) || iter.response.HasMore {
   467  		return true
   468  	}
   469  	return false
   470  }
   471  
   472  // Next returns the next key and value in the range query iterator.
   473  func (iter *StateQueryIterator) Next() (string, []byte, error) {
   474  	if iter.currentLoc < len(iter.response.KeysAndValues) {
   475  		keyValue := iter.response.KeysAndValues[iter.currentLoc]
   476  		iter.currentLoc++
   477  		return keyValue.Key, keyValue.Value, nil
   478  	} else if !iter.response.HasMore {
   479  		return "", nil, errors.New("No such key")
   480  	} else {
   481  		response, err := iter.handler.handleQueryStateNext(iter.response.Id, iter.uuid)
   482  
   483  		if err != nil {
   484  			return "", nil, err
   485  		}
   486  
   487  		iter.currentLoc = 0
   488  		iter.response = response
   489  		keyValue := iter.response.KeysAndValues[iter.currentLoc]
   490  		iter.currentLoc++
   491  		return keyValue.Key, keyValue.Value, nil
   492  
   493  	}
   494  }
   495  
   496  // Close closes the range query iterator. This should be called when done
   497  // reading from the iterator to free up resources.
   498  func (iter *StateQueryIterator) Close() error {
   499  	_, err := iter.handler.handleQueryStateClose(iter.response.Id, iter.uuid)
   500  	return err
   501  }
   502  
   503  // GetArgs returns the argument list
   504  func (stub *ChaincodeStub) GetArgs() [][]byte {
   505  	return stub.args
   506  }
   507  
   508  // GetStringArgs returns the arguments as array of strings
   509  func (stub *ChaincodeStub) GetStringArgs() []string {
   510  	args := stub.GetArgs()
   511  	strargs := make([]string, 0, len(args))
   512  	for _, barg := range args {
   513  		strargs = append(strargs, string(barg))
   514  	}
   515  	return strargs
   516  }
   517  
   518  // GetFunctionAndParameters returns the first arg as the function and the rest
   519  // as argument string array
   520  func (stub *ChaincodeStub) GetFunctionAndParameters() (function string, params []string) {
   521  	allargs := stub.GetStringArgs()
   522  	function = ""
   523  	params = []string{}
   524  	if len(allargs) >= 1 {
   525  		function = allargs[0]
   526  		params = allargs[1:]
   527  	}
   528  	return
   529  }
   530  
   531  // GetCreator returns SignatureHeader.Creator of the proposal
   532  // this Stub refers to.
   533  func (stub *ChaincodeStub) GetCreator() ([]byte, error) {
   534  	return stub.creator, nil
   535  }
   536  
   537  // GetTransient returns the ChaincodeProposalPayload.transient field.
   538  // It is a map that contains data (e.g. cryptographic material)
   539  // that might be used to implement some form of application-level confidentiality. The contents
   540  // of this field, as prescribed by ChaincodeProposalPayload, are supposed to always
   541  // be omitted from the transaction and excluded from the ledger.
   542  func (stub *ChaincodeStub) GetTransient() (map[string][]byte, error) {
   543  	return stub.transient, nil
   544  }
   545  
   546  // GetBinding returns the transaction binding
   547  func (stub *ChaincodeStub) GetBinding() ([]byte, error) {
   548  	return stub.binding, nil
   549  }
   550  
   551  // GetArgsSlice returns the arguments to the stub call as a byte array
   552  func (stub *ChaincodeStub) GetArgsSlice() ([]byte, error) {
   553  	args := stub.GetArgs()
   554  	res := []byte{}
   555  	for _, barg := range args {
   556  		res = append(res, barg...)
   557  	}
   558  	return res, nil
   559  }
   560  
   561  // GetTxTimestamp returns transaction created timestamp, which is currently
   562  // taken from the peer receiving the transaction. Note that this timestamp
   563  // may not be the same with the other peers' time.
   564  func (stub *ChaincodeStub) GetTxTimestamp() (*timestamp.Timestamp, error) {
   565  	return nil, nil
   566  }
   567  
   568  // ------------- ChaincodeEvent API ----------------------
   569  
   570  // SetEvent saves the event to be sent when a transaction is made part of a block
   571  func (stub *ChaincodeStub) SetEvent(name string, payload []byte) error {
   572  	if name == "" {
   573  		return errors.New("Event name can not be nil string.")
   574  	}
   575  	stub.chaincodeEvent = &pb.ChaincodeEvent{EventName: name, Payload: payload}
   576  	return nil
   577  }
   578  
   579  // ------------- Logging Control and Chaincode Loggers ---------------
   580  
   581  // As independent programs, Go language chaincodes can use any logging
   582  // methodology they choose, from simple fmt.Printf() to os.Stdout, to
   583  // decorated logs created by the author's favorite logging package. The
   584  // chaincode "shim" interface, however, is defined by the Hyperledger fabric
   585  // and implements its own logging methodology. This methodology currently
   586  // includes severity-based logging control and a standard way of decorating
   587  // the logs.
   588  //
   589  // The facilities defined here allow a Go language chaincode to control the
   590  // logging level of its shim, and to create its own logs formatted
   591  // consistently with, and temporally interleaved with the shim logs without
   592  // any knowledge of the underlying implementation of the shim, and without any
   593  // other package requirements. The lack of package requirements is especially
   594  // important because even if the chaincode happened to explicitly use the same
   595  // logging package as the shim, unless the chaincode is physically included as
   596  // part of the hyperledger fabric source code tree it could actually end up
   597  // using a distinct binary instance of the logging package, with different
   598  // formats and severity levels than the binary package used by the shim.
   599  //
   600  // Another approach that might have been taken, and could potentially be taken
   601  // in the future, would be for the chaincode to supply a logging object for
   602  // the shim to use, rather than the other way around as implemented
   603  // here. There would be some complexities associated with that approach, so
   604  // for the moment we have chosen the simpler implementation below. The shim
   605  // provides one or more abstract logging objects for the chaincode to use via
   606  // the NewLogger() API, and allows the chaincode to control the severity level
   607  // of shim logs using the SetLoggingLevel() API.
   608  
   609  // LoggingLevel is an enumerated type of severity levels that control
   610  // chaincode logging.
   611  type LoggingLevel logging.Level
   612  
   613  // These constants comprise the LoggingLevel enumeration
   614  const (
   615  	LogDebug    = LoggingLevel(logging.DEBUG)
   616  	LogInfo     = LoggingLevel(logging.INFO)
   617  	LogNotice   = LoggingLevel(logging.NOTICE)
   618  	LogWarning  = LoggingLevel(logging.WARNING)
   619  	LogError    = LoggingLevel(logging.ERROR)
   620  	LogCritical = LoggingLevel(logging.CRITICAL)
   621  )
   622  
   623  var shimLoggingLevel = LogDebug // Necessary for correct initialization; See Start()
   624  
   625  // SetLoggingLevel allows a Go language chaincode to set the logging level of
   626  // its shim.
   627  func SetLoggingLevel(level LoggingLevel) {
   628  	shimLoggingLevel = level
   629  	logging.SetLevel(logging.Level(level), "shim")
   630  }
   631  
   632  // LogLevel converts a case-insensitive string chosen from CRITICAL, ERROR,
   633  // WARNING, NOTICE, INFO or DEBUG into an element of the LoggingLevel
   634  // type. In the event of errors the level returned is LogError.
   635  func LogLevel(levelString string) (LoggingLevel, error) {
   636  	l, err := logging.LogLevel(levelString)
   637  	level := LoggingLevel(l)
   638  	if err != nil {
   639  		level = LogError
   640  	}
   641  	return level, err
   642  }
   643  
   644  // ------------- Chaincode Loggers ---------------
   645  
   646  // ChaincodeLogger is an abstraction of a logging object for use by
   647  // chaincodes. These objects are created by the NewLogger API.
   648  type ChaincodeLogger struct {
   649  	logger *logging.Logger
   650  }
   651  
   652  // NewLogger allows a Go language chaincode to create one or more logging
   653  // objects whose logs will be formatted consistently with, and temporally
   654  // interleaved with the logs created by the shim interface. The logs created
   655  // by this object can be distinguished from shim logs by the name provided,
   656  // which will appear in the logs.
   657  func NewLogger(name string) *ChaincodeLogger {
   658  	return &ChaincodeLogger{logging.MustGetLogger(name)}
   659  }
   660  
   661  // SetLevel sets the logging level for a chaincode logger. Note that currently
   662  // the levels are actually controlled by the name given when the logger is
   663  // created, so loggers should be given unique names other than "shim".
   664  func (c *ChaincodeLogger) SetLevel(level LoggingLevel) {
   665  	logging.SetLevel(logging.Level(level), c.logger.Module)
   666  }
   667  
   668  // IsEnabledFor returns true if the logger is enabled to creates logs at the
   669  // given logging level.
   670  func (c *ChaincodeLogger) IsEnabledFor(level LoggingLevel) bool {
   671  	return c.logger.IsEnabledFor(logging.Level(level))
   672  }
   673  
   674  // Debug logs will only appear if the ChaincodeLogger LoggingLevel is set to
   675  // LogDebug.
   676  func (c *ChaincodeLogger) Debug(args ...interface{}) {
   677  	c.logger.Debug(args...)
   678  }
   679  
   680  // Info logs will appear if the ChaincodeLogger LoggingLevel is set to
   681  // LogInfo or LogDebug.
   682  func (c *ChaincodeLogger) Info(args ...interface{}) {
   683  	c.logger.Info(args...)
   684  }
   685  
   686  // Notice logs will appear if the ChaincodeLogger LoggingLevel is set to
   687  // LogNotice, LogInfo or LogDebug.
   688  func (c *ChaincodeLogger) Notice(args ...interface{}) {
   689  	c.logger.Notice(args...)
   690  }
   691  
   692  // Warning logs will appear if the ChaincodeLogger LoggingLevel is set to
   693  // LogWarning, LogNotice, LogInfo or LogDebug.
   694  func (c *ChaincodeLogger) Warning(args ...interface{}) {
   695  	c.logger.Warning(args...)
   696  }
   697  
   698  // Error logs will appear if the ChaincodeLogger LoggingLevel is set to
   699  // LogError, LogWarning, LogNotice, LogInfo or LogDebug.
   700  func (c *ChaincodeLogger) Error(args ...interface{}) {
   701  	c.logger.Error(args...)
   702  }
   703  
   704  // Critical logs always appear; They can not be disabled.
   705  func (c *ChaincodeLogger) Critical(args ...interface{}) {
   706  	c.logger.Critical(args...)
   707  }
   708  
   709  // Debugf logs will only appear if the ChaincodeLogger LoggingLevel is set to
   710  // LogDebug.
   711  func (c *ChaincodeLogger) Debugf(format string, args ...interface{}) {
   712  	c.logger.Debugf(format, args...)
   713  }
   714  
   715  // Infof logs will appear if the ChaincodeLogger LoggingLevel is set to
   716  // LogInfo or LogDebug.
   717  func (c *ChaincodeLogger) Infof(format string, args ...interface{}) {
   718  	c.logger.Infof(format, args...)
   719  }
   720  
   721  // Noticef logs will appear if the ChaincodeLogger LoggingLevel is set to
   722  // LogNotice, LogInfo or LogDebug.
   723  func (c *ChaincodeLogger) Noticef(format string, args ...interface{}) {
   724  	c.logger.Noticef(format, args...)
   725  }
   726  
   727  // Warningf logs will appear if the ChaincodeLogger LoggingLevel is set to
   728  // LogWarning, LogNotice, LogInfo or LogDebug.
   729  func (c *ChaincodeLogger) Warningf(format string, args ...interface{}) {
   730  	c.logger.Warningf(format, args...)
   731  }
   732  
   733  // Errorf logs will appear if the ChaincodeLogger LoggingLevel is set to
   734  // LogError, LogWarning, LogNotice, LogInfo or LogDebug.
   735  func (c *ChaincodeLogger) Errorf(format string, args ...interface{}) {
   736  	c.logger.Errorf(format, args...)
   737  }
   738  
   739  // Criticalf logs always appear; They can not be disabled.
   740  func (c *ChaincodeLogger) Criticalf(format string, args ...interface{}) {
   741  	c.logger.Criticalf(format, args...)
   742  }