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 }