github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/core/scc/lscc/deployedcc_infoprovider.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lscc
     8  
     9  import (
    10  	"github.com/golang/protobuf/proto"
    11  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    12  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    13  	"github.com/hyperledger/fabric-protos-go/peer"
    14  	"github.com/osdi23p228/fabric/core/common/ccprovider"
    15  	"github.com/osdi23p228/fabric/core/common/privdata"
    16  	"github.com/osdi23p228/fabric/core/ledger"
    17  	"github.com/osdi23p228/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  const (
    22  	lsccNamespace = "lscc"
    23  )
    24  
    25  // DeployedCCInfoProvider implements interface ledger.DeployedChaincodeInfoProvider
    26  type DeployedCCInfoProvider struct {
    27  }
    28  
    29  // Namespaces implements function in interface ledger.DeployedChaincodeInfoProvider
    30  func (p *DeployedCCInfoProvider) Namespaces() []string {
    31  	return []string{lsccNamespace}
    32  }
    33  
    34  // UpdatedChaincodes implements function in interface ledger.DeployedChaincodeInfoProvider
    35  func (p *DeployedCCInfoProvider) UpdatedChaincodes(stateUpdates map[string][]*kvrwset.KVWrite) ([]*ledger.ChaincodeLifecycleInfo, error) {
    36  	lsccUpdates := stateUpdates[lsccNamespace]
    37  	lifecycleInfo := []*ledger.ChaincodeLifecycleInfo{}
    38  	updatedCCNames := map[string]bool{}
    39  
    40  	for _, kvWrite := range lsccUpdates {
    41  		if rwsetutil.IsKVWriteDelete(kvWrite) {
    42  			// lscc namespace is not expected to have deletes
    43  			continue
    44  		}
    45  		// There are LSCC entries for the chaincode and for the chaincode collections.
    46  		// We can detect collections based on the presence of a CollectionSeparator,
    47  		// which never exists in chaincode names.
    48  		if privdata.IsCollectionConfigKey(kvWrite.Key) {
    49  			ccname := privdata.GetCCNameFromCollectionConfigKey(kvWrite.Key)
    50  			updatedCCNames[ccname] = true
    51  			continue
    52  		}
    53  		updatedCCNames[kvWrite.Key] = true
    54  	}
    55  
    56  	for updatedCCNames := range updatedCCNames {
    57  		lifecycleInfo = append(lifecycleInfo, &ledger.ChaincodeLifecycleInfo{Name: updatedCCNames})
    58  	}
    59  	return lifecycleInfo, nil
    60  }
    61  
    62  func (p *DeployedCCInfoProvider) ImplicitCollections(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) ([]*peer.StaticCollectionConfig, error) {
    63  	return nil, nil
    64  }
    65  
    66  // GenerateImplicitCollectionForOrg is not implemented for legacy chaincodes
    67  func (p *DeployedCCInfoProvider) GenerateImplicitCollectionForOrg(mspid string) *peer.StaticCollectionConfig {
    68  	return nil
    69  }
    70  
    71  // ChaincodeInfo implements function in interface ledger.DeployedChaincodeInfoProvider
    72  func (p *DeployedCCInfoProvider) ChaincodeInfo(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*ledger.DeployedChaincodeInfo, error) {
    73  	chaincodeDataBytes, err := qe.GetState(lsccNamespace, chaincodeName)
    74  	if err != nil || chaincodeDataBytes == nil {
    75  		return nil, err
    76  	}
    77  	chaincodeData := &ccprovider.ChaincodeData{}
    78  	if err := proto.Unmarshal(chaincodeDataBytes, chaincodeData); err != nil {
    79  		return nil, errors.Wrap(err, "error unmarshalling chaincode state data")
    80  	}
    81  	collConfigPkg, err := fetchCollConfigPkg(chaincodeName, qe)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	return &ledger.DeployedChaincodeInfo{
    86  		Name:                        chaincodeName,
    87  		Hash:                        chaincodeData.Id,
    88  		Version:                     chaincodeData.Version,
    89  		ExplicitCollectionConfigPkg: collConfigPkg,
    90  		IsLegacy:                    true,
    91  	}, nil
    92  }
    93  
    94  // AllChaincodesInfo returns the mapping of chaincode name to DeployedChaincodeInfo for legacy chaincodes
    95  func (p *DeployedCCInfoProvider) AllChaincodesInfo(channelName string, qe ledger.SimpleQueryExecutor) (map[string]*ledger.DeployedChaincodeInfo, error) {
    96  	iter, err := qe.GetStateRangeScanIterator(lsccNamespace, "", "")
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	defer iter.Close()
   101  
   102  	result := make(map[string]*ledger.DeployedChaincodeInfo)
   103  	for {
   104  		entry, err := iter.Next()
   105  		if err != nil {
   106  			return nil, err
   107  		}
   108  		if entry == nil {
   109  			break
   110  		}
   111  
   112  		kv := entry.(*queryresult.KV)
   113  		if !privdata.IsCollectionConfigKey(kv.Key) {
   114  			deployedccInfo, err := p.ChaincodeInfo(channelName, kv.Key, qe)
   115  			if err != nil {
   116  				return nil, err
   117  			}
   118  			result[kv.Key] = deployedccInfo
   119  		}
   120  	}
   121  	return result, nil
   122  }
   123  
   124  // AllCollectionsConfigPkg implements function in interface ledger.DeployedChaincodeInfoProvider
   125  // this implementation returns just the explicit collection config package as the implicit collections
   126  // are not used with legacy lifecycle
   127  func (p *DeployedCCInfoProvider) AllCollectionsConfigPkg(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) {
   128  	return fetchCollConfigPkg(chaincodeName, qe)
   129  }
   130  
   131  // CollectionInfo implements function in interface ledger.DeployedChaincodeInfoProvider
   132  func (p *DeployedCCInfoProvider) CollectionInfo(channelName, chaincodeName, collectionName string, qe ledger.SimpleQueryExecutor) (*peer.StaticCollectionConfig, error) {
   133  	collConfigPkg, err := fetchCollConfigPkg(chaincodeName, qe)
   134  	if err != nil || collConfigPkg == nil {
   135  		return nil, err
   136  	}
   137  	for _, conf := range collConfigPkg.Config {
   138  		staticCollConfig := conf.GetStaticCollectionConfig()
   139  		if staticCollConfig != nil && staticCollConfig.Name == collectionName {
   140  			return staticCollConfig, nil
   141  		}
   142  	}
   143  	return nil, nil
   144  }
   145  
   146  func fetchCollConfigPkg(chaincodeName string, qe ledger.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) {
   147  	collKey := privdata.BuildCollectionKVSKey(chaincodeName)
   148  	collectionConfigPkgBytes, err := qe.GetState(lsccNamespace, collKey)
   149  	if err != nil || collectionConfigPkgBytes == nil {
   150  		return nil, err
   151  	}
   152  	collectionConfigPkg := &peer.CollectionConfigPackage{}
   153  	if err := proto.Unmarshal(collectionConfigPkgBytes, collectionConfigPkg); err != nil {
   154  		return nil, errors.Wrap(err, "error unmarshalling chaincode collection config pkg")
   155  	}
   156  	return collectionConfigPkg, nil
   157  }