github.com/yimialmonte/fabric@v2.1.1+incompatible/core/ledger/ledger_interface.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package ledger 8 9 import ( 10 "fmt" 11 12 "github.com/golang/protobuf/proto" 13 "github.com/hyperledger/fabric-lib-go/healthz" 14 "github.com/hyperledger/fabric-protos-go/common" 15 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 16 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 17 "github.com/hyperledger/fabric-protos-go/peer" 18 "github.com/hyperledger/fabric/bccsp" 19 commonledger "github.com/hyperledger/fabric/common/ledger" 20 "github.com/hyperledger/fabric/common/metrics" 21 "github.com/hyperledger/fabric/core/ledger/util/couchdb" 22 ) 23 24 // Initializer encapsulates dependencies for PeerLedgerProvider 25 type Initializer struct { 26 StateListeners []StateListener 27 DeployedChaincodeInfoProvider DeployedChaincodeInfoProvider 28 MembershipInfoProvider MembershipInfoProvider 29 ChaincodeLifecycleEventProvider ChaincodeLifecycleEventProvider 30 MetricsProvider metrics.Provider 31 HealthCheckRegistry HealthCheckRegistry 32 Config *Config 33 CustomTxProcessors map[common.HeaderType]CustomTxProcessor 34 Hasher Hasher 35 } 36 37 // Config is a structure used to configure a ledger provider. 38 type Config struct { 39 // RootFSPath is the top-level directory where ledger files are stored. 40 RootFSPath string 41 // StateDBConfig holds the configuration parameters for the state database. 42 StateDBConfig *StateDBConfig 43 // PrivateDataConfig holds the configuration parameters for the private data store. 44 PrivateDataConfig *PrivateDataConfig 45 // HistoryDBConfig holds the configuration parameters for the transaction history database. 46 HistoryDBConfig *HistoryDBConfig 47 } 48 49 // StateDBConfig is a structure used to configure the state parameters for the ledger. 50 type StateDBConfig struct { 51 // StateDatabase is the database to use for storing last known state. The 52 // two supported options are "goleveldb" and "CouchDB". 53 StateDatabase string 54 // CouchDB is the configuration for CouchDB. It is used when StateDatabase 55 // is set to "CouchDB". 56 CouchDB *couchdb.Config 57 } 58 59 // PrivateDataConfig is a structure used to configure a private data storage provider. 60 type PrivateDataConfig struct { 61 // BatchesInterval is the minimum duration (milliseconds) between batches 62 // for converting ineligible missing data entries into eligible entries. 63 BatchesInterval int 64 // MatchBatchSize is the maximum size of batches when converting ineligible 65 // missing data entries into eligible entries. 66 MaxBatchSize int 67 // PurgeInterval is the number of blocks to wait until purging expired 68 // private data entries. 69 PurgeInterval int 70 } 71 72 // HistoryDBConfig is a structure used to configure the transaction history database. 73 type HistoryDBConfig struct { 74 Enabled bool 75 } 76 77 // PeerLedgerProvider provides handle to ledger instances 78 type PeerLedgerProvider interface { 79 // Create creates a new ledger with the given genesis block. 80 // This function guarantees that the creation of ledger and committing the genesis block would an atomic action 81 // The chain id retrieved from the genesis block is treated as a ledger id 82 Create(genesisBlock *common.Block) (PeerLedger, error) 83 // Open opens an already created ledger 84 Open(ledgerID string) (PeerLedger, error) 85 // Exists tells whether the ledger with given id exists 86 Exists(ledgerID string) (bool, error) 87 // List lists the ids of the existing ledgers 88 List() ([]string, error) 89 // Close closes the PeerLedgerProvider 90 Close() 91 } 92 93 // PeerLedger differs from the OrdererLedger in that PeerLedger locally maintain a bitmask 94 // that tells apart valid transactions from invalid ones 95 type PeerLedger interface { 96 commonledger.Ledger 97 // GetTransactionByID retrieves a transaction by id 98 GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) 99 // GetBlockByHash returns a block given it's hash 100 GetBlockByHash(blockHash []byte) (*common.Block, error) 101 // GetBlockByTxID returns a block which contains a transaction 102 GetBlockByTxID(txID string) (*common.Block, error) 103 // GetTxValidationCodeByTxID returns reason code of transaction validation 104 GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) 105 // NewTxSimulator gives handle to a transaction simulator. 106 // A client can obtain more than one 'TxSimulator's for parallel execution. 107 // Any snapshoting/synchronization should be performed at the implementation level if required 108 NewTxSimulator(txid string) (TxSimulator, error) 109 // NewQueryExecutor gives handle to a query executor. 110 // A client can obtain more than one 'QueryExecutor's for parallel execution. 111 // Any synchronization should be performed at the implementation level if required 112 NewQueryExecutor() (QueryExecutor, error) 113 // NewHistoryQueryExecutor gives handle to a history query executor. 114 // A client can obtain more than one 'HistoryQueryExecutor's for parallel execution. 115 // Any synchronization should be performed at the implementation level if required 116 NewHistoryQueryExecutor() (HistoryQueryExecutor, error) 117 // GetPvtDataAndBlockByNum returns the block and the corresponding pvt data. 118 // The pvt data is filtered by the list of 'ns/collections' supplied 119 // A nil filter does not filter any results and causes retrieving all the pvt data for the given blockNum 120 GetPvtDataAndBlockByNum(blockNum uint64, filter PvtNsCollFilter) (*BlockAndPvtData, error) 121 // GetPvtDataByNum returns only the pvt data corresponding to the given block number 122 // The pvt data is filtered by the list of 'ns/collections' supplied in the filter 123 // A nil filter does not filter any results and causes retrieving all the pvt data for the given blockNum 124 GetPvtDataByNum(blockNum uint64, filter PvtNsCollFilter) ([]*TxPvtData, error) 125 // CommitLegacy commits the block and the corresponding pvt data in an atomic operation following the v14 validation/commit path 126 // TODO: add a new Commit() path that replaces CommitLegacy() for the validation refactor described in FAB-12221 127 CommitLegacy(blockAndPvtdata *BlockAndPvtData, commitOpts *CommitOptions) error 128 // GetConfigHistoryRetriever returns the ConfigHistoryRetriever 129 GetConfigHistoryRetriever() (ConfigHistoryRetriever, error) 130 // CommitPvtDataOfOldBlocks commits the private data corresponding to already committed block 131 // If hashes for some of the private data supplied in this function does not match 132 // the corresponding hash present in the block, the unmatched private data is not 133 // committed and instead the mismatch inforation is returned back 134 CommitPvtDataOfOldBlocks(reconciledPvtdata []*ReconciledPvtdata) ([]*PvtdataHashMismatch, error) 135 // GetMissingPvtDataTracker return the MissingPvtDataTracker 136 GetMissingPvtDataTracker() (MissingPvtDataTracker, error) 137 // DoesPvtDataInfoExist returns true when 138 // (1) the ledger has pvtdata associated with the given block number (or) 139 // (2) a few or all pvtdata associated with the given block number is missing but the 140 // missing info is recorded in the ledger (or) 141 // (3) the block is committed and does not contain any pvtData. 142 DoesPvtDataInfoExist(blockNum uint64) (bool, error) 143 } 144 145 // SimpleQueryExecutor encapsulates basic functions 146 type SimpleQueryExecutor interface { 147 // GetState gets the value for given namespace and key. For a chaincode, the namespace corresponds to the chaincodeId 148 GetState(namespace string, key string) ([]byte, error) 149 // GetStateRangeScanIterator returns an iterator that contains all the key-values between given key ranges. 150 // startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key 151 // and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey 152 // can be supplied as empty strings. However, a full scan should be used judiciously for performance reasons. 153 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 154 GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error) 155 // GetPrivateDataHash gets the hash of the value of a private data item identified by a tuple <namespace, collection, key> 156 // Function `GetPrivateData` is only meaningful when it is invoked on a peer that is authorized to have the private data 157 // for the collection <namespace, collection>. However, the function `GetPrivateDataHash` can be invoked on any peer 158 // to get the hash of the current value 159 GetPrivateDataHash(namespace, collection, key string) ([]byte, error) 160 } 161 162 // QueryExecutor executes the queries 163 // Get* methods are for supporting KV-based data model. ExecuteQuery method is for supporting a rich datamodel and query support 164 // 165 // ExecuteQuery method in the case of a rich data model is expected to support queries on 166 // latest state, historical state and on the intersection of state and transactions 167 type QueryExecutor interface { 168 SimpleQueryExecutor 169 // GetStateMetadata returns the metadata for given namespace and key 170 GetStateMetadata(namespace, key string) (map[string][]byte, error) 171 // GetStateMultipleKeys gets the values for multiple keys in a single call 172 GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) 173 // GetStateRangeScanIteratorWithMetadata returns an iterator that contains all the key-values between given key ranges. 174 // startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key 175 // and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey 176 // can be supplied as empty strings. However, a full scan should be used judiciously for performance reasons. 177 // metadata is a map of additional query parameters 178 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 179 GetStateRangeScanIteratorWithMetadata(namespace string, startKey, endKey string, metadata map[string]interface{}) (QueryResultsIterator, error) 180 // ExecuteQuery executes the given query and returns an iterator that contains results of type specific to the underlying data store. 181 // Only used for state databases that support query 182 // For a chaincode, the namespace corresponds to the chaincodeId 183 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 184 ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error) 185 // ExecuteQueryWithMetadata executes the given query and returns an iterator that contains results of type specific to the underlying data store. 186 // metadata is a map of additional query parameters 187 // Only used for state databases that support query 188 // For a chaincode, the namespace corresponds to the chaincodeId 189 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 190 ExecuteQueryWithMetadata(namespace, query string, metadata map[string]interface{}) (QueryResultsIterator, error) 191 // GetPrivateData gets the value of a private data item identified by a tuple <namespace, collection, key> 192 GetPrivateData(namespace, collection, key string) ([]byte, error) 193 // GetPrivateDataMetadata gets the metadata of a private data item identified by a tuple <namespace, collection, key> 194 GetPrivateDataMetadata(namespace, collection, key string) (map[string][]byte, error) 195 // GetPrivateDataMetadataByHash gets the metadata of a private data item identified by a tuple <namespace, collection, keyhash> 196 GetPrivateDataMetadataByHash(namespace, collection string, keyhash []byte) (map[string][]byte, error) 197 // GetPrivateDataMultipleKeys gets the values for the multiple private data items in a single call 198 GetPrivateDataMultipleKeys(namespace, collection string, keys []string) ([][]byte, error) 199 // GetPrivateDataRangeScanIterator returns an iterator that contains all the key-values between given key ranges. 200 // startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key 201 // and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey 202 // can be supplied as empty strings. However, a full scan shuold be used judiciously for performance reasons. 203 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 204 GetPrivateDataRangeScanIterator(namespace, collection, startKey, endKey string) (commonledger.ResultsIterator, error) 205 // ExecuteQuery executes the given query and returns an iterator that contains results of type specific to the underlying data store. 206 // Only used for state databases that support query 207 // For a chaincode, the namespace corresponds to the chaincodeId 208 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 209 ExecuteQueryOnPrivateData(namespace, collection, query string) (commonledger.ResultsIterator, error) 210 // Done releases resources occupied by the QueryExecutor 211 Done() 212 } 213 214 // HistoryQueryExecutor executes the history queries 215 type HistoryQueryExecutor interface { 216 // GetHistoryForKey retrieves the history of values for a key. 217 // The returned ResultsIterator contains results of type *KeyModification which is defined in fabric-protos/ledger/queryresult. 218 GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error) 219 } 220 221 // TxSimulator simulates a transaction on a consistent snapshot of the 'as recent state as possible' 222 // Set* methods are for supporting KV-based data model. ExecuteUpdate method is for supporting a rich datamodel and query support 223 type TxSimulator interface { 224 QueryExecutor 225 // SetState sets the given value for the given namespace and key. For a chaincode, the namespace corresponds to the chaincodeId 226 SetState(namespace string, key string, value []byte) error 227 // DeleteState deletes the given namespace and key 228 DeleteState(namespace string, key string) error 229 // SetMultipleKeys sets the values for multiple keys in a single call 230 SetStateMultipleKeys(namespace string, kvs map[string][]byte) error 231 // SetStateMetadata sets the metadata associated with an existing key-tuple <namespace, key> 232 SetStateMetadata(namespace, key string, metadata map[string][]byte) error 233 // DeleteStateMetadata deletes the metadata (if any) associated with an existing key-tuple <namespace, key> 234 DeleteStateMetadata(namespace, key string) error 235 // ExecuteUpdate for supporting rich data model (see comments on QueryExecutor above) 236 ExecuteUpdate(query string) error 237 // SetPrivateData sets the given value to a key in the private data state represented by the tuple <namespace, collection, key> 238 SetPrivateData(namespace, collection, key string, value []byte) error 239 // SetPrivateDataMultipleKeys sets the values for multiple keys in the private data space in a single call 240 SetPrivateDataMultipleKeys(namespace, collection string, kvs map[string][]byte) error 241 // DeletePrivateData deletes the given tuple <namespace, collection, key> from private data 242 DeletePrivateData(namespace, collection, key string) error 243 // SetPrivateDataMetadata sets the metadata associated with an existing key-tuple <namespace, collection, key> 244 SetPrivateDataMetadata(namespace, collection, key string, metadata map[string][]byte) error 245 // DeletePrivateDataMetadata deletes the metadata associated with an existing key-tuple <namespace, collection, key> 246 DeletePrivateDataMetadata(namespace, collection, key string) error 247 // GetTxSimulationResults encapsulates the results of the transaction simulation. 248 // This should contain enough detail for 249 // - The update in the state that would be caused if the transaction is to be committed 250 // - The environment in which the transaction is executed so as to be able to decide the validity of the environment 251 // (at a later time on a different peer) during committing the transactions 252 // Different ledger implementation (or configurations of a single implementation) may want to represent the above two pieces 253 // of information in different way in order to support different data-models or optimize the information representations. 254 // Returned type 'TxSimulationResults' contains the simulation results for both the public data and the private data. 255 // The public data simulation results are expected to be used as in V1 while the private data simulation results are expected 256 // to be used by the gossip to disseminate this to the other endorsers (in phase-2 of sidedb) 257 GetTxSimulationResults() (*TxSimulationResults, error) 258 } 259 260 // QueryResultsIterator - an iterator for query result set 261 type QueryResultsIterator interface { 262 commonledger.ResultsIterator 263 // GetBookmarkAndClose returns a paging bookmark and releases resources occupied by the iterator 264 GetBookmarkAndClose() string 265 } 266 267 // TxPvtData encapsulates the transaction number and pvt write-set for a transaction 268 type TxPvtData struct { 269 SeqInBlock uint64 270 WriteSet *rwset.TxPvtReadWriteSet 271 } 272 273 // TxPvtDataMap is a map from txNum to the pvtData 274 type TxPvtDataMap map[uint64]*TxPvtData 275 276 // MissingPvtData contains a namespace and collection for 277 // which the pvtData is not present. It also denotes 278 // whether the missing pvtData is eligible (i.e., whether 279 // the peer is member of the [namespace, collection] 280 type MissingPvtData struct { 281 Namespace string 282 Collection string 283 IsEligible bool 284 } 285 286 // TxMissingPvtDataMap is a map from txNum to the list of 287 // missing pvtData 288 type TxMissingPvtDataMap map[uint64][]*MissingPvtData 289 290 // BlockAndPvtData encapsulates the block and a map that contains the tuples <seqInBlock, *TxPvtData> 291 // The map is expected to contain the entries only for the transactions that has associated pvt data 292 type BlockAndPvtData struct { 293 Block *common.Block 294 PvtData TxPvtDataMap 295 MissingPvtData TxMissingPvtDataMap 296 } 297 298 // ReconciledPvtdata contains the private data for a block for reconciliation 299 type ReconciledPvtdata struct { 300 BlockNum uint64 301 WriteSets TxPvtDataMap 302 } 303 304 // Add adds a given missing private data in the MissingPrivateDataList 305 func (txMissingPvtData TxMissingPvtDataMap) Add(txNum uint64, ns, coll string, isEligible bool) { 306 txMissingPvtData[txNum] = append(txMissingPvtData[txNum], &MissingPvtData{ns, coll, isEligible}) 307 } 308 309 // RetrievedPvtdata is a dependency that is implemented by coordinator/gossip for ledger 310 // to be able to purge the transactions from the block after retrieving private data 311 type RetrievedPvtdata interface { 312 GetBlockPvtdata() *BlockPvtdata 313 Purge() 314 } 315 316 // TxPvtdataInfo captures information about the requested private data to be retrieved 317 type TxPvtdataInfo struct { 318 TxID string 319 Invalid bool 320 SeqInBlock uint64 321 CollectionPvtdataInfo []*CollectionPvtdataInfo 322 } 323 324 // CollectionPvtdataInfo contains information about the private data for a given collection 325 type CollectionPvtdataInfo struct { 326 Namespace, Collection string 327 ExpectedHash []byte 328 CollectionConfig *peer.StaticCollectionConfig 329 Endorsers []*peer.Endorsement 330 } 331 332 // BlockPvtdata contains the retrieved private data as well as missing and ineligible 333 // private data for use at commit time 334 type BlockPvtdata struct { 335 PvtData TxPvtDataMap 336 MissingPvtData TxMissingPvtDataMap 337 } 338 339 // CommitOptions encapsulates options associated with a block commit. 340 type CommitOptions struct { 341 FetchPvtDataFromLedger bool 342 } 343 344 // PvtCollFilter represents the set of the collection names (as keys of the map with value 'true') 345 type PvtCollFilter map[string]bool 346 347 // PvtNsCollFilter specifies the tuple <namespace, PvtCollFilter> 348 type PvtNsCollFilter map[string]PvtCollFilter 349 350 // NewPvtNsCollFilter constructs an empty PvtNsCollFilter 351 func NewPvtNsCollFilter() PvtNsCollFilter { 352 return make(map[string]PvtCollFilter) 353 } 354 355 // Has returns true if the pvtdata includes the data for collection <ns,coll> 356 func (pvtdata *TxPvtData) Has(ns string, coll string) bool { 357 if pvtdata.WriteSet == nil { 358 return false 359 } 360 for _, nsdata := range pvtdata.WriteSet.NsPvtRwset { 361 if nsdata.Namespace == ns { 362 for _, colldata := range nsdata.CollectionPvtRwset { 363 if colldata.CollectionName == coll { 364 return true 365 } 366 } 367 } 368 } 369 return false 370 } 371 372 // Add adds a namespace-collection tuple to the filter 373 func (filter PvtNsCollFilter) Add(ns string, coll string) { 374 collFilter, ok := filter[ns] 375 if !ok { 376 collFilter = make(map[string]bool) 377 filter[ns] = collFilter 378 } 379 collFilter[coll] = true 380 } 381 382 // Has returns true if the filter has the entry for tuple namespace-collection 383 func (filter PvtNsCollFilter) Has(ns string, coll string) bool { 384 collFilter, ok := filter[ns] 385 if !ok { 386 return false 387 } 388 return collFilter[coll] 389 } 390 391 // TxSimulationResults captures the details of the simulation results 392 type TxSimulationResults struct { 393 PubSimulationResults *rwset.TxReadWriteSet 394 PvtSimulationResults *rwset.TxPvtReadWriteSet 395 } 396 397 // GetPubSimulationBytes returns the serialized bytes of public readwrite set 398 func (txSim *TxSimulationResults) GetPubSimulationBytes() ([]byte, error) { 399 return proto.Marshal(txSim.PubSimulationResults) 400 } 401 402 // GetPvtSimulationBytes returns the serialized bytes of private readwrite set 403 func (txSim *TxSimulationResults) GetPvtSimulationBytes() ([]byte, error) { 404 if !txSim.ContainsPvtWrites() { 405 return nil, nil 406 } 407 return proto.Marshal(txSim.PvtSimulationResults) 408 } 409 410 // ContainsPvtWrites returns true if the simulation results include the private writes 411 func (txSim *TxSimulationResults) ContainsPvtWrites() bool { 412 return txSim.PvtSimulationResults != nil 413 } 414 415 // StateListener allows a custom code for performing additional stuff upon state change 416 // for a particular namespace against which the listener is registered. 417 // This helps to perform custom tasks other than the state updates. 418 // A ledger implementation is expected to invoke Function `HandleStateUpdates` once per block and 419 // the `stateUpdates` parameter passed to the function captures the state changes caused by the block 420 // for the namespace. The actual data type of stateUpdates depends on the data model enabled. 421 // For instance, for KV data model, the actual type would be proto message 422 // `github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset.KVWrite` 423 // Function `HandleStateUpdates` is expected to be invoked before block is committed and if this 424 // function returns an error, the ledger implementation is expected to halt block commit operation 425 // and result in a panic. 426 // The function Initialize is invoked only once at the time of opening the ledger. 427 type StateListener interface { 428 Initialize(ledgerID string, qe SimpleQueryExecutor) error 429 InterestedInNamespaces() []string 430 HandleStateUpdates(trigger *StateUpdateTrigger) error 431 StateCommitDone(channelID string) 432 } 433 434 // StateUpdateTrigger encapsulates the information and helper tools that may be used by a StateListener 435 type StateUpdateTrigger struct { 436 LedgerID string 437 StateUpdates StateUpdates 438 CommittingBlockNum uint64 439 CommittedStateQueryExecutor SimpleQueryExecutor 440 PostCommitQueryExecutor SimpleQueryExecutor 441 } 442 443 // StateUpdates encapsulates the state updates 444 type StateUpdates map[string]*KVStateUpdates 445 446 // KVStateUpdates captures the state updates for a namespace for KV datamodel 447 type KVStateUpdates struct { 448 PublicUpdates []*kvrwset.KVWrite 449 CollHashUpdates map[string][]*kvrwset.KVWriteHash 450 } 451 452 // ConfigHistoryRetriever allow retrieving history of collection configs 453 type ConfigHistoryRetriever interface { 454 CollectionConfigAt(blockNum uint64, chaincodeName string) (*CollectionConfigInfo, error) 455 MostRecentCollectionConfigBelow(blockNum uint64, chaincodeName string) (*CollectionConfigInfo, error) 456 } 457 458 // MissingPvtDataTracker allows getting information about the private data that is not missing on the peer 459 type MissingPvtDataTracker interface { 460 GetMissingPvtDataInfoForMostRecentBlocks(maxBlocks int) (MissingPvtDataInfo, error) 461 } 462 463 // MissingPvtDataInfo is a map of block number to MissingBlockPvtdataInfo 464 type MissingPvtDataInfo map[uint64]MissingBlockPvtdataInfo 465 466 // MissingBlockPvtdataInfo is a map of transaction number (within the block) to MissingCollectionPvtDataInfo 467 type MissingBlockPvtdataInfo map[uint64][]*MissingCollectionPvtDataInfo 468 469 // MissingCollectionPvtDataInfo includes the name of the chaincode and collection for which private data is missing 470 type MissingCollectionPvtDataInfo struct { 471 Namespace, Collection string 472 } 473 474 // CollectionConfigInfo encapsulates a collection config for a chaincode and its committing block number 475 type CollectionConfigInfo struct { 476 CollectionConfig *peer.CollectionConfigPackage 477 CommittingBlockNum uint64 478 } 479 480 // Add adds a missing data entry to the MissingPvtDataInfo Map 481 func (missingPvtDataInfo MissingPvtDataInfo) Add(blkNum, txNum uint64, ns, coll string) { 482 missingBlockPvtDataInfo, ok := missingPvtDataInfo[blkNum] 483 if !ok { 484 missingBlockPvtDataInfo = make(MissingBlockPvtdataInfo) 485 missingPvtDataInfo[blkNum] = missingBlockPvtDataInfo 486 } 487 488 if _, ok := missingBlockPvtDataInfo[txNum]; !ok { 489 missingBlockPvtDataInfo[txNum] = []*MissingCollectionPvtDataInfo{} 490 } 491 492 missingBlockPvtDataInfo[txNum] = append(missingBlockPvtDataInfo[txNum], 493 &MissingCollectionPvtDataInfo{ 494 Namespace: ns, 495 Collection: coll}) 496 } 497 498 // ErrCollectionConfigNotYetAvailable is an error which is returned from the function 499 // ConfigHistoryRetriever.CollectionConfigAt() if the latest block number committed 500 // is lower than the block number specified in the request. 501 type ErrCollectionConfigNotYetAvailable struct { 502 MaxBlockNumCommitted uint64 503 Msg string 504 } 505 506 func (e *ErrCollectionConfigNotYetAvailable) Error() string { 507 return e.Msg 508 } 509 510 // NotFoundInIndexErr is used to indicate missing entry in the index 511 type NotFoundInIndexErr string 512 513 func (NotFoundInIndexErr) Error() string { 514 return "Entry not found in index" 515 } 516 517 // CollConfigNotDefinedError is returned whenever an operation 518 // is requested on a collection whose config has not been defined 519 type CollConfigNotDefinedError struct { 520 Ns string 521 } 522 523 func (e *CollConfigNotDefinedError) Error() string { 524 return fmt.Sprintf("collection config not defined for chaincode [%s], pass the collection configuration upon chaincode definition/instantiation", e.Ns) 525 } 526 527 // InvalidCollNameError is returned whenever an operation 528 // is requested on a collection whose name is invalid 529 type InvalidCollNameError struct { 530 Ns, Coll string 531 } 532 533 func (e *InvalidCollNameError) Error() string { 534 return fmt.Sprintf("collection [%s] not defined in the collection config for chaincode [%s]", e.Coll, e.Ns) 535 } 536 537 // PvtdataHashMismatch is used when the hash of private write-set 538 // does not match the corresponding hash present in the block 539 // See function `PeerLedger.CommitPvtData` for the usages 540 type PvtdataHashMismatch struct { 541 BlockNum, TxNum uint64 542 Namespace, Collection string 543 ExpectedHash []byte 544 } 545 546 // DeployedChaincodeInfoProvider is a dependency that is used by ledger to build collection config history 547 // LSCC module is expected to provide an implementation for this dependencies 548 type DeployedChaincodeInfoProvider interface { 549 // Namespaces returns the slice of the namespaces that are used for maintaining chaincode lifecycle data 550 Namespaces() []string 551 // UpdatedChaincodes returns the chaincodes that are getting updated by the supplied 'stateUpdates' 552 UpdatedChaincodes(stateUpdates map[string][]*kvrwset.KVWrite) ([]*ChaincodeLifecycleInfo, error) 553 // ChaincodeInfo returns the info about a deployed chaincode 554 ChaincodeInfo(channelName, chaincodeName string, qe SimpleQueryExecutor) (*DeployedChaincodeInfo, error) 555 // CollectionInfo returns the proto msg that defines the named collection. This function can be called for both explicit and implicit collections 556 CollectionInfo(channelName, chaincodeName, collectionName string, qe SimpleQueryExecutor) (*peer.StaticCollectionConfig, error) 557 // ImplicitCollections returns a slice that contains one proto msg for each of the implicit collections 558 ImplicitCollections(channelName, chaincodeName string, qe SimpleQueryExecutor) ([]*peer.StaticCollectionConfig, error) 559 // AllCollectionsConfigPkg returns a combined collection config pkg that contains both explicit and implicit collections 560 AllCollectionsConfigPkg(channelName, chaincodeName string, qe SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) 561 } 562 563 // DeployedChaincodeInfo encapsulates chaincode information from the deployed chaincodes 564 type DeployedChaincodeInfo struct { 565 Name string 566 Hash []byte 567 Version string 568 ExplicitCollectionConfigPkg *peer.CollectionConfigPackage 569 IsLegacy bool 570 } 571 572 // ChaincodeLifecycleInfo captures the update info of a chaincode 573 type ChaincodeLifecycleInfo struct { 574 Name string 575 Deleted bool 576 Details *ChaincodeLifecycleDetails // Can contain finer details about lifecycle event that can be used for certain optimization 577 } 578 579 // ChaincodeLifecycleDetails captures the finer details of chaincode lifecycle event 580 type ChaincodeLifecycleDetails struct { 581 Updated bool // true, if an existing chaincode is updated (false for newly deployed chaincodes). 582 // Following attributes are meaningful only if 'Updated' is true 583 HashChanged bool // true, if the chaincode code package is changed 584 CollectionsUpdated []string // names of the explicit collections that are either added or updated 585 CollectionsRemoved []string // names of the explicit collections that are removed 586 } 587 588 // MembershipInfoProvider is a dependency that is used by ledger to determine whether the current peer is 589 // a member of a collection. Gossip module is expected to provide the dependency to ledger 590 type MembershipInfoProvider interface { 591 // AmMemberOf checks whether the current peer is a member of the given collection 592 AmMemberOf(channelName string, collectionPolicyConfig *peer.CollectionPolicyConfig) (bool, error) 593 } 594 595 type HealthCheckRegistry interface { 596 RegisterChecker(string, healthz.HealthChecker) error 597 } 598 599 // ChaincodeLifecycleEventListener interface enables ledger components (mainly, intended for statedb) 600 // to be able to listen to chaincode lifecycle events. 'dbArtifactsTar' represents db specific artifacts 601 // (such as index specs) packaged in a tar. Note that this interface is redefined here (in addition to 602 // the one defined in ledger/cceventmgmt package). Using the same interface for the new lifecycle path causes 603 // a cyclic import dependency. Moreover, eventually the whole package ledger/cceventmgmt is intented to 604 // be removed when migration to new lifecycle is mandated. 605 type ChaincodeLifecycleEventListener interface { 606 // HandleChaincodeDeploy is invoked when chaincode installed + defined becomes true. 607 // The expected usage are to creates all the necessary statedb structures (such as indexes) and update 608 // service discovery info. This function is invoked immediately before the committing the state changes 609 // that contain chaincode definition or when a chaincode install happens 610 HandleChaincodeDeploy(chaincodeDefinition *ChaincodeDefinition, dbArtifactsTar []byte) error 611 // ChaincodeDeployDone is invoked after the chaincode deployment is finished - `succeeded` indicates 612 // whether the deploy finished successfully 613 ChaincodeDeployDone(succeeded bool) 614 } 615 616 // ChaincodeDefinition captures the info about chaincode 617 type ChaincodeDefinition struct { 618 Name string 619 Hash []byte 620 Version string 621 CollectionConfigs *peer.CollectionConfigPackage 622 } 623 624 func (cdef *ChaincodeDefinition) String() string { 625 return fmt.Sprintf("Name=%s, Version=%s, Hash=%#v", cdef.Name, cdef.Version, cdef.Hash) 626 } 627 628 type ChaincodeLifecycleEventProvider interface { 629 RegisterListener(channelID string, listener ChaincodeLifecycleEventListener) 630 } 631 632 // CustomTxProcessor allows to generate simulation results during commit time for custom transactions. 633 // A custom processor may represent the information in a propriety fashion and can use this process to translate 634 // the information into the form of `TxSimulationResults`. Because, the original information is signed in a 635 // custom representation, an implementation of a `Processor` should be cautious that the custom representation 636 // is used for simulation in an deterministic fashion and should take care of compatibility cross fabric versions. 637 // 'initializingLedger' true indicates that either the transaction being processed is from the genesis block or the ledger is 638 // synching the state (which could happen during peer startup if the statedb is found to be lagging behind the blockchain). 639 // In the former case, the transactions processed are expected to be valid and in the latter case, only valid transactions 640 // are reprocessed and hence any validation can be skipped. 641 type CustomTxProcessor interface { 642 GenerateSimulationResults(txEnvelop *common.Envelope, simulator TxSimulator, initializingLedger bool) error 643 } 644 645 // InvalidTxError is expected to be thrown by a custom transaction processor 646 // if it wants the ledger to record a particular transaction as invalid 647 type InvalidTxError struct { 648 Msg string 649 } 650 651 func (e *InvalidTxError) Error() string { 652 return e.Msg 653 } 654 655 // Hasher implements the hash function that should be used for all ledger components. 656 // Currently works at a stepping stone to decrease surface area of bccsp 657 type Hasher interface { 658 Hash(msg []byte, opts bccsp.HashOpts) (hash []byte, err error) 659 } 660 661 //go:generate counterfeiter -o mock/state_listener.go -fake-name StateListener . StateListener 662 //go:generate counterfeiter -o mock/query_executor.go -fake-name QueryExecutor . QueryExecutor 663 //go:generate counterfeiter -o mock/tx_simulator.go -fake-name TxSimulator . TxSimulator 664 //go:generate counterfeiter -o mock/deployed_ccinfo_provider.go -fake-name DeployedChaincodeInfoProvider . DeployedChaincodeInfoProvider 665 //go:generate counterfeiter -o mock/membership_info_provider.go -fake-name MembershipInfoProvider . MembershipInfoProvider 666 //go:generate counterfeiter -o mock/health_check_registry.go -fake-name HealthCheckRegistry . HealthCheckRegistry 667 //go:generate counterfeiter -o mock/cc_event_listener.go -fake-name ChaincodeLifecycleEventListener . ChaincodeLifecycleEventListener 668 //go:generate counterfeiter -o mock/custom_tx_processor.go -fake-name CustomTxProcessor . CustomTxProcessor 669 //go:generate counterfeiter -o mock/cc_event_provider.go -fake-name ChaincodeLifecycleEventProvider . ChaincodeLifecycleEventProvider