github.com/yous1230/fabric@v2.0.0-beta.0.20191224111736-74345bee6ac2+incompatible/core/handlers/validation/builtin/v20/validation_logic.go (about)

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