github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/protos/utils/proputils_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 utils
    18  
    19  import (
    20  	"bytes"
    21  	"testing"
    22  
    23  	"reflect"
    24  
    25  	"fmt"
    26  	"os"
    27  
    28  	"crypto/sha256"
    29  	"encoding/hex"
    30  
    31  	"github.com/hyperledger/fabric/common/util"
    32  	"github.com/hyperledger/fabric/msp"
    33  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    34  	"github.com/hyperledger/fabric/msp/mgmt/testtools"
    35  	"github.com/hyperledger/fabric/protos/common"
    36  	pb "github.com/hyperledger/fabric/protos/peer"
    37  	"github.com/stretchr/testify/assert"
    38  )
    39  
    40  func createCIS() *pb.ChaincodeInvocationSpec {
    41  	return &pb.ChaincodeInvocationSpec{
    42  		ChaincodeSpec: &pb.ChaincodeSpec{
    43  			Type:        pb.ChaincodeSpec_GOLANG,
    44  			ChaincodeId: &pb.ChaincodeID{Name: "chaincode_name"},
    45  			Input:       &pb.ChaincodeInput{Args: [][]byte{[]byte("arg1"), []byte("arg2")}}}}
    46  }
    47  
    48  func TestProposal(t *testing.T) {
    49  	// create a proposal from a ChaincodeInvocationSpec
    50  	prop, _, err := CreateChaincodeProposalWithTransient(
    51  		common.HeaderType_ENDORSER_TRANSACTION,
    52  		util.GetTestChainID(), createCIS(),
    53  		[]byte("creator"),
    54  		map[string][]byte{"certx": []byte("transient")})
    55  	if err != nil {
    56  		t.Fatalf("Could not create chaincode proposal, err %s\n", err)
    57  		return
    58  	}
    59  
    60  	// serialize the proposal
    61  	pBytes, err := GetBytesProposal(prop)
    62  	if err != nil {
    63  		t.Fatalf("Could not serialize the chaincode proposal, err %s\n", err)
    64  		return
    65  	}
    66  
    67  	// deserialize it and expect it to be the same
    68  	propBack, err := GetProposal(pBytes)
    69  	if err != nil {
    70  		t.Fatalf("Could not deserialize the chaincode proposal, err %s\n", err)
    71  		return
    72  	}
    73  	if !reflect.DeepEqual(prop, propBack) {
    74  		t.Fatalf("Proposal and deserialized proposals don't match\n")
    75  		return
    76  	}
    77  
    78  	// get back the header
    79  	hdr, err := GetHeader(prop.Header)
    80  	if err != nil {
    81  		t.Fatalf("Could not extract the header from the proposal, err %s\n", err)
    82  	}
    83  
    84  	hdrBytes, err := GetBytesHeader(hdr)
    85  	if err != nil {
    86  		t.Fatalf("Could not marshal the header, err %s\n", err)
    87  	}
    88  
    89  	hdr, err = GetHeader(hdrBytes)
    90  	if err != nil {
    91  		t.Fatalf("Could not unmarshal the header, err %s\n", err)
    92  	}
    93  
    94  	chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader)
    95  	if err != nil {
    96  		t.Fatalf("Could not unmarshal channel header, err %s", err)
    97  	}
    98  
    99  	shdr, err := GetSignatureHeader(hdr.SignatureHeader)
   100  	if err != nil {
   101  		t.Fatalf("Could not unmarshal signature header, err %s", err)
   102  	}
   103  
   104  	// sanity check on header
   105  	if chdr.Type != int32(common.HeaderType_ENDORSER_TRANSACTION) ||
   106  		shdr.Nonce == nil ||
   107  		string(shdr.Creator) != "creator" {
   108  		t.Fatalf("Invalid header after unmarshalling\n")
   109  		return
   110  	}
   111  
   112  	// get back the header extension
   113  	hdrExt, err := GetChaincodeHeaderExtension(hdr)
   114  	if err != nil {
   115  		t.Fatalf("Could not extract the header extensions from the proposal, err %s\n", err)
   116  		return
   117  	}
   118  
   119  	// sanity check on header extension
   120  	if string(hdrExt.ChaincodeId.Name) != "chaincode_name" {
   121  		t.Fatalf("Invalid header extension after unmarshalling\n")
   122  		return
   123  	}
   124  
   125  	// get back the ChaincodeInvocationSpec
   126  	cis, err := GetChaincodeInvocationSpec(prop)
   127  	if err != nil {
   128  		t.Fatalf("Could not extract chaincode invocation spec from header, err %s\n", err)
   129  		return
   130  	}
   131  
   132  	// sanity check on cis
   133  	if cis.ChaincodeSpec.Type != pb.ChaincodeSpec_GOLANG ||
   134  		cis.ChaincodeSpec.ChaincodeId.Name != "chaincode_name" ||
   135  		len(cis.ChaincodeSpec.Input.Args) != 2 ||
   136  		string(cis.ChaincodeSpec.Input.Args[0]) != "arg1" ||
   137  		string(cis.ChaincodeSpec.Input.Args[1]) != "arg2" {
   138  		t.Fatalf("Invalid chaincode invocation spec after unmarshalling\n")
   139  		return
   140  	}
   141  
   142  	creator, transient, err := GetChaincodeProposalContext(prop)
   143  	if err != nil {
   144  		t.Fatalf("Failed getting chaincode proposal context [%s]", err)
   145  	}
   146  	if string(creator) != "creator" {
   147  		t.Fatalf("Failed checking Creator field. Invalid value, expectext 'creator', got [%s]", string(creator))
   148  		return
   149  	}
   150  	value, ok := transient["certx"]
   151  	if !ok || string(value) != "transient" {
   152  		t.Fatalf("Failed checking Transient field. Invalid value, expectext 'transient', got [%s]", string(value))
   153  		return
   154  	}
   155  }
   156  
   157  func TestProposalResponse(t *testing.T) {
   158  	events := &pb.ChaincodeEvent{
   159  		ChaincodeId: "ccid",
   160  		EventName:   "EventName",
   161  		Payload:     []byte("EventPayload"),
   162  		TxId:        "TxID"}
   163  
   164  	pHashBytes := []byte("proposal_hash")
   165  	pResponse := &pb.Response{Status: 200}
   166  	results := []byte("results")
   167  	eventBytes, err := GetBytesChaincodeEvent(events)
   168  	if err != nil {
   169  		t.Fatalf("Failure while marshalling the ProposalResponsePayload")
   170  		return
   171  	}
   172  
   173  	// get the bytes of the ProposalResponsePayload
   174  	prpBytes, err := GetBytesProposalResponsePayload(pHashBytes, pResponse, results, eventBytes)
   175  	if err != nil {
   176  		t.Fatalf("Failure while marshalling the ProposalResponsePayload")
   177  		return
   178  	}
   179  
   180  	// get the ProposalResponsePayload message
   181  	prp, err := GetProposalResponsePayload(prpBytes)
   182  	if err != nil {
   183  		t.Fatalf("Failure while unmarshalling the ProposalResponsePayload")
   184  		return
   185  	}
   186  
   187  	// get the ChaincodeAction message
   188  	act, err := GetChaincodeAction(prp.Extension)
   189  	if err != nil {
   190  		t.Fatalf("Failure while unmarshalling the ChaincodeAction")
   191  		return
   192  	}
   193  
   194  	// sanity check on the action
   195  	if string(act.Results) != "results" {
   196  		t.Fatalf("Invalid actions after unmarshalling")
   197  		return
   198  	}
   199  
   200  	event, err := GetChaincodeEvents(act.Events)
   201  	if err != nil {
   202  		t.Fatalf("Failure while unmarshalling the ChainCodeEvents")
   203  		return
   204  	}
   205  
   206  	// sanity check on the event
   207  	if string(event.ChaincodeId) != "ccid" {
   208  		t.Fatalf("Invalid actions after unmarshalling")
   209  		return
   210  	}
   211  
   212  	pr := &pb.ProposalResponse{
   213  		Payload:     prpBytes,
   214  		Endorsement: &pb.Endorsement{Endorser: []byte("endorser"), Signature: []byte("signature")},
   215  		Version:     1, // TODO: pick right version number
   216  		Response:    &pb.Response{Status: 200, Message: "OK"}}
   217  
   218  	// create a proposal response
   219  	prBytes, err := GetBytesProposalResponse(pr)
   220  	if err != nil {
   221  		t.Fatalf("Failure while marshalling the ProposalResponse")
   222  		return
   223  	}
   224  
   225  	// get the proposal response message back
   226  	prBack, err := GetProposalResponse(prBytes)
   227  	if err != nil {
   228  		t.Fatalf("Failure while unmarshalling the ProposalResponse")
   229  		return
   230  	}
   231  
   232  	// sanity check on pr
   233  	if prBack.Response.Status != 200 ||
   234  		string(prBack.Endorsement.Signature) != "signature" ||
   235  		string(prBack.Endorsement.Endorser) != "endorser" ||
   236  		bytes.Compare(prBack.Payload, prpBytes) != 0 {
   237  		t.Fatalf("Invalid ProposalResponse after unmarshalling")
   238  		return
   239  	}
   240  }
   241  
   242  func TestEnvelope(t *testing.T) {
   243  	// create a proposal from a ChaincodeInvocationSpec
   244  	prop, _, err := CreateChaincodeProposal(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), createCIS(), signerSerialized)
   245  	if err != nil {
   246  		t.Fatalf("Could not create chaincode proposal, err %s\n", err)
   247  		return
   248  	}
   249  
   250  	response := &pb.Response{Status: 200, Payload: []byte("payload")}
   251  	result := []byte("res")
   252  
   253  	presp, err := CreateProposalResponse(prop.Header, prop.Payload, response, result, nil, nil, signer)
   254  	if err != nil {
   255  		t.Fatalf("Could not create proposal response, err %s\n", err)
   256  		return
   257  	}
   258  
   259  	tx, err := CreateSignedTx(prop, signer, presp)
   260  	if err != nil {
   261  		t.Fatalf("Could not create signed tx, err %s\n", err)
   262  		return
   263  	}
   264  
   265  	envBytes, err := GetBytesEnvelope(tx)
   266  	if err != nil {
   267  		t.Fatalf("Could not marshal envelope, err %s\n", err)
   268  		return
   269  	}
   270  
   271  	tx, err = GetEnvelopeFromBlock(envBytes)
   272  	if err != nil {
   273  		t.Fatalf("Could not unmarshal envelope, err %s\n", err)
   274  		return
   275  	}
   276  
   277  	act2, err := GetActionFromEnvelope(envBytes)
   278  	if err != nil {
   279  		t.Fatalf("Could not extract actions from envelop, err %s\n", err)
   280  		return
   281  	}
   282  
   283  	if act2.Response.Status != response.Status {
   284  		t.Fatalf("response staus don't match")
   285  		return
   286  	}
   287  	if bytes.Compare(act2.Response.Payload, response.Payload) != 0 {
   288  		t.Fatalf("response payload don't match")
   289  		return
   290  	}
   291  
   292  	if bytes.Compare(act2.Results, result) != 0 {
   293  		t.Fatalf("results don't match")
   294  		return
   295  	}
   296  
   297  	txpayl, err := GetPayload(tx)
   298  	if err != nil {
   299  		t.Fatalf("Could not unmarshal payload, err %s\n", err)
   300  		return
   301  	}
   302  
   303  	tx2, err := GetTransaction(txpayl.Data)
   304  	if err != nil {
   305  		t.Fatalf("Could not unmarshal Transaction, err %s\n", err)
   306  		return
   307  	}
   308  
   309  	sh, err := GetSignatureHeader(tx2.Actions[0].Header)
   310  	if err != nil {
   311  		t.Fatalf("Could not unmarshal SignatureHeader, err %s\n", err)
   312  		return
   313  	}
   314  
   315  	if bytes.Compare(sh.Creator, signerSerialized) != 0 {
   316  		t.Fatalf("creator does not match")
   317  		return
   318  	}
   319  
   320  	cap, err := GetChaincodeActionPayload(tx2.Actions[0].Payload)
   321  	if err != nil {
   322  		t.Fatalf("Could not unmarshal ChaincodeActionPayload, err %s\n", err)
   323  		return
   324  	}
   325  	assert.NotNil(t, cap)
   326  
   327  	prp, err := GetProposalResponsePayload(cap.Action.ProposalResponsePayload)
   328  	if err != nil {
   329  		t.Fatalf("Could not unmarshal ProposalResponsePayload, err %s\n", err)
   330  		return
   331  	}
   332  
   333  	ca, err := GetChaincodeAction(prp.Extension)
   334  	if err != nil {
   335  		t.Fatalf("Could not unmarshal ChaincodeAction, err %s\n", err)
   336  		return
   337  	}
   338  
   339  	if ca.Response.Status != response.Status {
   340  		t.Fatalf("response staus don't match")
   341  		return
   342  	}
   343  	if bytes.Compare(ca.Response.Payload, response.Payload) != 0 {
   344  		t.Fatalf("response payload don't match")
   345  		return
   346  	}
   347  
   348  	if bytes.Compare(ca.Results, result) != 0 {
   349  		t.Fatalf("results don't match")
   350  		return
   351  	}
   352  }
   353  
   354  func TestProposalTxID(t *testing.T) {
   355  	nonce := []byte{1}
   356  	creator := []byte{2}
   357  
   358  	txid, err := ComputeProposalTxID(nonce, creator)
   359  	assert.NotEmpty(t, txid, "TxID cannot be empty.")
   360  	assert.NoError(t, err, "Failed computing txID")
   361  	assert.Nil(t, CheckProposalTxID(txid, nonce, creator))
   362  	assert.Error(t, CheckProposalTxID("", nonce, creator))
   363  
   364  	txid, err = ComputeProposalTxID(nil, nil)
   365  	assert.NotEmpty(t, txid, "TxID cannot be empty.")
   366  	assert.NoError(t, err, "Failed computing txID")
   367  }
   368  
   369  func TestComputeProposalTxID(t *testing.T) {
   370  	txid, err := ComputeProposalTxID([]byte{1}, []byte{1})
   371  	assert.NoError(t, err, "Failed computing TxID")
   372  
   373  	// Compute the function computed by ComputeProposalTxID,
   374  	// namely, base64(sha256(nonce||creator))
   375  	hf := sha256.New()
   376  	hf.Write([]byte{1})
   377  	hf.Write([]byte{1})
   378  	hashOut := hf.Sum(nil)
   379  	txid2 := hex.EncodeToString(hashOut)
   380  
   381  	t.Logf("% x\n", hashOut)
   382  	t.Logf("% s\n", txid)
   383  	t.Logf("% s\n", txid2)
   384  
   385  	assert.Equal(t, txid, txid2)
   386  }
   387  
   388  var signer msp.SigningIdentity
   389  var signerSerialized []byte
   390  
   391  func TestMain(m *testing.M) {
   392  	// setup the MSP manager so that we can sign/verify
   393  	mspMgrConfigFile := "../../msp/sampleconfig/"
   394  	err := msptesttools.LoadMSPSetupForTesting(mspMgrConfigFile)
   395  	if err != nil {
   396  		os.Exit(-1)
   397  		fmt.Printf("Could not initialize msp")
   398  		return
   399  	}
   400  	signer, err = mspmgmt.GetLocalMSP().GetDefaultSigningIdentity()
   401  	if err != nil {
   402  		os.Exit(-1)
   403  		fmt.Printf("Could not get signer")
   404  		return
   405  	}
   406  
   407  	signerSerialized, err = signer.Serialize()
   408  	if err != nil {
   409  		os.Exit(-1)
   410  		fmt.Printf("Could not serialize identity")
   411  		return
   412  	}
   413  
   414  	os.Exit(m.Run())
   415  }