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 }