github.com/renegr87/renegr87@v2.1.1+incompatible/core/ledger/pvtdatastorage/helper.go (about)

     1  /*
     2  Copyright IBM Corp. 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/hyperledger/fabric-protos-go/ledger/rwset"
    13  	"github.com/hyperledger/fabric/core/ledger"
    14  	"github.com/hyperledger/fabric/core/ledger/pvtdatapolicy"
    15  	"github.com/willf/bitset"
    16  )
    17  
    18  func prepareStoreEntries(blockNum uint64, pvtData []*ledger.TxPvtData, btlPolicy pvtdatapolicy.BTLPolicy,
    19  	missingPvtData ledger.TxMissingPvtDataMap) (*storeEntries, error) {
    20  	dataEntries := prepareDataEntries(blockNum, pvtData)
    21  
    22  	missingDataEntries := prepareMissingDataEntries(blockNum, missingPvtData)
    23  
    24  	expiryEntries, err := prepareExpiryEntries(blockNum, dataEntries, missingDataEntries, btlPolicy)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	return &storeEntries{
    30  		dataEntries:        dataEntries,
    31  		expiryEntries:      expiryEntries,
    32  		missingDataEntries: missingDataEntries}, nil
    33  }
    34  
    35  func prepareDataEntries(blockNum uint64, pvtData []*ledger.TxPvtData) []*dataEntry {
    36  	var dataEntries []*dataEntry
    37  	for _, txPvtdata := range pvtData {
    38  		for _, nsPvtdata := range txPvtdata.WriteSet.NsPvtRwset {
    39  			for _, collPvtdata := range nsPvtdata.CollectionPvtRwset {
    40  				txnum := txPvtdata.SeqInBlock
    41  				ns := nsPvtdata.Namespace
    42  				coll := collPvtdata.CollectionName
    43  				dataKey := &dataKey{nsCollBlk{ns, coll, blockNum}, txnum}
    44  				dataEntries = append(dataEntries, &dataEntry{key: dataKey, value: collPvtdata})
    45  			}
    46  		}
    47  	}
    48  	return dataEntries
    49  }
    50  
    51  func prepareMissingDataEntries(committingBlk uint64, missingPvtData ledger.TxMissingPvtDataMap) map[missingDataKey]*bitset.BitSet {
    52  	missingDataEntries := make(map[missingDataKey]*bitset.BitSet)
    53  
    54  	for txNum, missingData := range missingPvtData {
    55  		for _, nsColl := range missingData {
    56  			key := missingDataKey{nsCollBlk{nsColl.Namespace, nsColl.Collection, committingBlk},
    57  				nsColl.IsEligible}
    58  
    59  			if _, ok := missingDataEntries[key]; !ok {
    60  				missingDataEntries[key] = &bitset.BitSet{}
    61  			}
    62  			bitmap := missingDataEntries[key]
    63  
    64  			bitmap.Set(uint(txNum))
    65  		}
    66  	}
    67  
    68  	return missingDataEntries
    69  }
    70  
    71  // prepareExpiryEntries returns expiry entries for both private data which is present in the committingBlk
    72  // and missing private.
    73  func prepareExpiryEntries(committingBlk uint64, dataEntries []*dataEntry, missingDataEntries map[missingDataKey]*bitset.BitSet,
    74  	btlPolicy pvtdatapolicy.BTLPolicy) ([]*expiryEntry, error) {
    75  
    76  	var expiryEntries []*expiryEntry
    77  	mapByExpiringBlk := make(map[uint64]*ExpiryData)
    78  
    79  	// 1. prepare expiryData for non-missing data
    80  	for _, dataEntry := range dataEntries {
    81  		prepareExpiryEntriesForPresentData(mapByExpiringBlk, dataEntry.key, btlPolicy)
    82  	}
    83  
    84  	// 2. prepare expiryData for missing data
    85  	for missingDataKey := range missingDataEntries {
    86  		prepareExpiryEntriesForMissingData(mapByExpiringBlk, &missingDataKey, btlPolicy)
    87  	}
    88  
    89  	for expiryBlk, expiryData := range mapByExpiringBlk {
    90  		expiryKey := &expiryKey{expiringBlk: expiryBlk, committingBlk: committingBlk}
    91  		expiryEntries = append(expiryEntries, &expiryEntry{key: expiryKey, value: expiryData})
    92  	}
    93  
    94  	return expiryEntries, nil
    95  }
    96  
    97  // prepareExpiryDataForPresentData creates expiryData for non-missing pvt data
    98  func prepareExpiryEntriesForPresentData(mapByExpiringBlk map[uint64]*ExpiryData, dataKey *dataKey, btlPolicy pvtdatapolicy.BTLPolicy) error {
    99  	expiringBlk, err := btlPolicy.GetExpiringBlock(dataKey.ns, dataKey.coll, dataKey.blkNum)
   100  	if err != nil {
   101  		return err
   102  	}
   103  	if neverExpires(expiringBlk) {
   104  		return nil
   105  	}
   106  
   107  	expiryData := getOrCreateExpiryData(mapByExpiringBlk, expiringBlk)
   108  
   109  	expiryData.addPresentData(dataKey.ns, dataKey.coll, dataKey.txNum)
   110  	return nil
   111  }
   112  
   113  // prepareExpiryDataForMissingData creates expiryData for missing pvt data
   114  func prepareExpiryEntriesForMissingData(mapByExpiringBlk map[uint64]*ExpiryData, missingKey *missingDataKey, btlPolicy pvtdatapolicy.BTLPolicy) error {
   115  	expiringBlk, err := btlPolicy.GetExpiringBlock(missingKey.ns, missingKey.coll, missingKey.blkNum)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	if neverExpires(expiringBlk) {
   120  		return nil
   121  	}
   122  
   123  	expiryData := getOrCreateExpiryData(mapByExpiringBlk, expiringBlk)
   124  
   125  	expiryData.addMissingData(missingKey.ns, missingKey.coll)
   126  	return nil
   127  }
   128  
   129  func getOrCreateExpiryData(mapByExpiringBlk map[uint64]*ExpiryData, expiringBlk uint64) *ExpiryData {
   130  	expiryData, ok := mapByExpiringBlk[expiringBlk]
   131  	if !ok {
   132  		expiryData = newExpiryData()
   133  		mapByExpiringBlk[expiringBlk] = expiryData
   134  	}
   135  	return expiryData
   136  }
   137  
   138  // deriveKeys constructs dataKeys and missingDataKey from an expiryEntry
   139  func deriveKeys(expiryEntry *expiryEntry) (dataKeys []*dataKey, missingDataKeys []*missingDataKey) {
   140  	for ns, colls := range expiryEntry.value.Map {
   141  		// 1. constructs dataKeys of expired existing pvt data
   142  		for coll, txNums := range colls.Map {
   143  			for _, txNum := range txNums.List {
   144  				dataKeys = append(dataKeys,
   145  					&dataKey{nsCollBlk{ns, coll, expiryEntry.key.committingBlk}, txNum})
   146  			}
   147  		}
   148  		// 2. constructs missingDataKeys of expired missing pvt data
   149  		for coll := range colls.MissingDataMap {
   150  			// one key for eligible entries and another for ieligible entries
   151  			missingDataKeys = append(missingDataKeys,
   152  				&missingDataKey{nsCollBlk{ns, coll, expiryEntry.key.committingBlk}, true})
   153  			missingDataKeys = append(missingDataKeys,
   154  				&missingDataKey{nsCollBlk{ns, coll, expiryEntry.key.committingBlk}, false})
   155  
   156  		}
   157  	}
   158  	return
   159  }
   160  
   161  func passesFilter(dataKey *dataKey, filter ledger.PvtNsCollFilter) bool {
   162  	return filter == nil || filter.Has(dataKey.ns, dataKey.coll)
   163  }
   164  
   165  func isExpired(key nsCollBlk, btl pvtdatapolicy.BTLPolicy, latestBlkNum uint64) (bool, error) {
   166  	expiringBlk, err := btl.GetExpiringBlock(key.ns, key.coll, key.blkNum)
   167  	if err != nil {
   168  		return false, err
   169  	}
   170  
   171  	return latestBlkNum >= expiringBlk, nil
   172  }
   173  
   174  func neverExpires(expiringBlkNum uint64) bool {
   175  	return expiringBlkNum == math.MaxUint64
   176  }
   177  
   178  type txPvtdataAssembler struct {
   179  	blockNum, txNum uint64
   180  	txWset          *rwset.TxPvtReadWriteSet
   181  	currentNsWSet   *rwset.NsPvtReadWriteSet
   182  	firstCall       bool
   183  }
   184  
   185  func newTxPvtdataAssembler(blockNum, txNum uint64) *txPvtdataAssembler {
   186  	return &txPvtdataAssembler{blockNum, txNum, &rwset.TxPvtReadWriteSet{}, nil, true}
   187  }
   188  
   189  func (a *txPvtdataAssembler) add(ns string, collPvtWset *rwset.CollectionPvtReadWriteSet) {
   190  	// start a NsWset
   191  	if a.firstCall {
   192  		a.currentNsWSet = &rwset.NsPvtReadWriteSet{Namespace: ns}
   193  		a.firstCall = false
   194  	}
   195  
   196  	// if a new ns started, add the existing NsWset to TxWset and start a new one
   197  	if a.currentNsWSet.Namespace != ns {
   198  		a.txWset.NsPvtRwset = append(a.txWset.NsPvtRwset, a.currentNsWSet)
   199  		a.currentNsWSet = &rwset.NsPvtReadWriteSet{Namespace: ns}
   200  	}
   201  	// add the collWset to the current NsWset
   202  	a.currentNsWSet.CollectionPvtRwset = append(a.currentNsWSet.CollectionPvtRwset, collPvtWset)
   203  }
   204  
   205  func (a *txPvtdataAssembler) done() {
   206  	if a.currentNsWSet != nil {
   207  		a.txWset.NsPvtRwset = append(a.txWset.NsPvtRwset, a.currentNsWSet)
   208  	}
   209  	a.currentNsWSet = nil
   210  }
   211  
   212  func (a *txPvtdataAssembler) getTxPvtdata() *ledger.TxPvtData {
   213  	a.done()
   214  	return &ledger.TxPvtData{SeqInBlock: a.txNum, WriteSet: a.txWset}
   215  }