github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/common/validation/fullflow_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 validation 18 19 import ( 20 "fmt" 21 "math/rand" 22 "os" 23 "testing" 24 "time" 25 26 mmsp "github.com/hyperledger/fabric/common/mocks/msp" 27 "github.com/hyperledger/fabric/common/util" 28 "github.com/hyperledger/fabric/msp" 29 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 30 "github.com/hyperledger/fabric/msp/mgmt/testtools" 31 "github.com/hyperledger/fabric/protos/common" 32 "github.com/hyperledger/fabric/protos/peer" 33 "github.com/hyperledger/fabric/protos/utils" 34 "github.com/stretchr/testify/assert" 35 ) 36 37 func getProposal() (*peer.Proposal, error) { 38 cis := &peer.ChaincodeInvocationSpec{ 39 ChaincodeSpec: &peer.ChaincodeSpec{ 40 ChaincodeId: getChaincodeID(), 41 Type: peer.ChaincodeSpec_GOLANG}} 42 43 proposal, _, err := utils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), cis, signerSerialized) 44 return proposal, err 45 } 46 47 func getChaincodeID() *peer.ChaincodeID { 48 return &peer.ChaincodeID{Name: "foo", Version: "v1"} 49 } 50 51 func createSignedTxTwoActions(proposal *peer.Proposal, signer msp.SigningIdentity, resps ...*peer.ProposalResponse) (*common.Envelope, error) { 52 if len(resps) == 0 { 53 return nil, fmt.Errorf("At least one proposal response is necessary") 54 } 55 56 // the original header 57 hdr, err := utils.GetHeader(proposal.Header) 58 if err != nil { 59 return nil, fmt.Errorf("Could not unmarshal the proposal header") 60 } 61 62 // the original payload 63 pPayl, err := utils.GetChaincodeProposalPayload(proposal.Payload) 64 if err != nil { 65 return nil, fmt.Errorf("Could not unmarshal the proposal payload") 66 } 67 68 // fill endorsements 69 endorsements := make([]*peer.Endorsement, len(resps)) 70 for n, r := range resps { 71 endorsements[n] = r.Endorsement 72 } 73 74 // create ChaincodeEndorsedAction 75 cea := &peer.ChaincodeEndorsedAction{ProposalResponsePayload: resps[0].Payload, Endorsements: endorsements} 76 77 // obtain the bytes of the proposal payload that will go to the transaction 78 propPayloadBytes, err := utils.GetBytesProposalPayloadForTx(pPayl, nil) 79 if err != nil { 80 return nil, err 81 } 82 83 // serialize the chaincode action payload 84 cap := &peer.ChaincodeActionPayload{ChaincodeProposalPayload: propPayloadBytes, Action: cea} 85 capBytes, err := utils.GetBytesChaincodeActionPayload(cap) 86 if err != nil { 87 return nil, err 88 } 89 90 // create a transaction 91 taa := &peer.TransactionAction{Header: hdr.SignatureHeader, Payload: capBytes} 92 taas := make([]*peer.TransactionAction, 2) 93 taas[0] = taa 94 taas[1] = taa 95 tx := &peer.Transaction{Actions: taas} 96 97 // serialize the tx 98 txBytes, err := utils.GetBytesTransaction(tx) 99 if err != nil { 100 return nil, err 101 } 102 103 // create the payload 104 payl := &common.Payload{Header: hdr, Data: txBytes} 105 paylBytes, err := utils.GetBytesPayload(payl) 106 if err != nil { 107 return nil, err 108 } 109 110 // sign the payload 111 sig, err := signer.Sign(paylBytes) 112 if err != nil { 113 return nil, err 114 } 115 116 // here's the envelope 117 return &common.Envelope{Payload: paylBytes, Signature: sig}, nil 118 } 119 120 func TestGoodPath(t *testing.T) { 121 // get a toy proposal 122 prop, err := getProposal() 123 if err != nil { 124 t.Fatalf("getProposal failed, err %s", err) 125 return 126 } 127 128 // sign it 129 sProp, err := utils.GetSignedProposal(prop, signer) 130 if err != nil { 131 t.Fatalf("GetSignedProposal failed, err %s", err) 132 return 133 } 134 135 // validate it 136 _, _, _, err = ValidateProposalMessage(sProp) 137 if err != nil { 138 t.Fatalf("ValidateProposalMessage failed, err %s", err) 139 return 140 } 141 142 response := &peer.Response{Status: 200} 143 simRes := []byte("simulation_result") 144 145 // endorse it to get a proposal response 146 presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), nil, signer) 147 if err != nil { 148 t.Fatalf("CreateProposalResponse failed, err %s", err) 149 return 150 } 151 152 // assemble a transaction from that proposal and endorsement 153 tx, err := utils.CreateSignedTx(prop, signer, presp) 154 if err != nil { 155 t.Fatalf("CreateSignedTx failed, err %s", err) 156 return 157 } 158 159 // validate the transaction 160 payl, txResult := ValidateTransaction(tx) 161 if txResult != peer.TxValidationCode_VALID { 162 t.Fatalf("ValidateTransaction failed, err %s", err) 163 return 164 } 165 166 txx, err := utils.GetTransaction(payl.Data) 167 if err != nil { 168 t.Fatalf("GetTransaction failed, err %s", err) 169 return 170 } 171 172 act := txx.Actions 173 174 // expect one single action 175 if len(act) != 1 { 176 t.Fatalf("Ivalid number of TransactionAction, expected 1, got %d", len(act)) 177 return 178 } 179 180 // get the payload of the action 181 _, simResBack, err := utils.GetPayloads(act[0]) 182 if err != nil { 183 t.Fatalf("GetPayloads failed, err %s", err) 184 return 185 } 186 187 // compare it to the original action and expect it to be equal 188 if string(simRes) != string(simResBack.Results) { 189 t.Fatal("Simulation results are different") 190 return 191 } 192 } 193 194 func TestTXWithTwoActionsRejected(t *testing.T) { 195 // get a toy proposal 196 prop, err := getProposal() 197 if err != nil { 198 t.Fatalf("getProposal failed, err %s", err) 199 return 200 } 201 202 response := &peer.Response{Status: 200} 203 simRes := []byte("simulation_result") 204 205 // endorse it to get a proposal response 206 presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, &peer.ChaincodeID{Name: "somename", Version: "someversion"}, nil, signer) 207 if err != nil { 208 t.Fatalf("CreateProposalResponse failed, err %s", err) 209 return 210 } 211 212 // assemble a transaction from that proposal and endorsement 213 tx, err := createSignedTxTwoActions(prop, signer, presp) 214 if err != nil { 215 t.Fatalf("CreateSignedTx failed, err %s", err) 216 return 217 } 218 219 // validate the transaction 220 _, txResult := ValidateTransaction(tx) 221 if txResult == peer.TxValidationCode_VALID { 222 t.Fatalf("ValidateTransaction should have failed") 223 return 224 } 225 } 226 227 func TestBadProp(t *testing.T) { 228 // get a toy proposal 229 prop, err := getProposal() 230 if err != nil { 231 t.Fatalf("getProposal failed, err %s", err) 232 return 233 } 234 235 // sign it 236 sProp, err := utils.GetSignedProposal(prop, signer) 237 if err != nil { 238 t.Fatalf("GetSignedProposal failed, err %s", err) 239 return 240 } 241 242 // mess with the signature 243 sigOrig := sProp.Signature 244 for i := 0; i < len(sigOrig); i++ { 245 sigCopy := make([]byte, len(sigOrig)) 246 copy(sigCopy, sigOrig) 247 sigCopy[i] = byte(int(sigCopy[i]+1) % 255) 248 // validate it - it should fail 249 _, _, _, err = ValidateProposalMessage(&peer.SignedProposal{ProposalBytes: sProp.ProposalBytes, Signature: sigCopy}) 250 if err == nil { 251 t.Fatal("ValidateProposalMessage should have failed") 252 return 253 } 254 } 255 256 // sign it again 257 sProp, err = utils.GetSignedProposal(prop, signer) 258 if err != nil { 259 t.Fatalf("GetSignedProposal failed, err %s", err) 260 return 261 } 262 263 // mess with the message 264 pbytesOrig := sProp.ProposalBytes 265 for i := 0; i < len(pbytesOrig); i++ { 266 pbytesCopy := make([]byte, len(pbytesOrig)) 267 copy(pbytesCopy, pbytesOrig) 268 pbytesCopy[i] = byte(int(pbytesCopy[i]+1) % 255) 269 // validate it - it should fail 270 _, _, _, err = ValidateProposalMessage(&peer.SignedProposal{ProposalBytes: pbytesCopy, Signature: sProp.Signature}) 271 if err == nil { 272 t.Fatal("ValidateProposalMessage should have failed") 273 return 274 } 275 } 276 277 // get a bad signing identity 278 badSigner, err := mmsp.NewNoopMsp().GetDefaultSigningIdentity() 279 if err != nil { 280 t.Fatal("Couldn't get noop signer") 281 return 282 } 283 284 // sign it again with the bad signer 285 sProp, err = utils.GetSignedProposal(prop, badSigner) 286 if err != nil { 287 t.Fatalf("GetSignedProposal failed, err %s", err) 288 return 289 } 290 291 // validate it - it should fail 292 _, _, _, err = ValidateProposalMessage(sProp) 293 if err == nil { 294 t.Fatal("ValidateProposalMessage should have failed") 295 return 296 } 297 } 298 299 func corrupt(bytes []byte) { 300 rand.Seed(time.Now().UnixNano()) 301 bytes[rand.Intn(len(bytes))]-- 302 } 303 304 func TestBadTx(t *testing.T) { 305 // get a toy proposal 306 prop, err := getProposal() 307 if err != nil { 308 t.Fatalf("getProposal failed, err %s", err) 309 return 310 } 311 312 response := &peer.Response{Status: 200} 313 simRes := []byte("simulation_result") 314 315 // endorse it to get a proposal response 316 presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), nil, signer) 317 if err != nil { 318 t.Fatalf("CreateProposalResponse failed, err %s", err) 319 return 320 } 321 322 // assemble a transaction from that proposal and endorsement 323 tx, err := utils.CreateSignedTx(prop, signer, presp) 324 if err != nil { 325 t.Fatalf("CreateSignedTx failed, err %s", err) 326 return 327 } 328 329 // mess with the transaction payload 330 paylOrig := tx.Payload 331 for i := 0; i < len(paylOrig); i++ { 332 paylCopy := make([]byte, len(paylOrig)) 333 copy(paylCopy, paylOrig) 334 paylCopy[i] = byte(int(paylCopy[i]+1) % 255) 335 // validate the transaction it should fail 336 _, txResult := ValidateTransaction(&common.Envelope{Signature: tx.Signature, Payload: paylCopy}) 337 if txResult == peer.TxValidationCode_VALID { 338 t.Fatal("ValidateTransaction should have failed") 339 return 340 } 341 } 342 343 // assemble a transaction from that proposal and endorsement 344 tx, err = utils.CreateSignedTx(prop, signer, presp) 345 if err != nil { 346 t.Fatalf("CreateSignedTx failed, err %s", err) 347 return 348 } 349 350 // mess with the transaction payload 351 corrupt(tx.Signature) 352 353 // validate the transaction it should fail 354 _, txResult := ValidateTransaction(tx) 355 if txResult == peer.TxValidationCode_VALID { 356 t.Fatal("ValidateTransaction should have failed") 357 return 358 } 359 } 360 361 func Test2EndorsersAgree(t *testing.T) { 362 // get a toy proposal 363 prop, err := getProposal() 364 if err != nil { 365 t.Fatalf("getProposal failed, err %s", err) 366 return 367 } 368 369 response1 := &peer.Response{Status: 200} 370 simRes1 := []byte("simulation_result") 371 372 // endorse it to get a proposal response 373 presp1, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, getChaincodeID(), nil, signer) 374 if err != nil { 375 t.Fatalf("CreateProposalResponse failed, err %s", err) 376 return 377 } 378 379 response2 := &peer.Response{Status: 200} 380 simRes2 := []byte("simulation_result") 381 382 // endorse it to get a proposal response 383 presp2, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, getChaincodeID(), nil, signer) 384 if err != nil { 385 t.Fatalf("CreateProposalResponse failed, err %s", err) 386 return 387 } 388 389 // assemble a transaction from that proposal and endorsement 390 tx, err := utils.CreateSignedTx(prop, signer, presp1, presp2) 391 if err != nil { 392 t.Fatalf("CreateSignedTx failed, err %s", err) 393 return 394 } 395 396 // validate the transaction 397 _, txResult := ValidateTransaction(tx) 398 if txResult != peer.TxValidationCode_VALID { 399 t.Fatalf("ValidateTransaction failed, err %s", err) 400 return 401 } 402 } 403 404 func Test2EndorsersDisagree(t *testing.T) { 405 // get a toy proposal 406 prop, err := getProposal() 407 if err != nil { 408 t.Fatalf("getProposal failed, err %s", err) 409 return 410 } 411 412 response1 := &peer.Response{Status: 200} 413 simRes1 := []byte("simulation_result1") 414 415 // endorse it to get a proposal response 416 presp1, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, getChaincodeID(), nil, signer) 417 if err != nil { 418 t.Fatalf("CreateProposalResponse failed, err %s", err) 419 return 420 } 421 422 response2 := &peer.Response{Status: 200} 423 simRes2 := []byte("simulation_result2") 424 425 // endorse it to get a proposal response 426 presp2, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, getChaincodeID(), nil, signer) 427 if err != nil { 428 t.Fatalf("CreateProposalResponse failed, err %s", err) 429 return 430 } 431 432 // assemble a transaction from that proposal and endorsement 433 _, err = utils.CreateSignedTx(prop, signer, presp1, presp2) 434 if err == nil { 435 t.Fatal("CreateSignedTx should have failed") 436 return 437 } 438 } 439 440 func TestInvocationsBadArgs(t *testing.T) { 441 _, code := ValidateTransaction(nil) 442 assert.Equal(t, code, peer.TxValidationCode_NIL_ENVELOPE) 443 err := validateEndorserTransaction(nil, nil) 444 assert.Error(t, err) 445 err = validateConfigTransaction(nil, nil) 446 assert.Error(t, err) 447 _, _, err = validateCommonHeader(nil) 448 assert.Error(t, err) 449 err = validateChannelHeader(nil) 450 assert.Error(t, err) 451 err = validateChannelHeader(&common.ChannelHeader{}) 452 assert.Error(t, err) 453 err = validateSignatureHeader(nil) 454 assert.Error(t, err) 455 err = validateSignatureHeader(&common.SignatureHeader{}) 456 assert.Error(t, err) 457 err = validateSignatureHeader(&common.SignatureHeader{Nonce: []byte("a")}) 458 assert.Error(t, err) 459 err = checkSignatureFromCreator(nil, nil, nil, "") 460 assert.Error(t, err) 461 _, _, _, err = ValidateProposalMessage(nil) 462 assert.Error(t, err) 463 _, err = validateChaincodeProposalMessage(nil, nil) 464 assert.Error(t, err) 465 _, err = validateChaincodeProposalMessage(&peer.Proposal{}, &common.Header{[]byte("a"), []byte("a")}) 466 assert.Error(t, err) 467 } 468 469 var signer msp.SigningIdentity 470 var signerSerialized []byte 471 472 func TestMain(m *testing.M) { 473 // setup crypto algorithms 474 // setup the MSP manager so that we can sign/verify 475 err := msptesttools.LoadMSPSetupForTesting() 476 if err != nil { 477 fmt.Printf("Could not initialize msp, err %s", err) 478 os.Exit(-1) 479 return 480 } 481 482 signer, err = mspmgmt.GetLocalMSP().GetDefaultSigningIdentity() 483 if err != nil { 484 fmt.Println("Could not get signer") 485 os.Exit(-1) 486 return 487 } 488 489 signerSerialized, err = signer.Serialize() 490 if err != nil { 491 fmt.Println("Could not serialize identity") 492 os.Exit(-1) 493 return 494 } 495 496 os.Exit(m.Run()) 497 }