11use ethereum_types:: H256 ;
2- use ethrex_rlp:: { decode:: RLPDecode , encode:: RLPEncode } ;
2+ use ethrex_rlp:: { decode:: RLPDecode , encode:: RLPEncode , structs :: Encoder } ;
33#[ cfg( feature = "libmdbx" ) ]
44use libmdbx:: orm:: { Decodable , Encodable } ;
55use sha3:: { Digest , Keccak256 } ;
@@ -8,38 +8,50 @@ use sha3::{Digest, Keccak256};
88/// If the encoded node is less than 32 bits, contains the encoded node itself
99// TODO: Check if we can omit the Inline variant, as nodes will always be bigger than 32 bits in our use case
1010// TODO: Check if making this `Copy` can make the code less verbose at a reasonable performance cost
11- #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
11+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
1212pub enum NodeHash {
1313 Hashed ( H256 ) ,
14- Inline ( Vec < u8 > ) ,
14+ // Inline is always len < 32. We need to store the length of the data, a u8 is enough.
15+ Inline ( ( [ u8 ; 31 ] , u8 ) ) ,
1516}
1617
1718impl AsRef < [ u8 ] > for NodeHash {
1819 fn as_ref ( & self ) -> & [ u8 ] {
1920 match self {
20- NodeHash :: Inline ( x ) => x . as_ref ( ) ,
21+ NodeHash :: Inline ( ( slice , len ) ) => & slice [ 0 .. ( * len as usize ) ] ,
2122 NodeHash :: Hashed ( x) => x. as_bytes ( ) ,
2223 }
2324 }
2425}
2526
2627impl NodeHash {
2728 /// Returns the `NodeHash` of an encoded node (encoded using the NodeEncoder)
28- pub fn from_encoded_raw ( encoded : Vec < u8 > ) -> NodeHash {
29+ pub fn from_encoded_raw ( encoded : & [ u8 ] ) -> NodeHash {
2930 if encoded. len ( ) >= 32 {
30- let hash = Keccak256 :: new_with_prefix ( & encoded) . finalize ( ) ;
31+ let hash = Keccak256 :: new_with_prefix ( encoded) . finalize ( ) ;
3132 NodeHash :: Hashed ( H256 :: from_slice ( hash. as_slice ( ) ) )
3233 } else {
33- NodeHash :: Inline ( encoded)
34+ NodeHash :: inline_from_slice ( encoded)
3435 }
3536 }
37+
38+ pub ( crate ) fn inline_from_slice ( slice : & [ u8 ] ) -> NodeHash {
39+ assert ! ( slice. len( ) < 32 , "Slice must have a len < 32 to be inlined" ) ;
40+ let mut buffer = [ 0 ; 31 ] ;
41+ buffer[ 0 ..slice. len ( ) ] . copy_from_slice ( slice) ;
42+ NodeHash :: Inline ( ( buffer, slice. len ( ) as u8 ) )
43+ }
44+
3645 /// Returns the finalized hash
3746 /// NOTE: This will hash smaller nodes, only use to get the final root hash, not for intermediate node hashes
3847 pub fn finalize ( self ) -> H256 {
3948 match self {
40- NodeHash :: Inline ( x) => {
41- H256 :: from_slice ( Keccak256 :: new ( ) . chain_update ( & * x) . finalize ( ) . as_slice ( ) )
42- }
49+ NodeHash :: Inline ( _) => H256 :: from_slice (
50+ Keccak256 :: new ( )
51+ . chain_update ( self . as_ref ( ) )
52+ . finalize ( )
53+ . as_slice ( ) ,
54+ ) ,
4355 NodeHash :: Hashed ( x) => x,
4456 }
4557 }
@@ -48,20 +60,33 @@ impl NodeHash {
4860 /// The hash will only be considered invalid if it is empty
4961 /// Aka if it has a default value instead of being a product of hash computation
5062 pub fn is_valid ( & self ) -> bool {
51- !matches ! ( self , NodeHash :: Inline ( v) if v. is_empty ( ) )
63+ !matches ! ( self , NodeHash :: Inline ( v) if v. 1 == 0 )
5264 }
5365
5466 /// Const version of `Default` trait impl
5567 pub const fn const_default ( ) -> Self {
56- Self :: Inline ( vec ! [ ] )
68+ Self :: Inline ( ( [ 0 ; 31 ] , 0 ) )
69+ }
70+
71+ /// Encodes this NodeHash with the given encoder.
72+ pub fn encode < ' a > ( & self , mut encoder : Encoder < ' a > ) -> Encoder < ' a > {
73+ match self {
74+ NodeHash :: Inline ( _) => {
75+ encoder = encoder. encode_raw ( self . as_ref ( ) ) ;
76+ }
77+ NodeHash :: Hashed ( _) => {
78+ encoder = encoder. encode_bytes ( self . as_ref ( ) ) ;
79+ }
80+ }
81+ encoder
5782 }
5883}
5984
6085impl From < Vec < u8 > > for NodeHash {
6186 fn from ( value : Vec < u8 > ) -> Self {
6287 match value. len ( ) {
6388 32 => NodeHash :: Hashed ( H256 :: from_slice ( & value) ) ,
64- _ => NodeHash :: Inline ( value) ,
89+ _ => NodeHash :: inline_from_slice ( & value) ,
6590 }
6691 }
6792}
@@ -74,19 +99,13 @@ impl From<H256> for NodeHash {
7499
75100impl From < NodeHash > for Vec < u8 > {
76101 fn from ( val : NodeHash ) -> Self {
77- match val {
78- NodeHash :: Hashed ( x) => x. 0 . to_vec ( ) ,
79- NodeHash :: Inline ( x) => x,
80- }
102+ val. as_ref ( ) . to_vec ( )
81103 }
82104}
83105
84106impl From < & NodeHash > for Vec < u8 > {
85107 fn from ( val : & NodeHash ) -> Self {
86- match val {
87- NodeHash :: Hashed ( x) => x. 0 . to_vec ( ) ,
88- NodeHash :: Inline ( x) => x. clone ( ) ,
89- }
108+ val. as_ref ( ) . to_vec ( )
90109 }
91110}
92111
@@ -104,14 +123,14 @@ impl Decodable for NodeHash {
104123 fn decode ( b : & [ u8 ] ) -> anyhow:: Result < Self > {
105124 Ok ( match b. len ( ) {
106125 32 => NodeHash :: Hashed ( H256 :: from_slice ( b) ) ,
107- _ => NodeHash :: Inline ( b . into ( ) ) ,
126+ _ => NodeHash :: inline_from_slice ( b ) ,
108127 } )
109128 }
110129}
111130
112131impl Default for NodeHash {
113132 fn default ( ) -> Self {
114- NodeHash :: Inline ( Vec :: new ( ) )
133+ NodeHash :: Inline ( ( [ 0 ; 31 ] , 0 ) )
115134 }
116135}
117136
0 commit comments