github.com/yimialmonte/fabric@v2.1.1+incompatible/core/transientstore/store_helper.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package transientstore 8 9 import ( 10 "bytes" 11 "errors" 12 13 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 14 "github.com/hyperledger/fabric-protos-go/peer" 15 "github.com/hyperledger/fabric/common/ledger/util" 16 "github.com/hyperledger/fabric/core/ledger" 17 ) 18 19 var ( 20 prwsetPrefix = []byte("P")[0] // key prefix for storing private write set in transient store. 21 purgeIndexByHeightPrefix = []byte("H")[0] // key prefix for storing index on private write set using received at block height. 22 purgeIndexByTxidPrefix = []byte("T")[0] // key prefix for storing index on private write set using txid 23 compositeKeySep = byte(0x00) 24 ) 25 26 // createCompositeKeyForPvtRWSet creates a key for storing private write set 27 // in the transient store. The structure of the key is <prwsetPrefix>~txid~uuid~blockHeight. 28 func createCompositeKeyForPvtRWSet(txid string, uuid string, blockHeight uint64) []byte { 29 var compositeKey []byte 30 compositeKey = append(compositeKey, prwsetPrefix) 31 compositeKey = append(compositeKey, compositeKeySep) 32 compositeKey = append(compositeKey, createCompositeKeyWithoutPrefixForTxid(txid, uuid, blockHeight)...) 33 34 return compositeKey 35 } 36 37 // createCompositeKeyForPurgeIndexByTxid creates a key to index private write set based on 38 // txid such that purge based on txid can be achieved. The structure 39 // of the key is <purgeIndexByTxidPrefix>~txid~uuid~blockHeight. 40 func createCompositeKeyForPurgeIndexByTxid(txid string, uuid string, blockHeight uint64) []byte { 41 var compositeKey []byte 42 compositeKey = append(compositeKey, purgeIndexByTxidPrefix) 43 compositeKey = append(compositeKey, compositeKeySep) 44 compositeKey = append(compositeKey, createCompositeKeyWithoutPrefixForTxid(txid, uuid, blockHeight)...) 45 46 return compositeKey 47 } 48 49 // createCompositeKeyWithoutPrefixForTxid creates a composite key of structure txid~uuid~blockHeight. 50 func createCompositeKeyWithoutPrefixForTxid(txid string, uuid string, blockHeight uint64) []byte { 51 var compositeKey []byte 52 compositeKey = append(compositeKey, []byte(txid)...) 53 compositeKey = append(compositeKey, compositeKeySep) 54 compositeKey = append(compositeKey, []byte(uuid)...) 55 compositeKey = append(compositeKey, compositeKeySep) 56 compositeKey = append(compositeKey, util.EncodeOrderPreservingVarUint64(blockHeight)...) 57 58 return compositeKey 59 } 60 61 // createCompositeKeyForPurgeIndexByHeight creates a key to index private write set based on 62 // received at block height such that purge based on block height can be achieved. The structure 63 // of the key is <purgeIndexByHeightPrefix>~blockHeight~txid~uuid. 64 func createCompositeKeyForPurgeIndexByHeight(blockHeight uint64, txid string, uuid string) []byte { 65 var compositeKey []byte 66 compositeKey = append(compositeKey, purgeIndexByHeightPrefix) 67 compositeKey = append(compositeKey, compositeKeySep) 68 compositeKey = append(compositeKey, util.EncodeOrderPreservingVarUint64(blockHeight)...) 69 compositeKey = append(compositeKey, compositeKeySep) 70 compositeKey = append(compositeKey, []byte(txid)...) 71 compositeKey = append(compositeKey, compositeKeySep) 72 compositeKey = append(compositeKey, []byte(uuid)...) 73 74 return compositeKey 75 } 76 77 // splitCompositeKeyOfPvtRWSet splits the compositeKey (<prwsetPrefix>~txid~uuid~blockHeight) 78 // into uuid and blockHeight. 79 func splitCompositeKeyOfPvtRWSet(compositeKey []byte) (uuid string, blockHeight uint64, err error) { 80 return splitCompositeKeyWithoutPrefixForTxid(compositeKey[2:]) 81 } 82 83 // splitCompositeKeyOfPurgeIndexByTxid splits the compositeKey (<purgeIndexByTxidPrefix>~txid~uuid~blockHeight) 84 // into uuid and blockHeight. 85 func splitCompositeKeyOfPurgeIndexByTxid(compositeKey []byte) (uuid string, blockHeight uint64, err error) { 86 return splitCompositeKeyWithoutPrefixForTxid(compositeKey[2:]) 87 } 88 89 // splitCompositeKeyOfPurgeIndexByHeight splits the compositeKey (<purgeIndexByHeightPrefix>~blockHeight~txid~uuid) 90 // into txid, uuid and blockHeight. 91 func splitCompositeKeyOfPurgeIndexByHeight(compositeKey []byte) (txid string, uuid string, blockHeight uint64, err error) { 92 var n int 93 blockHeight, n, err = util.DecodeOrderPreservingVarUint64(compositeKey[2:]) 94 if err != nil { 95 return 96 } 97 splits := bytes.Split(compositeKey[n+3:], []byte{compositeKeySep}) 98 txid = string(splits[0]) 99 uuid = string(splits[1]) 100 return 101 } 102 103 // splitCompositeKeyWithoutPrefixForTxid splits the composite key txid~uuid~blockHeight into 104 // uuid and blockHeight 105 func splitCompositeKeyWithoutPrefixForTxid(compositeKey []byte) (uuid string, blockHeight uint64, err error) { 106 // skip txid as all functions which requires split of composite key already has it 107 firstSepIndex := bytes.IndexByte(compositeKey, compositeKeySep) 108 secondSepIndex := firstSepIndex + bytes.IndexByte(compositeKey[firstSepIndex+1:], compositeKeySep) + 1 109 uuid = string(compositeKey[firstSepIndex+1 : secondSepIndex]) 110 blockHeight, _, err = util.DecodeOrderPreservingVarUint64(compositeKey[secondSepIndex+1:]) 111 return 112 } 113 114 // createTxidRangeStartKey returns a startKey to do a range query on transient store using txid 115 func createTxidRangeStartKey(txid string) []byte { 116 var startKey []byte 117 startKey = append(startKey, prwsetPrefix) 118 startKey = append(startKey, compositeKeySep) 119 startKey = append(startKey, []byte(txid)...) 120 startKey = append(startKey, compositeKeySep) 121 return startKey 122 } 123 124 // createTxidRangeEndKey returns a endKey to do a range query on transient store using txid 125 func createTxidRangeEndKey(txid string) []byte { 126 var endKey []byte 127 endKey = append(endKey, prwsetPrefix) 128 endKey = append(endKey, compositeKeySep) 129 endKey = append(endKey, []byte(txid)...) 130 // As txid is a fixed length string (i.e., 128 bits long UUID), 0xff can be used as a stopper. 131 // Otherwise a super-string of a given txid would also fall under the end key of range query. 132 endKey = append(endKey, byte(0xff)) 133 return endKey 134 } 135 136 // createPurgeIndexByHeightRangeStartKey returns a startKey to do a range query on index stored in transient store 137 // using blockHeight 138 func createPurgeIndexByHeightRangeStartKey(blockHeight uint64) []byte { 139 var startKey []byte 140 startKey = append(startKey, purgeIndexByHeightPrefix) 141 startKey = append(startKey, compositeKeySep) 142 startKey = append(startKey, util.EncodeOrderPreservingVarUint64(blockHeight)...) 143 startKey = append(startKey, compositeKeySep) 144 return startKey 145 } 146 147 // createPurgeIndexByHeightRangeEndKey returns a endKey to do a range query on index stored in transient store 148 // using blockHeight 149 func createPurgeIndexByHeightRangeEndKey(blockHeight uint64) []byte { 150 var endKey []byte 151 endKey = append(endKey, purgeIndexByHeightPrefix) 152 endKey = append(endKey, compositeKeySep) 153 endKey = append(endKey, util.EncodeOrderPreservingVarUint64(blockHeight)...) 154 endKey = append(endKey, byte(0xff)) 155 return endKey 156 } 157 158 // createPurgeIndexByTxidRangeStartKey returns a startKey to do a range query on index stored in transient store 159 // using txid 160 func createPurgeIndexByTxidRangeStartKey(txid string) []byte { 161 var startKey []byte 162 startKey = append(startKey, purgeIndexByTxidPrefix) 163 startKey = append(startKey, compositeKeySep) 164 startKey = append(startKey, []byte(txid)...) 165 startKey = append(startKey, compositeKeySep) 166 return startKey 167 } 168 169 // createPurgeIndexByTxidRangeEndKey returns a endKey to do a range query on index stored in transient store 170 // using txid 171 func createPurgeIndexByTxidRangeEndKey(txid string) []byte { 172 var endKey []byte 173 endKey = append(endKey, purgeIndexByTxidPrefix) 174 endKey = append(endKey, compositeKeySep) 175 endKey = append(endKey, []byte(txid)...) 176 // As txid is a fixed length string (i.e., 128 bits long UUID), 0xff can be used as a stopper. 177 // Otherwise a super-string of a given txid would also fall under the end key of range query. 178 endKey = append(endKey, byte(0xff)) 179 return endKey 180 } 181 182 // trimPvtWSet returns a `TxPvtReadWriteSet` that retains only list of 'ns/collections' supplied in the filter 183 // A nil filter does not filter any results and returns the original `pvtWSet` as is 184 func trimPvtWSet(pvtWSet *rwset.TxPvtReadWriteSet, filter ledger.PvtNsCollFilter) *rwset.TxPvtReadWriteSet { 185 if filter == nil { 186 return pvtWSet 187 } 188 189 var filteredNsRwSet []*rwset.NsPvtReadWriteSet 190 for _, ns := range pvtWSet.NsPvtRwset { 191 var filteredCollRwSet []*rwset.CollectionPvtReadWriteSet 192 for _, coll := range ns.CollectionPvtRwset { 193 if filter.Has(ns.Namespace, coll.CollectionName) { 194 filteredCollRwSet = append(filteredCollRwSet, coll) 195 } 196 } 197 if filteredCollRwSet != nil { 198 filteredNsRwSet = append(filteredNsRwSet, 199 &rwset.NsPvtReadWriteSet{ 200 Namespace: ns.Namespace, 201 CollectionPvtRwset: filteredCollRwSet, 202 }, 203 ) 204 } 205 } 206 var filteredTxPvtRwSet *rwset.TxPvtReadWriteSet 207 if filteredNsRwSet != nil { 208 filteredTxPvtRwSet = &rwset.TxPvtReadWriteSet{ 209 DataModel: pvtWSet.GetDataModel(), 210 NsPvtRwset: filteredNsRwSet, 211 } 212 } 213 return filteredTxPvtRwSet 214 } 215 216 func trimPvtCollectionConfigs(configs map[string]*peer.CollectionConfigPackage, 217 filter ledger.PvtNsCollFilter) (map[string]*peer.CollectionConfigPackage, error) { 218 if filter == nil { 219 return configs, nil 220 } 221 result := make(map[string]*peer.CollectionConfigPackage) 222 223 for ns, pkg := range configs { 224 result[ns] = &peer.CollectionConfigPackage{} 225 for _, colConf := range pkg.GetConfig() { 226 switch cconf := colConf.Payload.(type) { 227 case *peer.CollectionConfig_StaticCollectionConfig: 228 if filter.Has(ns, cconf.StaticCollectionConfig.Name) { 229 result[ns].Config = append(result[ns].Config, colConf) 230 } 231 default: 232 return nil, errors.New("unexpected collection type") 233 } 234 } 235 } 236 return result, nil 237 }