github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/config.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  // Package configtx provides utilities to create and modify a channel configuration transaction.
     8  // Channel transactions contain the configuration data defining members and policies for a
     9  // system or application channel and can be used to either create or modify existing channels.
    10  // Both the creation of a new channel or modification of an existing channel outputs an unsigned
    11  // transaction represented in a protobuf binary format that must be signed by the requisite number
    12  // of members such that the transaction fulfills the channel's modification policy.
    13  //
    14  // See https://hyperledger-fabric.readthedocs.io/en/master/configtx.html#anatomy-of-a-configuration
    15  // for an in-depth description of channel configuration's anatomy.
    16  package configtx
    17  
    18  import (
    19  	"bytes"
    20  	"encoding/hex"
    21  	"errors"
    22  	"fmt"
    23  	"github.com/hellobchain/third_party/algo"
    24  	"strconv"
    25  	"strings"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  	"github.com/golang/protobuf/ptypes"
    29  	"github.com/golang/protobuf/ptypes/timestamp"
    30  	cb "github.com/hyperledger/fabric-protos-go/common"
    31  	mb "github.com/hyperledger/fabric-protos-go/msp"
    32  )
    33  
    34  // Channel is a channel configuration.
    35  type Channel struct {
    36  	Consortium   string
    37  	Application  Application
    38  	Orderer      Orderer
    39  	Consortiums  []Consortium
    40  	Capabilities []string
    41  	Policies     map[string]Policy
    42  	ModPolicy    string
    43  }
    44  
    45  // Policy is an expression used to define rules for access to channels, chaincodes, etc.
    46  type Policy struct {
    47  	Type      string
    48  	Rule      string
    49  	ModPolicy string
    50  }
    51  
    52  // Organization is an organization in the channel configuration.
    53  type Organization struct {
    54  	Name     string
    55  	Policies map[string]Policy
    56  	MSP      MSP
    57  
    58  	// AnchorPeers contains the endpoints of anchor peers for each
    59  	// application organization.
    60  	AnchorPeers      []Address
    61  	OrdererEndpoints []string
    62  	ModPolicy        string
    63  }
    64  
    65  // Address contains the hostname and port for an endpoint.
    66  type Address struct {
    67  	Host string
    68  	Port int
    69  }
    70  
    71  type standardConfigValue struct {
    72  	key   string
    73  	value proto.Message
    74  }
    75  
    76  type standardConfigPolicy struct {
    77  	key   string
    78  	value *cb.Policy
    79  }
    80  
    81  // ConfigTx wraps a config transaction.
    82  type ConfigTx struct {
    83  	// original state of the config
    84  	original *cb.Config
    85  	// modified state of the config
    86  	updated *cb.Config
    87  }
    88  
    89  // New creates a new ConfigTx from a Config protobuf.
    90  // New will panic if given an empty config.
    91  func New(config *cb.Config) ConfigTx {
    92  	return ConfigTx{
    93  		original: config,
    94  		// Clone the base config for processing updates
    95  		updated: proto.Clone(config).(*cb.Config),
    96  	}
    97  }
    98  
    99  // OriginalConfig returns the original unedited config.
   100  func (c *ConfigTx) OriginalConfig() *cb.Config {
   101  	return c.original
   102  }
   103  
   104  // UpdatedConfig returns the modified config.
   105  func (c *ConfigTx) UpdatedConfig() *cb.Config {
   106  	return c.updated
   107  }
   108  
   109  // ComputeMarshaledUpdate computes the ConfigUpdate from a base and modified
   110  // config transaction and returns the marshaled bytes.
   111  func (c *ConfigTx) ComputeMarshaledUpdate(channelID string) ([]byte, error) {
   112  	if channelID == "" {
   113  		return nil, errors.New("channel ID is required")
   114  	}
   115  
   116  	update, err := computeConfigUpdate(c.original, c.updated)
   117  	if err != nil {
   118  		return nil, fmt.Errorf("failed to compute update: %v", err)
   119  	}
   120  
   121  	update.ChannelId = channelID
   122  
   123  	marshaledUpdate, err := proto.Marshal(update)
   124  	if err != nil {
   125  		return nil, fmt.Errorf("marshaling config update: %v", err)
   126  	}
   127  
   128  	return marshaledUpdate, nil
   129  }
   130  
   131  // NewEnvelope creates an envelope with the provided marshaled config update
   132  // and config signatures.
   133  func NewEnvelope(marshaledUpdate []byte, signatures ...*cb.ConfigSignature) (*cb.Envelope, error) {
   134  	configUpdateEnvelope := &cb.ConfigUpdateEnvelope{
   135  		ConfigUpdate: marshaledUpdate,
   136  		Signatures:   signatures,
   137  	}
   138  
   139  	c := &cb.ConfigUpdate{}
   140  	err := proto.Unmarshal(marshaledUpdate, c)
   141  	if err != nil {
   142  		return nil, fmt.Errorf("unmarshaling config update: %v", err)
   143  	}
   144  
   145  	envelope, err := newEnvelope(cb.HeaderType_CONFIG_UPDATE, c.ChannelId, configUpdateEnvelope)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	return envelope, nil
   151  }
   152  
   153  // NewMarshaledCreateChannelTx creates a create channel config update
   154  // transaction using the provided application channel configuration and returns
   155  // the marshaled bytes.
   156  func NewMarshaledCreateChannelTx(channelConfig Channel, channelID string) ([]byte, error) {
   157  	if channelID == "" {
   158  		return nil, errors.New("profile's channel ID is required")
   159  	}
   160  
   161  	ct, err := defaultConfigTemplate(channelConfig)
   162  	if err != nil {
   163  		return nil, fmt.Errorf("creating default config template: %v", err)
   164  	}
   165  
   166  	update, err := newChannelCreateConfigUpdate(channelID, channelConfig, ct)
   167  	if err != nil {
   168  		return nil, fmt.Errorf("creating channel create config update: %v", err)
   169  	}
   170  
   171  	marshaledUpdate, err := proto.Marshal(update)
   172  	if err != nil {
   173  		return nil, fmt.Errorf("marshaling config update: %v", err)
   174  	}
   175  	return marshaledUpdate, nil
   176  }
   177  
   178  // NewSystemChannelGenesisBlock creates a genesis block using the provided
   179  // consortiums and orderer configuration and returns a block.
   180  func NewSystemChannelGenesisBlock(channelConfig Channel, channelID string) (*cb.Block, error) {
   181  	if channelID == "" {
   182  		return nil, errors.New("system channel ID is required")
   183  	}
   184  
   185  	systemChannelGroup, err := newSystemChannelGroup(channelConfig)
   186  	if err != nil {
   187  		return nil, fmt.Errorf("creating system channel group: %v", err)
   188  	}
   189  
   190  	block, err := newGenesisBlock(systemChannelGroup, channelID)
   191  	if err != nil {
   192  		return nil, fmt.Errorf("creating system channel genesis block: %v", err)
   193  	}
   194  
   195  	return block, nil
   196  }
   197  
   198  // NewApplicationChannelGenesisBlock creates a genesis block using the provided
   199  // application and orderer configuration and returns a block.
   200  func NewApplicationChannelGenesisBlock(channelConfig Channel, channelID string) (*cb.Block, error) {
   201  	if channelID == "" {
   202  		return nil, errors.New("application channel ID is required")
   203  	}
   204  
   205  	applicationChannelGroup, err := newApplicationChannelGroup(channelConfig)
   206  	if err != nil {
   207  		return nil, fmt.Errorf("creating application channel group: %v", err)
   208  	}
   209  
   210  	block, err := newGenesisBlock(applicationChannelGroup, channelID)
   211  	if err != nil {
   212  		return nil, fmt.Errorf("creating application channel genesis block: %v", err)
   213  	}
   214  
   215  	return block, nil
   216  }
   217  
   218  // newSystemChannelGroup defines the root of the system channel configuration.
   219  func newSystemChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) {
   220  	channelGroup, err := newChannelGroupWithOrderer(channelConfig)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  
   225  	consortiumsGroup, err := newConsortiumsGroup(channelConfig.Consortiums)
   226  	if err != nil {
   227  		return nil, err
   228  	}
   229  	channelGroup.Groups[ConsortiumsGroupKey] = consortiumsGroup
   230  
   231  	channelGroup.ModPolicy = AdminsPolicyKey
   232  
   233  	if channelConfig.ModPolicy != "" {
   234  		channelGroup.ModPolicy = channelConfig.ModPolicy
   235  	}
   236  
   237  	return channelGroup, nil
   238  }
   239  
   240  // newApplicationChannelGroup defines the root of the application
   241  // channel configuration.
   242  func newApplicationChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) {
   243  	channelGroup, err := newChannelGroupWithOrderer(channelConfig)
   244  	if err != nil {
   245  		return nil, err
   246  	}
   247  
   248  	applicationGroup, err := newApplicationGroup(channelConfig.Application)
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  
   253  	channelGroup.Groups[ApplicationGroupKey] = applicationGroup
   254  
   255  	channelGroup.ModPolicy = AdminsPolicyKey
   256  
   257  	if channelConfig.ModPolicy != "" {
   258  		channelGroup.ModPolicy = channelConfig.ModPolicy
   259  	}
   260  
   261  	return channelGroup, nil
   262  }
   263  
   264  func newChannelGroupWithOrderer(channelConfig Channel) (*cb.ConfigGroup, error) {
   265  	channelGroup := newConfigGroup()
   266  
   267  	err := setPolicies(channelGroup, channelConfig.Policies)
   268  	if err != nil {
   269  		return nil, fmt.Errorf("setting channel policies: %v", err)
   270  	}
   271  
   272  	err = setValue(channelGroup, hashingAlgorithmValue(), AdminsPolicyKey)
   273  	if err != nil {
   274  		return nil, err
   275  	}
   276  
   277  	err = setValue(channelGroup, blockDataHashingStructureValue(), AdminsPolicyKey)
   278  	if err != nil {
   279  		return nil, err
   280  	}
   281  
   282  	if len(channelConfig.Capabilities) == 0 {
   283  		return nil, errors.New("capabilities is not defined in channel config")
   284  	}
   285  
   286  	err = setValue(channelGroup, capabilitiesValue(channelConfig.Capabilities), AdminsPolicyKey)
   287  	if err != nil {
   288  		return nil, err
   289  	}
   290  
   291  	ordererGroup, err := newOrdererGroup(channelConfig.Orderer)
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  	channelGroup.Groups[OrdererGroupKey] = ordererGroup
   296  
   297  	return channelGroup, nil
   298  }
   299  
   300  // newGenesisBlock generates a genesis block from the config group and
   301  // channel ID. The block number is always zero.
   302  func newGenesisBlock(cg *cb.ConfigGroup, channelID string) (*cb.Block, error) {
   303  	payloadChannelHeader := channelHeader(cb.HeaderType_CONFIG, msgVersion, channelID, epoch)
   304  	nonce, err := newNonce()
   305  	if err != nil {
   306  		return nil, fmt.Errorf("creating nonce: %v", err)
   307  	}
   308  	payloadSignatureHeader := &cb.SignatureHeader{Creator: nil, Nonce: nonce}
   309  	payloadChannelHeader.TxId = computeTxID(payloadSignatureHeader.Nonce, payloadSignatureHeader.Creator)
   310  	payloadHeader, err := payloadHeader(payloadChannelHeader, payloadSignatureHeader)
   311  	if err != nil {
   312  		return nil, fmt.Errorf("construct payload header: %v", err)
   313  	}
   314  	payloadData, err := proto.Marshal(&cb.ConfigEnvelope{Config: &cb.Config{ChannelGroup: cg}})
   315  	if err != nil {
   316  		return nil, fmt.Errorf("marshaling payload data: %v", err)
   317  	}
   318  	payload := &cb.Payload{Header: payloadHeader, Data: payloadData}
   319  	envelopePayload, err := proto.Marshal(payload)
   320  	if err != nil {
   321  		return nil, fmt.Errorf("marshaling envelope payload: %v", err)
   322  	}
   323  	envelope := &cb.Envelope{Payload: envelopePayload, Signature: nil}
   324  	blockData, err := proto.Marshal(envelope)
   325  	if err != nil {
   326  		return nil, fmt.Errorf("marshaling envelope: %v", err)
   327  	}
   328  
   329  	block := newBlock(0, nil)
   330  	block.Data = &cb.BlockData{Data: [][]byte{blockData}}
   331  	block.Header.DataHash = blockDataHash(block.Data)
   332  
   333  	lastConfigValue, err := proto.Marshal(&cb.LastConfig{Index: 0})
   334  	if err != nil {
   335  		return nil, fmt.Errorf("marshaling metadata last config value: %v", err)
   336  	}
   337  	lastConfigMetadata, err := proto.Marshal(&cb.Metadata{Value: lastConfigValue})
   338  	if err != nil {
   339  		return nil, fmt.Errorf("marshaling metadata last config: %v", err)
   340  	}
   341  	block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = lastConfigMetadata
   342  
   343  	signatureValue, err := proto.Marshal(&cb.OrdererBlockMetadata{
   344  		LastConfig: &cb.LastConfig{Index: 0},
   345  	})
   346  	if err != nil {
   347  		return nil, fmt.Errorf("marshaling metadata signature value: %v", err)
   348  	}
   349  	signatureMetadata, err := proto.Marshal(&cb.Metadata{Value: signatureValue})
   350  	if err != nil {
   351  		return nil, fmt.Errorf("marshaling metadata signature: %v", err)
   352  	}
   353  	block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES] = signatureMetadata
   354  
   355  	return block, nil
   356  }
   357  
   358  // setValue sets the value as ConfigValue in the ConfigGroup.
   359  func setValue(cg *cb.ConfigGroup, value *standardConfigValue, modPolicy string) error {
   360  	v, err := proto.Marshal(value.value)
   361  	if err != nil {
   362  		return fmt.Errorf("marshaling standard config value '%s': %v", value.key, err)
   363  	}
   364  
   365  	if cg.Values == nil {
   366  		cg.Values = map[string]*cb.ConfigValue{}
   367  	}
   368  
   369  	cg.Values[value.key] = &cb.ConfigValue{
   370  		Value:     v,
   371  		ModPolicy: modPolicy,
   372  	}
   373  
   374  	return nil
   375  }
   376  
   377  // implicitMetaFromString parses a *cb.ImplicitMetaPolicy from an input string.
   378  func implicitMetaFromString(input string) (*cb.ImplicitMetaPolicy, error) {
   379  	args := strings.Split(input, " ")
   380  	if len(args) != 2 {
   381  		return nil, fmt.Errorf("expected two space separated tokens, but got %d", len(args))
   382  	}
   383  
   384  	res := &cb.ImplicitMetaPolicy{
   385  		SubPolicy: args[1],
   386  	}
   387  
   388  	switch args[0] {
   389  	case cb.ImplicitMetaPolicy_ANY.String():
   390  		res.Rule = cb.ImplicitMetaPolicy_ANY
   391  	case cb.ImplicitMetaPolicy_ALL.String():
   392  		res.Rule = cb.ImplicitMetaPolicy_ALL
   393  	case cb.ImplicitMetaPolicy_MAJORITY.String():
   394  		res.Rule = cb.ImplicitMetaPolicy_MAJORITY
   395  	default:
   396  		return nil, fmt.Errorf("unknown rule type '%s', expected ALL, ANY, or MAJORITY", args[0])
   397  	}
   398  
   399  	return res, nil
   400  }
   401  
   402  // mspValue returns the config definition for an MSP.
   403  // It is a value for the /Channel/Orderer/*, /Channel/Application/*, and /Channel/Consortiums/*/*/* groups.
   404  func mspValue(mspDef *mb.MSPConfig) *standardConfigValue {
   405  	return &standardConfigValue{
   406  		key:   MSPKey,
   407  		value: mspDef,
   408  	}
   409  }
   410  
   411  // defaultConfigTemplate generates a config template based on the assumption that
   412  // the input profile is a channel creation template and no system channel context
   413  // is available.
   414  func defaultConfigTemplate(channelConfig Channel) (*cb.ConfigGroup, error) {
   415  	channelGroup, err := newChannelGroup(channelConfig)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  
   420  	if _, ok := channelGroup.Groups[ApplicationGroupKey]; !ok {
   421  		return nil, errors.New("channel template config must contain an application section")
   422  	}
   423  
   424  	channelGroup.Groups[ApplicationGroupKey].Values = nil
   425  	channelGroup.Groups[ApplicationGroupKey].Policies = nil
   426  
   427  	return channelGroup, nil
   428  }
   429  
   430  // newChannelGroup defines the root of the channel configuration.
   431  func newChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) {
   432  	channelGroup := newConfigGroup()
   433  
   434  	if channelConfig.Consortium == "" {
   435  		return nil, errors.New("consortium is not defined in channel config")
   436  	}
   437  
   438  	err := setValue(channelGroup, consortiumValue(channelConfig.Consortium), "")
   439  	if err != nil {
   440  		return nil, err
   441  	}
   442  
   443  	channelGroup.Groups[ApplicationGroupKey], err = newApplicationGroupTemplate(channelConfig.Application)
   444  	if err != nil {
   445  		return nil, fmt.Errorf("failed to create application group: %v", err)
   446  	}
   447  
   448  	channelGroup.ModPolicy = AdminsPolicyKey
   449  
   450  	if channelConfig.ModPolicy != "" {
   451  		channelGroup.ModPolicy = channelConfig.ModPolicy
   452  	}
   453  
   454  	return channelGroup, nil
   455  }
   456  
   457  // newChannelCreateConfigUpdate generates a ConfigUpdate which can be sent to the orderer to create a new channel.
   458  // Optionally, the channel group of the ordering system channel may be passed in, and the resulting ConfigUpdate
   459  // will extract the appropriate versions from this file.
   460  func newChannelCreateConfigUpdate(channelID string, channelConfig Channel, templateConfig *cb.ConfigGroup) (*cb.ConfigUpdate, error) {
   461  	newChannelGroup, err := newChannelGroup(channelConfig)
   462  	if err != nil {
   463  		return nil, err
   464  	}
   465  
   466  	updt, err := computeConfigUpdate(&cb.Config{ChannelGroup: templateConfig}, &cb.Config{ChannelGroup: newChannelGroup})
   467  	if err != nil {
   468  		return nil, fmt.Errorf("computing update: %v", err)
   469  	}
   470  
   471  	wsValue, err := proto.Marshal(&cb.Consortium{
   472  		Name: channelConfig.Consortium,
   473  	})
   474  	if err != nil {
   475  		return nil, fmt.Errorf("marshaling consortium: %v", err)
   476  	}
   477  
   478  	// Add the consortium name to create the channel for into the write set as required
   479  	updt.ChannelId = channelID
   480  	updt.ReadSet.Values[ConsortiumKey] = &cb.ConfigValue{Version: 0}
   481  	updt.WriteSet.Values[ConsortiumKey] = &cb.ConfigValue{
   482  		Version: 0,
   483  		Value:   wsValue,
   484  	}
   485  
   486  	return updt, nil
   487  }
   488  
   489  // newConfigGroup creates an empty *cb.ConfigGroup.
   490  func newConfigGroup() *cb.ConfigGroup {
   491  	return &cb.ConfigGroup{
   492  		Groups:   map[string]*cb.ConfigGroup{},
   493  		Values:   map[string]*cb.ConfigValue{},
   494  		Policies: map[string]*cb.ConfigPolicy{},
   495  	}
   496  }
   497  
   498  // newEnvelope creates an unsigned envelope of the desired type containing
   499  // a payload Header and the marshaled proto message as the payload Data.
   500  func newEnvelope(
   501  	txType cb.HeaderType,
   502  	channelID string,
   503  	dataMsg proto.Message,
   504  ) (*cb.Envelope, error) {
   505  	payloadChannelHeader := channelHeader(txType, msgVersion, channelID, epoch)
   506  	payloadSignatureHeader := &cb.SignatureHeader{}
   507  
   508  	data, err := proto.Marshal(dataMsg)
   509  	if err != nil {
   510  		return nil, fmt.Errorf("marshaling envelope data: %v", err)
   511  	}
   512  
   513  	payloadHeader, err := payloadHeader(payloadChannelHeader, payloadSignatureHeader)
   514  	if err != nil {
   515  		return nil, fmt.Errorf("making payload header: %v", err)
   516  	}
   517  
   518  	paylBytes, err := proto.Marshal(
   519  		&cb.Payload{
   520  			Header: payloadHeader,
   521  			Data:   data,
   522  		},
   523  	)
   524  	if err != nil {
   525  		return nil, fmt.Errorf("marshaling payload: %v", err)
   526  	}
   527  
   528  	env := &cb.Envelope{
   529  		Payload: paylBytes,
   530  	}
   531  
   532  	return env, nil
   533  }
   534  
   535  // channelHeader creates a ChannelHeader.
   536  func channelHeader(headerType cb.HeaderType, version int32, channelID string, epoch uint64) *cb.ChannelHeader {
   537  	return &cb.ChannelHeader{
   538  		Type:    int32(headerType),
   539  		Version: version,
   540  		Timestamp: &timestamp.Timestamp{
   541  			Seconds: ptypes.TimestampNow().GetSeconds(),
   542  		},
   543  		ChannelId: channelID,
   544  		Epoch:     epoch,
   545  	}
   546  }
   547  
   548  // payloadHeader creates a Payload Header.
   549  func payloadHeader(ch *cb.ChannelHeader, sh *cb.SignatureHeader) (*cb.Header, error) {
   550  	channelHeader, err := proto.Marshal(ch)
   551  	if err != nil {
   552  		return nil, fmt.Errorf("marshaling channel header: %v", err)
   553  	}
   554  
   555  	signatureHeader, err := proto.Marshal(sh)
   556  	if err != nil {
   557  		return nil, fmt.Errorf("marshaling signature header: %v", err)
   558  	}
   559  
   560  	return &cb.Header{
   561  		ChannelHeader:   channelHeader,
   562  		SignatureHeader: signatureHeader,
   563  	}, nil
   564  }
   565  
   566  // concatenateBytes combines multiple arrays of bytes, for signatures or digests
   567  // over multiple fields.
   568  func concatenateBytes(data ...[]byte) []byte {
   569  	res := []byte{}
   570  	for i := range data {
   571  		res = append(res, data[i]...)
   572  	}
   573  
   574  	return res
   575  }
   576  
   577  // unmarshalConfigValueAtKey unmarshals the value for the specified key in a config group
   578  // into the designated proto message.
   579  func unmarshalConfigValueAtKey(group *cb.ConfigGroup, key string, msg proto.Message) error {
   580  	valueAtKey, ok := group.Values[key]
   581  	if !ok {
   582  		return fmt.Errorf("config does not contain value for %s", key)
   583  	}
   584  
   585  	err := proto.Unmarshal(valueAtKey.Value, msg)
   586  	if err != nil {
   587  		return fmt.Errorf("unmarshaling %s: %v", key, err)
   588  	}
   589  
   590  	return nil
   591  }
   592  
   593  func parseAddress(address string) (string, int, error) {
   594  	hostport := strings.Split(address, ":")
   595  	if len(hostport) != 2 {
   596  		return "", 0, fmt.Errorf("unable to parse host and port from %s", address)
   597  	}
   598  
   599  	host := hostport[0]
   600  	port := hostport[1]
   601  
   602  	portNum, err := strconv.Atoi(port)
   603  	if err != nil {
   604  		return "", 0, err
   605  	}
   606  
   607  	return host, portNum, nil
   608  }
   609  
   610  // newBlock constructs a block with no data and no metadata.
   611  func newBlock(seqNum uint64, previousHash []byte) *cb.Block {
   612  	block := &cb.Block{}
   613  	block.Header = &cb.BlockHeader{}
   614  	block.Header.Number = seqNum
   615  	block.Header.PreviousHash = previousHash
   616  	block.Header.DataHash = []byte{}
   617  	block.Data = &cb.BlockData{}
   618  
   619  	var metadataContents [][]byte
   620  	for i := 0; i < len(cb.BlockMetadataIndex_name); i++ {
   621  		metadataContents = append(metadataContents, []byte{})
   622  	}
   623  	block.Metadata = &cb.BlockMetadata{Metadata: metadataContents}
   624  
   625  	return block
   626  }
   627  
   628  // computeTxID computes TxID as the Hash computed
   629  // over the concatenation of nonce and creator.
   630  func computeTxID(nonce, creator []byte) string {
   631  	hasher := algo.GetDefaultHash().New()
   632  	hasher.Write(nonce)
   633  	hasher.Write(creator)
   634  	return hex.EncodeToString(hasher.Sum(nil))
   635  }
   636  
   637  // blockDataHash computes block data as the Hash
   638  func blockDataHash(b *cb.BlockData) []byte {
   639  	hasher := algo.GetDefaultHash().New()
   640  	hasher.Write(bytes.Join(b.Data, nil))
   641  	sum := hasher.Sum(nil)
   642  	return sum[:]
   643  }