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