588 lines
20 KiB
Go
588 lines
20 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package protoutil_test
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
cb "github.com/hyperledger/fabric-protos-go/common"
|
|
pb "github.com/hyperledger/fabric-protos-go/peer"
|
|
|
|
"github.com/hyperledger/fabric/protoutil"
|
|
"github.com/hyperledger/fabric/protoutil/fakes"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestGetPayloads(t *testing.T) {
|
|
var txAction *pb.TransactionAction
|
|
var err error
|
|
|
|
// good
|
|
ccActionBytes, _ := proto.Marshal(&pb.ChaincodeAction{
|
|
Results: []byte("results"),
|
|
})
|
|
proposalResponsePayload := &pb.ProposalResponsePayload{
|
|
Extension: ccActionBytes,
|
|
}
|
|
proposalResponseBytes, err := proto.Marshal(proposalResponsePayload)
|
|
require.NoError(t, err)
|
|
ccActionPayload := &pb.ChaincodeActionPayload{
|
|
Action: &pb.ChaincodeEndorsedAction{
|
|
ProposalResponsePayload: proposalResponseBytes,
|
|
},
|
|
}
|
|
ccActionPayloadBytes, _ := proto.Marshal(ccActionPayload)
|
|
txAction = &pb.TransactionAction{
|
|
Payload: ccActionPayloadBytes,
|
|
}
|
|
_, _, err = protoutil.GetPayloads(txAction)
|
|
require.NoError(t, err, "Unexpected error getting payload bytes")
|
|
t.Logf("error1 [%s]", err)
|
|
|
|
// nil proposal response extension
|
|
proposalResponseBytes, err = proto.Marshal(&pb.ProposalResponsePayload{
|
|
Extension: nil,
|
|
})
|
|
require.NoError(t, err)
|
|
ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
|
|
Action: &pb.ChaincodeEndorsedAction{
|
|
ProposalResponsePayload: proposalResponseBytes,
|
|
},
|
|
})
|
|
txAction = &pb.TransactionAction{
|
|
Payload: ccActionPayloadBytes,
|
|
}
|
|
_, _, err = protoutil.GetPayloads(txAction)
|
|
require.Error(t, err, "Expected error with nil proposal response extension")
|
|
t.Logf("error2 [%s]", err)
|
|
|
|
// malformed proposal response payload
|
|
ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
|
|
Action: &pb.ChaincodeEndorsedAction{
|
|
ProposalResponsePayload: []byte("bad payload"),
|
|
},
|
|
})
|
|
txAction = &pb.TransactionAction{
|
|
Payload: ccActionPayloadBytes,
|
|
}
|
|
_, _, err = protoutil.GetPayloads(txAction)
|
|
require.Error(t, err, "Expected error with malformed proposal response payload")
|
|
t.Logf("error3 [%s]", err)
|
|
|
|
// malformed proposal response payload extension
|
|
proposalResponseBytes, _ = proto.Marshal(&pb.ProposalResponsePayload{
|
|
Extension: []byte("bad extension"),
|
|
})
|
|
ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
|
|
Action: &pb.ChaincodeEndorsedAction{
|
|
ProposalResponsePayload: proposalResponseBytes,
|
|
},
|
|
})
|
|
txAction = &pb.TransactionAction{
|
|
Payload: ccActionPayloadBytes,
|
|
}
|
|
_, _, err = protoutil.GetPayloads(txAction)
|
|
require.Error(t, err, "Expected error with malformed proposal response extension")
|
|
t.Logf("error4 [%s]", err)
|
|
|
|
// nil proposal response payload extension
|
|
proposalResponseBytes, _ = proto.Marshal(&pb.ProposalResponsePayload{
|
|
ProposalHash: []byte("hash"),
|
|
})
|
|
ccActionPayloadBytes, _ = proto.Marshal(&pb.ChaincodeActionPayload{
|
|
Action: &pb.ChaincodeEndorsedAction{
|
|
ProposalResponsePayload: proposalResponseBytes,
|
|
},
|
|
})
|
|
txAction = &pb.TransactionAction{
|
|
Payload: ccActionPayloadBytes,
|
|
}
|
|
_, _, err = protoutil.GetPayloads(txAction)
|
|
require.Error(t, err, "Expected error with nil proposal response extension")
|
|
t.Logf("error5 [%s]", err)
|
|
|
|
// malformed transaction action payload
|
|
txAction = &pb.TransactionAction{
|
|
Payload: []byte("bad payload"),
|
|
}
|
|
_, _, err = protoutil.GetPayloads(txAction)
|
|
require.Error(t, err, "Expected error with malformed transaction action payload")
|
|
t.Logf("error6 [%s]", err)
|
|
}
|
|
|
|
func TestDeduplicateEndorsements(t *testing.T) {
|
|
signID := &fakes.SignerSerializer{}
|
|
signID.SerializeReturns([]byte("signer"), nil)
|
|
signerBytes, err := signID.Serialize()
|
|
require.NoError(t, err, "Unexpected error serializing signing identity")
|
|
|
|
proposal := &pb.Proposal{
|
|
Header: protoutil.MarshalOrPanic(&cb.Header{
|
|
ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
|
|
Extension: protoutil.MarshalOrPanic(&pb.ChaincodeHeaderExtension{}),
|
|
}),
|
|
SignatureHeader: protoutil.MarshalOrPanic(&cb.SignatureHeader{
|
|
Creator: signerBytes,
|
|
}),
|
|
}),
|
|
}
|
|
responses := []*pb.ProposalResponse{
|
|
{Payload: []byte("payload"), Endorsement: &pb.Endorsement{Endorser: []byte{5, 4, 3}}, Response: &pb.Response{Status: int32(200)}},
|
|
{Payload: []byte("payload"), Endorsement: &pb.Endorsement{Endorser: []byte{5, 4, 3}}, Response: &pb.Response{Status: int32(200)}},
|
|
}
|
|
|
|
transaction, err := protoutil.CreateSignedTx(proposal, signID, responses...)
|
|
require.NoError(t, err)
|
|
require.True(t, proto.Equal(transaction, transaction), "got: %#v, want: %#v", transaction, transaction)
|
|
|
|
pl := protoutil.UnmarshalPayloadOrPanic(transaction.Payload)
|
|
tx, err := protoutil.UnmarshalTransaction(pl.Data)
|
|
require.NoError(t, err)
|
|
ccap, err := protoutil.UnmarshalChaincodeActionPayload(tx.Actions[0].Payload)
|
|
require.NoError(t, err)
|
|
require.Len(t, ccap.Action.Endorsements, 1)
|
|
require.Equal(t, []byte{5, 4, 3}, ccap.Action.Endorsements[0].Endorser)
|
|
}
|
|
|
|
func TestCreateSignedTx(t *testing.T) {
|
|
var err error
|
|
prop := &pb.Proposal{}
|
|
|
|
signID := &fakes.SignerSerializer{}
|
|
signID.SerializeReturns([]byte("signer"), nil)
|
|
signerBytes, err := signID.Serialize()
|
|
require.NoError(t, err, "Unexpected error serializing signing identity")
|
|
|
|
ccHeaderExtensionBytes := protoutil.MarshalOrPanic(&pb.ChaincodeHeaderExtension{})
|
|
chdrBytes := protoutil.MarshalOrPanic(&cb.ChannelHeader{
|
|
Extension: ccHeaderExtensionBytes,
|
|
})
|
|
shdrBytes := protoutil.MarshalOrPanic(&cb.SignatureHeader{
|
|
Creator: signerBytes,
|
|
})
|
|
responses := []*pb.ProposalResponse{{}}
|
|
|
|
// malformed signature header
|
|
headerBytes := protoutil.MarshalOrPanic(&cb.Header{
|
|
SignatureHeader: []byte("bad signature header"),
|
|
})
|
|
prop.Header = headerBytes
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
require.Error(t, err, "Expected error with malformed signature header")
|
|
|
|
// set up the header bytes for the remaining tests
|
|
headerBytes, _ = proto.Marshal(&cb.Header{
|
|
ChannelHeader: chdrBytes,
|
|
SignatureHeader: shdrBytes,
|
|
})
|
|
prop.Header = headerBytes
|
|
|
|
nonMatchingTests := []struct {
|
|
responses []*pb.ProposalResponse
|
|
expectedError string
|
|
}{
|
|
// good response followed by bad response
|
|
{
|
|
[]*pb.ProposalResponse{
|
|
{Payload: []byte("payload"), Response: &pb.Response{Status: int32(200)}},
|
|
{Payload: []byte{}, Response: &pb.Response{Status: int32(500), Message: "failed to endorse"}},
|
|
},
|
|
"proposal response was not successful, error code 500, msg failed to endorse",
|
|
},
|
|
// bad response followed by good response
|
|
{
|
|
[]*pb.ProposalResponse{
|
|
{Payload: []byte{}, Response: &pb.Response{Status: int32(500), Message: "failed to endorse"}},
|
|
{Payload: []byte("payload"), Response: &pb.Response{Status: int32(200)}},
|
|
},
|
|
"proposal response was not successful, error code 500, msg failed to endorse",
|
|
},
|
|
}
|
|
for i, nonMatchingTest := range nonMatchingTests {
|
|
_, err = protoutil.CreateSignedTx(prop, signID, nonMatchingTest.responses...)
|
|
require.EqualErrorf(t, err, nonMatchingTest.expectedError, "Expected non-matching response error '%v' for test %d", nonMatchingTest.expectedError, i)
|
|
}
|
|
|
|
// good responses, but different payloads
|
|
responses = []*pb.ProposalResponse{
|
|
{Payload: []byte("payload"), Response: &pb.Response{Status: int32(200)}},
|
|
{Payload: []byte("payload2"), Response: &pb.Response{Status: int32(200)}},
|
|
}
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
if err == nil || strings.HasPrefix(err.Error(), "ProposalResponsePayloads do not match (base64):") == false {
|
|
require.FailNow(t, "Error is expected when response payloads do not match")
|
|
}
|
|
|
|
// no endorsement
|
|
responses = []*pb.ProposalResponse{{
|
|
Payload: []byte("payload"),
|
|
Response: &pb.Response{
|
|
Status: int32(200),
|
|
},
|
|
}}
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
require.Error(t, err, "Expected error with no endorsements")
|
|
|
|
// success
|
|
responses = []*pb.ProposalResponse{{
|
|
Payload: []byte("payload"),
|
|
Endorsement: &pb.Endorsement{},
|
|
Response: &pb.Response{
|
|
Status: int32(200),
|
|
},
|
|
}}
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
require.NoError(t, err, "Unexpected error creating signed transaction")
|
|
t.Logf("error: [%s]", err)
|
|
|
|
//
|
|
//
|
|
// additional failure cases
|
|
prop = &pb.Proposal{}
|
|
responses = []*pb.ProposalResponse{}
|
|
// no proposal responses
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
require.Error(t, err, "Expected error with no proposal responses")
|
|
|
|
// missing proposal header
|
|
responses = append(responses, &pb.ProposalResponse{})
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
require.Error(t, err, "Expected error with no proposal header")
|
|
|
|
// bad proposal payload
|
|
prop.Payload = []byte("bad payload")
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
require.Error(t, err, "Expected error with malformed proposal payload")
|
|
|
|
// bad payload header
|
|
prop.Header = []byte("bad header")
|
|
_, err = protoutil.CreateSignedTx(prop, signID, responses...)
|
|
require.Error(t, err, "Expected error with malformed proposal header")
|
|
}
|
|
|
|
func TestCreateSignedTxNoSigner(t *testing.T) {
|
|
_, err := protoutil.CreateSignedTx(nil, nil, &pb.ProposalResponse{})
|
|
require.ErrorContains(t, err, "signer is required when creating a signed transaction")
|
|
}
|
|
|
|
func TestCreateSignedTxStatus(t *testing.T) {
|
|
serializedExtension, err := proto.Marshal(&pb.ChaincodeHeaderExtension{})
|
|
require.NoError(t, err)
|
|
serializedChannelHeader, err := proto.Marshal(&cb.ChannelHeader{
|
|
Extension: serializedExtension,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
signingID := &fakes.SignerSerializer{}
|
|
signingID.SerializeReturns([]byte("signer"), nil)
|
|
serializedSigningID, err := signingID.Serialize()
|
|
require.NoError(t, err)
|
|
serializedSignatureHeader, err := proto.Marshal(&cb.SignatureHeader{
|
|
Creator: serializedSigningID,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
header := &cb.Header{
|
|
ChannelHeader: serializedChannelHeader,
|
|
SignatureHeader: serializedSignatureHeader,
|
|
}
|
|
|
|
serializedHeader, err := proto.Marshal(header)
|
|
require.NoError(t, err)
|
|
|
|
proposal := &pb.Proposal{
|
|
Header: serializedHeader,
|
|
}
|
|
|
|
tests := []struct {
|
|
status int32
|
|
expectedErr string
|
|
}{
|
|
{status: 0, expectedErr: "proposal response was not successful, error code 0, msg response-message"},
|
|
{status: 199, expectedErr: "proposal response was not successful, error code 199, msg response-message"},
|
|
{status: 200, expectedErr: ""},
|
|
{status: 201, expectedErr: ""},
|
|
{status: 399, expectedErr: ""},
|
|
{status: 400, expectedErr: "proposal response was not successful, error code 400, msg response-message"},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(strconv.Itoa(int(tc.status)), func(t *testing.T) {
|
|
response := &pb.ProposalResponse{
|
|
Payload: []byte("payload"),
|
|
Endorsement: &pb.Endorsement{},
|
|
Response: &pb.Response{
|
|
Status: tc.status,
|
|
Message: "response-message",
|
|
},
|
|
}
|
|
|
|
_, err := protoutil.CreateSignedTx(proposal, signingID, response)
|
|
if tc.expectedErr == "" {
|
|
require.NoError(t, err)
|
|
} else {
|
|
require.EqualError(t, err, tc.expectedErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCreateSignedEnvelope(t *testing.T) {
|
|
var env *cb.Envelope
|
|
channelID := "mychannelID"
|
|
msg := &cb.ConfigEnvelope{}
|
|
|
|
id := &fakes.SignerSerializer{}
|
|
id.SignReturnsOnCall(0, []byte("goodsig"), nil)
|
|
id.SignReturnsOnCall(1, nil, errors.New("bad signature"))
|
|
env, err := protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID,
|
|
id, msg, int32(1), uint64(1))
|
|
require.NoError(t, err, "Unexpected error creating signed envelope")
|
|
require.NotNil(t, env, "Envelope should not be nil")
|
|
// mock sign returns the bytes to be signed
|
|
require.Equal(t, []byte("goodsig"), env.Signature, "Unexpected signature returned")
|
|
payload := &cb.Payload{}
|
|
err = proto.Unmarshal(env.Payload, payload)
|
|
require.NoError(t, err, "Failed to unmarshal payload")
|
|
data := &cb.ConfigEnvelope{}
|
|
err = proto.Unmarshal(payload.Data, data)
|
|
require.NoError(t, err, "Expected payload data to be a config envelope")
|
|
require.Equal(t, msg, data, "Payload data does not match expected value")
|
|
|
|
_, err = protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID,
|
|
id, &cb.ConfigEnvelope{}, int32(1), uint64(1))
|
|
require.Error(t, err, "Expected sign error")
|
|
}
|
|
|
|
func TestCreateSignedEnvelopeNilSigner(t *testing.T) {
|
|
var env *cb.Envelope
|
|
channelID := "mychannelID"
|
|
msg := &cb.ConfigEnvelope{}
|
|
|
|
env, err := protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID,
|
|
nil, msg, int32(1), uint64(1))
|
|
require.NoError(t, err, "Unexpected error creating signed envelope")
|
|
require.NotNil(t, env, "Envelope should not be nil")
|
|
require.Empty(t, env.Signature, "Signature should have been empty")
|
|
payload := &cb.Payload{}
|
|
err = proto.Unmarshal(env.Payload, payload)
|
|
require.NoError(t, err, "Failed to unmarshal payload")
|
|
data := &cb.ConfigEnvelope{}
|
|
err = proto.Unmarshal(payload.Data, data)
|
|
require.NoError(t, err, "Expected payload data to be a config envelope")
|
|
require.Equal(t, msg, data, "Payload data does not match expected value")
|
|
}
|
|
|
|
func TestGetSignedProposal(t *testing.T) {
|
|
var signedProp *pb.SignedProposal
|
|
var err error
|
|
|
|
sig := []byte("signature")
|
|
|
|
signID := &fakes.SignerSerializer{}
|
|
signID.SignReturns(sig, nil)
|
|
|
|
prop := &pb.Proposal{}
|
|
propBytes, _ := proto.Marshal(prop)
|
|
signedProp, err = protoutil.GetSignedProposal(prop, signID)
|
|
require.NoError(t, err, "Unexpected error getting signed proposal")
|
|
require.Equal(t, propBytes, signedProp.ProposalBytes,
|
|
"Proposal bytes did not match expected value")
|
|
require.Equal(t, sig, signedProp.Signature,
|
|
"Signature did not match expected value")
|
|
|
|
_, err = protoutil.GetSignedProposal(nil, signID)
|
|
require.Error(t, err, "Expected error with nil proposal")
|
|
_, err = protoutil.GetSignedProposal(prop, nil)
|
|
require.Error(t, err, "Expected error with nil signing identity")
|
|
}
|
|
|
|
func TestMockSignedEndorserProposalOrPanic(t *testing.T) {
|
|
var prop *pb.Proposal
|
|
var signedProp *pb.SignedProposal
|
|
|
|
ccProposal := &pb.ChaincodeProposalPayload{}
|
|
cis := &pb.ChaincodeInvocationSpec{}
|
|
chainID := "testchannelid"
|
|
sig := []byte("signature")
|
|
creator := []byte("creator")
|
|
cs := &pb.ChaincodeSpec{
|
|
ChaincodeId: &pb.ChaincodeID{
|
|
Name: "mychaincode",
|
|
},
|
|
}
|
|
|
|
signedProp, prop = protoutil.MockSignedEndorserProposalOrPanic(chainID, cs,
|
|
creator, sig)
|
|
require.Equal(t, sig, signedProp.Signature,
|
|
"Signature did not match expected result")
|
|
propBytes, _ := proto.Marshal(prop)
|
|
require.Equal(t, propBytes, signedProp.ProposalBytes,
|
|
"Proposal bytes do not match expected value")
|
|
err := proto.Unmarshal(prop.Payload, ccProposal)
|
|
require.NoError(t, err, "Expected ChaincodeProposalPayload")
|
|
err = proto.Unmarshal(ccProposal.Input, cis)
|
|
require.NoError(t, err, "Expected ChaincodeInvocationSpec")
|
|
require.Equal(t, cs.ChaincodeId.Name, cis.ChaincodeSpec.ChaincodeId.Name,
|
|
"Chaincode name did not match expected value")
|
|
}
|
|
|
|
func TestMockSignedEndorserProposal2OrPanic(t *testing.T) {
|
|
var prop *pb.Proposal
|
|
var signedProp *pb.SignedProposal
|
|
|
|
ccProposal := &pb.ChaincodeProposalPayload{}
|
|
cis := &pb.ChaincodeInvocationSpec{}
|
|
chainID := "testchannelid"
|
|
sig := []byte("signature")
|
|
signID := &fakes.SignerSerializer{}
|
|
signID.SignReturns(sig, nil)
|
|
|
|
signedProp, prop = protoutil.MockSignedEndorserProposal2OrPanic(chainID,
|
|
&pb.ChaincodeSpec{}, signID)
|
|
require.Equal(t, sig, signedProp.Signature,
|
|
"Signature did not match expected result")
|
|
propBytes, _ := proto.Marshal(prop)
|
|
require.Equal(t, propBytes, signedProp.ProposalBytes,
|
|
"Proposal bytes do not match expected value")
|
|
err := proto.Unmarshal(prop.Payload, ccProposal)
|
|
require.NoError(t, err, "Expected ChaincodeProposalPayload")
|
|
err = proto.Unmarshal(ccProposal.Input, cis)
|
|
require.NoError(t, err, "Expected ChaincodeInvocationSpec")
|
|
}
|
|
|
|
func TestGetBytesProposalPayloadForTx(t *testing.T) {
|
|
input := &pb.ChaincodeProposalPayload{
|
|
Input: []byte("input"),
|
|
TransientMap: make(map[string][]byte),
|
|
}
|
|
expected, _ := proto.Marshal(&pb.ChaincodeProposalPayload{
|
|
Input: []byte("input"),
|
|
})
|
|
|
|
result, err := protoutil.GetBytesProposalPayloadForTx(input)
|
|
require.NoError(t, err, "Unexpected error getting proposal payload")
|
|
require.Equal(t, expected, result, "Payload does not match expected value")
|
|
|
|
_, err = protoutil.GetBytesProposalPayloadForTx(nil)
|
|
require.Error(t, err, "Expected error with nil proposal payload")
|
|
}
|
|
|
|
func TestGetProposalHash2(t *testing.T) {
|
|
expectedHashHex := "7b622ef4e1ab9b7093ec3bbfbca17d5d6f14a437914a6839319978a7034f7960"
|
|
expectedHash, _ := hex.DecodeString(expectedHashHex)
|
|
hdr := &cb.Header{
|
|
ChannelHeader: []byte("chdr"),
|
|
SignatureHeader: []byte("shdr"),
|
|
}
|
|
propHash, err := protoutil.GetProposalHash2(hdr, []byte("ccproppayload"))
|
|
require.NoError(t, err, "Unexpected error getting hash2 for proposal")
|
|
require.Equal(t, expectedHash, propHash, "Proposal hash did not match expected hash")
|
|
|
|
_, err = protoutil.GetProposalHash2(&cb.Header{}, []byte("ccproppayload"))
|
|
require.Error(t, err, "Expected error with nil arguments")
|
|
}
|
|
|
|
func TestGetProposalHash1(t *testing.T) {
|
|
expectedHashHex := "d4c1e3cac2105da5fddc2cfe776d6ec28e4598cf1e6fa51122c7f70d8076437b"
|
|
expectedHash, _ := hex.DecodeString(expectedHashHex)
|
|
hdr := &cb.Header{
|
|
ChannelHeader: []byte("chdr"),
|
|
SignatureHeader: []byte("shdr"),
|
|
}
|
|
|
|
ccProposal, _ := proto.Marshal(&pb.ChaincodeProposalPayload{})
|
|
|
|
propHash, err := protoutil.GetProposalHash1(hdr, ccProposal)
|
|
require.NoError(t, err, "Unexpected error getting hash for proposal")
|
|
require.Equal(t, expectedHash, propHash, "Proposal hash did not match expected hash")
|
|
|
|
_, err = protoutil.GetProposalHash1(hdr, []byte("ccproppayload"))
|
|
require.Error(t, err, "Expected error with malformed chaincode proposal payload")
|
|
|
|
_, err = protoutil.GetProposalHash1(&cb.Header{}, []byte("ccproppayload"))
|
|
require.Error(t, err, "Expected error with nil arguments")
|
|
}
|
|
|
|
func TestCreateProposalResponseFailure(t *testing.T) {
|
|
// create a proposal from a ChaincodeInvocationSpec
|
|
prop, _, err := protoutil.CreateChaincodeProposal(cb.HeaderType_ENDORSER_TRANSACTION, testChannelID, createCIS(), signerSerialized)
|
|
if err != nil {
|
|
t.Fatalf("Could not create chaincode proposal, err %s\n", err)
|
|
return
|
|
}
|
|
|
|
response := &pb.Response{Status: 502, Payload: []byte("Invalid function name")}
|
|
result := []byte("res")
|
|
|
|
prespFailure, err := protoutil.CreateProposalResponseFailure(prop.Header, prop.Payload, response, result, nil, "foo")
|
|
if err != nil {
|
|
t.Fatalf("Could not create proposal response failure, err %s\n", err)
|
|
return
|
|
}
|
|
|
|
require.Equal(t, int32(502), prespFailure.Response.Status)
|
|
// drilldown into the response to find the chaincode response
|
|
pRespPayload, err := protoutil.UnmarshalProposalResponsePayload(prespFailure.Payload)
|
|
require.NoError(t, err, "Error while unmarshalling proposal response payload: %s", err)
|
|
ca, err := protoutil.UnmarshalChaincodeAction(pRespPayload.Extension)
|
|
require.NoError(t, err, "Error while unmarshalling chaincode action: %s", err)
|
|
|
|
require.Equal(t, int32(502), ca.Response.Status)
|
|
require.Equal(t, "Invalid function name", string(ca.Response.Payload))
|
|
}
|
|
|
|
func TestGetorComputeTxIDFromEnvelope(t *testing.T) {
|
|
t.Run("txID is present in the envelope", func(t *testing.T) {
|
|
txID := "709184f9d24f6ade8fcd4d6521a6eef295fef6c2e67216c58b68ac15e8946492"
|
|
envelopeBytes := createSampleTxEnvelopeBytes(txID)
|
|
actualTxID, err := protoutil.GetOrComputeTxIDFromEnvelope(envelopeBytes)
|
|
require.Nil(t, err)
|
|
require.Equal(t, "709184f9d24f6ade8fcd4d6521a6eef295fef6c2e67216c58b68ac15e8946492", actualTxID)
|
|
})
|
|
|
|
t.Run("txID is not present in the envelope", func(t *testing.T) {
|
|
txID := ""
|
|
envelopeBytes := createSampleTxEnvelopeBytes(txID)
|
|
actualTxID, err := protoutil.GetOrComputeTxIDFromEnvelope(envelopeBytes)
|
|
require.Nil(t, err)
|
|
require.Equal(t, "709184f9d24f6ade8fcd4d6521a6eef295fef6c2e67216c58b68ac15e8946492", actualTxID)
|
|
})
|
|
}
|
|
|
|
func createSampleTxEnvelopeBytes(txID string) []byte {
|
|
chdr := &cb.ChannelHeader{
|
|
TxId: "709184f9d24f6ade8fcd4d6521a6eef295fef6c2e67216c58b68ac15e8946492",
|
|
}
|
|
chdrBytes := protoutil.MarshalOrPanic(chdr)
|
|
|
|
shdr := &cb.SignatureHeader{
|
|
Nonce: []byte("nonce"),
|
|
Creator: []byte("creator"),
|
|
}
|
|
shdrBytes := protoutil.MarshalOrPanic(shdr)
|
|
|
|
hdr := &cb.Header{
|
|
ChannelHeader: chdrBytes,
|
|
SignatureHeader: shdrBytes,
|
|
}
|
|
|
|
payload := &cb.Payload{
|
|
Header: hdr,
|
|
}
|
|
payloadBytes := protoutil.MarshalOrPanic(payload)
|
|
|
|
envelope := &cb.Envelope{
|
|
Payload: payloadBytes,
|
|
}
|
|
return protoutil.MarshalOrPanic(envelope)
|
|
}
|