github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/protos/utils/proputils.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  	"errors"
    21  	"fmt"
    22  
    23  	"encoding/binary"
    24  
    25  	"encoding/hex"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  	"github.com/hyperledger/fabric/bccsp"
    29  	"github.com/hyperledger/fabric/bccsp/factory"
    30  	"github.com/hyperledger/fabric/core/chaincode/platforms"
    31  	"github.com/hyperledger/fabric/core/crypto/primitives"
    32  	"github.com/hyperledger/fabric/protos/common"
    33  	"github.com/hyperledger/fabric/protos/peer"
    34  )
    35  
    36  // GetChaincodeInvocationSpec get the ChaincodeInvocationSpec from the proposal
    37  func GetChaincodeInvocationSpec(prop *peer.Proposal) (*peer.ChaincodeInvocationSpec, error) {
    38  	txhdr := &common.Header{}
    39  	err := proto.Unmarshal(prop.Header, txhdr)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	ccPropPayload := &peer.ChaincodeProposalPayload{}
    44  	err = proto.Unmarshal(prop.Payload, ccPropPayload)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	cis := &peer.ChaincodeInvocationSpec{}
    49  	err = proto.Unmarshal(ccPropPayload.Input, cis)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	return cis, nil
    54  }
    55  
    56  // GetChaincodeProposalContext returns creator and transient
    57  func GetChaincodeProposalContext(prop *peer.Proposal) ([]byte, map[string][]byte, error) {
    58  	if prop == nil {
    59  		return nil, nil, fmt.Errorf("Proposal is nil")
    60  	}
    61  	if len(prop.Header) == 0 {
    62  		return nil, nil, fmt.Errorf("Proposal's header is nil")
    63  	}
    64  	if len(prop.Payload) == 0 {
    65  		return nil, nil, fmt.Errorf("Proposal's payload is nil")
    66  	}
    67  
    68  	//// get back the header
    69  	hdr, err := GetHeader(prop.Header)
    70  	if err != nil {
    71  		return nil, nil, fmt.Errorf("Could not extract the header from the proposal: %s", err)
    72  	}
    73  	if hdr == nil {
    74  		return nil, nil, fmt.Errorf("Unmarshalled header is nil")
    75  	}
    76  
    77  	chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader)
    78  	if err != nil {
    79  		return nil, nil, fmt.Errorf("Could not extract the channel header from the proposal: %s", err)
    80  	}
    81  
    82  	if common.HeaderType(chdr.Type) != common.HeaderType_ENDORSER_TRANSACTION &&
    83  		common.HeaderType(chdr.Type) != common.HeaderType_CONFIG {
    84  		return nil, nil, fmt.Errorf("Invalid proposal type expected ENDORSER_TRANSACTION or CONFIG. Was: %d", chdr.Type)
    85  	}
    86  
    87  	shdr, err := GetSignatureHeader(hdr.SignatureHeader)
    88  	if err != nil {
    89  		return nil, nil, fmt.Errorf("Could not extract the signature header from the proposal: %s", err)
    90  	}
    91  
    92  	ccPropPayload := &peer.ChaincodeProposalPayload{}
    93  	err = proto.Unmarshal(prop.Payload, ccPropPayload)
    94  	if err != nil {
    95  		return nil, nil, err
    96  	}
    97  
    98  	return shdr.Creator, ccPropPayload.TransientMap, nil
    99  }
   100  
   101  // GetHeader Get Header from bytes
   102  func GetHeader(bytes []byte) (*common.Header, error) {
   103  	hdr := &common.Header{}
   104  	err := proto.Unmarshal(bytes, hdr)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	return hdr, nil
   110  }
   111  
   112  // GetNonce returns the nonce used in Proposal
   113  func GetNonce(prop *peer.Proposal) ([]byte, error) {
   114  	// get back the header
   115  	hdr, err := GetHeader(prop.Header)
   116  	if err != nil {
   117  		return nil, fmt.Errorf("Could not extract the header from the proposal: %s", err)
   118  	}
   119  
   120  	chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader)
   121  	if err != nil {
   122  		return nil, fmt.Errorf("Could not extract the channel header from the proposal: %s", err)
   123  	}
   124  	shdr, err := GetSignatureHeader(hdr.SignatureHeader)
   125  	if err != nil {
   126  		return nil, fmt.Errorf("Could not extract the signature header from the proposal: %s", err)
   127  	}
   128  
   129  	if common.HeaderType(chdr.Type) != common.HeaderType_ENDORSER_TRANSACTION &&
   130  		common.HeaderType(chdr.Type) != common.HeaderType_CONFIG {
   131  		return nil, fmt.Errorf("Invalid proposal type expected ENDORSER_TRANSACTION or CONFIG. Was: %d", chdr.Type)
   132  	}
   133  
   134  	if hdr.SignatureHeader == nil {
   135  		return nil, errors.New("Invalid signature header. It must be different from nil.")
   136  	}
   137  
   138  	ccPropPayload := &peer.ChaincodeProposalPayload{}
   139  	err = proto.Unmarshal(prop.Payload, ccPropPayload)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	return shdr.Nonce, nil
   145  }
   146  
   147  // GetChaincodeHeaderExtension get chaincode header extension given header
   148  func GetChaincodeHeaderExtension(hdr *common.Header) (*peer.ChaincodeHeaderExtension, error) {
   149  	chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  
   154  	chaincodeHdrExt := &peer.ChaincodeHeaderExtension{}
   155  	err = proto.Unmarshal(chdr.Extension, chaincodeHdrExt)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	return chaincodeHdrExt, nil
   161  }
   162  
   163  // GetProposalResponse given proposal in bytes
   164  func GetProposalResponse(prBytes []byte) (*peer.ProposalResponse, error) {
   165  	proposalResponse := &peer.ProposalResponse{}
   166  	err := proto.Unmarshal(prBytes, proposalResponse)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	return proposalResponse, nil
   172  }
   173  
   174  // GetChaincodeDeploymentSpec returns a ChaincodeDeploymentSpec given args
   175  func GetChaincodeDeploymentSpec(code []byte) (*peer.ChaincodeDeploymentSpec, error) {
   176  	cds := &peer.ChaincodeDeploymentSpec{}
   177  	err := proto.Unmarshal(code, cds)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	// FAB-2122: Validate the CDS according to platform specific requirements
   183  	platform, err := platforms.Find(cds.ChaincodeSpec.Type)
   184  	if err != nil {
   185  		return nil, err
   186  	}
   187  
   188  	err = platform.ValidateDeploymentSpec(cds)
   189  	if err != nil {
   190  		return nil, err
   191  	}
   192  
   193  	return cds, nil
   194  }
   195  
   196  // GetChaincodeAction gets the ChaincodeAction given chaicnode action bytes
   197  func GetChaincodeAction(caBytes []byte) (*peer.ChaincodeAction, error) {
   198  	chaincodeAction := &peer.ChaincodeAction{}
   199  	err := proto.Unmarshal(caBytes, chaincodeAction)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	return chaincodeAction, nil
   205  }
   206  
   207  // GetResponse gets the Response given response bytes
   208  func GetResponse(resBytes []byte) (*peer.Response, error) {
   209  	response := &peer.Response{}
   210  	err := proto.Unmarshal(resBytes, response)
   211  	if err != nil {
   212  		return nil, err
   213  	}
   214  
   215  	return response, nil
   216  }
   217  
   218  // GetChaincodeEvents gets the ChaincodeEvents given chaicnode event bytes
   219  func GetChaincodeEvents(eBytes []byte) (*peer.ChaincodeEvent, error) {
   220  	chaincodeEvent := &peer.ChaincodeEvent{}
   221  	err := proto.Unmarshal(eBytes, chaincodeEvent)
   222  	if err != nil {
   223  		return nil, err
   224  	}
   225  
   226  	return chaincodeEvent, nil
   227  }
   228  
   229  // GetProposalResponsePayload gets the proposal response payload
   230  func GetProposalResponsePayload(prpBytes []byte) (*peer.ProposalResponsePayload, error) {
   231  	prp := &peer.ProposalResponsePayload{}
   232  	err := proto.Unmarshal(prpBytes, prp)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  
   237  	return prp, nil
   238  }
   239  
   240  // GetProposal returns a Proposal message from its bytes
   241  func GetProposal(propBytes []byte) (*peer.Proposal, error) {
   242  	prop := &peer.Proposal{}
   243  	err := proto.Unmarshal(propBytes, prop)
   244  	if err != nil {
   245  		return nil, err
   246  	}
   247  
   248  	return prop, nil
   249  }
   250  
   251  // GetPayload Get Payload from Envelope message
   252  func GetPayload(e *common.Envelope) (*common.Payload, error) {
   253  	payload := &common.Payload{}
   254  	err := proto.Unmarshal(e.Payload, payload)
   255  	if err != nil {
   256  		return nil, err
   257  	}
   258  
   259  	return payload, nil
   260  }
   261  
   262  // GetTransaction Get Transaction from bytes
   263  func GetTransaction(txBytes []byte) (*peer.Transaction, error) {
   264  	tx := &peer.Transaction{}
   265  	err := proto.Unmarshal(txBytes, tx)
   266  	if err != nil {
   267  		return nil, err
   268  	}
   269  
   270  	return tx, nil
   271  }
   272  
   273  // GetChaincodeActionPayload Get ChaincodeActionPayload from bytes
   274  func GetChaincodeActionPayload(capBytes []byte) (*peer.ChaincodeActionPayload, error) {
   275  	cap := &peer.ChaincodeActionPayload{}
   276  	err := proto.Unmarshal(capBytes, cap)
   277  	if err != nil {
   278  		return nil, err
   279  	}
   280  
   281  	return cap, nil
   282  }
   283  
   284  // GetChaincodeProposalPayload Get ChaincodeProposalPayload from bytes
   285  func GetChaincodeProposalPayload(bytes []byte) (*peer.ChaincodeProposalPayload, error) {
   286  	cpp := &peer.ChaincodeProposalPayload{}
   287  	err := proto.Unmarshal(bytes, cpp)
   288  	if err != nil {
   289  		return nil, err
   290  	}
   291  
   292  	return cpp, nil
   293  }
   294  
   295  // GetSignatureHeader Get SignatureHeader from bytes
   296  func GetSignatureHeader(bytes []byte) (*common.SignatureHeader, error) {
   297  	sh := &common.SignatureHeader{}
   298  	err := proto.Unmarshal(bytes, sh)
   299  	if err != nil {
   300  		return nil, err
   301  	}
   302  
   303  	return sh, nil
   304  }
   305  
   306  // GetSignaturePolicyEnvelope returns a SignaturePolicyEnvelope from bytes
   307  func GetSignaturePolicyEnvelope(bytes []byte) (*common.SignaturePolicyEnvelope, error) {
   308  	p := &common.SignaturePolicyEnvelope{}
   309  	err := proto.Unmarshal(bytes, p)
   310  	if err != nil {
   311  		return nil, err
   312  	}
   313  
   314  	return p, nil
   315  }
   316  
   317  // CreateChaincodeProposal creates a proposal from given input.
   318  // It returns the proposal and the transaction id associated to the proposal
   319  func CreateChaincodeProposal(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error) {
   320  	return CreateChaincodeProposalWithTransient(typ, chainID, cis, creator, nil)
   321  }
   322  
   323  // CreateChaincodeProposalWithTransient creates a proposal from given input
   324  // It returns the proposal and the transaction id associated to the proposal
   325  func CreateChaincodeProposalWithTransient(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) {
   326  	// generate a random nonce
   327  	nonce, err := primitives.GetRandomNonce()
   328  	if err != nil {
   329  		return nil, "", err
   330  	}
   331  
   332  	// compute txid
   333  	txid, err := ComputeProposalTxID(nonce, creator)
   334  	if err != nil {
   335  		return nil, "", err
   336  	}
   337  
   338  	return CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, chainID, cis, nonce, creator, transientMap)
   339  }
   340  
   341  // CreateChaincodeProposalWithTxIDNonceAndTransient creates a proposal from given input
   342  func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) {
   343  	ccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId}
   344  	ccHdrExtBytes, err := proto.Marshal(ccHdrExt)
   345  	if err != nil {
   346  		return nil, "", err
   347  	}
   348  
   349  	cisBytes, err := proto.Marshal(cis)
   350  	if err != nil {
   351  		return nil, "", err
   352  	}
   353  
   354  	ccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap}
   355  	ccPropPayloadBytes, err := proto.Marshal(ccPropPayload)
   356  	if err != nil {
   357  		return nil, "", err
   358  	}
   359  
   360  	// TODO: epoch is now set to zero. This must be changed once we
   361  	// get a more appropriate mechanism to handle it in.
   362  	var epoch uint64 = 0
   363  
   364  	hdr := &common.Header{ChannelHeader: MarshalOrPanic(&common.ChannelHeader{
   365  		Type:      int32(typ),
   366  		TxId:      txid,
   367  		ChannelId: chainID,
   368  		Extension: ccHdrExtBytes,
   369  		Epoch:     epoch}),
   370  		SignatureHeader: MarshalOrPanic(&common.SignatureHeader{Nonce: nonce, Creator: creator})}
   371  
   372  	hdrBytes, err := proto.Marshal(hdr)
   373  	if err != nil {
   374  		return nil, "", err
   375  	}
   376  
   377  	return &peer.Proposal{Header: hdrBytes, Payload: ccPropPayloadBytes}, txid, nil
   378  }
   379  
   380  // GetBytesProposalResponsePayload gets proposal response payload
   381  func GetBytesProposalResponsePayload(hash []byte, response *peer.Response, result []byte, event []byte) ([]byte, error) {
   382  	cAct := &peer.ChaincodeAction{Events: event, Results: result, Response: response}
   383  	cActBytes, err := proto.Marshal(cAct)
   384  	if err != nil {
   385  		return nil, err
   386  	}
   387  
   388  	prp := &peer.ProposalResponsePayload{Extension: cActBytes, ProposalHash: hash}
   389  	prpBytes, err := proto.Marshal(prp)
   390  	if err != nil {
   391  		return nil, err
   392  	}
   393  
   394  	return prpBytes, nil
   395  }
   396  
   397  // GetBytesChaincodeProposalPayload gets the chaincode proposal payload
   398  func GetBytesChaincodeProposalPayload(cpp *peer.ChaincodeProposalPayload) ([]byte, error) {
   399  	cppBytes, err := proto.Marshal(cpp)
   400  	if err != nil {
   401  		return nil, err
   402  	}
   403  
   404  	return cppBytes, nil
   405  }
   406  
   407  // GetBytesResponse gets the bytes of Response
   408  func GetBytesResponse(res *peer.Response) ([]byte, error) {
   409  	resBytes, err := proto.Marshal(res)
   410  	if err != nil {
   411  		return nil, err
   412  	}
   413  
   414  	return resBytes, nil
   415  }
   416  
   417  // GetBytesChaincodeEvent gets the bytes of ChaincodeEvent
   418  func GetBytesChaincodeEvent(event *peer.ChaincodeEvent) ([]byte, error) {
   419  	eventBytes, err := proto.Marshal(event)
   420  	if err != nil {
   421  		return nil, err
   422  	}
   423  
   424  	return eventBytes, nil
   425  }
   426  
   427  // GetBytesChaincodeActionPayload get the bytes of ChaincodeActionPayload from the message
   428  func GetBytesChaincodeActionPayload(cap *peer.ChaincodeActionPayload) ([]byte, error) {
   429  	capBytes, err := proto.Marshal(cap)
   430  	if err != nil {
   431  		return nil, err
   432  	}
   433  
   434  	return capBytes, nil
   435  }
   436  
   437  // GetBytesProposalResponse gets propoal bytes response
   438  func GetBytesProposalResponse(pr *peer.ProposalResponse) ([]byte, error) {
   439  	respBytes, err := proto.Marshal(pr)
   440  	if err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	return respBytes, nil
   445  }
   446  
   447  // GetBytesProposal returns the bytes of a proposal message
   448  func GetBytesProposal(prop *peer.Proposal) ([]byte, error) {
   449  	propBytes, err := proto.Marshal(prop)
   450  	if err != nil {
   451  		return nil, err
   452  	}
   453  
   454  	return propBytes, nil
   455  }
   456  
   457  // GetBytesHeader get the bytes of Header from the message
   458  func GetBytesHeader(hdr *common.Header) ([]byte, error) {
   459  	bytes, err := proto.Marshal(hdr)
   460  	if err != nil {
   461  		return nil, err
   462  	}
   463  
   464  	return bytes, nil
   465  }
   466  
   467  // GetBytesSignatureHeader get the bytes of SignatureHeader from the message
   468  func GetBytesSignatureHeader(hdr *common.SignatureHeader) ([]byte, error) {
   469  	bytes, err := proto.Marshal(hdr)
   470  	if err != nil {
   471  		return nil, err
   472  	}
   473  
   474  	return bytes, nil
   475  }
   476  
   477  // GetBytesTransaction get the bytes of Transaction from the message
   478  func GetBytesTransaction(tx *peer.Transaction) ([]byte, error) {
   479  	bytes, err := proto.Marshal(tx)
   480  	if err != nil {
   481  		return nil, err
   482  	}
   483  
   484  	return bytes, nil
   485  }
   486  
   487  // GetBytesPayload get the bytes of Payload from the message
   488  func GetBytesPayload(payl *common.Payload) ([]byte, error) {
   489  	bytes, err := proto.Marshal(payl)
   490  	if err != nil {
   491  		return nil, err
   492  	}
   493  
   494  	return bytes, nil
   495  }
   496  
   497  // GetBytesEnvelope get the bytes of Envelope from the message
   498  func GetBytesEnvelope(env *common.Envelope) ([]byte, error) {
   499  	bytes, err := proto.Marshal(env)
   500  	if err != nil {
   501  		return nil, err
   502  	}
   503  
   504  	return bytes, nil
   505  }
   506  
   507  // GetActionFromEnvelope extracts a ChaincodeAction message from a serialized Envelope
   508  func GetActionFromEnvelope(envBytes []byte) (*peer.ChaincodeAction, error) {
   509  	env, err := GetEnvelopeFromBlock(envBytes)
   510  	if err != nil {
   511  		return nil, err
   512  	}
   513  
   514  	payl, err := GetPayload(env)
   515  	if err != nil {
   516  		return nil, err
   517  	}
   518  
   519  	tx, err := GetTransaction(payl.Data)
   520  	if err != nil {
   521  		return nil, err
   522  	}
   523  
   524  	_, respPayload, err := GetPayloads(tx.Actions[0])
   525  	return respPayload, err
   526  }
   527  
   528  // CreateProposalFromCIS returns a proposal given a serialized identity and a ChaincodeInvocationSpec
   529  func CreateProposalFromCIS(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error) {
   530  	return CreateChaincodeProposal(typ, chainID, cis, creator)
   531  }
   532  
   533  // CreateInstallProposalFromCDS returns a install proposal given a serialized identity and a ChaincodeDeploymentSpec
   534  func CreateInstallProposalFromCDS(cds *peer.ChaincodeDeploymentSpec, creator []byte) (*peer.Proposal, string, error) {
   535  	return createProposalFromCDS("", cds, creator, nil, nil, nil, "install")
   536  }
   537  
   538  // CreateDeployProposalFromCDS returns a deploy proposal given a serialized identity and a ChaincodeDeploymentSpec
   539  func CreateDeployProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error) {
   540  	return createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, "deploy")
   541  }
   542  
   543  // CreateUpgradeProposalFromCDS returns a upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec
   544  func CreateUpgradeProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error) {
   545  	return createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, "upgrade")
   546  }
   547  
   548  // createProposalFromCDS returns a deploy or upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec
   549  func createProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte, propType string) (*peer.Proposal, string, error) {
   550  	//in the new mode, cds will be nil, "deploy" and "upgrade" are instantiates.
   551  	var ccinp *peer.ChaincodeInput
   552  	var b []byte
   553  	var err error
   554  	if cds != nil {
   555  		b, err = proto.Marshal(cds)
   556  		if err != nil {
   557  			return nil, "", err
   558  		}
   559  	}
   560  	switch propType {
   561  	case "deploy":
   562  		fallthrough
   563  	case "upgrade":
   564  		ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), []byte(chainID), b, policy, escc, vscc}}
   565  	case "install":
   566  		ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), b}}
   567  	}
   568  
   569  	//wrap the deployment in an invocation spec to lccc...
   570  	lcccSpec := &peer.ChaincodeInvocationSpec{
   571  		ChaincodeSpec: &peer.ChaincodeSpec{
   572  			Type:        peer.ChaincodeSpec_GOLANG,
   573  			ChaincodeId: &peer.ChaincodeID{Name: "lccc"},
   574  			Input:       ccinp}}
   575  
   576  	//...and get the proposal for it
   577  	return CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, lcccSpec, creator)
   578  }
   579  
   580  // ComputeProposalTxID computes TxID as the Hash computed
   581  // over the concatenation of nonce and creator.
   582  func ComputeProposalTxID(nonce, creator []byte) (string, error) {
   583  	// TODO: Get the Hash function to be used from
   584  	// channel configuration
   585  	digest, err := factory.GetDefault().Hash(
   586  		append(nonce, creator...),
   587  		&bccsp.SHA256Opts{})
   588  	if err != nil {
   589  		return "", err
   590  	}
   591  	return hex.EncodeToString(digest), nil
   592  }
   593  
   594  // CheckProposalTxID checks that txid is equal to the Hash computed
   595  // over the concatenation of nonce and creator.
   596  func CheckProposalTxID(txid string, nonce, creator []byte) error {
   597  	computedTxID, err := ComputeProposalTxID(nonce, creator)
   598  	if err != nil {
   599  		return fmt.Errorf("Failed computing target TXID for comparison [%s]", err)
   600  	}
   601  
   602  	if txid != computedTxID {
   603  		return fmt.Errorf("Transaction is not valid. Got [%s], expected [%s]", txid, computedTxID)
   604  	}
   605  
   606  	return nil
   607  }
   608  
   609  // ComputeProposalBinding computes the binding of a proposal
   610  func ComputeProposalBinding(proposal *peer.Proposal) ([]byte, error) {
   611  	if proposal == nil {
   612  		return nil, fmt.Errorf("Porposal is nil")
   613  	}
   614  	if len(proposal.Header) == 0 {
   615  		return nil, fmt.Errorf("Proposal's Header is nil")
   616  	}
   617  
   618  	h, err := GetHeader(proposal.Header)
   619  	if err != nil {
   620  		return nil, err
   621  	}
   622  
   623  	chdr, err := UnmarshalChannelHeader(h.ChannelHeader)
   624  	if err != nil {
   625  		return nil, err
   626  	}
   627  	shdr, err := GetSignatureHeader(h.SignatureHeader)
   628  	if err != nil {
   629  		return nil, err
   630  	}
   631  
   632  	return computeProposalBindingInternal(shdr.Nonce, shdr.Creator, chdr.Epoch)
   633  }
   634  
   635  func computeProposalBindingInternal(nonce, creator []byte, epoch uint64) ([]byte, error) {
   636  	epochBytes := make([]byte, 8)
   637  	binary.LittleEndian.PutUint64(epochBytes, epoch)
   638  
   639  	// TODO: add to genesis block the hash function used for the binding computation.
   640  	digest, err := factory.GetDefault().Hash(
   641  		append(append(nonce, creator...), epochBytes...),
   642  		&bccsp.SHA256Opts{})
   643  	if err != nil {
   644  		return nil, err
   645  	}
   646  	return digest, nil
   647  }