github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/channelinfo_provider.go (about)

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