11use crate :: { migration_info:: DataSource , MigrationInfo } ;
22use std:: { collections:: HashMap , time:: Duration } ;
33
4- use alloy_primitives:: { bytes:: Buf , B256 } ;
4+ use alloy_primitives:: { bytes:: Buf , Address , B256 } ;
55use eyre:: { bail, eyre} ;
66use futures:: { stream:: FuturesUnordered , StreamExt } ;
77use indicatif:: { ProgressBar , ProgressFinish , ProgressState , ProgressStyle } ;
@@ -70,19 +70,23 @@ impl<MI: MigrationInfo + Send + Sync> MigrationTrait for Migration<MI> {
7070pub struct Model {
7171 #[ sea_orm( primary_key) ]
7272 number : i64 ,
73- extra_data : Vec < u8 > ,
74- state_root : Vec < u8 > ,
75- difficulty : i8 ,
73+ extra_data : Option < Vec < u8 > > ,
74+ state_root : Option < Vec < u8 > > ,
75+ coinbase : Option < Vec < u8 > > ,
76+ nonce : Option < String > ,
77+ difficulty : Option < i8 > ,
7678}
7779impl ActiveModelBehavior for ActiveModel { }
7880
7981impl From < ( i64 , HeaderMetadata ) > for ActiveModel {
8082 fn from ( ( bn, header) : ( i64 , HeaderMetadata ) ) -> Self {
8183 Self {
8284 number : ActiveValue :: Set ( bn) ,
83- extra_data : ActiveValue :: Set ( header. extra_data ) ,
84- state_root : ActiveValue :: Set ( header. state_root . to_vec ( ) ) ,
85- difficulty : ActiveValue :: Set ( header. difficulty as i8 ) ,
85+ extra_data : ActiveValue :: Set ( Some ( header. extra_data ) ) ,
86+ state_root : ActiveValue :: Set ( Some ( header. state_root . to_vec ( ) ) ) ,
87+ coinbase : ActiveValue :: Set ( header. coinbase . map ( |c| c. to_vec ( ) ) ) ,
88+ nonce : ActiveValue :: Set ( header. nonce . map ( |x| format ! ( "{x:x}" ) ) ) ,
89+ difficulty : ActiveValue :: Set ( Some ( header. difficulty as i8 ) ) ,
8690 }
8791 }
8892}
@@ -107,7 +111,8 @@ async fn download(url: &str) -> eyre::Result<Vec<u8>> {
107111 if total_size == 0 {
108112 bail ! ( "empty file" ) ;
109113 }
110- let iterations = total_size / CHUNK_SIZE + if total_size % CHUNK_SIZE != 0 { 1 } else { 0 } ;
114+ let iterations =
115+ total_size / CHUNK_SIZE + if !total_size. is_multiple_of ( CHUNK_SIZE ) { 1 } else { 0 } ;
111116
112117 // create a progress bar.
113118 let pb = ProgressBar :: new ( total_size) .
@@ -213,8 +218,8 @@ fn decode_to_headers(data: Vec<u8>) -> eyre::Result<Vec<HeaderMetadata>> {
213218
214219 // decode all available data.
215220 let mut headers = Vec :: with_capacity ( data_buf. len ( ) / HEADER_LOWER_SIZE_LIMIT ) ;
216- while let Some ( data ) = decoder . next ( data_buf ) {
217- headers. push ( data ) ;
221+ while !data_buf . is_empty ( ) {
222+ headers. push ( decoder . next ( data_buf ) . map_err ( |err| DbErr :: Custom ( err . to_string ( ) ) ) ? ) ;
218223 }
219224
220225 Ok ( headers)
@@ -225,6 +230,8 @@ fn decode_to_headers(data: Vec<u8>) -> eyre::Result<Vec<HeaderMetadata>> {
225230struct HeaderMetadata {
226231 extra_data : Vec < u8 > ,
227232 state_root : Vec < u8 > ,
233+ coinbase : Option < Vec < u8 > > ,
234+ nonce : Option < u64 > ,
228235 difficulty : u8 ,
229236}
230237
@@ -260,33 +267,56 @@ impl MetadataDecoder {
260267 }
261268
262269 /// Decodes the next header metadata from the buffer, advancing it.
263- fn next ( & self , buf : & mut & [ u8 ] ) -> Option < HeaderMetadata > {
270+ fn next ( & self , buf : & mut & [ u8 ] ) -> eyre :: Result < HeaderMetadata > {
264271 // sanity check.
265272 if buf. len ( ) < 2 {
266- return None
273+ bail ! ( "header buffer too small to read seal flag and vanity index" ) ;
267274 }
268275
269276 // get flag and vanity index.
270277 let flag = buf[ 0 ] ;
271278 let vanity_index = buf[ 1 ] ;
272279
280+ let has_coinbase = ( flag & 0b00010000 ) != 0 ;
281+ let has_nonce = ( flag & 0b00100000 ) != 0 ;
273282 let difficulty = if flag & 0b01000000 == 0 { 2 } else { 1 } ;
274283 let seal_length = if flag & 0b10000000 == 0 { 65 } else { 85 } ;
275- let vanity = self . vanity . get ( & vanity_index) ?;
284+ let vanity = self . vanity . get ( & vanity_index) . ok_or ( eyre ! ( "vanity not found" ) ) ?;
276285
277- if buf. len ( ) < B256 :: len_bytes ( ) + seal_length + 2 {
278- return None
286+ // flag + vanity index + state root + coinbase + nonce + seal
287+ let total_expected_size = 2 * size_of :: < u8 > ( ) +
288+ B256 :: len_bytes ( ) +
289+ Address :: len_bytes ( ) * has_coinbase as usize +
290+ size_of :: < u64 > ( ) * has_nonce as usize +
291+ seal_length;
292+
293+ if buf. len ( ) < total_expected_size {
294+ bail ! ( "header buffer too small: got {}, expected {}" , buf. len( ) , total_expected_size) ;
279295 }
280296 buf. advance ( 2 ) ;
281297
282298 let state_root = buf[ ..B256 :: len_bytes ( ) ] . to_vec ( ) ;
283299 buf. advance ( B256 :: len_bytes ( ) ) ;
284300
301+ let mut coinbase = None ;
302+ if has_coinbase {
303+ coinbase = Some ( buf[ ..Address :: len_bytes ( ) ] . to_vec ( ) ) ;
304+ buf. advance ( Address :: len_bytes ( ) ) ;
305+ }
306+
307+ let mut nonce = None ;
308+ if has_nonce {
309+ nonce = Some ( u64:: from_be_bytes (
310+ buf[ ..size_of :: < u64 > ( ) ] . try_into ( ) . expect ( "32 bytes slice" ) ,
311+ ) ) ;
312+ buf. advance ( size_of :: < u64 > ( ) ) ;
313+ }
314+
285315 let seal = & buf[ ..seal_length] ;
286316 let extra_data = [ vanity, seal] . concat ( ) ;
287317 buf. advance ( seal_length) ;
288318
289- Some ( HeaderMetadata { extra_data, state_root, difficulty } )
319+ Ok ( HeaderMetadata { extra_data, state_root, coinbase , nonce , difficulty } )
290320 }
291321}
292322
@@ -316,7 +346,13 @@ mod tests {
316346 let header_data = bytes ! ( "c00020695989e9038823e35f0e88fbc44659ffdbfa1fe89fbeb2689b43f15fa64cb548c3f81f3d998b6652900e1c3183736c238fe4290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ) ;
317347 let header = decoder. next ( & mut header_data. as_ref ( ) ) . unwrap ( ) ;
318348
319- let expected_header = HeaderMetadata { extra_data : bytes ! ( "0x000000000000000000000000000000000000000000000000000000000000000048c3f81f3d998b6652900e1c3183736c238fe4290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ) . to_vec ( ) , state_root : b256 ! ( "20695989e9038823e35f0e88fbc44659ffdbfa1fe89fbeb2689b43f15fa64cb5" ) . to_vec ( ) , difficulty : 1 } ;
349+ let expected_header = HeaderMetadata {
350+ extra_data : bytes ! ( "0x000000000000000000000000000000000000000000000000000000000000000048c3f81f3d998b6652900e1c3183736c238fe4290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ) . to_vec ( ) ,
351+ state_root : b256 ! ( "20695989e9038823e35f0e88fbc44659ffdbfa1fe89fbeb2689b43f15fa64cb5" ) . to_vec ( ) ,
352+ coinbase : None ,
353+ nonce : None ,
354+ difficulty : 1 ,
355+ } ;
320356 assert_eq ! ( header, expected_header)
321357 }
322358}
0 commit comments