github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/protos/utils/proputils_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package utils_test 18 19 import ( 20 "bytes" 21 "testing" 22 23 "reflect" 24 25 "fmt" 26 "os" 27 28 "crypto/sha256" 29 "encoding/hex" 30 31 "github.com/hyperledger/fabric/common/util" 32 "github.com/hyperledger/fabric/msp" 33 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 34 "github.com/hyperledger/fabric/msp/mgmt/testtools" 35 "github.com/hyperledger/fabric/protos/common" 36 pb "github.com/hyperledger/fabric/protos/peer" 37 "github.com/hyperledger/fabric/protos/utils" 38 "github.com/stretchr/testify/assert" 39 ) 40 41 func createCIS() *pb.ChaincodeInvocationSpec { 42 return &pb.ChaincodeInvocationSpec{ 43 ChaincodeSpec: &pb.ChaincodeSpec{ 44 Type: pb.ChaincodeSpec_GOLANG, 45 ChaincodeId: &pb.ChaincodeID{Name: "chaincode_name"}, 46 Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("arg1"), []byte("arg2")}}}} 47 } 48 49 func TestProposal(t *testing.T) { 50 // create a proposal from a ChaincodeInvocationSpec 51 prop, _, err := utils.CreateChaincodeProposalWithTransient( 52 common.HeaderType_ENDORSER_TRANSACTION, 53 util.GetTestChainID(), createCIS(), 54 []byte("creator"), 55 map[string][]byte{"certx": []byte("transient")}) 56 if err != nil { 57 t.Fatalf("Could not create chaincode proposal, err %s\n", err) 58 return 59 } 60 61 // serialize the proposal 62 pBytes, err := utils.GetBytesProposal(prop) 63 if err != nil { 64 t.Fatalf("Could not serialize the chaincode proposal, err %s\n", err) 65 return 66 } 67 68 // deserialize it and expect it to be the same 69 propBack, err := utils.GetProposal(pBytes) 70 if err != nil { 71 t.Fatalf("Could not deserialize the chaincode proposal, err %s\n", err) 72 return 73 } 74 if !reflect.DeepEqual(prop, propBack) { 75 t.Fatalf("Proposal and deserialized proposals don't match\n") 76 return 77 } 78 79 // get back the header 80 hdr, err := utils.GetHeader(prop.Header) 81 if err != nil { 82 t.Fatalf("Could not extract the header from the proposal, err %s\n", err) 83 } 84 85 hdrBytes, err := utils.GetBytesHeader(hdr) 86 if err != nil { 87 t.Fatalf("Could not marshal the header, err %s\n", err) 88 } 89 90 hdr, err = utils.GetHeader(hdrBytes) 91 if err != nil { 92 t.Fatalf("Could not unmarshal the header, err %s\n", err) 93 } 94 95 chdr, err := utils.UnmarshalChannelHeader(hdr.ChannelHeader) 96 if err != nil { 97 t.Fatalf("Could not unmarshal channel header, err %s", err) 98 } 99 100 shdr, err := utils.GetSignatureHeader(hdr.SignatureHeader) 101 if err != nil { 102 t.Fatalf("Could not unmarshal signature header, err %s", err) 103 } 104 105 // sanity check on header 106 if chdr.Type != int32(common.HeaderType_ENDORSER_TRANSACTION) || 107 shdr.Nonce == nil || 108 string(shdr.Creator) != "creator" { 109 t.Fatalf("Invalid header after unmarshalling\n") 110 return 111 } 112 113 // get back the header extension 114 hdrExt, err := utils.GetChaincodeHeaderExtension(hdr) 115 if err != nil { 116 t.Fatalf("Could not extract the header extensions from the proposal, err %s\n", err) 117 return 118 } 119 120 // sanity check on header extension 121 if string(hdrExt.ChaincodeId.Name) != "chaincode_name" { 122 t.Fatalf("Invalid header extension after unmarshalling\n") 123 return 124 } 125 126 // get back the ChaincodeInvocationSpec 127 cis, err := utils.GetChaincodeInvocationSpec(prop) 128 if err != nil { 129 t.Fatalf("Could not extract chaincode invocation spec from header, err %s\n", err) 130 return 131 } 132 133 // sanity check on cis 134 if cis.ChaincodeSpec.Type != pb.ChaincodeSpec_GOLANG || 135 cis.ChaincodeSpec.ChaincodeId.Name != "chaincode_name" || 136 len(cis.ChaincodeSpec.Input.Args) != 2 || 137 string(cis.ChaincodeSpec.Input.Args[0]) != "arg1" || 138 string(cis.ChaincodeSpec.Input.Args[1]) != "arg2" { 139 t.Fatalf("Invalid chaincode invocation spec after unmarshalling\n") 140 return 141 } 142 143 creator, transient, err := utils.GetChaincodeProposalContext(prop) 144 if err != nil { 145 t.Fatalf("Failed getting chaincode proposal context [%s]", err) 146 } 147 if string(creator) != "creator" { 148 t.Fatalf("Failed checking Creator field. Invalid value, expectext 'creator', got [%s]", string(creator)) 149 return 150 } 151 value, ok := transient["certx"] 152 if !ok || string(value) != "transient" { 153 t.Fatalf("Failed checking Transient field. Invalid value, expectext 'transient', got [%s]", string(value)) 154 return 155 } 156 } 157 158 func TestProposalResponse(t *testing.T) { 159 events := &pb.ChaincodeEvent{ 160 ChaincodeId: "ccid", 161 EventName: "EventName", 162 Payload: []byte("EventPayload"), 163 TxId: "TxID"} 164 ccid := &pb.ChaincodeID{ 165 Name: "ccid", 166 Version: "v1", 167 } 168 169 pHashBytes := []byte("proposal_hash") 170 pResponse := &pb.Response{Status: 200} 171 results := []byte("results") 172 eventBytes, err := utils.GetBytesChaincodeEvent(events) 173 if err != nil { 174 t.Fatalf("Failure while marshalling the ProposalResponsePayload") 175 return 176 } 177 178 // get the bytes of the ProposalResponsePayload 179 prpBytes, err := utils.GetBytesProposalResponsePayload(pHashBytes, pResponse, results, eventBytes, ccid) 180 if err != nil { 181 t.Fatalf("Failure while marshalling the ProposalResponsePayload") 182 return 183 } 184 185 // get the ProposalResponsePayload message 186 prp, err := utils.GetProposalResponsePayload(prpBytes) 187 if err != nil { 188 t.Fatalf("Failure while unmarshalling the ProposalResponsePayload") 189 return 190 } 191 192 // get the ChaincodeAction message 193 act, err := utils.GetChaincodeAction(prp.Extension) 194 if err != nil { 195 t.Fatalf("Failure while unmarshalling the ChaincodeAction") 196 return 197 } 198 199 // sanity check on the action 200 if string(act.Results) != "results" { 201 t.Fatalf("Invalid actions after unmarshalling") 202 return 203 } 204 205 event, err := utils.GetChaincodeEvents(act.Events) 206 if err != nil { 207 t.Fatalf("Failure while unmarshalling the ChainCodeEvents") 208 return 209 } 210 211 // sanity check on the event 212 if string(event.ChaincodeId) != "ccid" { 213 t.Fatalf("Invalid actions after unmarshalling") 214 return 215 } 216 217 pr := &pb.ProposalResponse{ 218 Payload: prpBytes, 219 Endorsement: &pb.Endorsement{Endorser: []byte("endorser"), Signature: []byte("signature")}, 220 Version: 1, // TODO: pick right version number 221 Response: &pb.Response{Status: 200, Message: "OK"}} 222 223 // create a proposal response 224 prBytes, err := utils.GetBytesProposalResponse(pr) 225 if err != nil { 226 t.Fatalf("Failure while marshalling the ProposalResponse") 227 return 228 } 229 230 // get the proposal response message back 231 prBack, err := utils.GetProposalResponse(prBytes) 232 if err != nil { 233 t.Fatalf("Failure while unmarshalling the ProposalResponse") 234 return 235 } 236 237 // sanity check on pr 238 if prBack.Response.Status != 200 || 239 string(prBack.Endorsement.Signature) != "signature" || 240 string(prBack.Endorsement.Endorser) != "endorser" || 241 bytes.Compare(prBack.Payload, prpBytes) != 0 { 242 t.Fatalf("Invalid ProposalResponse after unmarshalling") 243 return 244 } 245 } 246 247 func TestEnvelope(t *testing.T) { 248 // create a proposal from a ChaincodeInvocationSpec 249 prop, _, err := utils.CreateChaincodeProposal(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), createCIS(), signerSerialized) 250 if err != nil { 251 t.Fatalf("Could not create chaincode proposal, err %s\n", err) 252 return 253 } 254 255 response := &pb.Response{Status: 200, Payload: []byte("payload")} 256 result := []byte("res") 257 ccid := &pb.ChaincodeID{Name: "foo", Version: "v1"} 258 259 presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, result, nil, ccid, nil, signer) 260 if err != nil { 261 t.Fatalf("Could not create proposal response, err %s\n", err) 262 return 263 } 264 265 tx, err := utils.CreateSignedTx(prop, signer, presp) 266 if err != nil { 267 t.Fatalf("Could not create signed tx, err %s\n", err) 268 return 269 } 270 271 envBytes, err := utils.GetBytesEnvelope(tx) 272 if err != nil { 273 t.Fatalf("Could not marshal envelope, err %s\n", err) 274 return 275 } 276 277 tx, err = utils.GetEnvelopeFromBlock(envBytes) 278 if err != nil { 279 t.Fatalf("Could not unmarshal envelope, err %s\n", err) 280 return 281 } 282 283 act2, err := utils.GetActionFromEnvelope(envBytes) 284 if err != nil { 285 t.Fatalf("Could not extract actions from envelop, err %s\n", err) 286 return 287 } 288 289 if act2.Response.Status != response.Status { 290 t.Fatalf("response staus don't match") 291 return 292 } 293 if bytes.Compare(act2.Response.Payload, response.Payload) != 0 { 294 t.Fatalf("response payload don't match") 295 return 296 } 297 298 if bytes.Compare(act2.Results, result) != 0 { 299 t.Fatalf("results don't match") 300 return 301 } 302 303 txpayl, err := utils.GetPayload(tx) 304 if err != nil { 305 t.Fatalf("Could not unmarshal payload, err %s\n", err) 306 return 307 } 308 309 tx2, err := utils.GetTransaction(txpayl.Data) 310 if err != nil { 311 t.Fatalf("Could not unmarshal Transaction, err %s\n", err) 312 return 313 } 314 315 sh, err := utils.GetSignatureHeader(tx2.Actions[0].Header) 316 if err != nil { 317 t.Fatalf("Could not unmarshal SignatureHeader, err %s\n", err) 318 return 319 } 320 321 if bytes.Compare(sh.Creator, signerSerialized) != 0 { 322 t.Fatalf("creator does not match") 323 return 324 } 325 326 cap, err := utils.GetChaincodeActionPayload(tx2.Actions[0].Payload) 327 if err != nil { 328 t.Fatalf("Could not unmarshal ChaincodeActionPayload, err %s\n", err) 329 return 330 } 331 assert.NotNil(t, cap) 332 333 prp, err := utils.GetProposalResponsePayload(cap.Action.ProposalResponsePayload) 334 if err != nil { 335 t.Fatalf("Could not unmarshal ProposalResponsePayload, err %s\n", err) 336 return 337 } 338 339 ca, err := utils.GetChaincodeAction(prp.Extension) 340 if err != nil { 341 t.Fatalf("Could not unmarshal ChaincodeAction, err %s\n", err) 342 return 343 } 344 345 if ca.Response.Status != response.Status { 346 t.Fatalf("response staus don't match") 347 return 348 } 349 if bytes.Compare(ca.Response.Payload, response.Payload) != 0 { 350 t.Fatalf("response payload don't match") 351 return 352 } 353 354 if bytes.Compare(ca.Results, result) != 0 { 355 t.Fatalf("results don't match") 356 return 357 } 358 } 359 360 func TestProposalTxID(t *testing.T) { 361 nonce := []byte{1} 362 creator := []byte{2} 363 364 txid, err := utils.ComputeProposalTxID(nonce, creator) 365 assert.NotEmpty(t, txid, "TxID cannot be empty.") 366 assert.NoError(t, err, "Failed computing txID") 367 assert.Nil(t, utils.CheckProposalTxID(txid, nonce, creator)) 368 assert.Error(t, utils.CheckProposalTxID("", nonce, creator)) 369 370 txid, err = utils.ComputeProposalTxID(nil, nil) 371 assert.NotEmpty(t, txid, "TxID cannot be empty.") 372 assert.NoError(t, err, "Failed computing txID") 373 } 374 375 func TestComputeProposalTxID(t *testing.T) { 376 txid, err := utils.ComputeProposalTxID([]byte{1}, []byte{1}) 377 assert.NoError(t, err, "Failed computing TxID") 378 379 // Compute the function computed by ComputeProposalTxID, 380 // namely, base64(sha256(nonce||creator)) 381 hf := sha256.New() 382 hf.Write([]byte{1}) 383 hf.Write([]byte{1}) 384 hashOut := hf.Sum(nil) 385 txid2 := hex.EncodeToString(hashOut) 386 387 t.Logf("% x\n", hashOut) 388 t.Logf("% s\n", txid) 389 t.Logf("% s\n", txid2) 390 391 assert.Equal(t, txid, txid2) 392 } 393 394 var signer msp.SigningIdentity 395 var signerSerialized []byte 396 397 func TestMain(m *testing.M) { 398 // setup the MSP manager so that we can sign/verify 399 err := msptesttools.LoadMSPSetupForTesting() 400 if err != nil { 401 os.Exit(-1) 402 fmt.Printf("Could not initialize msp") 403 return 404 } 405 signer, err = mspmgmt.GetLocalMSP().GetDefaultSigningIdentity() 406 if err != nil { 407 os.Exit(-1) 408 fmt.Printf("Could not get signer") 409 return 410 } 411 412 signerSerialized, err = signer.Serialize() 413 if err != nil { 414 os.Exit(-1) 415 fmt.Printf("Could not serialize identity") 416 return 417 } 418 419 os.Exit(m.Run()) 420 }