github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/core/chaincode/shim/mockstub.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  	"container/list"
    23  	"errors"
    24  	"fmt"
    25  	"strings"
    26  
    27  	"encoding/json"
    28  	"math/big"
    29  
    30  	"github.com/golang/protobuf/ptypes/timestamp"
    31  	"github.com/inklabsfoundation/inkchain/common/util"
    32  	"github.com/inklabsfoundation/inkchain/core/wallet"
    33  	"github.com/inklabsfoundation/inkchain/protos/ledger/queryresult"
    34  	"github.com/inklabsfoundation/inkchain/protos/ledger/transet/kvtranset"
    35  	pb "github.com/inklabsfoundation/inkchain/protos/peer"
    36  	"github.com/op/go-logging"
    37  )
    38  
    39  // Logger for the shim package.
    40  var mockLogger = logging.MustGetLogger("mock")
    41  
    42  // MockStub is an implementation of ChaincodeStubInterface for unit testing chaincode.
    43  // Use this instead of ChaincodeStub in your chaincode's unit test calls to Init or Invoke.
    44  type MockStub struct {
    45  	// arguments the stub was called with
    46  	args [][]byte
    47  
    48  	// A pointer back to the chaincode that will invoke this, set by constructor.
    49  	// If a peer calls this stub, the chaincode will be invoked from here.
    50  	cc Chaincode
    51  
    52  	// A nice name that can be used for logging
    53  	Name string
    54  
    55  	// State keeps name value pairs
    56  	State map[string][]byte
    57  
    58  	// Keys stores the list of mapped values in lexical order
    59  	Keys *list.List
    60  
    61  	// registered list of other MockStub chaincodes that can be called from this MockStub
    62  	Invokables map[string]*MockStub
    63  
    64  	// stores a transaction uuid while being Invoked / Deployed
    65  	// TODO if a chaincode uses recursion this may need to be a stack of TxIDs or possibly a reference counting map
    66  	TxID string
    67  
    68  	TxTimestamp *timestamp.Timestamp
    69  
    70  	// mocked signedProposal
    71  	signedProposal *pb.SignedProposal
    72  }
    73  
    74  func (stub *MockStub) GetTxID() string {
    75  	return stub.TxID
    76  }
    77  
    78  func (stub *MockStub) GetArgs() [][]byte {
    79  	return stub.args
    80  }
    81  
    82  func (stub *MockStub) GetStringArgs() []string {
    83  	args := stub.GetArgs()
    84  	strargs := make([]string, 0, len(args))
    85  	for _, barg := range args {
    86  		strargs = append(strargs, string(barg))
    87  	}
    88  	return strargs
    89  }
    90  
    91  func (stub *MockStub) GetFunctionAndParameters() (function string, params []string) {
    92  	allargs := stub.GetStringArgs()
    93  	function = ""
    94  	params = []string{}
    95  	if len(allargs) >= 1 {
    96  		function = allargs[0]
    97  		params = allargs[1:]
    98  	}
    99  	return
   100  }
   101  
   102  // Used to indicate to a chaincode that it is part of a transaction.
   103  // This is important when chaincodes invoke each other.
   104  // MockStub doesn't support concurrent transactions at present.
   105  func (stub *MockStub) MockTransactionStart(txid string) {
   106  	stub.TxID = txid
   107  	stub.setSignedProposal(&pb.SignedProposal{})
   108  	stub.setTxTimestamp(util.CreateUtcTimestamp())
   109  }
   110  
   111  // End a mocked transaction, clearing the UUID.
   112  func (stub *MockStub) MockTransactionEnd(uuid string) {
   113  	stub.signedProposal = nil
   114  	stub.TxID = ""
   115  }
   116  
   117  // Register a peer chaincode with this MockStub
   118  // invokableChaincodeName is the name or hash of the peer
   119  // otherStub is a MockStub of the peer, already intialised
   120  func (stub *MockStub) MockPeerChaincode(invokableChaincodeName string, otherStub *MockStub) {
   121  	stub.Invokables[invokableChaincodeName] = otherStub
   122  }
   123  
   124  // Initialise this chaincode,  also starts and ends a transaction.
   125  func (stub *MockStub) MockInit(uuid string, args [][]byte) pb.Response {
   126  	stub.args = args
   127  	stub.MockTransactionStart(uuid)
   128  	res := stub.cc.Init(stub)
   129  	stub.MockTransactionEnd(uuid)
   130  	return res
   131  }
   132  
   133  // Invoke this chaincode, also starts and ends a transaction.
   134  func (stub *MockStub) MockInvoke(uuid string, args [][]byte) pb.Response {
   135  	stub.args = args
   136  	stub.MockTransactionStart(uuid)
   137  	res := stub.cc.Invoke(stub)
   138  	stub.MockTransactionEnd(uuid)
   139  	return res
   140  }
   141  
   142  // Invoke this chaincode, also starts and ends a transaction.
   143  func (stub *MockStub) MockInvokeWithSignedProposal(uuid string, args [][]byte, sp *pb.SignedProposal) pb.Response {
   144  	stub.args = args
   145  	stub.MockTransactionStart(uuid)
   146  	stub.signedProposal = sp
   147  	res := stub.cc.Invoke(stub)
   148  	stub.MockTransactionEnd(uuid)
   149  	return res
   150  }
   151  
   152  // GetState retrieves the value for a given key from the ledger
   153  func (stub *MockStub) GetState(key string) ([]byte, error) {
   154  	value := stub.State[key]
   155  	mockLogger.Debug("MockStub", stub.Name, "Getting", key, value)
   156  	return value, nil
   157  }
   158  
   159  // PutState writes the specified `value` and `key` into the ledger.
   160  func (stub *MockStub) PutState(key string, value []byte) error {
   161  	if stub.TxID == "" {
   162  		mockLogger.Error("Cannot PutState without a transactions - call stub.MockTransactionStart()?")
   163  		return errors.New("Cannot PutState without a transactions - call stub.MockTransactionStart()?")
   164  	}
   165  
   166  	mockLogger.Debug("MockStub", stub.Name, "Putting", key, value)
   167  	stub.State[key] = value
   168  
   169  	// insert key into ordered list of keys
   170  	for elem := stub.Keys.Front(); elem != nil; elem = elem.Next() {
   171  		elemValue := elem.Value.(string)
   172  		comp := strings.Compare(key, elemValue)
   173  		mockLogger.Debug("MockStub", stub.Name, "Compared", key, elemValue, " and got ", comp)
   174  		if comp < 0 {
   175  			// key < elem, insert it before elem
   176  			stub.Keys.InsertBefore(key, elem)
   177  			mockLogger.Debug("MockStub", stub.Name, "Key", key, " inserted before", elem.Value)
   178  			break
   179  		} else if comp == 0 {
   180  			// keys exists, no need to change
   181  			mockLogger.Debug("MockStub", stub.Name, "Key", key, "already in State")
   182  			break
   183  		} else { // comp > 0
   184  			// key > elem, keep looking unless this is the end of the list
   185  			if elem.Next() == nil {
   186  				stub.Keys.PushBack(key)
   187  				mockLogger.Debug("MockStub", stub.Name, "Key", key, "appended")
   188  				break
   189  			}
   190  		}
   191  	}
   192  
   193  	// special case for empty Keys list
   194  	if stub.Keys.Len() == 0 {
   195  		stub.Keys.PushFront(key)
   196  		mockLogger.Debug("MockStub", stub.Name, "Key", key, "is first element in list")
   197  	}
   198  
   199  	return nil
   200  }
   201  
   202  // DelState removes the specified `key` and its value from the ledger.
   203  func (stub *MockStub) DelState(key string) error {
   204  	mockLogger.Debug("MockStub", stub.Name, "Deleting", key, stub.State[key])
   205  	delete(stub.State, key)
   206  
   207  	for elem := stub.Keys.Front(); elem != nil; elem = elem.Next() {
   208  		if strings.Compare(key, elem.Value.(string)) == 0 {
   209  			stub.Keys.Remove(elem)
   210  		}
   211  	}
   212  
   213  	return nil
   214  }
   215  
   216  func (stub *MockStub) GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) {
   217  	if err := validateSimpleKeys(startKey, endKey); err != nil {
   218  		return nil, err
   219  	}
   220  	return NewMockStateRangeQueryIterator(stub, startKey, endKey), nil
   221  }
   222  
   223  // GetQueryResult function can be invoked by a chaincode to perform a
   224  // rich query against state database.  Only supported by state database implementations
   225  // that support rich query.  The query string is in the syntax of the underlying
   226  // state database. An iterator is returned which can be used to iterate (next) over
   227  // the query result set
   228  func (stub *MockStub) GetQueryResult(query string) (StateQueryIteratorInterface, error) {
   229  	// Not implemented since the mock engine does not have a query engine.
   230  	// However, a very simple query engine that supports string matching
   231  	// could be implemented to test that the framework supports queries
   232  	return nil, errors.New("Not Implemented")
   233  }
   234  
   235  // GetHistoryForKey function can be invoked by a chaincode to return a history of
   236  // key values across time. GetHistoryForKey is intended to be used for read-only queries.
   237  func (stub *MockStub) GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error) {
   238  	return nil, errors.New("Not Implemented")
   239  }
   240  
   241  //GetStateByPartialCompositeKey function can be invoked by a chaincode to query the
   242  //state based on a given partial composite key. This function returns an
   243  //iterator which can be used to iterate over all composite keys whose prefix
   244  //matches the given partial composite key. This function should be used only for
   245  //a partial composite key. For a full composite key, an iter with empty response
   246  //would be returned.
   247  func (stub *MockStub) GetStateByPartialCompositeKey(objectType string, attributes []string) (StateQueryIteratorInterface, error) {
   248  	partialCompositeKey, err := stub.CreateCompositeKey(objectType, attributes)
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  	return NewMockStateRangeQueryIterator(stub, partialCompositeKey, partialCompositeKey+string(maxUnicodeRuneValue)), nil
   253  }
   254  
   255  // CreateCompositeKey combines the list of attributes
   256  //to form a composite key.
   257  func (stub *MockStub) CreateCompositeKey(objectType string, attributes []string) (string, error) {
   258  	return createCompositeKey(objectType, attributes)
   259  }
   260  
   261  // SplitCompositeKey splits the composite key into attributes
   262  // on which the composite key was formed.
   263  func (stub *MockStub) SplitCompositeKey(compositeKey string) (string, []string, error) {
   264  	return splitCompositeKey(compositeKey)
   265  }
   266  
   267  // InvokeChaincode calls a peered chaincode.
   268  // E.g. stub1.InvokeChaincode("stub2Hash", funcArgs, channel)
   269  // Before calling this make sure to create another MockStub stub2, call stub2.MockInit(uuid, func, args)
   270  // and register it with stub1 by calling stub1.MockPeerChaincode("stub2Hash", stub2)
   271  func (stub *MockStub) InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response {
   272  	// Internally we use chaincode name as a composite name
   273  	if channel != "" {
   274  		chaincodeName = chaincodeName + "/" + channel
   275  	}
   276  	// TODO "args" here should possibly be a serialized pb.ChaincodeInput
   277  	otherStub := stub.Invokables[chaincodeName]
   278  	mockLogger.Debug("MockStub", stub.Name, "Invoking peer chaincode", otherStub.Name, args)
   279  	//	function, strings := getFuncArgs(args)
   280  	res := otherStub.MockInvoke(stub.TxID, args)
   281  	mockLogger.Debug("MockStub", stub.Name, "Invoked peer chaincode", otherStub.Name, "got", fmt.Sprintf("%+v", res))
   282  	return res
   283  }
   284  
   285  // warning!  This method can not produce right outputs cause the sender is obtained from ChaincodeInvokeSpec
   286  func (stub *MockStub) Transfer(to string, balanceType string, amount *big.Int) error {
   287  	if stub.TxID == "" {
   288  		mockLogger.Error("Cannot Transfer without a transactions - call stub.MockTransactionStart()?")
   289  		return errors.New("Cannot Transfer without a transactions - call stub.MockTransactionStart()?")
   290  	}
   291  	/*
   292  		to = strings.ToLower(to)
   293  		mockLogger.Debug("MockStub", stub.Name, "Transfer To", to, amount)
   294  
   295  		toAddress, err := wallet.HexToAddress(to)
   296  		if err != nil {
   297  			return err
   298  		}
   299  
   300  			sig, err := wallet.SignatureStringToBytes(signature)
   301  			if err != nil {
   302  				return errors.New(err.Error())
   303  			}
   304  			fromAddressExtracted, err := wallet.GetSenderFromSignature(fromAddress, toAddress, amount, sig)
   305  			if fromAddressExtracted.ToString() != from {
   306  				return errors.New("sender mismatch")
   307  			}
   308  
   309  		toAccount := &wallet.Account{}
   310  		if value, ok := stub.State[fromAddress.ToString()]; ok {
   311  			jsonErr := json.Unmarshal(value, fromAccount)
   312  			if jsonErr != nil {
   313  				return jsonErr
   314  			}
   315  			if fromAccount.Balance == nil {
   316  				return errors.New("balance" + balanceType + "not exists")
   317  			}
   318  			fromBalance, ok := fromAccount.Balance[balanceType]
   319  			if !ok {
   320  				return errors.New("balance" + wallet.MAIN_BALANCE_NAME + "not exists")
   321  			}
   322  			if fromBalance.Cmp(amount) < 0 {
   323  				return errors.New("insufficient balance for sender")
   324  			}
   325  			fromBalance = fromBalance.Sub(fromBalance, amount)
   326  
   327  			fromAccountBytes, jsonErr := json.Marshal(fromAccount)
   328  
   329  			if jsonErr != nil {
   330  				return errors.New("error marshaling sender account")
   331  			}
   332  			stub.State[fromAddress.ToString()] = fromAccountBytes
   333  			key := fromAddress.ToString()
   334  			// insert key into ordered list of keys
   335  			for elem := stub.Keys.Front(); elem != nil; elem = elem.Next() {
   336  				elemValue := elem.Value.(string)
   337  				comp := strings.Compare(key, elemValue)
   338  				mockLogger.Debug("MockStub", stub.Name, "Compared", key, elemValue, " and got ", comp)
   339  				if comp < 0 {
   340  					// key < elem, insert it before elem
   341  					stub.Keys.InsertBefore(key, elem)
   342  					mockLogger.Debug("MockStub", stub.Name, "Key", key, " inserted before", elem.Value)
   343  					break
   344  				} else if comp == 0 {
   345  					// keys exists, no need to change
   346  					mockLogger.Debug("MockStub", stub.Name, "Key", key, "already in State")
   347  					break
   348  				} else { // comp > 0
   349  					// key > elem, keep looking unless this is the end of the list
   350  					if elem.Next() == nil {
   351  						stub.Keys.PushBack(key)
   352  						mockLogger.Debug("MockStub", stub.Name, "Key", key, "appended")
   353  						break
   354  					}
   355  				}
   356  			}
   357  
   358  			// special case for empty Keys list
   359  			if stub.Keys.Len() == 0 {
   360  				stub.Keys.PushFront(key)
   361  				mockLogger.Debug("MockStub", stub.Name, "Key", key, "is first element in list")
   362  			}
   363  			value, ok = stub.State[toAddress.ToString()]
   364  			if ok {
   365  				jsonErr = json.Unmarshal(value, &toAccount)
   366  				if jsonErr != nil {
   367  					return jsonErr
   368  				}
   369  			}
   370  			if toAccount.Balance == nil {
   371  				toAccount.Balance = make(map[string]*big.Int)
   372  			}
   373  			toBalance, ok := toAccount.Balance[balanceType]
   374  			if !ok {
   375  				toBalance = big.NewInt(0)
   376  				toAccount.Balance[balanceType] = toBalance
   377  			}
   378  			toBalance.Add(toBalance, amount)
   379  			toAccountBytes, jsonErr := json.Marshal(toAccount)
   380  			stub.State[to] = toAccountBytes
   381  
   382  			key = to
   383  			// insert key into ordered list of keys
   384  			for elem := stub.Keys.Front(); elem != nil; elem = elem.Next() {
   385  				elemValue := elem.Value.(string)
   386  				comp := strings.Compare(key, elemValue)
   387  				mockLogger.Debug("MockStub", stub.Name, "Compared", key, elemValue, " and got ", comp)
   388  				if comp < 0 {
   389  					// key < elem, insert it before elem
   390  					stub.Keys.InsertBefore(key, elem)
   391  					mockLogger.Debug("MockStub", stub.Name, "Key", key, " inserted before", elem.Value)
   392  					break
   393  				} else if comp == 0 {
   394  					// keys exists, no need to change
   395  					mockLogger.Debug("MockStub", stub.Name, "Key", key, "already in State")
   396  					break
   397  				} else { // comp > 0
   398  					// key > elem, keep looking unless this is the end of the list
   399  					if elem.Next() == nil {
   400  						stub.Keys.PushBack(key)
   401  						mockLogger.Debug("MockStub", stub.Name, "Key", key, "appended")
   402  						break
   403  					}
   404  				}
   405  			}
   406  
   407  			// special case for empty Keys list
   408  			if stub.Keys.Len() == 0 {
   409  				stub.Keys.PushFront(key)
   410  				mockLogger.Debug("MockStub", stub.Name, "Key", key, "is first element in list")
   411  			}
   412  			return nil
   413  		}
   414  	*/
   415  	return errors.New(" this function could not be used in mock invocation")
   416  }
   417  
   418  // warning!  This method can not produce right outputs cause the sender is obtained from ChaincodeInvokeSpec
   419  func (stub *MockStub) CalcFeeByInvoke() (*big.Int, error) {
   420  	if stub.TxID == "" {
   421  		mockLogger.Error("Cannot Transfer without a transactions - call stub.MockTransactionStart()?")
   422  		return nil, errors.New("Cannot Transfer without a transactions - call stub.MockTransactionStart()?")
   423  	}
   424  	return nil, errors.New(" this function could not be used in mock invocation")
   425  }
   426  
   427  // warning!  This method can not produce right outputs cause the sender is obtained from ChaincodeInvokeSpec
   428  func (stub *MockStub) CalcFee(content string) (*big.Int, error) {
   429  	if stub.TxID == "" {
   430  		mockLogger.Error("Cannot Transfer without a transactions - call stub.MockTransactionStart()?")
   431  		return nil, errors.New("Cannot Transfer without a transactions - call stub.MockTransactionStart()?")
   432  	}
   433  	return nil, errors.New(" this function could not be used in mock invocation")
   434  }
   435  
   436  func (stub *MockStub) MultiTransfer(trans *kvtranset.KVTranSet) error {
   437  	return errors.New(" this function could not be used in mock invocation")
   438  }
   439  
   440  //sign data
   441  func (stub *MockStub) Sign(data []byte) (result string, err error) {
   442  	return "", nil
   443  }
   444  
   445  //verify signature from Sign
   446  func (stub *MockStub) Verify(signature string, data []byte, address string) (result bool, err error) {
   447  	return false, nil
   448  }
   449  
   450  func (stub *MockStub) GetAccount(address string) (*wallet.Account, error) {
   451  	address = strings.ToLower(address)
   452  	if accountBytes, ok := stub.State[address]; ok {
   453  		account := &wallet.Account{}
   454  		jsonErr := json.Unmarshal(accountBytes, account)
   455  		if jsonErr != nil {
   456  			return nil, jsonErr
   457  		}
   458  		return account, nil
   459  	}
   460  	return nil, errors.New("getAccount error")
   461  }
   462  
   463  func (stub *MockStub) IssueToken(address string, balanceType string, amount *big.Int) error {
   464  	address = strings.ToLower(address)
   465  	if stub.TxID == "" {
   466  		mockLogger.Error("Cannot issue token without a transactions - call stub.MockTransactionStart()?")
   467  		return errors.New("Cannot issue token without a transactions - call stub.MockTransactionStart()?")
   468  	}
   469  	account := &wallet.Account{}
   470  	accountJson, ok := stub.State[address]
   471  	if ok {
   472  		err := json.Unmarshal(accountJson, account)
   473  		if err == nil {
   474  			_, ok := account.Balance[balanceType]
   475  			if ok {
   476  				return errors.New("balance exists in this address")
   477  			}
   478  		}
   479  
   480  	}
   481  	if account.Balance == nil {
   482  		account.Balance = make(map[string]*big.Int)
   483  	}
   484  
   485  	account.Balance[balanceType] = amount
   486  	accountBytes, jsonErr := json.Marshal(account)
   487  	if jsonErr != nil {
   488  		return jsonErr
   489  	}
   490  	stub.State[address] = accountBytes
   491  	// insert key into ordered list of keys
   492  	for elem := stub.Keys.Front(); elem != nil; elem = elem.Next() {
   493  		elemValue := elem.Value.(string)
   494  		comp := strings.Compare(address, elemValue)
   495  		mockLogger.Debug("MockStub", stub.Name, "Compared", address, elemValue, " and got ", comp)
   496  		if comp < 0 {
   497  			// key < elem, insert it before elem
   498  			stub.Keys.InsertBefore(address, elem)
   499  			mockLogger.Debug("MockStub", stub.Name, "Key", address, " inserted before", elem.Value)
   500  			break
   501  		} else if comp == 0 {
   502  			// keys exists, no need to change
   503  			mockLogger.Debug("MockStub", stub.Name, "Key", address, "already in State")
   504  			break
   505  		} else { // comp > 0
   506  			// key > elem, keep looking unless this is the end of the list
   507  			if elem.Next() == nil {
   508  				stub.Keys.PushBack(address)
   509  				mockLogger.Debug("MockStub", stub.Name, "Key", address, "appended")
   510  				break
   511  			}
   512  		}
   513  	}
   514  
   515  	// special case for empty Keys list
   516  	if stub.Keys.Len() == 0 {
   517  		stub.Keys.PushFront(address)
   518  		mockLogger.Debug("MockStub", stub.Name, "Key", address, "is first element in list")
   519  	}
   520  
   521  	return nil
   522  	return nil
   523  }
   524  
   525  // Not implemented
   526  func (stub *MockStub) GetCreator() ([]byte, error) {
   527  	return nil, nil
   528  }
   529  
   530  // Not implemented
   531  func (stub *MockStub) GetTransient() (map[string][]byte, error) {
   532  	return nil, nil
   533  }
   534  
   535  // Not implemented
   536  func (stub *MockStub) GetBinding() ([]byte, error) {
   537  	return nil, nil
   538  }
   539  func (stub *MockStub) GetSender() (string, error) {
   540  	return "", nil
   541  }
   542  
   543  // Not implemented yet
   544  func (stub *MockStub) GetSenderPubKey() (string, error) {
   545  	return "", nil
   546  }
   547  
   548  // Not implemented
   549  func (stub *MockStub) GetSignedProposal() (*pb.SignedProposal, error) {
   550  	return stub.signedProposal, nil
   551  }
   552  
   553  func (stub *MockStub) setSignedProposal(sp *pb.SignedProposal) {
   554  	stub.signedProposal = sp
   555  }
   556  
   557  // Not implemented
   558  func (stub *MockStub) GetArgsSlice() ([]byte, error) {
   559  	return nil, nil
   560  }
   561  
   562  func (stub *MockStub) setTxTimestamp(time *timestamp.Timestamp) {
   563  	stub.TxTimestamp = time
   564  }
   565  
   566  func (stub *MockStub) GetTxTimestamp() (*timestamp.Timestamp, error) {
   567  	if stub.TxTimestamp == nil {
   568  		return nil, errors.New("TxTimestamp not set.")
   569  	}
   570  	return stub.TxTimestamp, nil
   571  }
   572  
   573  // Not implemented
   574  func (stub *MockStub) SetEvent(name string, payload []byte) error {
   575  	return nil
   576  }
   577  
   578  // Constructor to initialise the internal State map
   579  func NewMockStub(name string, cc Chaincode) *MockStub {
   580  	mockLogger.Debug("MockStub(", name, cc, ")")
   581  	s := new(MockStub)
   582  	s.Name = name
   583  	s.cc = cc
   584  	s.State = make(map[string][]byte)
   585  	s.Invokables = make(map[string]*MockStub)
   586  	s.Keys = list.New()
   587  
   588  	return s
   589  }
   590  
   591  /*****************************
   592   Range Query Iterator
   593  *****************************/
   594  
   595  type MockStateRangeQueryIterator struct {
   596  	Closed   bool
   597  	Stub     *MockStub
   598  	StartKey string
   599  	EndKey   string
   600  	Current  *list.Element
   601  }
   602  
   603  // HasNext returns true if the range query iterator contains additional keys
   604  // and values.
   605  func (iter *MockStateRangeQueryIterator) HasNext() bool {
   606  	if iter.Closed {
   607  		// previously called Close()
   608  		mockLogger.Error("HasNext() but already closed")
   609  		return false
   610  	}
   611  
   612  	if iter.Current == nil {
   613  		mockLogger.Error("HasNext() couldn't get Current")
   614  		return false
   615  	}
   616  
   617  	current := iter.Current
   618  	for current != nil {
   619  		// if this is an open-ended query for all keys, return true
   620  		if iter.StartKey == "" && iter.EndKey == "" {
   621  			return true
   622  		}
   623  		comp1 := strings.Compare(current.Value.(string), iter.StartKey)
   624  		comp2 := strings.Compare(current.Value.(string), iter.EndKey)
   625  		if comp1 >= 0 {
   626  			if comp2 <= 0 {
   627  				mockLogger.Debug("HasNext() got next")
   628  				return true
   629  			} else {
   630  				mockLogger.Debug("HasNext() but no next")
   631  				return false
   632  
   633  			}
   634  		}
   635  		current = current.Next()
   636  	}
   637  
   638  	// we've reached the end of the underlying values
   639  	mockLogger.Debug("HasNext() but no next")
   640  	return false
   641  }
   642  
   643  // Next returns the next key and value in the range query iterator.
   644  func (iter *MockStateRangeQueryIterator) Next() (*queryresult.KV, error) {
   645  	if iter.Closed == true {
   646  		mockLogger.Error("MockStateRangeQueryIterator.Next() called after Close()")
   647  		return nil, errors.New("MockStateRangeQueryIterator.Next() called after Close()")
   648  	}
   649  
   650  	if iter.HasNext() == false {
   651  		mockLogger.Error("MockStateRangeQueryIterator.Next() called when it does not HaveNext()")
   652  		return nil, errors.New("MockStateRangeQueryIterator.Next() called when it does not HaveNext()")
   653  	}
   654  
   655  	for iter.Current != nil {
   656  		comp1 := strings.Compare(iter.Current.Value.(string), iter.StartKey)
   657  		comp2 := strings.Compare(iter.Current.Value.(string), iter.EndKey)
   658  		// compare to start and end keys. or, if this is an open-ended query for
   659  		// all keys, it should always return the key and value
   660  		if (comp1 >= 0 && comp2 <= 0) || (iter.StartKey == "" && iter.EndKey == "") {
   661  			key := iter.Current.Value.(string)
   662  			value, err := iter.Stub.GetState(key)
   663  			iter.Current = iter.Current.Next()
   664  			return &queryresult.KV{Key: key, Value: value}, err
   665  		}
   666  		iter.Current = iter.Current.Next()
   667  	}
   668  	mockLogger.Error("MockStateRangeQueryIterator.Next() went past end of range")
   669  	return nil, errors.New("MockStateRangeQueryIterator.Next() went past end of range")
   670  }
   671  
   672  // Close closes the range query iterator. This should be called when done
   673  // reading from the iterator to free up resources.
   674  func (iter *MockStateRangeQueryIterator) Close() error {
   675  	if iter.Closed == true {
   676  		mockLogger.Error("MockStateRangeQueryIterator.Close() called after Close()")
   677  		return errors.New("MockStateRangeQueryIterator.Close() called after Close()")
   678  	}
   679  
   680  	iter.Closed = true
   681  	return nil
   682  }
   683  
   684  func (iter *MockStateRangeQueryIterator) Print() {
   685  	mockLogger.Debug("MockStateRangeQueryIterator {")
   686  	mockLogger.Debug("Closed?", iter.Closed)
   687  	mockLogger.Debug("Stub", iter.Stub)
   688  	mockLogger.Debug("StartKey", iter.StartKey)
   689  	mockLogger.Debug("EndKey", iter.EndKey)
   690  	mockLogger.Debug("Current", iter.Current)
   691  	mockLogger.Debug("HasNext?", iter.HasNext())
   692  	mockLogger.Debug("}")
   693  }
   694  
   695  func NewMockStateRangeQueryIterator(stub *MockStub, startKey string, endKey string) *MockStateRangeQueryIterator {
   696  	mockLogger.Debug("NewMockStateRangeQueryIterator(", stub, startKey, endKey, ")")
   697  	iter := new(MockStateRangeQueryIterator)
   698  	iter.Closed = false
   699  	iter.Stub = stub
   700  	iter.StartKey = startKey
   701  	iter.EndKey = endKey
   702  	iter.Current = stub.Keys.Front()
   703  
   704  	iter.Print()
   705  
   706  	return iter
   707  }
   708  
   709  func getBytes(function string, args []string) [][]byte {
   710  	bytes := make([][]byte, 0, len(args)+1)
   711  	bytes = append(bytes, []byte(function))
   712  	for _, s := range args {
   713  		bytes = append(bytes, []byte(s))
   714  	}
   715  	return bytes
   716  }
   717  
   718  func getFuncArgs(bytes [][]byte) (string, []string) {
   719  	mockLogger.Debugf("getFuncArgs(%x)", bytes)
   720  	function := string(bytes[0])
   721  	args := make([]string, len(bytes)-1)
   722  	for i := 1; i < len(bytes); i++ {
   723  		mockLogger.Debugf("getFuncArgs - i:%x, len(bytes):%x", i, len(bytes))
   724  		args[i-1] = string(bytes[i])
   725  	}
   726  	return function, args
   727  }