1
1
use alloy:: {
2
2
primitives:: { keccak256, Address , Bloom , Bytes , B256 , B64 , U256 , U64 } ,
3
- rlp:: { Decodable , Encodable , Header as RlpHeader } ,
3
+ rlp:: { self , Decodable , Encodable } ,
4
4
rpc:: types:: Header as RpcHeader ,
5
5
} ;
6
+ use bytes:: Buf ;
6
7
use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
7
8
8
9
use crate :: utils:: bytes:: { hex_decode, hex_encode} ;
@@ -87,113 +88,138 @@ where
87
88
impl Header {
88
89
/// Returns the Keccak-256 hash of the header.
89
90
pub fn hash ( & self ) -> B256 {
90
- keccak256 ( alloy:: rlp:: encode ( self ) )
91
+ keccak256 ( rlp:: encode ( self ) )
92
+ }
93
+
94
+ /// Calculates the byte length of the RLP encoding without RLP header.
95
+ fn rlp_payload_length ( & self ) -> usize {
96
+ self . parent_hash . length ( )
97
+ + self . uncles_hash . length ( )
98
+ + self . author . length ( )
99
+ + self . state_root . length ( )
100
+ + self . transactions_root . length ( )
101
+ + self . receipts_root . length ( )
102
+ + self . logs_bloom . length ( )
103
+ + self . difficulty . length ( )
104
+ + self . number . length ( )
105
+ + self . gas_limit . length ( )
106
+ + self . gas_used . length ( )
107
+ + self . timestamp . length ( )
108
+ + self . extra_data . as_slice ( ) . length ( )
109
+ + self . mix_hash . as_ref ( ) . map_or ( 0 , Encodable :: length)
110
+ + self . nonce . as_ref ( ) . map_or ( 0 , Encodable :: length)
111
+ + self . base_fee_per_gas . as_ref ( ) . map_or ( 0 , Encodable :: length)
112
+ + self . withdrawals_root . as_ref ( ) . map_or ( 0 , Encodable :: length)
113
+ + self . blob_gas_used . as_ref ( ) . map_or ( 0 , Encodable :: length)
114
+ + self . excess_blob_gas . as_ref ( ) . map_or ( 0 , Encodable :: length)
115
+ + self
116
+ . parent_beacon_block_root
117
+ . as_ref ( )
118
+ . map_or ( 0 , Encodable :: length)
91
119
}
92
120
}
93
121
94
122
impl Encodable for Header {
95
123
fn encode ( & self , out : & mut dyn bytes:: BufMut ) {
96
- let mut list = vec ! [ ] ;
97
- self . parent_hash . encode ( & mut list) ;
98
- self . uncles_hash . encode ( & mut list) ;
99
- self . author . encode ( & mut list) ;
100
- self . state_root . encode ( & mut list) ;
101
- self . transactions_root . encode ( & mut list) ;
102
- self . receipts_root . encode ( & mut list) ;
103
- self . logs_bloom . encode ( & mut list) ;
104
- self . difficulty . encode ( & mut list) ;
105
- self . number . encode ( & mut list) ;
106
- self . gas_limit . encode ( & mut list) ;
107
- self . gas_used . encode ( & mut list) ;
108
- self . timestamp . encode ( & mut list) ;
109
- self . extra_data . as_slice ( ) . encode ( & mut list) ;
110
-
111
- if let Some ( val) = self . mix_hash {
112
- val. encode ( & mut list) ;
124
+ rlp:: Header {
125
+ list : true ,
126
+ payload_length : self . rlp_payload_length ( ) ,
113
127
}
114
-
115
- if let Some ( val) = self . nonce {
116
- val. encode ( & mut list) ;
128
+ . encode ( out) ;
129
+
130
+ self . parent_hash . encode ( out) ;
131
+ self . uncles_hash . encode ( out) ;
132
+ self . author . encode ( out) ;
133
+ self . state_root . encode ( out) ;
134
+ self . transactions_root . encode ( out) ;
135
+ self . receipts_root . encode ( out) ;
136
+ self . logs_bloom . encode ( out) ;
137
+ self . difficulty . encode ( out) ;
138
+ self . number . encode ( out) ;
139
+ self . gas_limit . encode ( out) ;
140
+ self . gas_used . encode ( out) ;
141
+ self . timestamp . encode ( out) ;
142
+ self . extra_data . as_slice ( ) . encode ( out) ;
143
+
144
+ if let Some ( val) = & self . mix_hash {
145
+ val. encode ( out) ;
117
146
}
118
-
119
- if let Some ( val) = self . base_fee_per_gas {
120
- val. encode ( & mut list) ;
147
+ if let Some ( val) = & self . nonce {
148
+ val. encode ( out) ;
121
149
}
122
-
123
- if let Some ( val) = self . withdrawals_root {
124
- val. encode ( & mut list) ;
150
+ if let Some ( val) = & self . base_fee_per_gas {
151
+ val. encode ( out) ;
125
152
}
126
-
127
- if let Some ( val) = self . blob_gas_used {
128
- val. encode ( & mut list) ;
153
+ if let Some ( val) = & self . withdrawals_root {
154
+ val. encode ( out) ;
129
155
}
130
-
131
- if let Some ( val) = self . excess_blob_gas {
132
- val. encode ( & mut list) ;
156
+ if let Some ( val) = & self . blob_gas_used {
157
+ val. encode ( out) ;
133
158
}
134
-
135
- if let Some ( val) = self . parent_beacon_block_root {
136
- val. encode ( & mut list) ;
159
+ if let Some ( val) = & self . excess_blob_gas {
160
+ val. encode ( out) ;
161
+ }
162
+ if let Some ( val) = & self . parent_beacon_block_root {
163
+ val. encode ( out) ;
137
164
}
165
+ }
138
166
139
- let header = RlpHeader {
140
- list : true ,
141
- payload_length : list. len ( ) ,
142
- } ;
143
- header. encode ( out) ;
144
- out. put_slice ( list. as_slice ( ) ) ;
167
+ fn length ( & self ) -> usize {
168
+ let payload_length = self . rlp_payload_length ( ) ;
169
+ payload_length + rlp:: length_of_length ( payload_length)
145
170
}
146
171
}
147
172
148
173
impl Decodable for Header {
149
- /// Attempt to decode a header from RLP bytes.
150
- fn decode ( buf : & mut & [ u8 ] ) -> alloy:: rlp:: Result < Self > {
151
- let rlp_head = alloy:: rlp:: Header :: decode ( buf) ?;
152
- if !rlp_head. list {
153
- return Err ( alloy:: rlp:: Error :: UnexpectedString ) ;
154
- }
155
- let started_len = buf. len ( ) ;
174
+ fn decode ( buf : & mut & [ u8 ] ) -> rlp:: Result < Self > {
175
+ let mut payload_view = rlp:: Header :: decode_bytes ( buf, /* is_list= */ true ) ?;
176
+ let payload_size = payload_view. remaining ( ) ;
177
+
156
178
let mut header = Header {
157
- parent_hash : Decodable :: decode ( buf ) ?,
158
- uncles_hash : Decodable :: decode ( buf ) ?,
159
- author : Decodable :: decode ( buf ) ?,
160
- state_root : Decodable :: decode ( buf ) ?,
161
- transactions_root : Decodable :: decode ( buf ) ?,
162
- receipts_root : Decodable :: decode ( buf ) ?,
163
- logs_bloom : Decodable :: decode ( buf ) ?,
164
- difficulty : Decodable :: decode ( buf ) ?,
165
- number : Decodable :: decode ( buf ) ?,
166
- gas_limit : Decodable :: decode ( buf ) ?,
167
- gas_used : Decodable :: decode ( buf ) ?,
168
- timestamp : Decodable :: decode ( buf ) ?,
169
- extra_data : Bytes :: decode ( buf ) ?. to_vec ( ) ,
170
- mix_hash : Some ( Decodable :: decode ( buf ) ?) ,
171
- nonce : Some ( Decodable :: decode ( buf ) ?) ,
179
+ parent_hash : Decodable :: decode ( & mut payload_view ) ?,
180
+ uncles_hash : Decodable :: decode ( & mut payload_view ) ?,
181
+ author : Decodable :: decode ( & mut payload_view ) ?,
182
+ state_root : Decodable :: decode ( & mut payload_view ) ?,
183
+ transactions_root : Decodable :: decode ( & mut payload_view ) ?,
184
+ receipts_root : Decodable :: decode ( & mut payload_view ) ?,
185
+ logs_bloom : Decodable :: decode ( & mut payload_view ) ?,
186
+ difficulty : Decodable :: decode ( & mut payload_view ) ?,
187
+ number : Decodable :: decode ( & mut payload_view ) ?,
188
+ gas_limit : Decodable :: decode ( & mut payload_view ) ?,
189
+ gas_used : Decodable :: decode ( & mut payload_view ) ?,
190
+ timestamp : Decodable :: decode ( & mut payload_view ) ?,
191
+ extra_data : Bytes :: decode ( & mut payload_view ) ?. to_vec ( ) ,
192
+ mix_hash : Some ( Decodable :: decode ( & mut payload_view ) ?) ,
193
+ nonce : Some ( Decodable :: decode ( & mut payload_view ) ?) ,
172
194
base_fee_per_gas : None ,
173
195
withdrawals_root : None ,
174
196
blob_gas_used : None ,
175
197
excess_blob_gas : None ,
176
198
parent_beacon_block_root : None ,
177
199
} ;
178
200
179
- if started_len - buf . len ( ) < rlp_head . payload_length {
180
- header. base_fee_per_gas = Some ( Decodable :: decode ( buf ) ?)
201
+ if payload_view . has_remaining ( ) {
202
+ header. base_fee_per_gas = Some ( Decodable :: decode ( & mut payload_view ) ?)
181
203
}
182
-
183
- if started_len - buf. len ( ) < rlp_head. payload_length {
184
- header. withdrawals_root = Some ( Decodable :: decode ( buf) ?)
204
+ if payload_view. has_remaining ( ) {
205
+ header. withdrawals_root = Some ( Decodable :: decode ( & mut payload_view) ?)
185
206
}
186
-
187
- if started_len - buf. len ( ) < rlp_head. payload_length {
188
- header. blob_gas_used = Some ( Decodable :: decode ( buf) ?)
207
+ if payload_view. has_remaining ( ) {
208
+ header. blob_gas_used = Some ( Decodable :: decode ( & mut payload_view) ?)
189
209
}
190
-
191
- if started_len - buf. len ( ) < rlp_head. payload_length {
192
- header. excess_blob_gas = Some ( Decodable :: decode ( buf) ?)
210
+ if payload_view. has_remaining ( ) {
211
+ header. excess_blob_gas = Some ( Decodable :: decode ( & mut payload_view) ?)
212
+ }
213
+ if payload_view. has_remaining ( ) {
214
+ header. parent_beacon_block_root = Some ( Decodable :: decode ( & mut payload_view) ?)
193
215
}
194
216
195
- if started_len - buf. len ( ) < rlp_head. payload_length {
196
- header. parent_beacon_block_root = Some ( Decodable :: decode ( buf) ?)
217
+ if payload_view. has_remaining ( ) {
218
+ let consumed = payload_size - payload_view. remaining ( ) ;
219
+ return Err ( rlp:: Error :: ListLengthMismatch {
220
+ expected : payload_size,
221
+ got : consumed,
222
+ } ) ;
197
223
}
198
224
199
225
Ok ( header)
@@ -333,7 +359,7 @@ mod tests {
333
359
)
334
360
) ;
335
361
336
- let encoded_header = alloy :: rlp:: encode ( header) ;
362
+ let encoded_header = rlp:: encode ( header) ;
337
363
assert_eq ! ( header_rlp, encoded_header) ;
338
364
}
339
365
@@ -353,7 +379,7 @@ mod tests {
353
379
. unwrap( )
354
380
)
355
381
) ;
356
- let encoded_header = alloy :: rlp:: encode ( header) ;
382
+ let encoded_header = rlp:: encode ( header) ;
357
383
assert_eq ! ( header_rlp, encoded_header) ;
358
384
}
359
385
@@ -466,7 +492,7 @@ mod tests {
466
492
B256 :: from_str ( "0x10aca3ebb4cf6ddd9e945a5db19385f9c105ede7374380c50d56384c3d233785" )
467
493
. unwrap ( ) ;
468
494
assert_eq ! ( decoded. hash( ) , expected_hash) ;
469
- let expected_header = alloy :: rlp:: encode ( expected) ;
495
+ let expected_header = rlp:: encode ( expected) ;
470
496
assert_eq ! ( data, expected_header) ;
471
497
}
472
498
0 commit comments