github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/core/ledger/kvledger/channelinfo_provider.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package kvledger
     8  
     9  import (
    10  	cb "github.com/hyperledger/fabric-protos-go/common"
    11  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    12  	"github.com/osdi23p228/fabric/bccsp/factory"
    13  	"github.com/osdi23p228/fabric/common/channelconfig"
    14  	commonledger "github.com/osdi23p228/fabric/common/ledger"
    15  	"github.com/osdi23p228/fabric/common/ledger/blkstorage"
    16  	"github.com/osdi23p228/fabric/core/ledger"
    17  	"github.com/osdi23p228/fabric/core/ledger/kvledger/txmgmt/statedb"
    18  	"github.com/osdi23p228/fabric/protoutil"
    19  	"github.com/pkg/errors"
    20  )
    21  
    22  type channelInfoProvider struct {
    23  	channelName string
    24  	blockStore  *blkstorage.BlockStore
    25  	ledger.DeployedChaincodeInfoProvider
    26  }
    27  
    28  // NamespacesAndCollections returns namespaces and their collections for the channel.
    29  func (p *channelInfoProvider) NamespacesAndCollections(vdb statedb.VersionedDB) (map[string][]string, error) {
    30  	mspIDs, err := p.getAllMSPIDs()
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	implicitCollNames := make([]string, len(mspIDs))
    35  	for i, mspID := range mspIDs {
    36  		implicitCollNames[i] = p.GenerateImplicitCollectionForOrg(mspID).Name
    37  	}
    38  	chaincodesInfo, err := p.AllChaincodesInfo(p.channelName, &simpleQueryExecutor{vdb})
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	retNamespaces := map[string][]string{}
    44  	// iterate each chaincode, add implicit collections and explicit collections
    45  	for _, ccInfo := range chaincodesInfo {
    46  		ccName := ccInfo.Name
    47  		retNamespaces[ccName] = []string{}
    48  		for _, implicitCollName := range implicitCollNames {
    49  			retNamespaces[ccName] = append(retNamespaces[ccName], implicitCollName)
    50  		}
    51  		if ccInfo.ExplicitCollectionConfigPkg == nil {
    52  			continue
    53  		}
    54  		for _, config := range ccInfo.ExplicitCollectionConfigPkg.Config {
    55  			collConfig := config.GetStaticCollectionConfig()
    56  			if collConfig != nil {
    57  				retNamespaces[ccName] = append(retNamespaces[ccName], collConfig.Name)
    58  			}
    59  		}
    60  	}
    61  
    62  	// add lifecycle management namespaces with implicit collections (not applicable to legacy lifecycle)
    63  	for _, ns := range p.Namespaces() {
    64  		retNamespaces[ns] = []string{}
    65  		if ns == "lscc" {
    66  			continue
    67  		}
    68  		for _, implicitCollName := range implicitCollNames {
    69  			retNamespaces[ns] = append(retNamespaces[ns], implicitCollName)
    70  		}
    71  	}
    72  
    73  	// add namespace ""
    74  	retNamespaces[""] = []string{}
    75  	return retNamespaces, nil
    76  }
    77  
    78  // getAllMSPIDs retrieves the MSPIDs of application organizations in all the channel configurations,
    79  // including current and previous channel configurations.
    80  func (p *channelInfoProvider) getAllMSPIDs() ([]string, error) {
    81  	blockchainInfo, err := p.blockStore.GetBlockchainInfo()
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	if blockchainInfo.Height == 0 {
    86  		return nil, nil
    87  	}
    88  
    89  	// Iterate over the config blocks to get all the channel configs, extract MSPIDs and add to mspidsMap
    90  	mspidsMap := map[string]struct{}{}
    91  	blockNum := blockchainInfo.Height - 1
    92  	for {
    93  		configBlock, err := p.mostRecentConfigBlockAsOf(blockNum)
    94  		if err != nil {
    95  			return nil, err
    96  		}
    97  
    98  		mspids, err := channelconfig.ExtractMSPIDsForApplicationOrgs(configBlock, factory.GetDefault())
    99  		if err != nil {
   100  			return nil, err
   101  		}
   102  		for _, mspid := range mspids {
   103  			if _, ok := mspidsMap[mspid]; !ok {
   104  				mspidsMap[mspid] = struct{}{}
   105  			}
   106  		}
   107  
   108  		if configBlock.Header.Number == 0 {
   109  			break
   110  		}
   111  		blockNum = configBlock.Header.Number - 1
   112  	}
   113  
   114  	mspids := make([]string, 0, len(mspidsMap))
   115  	for mspid := range mspidsMap {
   116  		mspids = append(mspids, mspid)
   117  	}
   118  	return mspids, nil
   119  }
   120  
   121  // mostRecentConfigBlockAsOf fetches the most recent config block at or below the blockNum
   122  func (p *channelInfoProvider) mostRecentConfigBlockAsOf(blockNum uint64) (*cb.Block, error) {
   123  	block, err := p.blockStore.RetrieveBlockByNumber(blockNum)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	configBlockNum, err := protoutil.GetLastConfigIndexFromBlock(block)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	return p.blockStore.RetrieveBlockByNumber(configBlockNum)
   132  }
   133  
   134  // simpleQueryExecutor implements ledger.SimpleQueryExecutor interface
   135  type simpleQueryExecutor struct {
   136  	statedb.VersionedDB
   137  }
   138  
   139  func (sqe *simpleQueryExecutor) GetState(ns string, key string) ([]byte, error) {
   140  	versionedValue, err := sqe.VersionedDB.GetState(ns, key)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  	var value []byte
   145  	if versionedValue != nil {
   146  		value = versionedValue.Value
   147  	}
   148  	return value, nil
   149  }
   150  
   151  func (sqe *simpleQueryExecutor) GetStateRangeScanIterator(ns string, startKey string, endKey string) (commonledger.ResultsIterator, error) {
   152  	dbItr, err := sqe.VersionedDB.GetStateRangeScanIterator(ns, startKey, endKey)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  	itr := &resultsItr{ns: ns, dbItr: dbItr}
   157  	return itr, nil
   158  }
   159  
   160  // GetPrivateDataHash is not implemented and should not be called
   161  func (sqe *simpleQueryExecutor) GetPrivateDataHash(namespace, collection, key string) ([]byte, error) {
   162  	return nil, errors.New("not implemented yet")
   163  }
   164  
   165  type resultsItr struct {
   166  	ns    string
   167  	dbItr statedb.ResultsIterator
   168  }
   169  
   170  // Next implements method in interface ledger.ResultsIterator
   171  func (itr *resultsItr) Next() (commonledger.QueryResult, error) {
   172  	queryResult, err := itr.dbItr.Next()
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  	// itr.updateRangeQueryInfo(queryResult)
   177  	if queryResult == nil {
   178  		return nil, nil
   179  	}
   180  	versionedKV := queryResult.(*statedb.VersionedKV)
   181  	return &queryresult.KV{Namespace: versionedKV.Namespace, Key: versionedKV.Key, Value: versionedKV.Value}, nil
   182  }
   183  
   184  // Close implements method in interface ledger.ResultsIterator
   185  func (itr *resultsItr) Close() {
   186  	itr.dbItr.Close()
   187  }