github.com/Hnampk/fabric@v2.1.1+incompatible/protoutil/commonutils.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package protoutil
     8  
     9  import (
    10  	"crypto/rand"
    11  	"fmt"
    12  	"time"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	"github.com/golang/protobuf/ptypes/timestamp"
    16  	cb "github.com/hyperledger/fabric-protos-go/common"
    17  	"github.com/hyperledger/fabric/internal/pkg/identity"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  // MarshalOrPanic serializes a protobuf message and panics if this
    22  // operation fails
    23  func MarshalOrPanic(pb proto.Message) []byte {
    24  	data, err := proto.Marshal(pb)
    25  	if err != nil {
    26  		panic(err)
    27  	}
    28  	return data
    29  }
    30  
    31  // Marshal serializes a protobuf message.
    32  func Marshal(pb proto.Message) ([]byte, error) {
    33  	return proto.Marshal(pb)
    34  }
    35  
    36  // CreateNonceOrPanic generates a nonce using the common/crypto package
    37  // and panics if this operation fails.
    38  func CreateNonceOrPanic() []byte {
    39  	nonce, err := CreateNonce()
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  	return nonce
    44  }
    45  
    46  // CreateNonce generates a nonce using the common/crypto package.
    47  func CreateNonce() ([]byte, error) {
    48  	nonce, err := getRandomNonce()
    49  	return nonce, errors.WithMessage(err, "error generating random nonce")
    50  }
    51  
    52  // UnmarshalEnvelopeOfType unmarshals an envelope of the specified type,
    53  // including unmarshaling the payload data
    54  func UnmarshalEnvelopeOfType(envelope *cb.Envelope, headerType cb.HeaderType, message proto.Message) (*cb.ChannelHeader, error) {
    55  	payload, err := UnmarshalPayload(envelope.Payload)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	if payload.Header == nil {
    61  		return nil, errors.New("envelope must have a Header")
    62  	}
    63  
    64  	chdr, err := UnmarshalChannelHeader(payload.Header.ChannelHeader)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	if chdr.Type != int32(headerType) {
    70  		return nil, errors.Errorf("invalid type %s, expected %s", cb.HeaderType(chdr.Type), headerType)
    71  	}
    72  
    73  	err = proto.Unmarshal(payload.Data, message)
    74  	err = errors.Wrapf(err, "error unmarshaling message for type %s", headerType)
    75  	return chdr, err
    76  }
    77  
    78  // ExtractEnvelopeOrPanic retrieves the requested envelope from a given block
    79  // and unmarshals it -- it panics if either of these operations fail
    80  func ExtractEnvelopeOrPanic(block *cb.Block, index int) *cb.Envelope {
    81  	envelope, err := ExtractEnvelope(block, index)
    82  	if err != nil {
    83  		panic(err)
    84  	}
    85  	return envelope
    86  }
    87  
    88  // ExtractEnvelope retrieves the requested envelope from a given block and
    89  // unmarshals it
    90  func ExtractEnvelope(block *cb.Block, index int) (*cb.Envelope, error) {
    91  	if block.Data == nil {
    92  		return nil, errors.New("block data is nil")
    93  	}
    94  
    95  	envelopeCount := len(block.Data.Data)
    96  	if index < 0 || index >= envelopeCount {
    97  		return nil, errors.New("envelope index out of bounds")
    98  	}
    99  	marshaledEnvelope := block.Data.Data[index]
   100  	envelope, err := GetEnvelopeFromBlock(marshaledEnvelope)
   101  	err = errors.WithMessagef(err, "block data does not carry an envelope at index %d", index)
   102  	return envelope, err
   103  }
   104  
   105  // MakeChannelHeader creates a ChannelHeader.
   106  func MakeChannelHeader(headerType cb.HeaderType, version int32, chainID string, epoch uint64) *cb.ChannelHeader {
   107  	return &cb.ChannelHeader{
   108  		Type:    int32(headerType),
   109  		Version: version,
   110  		Timestamp: &timestamp.Timestamp{
   111  			Seconds: time.Now().Unix(),
   112  			Nanos:   0,
   113  		},
   114  		ChannelId: chainID,
   115  		Epoch:     epoch,
   116  	}
   117  }
   118  
   119  // MakeSignatureHeader creates a SignatureHeader.
   120  func MakeSignatureHeader(serializedCreatorCertChain []byte, nonce []byte) *cb.SignatureHeader {
   121  	return &cb.SignatureHeader{
   122  		Creator: serializedCreatorCertChain,
   123  		Nonce:   nonce,
   124  	}
   125  }
   126  
   127  // SetTxID generates a transaction id based on the provided signature header
   128  // and sets the TxId field in the channel header
   129  func SetTxID(channelHeader *cb.ChannelHeader, signatureHeader *cb.SignatureHeader) {
   130  	channelHeader.TxId = ComputeTxID(
   131  		signatureHeader.Nonce,
   132  		signatureHeader.Creator,
   133  	)
   134  }
   135  
   136  // MakePayloadHeader creates a Payload Header.
   137  func MakePayloadHeader(ch *cb.ChannelHeader, sh *cb.SignatureHeader) *cb.Header {
   138  	return &cb.Header{
   139  		ChannelHeader:   MarshalOrPanic(ch),
   140  		SignatureHeader: MarshalOrPanic(sh),
   141  	}
   142  }
   143  
   144  // NewSignatureHeader returns a SignatureHeader with a valid nonce.
   145  func NewSignatureHeader(id identity.Serializer) (*cb.SignatureHeader, error) {
   146  	creator, err := id.Serialize()
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	nonce, err := CreateNonce()
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  
   155  	return &cb.SignatureHeader{
   156  		Creator: creator,
   157  		Nonce:   nonce,
   158  	}, nil
   159  }
   160  
   161  // NewSignatureHeaderOrPanic returns a signature header and panics on error.
   162  func NewSignatureHeaderOrPanic(id identity.Serializer) *cb.SignatureHeader {
   163  	if id == nil {
   164  		panic(errors.New("invalid signer. cannot be nil"))
   165  	}
   166  
   167  	signatureHeader, err := NewSignatureHeader(id)
   168  	if err != nil {
   169  		panic(fmt.Errorf("failed generating a new SignatureHeader: %s", err))
   170  	}
   171  
   172  	return signatureHeader
   173  }
   174  
   175  // SignOrPanic signs a message and panics on error.
   176  func SignOrPanic(signer identity.Signer, msg []byte) []byte {
   177  	if signer == nil {
   178  		panic(errors.New("invalid signer. cannot be nil"))
   179  	}
   180  
   181  	sigma, err := signer.Sign(msg)
   182  	if err != nil {
   183  		panic(fmt.Errorf("failed generating signature: %s", err))
   184  	}
   185  	return sigma
   186  }
   187  
   188  // IsConfigBlock validates whenever given block contains configuration
   189  // update transaction
   190  func IsConfigBlock(block *cb.Block) bool {
   191  	envelope, err := ExtractEnvelope(block, 0)
   192  	if err != nil {
   193  		return false
   194  	}
   195  
   196  	payload, err := UnmarshalPayload(envelope.Payload)
   197  	if err != nil {
   198  		return false
   199  	}
   200  
   201  	if payload.Header == nil {
   202  		return false
   203  	}
   204  
   205  	hdr, err := UnmarshalChannelHeader(payload.Header.ChannelHeader)
   206  	if err != nil {
   207  		return false
   208  	}
   209  
   210  	return cb.HeaderType(hdr.Type) == cb.HeaderType_CONFIG || cb.HeaderType(hdr.Type) == cb.HeaderType_ORDERER_TRANSACTION
   211  }
   212  
   213  // ChannelHeader returns the *cb.ChannelHeader for a given *cb.Envelope.
   214  func ChannelHeader(env *cb.Envelope) (*cb.ChannelHeader, error) {
   215  	envPayload, err := UnmarshalPayload(env.Payload)
   216  	if err != nil {
   217  		return nil, err
   218  	}
   219  
   220  	if envPayload.Header == nil {
   221  		return nil, errors.New("header not set")
   222  	}
   223  
   224  	if envPayload.Header.ChannelHeader == nil {
   225  		return nil, errors.New("channel header not set")
   226  	}
   227  
   228  	chdr, err := UnmarshalChannelHeader(envPayload.Header.ChannelHeader)
   229  	if err != nil {
   230  		return nil, errors.WithMessage(err, "error unmarshaling channel header")
   231  	}
   232  
   233  	return chdr, nil
   234  }
   235  
   236  // ChannelID returns the Channel ID for a given *cb.Envelope.
   237  func ChannelID(env *cb.Envelope) (string, error) {
   238  	chdr, err := ChannelHeader(env)
   239  	if err != nil {
   240  		return "", errors.WithMessage(err, "error retrieving channel header")
   241  	}
   242  
   243  	return chdr.ChannelId, nil
   244  }
   245  
   246  // EnvelopeToConfigUpdate is used to extract a ConfigUpdateEnvelope from an envelope of
   247  // type CONFIG_UPDATE
   248  func EnvelopeToConfigUpdate(configtx *cb.Envelope) (*cb.ConfigUpdateEnvelope, error) {
   249  	configUpdateEnv := &cb.ConfigUpdateEnvelope{}
   250  	_, err := UnmarshalEnvelopeOfType(configtx, cb.HeaderType_CONFIG_UPDATE, configUpdateEnv)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	return configUpdateEnv, nil
   255  }
   256  
   257  func getRandomNonce() ([]byte, error) {
   258  	key := make([]byte, 24)
   259  
   260  	_, err := rand.Read(key)
   261  	if err != nil {
   262  		return nil, errors.Wrap(err, "error getting random bytes")
   263  	}
   264  	return key, nil
   265  }