1
1
use ethereum_types:: H256 ;
2
- use ethrex_rlp:: { decode:: RLPDecode , encode:: RLPEncode } ;
2
+ use ethrex_rlp:: { decode:: RLPDecode , encode:: RLPEncode , structs :: Encoder } ;
3
3
#[ cfg( feature = "libmdbx" ) ]
4
4
use libmdbx:: orm:: { Decodable , Encodable } ;
5
5
use sha3:: { Digest , Keccak256 } ;
@@ -8,38 +8,57 @@ use sha3::{Digest, Keccak256};
8
8
/// If the encoded node is less than 32 bits, contains the encoded node itself
9
9
// TODO: Check if we can omit the Inline variant, as nodes will always be bigger than 32 bits in our use case
10
10
// 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 ) ]
12
12
pub enum NodeHash {
13
13
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 ) ) ,
15
16
}
16
17
17
18
impl AsRef < [ u8 ] > for NodeHash {
18
19
fn as_ref ( & self ) -> & [ u8 ] {
19
20
match self {
20
- NodeHash :: Inline ( x ) => x . as_ref ( ) ,
21
+ NodeHash :: Inline ( ( slice , len ) ) => & slice [ 0 .. ( * len as usize ) ] ,
21
22
NodeHash :: Hashed ( x) => x. as_bytes ( ) ,
22
23
}
23
24
}
24
25
}
25
26
26
27
impl NodeHash {
27
28
/// 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 {
29
30
if encoded. len ( ) >= 32 {
30
- let hash = Keccak256 :: new_with_prefix ( & encoded) . finalize ( ) ;
31
+ let hash = Keccak256 :: new_with_prefix ( encoded) . finalize ( ) ;
31
32
NodeHash :: Hashed ( H256 :: from_slice ( hash. as_slice ( ) ) )
32
33
} else {
33
- NodeHash :: Inline ( encoded)
34
+ NodeHash :: from_slice ( encoded)
34
35
}
35
36
}
37
+
38
+ /// Converts a slice of an already hashed data (in case it's not inlineable) to a NodeHash.
39
+ ///
40
+ /// If you need to hash it in case its len >= 32 see `from_encoded_raw`
41
+ pub ( crate ) fn from_slice ( slice : & [ u8 ] ) -> NodeHash {
42
+ match slice. len ( ) {
43
+ 0 ..32 => {
44
+ let mut buffer = [ 0 ; 31 ] ;
45
+ buffer[ 0 ..slice. len ( ) ] . copy_from_slice ( slice) ;
46
+ NodeHash :: Inline ( ( buffer, slice. len ( ) as u8 ) )
47
+ }
48
+ _ => NodeHash :: Hashed ( H256 :: from_slice ( slice) ) ,
49
+ }
50
+ }
51
+
36
52
/// Returns the finalized hash
37
53
/// NOTE: This will hash smaller nodes, only use to get the final root hash, not for intermediate node hashes
38
54
pub fn finalize ( self ) -> H256 {
39
55
match self {
40
- NodeHash :: Inline ( x) => {
41
- H256 :: from_slice ( Keccak256 :: new ( ) . chain_update ( & * x) . finalize ( ) . as_slice ( ) )
42
- }
56
+ NodeHash :: Inline ( _) => H256 :: from_slice (
57
+ Keccak256 :: new ( )
58
+ . chain_update ( self . as_ref ( ) )
59
+ . finalize ( )
60
+ . as_slice ( ) ,
61
+ ) ,
43
62
NodeHash :: Hashed ( x) => x,
44
63
}
45
64
}
@@ -48,21 +67,31 @@ impl NodeHash {
48
67
/// The hash will only be considered invalid if it is empty
49
68
/// Aka if it has a default value instead of being a product of hash computation
50
69
pub fn is_valid ( & self ) -> bool {
51
- !matches ! ( self , NodeHash :: Inline ( v) if v. is_empty ( ) )
70
+ !matches ! ( self , NodeHash :: Inline ( v) if v. 1 == 0 )
52
71
}
53
72
54
73
/// Const version of `Default` trait impl
55
74
pub const fn const_default ( ) -> Self {
56
- Self :: Inline ( vec ! [ ] )
75
+ Self :: Inline ( ( [ 0 ; 31 ] , 0 ) )
76
+ }
77
+
78
+ /// Encodes this NodeHash with the given encoder.
79
+ pub fn encode < ' a > ( & self , mut encoder : Encoder < ' a > ) -> Encoder < ' a > {
80
+ match self {
81
+ NodeHash :: Inline ( _) => {
82
+ encoder = encoder. encode_raw ( self . as_ref ( ) ) ;
83
+ }
84
+ NodeHash :: Hashed ( _) => {
85
+ encoder = encoder. encode_bytes ( self . as_ref ( ) ) ;
86
+ }
87
+ }
88
+ encoder
57
89
}
58
90
}
59
91
60
92
impl From < Vec < u8 > > for NodeHash {
61
93
fn from ( value : Vec < u8 > ) -> Self {
62
- match value. len ( ) {
63
- 32 => NodeHash :: Hashed ( H256 :: from_slice ( & value) ) ,
64
- _ => NodeHash :: Inline ( value) ,
65
- }
94
+ NodeHash :: from_slice ( & value)
66
95
}
67
96
}
68
97
@@ -74,19 +103,13 @@ impl From<H256> for NodeHash {
74
103
75
104
impl From < NodeHash > for Vec < u8 > {
76
105
fn from ( val : NodeHash ) -> Self {
77
- match val {
78
- NodeHash :: Hashed ( x) => x. 0 . to_vec ( ) ,
79
- NodeHash :: Inline ( x) => x,
80
- }
106
+ val. as_ref ( ) . to_vec ( )
81
107
}
82
108
}
83
109
84
110
impl From < & NodeHash > for Vec < u8 > {
85
111
fn from ( val : & NodeHash ) -> Self {
86
- match val {
87
- NodeHash :: Hashed ( x) => x. 0 . to_vec ( ) ,
88
- NodeHash :: Inline ( x) => x. clone ( ) ,
89
- }
112
+ val. as_ref ( ) . to_vec ( )
90
113
}
91
114
}
92
115
@@ -102,16 +125,13 @@ impl Encodable for NodeHash {
102
125
#[ cfg( feature = "libmdbx" ) ]
103
126
impl Decodable for NodeHash {
104
127
fn decode ( b : & [ u8 ] ) -> anyhow:: Result < Self > {
105
- Ok ( match b. len ( ) {
106
- 32 => NodeHash :: Hashed ( H256 :: from_slice ( b) ) ,
107
- _ => NodeHash :: Inline ( b. into ( ) ) ,
108
- } )
128
+ Ok ( NodeHash :: from_slice ( b) )
109
129
}
110
130
}
111
131
112
132
impl Default for NodeHash {
113
133
fn default ( ) -> Self {
114
- NodeHash :: Inline ( Vec :: new ( ) )
134
+ NodeHash :: Inline ( ( [ 0 ; 31 ] , 0 ) )
115
135
}
116
136
}
117
137
0 commit comments