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 }