github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/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/rwset/kvrwset"
    12  	"github.com/hyperledger/fabric-protos-go/peer"
    13  	"github.com/hyperledger/fabric/core/common/ccprovider"
    14  	"github.com/hyperledger/fabric/core/common/privdata"
    15  	"github.com/hyperledger/fabric/core/ledger"
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  const (
    20  	lsccNamespace = "lscc"
    21  )
    22  
    23  // DeployedCCInfoProvider implements interface ledger.DeployedChaincodeInfoProvider
    24  type DeployedCCInfoProvider struct {
    25  }
    26  
    27  // Namespaces implements function in interface ledger.DeployedChaincodeInfoProvider
    28  func (p *DeployedCCInfoProvider) Namespaces() []string {
    29  	return []string{lsccNamespace}
    30  }
    31  
    32  // UpdatedChaincodes implements function in interface ledger.DeployedChaincodeInfoProvider
    33  func (p *DeployedCCInfoProvider) UpdatedChaincodes(stateUpdates map[string][]*kvrwset.KVWrite) ([]*ledger.ChaincodeLifecycleInfo, error) {
    34  	lsccUpdates := stateUpdates[lsccNamespace]
    35  	lifecycleInfo := []*ledger.ChaincodeLifecycleInfo{}
    36  	updatedCCNames := map[string]bool{}
    37  
    38  	for _, kvWrite := range lsccUpdates {
    39  		if kvWrite.IsDelete {
    40  			// lscc namespace is not expected to have deletes
    41  			continue
    42  		}
    43  		// There are LSCC entries for the chaincode and for the chaincode collections.
    44  		// We can detect collections based on the presence of a CollectionSeparator,
    45  		// which never exists in chaincode names.
    46  		if privdata.IsCollectionConfigKey(kvWrite.Key) {
    47  			ccname := privdata.GetCCNameFromCollectionConfigKey(kvWrite.Key)
    48  			updatedCCNames[ccname] = true
    49  			continue
    50  		}
    51  		updatedCCNames[kvWrite.Key] = true
    52  	}
    53  
    54  	for updatedCCNames := range updatedCCNames {
    55  		lifecycleInfo = append(lifecycleInfo, &ledger.ChaincodeLifecycleInfo{Name: updatedCCNames})
    56  	}
    57  	return lifecycleInfo, nil
    58  }
    59  
    60  func (p *DeployedCCInfoProvider) ImplicitCollections(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) ([]*peer.StaticCollectionConfig, error) {
    61  	return nil, nil
    62  }
    63  
    64  // ChaincodeInfo implements function in interface ledger.DeployedChaincodeInfoProvider
    65  func (p *DeployedCCInfoProvider) ChaincodeInfo(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*ledger.DeployedChaincodeInfo, error) {
    66  	chaincodeDataBytes, err := qe.GetState(lsccNamespace, chaincodeName)
    67  	if err != nil || chaincodeDataBytes == nil {
    68  		return nil, err
    69  	}
    70  	chaincodeData := &ccprovider.ChaincodeData{}
    71  	if err := proto.Unmarshal(chaincodeDataBytes, chaincodeData); err != nil {
    72  		return nil, errors.Wrap(err, "error unmarshalling chaincode state data")
    73  	}
    74  	collConfigPkg, err := fetchCollConfigPkg(chaincodeName, qe)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	return &ledger.DeployedChaincodeInfo{
    79  		Name:                        chaincodeName,
    80  		Hash:                        chaincodeData.Id,
    81  		Version:                     chaincodeData.Version,
    82  		ExplicitCollectionConfigPkg: collConfigPkg,
    83  		IsLegacy:                    true,
    84  	}, nil
    85  }
    86  
    87  // AllCollectionsConfigPkg implements function in interface ledger.DeployedChaincodeInfoProvider
    88  // this implementation returns just the explicit collection config package as the implicit collections
    89  // are not used with legacy lifecycle
    90  func (p *DeployedCCInfoProvider) AllCollectionsConfigPkg(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) {
    91  	return fetchCollConfigPkg(chaincodeName, qe)
    92  }
    93  
    94  // CollectionInfo implements function in interface ledger.DeployedChaincodeInfoProvider
    95  func (p *DeployedCCInfoProvider) CollectionInfo(channelName, chaincodeName, collectionName string, qe ledger.SimpleQueryExecutor) (*peer.StaticCollectionConfig, error) {
    96  	collConfigPkg, err := fetchCollConfigPkg(chaincodeName, qe)
    97  	if err != nil || collConfigPkg == nil {
    98  		return nil, err
    99  	}
   100  	for _, conf := range collConfigPkg.Config {
   101  		staticCollConfig := conf.GetStaticCollectionConfig()
   102  		if staticCollConfig != nil && staticCollConfig.Name == collectionName {
   103  			return staticCollConfig, nil
   104  		}
   105  	}
   106  	return nil, nil
   107  }
   108  
   109  func fetchCollConfigPkg(chaincodeName string, qe ledger.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) {
   110  	collKey := privdata.BuildCollectionKVSKey(chaincodeName)
   111  	collectionConfigPkgBytes, err := qe.GetState(lsccNamespace, collKey)
   112  	if err != nil || collectionConfigPkgBytes == nil {
   113  		return nil, err
   114  	}
   115  	collectionConfigPkg := &peer.CollectionConfigPackage{}
   116  	if err := proto.Unmarshal(collectionConfigPkgBytes, collectionConfigPkg); err != nil {
   117  		return nil, errors.Wrap(err, "error unmarshalling chaincode collection config pkg")
   118  	}
   119  	return collectionConfigPkg, nil
   120  }