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