1
1
use crate :: {
2
2
types:: content_key:: { error:: ContentKeyError , overlay:: OverlayContentKey } ,
3
- utils:: bytes:: { hex_decode , hex_encode_compact} ,
3
+ utils:: bytes:: hex_encode_compact,
4
4
} ;
5
- use serde:: { de , Deserialize , Deserializer , Serialize , Serializer } ;
5
+ use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
6
6
use sha2:: { Digest , Sha256 } ;
7
7
use ssz:: { Decode , DecodeError , Encode } ;
8
8
use ssz_derive:: { Decode , Encode } ;
9
9
use std:: fmt;
10
10
11
11
// Prefixes for the different types of beacon content keys:
12
- // https://github.com/ethereum/portal-network-specs/blob/72327da43c7a199ba2735344ef98f9121aef2f68 /beacon-chain/beacon-network.md
12
+ // https://github.com/ethereum/portal-network-specs/blob/638aca50c913a749d0d762264d9a4ac72f1a9966 /beacon-chain/beacon-network.md
13
13
pub const LIGHT_CLIENT_BOOTSTRAP_KEY_PREFIX : u8 = 0x10 ;
14
14
pub const LIGHT_CLIENT_UPDATES_BY_RANGE_KEY_PREFIX : u8 = 0x11 ;
15
15
pub const LIGHT_CLIENT_FINALITY_UPDATE_KEY_PREFIX : u8 = 0x12 ;
@@ -24,83 +24,6 @@ pub enum BeaconContentKey {
24
24
LightClientOptimisticUpdate ( LightClientOptimisticUpdateKey ) ,
25
25
}
26
26
27
- impl Encode for BeaconContentKey {
28
- fn is_ssz_fixed_len ( ) -> bool {
29
- false
30
- }
31
-
32
- fn ssz_append ( & self , buf : & mut Vec < u8 > ) {
33
- let bytes = self . to_bytes ( ) ;
34
- buf. extend_from_slice ( & bytes) ;
35
- }
36
-
37
- fn ssz_bytes_len ( & self ) -> usize {
38
- self . to_bytes ( ) . len ( )
39
- }
40
- }
41
-
42
- impl Decode for BeaconContentKey {
43
- fn is_ssz_fixed_len ( ) -> bool {
44
- false
45
- }
46
-
47
- fn from_ssz_bytes ( bytes : & [ u8 ] ) -> Result < Self , DecodeError > {
48
- match bytes[ 0 ] {
49
- LIGHT_CLIENT_BOOTSTRAP_KEY_PREFIX => {
50
- let block_hash = <[ u8 ; 32 ] >:: try_from ( & bytes[ 1 ..33 ] ) . map_err ( |err| {
51
- DecodeError :: BytesInvalid ( format ! (
52
- "Failed to decode LightClientBootstrapKey: {err:?}"
53
- ) )
54
- } ) ?;
55
- Ok ( Self :: LightClientBootstrap ( LightClientBootstrapKey {
56
- block_hash,
57
- } ) )
58
- }
59
- LIGHT_CLIENT_UPDATES_BY_RANGE_KEY_PREFIX => {
60
- let start_period = u64:: from_ssz_bytes ( & bytes[ 1 ..9 ] ) . map_err ( |err| {
61
- DecodeError :: BytesInvalid ( format ! (
62
- "Failed to decode LightClientUpdatesByRangeKey: {err:?}"
63
- ) )
64
- } ) ?;
65
- let count = u64:: from_ssz_bytes ( & bytes[ 9 ..17 ] ) . map_err ( |err| {
66
- DecodeError :: BytesInvalid ( format ! (
67
- "Failed to decode LightClientUpdatesByRangeKey: {err:?}"
68
- ) )
69
- } ) ?;
70
- Ok ( Self :: LightClientUpdatesByRange (
71
- LightClientUpdatesByRangeKey {
72
- start_period,
73
- count,
74
- } ,
75
- ) )
76
- }
77
- LIGHT_CLIENT_FINALITY_UPDATE_KEY_PREFIX => {
78
- let finalized_slot = u64:: from_ssz_bytes ( & bytes[ 1 ..9 ] ) . map_err ( |err| {
79
- DecodeError :: BytesInvalid ( format ! (
80
- "Failed to decode LightClientFinalityUpdateKey: {err:?}" ,
81
- ) )
82
- } ) ?;
83
- Ok ( Self :: LightClientFinalityUpdate (
84
- LightClientFinalityUpdateKey :: new ( finalized_slot) ,
85
- ) )
86
- }
87
- LIGHT_CLIENT_OPTIMISTIC_UPDATE_KEY_PREFIX => {
88
- let signature_slot = u64:: from_ssz_bytes ( & bytes[ 1 ..9 ] ) . map_err ( |err| {
89
- DecodeError :: BytesInvalid ( format ! (
90
- "Failed to decode LightClientOptimisticUpdateKey: {err:?}" ,
91
- ) )
92
- } ) ?;
93
- Ok ( Self :: LightClientOptimisticUpdate (
94
- LightClientOptimisticUpdateKey :: new ( signature_slot) ,
95
- ) )
96
- }
97
- _ => Err ( DecodeError :: BytesInvalid ( format ! (
98
- "Failed to decode BeaconContentKey, Unexpected union selector byte: {bytes:?}" ,
99
- ) ) ) ,
100
- }
101
- }
102
- }
103
-
104
27
/// Key used to identify a light client bootstrap.
105
28
#[ derive( Clone , Debug , Decode , Encode , Eq , PartialEq ) ]
106
29
pub struct LightClientBootstrapKey {
@@ -145,22 +68,50 @@ impl LightClientOptimisticUpdateKey {
145
68
146
69
impl From < & BeaconContentKey > for Vec < u8 > {
147
70
fn from ( val : & BeaconContentKey ) -> Self {
148
- val. as_ssz_bytes ( )
71
+ val. to_bytes ( )
149
72
}
150
73
}
151
74
152
75
impl From < BeaconContentKey > for Vec < u8 > {
153
76
fn from ( val : BeaconContentKey ) -> Self {
154
- val. as_ssz_bytes ( )
77
+ val. to_bytes ( )
155
78
}
156
79
}
157
80
158
81
impl TryFrom < Vec < u8 > > for BeaconContentKey {
159
82
type Error = ContentKeyError ;
160
83
161
84
fn try_from ( value : Vec < u8 > ) -> Result < Self , Self :: Error > {
162
- BeaconContentKey :: from_ssz_bytes ( & value)
163
- . map_err ( |e| ContentKeyError :: from_decode_error ( e, value) )
85
+ let Some ( ( & selector, key) ) = value. split_first ( ) else {
86
+ return Err ( ContentKeyError :: InvalidLength {
87
+ received : value. len ( ) ,
88
+ expected : 1 ,
89
+ } ) ;
90
+ } ;
91
+ match selector {
92
+ LIGHT_CLIENT_BOOTSTRAP_KEY_PREFIX => LightClientBootstrapKey :: from_ssz_bytes ( key)
93
+ . map ( Self :: LightClientBootstrap )
94
+ . map_err ( |e| ContentKeyError :: from_decode_error ( e, value) ) ,
95
+ LIGHT_CLIENT_UPDATES_BY_RANGE_KEY_PREFIX => {
96
+ LightClientUpdatesByRangeKey :: from_ssz_bytes ( key)
97
+ . map ( Self :: LightClientUpdatesByRange )
98
+ . map_err ( |e| ContentKeyError :: from_decode_error ( e, value) )
99
+ }
100
+ LIGHT_CLIENT_FINALITY_UPDATE_KEY_PREFIX => {
101
+ LightClientFinalityUpdateKey :: from_ssz_bytes ( key)
102
+ . map ( Self :: LightClientFinalityUpdate )
103
+ . map_err ( |e| ContentKeyError :: from_decode_error ( e, value) )
104
+ }
105
+ LIGHT_CLIENT_OPTIMISTIC_UPDATE_KEY_PREFIX => {
106
+ LightClientOptimisticUpdateKey :: from_ssz_bytes ( key)
107
+ . map ( Self :: LightClientOptimisticUpdate )
108
+ . map_err ( |e| ContentKeyError :: from_decode_error ( e, value) )
109
+ }
110
+ _ => Err ( ContentKeyError :: from_decode_error (
111
+ DecodeError :: UnionSelectorInvalid ( selector) ,
112
+ value,
113
+ ) ) ,
114
+ }
164
115
}
165
116
}
166
117
@@ -192,7 +143,7 @@ impl fmt::Display for BeaconContentKey {
192
143
impl OverlayContentKey for BeaconContentKey {
193
144
fn content_id ( & self ) -> [ u8 ; 32 ] {
194
145
let mut sha256 = Sha256 :: new ( ) ;
195
- sha256. update ( self . as_ssz_bytes ( ) ) ;
146
+ sha256. update ( self . to_bytes ( ) ) ;
196
147
sha256. finalize ( ) . into ( )
197
148
}
198
149
@@ -202,20 +153,19 @@ impl OverlayContentKey for BeaconContentKey {
202
153
match self {
203
154
BeaconContentKey :: LightClientBootstrap ( key) => {
204
155
bytes. push ( LIGHT_CLIENT_BOOTSTRAP_KEY_PREFIX ) ;
205
- bytes. extend_from_slice ( & key. block_hash ) ;
156
+ bytes. extend_from_slice ( & key. as_ssz_bytes ( ) ) ;
206
157
}
207
158
BeaconContentKey :: LightClientUpdatesByRange ( key) => {
208
159
bytes. push ( LIGHT_CLIENT_UPDATES_BY_RANGE_KEY_PREFIX ) ;
209
- bytes. extend_from_slice ( & key. start_period . as_ssz_bytes ( ) ) ;
210
- bytes. extend_from_slice ( & key. count . as_ssz_bytes ( ) ) ;
160
+ bytes. extend_from_slice ( & key. as_ssz_bytes ( ) ) ;
211
161
}
212
162
BeaconContentKey :: LightClientFinalityUpdate ( key) => {
213
163
bytes. push ( LIGHT_CLIENT_FINALITY_UPDATE_KEY_PREFIX ) ;
214
- bytes. extend_from_slice ( & key. finalized_slot . as_ssz_bytes ( ) )
164
+ bytes. extend_from_slice ( & key. as_ssz_bytes ( ) )
215
165
}
216
166
BeaconContentKey :: LightClientOptimisticUpdate ( key) => {
217
167
bytes. push ( LIGHT_CLIENT_OPTIMISTIC_UPDATE_KEY_PREFIX ) ;
218
- bytes. extend_from_slice ( & key. signature_slot . as_ssz_bytes ( ) )
168
+ bytes. extend_from_slice ( & key. as_ssz_bytes ( ) )
219
169
}
220
170
}
221
171
@@ -237,31 +187,21 @@ impl<'de> Deserialize<'de> for BeaconContentKey {
237
187
where
238
188
D : Deserializer < ' de > ,
239
189
{
240
- let data = String :: deserialize ( deserializer) ?. to_lowercase ( ) ;
241
-
242
- if !data. starts_with ( "0x" ) {
243
- return Err ( de:: Error :: custom ( format ! (
244
- "Hex strings must start with 0x, but found {}" ,
245
- & data[ ..2 ]
246
- ) ) ) ;
247
- }
248
-
249
- let ssz_bytes = hex_decode ( & data) . map_err ( de:: Error :: custom) ?;
250
-
251
- Self :: from_ssz_bytes ( & ssz_bytes)
252
- . map_err ( |e| ContentKeyError :: from_decode_error ( e, ssz_bytes) )
253
- . map_err ( serde:: de:: Error :: custom)
190
+ let s = String :: deserialize ( deserializer) ?;
191
+ Self :: from_hex ( & s) . map_err ( serde:: de:: Error :: custom)
254
192
}
255
193
}
256
194
257
195
#[ cfg( test) ]
258
196
#[ allow( clippy:: unwrap_used) ]
259
197
mod test {
198
+ use crate :: utils:: bytes:: hex_decode;
199
+
260
200
use super :: * ;
261
201
262
- fn test_ssz_encode_decode ( content_key : & BeaconContentKey ) {
263
- let ssz_bytes = content_key. as_ssz_bytes ( ) ;
264
- let decoded_key = BeaconContentKey :: from_ssz_bytes ( & ssz_bytes ) . unwrap ( ) ;
202
+ fn test_encode_decode ( content_key : & BeaconContentKey ) {
203
+ let bytes = content_key. to_bytes ( ) ;
204
+ let decoded_key = BeaconContentKey :: try_from ( bytes ) . unwrap ( ) ;
265
205
assert_eq ! ( * content_key, decoded_key) ;
266
206
}
267
207
@@ -281,7 +221,7 @@ mod test {
281
221
282
222
let content_key = BeaconContentKey :: LightClientBootstrap ( bootstrap) ;
283
223
284
- test_ssz_encode_decode ( & content_key) ;
224
+ test_encode_decode ( & content_key) ;
285
225
286
226
assert_eq ! ( content_key. to_bytes( ) , expected_content_key) ;
287
227
assert_eq ! (
@@ -306,7 +246,7 @@ mod test {
306
246
307
247
let content_key = BeaconContentKey :: LightClientUpdatesByRange ( content_key) ;
308
248
309
- test_ssz_encode_decode ( & content_key) ;
249
+ test_encode_decode ( & content_key) ;
310
250
311
251
assert_eq ! ( content_key. to_bytes( ) , expected_content_key) ;
312
252
assert_eq ! (
@@ -323,7 +263,7 @@ mod test {
323
263
let content_key =
324
264
BeaconContentKey :: LightClientFinalityUpdate ( LightClientFinalityUpdateKey :: new ( 7271362 ) ) ;
325
265
326
- test_ssz_encode_decode ( & content_key) ;
266
+ test_encode_decode ( & content_key) ;
327
267
328
268
assert_eq ! ( content_key. to_bytes( ) , expected_content_key) ;
329
269
assert_eq ! (
@@ -341,7 +281,7 @@ mod test {
341
281
LightClientOptimisticUpdateKey :: new ( 7271362 ) ,
342
282
) ;
343
283
344
- test_ssz_encode_decode ( & content_key) ;
284
+ test_encode_decode ( & content_key) ;
345
285
346
286
assert_eq ! ( content_key. to_bytes( ) , expected_content_key) ;
347
287
assert_eq ! (
0 commit comments