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