-
Notifications
You must be signed in to change notification settings - Fork 90
/
types.go
312 lines (259 loc) · 8.68 KB
/
types.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
// Copyright © 2022-2023 Obol Labs Inc. Licensed under the terms of a Business Source License 1.1
package eth2util
import (
"encoding/json"
"strings"
eth2spec "github.com/attestantio/go-eth2-client/spec"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
ssz "github.com/ferranbt/fastssz"
"github.com/obolnetwork/charon/app/errors"
)
// DataVersion defines the spec version of the data in a response.
// The number values match those of go-eth2-client v0.17 and earlier releases.
//
// We should maybe migrate to serialising as strings to aligned with eth2 spec at which
// point this type can be removed in favour of the go-eth2-client type.
type DataVersion string
const (
DataVersionUnknown DataVersion = ""
DataVersionPhase0 DataVersion = "phase0"
DataVersionAltair DataVersion = "altair"
DataVersionBellatrix DataVersion = "bellatrix"
DataVersionCapella DataVersion = "capella"
DataVersionDeneb DataVersion = "deneb"
)
// dataVersionValues maps DataVersion to the integer value used by go-eth2-client pre-v0.18.
var dataVersionValues = map[DataVersion]int{
DataVersionPhase0: 0,
DataVersionAltair: 1,
DataVersionBellatrix: 2,
DataVersionCapella: 3,
DataVersionDeneb: 4,
}
// MarshalJSON marshals the DataVersion as a number equaled to the go-eth2-client
// pre-v0.18 integer value.
func (v DataVersion) MarshalJSON() ([]byte, error) {
val, ok := dataVersionValues[v]
if !ok {
return nil, errors.New("unknown data version")
}
b, err := json.Marshal(val)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal data version")
}
return b, nil
}
// UnmarshalJSON unmarshals the DataVersion from strings or a number equaled to the go-eth2-client
// pre-v0.18 integer value.
func (v *DataVersion) UnmarshalJSON(input []byte) error {
var intVal int
if err := json.Unmarshal(input, &intVal); err != nil {
return errors.Wrap(err, "failed to unmarshal data version")
}
for version, val := range dataVersionValues {
if intVal == val {
*v = version
return nil
}
}
return errors.New("unknown data version")
}
// ToUint64 returns the integer value used by go-eth2-client pre-v0.18.
func (v DataVersion) ToUint64() uint64 {
return uint64(dataVersionValues[v])
}
// ToETH2 returns a eth2spec.DataVersion equivalent to the DataVersion.
func (v DataVersion) ToETH2() eth2spec.DataVersion {
switch v {
case DataVersionPhase0:
return eth2spec.DataVersionPhase0
case DataVersionAltair:
return eth2spec.DataVersionAltair
case DataVersionBellatrix:
return eth2spec.DataVersionBellatrix
case DataVersionCapella:
return eth2spec.DataVersionCapella
case DataVersionDeneb:
return eth2spec.DataVersionDeneb
default:
return eth2spec.DataVersion(0)
}
}
// String returns the string representation of the DataVersion.
func (v DataVersion) String() string {
_, ok := dataVersionValues[v]
if !ok {
return "unknown"
}
return string(v)
}
// DataVersionFromUint64 returns the DataVersion from the integer value used by go-eth2-client pre-v0.18.
func DataVersionFromUint64(val uint64) (DataVersion, error) {
for version, v := range dataVersionValues {
if val == uint64(v) {
return version, nil
}
}
return DataVersionUnknown, errors.New("unknown data version")
}
// DataVersionFromETH2 returns the DataVersion from the eth2spec.DataVersion.
func DataVersionFromETH2(version eth2spec.DataVersion) (DataVersion, error) {
switch version {
case eth2spec.DataVersionPhase0:
return DataVersionPhase0, nil
case eth2spec.DataVersionAltair:
return DataVersionAltair, nil
case eth2spec.DataVersionBellatrix:
return DataVersionBellatrix, nil
case eth2spec.DataVersionCapella:
return DataVersionCapella, nil
case eth2spec.DataVersionDeneb:
return DataVersionDeneb, nil
default:
return DataVersionUnknown, errors.New("unknown data version")
}
}
// BuilderVersion defines the builder spec version.
// The number values match those of go-eth2-client v0.17 and earlier releases.
//
// We should maybe migrate to serialising as strings to aligned with eth2 spec at which
// point this type can be removed in favour of the go-eth2-client type.
type BuilderVersion string
const (
BuilderVersionUnknown BuilderVersion = ""
BuilderVersionV1 BuilderVersion = "v1"
)
// builderVersionValues maps BuilderVersion to the integer value used by go-eth2-client pre-v0.18.
var builderVersionValues = map[BuilderVersion]int{
BuilderVersionV1: 0,
}
// MarshalJSON marshals the BuilderVersion as a number equaled to the go-eth2-client
// pre-v0.18 integer value.
func (v BuilderVersion) MarshalJSON() ([]byte, error) {
val, ok := builderVersionValues[v]
if !ok {
return nil, errors.New("unknown builder version")
}
b, err := json.Marshal(val)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal builder version")
}
return b, nil
}
// UnmarshalJSON unmarshals the BuilderVersion from strings or a number equaled to the go-eth2-client
// pre-v0.18 integer value.
func (v *BuilderVersion) UnmarshalJSON(input []byte) error {
var intVal int
if err := json.Unmarshal(input, &intVal); err != nil {
return errors.Wrap(err, "failed to unmarshal builder version")
}
for version, val := range builderVersionValues {
if intVal == val {
*v = version
return nil
}
}
return errors.New("unknown builder version")
}
// ToUint64 returns the integer value used by go-eth2-client pre-v0.18.
func (v BuilderVersion) ToUint64() uint64 {
return uint64(builderVersionValues[v])
}
// ToETH2 returns a eth2spec.BuilderVersion equivalent to the BuilderVersion.
func (v BuilderVersion) ToETH2() eth2spec.BuilderVersion {
switch v {
case BuilderVersionV1:
return eth2spec.BuilderVersionV1
default:
return eth2spec.BuilderVersion(0)
}
}
// String returns the string representation of the BuilderVersion.
func (v BuilderVersion) String() string {
_, ok := builderVersionValues[v]
if !ok {
return "unknown"
}
return string(v)
}
// BuilderVersionFromUint64 returns the BuilderVersion from the integer value used by go-eth2-client pre-v0.18.
func BuilderVersionFromUint64(val uint64) (BuilderVersion, error) {
for version, v := range builderVersionValues {
if val == uint64(v) {
return version, nil
}
}
return BuilderVersionUnknown, errors.New("unknown builder version")
}
// BuilderVersionFromETH2 returns the BuilderVersion from the eth2spec.BuilderVersion.
func BuilderVersionFromETH2(version eth2spec.BuilderVersion) (BuilderVersion, error) {
switch version {
case eth2spec.BuilderVersionV1:
return BuilderVersionV1, nil
default:
return BuilderVersionUnknown, errors.New("unknown builder version")
}
}
// SignedEpoch represents signature of corresponding epoch.
type SignedEpoch struct {
Epoch eth2p0.Epoch
Signature eth2p0.BLSSignature
}
// GetTree ssz hashes the SignedEpoch object.
func (s SignedEpoch) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(s) //nolint:wrapcheck
}
// HashTreeRoot ssz hashes the SignedEpoch object.
func (s SignedEpoch) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(s) //nolint:wrapcheck
}
// HashTreeRootWith ssz hashes the epoch from SignedEpoch.
func (s SignedEpoch) HashTreeRootWith(hh ssz.HashWalker) error {
indx := hh.Index()
hh.PutUint64(uint64(s.Epoch))
hh.Merkleize(indx)
return nil
}
// MarshalJSON marshals the SignedEpoch as json. It only supports 0xhex signatures.
func (s SignedEpoch) MarshalJSON() ([]byte, error) {
b, err := json.Marshal(signedEpochJSON(s))
if err != nil {
return nil, errors.Wrap(err, "marshal signed epoch signature")
}
return b, nil
}
// UnmarshalJSON unmarshalls both legacy []byte as well as 0xhex signatures.
// Remove support for legacy []byte in v0.19.
func (s *SignedEpoch) UnmarshalJSON(b []byte) error {
var resp legacySignedEpochJSON
if err := json.Unmarshal(b, &resp); err != nil {
return errors.Wrap(err, "unmarshal signed epoch")
}
s.Epoch = resp.Epoch
if strings.HasPrefix(string(resp.Signature), "\"0x") {
if err := json.Unmarshal(resp.Signature, &s.Signature); err != nil {
return errors.Wrap(err, "unmarshal signed epoch signature")
}
return nil
}
var sig []byte
if err := json.Unmarshal(resp.Signature, &sig); err != nil {
return errors.Wrap(err, "unmarshal legacy signed epoch signature")
} else if len(sig) != 96 {
return errors.New("invalid legacy signed epoch signature length")
}
s.Signature = eth2p0.BLSSignature(sig)
return nil
}
// signedEpochJSON supports 0xhex signatures.
type signedEpochJSON struct {
Epoch eth2p0.Epoch `json:"epoch"`
Signature eth2p0.BLSSignature `json:"signature"`
}
// legacySignedEpochJSON supports both legacy []byte and 0xhex signatures
//
// TODO(corver): Remove in v0.19.
type legacySignedEpochJSON struct {
Epoch eth2p0.Epoch `json:"epoch"`
Signature json.RawMessage `json:"signature"`
}