/
commonutils.go
137 lines (115 loc) · 3.38 KB
/
commonutils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package protoutil
import (
"crypto/rand"
"time"
"github.com/golang/protobuf/ptypes/timestamp"
cb "github.com/hyperledger/fabric-protos-go-apiv2/common"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
)
// MarshalOrPanic serializes a protobuf message and panics if this
// operation fails
func MarshalOrPanic(pb proto.Message) []byte {
data, err := proto.Marshal(pb)
if err != nil {
panic(err)
}
return data
}
// Marshal serializes a protobuf message.
func Marshal(pb proto.Message) ([]byte, error) {
return proto.Marshal(pb)
}
// CreateNonce generates a nonce using the common/crypto package.
func CreateNonce() ([]byte, error) {
nonce, err := getRandomNonce()
return nonce, errors.WithMessage(err, "error generating random nonce")
}
// ExtractEnvelope retrieves the requested envelope from a given block and
// unmarshals it
func ExtractEnvelope(block *cb.Block, index int) (*cb.Envelope, error) {
if block.Data == nil {
return nil, errors.New("block data is nil")
}
envelopeCount := len(block.Data.Data)
if index < 0 || index >= envelopeCount {
return nil, errors.New("envelope index out of bounds")
}
marshaledEnvelope := block.Data.Data[index]
envelope, err := GetEnvelopeFromBlock(marshaledEnvelope)
err = errors.WithMessagef(err, "block data does not carry an envelope at index %d", index)
return envelope, err
}
// MakeChannelHeader creates a ChannelHeader.
func MakeChannelHeader(headerType cb.HeaderType, version int32, chainID string, epoch uint64) *cb.ChannelHeader {
return &cb.ChannelHeader{
Type: int32(headerType),
Version: version,
Timestamp: ×tamp.Timestamp{
Seconds: time.Now().Unix(),
Nanos: 0,
},
ChannelId: chainID,
Epoch: epoch,
}
}
// MakePayloadHeader creates a Payload Header.
func MakePayloadHeader(ch *cb.ChannelHeader, sh *cb.SignatureHeader) *cb.Header {
return &cb.Header{
ChannelHeader: MarshalOrPanic(ch),
SignatureHeader: MarshalOrPanic(sh),
}
}
// NewSignatureHeader returns a SignatureHeader with a valid nonce.
func NewSignatureHeader(id Signer) (*cb.SignatureHeader, error) {
creator, err := id.Serialize()
if err != nil {
return nil, err
}
nonce, err := CreateNonce()
if err != nil {
return nil, err
}
return &cb.SignatureHeader{
Creator: creator,
Nonce: nonce,
}, nil
}
// ChannelHeader returns the *cb.ChannelHeader for a given *cb.Envelope.
func ChannelHeader(env *cb.Envelope) (*cb.ChannelHeader, error) {
envPayload, err := UnmarshalPayload(env.Payload)
if err != nil {
return nil, err
}
if envPayload.Header == nil {
return nil, errors.New("header not set")
}
if envPayload.Header.ChannelHeader == nil {
return nil, errors.New("channel header not set")
}
chdr, err := UnmarshalChannelHeader(envPayload.Header.ChannelHeader)
if err != nil {
return nil, errors.WithMessage(err, "error unmarshaling channel header")
}
return chdr, nil
}
// ChannelID returns the Channel ID for a given *cb.Envelope.
func ChannelID(env *cb.Envelope) (string, error) {
chdr, err := ChannelHeader(env)
if err != nil {
return "", errors.WithMessage(err, "error retrieving channel header")
}
return chdr.ChannelId, nil
}
func getRandomNonce() ([]byte, error) {
key := make([]byte, 24)
_, err := rand.Read(key)
if err != nil {
return nil, errors.Wrap(err, "error getting random bytes")
}
return key, nil
}