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