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  }