github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/ledger_interface.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package ledger 8 9 import ( 10 "fmt" 11 "hash" 12 "time" 13 14 "github.com/golang/protobuf/proto" 15 "github.com/hechain20/hechain/bccsp" 16 commonledger "github.com/hechain20/hechain/common/ledger" 17 "github.com/hechain20/hechain/common/metrics" 18 "github.com/hyperledger/fabric-lib-go/healthz" 19 "github.com/hyperledger/fabric-protos-go/common" 20 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 21 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 22 "github.com/hyperledger/fabric-protos-go/peer" 23 ) 24 25 const ( 26 GoLevelDB = "goleveldb" 27 CouchDB = "CouchDB" 28 ) 29 30 // Initializer encapsulates dependencies for PeerLedgerProvider 31 type Initializer struct { 32 StateListeners []StateListener 33 DeployedChaincodeInfoProvider DeployedChaincodeInfoProvider 34 MembershipInfoProvider MembershipInfoProvider 35 ChaincodeLifecycleEventProvider ChaincodeLifecycleEventProvider 36 MetricsProvider metrics.Provider 37 HealthCheckRegistry HealthCheckRegistry 38 Config *Config 39 CustomTxProcessors map[common.HeaderType]CustomTxProcessor 40 HashProvider HashProvider 41 } 42 43 // Config is a structure used to configure a ledger provider. 44 type Config struct { 45 // RootFSPath is the top-level directory where ledger files are stored. 46 RootFSPath string 47 // StateDBConfig holds the configuration parameters for the state database. 48 StateDBConfig *StateDBConfig 49 // PrivateDataConfig holds the configuration parameters for the private data store. 50 PrivateDataConfig *PrivateDataConfig 51 // HistoryDBConfig holds the configuration parameters for the transaction history database. 52 HistoryDBConfig *HistoryDBConfig 53 // SnapshotsConfig holds the configuration parameters for the snapshots. 54 SnapshotsConfig *SnapshotsConfig 55 } 56 57 // StateDBConfig is a structure used to configure the state parameters for the ledger. 58 type StateDBConfig struct { 59 // StateDatabase is the database to use for storing last known state. The 60 // two supported options are "goleveldb" and "CouchDB" (captured in the constants GoLevelDB and CouchDB respectively). 61 StateDatabase string 62 // CouchDB is the configuration for CouchDB. It is used when StateDatabase 63 // is set to "CouchDB". 64 CouchDB *CouchDBConfig 65 } 66 67 // CouchDBConfig is a structure used to configure a CouchInstance. 68 type CouchDBConfig struct { 69 // Address is the hostname:port of the CouchDB database instance. 70 Address string 71 // Username is the username used to authenticate with CouchDB. This username 72 // must have read and write access permissions. 73 Username string 74 // Password is the password for Username. 75 Password string 76 // MaxRetries is the maximum number of times to retry CouchDB operations on 77 // failure. 78 MaxRetries int 79 // MaxRetriesOnStartup is the maximum number of times to retry CouchDB operations on 80 // failure when initializing the ledger. 81 MaxRetriesOnStartup int 82 // RequestTimeout is the timeout used for CouchDB operations. 83 RequestTimeout time.Duration 84 // InternalQueryLimit is the maximum number of records to return internally 85 // when querying CouchDB. 86 InternalQueryLimit int 87 // MaxBatchUpdateSize is the maximum number of records to included in CouchDB 88 // bulk update operations. 89 MaxBatchUpdateSize int 90 // CreateGlobalChangesDB determines whether or not to create the "_global_changes" 91 // system database. 92 CreateGlobalChangesDB bool 93 // RedoLogPath is the directory where the CouchDB redo log files are stored. 94 RedoLogPath string 95 // UserCacheSizeMBs denotes the user specified maximum mega bytes (MB) to be allocated 96 // for the user state cache (i.e., all chaincodes deployed by the user). Note that 97 // UserCacheSizeMBs needs to be a multiple of 32 MB. If it is not a multiple of 32 MB, 98 // the peer would round the size to the next multiple of 32 MB. 99 UserCacheSizeMBs int 100 } 101 102 // PrivateDataConfig is a structure used to configure a private data storage provider. 103 type PrivateDataConfig struct { 104 // BatchesInterval is the minimum duration (milliseconds) between batches 105 // for converting ineligible missing data entries into eligible entries. 106 BatchesInterval int 107 // MatchBatchSize is the maximum size of batches when converting ineligible 108 // missing data entries into eligible entries. 109 MaxBatchSize int 110 // PurgeInterval is the number of blocks to wait until purging expired 111 // private data entries. 112 PurgeInterval int 113 // The missing data entries are classified into three categories: 114 // (1) eligible prioritized 115 // (2) eligible deprioritized 116 // (3) ineligible 117 // The reconciler would fetch the eligible prioritized missing data 118 // from other peers. A chance for eligible deprioritized missing data 119 // would be given after every DeprioritizedDataReconcilerInterval 120 DeprioritizedDataReconcilerInterval time.Duration 121 } 122 123 // HistoryDBConfig is a structure used to configure the transaction history database. 124 type HistoryDBConfig struct { 125 Enabled bool 126 } 127 128 // SnapshotsConfig is a structure used to configure snapshot function 129 type SnapshotsConfig struct { 130 // RootDir is the top-level directory for the snapshots. 131 RootDir string 132 } 133 134 // PeerLedgerProvider provides handle to ledger instances 135 type PeerLedgerProvider interface { 136 // CreateFromGenesisBlock creates a new ledger with the given genesis block. 137 // This function guarantees that the creation of ledger and committing the genesis block would an atomic action 138 // The channel id retrieved from the genesis block is treated as a ledger id 139 CreateFromGenesisBlock(genesisBlock *common.Block) (PeerLedger, error) 140 // CreateFromSnapshot creates a new ledger from a snapshot and returns the ledger and channel id. 141 // The channel id retrieved from snapshot metadata is treated as a ledger id 142 CreateFromSnapshot(snapshotDir string) (PeerLedger, string, error) 143 // Open opens an already created ledger 144 Open(ledgerID string) (PeerLedger, error) 145 // Exists tells whether the ledger with given id exists 146 Exists(ledgerID string) (bool, error) 147 // List lists the ids of the existing ledgers 148 List() ([]string, error) 149 // Close closes the PeerLedgerProvider 150 Close() 151 } 152 153 // PeerLedger differs from the OrdererLedger in that PeerLedger locally maintain a bitmask 154 // that tells apart valid transactions from invalid ones 155 type PeerLedger interface { 156 commonledger.Ledger 157 // TxIDExists returns true if the specified txID is already present in one of the already committed blocks. 158 // This function returns error only if there is an underlying condition that prevents checking for the txID, such as an I/O error. 159 TxIDExists(txID string) (bool, error) 160 // GetTransactionByID retrieves a transaction by id 161 GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) 162 // GetBlockByHash returns a block given it's hash 163 GetBlockByHash(blockHash []byte) (*common.Block, error) 164 // GetBlockByTxID returns a block which contains a transaction 165 GetBlockByTxID(txID string) (*common.Block, error) 166 // GetTxValidationCodeByTxID returns transaction validation code and block number in which the transaction was committed 167 GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, uint64, error) 168 // NewTxSimulator gives handle to a transaction simulator. 169 // A client can obtain more than one 'TxSimulator's for parallel execution. 170 // Any snapshoting/synchronization should be performed at the implementation level if required 171 NewTxSimulator(txid string) (TxSimulator, error) 172 // NewQueryExecutor gives handle to a query executor. 173 // A client can obtain more than one 'QueryExecutor's for parallel execution. 174 // Any synchronization should be performed at the implementation level if required 175 NewQueryExecutor() (QueryExecutor, error) 176 // NewHistoryQueryExecutor gives handle to a history query executor. 177 // A client can obtain more than one 'HistoryQueryExecutor's for parallel execution. 178 // Any synchronization should be performed at the implementation level if required 179 NewHistoryQueryExecutor() (HistoryQueryExecutor, error) 180 // GetPvtDataAndBlockByNum returns the block and the corresponding pvt data. 181 // The pvt data is filtered by the list of 'ns/collections' supplied 182 // A nil filter does not filter any results and causes retrieving all the pvt data for the given blockNum 183 GetPvtDataAndBlockByNum(blockNum uint64, filter PvtNsCollFilter) (*BlockAndPvtData, error) 184 // GetPvtDataByNum returns only the pvt data corresponding to the given block number 185 // The pvt data is filtered by the list of 'ns/collections' supplied in the filter 186 // A nil filter does not filter any results and causes retrieving all the pvt data for the given blockNum 187 GetPvtDataByNum(blockNum uint64, filter PvtNsCollFilter) ([]*TxPvtData, error) 188 // CommitLegacy commits the block and the corresponding pvt data in an atomic operation following the v14 validation/commit path 189 // TODO: add a new Commit() path that replaces CommitLegacy() for the validation refactor described in FAB-12221 190 CommitLegacy(blockAndPvtdata *BlockAndPvtData, commitOpts *CommitOptions) error 191 // GetConfigHistoryRetriever returns the ConfigHistoryRetriever 192 GetConfigHistoryRetriever() (ConfigHistoryRetriever, error) 193 // CommitPvtDataOfOldBlocks commits the private data corresponding to already committed block 194 // If hashes for some of the private data supplied in this function does not match 195 // the corresponding hash present in the block, the unmatched private data is not 196 // committed and instead the mismatch inforation is returned back 197 CommitPvtDataOfOldBlocks(reconciledPvtdata []*ReconciledPvtdata, unreconciled MissingPvtDataInfo) ([]*PvtdataHashMismatch, error) 198 // GetMissingPvtDataTracker return the MissingPvtDataTracker 199 GetMissingPvtDataTracker() (MissingPvtDataTracker, error) 200 // DoesPvtDataInfoExist returns true when 201 // (1) the ledger has pvtdata associated with the given block number (or) 202 // (2) a few or all pvtdata associated with the given block number is missing but the 203 // missing info is recorded in the ledger (or) 204 // (3) the block is committed and does not contain any pvtData. 205 DoesPvtDataInfoExist(blockNum uint64) (bool, error) 206 207 // SubmitSnapshotRequest submits a snapshot request for the specified height. 208 // The request will be stored in the ledger until the ledger's block height is equal to 209 // the specified height and the snapshot generation is completed. 210 // When height is 0, it will generate a snapshot at the current block height. 211 // It returns an error if the specified height is smaller than the ledger's block height. 212 SubmitSnapshotRequest(height uint64) error 213 // CancelSnapshotRequest cancels the previously submitted request. 214 // It returns an error if such a request does not exist or is under processing. 215 CancelSnapshotRequest(height uint64) error 216 // PendingSnapshotRequests returns a list of heights for the pending (or under processing) snapshot requests. 217 PendingSnapshotRequests() ([]uint64, error) 218 // CommitNotificationsChannel returns a read-only channel on which ledger sends a `CommitNotification` 219 // when a block is committed. The CommitNotification contains entries for the transactions from the committed block, 220 // which are not malformed, carry a legitimate TxID, and in addition, are not marked as a duplicate transaction. 221 // The consumer can close the 'done' channel to signal that the notifications are no longer needed. This will cause the 222 // CommitNotifications channel to close. There is expected to be only one consumer at a time. The function returns error 223 // if already a CommitNotification channel is active. 224 CommitNotificationsChannel(done <-chan struct{}) (<-chan *CommitNotification, error) 225 } 226 227 // SimpleQueryExecutor encapsulates basic functions 228 type SimpleQueryExecutor interface { 229 // GetState gets the value for given namespace and key. For a chaincode, the namespace corresponds to the chaincodeId 230 GetState(namespace string, key string) ([]byte, error) 231 // GetStateRangeScanIterator returns an iterator that contains all the key-values between given key ranges. 232 // startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key 233 // and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey 234 // can be supplied as empty strings. However, a full scan should be used judiciously for performance reasons. 235 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 236 GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error) 237 // GetPrivateDataHash gets the hash of the value of a private data item identified by a tuple <namespace, collection, key> 238 // Function `GetPrivateData` is only meaningful when it is invoked on a peer that is authorized to have the private data 239 // for the collection <namespace, collection>. However, the function `GetPrivateDataHash` can be invoked on any peer 240 // to get the hash of the current value 241 GetPrivateDataHash(namespace, collection, key string) ([]byte, error) 242 } 243 244 // QueryExecutor executes the queries 245 // Get* methods are for supporting KV-based data model. ExecuteQuery method is for supporting a rich datamodel and query support 246 // 247 // ExecuteQuery method in the case of a rich data model is expected to support queries on 248 // latest state, historical state and on the intersection of state and transactions 249 type QueryExecutor interface { 250 SimpleQueryExecutor 251 // GetStateMetadata returns the metadata for given namespace and key 252 GetStateMetadata(namespace, key string) (map[string][]byte, error) 253 // GetStateMultipleKeys gets the values for multiple keys in a single call 254 GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) 255 // GetStateRangeScanIteratorWithPagination returns an iterator that contains all the key-values between given key ranges. 256 // startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key 257 // and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey 258 // can be supplied as empty strings. However, a full scan should be used judiciously for performance reasons. 259 // The page size parameter limits the number of returned results. 260 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 261 GetStateRangeScanIteratorWithPagination(namespace string, startKey, endKey string, pageSize int32) (QueryResultsIterator, error) 262 // ExecuteQuery executes the given query and returns an iterator that contains results of type specific to the underlying data store. 263 // Only used for state databases that support query 264 // For a chaincode, the namespace corresponds to the chaincodeId 265 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 266 ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error) 267 // ExecuteQueryWithPagination executes the given query and returns an iterator that contains results of type specific to the underlying data store. 268 // The bookmark and page size parameters are associated with the pagination. 269 // Only used for state databases that support query 270 // For a chaincode, the namespace corresponds to the chaincodeId 271 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 272 ExecuteQueryWithPagination(namespace, query, bookmark string, pageSize int32) (QueryResultsIterator, error) 273 // GetPrivateData gets the value of a private data item identified by a tuple <namespace, collection, key> 274 GetPrivateData(namespace, collection, key string) ([]byte, error) 275 // GetPrivateDataMetadata gets the metadata of a private data item identified by a tuple <namespace, collection, key> 276 GetPrivateDataMetadata(namespace, collection, key string) (map[string][]byte, error) 277 // GetPrivateDataMetadataByHash gets the metadata of a private data item identified by a tuple <namespace, collection, keyhash> 278 GetPrivateDataMetadataByHash(namespace, collection string, keyhash []byte) (map[string][]byte, error) 279 // GetPrivateDataMultipleKeys gets the values for the multiple private data items in a single call 280 GetPrivateDataMultipleKeys(namespace, collection string, keys []string) ([][]byte, error) 281 // GetPrivateDataRangeScanIterator returns an iterator that contains all the key-values between given key ranges. 282 // startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key 283 // and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey 284 // can be supplied as empty strings. However, a full scan shuold be used judiciously for performance reasons. 285 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 286 GetPrivateDataRangeScanIterator(namespace, collection, startKey, endKey string) (commonledger.ResultsIterator, error) 287 // ExecuteQuery executes the given query and returns an iterator that contains results of type specific to the underlying data store. 288 // Only used for state databases that support query 289 // For a chaincode, the namespace corresponds to the chaincodeId 290 // The returned ResultsIterator contains results of type *KV which is defined in fabric-protos/ledger/queryresult. 291 ExecuteQueryOnPrivateData(namespace, collection, query string) (commonledger.ResultsIterator, error) 292 // Done releases resources occupied by the QueryExecutor 293 Done() 294 } 295 296 // HistoryQueryExecutor executes the history queries 297 type HistoryQueryExecutor interface { 298 // GetHistoryForKey retrieves the history of values for a key. 299 // The returned ResultsIterator contains results of type *KeyModification which is defined in fabric-protos/ledger/queryresult. 300 GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error) 301 } 302 303 // TxSimulator simulates a transaction on a consistent snapshot of the 'as recent state as possible' 304 // Set* methods are for supporting KV-based data model. ExecuteUpdate method is for supporting a rich datamodel and query support 305 type TxSimulator interface { 306 QueryExecutor 307 // SetState sets the given value for the given namespace and key. For a chaincode, the namespace corresponds to the chaincodeId 308 SetState(namespace string, key string, value []byte) error 309 // DeleteState deletes the given namespace and key 310 DeleteState(namespace string, key string) error 311 // SetMultipleKeys sets the values for multiple keys in a single call 312 SetStateMultipleKeys(namespace string, kvs map[string][]byte) error 313 // SetStateMetadata sets the metadata associated with an existing key-tuple <namespace, key> 314 SetStateMetadata(namespace, key string, metadata map[string][]byte) error 315 // DeleteStateMetadata deletes the metadata (if any) associated with an existing key-tuple <namespace, key> 316 DeleteStateMetadata(namespace, key string) error 317 // ExecuteUpdate for supporting rich data model (see comments on QueryExecutor above) 318 ExecuteUpdate(query string) error 319 // SetPrivateData sets the given value to a key in the private data state represented by the tuple <namespace, collection, key> 320 SetPrivateData(namespace, collection, key string, value []byte) error 321 // SetPrivateDataMultipleKeys sets the values for multiple keys in the private data space in a single call 322 SetPrivateDataMultipleKeys(namespace, collection string, kvs map[string][]byte) error 323 // DeletePrivateData deletes the given tuple <namespace, collection, key> from private data 324 DeletePrivateData(namespace, collection, key string) error 325 // SetPrivateDataMetadata sets the metadata associated with an existing key-tuple <namespace, collection, key> 326 SetPrivateDataMetadata(namespace, collection, key string, metadata map[string][]byte) error 327 // DeletePrivateDataMetadata deletes the metadata associated with an existing key-tuple <namespace, collection, key> 328 DeletePrivateDataMetadata(namespace, collection, key string) error 329 // GetTxSimulationResults encapsulates the results of the transaction simulation. 330 // This should contain enough detail for 331 // - The update in the state that would be caused if the transaction is to be committed 332 // - The environment in which the transaction is executed so as to be able to decide the validity of the environment 333 // (at a later time on a different peer) during committing the transactions 334 // Different ledger implementation (or configurations of a single implementation) may want to represent the above two pieces 335 // of information in different way in order to support different data-models or optimize the information representations. 336 // Returned type 'TxSimulationResults' contains the simulation results for both the public data and the private data. 337 // The public data simulation results are expected to be used as in V1 while the private data simulation results are expected 338 // to be used by the gossip to disseminate this to the other endorsers (in phase-2 of sidedb) 339 GetTxSimulationResults() (*TxSimulationResults, error) 340 } 341 342 // QueryResultsIterator - an iterator for query result set 343 type QueryResultsIterator interface { 344 commonledger.ResultsIterator 345 // GetBookmarkAndClose returns a paging bookmark and releases resources occupied by the iterator 346 GetBookmarkAndClose() string 347 } 348 349 // TxPvtData encapsulates the transaction number and pvt write-set for a transaction 350 type TxPvtData struct { 351 SeqInBlock uint64 352 WriteSet *rwset.TxPvtReadWriteSet 353 } 354 355 // TxPvtDataMap is a map from txNum to the pvtData 356 type TxPvtDataMap map[uint64]*TxPvtData 357 358 // MissingPvtData contains a namespace and collection for 359 // which the pvtData is not present. It also denotes 360 // whether the missing pvtData is eligible (i.e., whether 361 // the peer is member of the [namespace, collection] 362 type MissingPvtData struct { 363 Namespace string 364 Collection string 365 IsEligible bool 366 } 367 368 // TxMissingPvtData is a map from txNum to the list of 369 // missing pvtData 370 type TxMissingPvtData map[uint64][]*MissingPvtData 371 372 // BlockAndPvtData encapsulates the block and a map that contains the tuples <seqInBlock, *TxPvtData> 373 // The map is expected to contain the entries only for the transactions that has associated pvt data 374 type BlockAndPvtData struct { 375 Block *common.Block 376 PvtData TxPvtDataMap 377 MissingPvtData TxMissingPvtData 378 } 379 380 // ReconciledPvtdata contains the private data for a block for reconciliation 381 type ReconciledPvtdata struct { 382 BlockNum uint64 383 WriteSets TxPvtDataMap 384 } 385 386 // Add adds a given missing private data in the MissingPrivateDataList 387 func (txMissingPvtData TxMissingPvtData) Add(txNum uint64, ns, coll string, isEligible bool) { 388 txMissingPvtData[txNum] = append(txMissingPvtData[txNum], &MissingPvtData{ns, coll, isEligible}) 389 } 390 391 // RetrievedPvtdata is a dependency that is implemented by coordinator/gossip for ledger 392 // to be able to purge the transactions from the block after retrieving private data 393 type RetrievedPvtdata interface { 394 GetBlockPvtdata() *BlockPvtdata 395 Purge() 396 } 397 398 // TxPvtdataInfo captures information about the requested private data to be retrieved 399 type TxPvtdataInfo struct { 400 TxID string 401 Invalid bool 402 SeqInBlock uint64 403 CollectionPvtdataInfo []*CollectionPvtdataInfo 404 } 405 406 // CollectionPvtdataInfo contains information about the private data for a given collection 407 type CollectionPvtdataInfo struct { 408 Namespace, Collection string 409 ExpectedHash []byte 410 CollectionConfig *peer.StaticCollectionConfig 411 Endorsers []*peer.Endorsement 412 } 413 414 // BlockPvtdata contains the retrieved private data as well as missing and ineligible 415 // private data for use at commit time 416 type BlockPvtdata struct { 417 PvtData TxPvtDataMap 418 MissingPvtData TxMissingPvtData 419 } 420 421 // CommitOptions encapsulates options associated with a block commit. 422 type CommitOptions struct { 423 FetchPvtDataFromLedger bool 424 } 425 426 // PvtCollFilter represents the set of the collection names (as keys of the map with value 'true') 427 type PvtCollFilter map[string]bool 428 429 // PvtNsCollFilter specifies the tuple <namespace, PvtCollFilter> 430 type PvtNsCollFilter map[string]PvtCollFilter 431 432 // NewPvtNsCollFilter constructs an empty PvtNsCollFilter 433 func NewPvtNsCollFilter() PvtNsCollFilter { 434 return make(map[string]PvtCollFilter) 435 } 436 437 // Has returns true if the pvtdata includes the data for collection <ns,coll> 438 func (pvtdata *TxPvtData) Has(ns string, coll string) bool { 439 if pvtdata.WriteSet == nil { 440 return false 441 } 442 for _, nsdata := range pvtdata.WriteSet.NsPvtRwset { 443 if nsdata.Namespace == ns { 444 for _, colldata := range nsdata.CollectionPvtRwset { 445 if colldata.CollectionName == coll { 446 return true 447 } 448 } 449 } 450 } 451 return false 452 } 453 454 // Add adds a namespace-collection tuple to the filter 455 func (filter PvtNsCollFilter) Add(ns string, coll string) { 456 collFilter, ok := filter[ns] 457 if !ok { 458 collFilter = make(map[string]bool) 459 filter[ns] = collFilter 460 } 461 collFilter[coll] = true 462 } 463 464 // Has returns true if the filter has the entry for tuple namespace-collection 465 func (filter PvtNsCollFilter) Has(ns string, coll string) bool { 466 collFilter, ok := filter[ns] 467 if !ok { 468 return false 469 } 470 return collFilter[coll] 471 } 472 473 // PrivateReads captures which private data collections are read during TX simulation. 474 type PrivateReads map[string]map[string]struct{} 475 476 // Add a collection to the set of private data collections that are read by the chaincode. 477 func (pr PrivateReads) Add(ns, coll string) { 478 if _, ok := pr[ns]; !ok { 479 pr[ns] = map[string]struct{}{} 480 } 481 pr[ns][coll] = struct{}{} 482 } 483 484 // Clone returns a copy of this struct. 485 func (pr PrivateReads) Clone() PrivateReads { 486 clone := PrivateReads{} 487 for ns, v := range pr { 488 for coll := range v { 489 clone.Add(ns, coll) 490 } 491 } 492 return clone 493 } 494 495 // Exists returns whether a collection has been read 496 func (pr PrivateReads) Exists(ns, coll string) bool { 497 if c, ok := pr[ns]; ok { 498 if _, ok2 := c[coll]; ok2 { 499 return true 500 } 501 } 502 return false 503 } 504 505 // WritesetMetadata represents the content of the state metadata for each state (key) that gets written to during transaction simulation. 506 type WritesetMetadata map[string]map[string]map[string]map[string][]byte 507 508 // Add metadata to the structure. 509 func (wm WritesetMetadata) Add(ns, coll, key string, metadata map[string][]byte) { 510 if _, ok := wm[ns]; !ok { 511 wm[ns] = map[string]map[string]map[string][]byte{} 512 } 513 if _, ok := wm[ns][coll]; !ok { 514 wm[ns][coll] = map[string]map[string][]byte{} 515 } 516 if metadata == nil { 517 metadata = map[string][]byte{} 518 } 519 wm[ns][coll][key] = metadata 520 } 521 522 // Clone returns a copy of this struct. 523 func (wm WritesetMetadata) Clone() WritesetMetadata { 524 clone := WritesetMetadata{} 525 for ns, cm := range wm { 526 for coll, km := range cm { 527 for key, metadata := range km { 528 clone.Add(ns, coll, key, metadata) 529 } 530 } 531 } 532 return clone 533 } 534 535 // TxSimulationResults captures the details of the simulation results 536 type TxSimulationResults struct { 537 PubSimulationResults *rwset.TxReadWriteSet 538 PvtSimulationResults *rwset.TxPvtReadWriteSet 539 PrivateReads PrivateReads 540 WritesetMetadata WritesetMetadata 541 } 542 543 // GetPubSimulationBytes returns the serialized bytes of public readwrite set 544 func (txSim *TxSimulationResults) GetPubSimulationBytes() ([]byte, error) { 545 return proto.Marshal(txSim.PubSimulationResults) 546 } 547 548 // GetPvtSimulationBytes returns the serialized bytes of private readwrite set 549 func (txSim *TxSimulationResults) GetPvtSimulationBytes() ([]byte, error) { 550 if !txSim.ContainsPvtWrites() { 551 return nil, nil 552 } 553 return proto.Marshal(txSim.PvtSimulationResults) 554 } 555 556 // ContainsPvtWrites returns true if the simulation results include the private writes 557 func (txSim *TxSimulationResults) ContainsPvtWrites() bool { 558 return txSim.PvtSimulationResults != nil 559 } 560 561 // StateListener allows a custom code for performing additional stuff upon state change 562 // for a particular namespace against which the listener is registered. 563 // This helps to perform custom tasks other than the state updates. 564 // A ledger implementation is expected to invoke Function `HandleStateUpdates` once per block and 565 // the `stateUpdates` parameter passed to the function captures the state changes caused by the block 566 // for the namespace. The actual data type of stateUpdates depends on the data model enabled. 567 // For instance, for KV data model, the actual type would be proto message 568 // `github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset.KVWrite` 569 // Function `HandleStateUpdates` is expected to be invoked before block is committed and if this 570 // function returns an error, the ledger implementation is expected to halt block commit operation 571 // and result in a panic. 572 // The function Initialize is invoked only once at the time of opening the ledger. 573 type StateListener interface { 574 Name() string 575 Initialize(ledgerID string, qe SimpleQueryExecutor) error 576 InterestedInNamespaces() []string 577 HandleStateUpdates(trigger *StateUpdateTrigger) error 578 StateCommitDone(channelID string) 579 } 580 581 // StateUpdateTrigger encapsulates the information and helper tools that may be used by a StateListener 582 type StateUpdateTrigger struct { 583 LedgerID string 584 StateUpdates StateUpdates 585 CommittingBlockNum uint64 586 CommittedStateQueryExecutor SimpleQueryExecutor 587 PostCommitQueryExecutor SimpleQueryExecutor 588 } 589 590 // StateUpdates encapsulates the state updates 591 type StateUpdates map[string]*KVStateUpdates 592 593 // KVStateUpdates captures the state updates for a namespace for KV datamodel 594 type KVStateUpdates struct { 595 PublicUpdates []*kvrwset.KVWrite 596 CollHashUpdates map[string][]*kvrwset.KVWriteHash 597 } 598 599 // ConfigHistoryRetriever allow retrieving history of collection configs 600 type ConfigHistoryRetriever interface { 601 MostRecentCollectionConfigBelow(blockNum uint64, chaincodeName string) (*CollectionConfigInfo, error) 602 } 603 604 // MissingPvtDataTracker allows getting information about the private data that is not missing on the peer 605 type MissingPvtDataTracker interface { 606 GetMissingPvtDataInfoForMostRecentBlocks(maxBlocks int) (MissingPvtDataInfo, error) 607 } 608 609 // MissingPvtDataInfo is a map of block number to MissingBlockPvtdataInfo 610 type MissingPvtDataInfo map[uint64]MissingBlockPvtdataInfo 611 612 // MissingBlockPvtdataInfo is a map of transaction number (within the block) to MissingCollectionPvtDataInfo 613 type MissingBlockPvtdataInfo map[uint64][]*MissingCollectionPvtDataInfo 614 615 // MissingCollectionPvtDataInfo includes the name of the chaincode and collection for which private data is missing 616 type MissingCollectionPvtDataInfo struct { 617 Namespace, Collection string 618 } 619 620 // CollectionConfigInfo encapsulates a collection config for a chaincode and its committing block number 621 type CollectionConfigInfo struct { 622 CollectionConfig *peer.CollectionConfigPackage 623 CommittingBlockNum uint64 624 } 625 626 // Add adds a missing data entry to the MissingPvtDataInfo Map 627 func (missingPvtDataInfo MissingPvtDataInfo) Add(blkNum, txNum uint64, ns, coll string) { 628 missingBlockPvtDataInfo, ok := missingPvtDataInfo[blkNum] 629 if !ok { 630 missingBlockPvtDataInfo = make(MissingBlockPvtdataInfo) 631 missingPvtDataInfo[blkNum] = missingBlockPvtDataInfo 632 } 633 634 if _, ok := missingBlockPvtDataInfo[txNum]; !ok { 635 missingBlockPvtDataInfo[txNum] = []*MissingCollectionPvtDataInfo{} 636 } 637 638 missingBlockPvtDataInfo[txNum] = append(missingBlockPvtDataInfo[txNum], 639 &MissingCollectionPvtDataInfo{ 640 Namespace: ns, 641 Collection: coll, 642 }) 643 } 644 645 // CollConfigNotDefinedError is returned whenever an operation 646 // is requested on a collection whose config has not been defined 647 type CollConfigNotDefinedError struct { 648 Ns string 649 } 650 651 func (e *CollConfigNotDefinedError) Error() string { 652 return fmt.Sprintf("collection config not defined for chaincode [%s], pass the collection configuration upon chaincode definition/instantiation", e.Ns) 653 } 654 655 // InvalidCollNameError is returned whenever an operation 656 // is requested on a collection whose name is invalid 657 type InvalidCollNameError struct { 658 Ns, Coll string 659 } 660 661 func (e *InvalidCollNameError) Error() string { 662 return fmt.Sprintf("collection [%s] not defined in the collection config for chaincode [%s]", e.Coll, e.Ns) 663 } 664 665 // PvtdataHashMismatch is used when the hash of private write-set 666 // does not match the corresponding hash present in the block 667 // or there is a mismatch with the boot-KV-hashes present in the 668 // private block store if the legder is created from a snapshot 669 type PvtdataHashMismatch struct { 670 BlockNum, TxNum uint64 671 Namespace, Collection string 672 } 673 674 // DeployedChaincodeInfoProvider is a dependency that is used by ledger to build collection config history 675 // LSCC module is expected to provide an implementation for this dependencies 676 type DeployedChaincodeInfoProvider interface { 677 // Namespaces returns the slice of the namespaces that are used for maintaining chaincode lifecycle data 678 Namespaces() []string 679 // UpdatedChaincodes returns the chaincodes that are getting updated by the supplied 'stateUpdates' 680 UpdatedChaincodes(stateUpdates map[string][]*kvrwset.KVWrite) ([]*ChaincodeLifecycleInfo, error) 681 // ChaincodeInfo returns the info about a deployed chaincode 682 ChaincodeInfo(channelName, chaincodeName string, qe SimpleQueryExecutor) (*DeployedChaincodeInfo, error) 683 // AllChaincodesInfo returns the mapping of chaincode name to DeployedChaincodeInfo for all the deployed chaincodes 684 AllChaincodesInfo(channelName string, qe SimpleQueryExecutor) (map[string]*DeployedChaincodeInfo, error) 685 // CollectionInfo returns the proto msg that defines the named collection. This function can be called for both explicit and implicit collections 686 CollectionInfo(channelName, chaincodeName, collectionName string, qe SimpleQueryExecutor) (*peer.StaticCollectionConfig, error) 687 // ImplicitCollections returns a slice that contains one proto msg for each of the implicit collections 688 ImplicitCollections(channelName, chaincodeName string, qe SimpleQueryExecutor) ([]*peer.StaticCollectionConfig, error) 689 // GenerateImplicitCollectionForOrg generates implicit collection for the org 690 GenerateImplicitCollectionForOrg(mspid string) *peer.StaticCollectionConfig 691 // AllCollectionsConfigPkg returns a combined collection config pkg that contains both explicit and implicit collections 692 AllCollectionsConfigPkg(channelName, chaincodeName string, qe SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) 693 } 694 695 // DeployedChaincodeInfo encapsulates chaincode information from the deployed chaincodes 696 type DeployedChaincodeInfo struct { 697 Name string 698 Hash []byte 699 Version string 700 ExplicitCollectionConfigPkg *peer.CollectionConfigPackage 701 IsLegacy bool 702 } 703 704 // ChaincodeLifecycleInfo captures the update info of a chaincode 705 type ChaincodeLifecycleInfo struct { 706 Name string 707 Deleted bool 708 Details *ChaincodeLifecycleDetails // Can contain finer details about lifecycle event that can be used for certain optimization 709 } 710 711 // ChaincodeLifecycleDetails captures the finer details of chaincode lifecycle event 712 type ChaincodeLifecycleDetails struct { 713 Updated bool // true, if an existing chaincode is updated (false for newly deployed chaincodes). 714 // Following attributes are meaningful only if 'Updated' is true 715 HashChanged bool // true, if the chaincode code package is changed 716 CollectionsUpdated []string // names of the explicit collections that are either added or updated 717 CollectionsRemoved []string // names of the explicit collections that are removed 718 } 719 720 // MembershipInfoProvider is a dependency that is used by ledger to determine whether the current peer is 721 // a member of a collection. Gossip module is expected to provide the dependency to ledger 722 type MembershipInfoProvider interface { 723 // AmMemberOf checks whether the current peer is a member of the given collection 724 AmMemberOf(channelName string, collectionPolicyConfig *peer.CollectionPolicyConfig) (bool, error) 725 // MyImplicitCollectionName returns the name of the implicit collection for the current peer 726 MyImplicitCollectionName() string 727 } 728 729 type HealthCheckRegistry interface { 730 RegisterChecker(string, healthz.HealthChecker) error 731 } 732 733 // ChaincodeLifecycleEventListener interface enables ledger components (mainly, intended for statedb) 734 // to be able to listen to chaincode lifecycle events. 'dbArtifactsTar' represents db specific artifacts 735 // (such as index specs) packaged in a tar. Note that this interface is redefined here (in addition to 736 // the one defined in ledger/cceventmgmt package). Using the same interface for the new lifecycle path causes 737 // a cyclic import dependency. Moreover, eventually the whole package ledger/cceventmgmt is intended to 738 // be removed when migration to new lifecycle is mandated. 739 type ChaincodeLifecycleEventListener interface { 740 // HandleChaincodeDeploy is invoked when chaincode installed + defined becomes true. 741 // The expected usage are to creates all the necessary statedb structures (such as indexes) and update 742 // service discovery info. This function is invoked immediately before the committing the state changes 743 // that contain chaincode definition or when a chaincode install happens 744 HandleChaincodeDeploy(chaincodeDefinition *ChaincodeDefinition, dbArtifactsTar []byte) error 745 // ChaincodeDeployDone is invoked after the chaincode deployment is finished - `succeeded` indicates 746 // whether the deploy finished successfully 747 ChaincodeDeployDone(succeeded bool) 748 } 749 750 // ChaincodeDefinition captures the info about chaincode 751 type ChaincodeDefinition struct { 752 Name string 753 Hash []byte 754 Version string 755 CollectionConfigs *peer.CollectionConfigPackage 756 } 757 758 func (cdef *ChaincodeDefinition) String() string { 759 return fmt.Sprintf("Name=%s, Version=%s, Hash=%#v", cdef.Name, cdef.Version, cdef.Hash) 760 } 761 762 // ChaincodeLifecycleEventProvider enables ledger to create indexes in the statedb 763 type ChaincodeLifecycleEventProvider interface { 764 // RegisterListener is used by ledger to receive a callback alongwith dbArtifacts when a chaincode becomes invocable on the peer 765 // In addition, if needsExistingChaincodesDefinitions is true, the provider calls back the listener with existing invocable chaincodes 766 // This parameter is used when we create a ledger from a snapshot so that we can create indexes for the existing invocable chaincodes 767 // already defined in the imported ledger data 768 RegisterListener(channelID string, listener ChaincodeLifecycleEventListener, needsExistingChaincodesDefinitions bool) error 769 } 770 771 // CustomTxProcessor allows to generate simulation results during commit time for custom transactions. 772 // A custom processor may represent the information in a propriety fashion and can use this process to translate 773 // the information into the form of `TxSimulationResults`. Because, the original information is signed in a 774 // custom representation, an implementation of a `Processor` should be cautious that the custom representation 775 // is used for simulation in an deterministic fashion and should take care of compatibility cross fabric versions. 776 // 'initializingLedger' true indicates that either the transaction being processed is from the genesis block or the ledger is 777 // synching the state (which could happen during peer startup if the statedb is found to be lagging behind the blockchain). 778 // In the former case, the transactions processed are expected to be valid and in the latter case, only valid transactions 779 // are reprocessed and hence any validation can be skipped. 780 type CustomTxProcessor interface { 781 GenerateSimulationResults(txEnvelop *common.Envelope, simulator TxSimulator, initializingLedger bool) error 782 } 783 784 // InvalidTxError is expected to be thrown by a custom transaction processor 785 // if it wants the ledger to record a particular transaction as invalid 786 type InvalidTxError struct { 787 Msg string 788 } 789 790 func (e *InvalidTxError) Error() string { 791 return e.Msg 792 } 793 794 // HashProvider provides access to a hash.Hash for ledger components. 795 // Currently works at a stepping stone to decrease surface area of bccsp 796 type HashProvider interface { 797 GetHash(opts bccsp.HashOpts) (hash.Hash, error) 798 } 799 800 // CommitNotification is sent on each block commit to the channel returned by PeerLedger.CommitNotificationsChannel(). 801 // TxsInfo field contains the info about individual transactions in the block in the order the transactions appear in the block 802 // The transactions with a unique and non-empty txID are included in the notification 803 type CommitNotification struct { 804 BlockNumber uint64 805 TxsInfo []*CommitNotificationTxInfo 806 } 807 808 // CommitNotificationTxInfo contains the details of a transaction that is included in the CommitNotification 809 // ChaincodeID will be nil if the transaction is not an endorser transaction. This may or may not be nil if the tranasction is invalid. 810 // Specifically, it will be nil if the transaction is marked invalid by the validator (e.g., bad payload or insufficient endorements) and it will be non-nil if the transaction is marked invalid for concurrency conflicts. 811 // However, it is guaranteed be non-nil if the transaction is a valid endorser transaction. 812 type CommitNotificationTxInfo struct { 813 TxType common.HeaderType 814 TxID string 815 ValidationCode peer.TxValidationCode 816 ChaincodeID *peer.ChaincodeID 817 ChaincodeEventData []byte 818 } 819 820 //go:generate counterfeiter -o mock/state_listener.go -fake-name StateListener . StateListener 821 //go:generate counterfeiter -o mock/query_executor.go -fake-name QueryExecutor . QueryExecutor 822 //go:generate counterfeiter -o mock/tx_simulator.go -fake-name TxSimulator . TxSimulator 823 //go:generate counterfeiter -o mock/deployed_ccinfo_provider.go -fake-name DeployedChaincodeInfoProvider . DeployedChaincodeInfoProvider 824 //go:generate counterfeiter -o mock/membership_info_provider.go -fake-name MembershipInfoProvider . MembershipInfoProvider 825 //go:generate counterfeiter -o mock/health_check_registry.go -fake-name HealthCheckRegistry . HealthCheckRegistry 826 //go:generate counterfeiter -o mock/cc_event_listener.go -fake-name ChaincodeLifecycleEventListener . ChaincodeLifecycleEventListener 827 //go:generate counterfeiter -o mock/custom_tx_processor.go -fake-name CustomTxProcessor . CustomTxProcessor 828 //go:generate counterfeiter -o mock/cc_event_provider.go -fake-name ChaincodeLifecycleEventProvider . ChaincodeLifecycleEventProvider