github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/pvtdatastorage/helper.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package pvtdatastorage 8 9 import ( 10 "math" 11 12 "github.com/hechain20/hechain/core/ledger" 13 "github.com/hechain20/hechain/core/ledger/pvtdatapolicy" 14 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 15 "github.com/willf/bitset" 16 ) 17 18 func prepareStoreEntries(blockNum uint64, pvtData []*ledger.TxPvtData, btlPolicy pvtdatapolicy.BTLPolicy, 19 missingPvtData ledger.TxMissingPvtData) (*storeEntries, error) { 20 dataEntries := prepareDataEntries(blockNum, pvtData) 21 22 elgMissingDataEntries, inelgMissingDataEntries := prepareMissingDataEntries(blockNum, missingPvtData) 23 24 expiryEntries, err := prepareExpiryEntries(blockNum, dataEntries, elgMissingDataEntries, inelgMissingDataEntries, btlPolicy) 25 if err != nil { 26 return nil, err 27 } 28 29 return &storeEntries{ 30 dataEntries: dataEntries, 31 expiryEntries: expiryEntries, 32 elgMissingDataEntries: elgMissingDataEntries, 33 inelgMissingDataEntries: inelgMissingDataEntries, 34 }, nil 35 } 36 37 func prepareDataEntries(blockNum uint64, pvtData []*ledger.TxPvtData) []*dataEntry { 38 var dataEntries []*dataEntry 39 for _, txPvtdata := range pvtData { 40 for _, nsPvtdata := range txPvtdata.WriteSet.NsPvtRwset { 41 for _, collPvtdata := range nsPvtdata.CollectionPvtRwset { 42 txnum := txPvtdata.SeqInBlock 43 ns := nsPvtdata.Namespace 44 coll := collPvtdata.CollectionName 45 dataKey := &dataKey{nsCollBlk{ns, coll, blockNum}, txnum} 46 dataEntries = append(dataEntries, &dataEntry{key: dataKey, value: collPvtdata}) 47 } 48 } 49 } 50 return dataEntries 51 } 52 53 func prepareMissingDataEntries( 54 committingBlk uint64, 55 missingPvtData ledger.TxMissingPvtData, 56 ) (map[missingDataKey]*bitset.BitSet, map[missingDataKey]*bitset.BitSet) { 57 elgMissingDataEntries := make(map[missingDataKey]*bitset.BitSet) 58 inelgMissingDataEntries := make(map[missingDataKey]*bitset.BitSet) 59 60 for txNum, missingData := range missingPvtData { 61 for _, nsColl := range missingData { 62 key := missingDataKey{ 63 nsCollBlk{ 64 ns: nsColl.Namespace, 65 coll: nsColl.Collection, 66 blkNum: committingBlk, 67 }, 68 } 69 70 switch nsColl.IsEligible { 71 case true: 72 if _, ok := elgMissingDataEntries[key]; !ok { 73 elgMissingDataEntries[key] = &bitset.BitSet{} 74 } 75 elgMissingDataEntries[key].Set(uint(txNum)) 76 default: 77 if _, ok := inelgMissingDataEntries[key]; !ok { 78 inelgMissingDataEntries[key] = &bitset.BitSet{} 79 } 80 inelgMissingDataEntries[key].Set(uint(txNum)) 81 } 82 } 83 } 84 85 return elgMissingDataEntries, inelgMissingDataEntries 86 } 87 88 // prepareExpiryEntries returns expiry entries for both private data which is present in the committingBlk 89 // and missing private. 90 func prepareExpiryEntries(committingBlk uint64, dataEntries []*dataEntry, elgMissingDataEntries, inelgMissingDataEntries map[missingDataKey]*bitset.BitSet, 91 btlPolicy pvtdatapolicy.BTLPolicy) ([]*expiryEntry, error) { 92 var expiryEntries []*expiryEntry 93 mapByExpiringBlk := make(map[uint64]*ExpiryData) 94 95 for _, dataEntry := range dataEntries { 96 if err := prepareExpiryEntriesForPresentData(mapByExpiringBlk, dataEntry.key, btlPolicy); err != nil { 97 return nil, err 98 } 99 } 100 101 for missingDataKey := range elgMissingDataEntries { 102 if err := prepareExpiryEntriesForMissingData(mapByExpiringBlk, &missingDataKey, btlPolicy); err != nil { 103 return nil, err 104 } 105 } 106 107 for missingDataKey := range inelgMissingDataEntries { 108 if err := prepareExpiryEntriesForMissingData(mapByExpiringBlk, &missingDataKey, btlPolicy); err != nil { 109 return nil, err 110 } 111 } 112 113 for expiryBlk, expiryData := range mapByExpiringBlk { 114 expiryKey := &expiryKey{expiringBlk: expiryBlk, committingBlk: committingBlk} 115 expiryEntries = append(expiryEntries, &expiryEntry{key: expiryKey, value: expiryData}) 116 } 117 118 return expiryEntries, nil 119 } 120 121 // prepareExpiryDataForPresentData creates expiryData for non-missing pvt data 122 func prepareExpiryEntriesForPresentData(mapByExpiringBlk map[uint64]*ExpiryData, dataKey *dataKey, btlPolicy pvtdatapolicy.BTLPolicy) error { 123 expiringBlk, err := btlPolicy.GetExpiringBlock(dataKey.ns, dataKey.coll, dataKey.blkNum) 124 if err != nil { 125 return err 126 } 127 if neverExpires(expiringBlk) { 128 return nil 129 } 130 131 expiryData := getOrCreateExpiryData(mapByExpiringBlk, expiringBlk) 132 133 expiryData.addPresentData(dataKey.ns, dataKey.coll, dataKey.txNum) 134 return nil 135 } 136 137 // prepareExpiryDataForMissingData creates expiryData for missing pvt data 138 func prepareExpiryEntriesForMissingData(mapByExpiringBlk map[uint64]*ExpiryData, missingKey *missingDataKey, btlPolicy pvtdatapolicy.BTLPolicy) error { 139 expiringBlk, err := btlPolicy.GetExpiringBlock(missingKey.ns, missingKey.coll, missingKey.blkNum) 140 if err != nil { 141 return err 142 } 143 if neverExpires(expiringBlk) { 144 return nil 145 } 146 147 expiryData := getOrCreateExpiryData(mapByExpiringBlk, expiringBlk) 148 149 expiryData.addMissingData(missingKey.ns, missingKey.coll) 150 return nil 151 } 152 153 func getOrCreateExpiryData(mapByExpiringBlk map[uint64]*ExpiryData, expiringBlk uint64) *ExpiryData { 154 expiryData, ok := mapByExpiringBlk[expiringBlk] 155 if !ok { 156 expiryData = newExpiryData() 157 mapByExpiringBlk[expiringBlk] = expiryData 158 } 159 return expiryData 160 } 161 162 func deriveKeys(expiryEntry *expiryEntry) ([]*dataKey, []*missingDataKey, []*bootKVHashesKey) { 163 var dataKeys []*dataKey 164 var missingDataKeys []*missingDataKey 165 var bootKVHashesKeys []*bootKVHashesKey 166 167 for ns, colls := range expiryEntry.value.Map { 168 for coll, txNums := range colls.PresentData { 169 for _, txNum := range txNums.List { 170 dataKeys = append(dataKeys, 171 &dataKey{ 172 nsCollBlk: nsCollBlk{ 173 ns: ns, 174 coll: coll, 175 blkNum: expiryEntry.key.committingBlk, 176 }, 177 txNum: txNum, 178 }) 179 } 180 } 181 182 for coll := range colls.MissingData { 183 missingDataKeys = append(missingDataKeys, 184 &missingDataKey{ 185 nsCollBlk: nsCollBlk{ 186 ns: ns, 187 coll: coll, 188 blkNum: expiryEntry.key.committingBlk, 189 }, 190 }) 191 } 192 193 for coll, txNums := range colls.BootKVHashes { 194 for _, txNum := range txNums.List { 195 bootKVHashesKeys = append(bootKVHashesKeys, 196 &bootKVHashesKey{ 197 blkNum: expiryEntry.key.committingBlk, 198 txNum: txNum, 199 ns: ns, 200 coll: coll, 201 }, 202 ) 203 } 204 } 205 } 206 207 return dataKeys, missingDataKeys, bootKVHashesKeys 208 } 209 210 func passesFilter(dataKey *dataKey, filter ledger.PvtNsCollFilter) bool { 211 return filter == nil || filter.Has(dataKey.ns, dataKey.coll) 212 } 213 214 func isExpired(key nsCollBlk, btl pvtdatapolicy.BTLPolicy, latestBlkNum uint64) (bool, error) { 215 expiringBlk, err := btl.GetExpiringBlock(key.ns, key.coll, key.blkNum) 216 if err != nil { 217 return false, err 218 } 219 220 return latestBlkNum >= expiringBlk, nil 221 } 222 223 func neverExpires(expiringBlkNum uint64) bool { 224 return expiringBlkNum == math.MaxUint64 225 } 226 227 type txPvtdataAssembler struct { 228 blockNum, txNum uint64 229 txWset *rwset.TxPvtReadWriteSet 230 currentNsWSet *rwset.NsPvtReadWriteSet 231 firstCall bool 232 } 233 234 func newTxPvtdataAssembler(blockNum, txNum uint64) *txPvtdataAssembler { 235 return &txPvtdataAssembler{blockNum, txNum, &rwset.TxPvtReadWriteSet{}, nil, true} 236 } 237 238 func (a *txPvtdataAssembler) add(ns string, collPvtWset *rwset.CollectionPvtReadWriteSet) { 239 // start a NsWset 240 if a.firstCall { 241 a.currentNsWSet = &rwset.NsPvtReadWriteSet{Namespace: ns} 242 a.firstCall = false 243 } 244 245 // if a new ns started, add the existing NsWset to TxWset and start a new one 246 if a.currentNsWSet.Namespace != ns { 247 a.txWset.NsPvtRwset = append(a.txWset.NsPvtRwset, a.currentNsWSet) 248 a.currentNsWSet = &rwset.NsPvtReadWriteSet{Namespace: ns} 249 } 250 // add the collWset to the current NsWset 251 a.currentNsWSet.CollectionPvtRwset = append(a.currentNsWSet.CollectionPvtRwset, collPvtWset) 252 } 253 254 func (a *txPvtdataAssembler) done() { 255 if a.currentNsWSet != nil { 256 a.txWset.NsPvtRwset = append(a.txWset.NsPvtRwset, a.currentNsWSet) 257 } 258 a.currentNsWSet = nil 259 } 260 261 func (a *txPvtdataAssembler) getTxPvtdata() *ledger.TxPvtData { 262 a.done() 263 return &ledger.TxPvtData{SeqInBlock: a.txNum, WriteSet: a.txWset} 264 }