github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/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/common/crypto"
    31  	"github.com/hyperledger/fabric/common/util"
    32  	"github.com/hyperledger/fabric/core/chaincode/platforms"
    33  	"github.com/hyperledger/fabric/protos/common"
    34  	"github.com/hyperledger/fabric/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.ChaincodeAction, error) {
   395  	env, err := GetEnvelopeFromBlock(envBytes)
   396  	if err != nil {
   397  		return nil, err
   398  	}
   399  
   400  	payl, err := GetPayload(env)
   401  	if err != nil {
   402  		return nil, err
   403  	}
   404  
   405  	tx, err := GetTransaction(payl.Data)
   406  	if err != nil {
   407  		return nil, err
   408  	}
   409  
   410  	if len(tx.Actions) == 0 {
   411  		return nil, fmt.Errorf("At least one TransactionAction is required")
   412  	}
   413  
   414  	_, respPayload, err := GetPayloads(tx.Actions[0])
   415  	return respPayload, err
   416  }
   417  
   418  // CreateProposalFromCIS returns a proposal given a serialized identity and a ChaincodeInvocationSpec
   419  func CreateProposalFromCIS(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte) (*peer.Proposal, string, error) {
   420  	return CreateChaincodeProposal(typ, chainID, cis, creator)
   421  }
   422  
   423  // CreateInstallProposalFromCDS returns a install proposal given a serialized identity and a ChaincodeDeploymentSpec
   424  func CreateInstallProposalFromCDS(ccpack proto.Message, creator []byte) (*peer.Proposal, string, error) {
   425  	return createProposalFromCDS("", ccpack, creator, nil, nil, nil, "install")
   426  }
   427  
   428  // CreateDeployProposalFromCDS returns a deploy proposal given a serialized identity and a ChaincodeDeploymentSpec
   429  func CreateDeployProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error) {
   430  	return createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, "deploy")
   431  }
   432  
   433  // CreateUpgradeProposalFromCDS returns a upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec
   434  func CreateUpgradeProposalFromCDS(chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, string, error) {
   435  	return createProposalFromCDS(chainID, cds, creator, policy, escc, vscc, "upgrade")
   436  }
   437  
   438  // createProposalFromCDS returns a deploy or upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec
   439  func createProposalFromCDS(chainID string, msg proto.Message, creator []byte, policy []byte, escc []byte, vscc []byte, propType string) (*peer.Proposal, string, error) {
   440  	//in the new mode, cds will be nil, "deploy" and "upgrade" are instantiates.
   441  	var ccinp *peer.ChaincodeInput
   442  	var b []byte
   443  	var err error
   444  	if msg != nil {
   445  		b, err = proto.Marshal(msg)
   446  		if err != nil {
   447  			return nil, "", err
   448  		}
   449  	}
   450  	switch propType {
   451  	case "deploy":
   452  		fallthrough
   453  	case "upgrade":
   454  		cds, ok := msg.(*peer.ChaincodeDeploymentSpec)
   455  		if !ok || cds == nil {
   456  			return nil, "", fmt.Errorf("invalid message for creating lifecycle chaincode proposal from")
   457  		}
   458  		ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), []byte(chainID), b, policy, escc, vscc}}
   459  	case "install":
   460  		ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), b}}
   461  	}
   462  
   463  	//wrap the deployment in an invocation spec to lscc...
   464  	lsccSpec := &peer.ChaincodeInvocationSpec{
   465  		ChaincodeSpec: &peer.ChaincodeSpec{
   466  			Type:        peer.ChaincodeSpec_GOLANG,
   467  			ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
   468  			Input:       ccinp}}
   469  
   470  	//...and get the proposal for it
   471  	return CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, lsccSpec, creator)
   472  }
   473  
   474  // ComputeProposalTxID computes TxID as the Hash computed
   475  // over the concatenation of nonce and creator.
   476  func ComputeProposalTxID(nonce, creator []byte) (string, error) {
   477  	// TODO: Get the Hash function to be used from
   478  	// channel configuration
   479  	digest, err := factory.GetDefault().Hash(
   480  		append(nonce, creator...),
   481  		&bccsp.SHA256Opts{})
   482  	if err != nil {
   483  		return "", err
   484  	}
   485  	return hex.EncodeToString(digest), nil
   486  }
   487  
   488  // CheckProposalTxID checks that txid is equal to the Hash computed
   489  // over the concatenation of nonce and creator.
   490  func CheckProposalTxID(txid string, nonce, creator []byte) error {
   491  	computedTxID, err := ComputeProposalTxID(nonce, creator)
   492  	if err != nil {
   493  		return fmt.Errorf("Failed computing target TXID for comparison [%s]", err)
   494  	}
   495  
   496  	if txid != computedTxID {
   497  		return fmt.Errorf("Transaction is not valid. Got [%s], expected [%s]", txid, computedTxID)
   498  	}
   499  
   500  	return nil
   501  }
   502  
   503  // ComputeProposalBinding computes the binding of a proposal
   504  func ComputeProposalBinding(proposal *peer.Proposal) ([]byte, error) {
   505  	if proposal == nil {
   506  		return nil, fmt.Errorf("Porposal is nil")
   507  	}
   508  	if len(proposal.Header) == 0 {
   509  		return nil, fmt.Errorf("Proposal's Header is nil")
   510  	}
   511  
   512  	h, err := GetHeader(proposal.Header)
   513  	if err != nil {
   514  		return nil, err
   515  	}
   516  
   517  	chdr, err := UnmarshalChannelHeader(h.ChannelHeader)
   518  	if err != nil {
   519  		return nil, err
   520  	}
   521  	shdr, err := GetSignatureHeader(h.SignatureHeader)
   522  	if err != nil {
   523  		return nil, err
   524  	}
   525  
   526  	return computeProposalBindingInternal(shdr.Nonce, shdr.Creator, chdr.Epoch)
   527  }
   528  
   529  func computeProposalBindingInternal(nonce, creator []byte, epoch uint64) ([]byte, error) {
   530  	epochBytes := make([]byte, 8)
   531  	binary.LittleEndian.PutUint64(epochBytes, epoch)
   532  
   533  	// TODO: add to genesis block the hash function used for the binding computation.
   534  	return factory.GetDefault().Hash(
   535  		append(append(nonce, creator...), epochBytes...),
   536  		&bccsp.SHA256Opts{})
   537  }