github.com/lzy4123/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: ×tamp.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 }