github.com/lzy4123/fabric@v2.1.1+incompatible/protoutil/proputils_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package protoutil_test 8 9 import ( 10 "bytes" 11 "crypto/sha256" 12 "encoding/hex" 13 "fmt" 14 "os" 15 "testing" 16 17 "github.com/golang/protobuf/proto" 18 "github.com/hyperledger/fabric-protos-go/common" 19 pb "github.com/hyperledger/fabric-protos-go/peer" 20 "github.com/hyperledger/fabric/bccsp/sw" 21 "github.com/hyperledger/fabric/msp" 22 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 23 msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" 24 "github.com/hyperledger/fabric/protoutil" 25 "github.com/stretchr/testify/assert" 26 ) 27 28 func createCIS() *pb.ChaincodeInvocationSpec { 29 return &pb.ChaincodeInvocationSpec{ 30 ChaincodeSpec: &pb.ChaincodeSpec{ 31 Type: pb.ChaincodeSpec_GOLANG, 32 ChaincodeId: &pb.ChaincodeID{Name: "chaincode_name"}, 33 Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("arg1"), []byte("arg2")}}}} 34 } 35 36 func TestGetChaincodeDeploymentSpec(t *testing.T) { 37 _, err := protoutil.UnmarshalChaincodeDeploymentSpec([]byte("bad spec")) 38 assert.Error(t, err, "Expected error with malformed spec") 39 40 cds, _ := proto.Marshal(&pb.ChaincodeDeploymentSpec{ 41 ChaincodeSpec: &pb.ChaincodeSpec{ 42 Type: pb.ChaincodeSpec_GOLANG, 43 }, 44 }) 45 _, err = protoutil.UnmarshalChaincodeDeploymentSpec(cds) 46 assert.NoError(t, err, "Unexpected error getting deployment spec") 47 } 48 49 func TestCDSProposals(t *testing.T) { 50 var prop *pb.Proposal 51 var err error 52 var txid string 53 creator := []byte("creator") 54 cds := &pb.ChaincodeDeploymentSpec{ 55 ChaincodeSpec: &pb.ChaincodeSpec{ 56 Type: pb.ChaincodeSpec_GOLANG, 57 }, 58 } 59 policy := []byte("policy") 60 escc := []byte("escc") 61 vscc := []byte("vscc") 62 chainID := "testchannelid" 63 64 // install 65 prop, txid, err = protoutil.CreateInstallProposalFromCDS(cds, creator) 66 assert.NotNil(t, prop, "Install proposal should not be nil") 67 assert.NoError(t, err, "Unexpected error creating install proposal") 68 assert.NotEqual(t, "", txid, "txid should not be empty") 69 70 // deploy 71 prop, txid, err = protoutil.CreateDeployProposalFromCDS(chainID, cds, creator, policy, escc, vscc, nil) 72 assert.NotNil(t, prop, "Deploy proposal should not be nil") 73 assert.NoError(t, err, "Unexpected error creating deploy proposal") 74 assert.NotEqual(t, "", txid, "txid should not be empty") 75 76 // upgrade 77 prop, txid, err = protoutil.CreateUpgradeProposalFromCDS(chainID, cds, creator, policy, escc, vscc, nil) 78 assert.NotNil(t, prop, "Upgrade proposal should not be nil") 79 assert.NoError(t, err, "Unexpected error creating upgrade proposal") 80 assert.NotEqual(t, "", txid, "txid should not be empty") 81 82 } 83 84 func TestProposal(t *testing.T) { 85 // create a proposal from a ChaincodeInvocationSpec 86 prop, _, err := protoutil.CreateChaincodeProposalWithTransient( 87 common.HeaderType_ENDORSER_TRANSACTION, 88 testChannelID, createCIS(), 89 []byte("creator"), 90 map[string][]byte{"certx": []byte("transient")}) 91 if err != nil { 92 t.Fatalf("Could not create chaincode proposal, err %s\n", err) 93 return 94 } 95 96 // serialize the proposal 97 pBytes, err := proto.Marshal(prop) 98 if err != nil { 99 t.Fatalf("Could not serialize the chaincode proposal, err %s\n", err) 100 return 101 } 102 103 // deserialize it and expect it to be the same 104 propBack, err := protoutil.UnmarshalProposal(pBytes) 105 if err != nil { 106 t.Fatalf("Could not deserialize the chaincode proposal, err %s\n", err) 107 return 108 } 109 if !proto.Equal(prop, propBack) { 110 t.Fatalf("Proposal and deserialized proposals don't match\n") 111 return 112 } 113 114 // get back the header 115 hdr, err := protoutil.UnmarshalHeader(prop.Header) 116 if err != nil { 117 t.Fatalf("Could not extract the header from the proposal, err %s\n", err) 118 } 119 120 hdrBytes, err := protoutil.GetBytesHeader(hdr) 121 if err != nil { 122 t.Fatalf("Could not marshal the header, err %s\n", err) 123 } 124 125 hdr, err = protoutil.UnmarshalHeader(hdrBytes) 126 if err != nil { 127 t.Fatalf("Could not unmarshal the header, err %s\n", err) 128 } 129 130 chdr, err := protoutil.UnmarshalChannelHeader(hdr.ChannelHeader) 131 if err != nil { 132 t.Fatalf("Could not unmarshal channel header, err %s", err) 133 } 134 135 shdr, err := protoutil.UnmarshalSignatureHeader(hdr.SignatureHeader) 136 if err != nil { 137 t.Fatalf("Could not unmarshal signature header, err %s", err) 138 } 139 140 _, err = protoutil.GetBytesSignatureHeader(shdr) 141 if err != nil { 142 t.Fatalf("Could not marshal signature header, err %s", err) 143 } 144 145 // sanity check on header 146 if chdr.Type != int32(common.HeaderType_ENDORSER_TRANSACTION) || 147 shdr.Nonce == nil || 148 string(shdr.Creator) != "creator" { 149 t.Fatalf("Invalid header after unmarshalling\n") 150 return 151 } 152 153 // get back the header extension 154 hdrExt, err := protoutil.UnmarshalChaincodeHeaderExtension(chdr.Extension) 155 if err != nil { 156 t.Fatalf("Could not extract the header extensions from the proposal, err %s\n", err) 157 return 158 } 159 160 // sanity check on header extension 161 if string(hdrExt.ChaincodeId.Name) != "chaincode_name" { 162 t.Fatalf("Invalid header extension after unmarshalling\n") 163 return 164 } 165 166 cpp, err := protoutil.UnmarshalChaincodeProposalPayload(prop.Payload) 167 if err != nil { 168 t.Fatalf("could not unmarshal proposal payload") 169 } 170 171 cis, err := protoutil.UnmarshalChaincodeInvocationSpec(cpp.Input) 172 if err != nil { 173 t.Fatalf("could not unmarshal proposal chaincode invocation spec") 174 } 175 176 // sanity check on cis 177 if cis.ChaincodeSpec.Type != pb.ChaincodeSpec_GOLANG || 178 cis.ChaincodeSpec.ChaincodeId.Name != "chaincode_name" || 179 len(cis.ChaincodeSpec.Input.Args) != 2 || 180 string(cis.ChaincodeSpec.Input.Args[0]) != "arg1" || 181 string(cis.ChaincodeSpec.Input.Args[1]) != "arg2" { 182 t.Fatalf("Invalid chaincode invocation spec after unmarshalling\n") 183 return 184 } 185 186 if string(shdr.Creator) != "creator" { 187 t.Fatalf("Failed checking Creator field. Invalid value, expectext 'creator', got [%s]", string(shdr.Creator)) 188 return 189 } 190 value, ok := cpp.TransientMap["certx"] 191 if !ok || string(value) != "transient" { 192 t.Fatalf("Failed checking Transient field. Invalid value, expectext 'transient', got [%s]", string(value)) 193 return 194 } 195 } 196 197 func TestProposalWithTxID(t *testing.T) { 198 // create a proposal from a ChaincodeInvocationSpec 199 prop, txid, err := protoutil.CreateChaincodeProposalWithTxIDAndTransient( 200 common.HeaderType_ENDORSER_TRANSACTION, 201 testChannelID, 202 createCIS(), 203 []byte("creator"), 204 "testtx", 205 map[string][]byte{"certx": []byte("transient")}, 206 ) 207 assert.Nil(t, err) 208 assert.NotNil(t, prop) 209 assert.Equal(t, txid, "testtx") 210 211 prop, txid, err = protoutil.CreateChaincodeProposalWithTxIDAndTransient( 212 common.HeaderType_ENDORSER_TRANSACTION, 213 testChannelID, 214 createCIS(), 215 []byte("creator"), 216 "", 217 map[string][]byte{"certx": []byte("transient")}, 218 ) 219 assert.Nil(t, err) 220 assert.NotNil(t, prop) 221 assert.NotEmpty(t, txid) 222 } 223 224 func TestProposalResponse(t *testing.T) { 225 events := &pb.ChaincodeEvent{ 226 ChaincodeId: "ccid", 227 EventName: "EventName", 228 Payload: []byte("EventPayload"), 229 TxId: "TxID"} 230 ccid := &pb.ChaincodeID{ 231 Name: "ccid", 232 Version: "v1", 233 } 234 235 pHashBytes := []byte("proposal_hash") 236 pResponse := &pb.Response{Status: 200} 237 results := []byte("results") 238 eventBytes, err := protoutil.GetBytesChaincodeEvent(events) 239 if err != nil { 240 t.Fatalf("Failure while marshalling the ProposalResponsePayload") 241 return 242 } 243 244 // get the bytes of the response 245 pResponseBytes, err := protoutil.GetBytesResponse(pResponse) 246 if err != nil { 247 t.Fatalf("Failure while marshalling the Response") 248 return 249 } 250 251 // get the response from bytes 252 _, err = protoutil.UnmarshalResponse(pResponseBytes) 253 if err != nil { 254 t.Fatalf("Failure while unmarshalling the Response") 255 return 256 } 257 258 // get the bytes of the ProposalResponsePayload 259 prpBytes, err := protoutil.GetBytesProposalResponsePayload(pHashBytes, pResponse, results, eventBytes, ccid) 260 if err != nil { 261 t.Fatalf("Failure while marshalling the ProposalResponsePayload") 262 return 263 } 264 265 // get the ProposalResponsePayload message 266 prp, err := protoutil.UnmarshalProposalResponsePayload(prpBytes) 267 if err != nil { 268 t.Fatalf("Failure while unmarshalling the ProposalResponsePayload") 269 return 270 } 271 272 // get the ChaincodeAction message 273 act, err := protoutil.UnmarshalChaincodeAction(prp.Extension) 274 if err != nil { 275 t.Fatalf("Failure while unmarshalling the ChaincodeAction") 276 return 277 } 278 279 // sanity check on the action 280 if string(act.Results) != "results" { 281 t.Fatalf("Invalid actions after unmarshalling") 282 return 283 } 284 285 event, err := protoutil.UnmarshalChaincodeEvents(act.Events) 286 if err != nil { 287 t.Fatalf("Failure while unmarshalling the ChainCodeEvents") 288 return 289 } 290 291 // sanity check on the event 292 if string(event.ChaincodeId) != "ccid" { 293 t.Fatalf("Invalid actions after unmarshalling") 294 return 295 } 296 297 pr := &pb.ProposalResponse{ 298 Payload: prpBytes, 299 Endorsement: &pb.Endorsement{Endorser: []byte("endorser"), Signature: []byte("signature")}, 300 Version: 1, // TODO: pick right version number 301 Response: &pb.Response{Status: 200, Message: "OK"}} 302 303 // create a proposal response 304 prBytes, err := protoutil.GetBytesProposalResponse(pr) 305 if err != nil { 306 t.Fatalf("Failure while marshalling the ProposalResponse") 307 return 308 } 309 310 // get the proposal response message back 311 prBack, err := protoutil.UnmarshalProposalResponse(prBytes) 312 if err != nil { 313 t.Fatalf("Failure while unmarshalling the ProposalResponse") 314 return 315 } 316 317 // sanity check on pr 318 if prBack.Response.Status != 200 || 319 string(prBack.Endorsement.Signature) != "signature" || 320 string(prBack.Endorsement.Endorser) != "endorser" || 321 !bytes.Equal(prBack.Payload, prpBytes) { 322 t.Fatalf("Invalid ProposalResponse after unmarshalling") 323 return 324 } 325 } 326 327 func TestEnvelope(t *testing.T) { 328 // create a proposal from a ChaincodeInvocationSpec 329 prop, _, err := protoutil.CreateChaincodeProposal(common.HeaderType_ENDORSER_TRANSACTION, testChannelID, createCIS(), signerSerialized) 330 if err != nil { 331 t.Fatalf("Could not create chaincode proposal, err %s\n", err) 332 return 333 } 334 335 response := &pb.Response{Status: 200, Payload: []byte("payload")} 336 result := []byte("res") 337 ccid := &pb.ChaincodeID{Name: "foo", Version: "v1"} 338 339 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, result, nil, ccid, signer) 340 if err != nil { 341 t.Fatalf("Could not create proposal response, err %s\n", err) 342 return 343 } 344 345 tx, err := protoutil.CreateSignedTx(prop, signer, presp) 346 if err != nil { 347 t.Fatalf("Could not create signed tx, err %s\n", err) 348 return 349 } 350 351 envBytes, err := protoutil.GetBytesEnvelope(tx) 352 if err != nil { 353 t.Fatalf("Could not marshal envelope, err %s\n", err) 354 return 355 } 356 357 tx, err = protoutil.GetEnvelopeFromBlock(envBytes) 358 if err != nil { 359 t.Fatalf("Could not unmarshal envelope, err %s\n", err) 360 return 361 } 362 363 act2, err := protoutil.GetActionFromEnvelope(envBytes) 364 if err != nil { 365 t.Fatalf("Could not extract actions from envelop, err %s\n", err) 366 return 367 } 368 369 if act2.Response.Status != response.Status { 370 t.Fatalf("response staus don't match") 371 return 372 } 373 if !bytes.Equal(act2.Response.Payload, response.Payload) { 374 t.Fatalf("response payload don't match") 375 return 376 } 377 378 if !bytes.Equal(act2.Results, result) { 379 t.Fatalf("results don't match") 380 return 381 } 382 383 txpayl, err := protoutil.UnmarshalPayload(tx.Payload) 384 if err != nil { 385 t.Fatalf("Could not unmarshal payload, err %s\n", err) 386 return 387 } 388 389 tx2, err := protoutil.UnmarshalTransaction(txpayl.Data) 390 if err != nil { 391 t.Fatalf("Could not unmarshal Transaction, err %s\n", err) 392 return 393 } 394 395 sh, err := protoutil.UnmarshalSignatureHeader(tx2.Actions[0].Header) 396 if err != nil { 397 t.Fatalf("Could not unmarshal SignatureHeader, err %s\n", err) 398 return 399 } 400 401 if !bytes.Equal(sh.Creator, signerSerialized) { 402 t.Fatalf("creator does not match") 403 return 404 } 405 406 cap, err := protoutil.UnmarshalChaincodeActionPayload(tx2.Actions[0].Payload) 407 if err != nil { 408 t.Fatalf("Could not unmarshal ChaincodeActionPayload, err %s\n", err) 409 return 410 } 411 assert.NotNil(t, cap) 412 413 prp, err := protoutil.UnmarshalProposalResponsePayload(cap.Action.ProposalResponsePayload) 414 if err != nil { 415 t.Fatalf("Could not unmarshal ProposalResponsePayload, err %s\n", err) 416 return 417 } 418 419 ca, err := protoutil.UnmarshalChaincodeAction(prp.Extension) 420 if err != nil { 421 t.Fatalf("Could not unmarshal ChaincodeAction, err %s\n", err) 422 return 423 } 424 425 if ca.Response.Status != response.Status { 426 t.Fatalf("response staus don't match") 427 return 428 } 429 if !bytes.Equal(ca.Response.Payload, response.Payload) { 430 t.Fatalf("response payload don't match") 431 return 432 } 433 434 if !bytes.Equal(ca.Results, result) { 435 t.Fatalf("results don't match") 436 return 437 } 438 } 439 440 func TestProposalTxID(t *testing.T) { 441 nonce := []byte{1} 442 creator := []byte{2} 443 444 txid := protoutil.ComputeTxID(nonce, creator) 445 assert.NotEmpty(t, txid, "TxID cannot be empty.") 446 assert.Nil(t, protoutil.CheckTxID(txid, nonce, creator)) 447 assert.Error(t, protoutil.CheckTxID("", nonce, creator)) 448 449 txid = protoutil.ComputeTxID(nil, nil) 450 assert.NotEmpty(t, txid, "TxID cannot be empty.") 451 } 452 453 func TestComputeProposalTxID(t *testing.T) { 454 txid := protoutil.ComputeTxID([]byte{1}, []byte{1}) 455 456 // Compute the function computed by ComputeTxID, 457 // namely, base64(sha256(nonce||creator)) 458 hf := sha256.New() 459 hf.Write([]byte{1}) 460 hf.Write([]byte{1}) 461 hashOut := hf.Sum(nil) 462 txid2 := hex.EncodeToString(hashOut) 463 464 t.Logf("% x\n", hashOut) 465 t.Logf("% s\n", txid) 466 t.Logf("% s\n", txid2) 467 468 assert.Equal(t, txid, txid2) 469 } 470 471 var signer msp.SigningIdentity 472 var signerSerialized []byte 473 474 func TestMain(m *testing.M) { 475 // setup the MSP manager so that we can sign/verify 476 err := msptesttools.LoadMSPSetupForTesting() 477 if err != nil { 478 os.Exit(-1) 479 fmt.Printf("Could not initialize msp") 480 return 481 } 482 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 483 if err != nil { 484 os.Exit(-1) 485 fmt.Printf("Could not initialize cryptoProvider") 486 return 487 } 488 signer, err = mspmgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity() 489 if err != nil { 490 os.Exit(-1) 491 fmt.Printf("Could not get signer") 492 return 493 } 494 495 signerSerialized, err = signer.Serialize() 496 if err != nil { 497 os.Exit(-1) 498 fmt.Printf("Could not serialize identity") 499 return 500 } 501 502 os.Exit(m.Run()) 503 } 504 505 func TestInvokedChaincodeName(t *testing.T) { 506 t.Run("Success", func(t *testing.T) { 507 name, err := protoutil.InvokedChaincodeName(protoutil.MarshalOrPanic(&pb.Proposal{ 508 Payload: protoutil.MarshalOrPanic(&pb.ChaincodeProposalPayload{ 509 Input: protoutil.MarshalOrPanic(&pb.ChaincodeInvocationSpec{ 510 ChaincodeSpec: &pb.ChaincodeSpec{ 511 ChaincodeId: &pb.ChaincodeID{ 512 Name: "cscc", 513 }, 514 }, 515 }), 516 }), 517 })) 518 assert.NoError(t, err) 519 assert.Equal(t, "cscc", name) 520 }) 521 522 t.Run("BadProposalBytes", func(t *testing.T) { 523 _, err := protoutil.InvokedChaincodeName([]byte("garbage")) 524 assert.EqualError(t, err, "could not unmarshal proposal: proto: can't skip unknown wire type 7") 525 }) 526 527 t.Run("BadChaincodeProposalBytes", func(t *testing.T) { 528 _, err := protoutil.InvokedChaincodeName(protoutil.MarshalOrPanic(&pb.Proposal{ 529 Payload: []byte("garbage"), 530 })) 531 assert.EqualError(t, err, "could not unmarshal chaincode proposal payload: proto: can't skip unknown wire type 7") 532 }) 533 534 t.Run("BadChaincodeInvocationSpec", func(t *testing.T) { 535 _, err := protoutil.InvokedChaincodeName(protoutil.MarshalOrPanic(&pb.Proposal{ 536 Payload: protoutil.MarshalOrPanic(&pb.ChaincodeProposalPayload{ 537 Input: []byte("garbage"), 538 }), 539 })) 540 assert.EqualError(t, err, "could not unmarshal chaincode invocation spec: proto: can't skip unknown wire type 7") 541 }) 542 543 t.Run("NilChaincodeSpec", func(t *testing.T) { 544 _, err := protoutil.InvokedChaincodeName(protoutil.MarshalOrPanic(&pb.Proposal{ 545 Payload: protoutil.MarshalOrPanic(&pb.ChaincodeProposalPayload{ 546 Input: protoutil.MarshalOrPanic(&pb.ChaincodeInvocationSpec{}), 547 }), 548 })) 549 assert.EqualError(t, err, "chaincode spec is nil") 550 }) 551 552 t.Run("NilChaincodeID", func(t *testing.T) { 553 _, err := protoutil.InvokedChaincodeName(protoutil.MarshalOrPanic(&pb.Proposal{ 554 Payload: protoutil.MarshalOrPanic(&pb.ChaincodeProposalPayload{ 555 Input: protoutil.MarshalOrPanic(&pb.ChaincodeInvocationSpec{ 556 ChaincodeSpec: &pb.ChaincodeSpec{}, 557 }), 558 }), 559 })) 560 assert.EqualError(t, err, "chaincode id is nil") 561 }) 562 }