github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/pkg/tx/interfaces.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  SPDX-License-Identifier: Apache-2.0
     4  */
     5  
     6  package tx
     7  
     8  import (
     9  	"fmt"
    10  	"io"
    11  
    12  	"github.com/hyperledger/fabric-protos-go/common"
    13  	"github.com/hyperledger/fabric-protos-go/peer"
    14  	"github.com/hyperledger/fabric/pkg/statedata"
    15  )
    16  
    17  // ProcessorCreator creates a new instance of a processor of a particular transaction type.
    18  // In addition, this function also returns zero or more simulated readwrite sets that may
    19  // be present in the transaction if the transaction type supports enclosing of these.
    20  // There is expected to be one to one mapping between a supported transaction type and the
    21  // corresponding implementation of this interface. The transaction envelope passed to the
    22  // function `NewProcessor` is guaranteed to be of the associated transaction type.
    23  // If the ProcessCreator finds the transaction envelop to be invalid the err returned by
    24  // this function should be of type `InvalidErr`
    25  type ProcessorCreator interface {
    26  	NewProcessor(txenv *Envelope) (processor Processor, simulatedRWSet [][]byte, err error)
    27  }
    28  
    29  // Processor contains logic for processing a transaction on the committing peer.
    30  // One instance of a Processor is created for each transaction via `NewProcessor` function on the
    31  // corresponding `ProcessorCreator`.
    32  //
    33  // On a Processor, the first a `Preprocess` function is invoked and then the `Process` function is invoked.
    34  // The `Preprocess` function is invoked exactly once however, this may be invoked in parallel on different instances of Processors.
    35  // The function `Process` is invoked one by one on the `Processors` in the order in which the associated transactions
    36  // appear in the block. The `State` passed to the `Process` function represents the world state for the channel as of preceding valid
    37  // transaction in the block. For the purpose of efficiency (e.g., speculative execution), this function can be invoked more
    38  // than once and hence this function should not preserve anything in the form of instance variables.
    39  // Eventually, the function `Done` is invoked when the `Processor` has been used so as to indicate that the `Processor` can
    40  // release any resources held. This invocation could be because of a successful invocation to the `Process` function or
    41  // because the associated transaction is found to be invalid at any stage during the process
    42  // (e.g., concurrency conflict with other transactions). If the `Processor` finds the transaction to be invalid at any stage,
    43  // the error returned by the functions `PreProcess` and `Process` should be of type `InvalidErr`
    44  //
    45  // The intent is to support different transaction types via interface Processor such as pure endorser transactions,
    46  // pure post-order transactions, and a mixed transaction - e.g., a transaction that combines an endorser transaction and
    47  // and a post-order transaction (say, a token transaction).
    48  //
    49  // Below is the detail description of the semantics of the function `Process`
    50  // In order to process a transaction on a committing peer, we first evaluate the simulated readwrite set of the transaction
    51  //(returned by the function `NewProcessor` on the corresponding `ProcessorCreator`).
    52  // If the simulated part is found to have a concurrency conflict with one or more preceding valid transactions
    53  // (either a preceding transaction in the same block or in a preceding block), we mark the transaction invalid.
    54  // However, if simulated part of the transaction is found to be conflict free,
    55  // this is assumed that the transaction has logically started executing during commit time and has produced the
    56  // writes present in the simulated part of the transaction. In this case, the transaction processing is
    57  // continued from this point on and the `Process` function gives a chance to the `Processor` to complete the
    58  // transaction processing. Via the `Process` function, the transaction processor can perform reads/writes to the
    59  // state passed to this function.
    60  //
    61  // Following is an illustration how the Processor is potentially expected be implemented for the transaction type "ENDORSER_TRANSACTION".
    62  // 1) Preprocess function - Verifies the signatures and keeps the identities in internal state
    63  // 2) Process function - Reads and evaluates endorsement policies that are applicable to the transactions writes.
    64  //    The parameter "proposedWrites" to the Process function, contains the data items are intended writes by the processing of
    65  //    the simulatedRWSet. The endorser transaction processor can load the applicable endorsement policies (such as chaincode or key-based)
    66  //    and returns an error of type InvalidErr if the endorsement policy is not satisfied.
    67  //
    68  type Processor interface {
    69  	Preprocess(latestChannelConfig *ChannelConfig) error
    70  	Process(state *State, proposedWrites *statedata.ProposedWrites) error
    71  	Done()
    72  }
    73  
    74  // InvalidErr is intended to be used by a ProcessorCreator or a Processor to indicate that the transaction is found to be invalid
    75  type InvalidErr struct {
    76  	ActualErr      error
    77  	ValidationCode peer.TxValidationCode
    78  }
    79  
    80  func (e *InvalidErr) msgWithoutStack() string {
    81  	return fmt.Sprintf("ValidationCode = %s, ActualErr = %s", e.ValidationCode.String(), e.ActualErr)
    82  }
    83  
    84  func (e *InvalidErr) msgWithStack() string {
    85  	return fmt.Sprintf("ValidationCode = %s, ActualErr = %+v", e.ValidationCode.String(), e.ActualErr)
    86  }
    87  
    88  func (e *InvalidErr) Error() string {
    89  	return e.msgWithoutStack()
    90  }
    91  
    92  // Format implements interface fmt.Formatter
    93  func (e *InvalidErr) Format(s fmt.State, verb rune) {
    94  	switch verb {
    95  	case 'v':
    96  		if s.Flag('+') {
    97  			io.WriteString(s, e.msgWithStack())
    98  			return
    99  		}
   100  		fallthrough
   101  	case 's':
   102  		io.WriteString(s, e.msgWithoutStack())
   103  	case 'q':
   104  		fmt.Fprintf(s, "%q", e.msgWithoutStack())
   105  	}
   106  }
   107  
   108  // ReadHinter is an optional interface that a `Processor` implementation is encouraged to
   109  // implement if the `Processor` can give any hints about what data items it would potentially read
   110  // during its processing. This helps in pre-fetching/bulkloading the data in order to boost the performance
   111  // For instance, the `Processor` implementation for the endorser transactions is expected to give hint
   112  // about the endorsement policies based on the chaincode/collection/keys present in the "potentialWrites" parameter
   113  // (which in turn are derived from the simulated readwrite set present in the transaction envelope)
   114  // If a `Processor` implements this interface, the function `ReadHint` also gets the same treatment as the function `PreProcess`
   115  // i.e., this is invoked before invoking function `Process` and exactly once and may be invoked in parallel on different
   116  // instances of Processors. Note that the Preprocess and ReadHint functions on a Processor can get invoked in parallel
   117  type ReadHinter interface {
   118  	ReadHint(potentialWrites *statedata.WriteHint) *statedata.ReadHint
   119  }
   120  
   121  // Reprocessor is an optional interface that a `Processor` is encouraged to implement if a
   122  // a significant large number of transactions of the corresponding type are expected to be present and
   123  // validation of the transaction is significantly resource consuming (e.g., signature matching/crypto operations)
   124  // as compare to manipulating the state.
   125  // The main context in which the function in this interface is to be invoked is to rebuild the ledger constructs such as
   126  // statedb and historydb from the blocks that has already been processed in the past.
   127  // For instance, if the statedb is dropped and it is to be rebuilt, fabric will only use function in this interface (if implemented)
   128  // instead of the function in the Processor interface.
   129  // The function in this interface can safely assume that only transaction that are processed using this
   130  // were found to be valid earlier (when Processor interface was used for processing the transaction for the first time)
   131  // and hence, this function can skip any validation step and can just manipulate the state. However, if there is
   132  // no significant difference in the resource consumption, there is no value in implementing this interface and
   133  // the regular functions in the Processor interface would be invoked
   134  type Reprocessor interface {
   135  	Reprocess(state *State, latestChannelConfig *ChannelConfig, proposedWrites *statedata.ProposedWrites)
   136  }
   137  
   138  // ReprocessReadHinter is an optional interface that a `Processor` may choose to implement if it implements Reprocessor.
   139  // This is similar to as a processor may implement the ReadHinter interface albiet this gets invoked only if Reprocessor
   140  // is used for processing the transaction
   141  type ReprocessReadHinter interface {
   142  	ReprocessReadHint(potentialWrites *statedata.WriteHint) *statedata.ReadHint
   143  }
   144  
   145  // PvtdataSourceHinter is an optional interface that a `Processor` implements to return the peers
   146  // (identity bytes, e.g., certs) that could be the potential source for the private data associated
   147  // with the transaction
   148  type PvtdataSourceHinter interface {
   149  	PvtdataSource() [][]byte
   150  }
   151  
   152  // ChannelConfig gives handle to the channel config
   153  type ChannelConfig struct {
   154  }
   155  
   156  // State exposes functions that helps a `Processor` in retrieving the latest state
   157  // The `State` passed to the `Process` function represents the world state for the channel as of
   158  // commit of the preceding valid transaction in the block
   159  type State struct {
   160  	BackingState state
   161  }
   162  
   163  // GetState returns value associated with a tuple <namespace, key>
   164  func (s *State) GetState(ns, key string) ([]byte, error) {
   165  	return s.BackingState.GetState(ns, key)
   166  }
   167  
   168  // GetStateMetadata returns a map containing the metadata associated with a tuple <namespace, key>
   169  func (s *State) GetStateMetadata(ns, key string) (map[string][]byte, error) {
   170  	return s.BackingState.GetStateMetadata(ns, key)
   171  }
   172  
   173  // GetStateRangeScanIterator returns an iterator that can be used to iterate over all the keys
   174  // present in the range startKey (inclusive) and endKey (exclusive) for the a namespace.
   175  func (s *State) GetStateRangeScanIterator(ns, startKey, endKey string) (*KeyValueItr, error) {
   176  	itr, err := s.BackingState.GetStateRangeScanIterator(ns, startKey, endKey)
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  	return &KeyValueItr{
   181  		BackingItr: itr,
   182  	}, nil
   183  }
   184  
   185  // SetState sets the value associated with a tuple <namespace, key>
   186  // A nil value implies the delete of the key
   187  func (s *State) SetState(ns, key string, value []byte) error {
   188  	return s.BackingState.SetState(ns, key, value)
   189  }
   190  
   191  // SetStateMetadata sets the metadata associated with a tuple <namespace, key> for an existing key
   192  // This function is a noop for a non existing key. A nil metadata implied the delete of the metadata
   193  func (s *State) SetStateMetadata(ns, key string, metadata map[string][]byte) error {
   194  	return s.BackingState.SetStateMetadata(ns, key, metadata)
   195  }
   196  
   197  // GetPrivateDataMetadataByHash returns the metadata associated with a tuple <namespace, collection, keyhash>
   198  func (s *State) GetPrivateDataMetadataByHash(ns, coll string, keyHash []byte) (map[string][]byte, error) {
   199  	return s.BackingState.GetPrivateDataMetadataByHash(ns, coll, keyHash)
   200  }
   201  
   202  // KeyValueItr helps iterates over the results of a range scan query
   203  type KeyValueItr struct {
   204  	BackingItr keyValueItr
   205  }
   206  
   207  // Next returns the next result. A nil in the return value implies that no more results are available
   208  func (i *KeyValueItr) Next() (*statedata.KeyValue, error) {
   209  	return i.BackingItr.Next()
   210  }
   211  
   212  // Close closes the iterator
   213  func (i *KeyValueItr) Close() {
   214  	i.BackingItr.Close()
   215  }
   216  
   217  // Envelope contains data of the common.Envelope; some byte fields are already
   218  // unmarshalled to structs and we preserve the unmarshalled version so as to not
   219  // duplicate the unmarshalling work. Still, given the non-deterministic nature of
   220  // protobufs, we preserve their original byte representation so that the tx processor
   221  // may for instance verify signatures or perform bitwise operations on their original
   222  // representation.
   223  type Envelope struct {
   224  	// SignedBytes contains the marshalled common.Payload in the envelope
   225  	SignedBytes []byte
   226  	// Signature contains the creator's signature over the SignedBytes
   227  	Signature []byte
   228  	// Data contains the opaque Data bytes in the common.Payload
   229  	Data []byte
   230  	// ChannelHeaderBytes contains the marshalled ChannelHeader of the common.Header
   231  	ChannelHeaderBytes []byte
   232  	// ChannelHeaderBytes contains the marshalled SignatureHeader of the common.Header
   233  	SignatureHeaderBytes []byte
   234  	// ChannelHeader contains the ChannelHeader of this envelope
   235  	ChannelHeader *common.ChannelHeader
   236  	// SignatureHeader contains the SignatureHeader of this envelope
   237  	SignatureHeader *common.SignatureHeader
   238  }
   239  
   240  //**********************    Unexported types ***********************************************//
   241  // state represents the latest state that is passed to the "Process" function of the TxProcessor
   242  type state interface {
   243  	GetState(ns, key string) ([]byte, error)
   244  	GetStateMetadata(ns, key string) (map[string][]byte, error)
   245  	GetStateRangeScanIterator(ns, startKey, endKey string) (keyValueItr, error)
   246  	SetState(ns, key string, value []byte) error
   247  	SetStateMetadata(ns, key string, metadata map[string][]byte) error
   248  	GetPrivateDataMetadataByHash(ns, coll string, keyHash []byte) (map[string][]byte, error)
   249  }
   250  
   251  // keyValueItr iterates over a range of key-values
   252  type keyValueItr interface {
   253  	Next() (*statedata.KeyValue, error)
   254  	Close()
   255  }