github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/protos/utils/txutils_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package utils_test
     8  
     9  import (
    10  	"encoding/hex"
    11  	"errors"
    12  	"testing"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	mockmsp "github.com/hyperledger/fabric/common/mocks/msp"
    16  	"github.com/hyperledger/fabric/common/util"
    17  	cb "github.com/hyperledger/fabric/protos/common"
    18  	pb "github.com/hyperledger/fabric/protos/peer"
    19  	"github.com/hyperledger/fabric/protos/utils"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestGetPayloads(t *testing.T) {
    24  	var txAction *pb.TransactionAction
    25  	var err error
    26  
    27  	// good
    28  	ccActionBytes, _ := proto.Marshal(&pb.ChaincodeAction{
    29  		Results: []byte("results"),
    30  	})
    31  	proposalResponsePayload := &pb.ProposalResponsePayload{
    32  		Extension: ccActionBytes,
    33  	}
    34  	proposalResponseBytes, err := proto.Marshal(proposalResponsePayload)
    35  	ccActionPayload := &pb.ChaincodeActionPayload{
    36  		Action: &pb.ChaincodeEndorsedAction{
    37  			ProposalResponsePayload: proposalResponseBytes,
    38  		},
    39  	}
    40  	ccActionPayloadBytes, _ := proto.Marshal(ccActionPayload)
    41  	txAction = &pb.TransactionAction{
    42  		Payload: ccActionPayloadBytes,
    43  	}
    44  	_, _, err = utils.GetPayloads(txAction)
    45  	assert.NoError(t, err, "Unexpected error getting payload bytes")
    46  	t.Logf("error1 [%s]", err)
    47  
    48  	// nil proposal response extension
    49  	proposalResponseBytes, err = proto.Marshal(&pb.ProposalResponsePayload{
    50  		Extension: nil,
    51  	})
    52  	ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
    53  		Action: &pb.ChaincodeEndorsedAction{
    54  			ProposalResponsePayload: proposalResponseBytes,
    55  		},
    56  	})
    57  	txAction = &pb.TransactionAction{
    58  		Payload: ccActionPayloadBytes,
    59  	}
    60  	_, _, err = utils.GetPayloads(txAction)
    61  	assert.Error(t, err, "Expected error with nil proposal response extension")
    62  	t.Logf("error2 [%s]", err)
    63  
    64  	// malformed proposal response payload
    65  	ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
    66  		Action: &pb.ChaincodeEndorsedAction{
    67  			ProposalResponsePayload: []byte("bad payload"),
    68  		},
    69  	})
    70  	txAction = &pb.TransactionAction{
    71  		Payload: ccActionPayloadBytes,
    72  	}
    73  	_, _, err = utils.GetPayloads(txAction)
    74  	assert.Error(t, err, "Expected error with malformed proposal response payload")
    75  	t.Logf("error3 [%s]", err)
    76  
    77  	// malformed proposal response payload extension
    78  	proposalResponseBytes, _ = proto.Marshal(&pb.ProposalResponsePayload{
    79  		Extension: []byte("bad extension"),
    80  	})
    81  	ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
    82  		Action: &pb.ChaincodeEndorsedAction{
    83  			ProposalResponsePayload: proposalResponseBytes,
    84  		},
    85  	})
    86  	txAction = &pb.TransactionAction{
    87  		Payload: ccActionPayloadBytes,
    88  	}
    89  	_, _, err = utils.GetPayloads(txAction)
    90  	assert.Error(t, err, "Expected error with malformed proposal response extension")
    91  	t.Logf("error4 [%s]", err)
    92  
    93  	// nil proposal response payload extension
    94  	proposalResponseBytes, _ = proto.Marshal(&pb.ProposalResponsePayload{
    95  		ProposalHash: []byte("hash"),
    96  	})
    97  	ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
    98  		Action: &pb.ChaincodeEndorsedAction{
    99  			ProposalResponsePayload: proposalResponseBytes,
   100  		},
   101  	})
   102  	txAction = &pb.TransactionAction{
   103  		Payload: ccActionPayloadBytes,
   104  	}
   105  	_, _, err = utils.GetPayloads(txAction)
   106  	assert.Error(t, err, "Expected error with nil proposal response extension")
   107  	t.Logf("error5 [%s]", err)
   108  
   109  	// malformed transaction action payload
   110  	txAction = &pb.TransactionAction{
   111  		Payload: []byte("bad payload"),
   112  	}
   113  	_, _, err = utils.GetPayloads(txAction)
   114  	assert.Error(t, err, "Expected error with malformed transaction action payload")
   115  	t.Logf("error6 [%s]", err)
   116  
   117  }
   118  
   119  func TestCreateSignedTx(t *testing.T) {
   120  	var err error
   121  	prop := &pb.Proposal{}
   122  
   123  	signID, err := mockmsp.NewNoopMsp().GetDefaultSigningIdentity()
   124  	assert.NoError(t, err, "Unexpected error getting signing identity")
   125  	signerBytes, err := signID.Serialize()
   126  	assert.NoError(t, err, "Unexpected error serializing signing identity")
   127  
   128  	ccHeaderExtensionBytes, _ := proto.Marshal(&pb.ChaincodeHeaderExtension{})
   129  	chdrBytes, _ := proto.Marshal(&cb.ChannelHeader{
   130  		Extension: ccHeaderExtensionBytes,
   131  	})
   132  	shdrBytes, _ := proto.Marshal(&cb.SignatureHeader{
   133  		Creator: signerBytes,
   134  	})
   135  	responses := []*pb.ProposalResponse{&pb.ProposalResponse{}}
   136  
   137  	// malformed chaincode header extension
   138  	headerBytes, _ := proto.Marshal(&cb.Header{
   139  		ChannelHeader:   []byte("bad channel header"),
   140  		SignatureHeader: shdrBytes,
   141  	})
   142  	prop.Header = headerBytes
   143  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   144  	assert.Error(t, err, "Expected error with malformed chaincode extension")
   145  
   146  	// malformed signature header
   147  	headerBytes, _ = proto.Marshal(&cb.Header{
   148  		SignatureHeader: []byte("bad signature header"),
   149  	})
   150  	prop.Header = headerBytes
   151  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   152  	assert.Error(t, err, "Expected error with malformed signature header")
   153  
   154  	// set up the header bytes for the remaining tests
   155  	headerBytes, _ = proto.Marshal(&cb.Header{
   156  		ChannelHeader:   chdrBytes,
   157  		SignatureHeader: shdrBytes,
   158  	})
   159  	prop.Header = headerBytes
   160  
   161  	// bad status
   162  	responses = []*pb.ProposalResponse{&pb.ProposalResponse{
   163  		Payload: []byte("payload"),
   164  		Response: &pb.Response{
   165  			Status: int32(100),
   166  		},
   167  	}}
   168  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   169  	assert.Error(t, err, "Expected error with status code not equal to 200")
   170  
   171  	// non-matching responses
   172  	responses = []*pb.ProposalResponse{&pb.ProposalResponse{
   173  		Payload: []byte("payload"),
   174  		Response: &pb.Response{
   175  			Status: int32(200),
   176  		},
   177  	}}
   178  	responses = append(responses, &pb.ProposalResponse{
   179  		Payload: []byte("payload2"),
   180  		Response: &pb.Response{
   181  			Status: int32(200),
   182  		},
   183  	})
   184  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   185  	assert.Error(t, err, "Expected error with non-matching responses")
   186  
   187  	// no endorsement
   188  	responses = []*pb.ProposalResponse{&pb.ProposalResponse{
   189  		Payload: []byte("payload"),
   190  		Response: &pb.Response{
   191  			Status: int32(200),
   192  		},
   193  	}}
   194  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   195  	assert.Error(t, err, "Expected error with no endorsements")
   196  
   197  	// success
   198  	responses = []*pb.ProposalResponse{&pb.ProposalResponse{
   199  		Payload:     []byte("payload"),
   200  		Endorsement: &pb.Endorsement{},
   201  		Response: &pb.Response{
   202  			Status: int32(200),
   203  		},
   204  	}}
   205  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   206  	assert.NoError(t, err, "Unexpected error creating signed transaction")
   207  	t.Logf("error: [%s]", err)
   208  
   209  	//
   210  	//
   211  	// additional failure cases
   212  	prop = &pb.Proposal{}
   213  	responses = []*pb.ProposalResponse{}
   214  	// no proposal responses
   215  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   216  	assert.Error(t, err, "Expected error with no proposal responses")
   217  
   218  	// missing proposal header
   219  	responses = append(responses, &pb.ProposalResponse{})
   220  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   221  	assert.Error(t, err, "Expected error with no proposal header")
   222  
   223  	// bad proposal payload
   224  	prop.Payload = []byte("bad payload")
   225  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   226  	assert.Error(t, err, "Expected error with malformed proposal payload")
   227  
   228  	// bad payload header
   229  	prop.Header = []byte("bad header")
   230  	_, err = utils.CreateSignedTx(prop, signID, responses...)
   231  	assert.Error(t, err, "Expected error with malformed proposal header")
   232  
   233  }
   234  
   235  func TestCreateSignedEnvelope(t *testing.T) {
   236  	var env *cb.Envelope
   237  	channelID := "mychannelID"
   238  	msg := &cb.ConfigEnvelope{}
   239  
   240  	env, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID,
   241  		goodSigner, msg, int32(1), uint64(1))
   242  	assert.NoError(t, err, "Unexpected error creating signed envelope")
   243  	assert.NotNil(t, env, "Envelope should not be nil")
   244  	// mock sign returns the bytes to be signed
   245  	assert.Equal(t, env.Payload, env.Signature, "Unexpected signature returned")
   246  	payload := &cb.Payload{}
   247  	err = proto.Unmarshal(env.Payload, payload)
   248  	assert.NoError(t, err, "Failed to unmarshal payload")
   249  	data := &cb.ConfigEnvelope{}
   250  	err = proto.Unmarshal(payload.Data, data)
   251  	assert.NoError(t, err, "Expected payload data to be a config envelope")
   252  	assert.Equal(t, msg, data, "Payload data does not match expected value")
   253  
   254  	_, err = utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID,
   255  		badSigner, &cb.ConfigEnvelope{}, int32(1), uint64(1))
   256  	assert.Error(t, err, "Expected sign error")
   257  }
   258  
   259  func TestCreateSignedEnvelopeNilSigner(t *testing.T) {
   260  	var env *cb.Envelope
   261  	channelID := "mychannelID"
   262  	msg := &cb.ConfigEnvelope{}
   263  
   264  	env, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID,
   265  		nil, msg, int32(1), uint64(1))
   266  	assert.NoError(t, err, "Unexpected error creating signed envelope")
   267  	assert.NotNil(t, env, "Envelope should not be nil")
   268  	assert.Empty(t, env.Signature, "Signature should have been empty")
   269  	payload := &cb.Payload{}
   270  	err = proto.Unmarshal(env.Payload, payload)
   271  	assert.NoError(t, err, "Failed to unmarshal payload")
   272  	data := &cb.ConfigEnvelope{}
   273  	err = proto.Unmarshal(payload.Data, data)
   274  	assert.NoError(t, err, "Expected payload data to be a config envelope")
   275  	assert.Equal(t, msg, data, "Payload data does not match expected value")
   276  }
   277  
   278  func TestGetSignedProposal(t *testing.T) {
   279  	var signedProp *pb.SignedProposal
   280  	var err error
   281  
   282  	signID, err := mockmsp.NewNoopMsp().GetDefaultSigningIdentity()
   283  	assert.NoError(t, err, "Unexpected error getting signing identity")
   284  
   285  	prop := &pb.Proposal{}
   286  	propBytes, _ := proto.Marshal(prop)
   287  	signedProp, err = utils.GetSignedProposal(prop, signID)
   288  	assert.NoError(t, err, "Unexpected error getting signed proposal")
   289  	assert.Equal(t, propBytes, signedProp.ProposalBytes,
   290  		"Proposal bytes did not match expected value")
   291  	assert.Equal(t, []byte("signature"), signedProp.Signature,
   292  		"Signature did not match expected value")
   293  
   294  	_, err = utils.GetSignedProposal(nil, signID)
   295  	assert.Error(t, err, "Expected error with nil proposal")
   296  	_, err = utils.GetSignedProposal(prop, nil)
   297  	assert.Error(t, err, "Expected error with nil signing identity")
   298  
   299  }
   300  
   301  func TestGetSignedEvent(t *testing.T) {
   302  	var signedEvt *pb.SignedEvent
   303  	var err error
   304  
   305  	signID, err := mockmsp.NewNoopMsp().GetDefaultSigningIdentity()
   306  	assert.NoError(t, err, "Unexpected error getting signing identity")
   307  
   308  	evt := &pb.Event{}
   309  	evtBytes, _ := proto.Marshal(evt)
   310  	signedEvt, err = utils.GetSignedEvent(evt, signID)
   311  	assert.NoError(t, err, "Unexpected error getting signed event")
   312  	assert.Equal(t, evtBytes, signedEvt.EventBytes,
   313  		"Event bytes did not match expected value")
   314  	assert.Equal(t, []byte("signature"), signedEvt.Signature,
   315  		"Signature did not match expected value")
   316  
   317  	_, err = utils.GetSignedEvent(nil, signID)
   318  	assert.Error(t, err, "Expected error with nil event")
   319  	_, err = utils.GetSignedEvent(evt, nil)
   320  	assert.Error(t, err, "Expected error with nil signing identity")
   321  
   322  }
   323  
   324  func TestMockSignedEndorserProposalOrPanic(t *testing.T) {
   325  	var prop *pb.Proposal
   326  	var signedProp *pb.SignedProposal
   327  
   328  	ccProposal := &pb.ChaincodeProposalPayload{}
   329  	cis := &pb.ChaincodeInvocationSpec{}
   330  	chainID := "testchainid"
   331  	sig := []byte("signature")
   332  	creator := []byte("creator")
   333  	cs := &pb.ChaincodeSpec{
   334  		ChaincodeId: &pb.ChaincodeID{
   335  			Name: "mychaincode",
   336  		},
   337  	}
   338  
   339  	signedProp, prop = utils.MockSignedEndorserProposalOrPanic(chainID, cs,
   340  		creator, sig)
   341  	assert.Equal(t, sig, signedProp.Signature,
   342  		"Signature did not match expected result")
   343  	propBytes, _ := proto.Marshal(prop)
   344  	assert.Equal(t, propBytes, signedProp.ProposalBytes,
   345  		"Proposal bytes do not match expected value")
   346  	err := proto.Unmarshal(prop.Payload, ccProposal)
   347  	assert.NoError(t, err, "Expected ChaincodeProposalPayload")
   348  	err = proto.Unmarshal(ccProposal.Input, cis)
   349  	assert.NoError(t, err, "Expected ChaincodeInvocationSpec")
   350  	assert.Equal(t, cs.ChaincodeId.Name, cis.ChaincodeSpec.ChaincodeId.Name,
   351  		"Chaincode name did not match expected value")
   352  }
   353  
   354  func TestMockSignedEndorserProposal2OrPanic(t *testing.T) {
   355  	var prop *pb.Proposal
   356  	var signedProp *pb.SignedProposal
   357  
   358  	ccProposal := &pb.ChaincodeProposalPayload{}
   359  	cis := &pb.ChaincodeInvocationSpec{}
   360  	chainID := "testchainid"
   361  	sig := []byte("signature")
   362  	signID, err := mockmsp.NewNoopMsp().GetDefaultSigningIdentity()
   363  	assert.NoError(t, err, "Unexpected error getting signing identity")
   364  
   365  	signedProp, prop = utils.MockSignedEndorserProposal2OrPanic(chainID,
   366  		&pb.ChaincodeSpec{}, signID)
   367  	assert.Equal(t, sig, signedProp.Signature,
   368  		"Signature did not match expected result")
   369  	propBytes, _ := proto.Marshal(prop)
   370  	assert.Equal(t, propBytes, signedProp.ProposalBytes,
   371  		"Proposal bytes do not match expected value")
   372  	err = proto.Unmarshal(prop.Payload, ccProposal)
   373  	assert.NoError(t, err, "Expected ChaincodeProposalPayload")
   374  	err = proto.Unmarshal(ccProposal.Input, cis)
   375  	assert.NoError(t, err, "Expected ChaincodeInvocationSpec")
   376  }
   377  
   378  func TestGetBytesProposalPayloadForTx(t *testing.T) {
   379  	input := &pb.ChaincodeProposalPayload{
   380  		Input:        []byte("input"),
   381  		TransientMap: make(map[string][]byte),
   382  	}
   383  	expected, _ := proto.Marshal(&pb.ChaincodeProposalPayload{
   384  		Input: []byte("input"),
   385  	})
   386  
   387  	result, err := utils.GetBytesProposalPayloadForTx(input, []byte{})
   388  	assert.NoError(t, err, "Unexpected error getting proposal payload")
   389  	assert.Equal(t, expected, result, "Payload does not match expected value")
   390  
   391  	_, err = utils.GetBytesProposalPayloadForTx(nil, []byte{})
   392  	assert.Error(t, err, "Expected error with nil proposal payload")
   393  }
   394  
   395  func TestGetProposalHash2(t *testing.T) {
   396  	expectedHashHex := "7b622ef4e1ab9b7093ec3bbfbca17d5d6f14a437914a6839319978a7034f7960"
   397  	expectedHash, _ := hex.DecodeString(expectedHashHex)
   398  	hdr := &cb.Header{
   399  		ChannelHeader:   []byte("chdr"),
   400  		SignatureHeader: []byte("shdr"),
   401  	}
   402  	propHash, err := utils.GetProposalHash2(hdr, []byte("ccproppayload"))
   403  	assert.NoError(t, err, "Unexpected error getting hash2 for proposal")
   404  	t.Logf("%x", propHash)
   405  	assert.Equal(t, expectedHash, propHash,
   406  		"Proposal hash did not match expected hash")
   407  
   408  	propHash, err = utils.GetProposalHash2(&cb.Header{},
   409  		[]byte("ccproppayload"))
   410  	assert.Error(t, err, "Expected error with nil arguments")
   411  }
   412  
   413  func TestGetProposalHash1(t *testing.T) {
   414  	expectedHashHex := "d4c1e3cac2105da5fddc2cfe776d6ec28e4598cf1e6fa51122c7f70d8076437b"
   415  	expectedHash, _ := hex.DecodeString(expectedHashHex)
   416  	hdr := &cb.Header{
   417  		ChannelHeader:   []byte("chdr"),
   418  		SignatureHeader: []byte("shdr"),
   419  	}
   420  
   421  	ccProposal, _ := proto.Marshal(&pb.ChaincodeProposalPayload{})
   422  
   423  	propHash, err := utils.GetProposalHash1(hdr, ccProposal, []byte{})
   424  	assert.NoError(t, err, "Unexpected error getting hash for proposal")
   425  	t.Logf("%x", propHash)
   426  	assert.Equal(t, expectedHash, propHash,
   427  		"Proposal hash did not match expected hash")
   428  
   429  	propHash, err = utils.GetProposalHash1(hdr,
   430  		[]byte("ccproppayload"), []byte{})
   431  	assert.Error(t, err,
   432  		"Expected error with malformed chaincode proposal payload")
   433  
   434  	propHash, err = utils.GetProposalHash1(&cb.Header{},
   435  		[]byte("ccproppayload"), []byte{})
   436  	assert.Error(t, err, "Expected error with nil arguments")
   437  }
   438  
   439  func TestCreateProposalResponseFailure(t *testing.T) {
   440  	// create a proposal from a ChaincodeInvocationSpec
   441  	prop, _, err := utils.CreateChaincodeProposal(cb.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), createCIS(), signerSerialized)
   442  	if err != nil {
   443  		t.Fatalf("Could not create chaincode proposal, err %s\n", err)
   444  		return
   445  	}
   446  
   447  	response := &pb.Response{Status: 502, Payload: []byte("Invalid function name")}
   448  	result := []byte("res")
   449  	ccid := &pb.ChaincodeID{Name: "foo", Version: "v1"}
   450  
   451  	prespFailure, err := utils.CreateProposalResponseFailure(prop.Header, prop.Payload, response, result, nil, ccid, nil)
   452  	if err != nil {
   453  		t.Fatalf("Could not create proposal response failure, err %s\n", err)
   454  		return
   455  	}
   456  
   457  	assert.Equal(t, int32(500), prespFailure.Response.Status)
   458  	// drilldown into the response to find the chaincode response
   459  	pRespPayload, err := utils.GetProposalResponsePayload(prespFailure.Payload)
   460  	assert.NoError(t, err, "Error while unmarshaling proposal response payload: %s", err)
   461  	ca, err := utils.GetChaincodeAction(pRespPayload.Extension)
   462  	assert.NoError(t, err, "Error while unmarshaling chaincode action: %s", err)
   463  
   464  	assert.Equal(t, int32(502), ca.Response.Status)
   465  	assert.Equal(t, "Invalid function name", string(ca.Response.Payload))
   466  }
   467  
   468  // mock
   469  var badSigner = &mockLocalSigner{
   470  	returnError: true,
   471  }
   472  
   473  var goodSigner = &mockLocalSigner{
   474  	returnError: false,
   475  }
   476  
   477  type mockLocalSigner struct {
   478  	returnError bool
   479  }
   480  
   481  func (m *mockLocalSigner) NewSignatureHeader() (*cb.SignatureHeader, error) {
   482  	if m.returnError {
   483  		return nil, errors.New("signature header error")
   484  	}
   485  	return &cb.SignatureHeader{}, nil
   486  }
   487  
   488  func (m *mockLocalSigner) Sign(message []byte) ([]byte, error) {
   489  	if m.returnError {
   490  		return nil, errors.New("sign error")
   491  	}
   492  	return message, nil
   493  }