github.com/ewagmig/fabric@v2.1.1+incompatible/core/chaincode/lifecycle/ledger_shim.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lifecycle
     8  
     9  import (
    10  	"github.com/hyperledger/fabric-chaincode-go/shim"
    11  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    12  	commonledger "github.com/hyperledger/fabric/common/ledger"
    13  	validatorstate "github.com/hyperledger/fabric/core/handlers/validation/api/state"
    14  	"github.com/hyperledger/fabric/core/ledger"
    15  
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  type StateIterator interface {
    20  	Close() error
    21  	Next() (*queryresult.KV, error)
    22  }
    23  
    24  // StateIteratorToMap takes an iterator, and iterates over the entire thing, encoding the KVs
    25  // into a map, and then closes it.
    26  func StateIteratorToMap(itr StateIterator) (map[string][]byte, error) {
    27  	defer itr.Close()
    28  	result := map[string][]byte{}
    29  	for {
    30  		entry, err := itr.Next()
    31  		if err != nil {
    32  			return nil, errors.WithMessage(err, "could not iterate over range")
    33  		}
    34  		if entry == nil {
    35  			return result, nil
    36  		}
    37  		result[entry.Key] = entry.Value
    38  	}
    39  }
    40  
    41  // ChaincodePublicLedgerShim decorates the chaincode shim to support the state interfaces
    42  // required by the serialization code.
    43  type ChaincodePublicLedgerShim struct {
    44  	shim.ChaincodeStubInterface
    45  }
    46  
    47  // GetStateRange performs a range query for keys beginning with a particular prefix, and
    48  // returns it as a map. This function assumes that keys contain only ascii chars from \x00 to \x7e.
    49  func (cls *ChaincodePublicLedgerShim) GetStateRange(prefix string) (map[string][]byte, error) {
    50  	itr, err := cls.GetStateByRange(prefix, prefix+"\x7f")
    51  	if err != nil {
    52  		return nil, errors.WithMessage(err, "could not get state iterator")
    53  	}
    54  	return StateIteratorToMap(&ChaincodeResultIteratorShim{ResultsIterator: itr})
    55  }
    56  
    57  type ChaincodeResultIteratorShim struct {
    58  	ResultsIterator shim.StateQueryIteratorInterface
    59  }
    60  
    61  func (cris *ChaincodeResultIteratorShim) Next() (*queryresult.KV, error) {
    62  	if !cris.ResultsIterator.HasNext() {
    63  		return nil, nil
    64  	}
    65  	return cris.ResultsIterator.Next()
    66  }
    67  
    68  func (cris *ChaincodeResultIteratorShim) Close() error {
    69  	return cris.ResultsIterator.Close()
    70  }
    71  
    72  // ChaincodePrivateLedgerShim wraps the chaincode shim to make access to keys in a collection
    73  // have the same semantics as normal public keys.
    74  type ChaincodePrivateLedgerShim struct {
    75  	Stub       shim.ChaincodeStubInterface
    76  	Collection string
    77  }
    78  
    79  // GetStateRange performs a range query in the configured collection for all keys beginning
    80  // with a particular prefix.  This function assumes that keys contain only ascii chars from \x00 to \x7e.
    81  func (cls *ChaincodePrivateLedgerShim) GetStateRange(prefix string) (map[string][]byte, error) {
    82  	itr, err := cls.Stub.GetPrivateDataByRange(cls.Collection, prefix, prefix+"\x7f")
    83  	if err != nil {
    84  		return nil, errors.WithMessage(err, "could not get state iterator")
    85  	}
    86  	return StateIteratorToMap(&ChaincodeResultIteratorShim{ResultsIterator: itr})
    87  }
    88  
    89  // GetState returns the value for the key in the configured collection.
    90  func (cls *ChaincodePrivateLedgerShim) GetState(key string) ([]byte, error) {
    91  	return cls.Stub.GetPrivateData(cls.Collection, key)
    92  }
    93  
    94  // GetStateHash return the hash of the pre-image for the key in the configured collection.
    95  func (cls *ChaincodePrivateLedgerShim) GetStateHash(key string) ([]byte, error) {
    96  	return cls.Stub.GetPrivateDataHash(cls.Collection, key)
    97  }
    98  
    99  // PutState sets the value for the key in the configured collection.
   100  func (cls *ChaincodePrivateLedgerShim) PutState(key string, value []byte) error {
   101  	return cls.Stub.PutPrivateData(cls.Collection, key, value)
   102  }
   103  
   104  // DelState deletes the key in the configured collection.
   105  func (cls *ChaincodePrivateLedgerShim) DelState(key string) error {
   106  	return cls.Stub.DelPrivateData(cls.Collection, key)
   107  }
   108  
   109  func (cls *ChaincodePrivateLedgerShim) CollectionName() string {
   110  	return cls.Collection
   111  }
   112  
   113  // SimpleQueryExecutorShim implements the ReadableState and RangeableState interfaces
   114  // based on an underlying ledger.SimpleQueryExecutor
   115  type SimpleQueryExecutorShim struct {
   116  	Namespace           string
   117  	SimpleQueryExecutor ledger.SimpleQueryExecutor
   118  }
   119  
   120  func (sqes *SimpleQueryExecutorShim) GetState(key string) ([]byte, error) {
   121  	return sqes.SimpleQueryExecutor.GetState(sqes.Namespace, key)
   122  }
   123  
   124  func (sqes *SimpleQueryExecutorShim) GetStateRange(prefix string) (map[string][]byte, error) {
   125  	itr, err := sqes.SimpleQueryExecutor.GetStateRangeScanIterator(sqes.Namespace, prefix, prefix+"\x7f")
   126  	if err != nil {
   127  		return nil, errors.WithMessage(err, "could not get state iterator")
   128  	}
   129  	return StateIteratorToMap(&ResultsIteratorShim{ResultsIterator: itr})
   130  }
   131  
   132  type ResultsIteratorShim struct {
   133  	ResultsIterator commonledger.ResultsIterator
   134  }
   135  
   136  func (ris *ResultsIteratorShim) Next() (*queryresult.KV, error) {
   137  	res, err := ris.ResultsIterator.Next()
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	if res == nil {
   142  		return nil, nil
   143  	}
   144  	return res.(*queryresult.KV), err
   145  }
   146  
   147  func (ris *ResultsIteratorShim) Close() error {
   148  	ris.ResultsIterator.Close()
   149  	return nil
   150  }
   151  
   152  type ValidatorStateShim struct {
   153  	ValidatorState validatorstate.State
   154  	Namespace      string
   155  }
   156  
   157  func (vss *ValidatorStateShim) GetState(key string) ([]byte, error) {
   158  	result, err := vss.ValidatorState.GetStateMultipleKeys(vss.Namespace, []string{key})
   159  	if err != nil {
   160  		return nil, errors.WithMessage(err, "could not get state thought validatorstate shim")
   161  	}
   162  	return result[0], nil
   163  }
   164  
   165  type PrivateQueryExecutor interface {
   166  	GetPrivateDataHash(namespace, collection, key string) (value []byte, err error)
   167  }
   168  
   169  type PrivateQueryExecutorShim struct {
   170  	Namespace  string
   171  	Collection string
   172  	State      PrivateQueryExecutor
   173  }
   174  
   175  func (pqes *PrivateQueryExecutorShim) GetStateHash(key string) ([]byte, error) {
   176  	return pqes.State.GetPrivateDataHash(pqes.Namespace, pqes.Collection, key)
   177  }
   178  
   179  func (pqes *PrivateQueryExecutorShim) CollectionName() string {
   180  	return pqes.Collection
   181  }
   182  
   183  // DummyQueryExecutorShim implements the ReadableState interface. It is
   184  // used to ensure channel-less system chaincode calls don't panic and return
   185  // and error when an invalid operation is attempted (i.e. an InstallChaincode
   186  // invocation against a chaincode other than _lifecycle)
   187  type DummyQueryExecutorShim struct {
   188  }
   189  
   190  func (*DummyQueryExecutorShim) GetState(key string) ([]byte, error) {
   191  	return nil, errors.New("invalid channel-less operation")
   192  }