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  }