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 }