@@ -5,7 +5,10 @@ use charon_k1util::{self, self as k1util, SIGNATURE_LEN_WITHOUT_V};
55use k256:: { PublicKey , SecretKey , elliptic_curve} ;
66use sha3:: { Digest , Keccak256 } ;
77
8- use crate :: rlp:: { RlpError , decode_bytes_list, encode_bytes_list} ;
8+ use crate :: {
9+ rlp:: { RlpError , decode_bytes_list, encode_bytes_list} ,
10+ utils,
11+ } ;
912
1013/// The key for the secp256k1 public key in the ENR.
1114pub const KEY_SECP256K1 : & str = "secp256k1" ;
@@ -154,45 +157,27 @@ impl Record {
154157 ///
155158 /// Returns None if the IP address is not set.
156159 pub fn ip ( & self ) -> Option < Ipv4Addr > {
157- self . kvs . get ( KEY_IP ) . and_then ( |value| {
158- if value. len ( ) != 4 {
159- return None ;
160- }
161-
162- let mut bytes = [ 0u8 ; 4 ] ;
163- bytes. copy_from_slice ( value) ;
164- Some ( Ipv4Addr :: from ( bytes) )
165- } )
160+ let value = self . kvs . get ( KEY_IP ) ?;
161+ let bytes: [ u8 ; 4 ] = value. as_slice ( ) . try_into ( ) . ok ( ) ?;
162+ Some ( Ipv4Addr :: from ( bytes) )
166163 }
167164
168165 /// Returns the TCP port of the record.
169166 ///
170167 /// Returns None if the TCP port is not set.
171168 pub fn tcp ( & self ) -> Option < u16 > {
172- self . kvs . get ( KEY_TCP ) . and_then ( |value| {
173- if value. len ( ) != 2 {
174- return None ;
175- }
176-
177- let mut bytes = [ 0u8 ; 2 ] ;
178- bytes. copy_from_slice ( value) ;
179- Some ( u16:: from_be_bytes ( bytes) )
180- } )
169+ let value = self . kvs . get ( KEY_TCP ) ?;
170+ let bytes = value. as_slice ( ) . try_into ( ) . ok ( ) ?;
171+ Some ( u16:: from_be_bytes ( bytes) )
181172 }
182173
183174 /// Returns the UDP port of the record.
184175 ///
185176 /// Returns None if the UDP port is not set.
186177 pub fn udp ( & self ) -> Option < u16 > {
187- self . kvs . get ( KEY_UDP ) . and_then ( |value| {
188- if value. len ( ) != 2 {
189- return None ;
190- }
191-
192- let mut bytes = [ 0u8 ; 2 ] ;
193- bytes. copy_from_slice ( value) ;
194- Some ( u16:: from_be_bytes ( bytes) )
195- } )
178+ let value = self . kvs . get ( KEY_UDP ) ?;
179+ let bytes = value. as_slice ( ) . try_into ( ) . ok ( ) ?;
180+ Some ( u16:: from_be_bytes ( bytes) )
196181 }
197182}
198183
@@ -249,9 +234,11 @@ impl TryFrom<&str> for Record {
249234 kvs : HashMap :: new ( ) ,
250235 } ;
251236
252- for i in ( 2 ..elements. len ( ) ) . step_by ( 2 ) {
253- let key = String :: from_utf8_lossy ( & elements[ i] ) . to_string ( ) ;
254- let value = elements[ i. wrapping_add ( 1 ) ] . clone ( ) ;
237+ for pair in elements. chunks_exact ( 2 ) . skip ( 1 ) {
238+ let [ key, value] = pair else {
239+ unreachable ! ( "Expected even number of elements" ) ;
240+ } ;
241+ let key = String :: from_utf8_lossy ( key) . to_string ( ) ;
255242
256243 if record. kvs . contains_key ( & key) {
257244 return Err ( RecordError :: DuplicateKey ( key) ) ;
@@ -262,11 +249,11 @@ impl TryFrom<&str> for Record {
262249 match key. as_str ( ) {
263250 KEY_SECP256K1 => {
264251 record. public_key = Some (
265- PublicKey :: from_sec1_bytes ( & value) . map_err ( RecordError :: Secp256k1Error ) ?,
252+ PublicKey :: from_sec1_bytes ( value) . map_err ( RecordError :: Secp256k1Error ) ?,
266253 ) ;
267254 }
268255 KEY_ID => {
269- let value_str = String :: from_utf8_lossy ( & value) . to_string ( ) ;
256+ let value_str = String :: from_utf8_lossy ( value) . to_string ( ) ;
270257 if value_str != VAL_ID {
271258 return Err ( RecordError :: InvalidFormat (
272259 InvalidFormatError :: NonV4IdentitySchemeNotSupported ,
@@ -277,21 +264,15 @@ impl TryFrom<&str> for Record {
277264 }
278265 }
279266
280- if record. public_key . is_none ( ) {
267+ let Some ( public_key ) = record. public_key else {
281268 return Err ( RecordError :: InvalidFormat (
282269 InvalidFormatError :: PublicKeyNotSet ,
283270 ) ) ;
284- }
271+ } ;
285272
286273 let encoded_elements = encode_bytes_list ( & elements[ 1 ..] ) ;
287274
288- verify (
289- & record
290- . public_key
291- . unwrap_or_else ( || unreachable ! ( "Public key expected to be set" ) ) ,
292- & record. signature ,
293- & encoded_elements,
294- ) ?;
275+ verify ( & public_key, & record. signature , & encoded_elements) ?;
295276
296277 Ok ( record)
297278 }
@@ -307,8 +288,9 @@ pub(crate) fn sign(
307288 let digest = hasher. finalize ( ) ;
308289
309290 let signature = k1util:: sign ( private_key, & digest) . map_err ( RecordError :: FailedToSign ) ?;
310- let mut signature_without_v = [ 0u8 ; SIGNATURE_LEN_WITHOUT_V ] ;
311- signature_without_v. copy_from_slice ( & signature[ ..SIGNATURE_LEN_WITHOUT_V ] ) ;
291+ let signature_without_v = signature[ ..SIGNATURE_LEN_WITHOUT_V ]
292+ . try_into ( )
293+ . expect ( "SIGNATURE_LEN_WITHOUT_V < SIGNATURE_LEN" ) ;
312294
313295 Ok ( signature_without_v)
314296}
@@ -335,7 +317,7 @@ pub(crate) fn encode_elements(signature: &[u8], kvs: &HashMap<String, Vec<u8>>)
335317 keys. sort ( ) ;
336318
337319 // Start with sequence number = 0
338- let mut elements: Vec < Vec < u8 > > = vec ! [ to_big_endian( 0 ) ] ;
320+ let mut elements: Vec < Vec < u8 > > = vec ! [ utils :: to_big_endian( 0 ) ] ;
339321
340322 for key in keys {
341323 elements. push ( key. as_bytes ( ) . to_vec ( ) ) ;
@@ -349,18 +331,9 @@ pub(crate) fn encode_elements(signature: &[u8], kvs: &HashMap<String, Vec<u8>>)
349331 encode_bytes_list ( & elements)
350332}
351333
352- /// Converts an integer to big-endian bytes without leading zeros.
353- fn to_big_endian ( mut n : u64 ) -> Vec < u8 > {
354- let mut result = Vec :: new ( ) ;
355- while n > 0 {
356- result. insert ( 0 , ( n & 0xFF ) as u8 ) ;
357- n >>= 8 ;
358- }
359- result
360- }
361-
362334#[ cfg( test) ]
363335mod tests {
336+ use crate :: utils;
364337 use charon_testutil:: random:: generate_insecure_k1_key;
365338 use k256:: {
366339 Secp256k1 ,
@@ -491,7 +464,7 @@ mod tests {
491464 keys. sort ( ) ;
492465
493466 // Start with sequence number = 0
494- let mut elements: Vec < Vec < u8 > > = vec ! [ to_big_endian( 0 ) , to_big_endian( 0 ) ] ;
467+ let mut elements: Vec < Vec < u8 > > = vec ! [ utils :: to_big_endian( 0 ) , utils :: to_big_endian( 0 ) ] ;
495468
496469 for key in keys {
497470 elements. push ( key. as_bytes ( ) . to_vec ( ) ) ;
0 commit comments