github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/handlers/validation/builtin/v13/validation_logic.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package v13
     8  
     9  import (
    10  	"fmt"
    11  	"regexp"
    12  
    13  	commonerrors "github.com/hechain20/hechain/common/errors"
    14  	"github.com/hechain20/hechain/common/flogging"
    15  	"github.com/hechain20/hechain/core/common/validation/statebased"
    16  	vc "github.com/hechain20/hechain/core/handlers/validation/api/capabilities"
    17  	vi "github.com/hechain20/hechain/core/handlers/validation/api/identities"
    18  	vp "github.com/hechain20/hechain/core/handlers/validation/api/policies"
    19  	vs "github.com/hechain20/hechain/core/handlers/validation/api/state"
    20  	"github.com/hechain20/hechain/protoutil"
    21  	"github.com/hyperledger/fabric-protos-go/common"
    22  	"github.com/hyperledger/fabric-protos-go/peer"
    23  )
    24  
    25  var logger = flogging.MustGetLogger("vscc")
    26  
    27  // previously imported from ccmetadata.AllowedCharsCollectionName but could not change to avoid non-determinism
    28  const AllowedCharsCollectionName = "[A-Za-z0-9_-]+"
    29  
    30  var validCollectionNameRegex = regexp.MustCompile(AllowedCharsCollectionName)
    31  
    32  //go:generate mockery -dir . -name Capabilities -case underscore -output mocks/
    33  
    34  // Capabilities is the local interface that used to generate mocks for foreign interface.
    35  type Capabilities interface {
    36  	vc.Capabilities
    37  }
    38  
    39  //go:generate mockery -dir . -name StateFetcher -case underscore -output mocks/
    40  
    41  // StateFetcher is the local interface that used to generate mocks for foreign interface.
    42  type StateFetcher interface {
    43  	vs.StateFetcher
    44  }
    45  
    46  //go:generate mockery -dir . -name IdentityDeserializer -case underscore -output mocks/
    47  
    48  // IdentityDeserializer is the local interface that used to generate mocks for foreign interface.
    49  type IdentityDeserializer interface {
    50  	vi.IdentityDeserializer
    51  }
    52  
    53  //go:generate mockery -dir . -name PolicyEvaluator -case underscore -output mocks/
    54  
    55  // PolicyEvaluator is the local interface that used to generate mocks for foreign interface.
    56  type PolicyEvaluator interface {
    57  	vp.PolicyEvaluator
    58  }
    59  
    60  //go:generate mockery -dir . -name StateBasedValidator -case underscore -output mocks/
    61  
    62  // noopTranslator implements statebased.PolicyTranslator
    63  // by performing no policy translation; this is okay because
    64  // the implementation of the 1.3 validator has a policy
    65  // evaluator that sirectly consumes SignaturePolicyEnvelope
    66  // policies directly
    67  type noopTranslator struct{}
    68  
    69  func (n *noopTranslator) Translate(b []byte) ([]byte, error) {
    70  	return b, nil
    71  }
    72  
    73  // New creates a new instance of the default VSCC
    74  // Typically this will only be invoked once per peer
    75  func New(c vc.Capabilities, s vs.StateFetcher, d vi.IdentityDeserializer, pe vp.PolicyEvaluator) *Validator {
    76  	vpmgr := &statebased.KeyLevelValidationParameterManagerImpl{
    77  		StateFetcher:     s,
    78  		PolicyTranslator: &noopTranslator{},
    79  	}
    80  	eval := statebased.NewV13Evaluator(pe, vpmgr)
    81  	sbv := statebased.NewKeyLevelValidator(eval, vpmgr)
    82  
    83  	return &Validator{
    84  		capabilities:        c,
    85  		stateFetcher:        s,
    86  		deserializer:        d,
    87  		policyEvaluator:     pe,
    88  		stateBasedValidator: sbv,
    89  	}
    90  }
    91  
    92  // Validator implements the default transaction validation policy,
    93  // which is to check the correctness of the read-write set and the endorsement
    94  // signatures against an endorsement policy that is supplied as argument to
    95  // every invoke
    96  type Validator struct {
    97  	deserializer        vi.IdentityDeserializer
    98  	capabilities        vc.Capabilities
    99  	stateFetcher        vs.StateFetcher
   100  	policyEvaluator     vp.PolicyEvaluator
   101  	stateBasedValidator StateBasedValidator
   102  }
   103  
   104  type validationArtifacts struct {
   105  	rwset        []byte
   106  	prp          []byte
   107  	endorsements []*peer.Endorsement
   108  	chdr         *common.ChannelHeader
   109  	env          *common.Envelope
   110  	payl         *common.Payload
   111  	cap          *peer.ChaincodeActionPayload
   112  }
   113  
   114  func (vscc *Validator) extractValidationArtifacts(
   115  	block *common.Block,
   116  	txPosition int,
   117  	actionPosition int,
   118  ) (*validationArtifacts, error) {
   119  	// get the envelope...
   120  	env, err := protoutil.GetEnvelopeFromBlock(block.Data.Data[txPosition])
   121  	if err != nil {
   122  		logger.Errorf("VSCC error: GetEnvelope failed, err %s", err)
   123  		return nil, err
   124  	}
   125  
   126  	// ...and the payload...
   127  	payl, err := protoutil.UnmarshalPayload(env.Payload)
   128  	if err != nil {
   129  		logger.Errorf("VSCC error: GetPayload failed, err %s", err)
   130  		return nil, err
   131  	}
   132  
   133  	chdr, err := protoutil.UnmarshalChannelHeader(payl.Header.ChannelHeader)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  
   138  	// validate the payload type
   139  	if common.HeaderType(chdr.Type) != common.HeaderType_ENDORSER_TRANSACTION {
   140  		logger.Errorf("Only Endorser Transactions are supported, provided type %d", chdr.Type)
   141  		err = fmt.Errorf("Only Endorser Transactions are supported, provided type %d", chdr.Type)
   142  		return nil, err
   143  	}
   144  
   145  	// ...and the transaction...
   146  	tx, err := protoutil.UnmarshalTransaction(payl.Data)
   147  	if err != nil {
   148  		logger.Errorf("VSCC error: GetTransaction failed, err %s", err)
   149  		return nil, err
   150  	}
   151  
   152  	cap, err := protoutil.UnmarshalChaincodeActionPayload(tx.Actions[actionPosition].Payload)
   153  	if err != nil {
   154  		logger.Errorf("VSCC error: GetChaincodeActionPayload failed, err %s", err)
   155  		return nil, err
   156  	}
   157  
   158  	pRespPayload, err := protoutil.UnmarshalProposalResponsePayload(cap.Action.ProposalResponsePayload)
   159  	if err != nil {
   160  		err = fmt.Errorf("GetProposalResponsePayload error %s", err)
   161  		return nil, err
   162  	}
   163  	if pRespPayload.Extension == nil {
   164  		err = fmt.Errorf("nil pRespPayload.Extension")
   165  		return nil, err
   166  	}
   167  	respPayload, err := protoutil.UnmarshalChaincodeAction(pRespPayload.Extension)
   168  	if err != nil {
   169  		err = fmt.Errorf("GetChaincodeAction error %s", err)
   170  		return nil, err
   171  	}
   172  
   173  	return &validationArtifacts{
   174  		rwset:        respPayload.Results,
   175  		prp:          cap.Action.ProposalResponsePayload,
   176  		endorsements: cap.Action.Endorsements,
   177  		chdr:         chdr,
   178  		env:          env,
   179  		payl:         payl,
   180  		cap:          cap,
   181  	}, nil
   182  }
   183  
   184  // Validate validates the given envelope corresponding to a transaction with an endorsement
   185  // policy as given in its serialized form.
   186  // Note that in the case of dependencies in a block, such as tx_n modifying the endorsement policy
   187  // for key a and tx_n+1 modifying the value of key a, Validate(tx_n+1) will block until Validate(tx_n)
   188  // has been resolved. If working with a limited number of goroutines for parallel validation, ensure
   189  // that they are allocated to transactions in ascending order.
   190  func (vscc *Validator) Validate(
   191  	block *common.Block,
   192  	namespace string,
   193  	txPosition int,
   194  	actionPosition int,
   195  	policyBytes []byte,
   196  ) commonerrors.TxValidationError {
   197  	vscc.stateBasedValidator.PreValidate(uint64(txPosition), block)
   198  
   199  	va, err := vscc.extractValidationArtifacts(block, txPosition, actionPosition)
   200  	if err != nil {
   201  		vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), err)
   202  		return policyErr(err)
   203  	}
   204  
   205  	txverr := vscc.stateBasedValidator.Validate(
   206  		namespace,
   207  		block.Header.Number,
   208  		uint64(txPosition),
   209  		va.rwset,
   210  		va.prp,
   211  		policyBytes,
   212  		va.endorsements,
   213  	)
   214  	if txverr != nil {
   215  		logger.Errorf("VSCC error: stateBasedValidator.Validate failed, err %s", txverr)
   216  		vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), txverr)
   217  		return txverr
   218  	}
   219  
   220  	// do some extra validation that is specific to lscc
   221  	if namespace == "lscc" {
   222  		logger.Debugf("VSCC info: doing special validation for LSCC")
   223  		err := vscc.ValidateLSCCInvocation(va.chdr.ChannelId, va.env, va.cap, va.payl, vscc.capabilities)
   224  		if err != nil {
   225  			logger.Errorf("VSCC error: ValidateLSCCInvocation failed, err %s", err)
   226  			vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), err)
   227  			return err
   228  		}
   229  	}
   230  
   231  	vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), nil)
   232  	return nil
   233  }
   234  
   235  func policyErr(err error) *commonerrors.VSCCEndorsementPolicyError {
   236  	return &commonerrors.VSCCEndorsementPolicyError{
   237  		Err: err,
   238  	}
   239  }