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