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 }