github.com/zhouxv/fabric@v2.1.1+incompatible/core/common/validation/msgvalidation_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package validation
     8  
     9  import (
    10  	"fmt"
    11  	"strconv"
    12  	"testing"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	"github.com/hyperledger/fabric-protos-go/common"
    16  	"github.com/hyperledger/fabric-protos-go/peer"
    17  	"github.com/hyperledger/fabric/bccsp/sw"
    18  	"github.com/hyperledger/fabric/msp"
    19  	"github.com/hyperledger/fabric/protoutil"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func createTestTransactionEnvelope(channel string, response *peer.Response, simRes []byte) (*common.Envelope, error) {
    24  	prop, err := createTestProposalAndSignedProposal(channel)
    25  	if err != nil {
    26  		return nil, fmt.Errorf("failed to create test proposal and signed proposal, err %s", err)
    27  	}
    28  
    29  	// endorse it to get a proposal response
    30  	presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), signer)
    31  	if err != nil {
    32  		return nil, fmt.Errorf("CreateProposalResponse failed, err %s", err)
    33  	}
    34  
    35  	// assemble a transaction from that proposal and endorsement
    36  	tx, err := protoutil.CreateSignedTx(prop, signer, presp)
    37  	if err != nil {
    38  		return nil, fmt.Errorf("CreateSignedTx failed, err %s", err)
    39  	}
    40  
    41  	return tx, nil
    42  }
    43  
    44  func createTestProposalAndSignedProposal(channel string) (*peer.Proposal, error) {
    45  	// get a toy proposal
    46  	prop, err := getProposal(channel)
    47  	if err != nil {
    48  		return nil, fmt.Errorf("getProposal failed, err %s", err)
    49  	}
    50  
    51  	return prop, nil
    52  }
    53  
    54  func protoMarshal(t *testing.T, m proto.Message) []byte {
    55  	bytes, err := proto.Marshal(m)
    56  	assert.NoError(t, err)
    57  	return bytes
    58  }
    59  
    60  // createTestHeader creates a header for a given transaction type, channel id, and creator
    61  // Based on useGoodTxid, the returned header will have either a good or bad txid for testing purpose
    62  func createTestHeader(t *testing.T, txType common.HeaderType, channelId string, creator []byte, useGoodTxid bool) (*common.Header, error) {
    63  	nonce := []byte("nonce-abc-12345")
    64  
    65  	// useGoodTxid is used to for testing purpose. When it is true, we use a bad value for txid
    66  	txid := "bad"
    67  	if useGoodTxid {
    68  		txid = protoutil.ComputeTxID(nonce, creator)
    69  	}
    70  
    71  	chdr := &common.ChannelHeader{
    72  		Type:      int32(txType),
    73  		ChannelId: channelId,
    74  		TxId:      txid,
    75  		Epoch:     uint64(0),
    76  	}
    77  
    78  	shdr := &common.SignatureHeader{
    79  		Creator: creator,
    80  		Nonce:   nonce,
    81  	}
    82  
    83  	return &common.Header{
    84  		ChannelHeader:   protoMarshal(t, chdr),
    85  		SignatureHeader: protoMarshal(t, shdr),
    86  	}, nil
    87  }
    88  
    89  func createTestEnvelope(t *testing.T, data []byte, header *common.Header, signer msp.SigningIdentity) (*common.Envelope, error) {
    90  	payload := &common.Payload{
    91  		Header: header,
    92  		Data:   data,
    93  	}
    94  	payloadBytes := protoMarshal(t, payload)
    95  
    96  	signature, err := signer.Sign(payloadBytes)
    97  	assert.NoError(t, err)
    98  
    99  	return &common.Envelope{
   100  		Payload:   payloadBytes,
   101  		Signature: signature,
   102  	}, nil
   103  }
   104  
   105  func TestCheckSignatureFromCreator(t *testing.T) {
   106  	response := &peer.Response{Status: 200}
   107  	simRes := []byte("simulation_result")
   108  
   109  	env, err := createTestTransactionEnvelope("testchannelid", response, simRes)
   110  	assert.Nil(t, err, "failed to create test transaction: %s", err)
   111  	assert.NotNil(t, env)
   112  
   113  	// get the payload from the envelope
   114  	payload, err := protoutil.UnmarshalPayload(env.Payload)
   115  	assert.NoError(t, err, "GetPayload returns err %s", err)
   116  
   117  	// validate the header
   118  	chdr, shdr, err := validateCommonHeader(payload.Header)
   119  	assert.NoError(t, err, "validateCommonHeader returns err %s", err)
   120  
   121  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   122  	assert.NoError(t, err)
   123  
   124  	// validate the signature in the envelope
   125  	err = checkSignatureFromCreator(shdr.Creator, env.Signature, env.Payload, chdr.ChannelId, cryptoProvider)
   126  	assert.NoError(t, err, "checkSignatureFromCreator returns err %s", err)
   127  
   128  	// corrupt the creator
   129  	err = checkSignatureFromCreator([]byte("junk"), env.Signature, env.Payload, chdr.ChannelId, cryptoProvider)
   130  	assert.Error(t, err)
   131  	assert.Contains(t, err.Error(), "MSP error: could not deserialize")
   132  
   133  	// check nonexistent channel
   134  	err = checkSignatureFromCreator(shdr.Creator, env.Signature, env.Payload, "junkchannel", cryptoProvider)
   135  	assert.Error(t, err)
   136  	assert.Contains(t, err.Error(), "MSP error: channel doesn't exist")
   137  }
   138  
   139  func ToHex(q uint64) string {
   140  	return "0x" + strconv.FormatUint(q, 16)
   141  }