github.com/yimialmonte/fabric@v2.1.1+incompatible/core/tx/processor_factory.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tx
     8  
     9  import (
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/hyperledger/fabric-protos-go/common"
    13  	"github.com/hyperledger/fabric-protos-go/peer"
    14  	"github.com/hyperledger/fabric/pkg/tx"
    15  	"github.com/hyperledger/fabric/protoutil"
    16  )
    17  
    18  // ProcessorFactory maintains a mapping between transaction type and associate `ProcessorCreator`
    19  type ProcessorFactory struct {
    20  	ProcessorCreators map[common.HeaderType]tx.ProcessorCreator
    21  }
    22  
    23  // CreateProcessor unmarshals bytes into an Envelope and invokes a ProcessorCreators corresponding to the transaction type
    24  // present in the ChannelHeader. If successful, this function returns the Processor and simulatedRWSet created by the ProcessorCreators.
    25  // However, if this function encounters and error in detecting the transaction type or a
    26  // ProcessorCreators has not been registered for the transaction type, the error returned would be of type
    27  // `tx.InvalidErr` which implies that the transaction is found to be invalid at the very beginning stage
    28  func (f *ProcessorFactory) CreateProcessor(txEnvelopeBytes []byte) (processor tx.Processor, simulatedRWSet [][]byte, err error) {
    29  	txEnv, err := validateProtoAndConstructTxEnv(txEnvelopeBytes)
    30  	if err != nil {
    31  		return nil, nil, err
    32  	}
    33  	c, ok := f.ProcessorCreators[common.HeaderType(txEnv.ChannelHeader.Type)]
    34  	if !ok {
    35  		return nil, nil, &tx.InvalidErr{
    36  			ActualErr:      errors.Errorf("invalid transaction type %d", txEnv.ChannelHeader.Type),
    37  			ValidationCode: peer.TxValidationCode_UNKNOWN_TX_TYPE,
    38  		}
    39  	}
    40  	return c.NewProcessor(txEnv)
    41  }
    42  
    43  // validateProtoAndConstructTxEnv attemps to unmarshal the bytes and prepare an instance of struct tx.Envelope
    44  // It returns an error of type `tx.InvalidErr` if the proto message is found to be invalid
    45  func validateProtoAndConstructTxEnv(txEnvelopeBytes []byte) (*tx.Envelope, error) {
    46  	txenv, err := protoutil.UnmarshalEnvelope(txEnvelopeBytes)
    47  	if err != nil {
    48  		return nil, &tx.InvalidErr{
    49  			ActualErr:      err,
    50  			ValidationCode: peer.TxValidationCode_INVALID_OTHER_REASON,
    51  		}
    52  	}
    53  
    54  	if len(txenv.Payload) == 0 {
    55  		return nil, &tx.InvalidErr{
    56  			ActualErr:      errors.New("nil envelope payload"),
    57  			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
    58  		}
    59  	}
    60  
    61  	payload, err := protoutil.UnmarshalPayload(txenv.Payload)
    62  	if err != nil {
    63  		return nil, &tx.InvalidErr{
    64  			ActualErr:      err,
    65  			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
    66  		}
    67  	}
    68  
    69  	if payload.Header == nil {
    70  		return nil, &tx.InvalidErr{
    71  			ActualErr:      errors.New("nil payload header"),
    72  			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
    73  		}
    74  	}
    75  
    76  	if len(payload.Header.ChannelHeader) == 0 {
    77  		return nil, &tx.InvalidErr{
    78  			ActualErr:      errors.New("nil payload channel header"),
    79  			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
    80  		}
    81  	}
    82  
    83  	chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
    84  	if err != nil {
    85  		return nil, &tx.InvalidErr{
    86  			ActualErr:      err,
    87  			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
    88  		}
    89  	}
    90  
    91  	if len(payload.Header.SignatureHeader) == 0 {
    92  		return nil, &tx.InvalidErr{
    93  			ActualErr:      errors.New("nil payload signature header"),
    94  			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
    95  		}
    96  	}
    97  
    98  	shdr, err := protoutil.UnmarshalSignatureHeader(payload.Header.SignatureHeader)
    99  	if err != nil {
   100  		return nil, &tx.InvalidErr{
   101  			ActualErr:      err,
   102  			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
   103  		}
   104  	}
   105  
   106  	//other checks over shdr.Nonce, shdr.Creator can be added if universally applicable
   107  
   108  	//what TODO in legacy validation:
   109  	//   validate cHdr.ChainID ?
   110  	//   validate epoch in cHdr.Epoch?
   111  
   112  	return &tx.Envelope{
   113  			SignedBytes:          txenv.Payload,
   114  			Signature:            txenv.Signature,
   115  			Data:                 payload.Data,
   116  			ChannelHeaderBytes:   payload.Header.ChannelHeader,
   117  			SignatureHeaderBytes: payload.Header.SignatureHeader,
   118  			ChannelHeader:        chdr,
   119  			SignatureHeader:      shdr,
   120  		},
   121  		nil
   122  }