github.com/renegr87/renegr87@v2.1.1+incompatible/core/common/validation/fullflow_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package validation 8 9 import ( 10 "fmt" 11 "math/rand" 12 "os" 13 "testing" 14 "time" 15 16 "github.com/hyperledger/fabric-protos-go/common" 17 "github.com/hyperledger/fabric-protos-go/peer" 18 "github.com/hyperledger/fabric/bccsp/sw" 19 "github.com/hyperledger/fabric/msp" 20 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 21 msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" 22 "github.com/hyperledger/fabric/protoutil" 23 "github.com/stretchr/testify/assert" 24 ) 25 26 func getProposal(channelID string) (*peer.Proposal, error) { 27 cis := &peer.ChaincodeInvocationSpec{ 28 ChaincodeSpec: &peer.ChaincodeSpec{ 29 ChaincodeId: getChaincodeID(), 30 Type: peer.ChaincodeSpec_GOLANG}} 31 32 proposal, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, channelID, cis, signerSerialized) 33 return proposal, err 34 } 35 36 func getChaincodeID() *peer.ChaincodeID { 37 return &peer.ChaincodeID{Name: "foo", Version: "v1"} 38 } 39 40 func createSignedTxTwoActions(proposal *peer.Proposal, signer msp.SigningIdentity, resps ...*peer.ProposalResponse) (*common.Envelope, error) { 41 if len(resps) == 0 { 42 return nil, fmt.Errorf("At least one proposal response is necessary") 43 } 44 45 // the original header 46 hdr, err := protoutil.UnmarshalHeader(proposal.Header) 47 if err != nil { 48 return nil, fmt.Errorf("Could not unmarshal the proposal header") 49 } 50 51 // the original payload 52 pPayl, err := protoutil.UnmarshalChaincodeProposalPayload(proposal.Payload) 53 if err != nil { 54 return nil, fmt.Errorf("Could not unmarshal the proposal payload") 55 } 56 57 // fill endorsements 58 endorsements := make([]*peer.Endorsement, len(resps)) 59 for n, r := range resps { 60 endorsements[n] = r.Endorsement 61 } 62 63 // create ChaincodeEndorsedAction 64 cea := &peer.ChaincodeEndorsedAction{ProposalResponsePayload: resps[0].Payload, Endorsements: endorsements} 65 66 // obtain the bytes of the proposal payload that will go to the transaction 67 propPayloadBytes, err := protoutil.GetBytesProposalPayloadForTx(pPayl) 68 if err != nil { 69 return nil, err 70 } 71 72 // serialize the chaincode action payload 73 cap := &peer.ChaincodeActionPayload{ChaincodeProposalPayload: propPayloadBytes, Action: cea} 74 capBytes, err := protoutil.GetBytesChaincodeActionPayload(cap) 75 if err != nil { 76 return nil, err 77 } 78 79 // create a transaction 80 taa := &peer.TransactionAction{Header: hdr.SignatureHeader, Payload: capBytes} 81 taas := make([]*peer.TransactionAction, 2) 82 taas[0] = taa 83 taas[1] = taa 84 tx := &peer.Transaction{Actions: taas} 85 86 // serialize the tx 87 txBytes, err := protoutil.GetBytesTransaction(tx) 88 if err != nil { 89 return nil, err 90 } 91 92 // create the payload 93 payl := &common.Payload{Header: hdr, Data: txBytes} 94 paylBytes, err := protoutil.GetBytesPayload(payl) 95 if err != nil { 96 return nil, err 97 } 98 99 // sign the payload 100 sig, err := signer.Sign(paylBytes) 101 if err != nil { 102 return nil, err 103 } 104 105 // here's the envelope 106 return &common.Envelope{Payload: paylBytes, Signature: sig}, nil 107 } 108 109 func TestGoodPath(t *testing.T) { 110 // get a toy proposal 111 prop, err := getProposal("testchannelid") 112 if err != nil { 113 t.Fatalf("getProposal failed, err %s", err) 114 return 115 } 116 117 response := &peer.Response{Status: 200} 118 simRes := []byte("simulation_result") 119 120 // endorse it to get a proposal response 121 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), signer) 122 if err != nil { 123 t.Fatalf("CreateProposalResponse failed, err %s", err) 124 return 125 } 126 127 // assemble a transaction from that proposal and endorsement 128 tx, err := protoutil.CreateSignedTx(prop, signer, presp) 129 if err != nil { 130 t.Fatalf("CreateSignedTx failed, err %s", err) 131 return 132 } 133 134 // validate the transaction 135 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 136 assert.NoError(t, err) 137 payl, txResult := ValidateTransaction(tx, cryptoProvider) 138 if txResult != peer.TxValidationCode_VALID { 139 t.Fatalf("ValidateTransaction failed, err %s", err) 140 return 141 } 142 143 txx, err := protoutil.UnmarshalTransaction(payl.Data) 144 if err != nil { 145 t.Fatalf("GetTransaction failed, err %s", err) 146 return 147 } 148 149 act := txx.Actions 150 151 // expect one single action 152 if len(act) != 1 { 153 t.Fatalf("Ivalid number of TransactionAction, expected 1, got %d", len(act)) 154 return 155 } 156 157 // get the payload of the action 158 _, simResBack, err := protoutil.GetPayloads(act[0]) 159 if err != nil { 160 t.Fatalf("GetPayloads failed, err %s", err) 161 return 162 } 163 164 // compare it to the original action and expect it to be equal 165 if string(simRes) != string(simResBack.Results) { 166 t.Fatal("Simulation results are different") 167 return 168 } 169 } 170 171 func TestTXWithTwoActionsRejected(t *testing.T) { 172 // get a toy proposal 173 prop, err := getProposal("testchannelid") 174 if err != nil { 175 t.Fatalf("getProposal failed, err %s", err) 176 return 177 } 178 179 response := &peer.Response{Status: 200} 180 simRes := []byte("simulation_result") 181 182 // endorse it to get a proposal response 183 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, &peer.ChaincodeID{Name: "somename", Version: "someversion"}, signer) 184 if err != nil { 185 t.Fatalf("CreateProposalResponse failed, err %s", err) 186 return 187 } 188 189 // assemble a transaction from that proposal and endorsement 190 tx, err := createSignedTxTwoActions(prop, signer, presp) 191 if err != nil { 192 t.Fatalf("CreateSignedTx failed, err %s", err) 193 return 194 } 195 196 // validate the transaction 197 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 198 assert.NoError(t, err) 199 _, txResult := ValidateTransaction(tx, cryptoProvider) 200 if txResult == peer.TxValidationCode_VALID { 201 t.Fatalf("ValidateTransaction should have failed") 202 return 203 } 204 } 205 206 func corrupt(bytes []byte) { 207 rand.Seed(time.Now().UnixNano()) 208 bytes[rand.Intn(len(bytes))]-- 209 } 210 211 func TestBadTx(t *testing.T) { 212 // get a toy proposal 213 prop, err := getProposal("testchannelid") 214 if err != nil { 215 t.Fatalf("getProposal failed, err %s", err) 216 return 217 } 218 219 response := &peer.Response{Status: 200} 220 simRes := []byte("simulation_result") 221 222 // endorse it to get a proposal response 223 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, simRes, nil, getChaincodeID(), signer) 224 if err != nil { 225 t.Fatalf("CreateProposalResponse failed, err %s", err) 226 return 227 } 228 229 // assemble a transaction from that proposal and endorsement 230 tx, err := protoutil.CreateSignedTx(prop, signer, presp) 231 if err != nil { 232 t.Fatalf("CreateSignedTx failed, err %s", err) 233 return 234 } 235 236 // mess with the transaction payload 237 paylOrig := tx.Payload 238 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 239 assert.NoError(t, err) 240 for i := 0; i < len(paylOrig); i++ { 241 paylCopy := make([]byte, len(paylOrig)) 242 copy(paylCopy, paylOrig) 243 paylCopy[i] = byte(int(paylCopy[i]+1) % 255) 244 // validate the transaction it should fail 245 _, txResult := ValidateTransaction(&common.Envelope{Signature: tx.Signature, Payload: paylCopy}, cryptoProvider) 246 if txResult == peer.TxValidationCode_VALID { 247 t.Fatal("ValidateTransaction should have failed") 248 return 249 } 250 } 251 252 // assemble a transaction from that proposal and endorsement 253 tx, err = protoutil.CreateSignedTx(prop, signer, presp) 254 if err != nil { 255 t.Fatalf("CreateSignedTx failed, err %s", err) 256 return 257 } 258 259 // mess with the transaction payload 260 corrupt(tx.Signature) 261 262 // validate the transaction it should fail 263 _, txResult := ValidateTransaction(tx, cryptoProvider) 264 if txResult == peer.TxValidationCode_VALID { 265 t.Fatal("ValidateTransaction should have failed") 266 return 267 } 268 } 269 270 func Test2EndorsersAgree(t *testing.T) { 271 // get a toy proposal 272 prop, err := getProposal("testchannelid") 273 if err != nil { 274 t.Fatalf("getProposal failed, err %s", err) 275 return 276 } 277 278 response1 := &peer.Response{Status: 200} 279 simRes1 := []byte("simulation_result") 280 281 // endorse it to get a proposal response 282 presp1, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, getChaincodeID(), signer) 283 if err != nil { 284 t.Fatalf("CreateProposalResponse failed, err %s", err) 285 return 286 } 287 288 response2 := &peer.Response{Status: 200} 289 simRes2 := []byte("simulation_result") 290 291 // endorse it to get a proposal response 292 presp2, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, getChaincodeID(), signer) 293 if err != nil { 294 t.Fatalf("CreateProposalResponse failed, err %s", err) 295 return 296 } 297 298 // assemble a transaction from that proposal and endorsement 299 tx, err := protoutil.CreateSignedTx(prop, signer, presp1, presp2) 300 if err != nil { 301 t.Fatalf("CreateSignedTx failed, err %s", err) 302 return 303 } 304 305 // validate the transaction 306 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 307 assert.NoError(t, err) 308 _, txResult := ValidateTransaction(tx, cryptoProvider) 309 if txResult != peer.TxValidationCode_VALID { 310 t.Fatalf("ValidateTransaction failed, err %s", err) 311 return 312 } 313 } 314 315 func Test2EndorsersDisagree(t *testing.T) { 316 // get a toy proposal 317 prop, err := getProposal("testchannelid") 318 if err != nil { 319 t.Fatalf("getProposal failed, err %s", err) 320 return 321 } 322 323 response1 := &peer.Response{Status: 200} 324 simRes1 := []byte("simulation_result1") 325 326 // endorse it to get a proposal response 327 presp1, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response1, simRes1, nil, getChaincodeID(), signer) 328 if err != nil { 329 t.Fatalf("CreateProposalResponse failed, err %s", err) 330 return 331 } 332 333 response2 := &peer.Response{Status: 200} 334 simRes2 := []byte("simulation_result2") 335 336 // endorse it to get a proposal response 337 presp2, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response2, simRes2, nil, getChaincodeID(), signer) 338 if err != nil { 339 t.Fatalf("CreateProposalResponse failed, err %s", err) 340 return 341 } 342 343 // assemble a transaction from that proposal and endorsement 344 _, err = protoutil.CreateSignedTx(prop, signer, presp1, presp2) 345 if err == nil { 346 t.Fatal("CreateSignedTx should have failed") 347 return 348 } 349 } 350 351 func TestInvocationsBadArgs(t *testing.T) { 352 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 353 assert.NoError(t, err) 354 355 _, code := ValidateTransaction(nil, cryptoProvider) 356 assert.Equal(t, code, peer.TxValidationCode_NIL_ENVELOPE) 357 err = validateEndorserTransaction(nil, nil) 358 assert.Error(t, err) 359 err = validateConfigTransaction(nil, nil) 360 assert.Error(t, err) 361 _, _, err = validateCommonHeader(nil) 362 assert.Error(t, err) 363 err = validateChannelHeader(nil) 364 assert.Error(t, err) 365 err = validateChannelHeader(&common.ChannelHeader{}) 366 assert.Error(t, err) 367 err = validateSignatureHeader(nil) 368 assert.Error(t, err) 369 err = validateSignatureHeader(&common.SignatureHeader{}) 370 assert.Error(t, err) 371 err = validateSignatureHeader(&common.SignatureHeader{Nonce: []byte("a")}) 372 assert.Error(t, err) 373 err = checkSignatureFromCreator(nil, nil, nil, "", cryptoProvider) 374 assert.Error(t, err) 375 } 376 377 var signer msp.SigningIdentity 378 var signerSerialized []byte 379 var signerMSPId string 380 381 func TestMain(m *testing.M) { 382 // setup crypto algorithms 383 // setup the MSP manager so that we can sign/verify 384 err := msptesttools.LoadMSPSetupForTesting() 385 if err != nil { 386 fmt.Printf("Could not initialize msp, err %s", err) 387 os.Exit(-1) 388 return 389 } 390 391 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 392 if err != nil { 393 fmt.Printf("Initialize cryptoProvider bccsp failed: %s", err) 394 os.Exit(-1) 395 return 396 } 397 398 signer, err = mspmgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity() 399 if err != nil { 400 fmt.Println("Could not get signer") 401 os.Exit(-1) 402 return 403 } 404 signerMSPId = signer.GetMSPIdentifier() 405 406 signerSerialized, err = signer.Serialize() 407 if err != nil { 408 fmt.Println("Could not serialize identity") 409 os.Exit(-1) 410 return 411 } 412 413 os.Exit(m.Run()) 414 }