@@ -36,17 +36,25 @@ impl SqLiteEntity for BlockRangeRootRecord {
3636 Self : Sized ,
3737 {
3838 let start = try_to_u64 ( "block_range.start" , row. read :: < i64 , _ > ( 0 ) ) ?;
39- let _end = try_to_u64 ( "block_range.end" , row. read :: < i64 , _ > ( 1 ) ) ?;
39+ let end = try_to_u64 ( "block_range.end" , row. read :: < i64 , _ > ( 1 ) ) ?;
40+ let range = BlockRange :: from_block_number ( start) ;
4041 let merkle_root = row. read :: < & str , _ > ( 2 ) ;
4142
43+ if range. start != start || range. end != end {
44+ return Err ( HydrationError :: InvalidData ( format ! (
45+ "Invalid block range: start={start}, end={end}, expected_start={}, expected_end={}" ,
46+ range. start, range. end
47+ ) ) ) ;
48+ }
49+
4250 Ok ( Self {
43- range : BlockRange :: from_block_number ( start ) ,
51+ range,
4452 merkle_root : MKTreeNode :: from_hex ( merkle_root)
4553 . map_err ( |e| HydrationError :: InvalidData (
4654 format ! (
4755 "Field block_range.merkle_root (value={merkle_root}) is incompatible with hex representation. Error = {e}" )
4856 )
49- ) ?,
57+ ) ?,
5058 } )
5159 }
5260
@@ -58,3 +66,54 @@ impl SqLiteEntity for BlockRangeRootRecord {
5866 ] )
5967 }
6068}
69+
70+ #[ cfg( test) ]
71+ mod tests {
72+ use super :: * ;
73+ use mithril_common:: entities:: BlockNumber ;
74+ use sqlite:: Connection ;
75+
76+ fn select_block_range_from_db ( start : BlockNumber , end : BlockNumber , merkle_root : & str ) -> Row {
77+ let conn = Connection :: open ( ":memory:" ) . unwrap ( ) ;
78+ let query = format ! ( "SELECT {start}, {end}, '{merkle_root}'" ) ;
79+ let mut statement = conn. prepare ( query) . unwrap ( ) ;
80+ statement. iter ( ) . next ( ) . unwrap ( ) . unwrap ( )
81+ }
82+
83+ #[ test]
84+ fn hydrate_succeed_if_valid_block_range_in_row ( ) {
85+ // A valid block range has both bounds as multiples of block range length and the interval
86+ // size is equal to block range length.
87+ let row = select_block_range_from_db ( 0 , BlockRange :: LENGTH , "AAAA" ) ;
88+ let res = BlockRangeRootRecord :: hydrate ( row) . expect ( "Expected hydrate to succeed" ) ;
89+
90+ assert_eq ! (
91+ res,
92+ BlockRangeRootRecord {
93+ range: BlockRange :: from_block_number( 0 ) ,
94+ merkle_root: MKTreeNode :: from_hex( "AAAA" ) . unwrap( ) ,
95+ }
96+ ) ;
97+ }
98+
99+ #[ test]
100+ fn hydrate_fail_if_invalid_block_range_in_row ( ) {
101+ for invalid_row in [
102+ // Start is not a multiple of block range length
103+ select_block_range_from_db ( 1 , BlockRange :: LENGTH , "AAAA" ) ,
104+ // End is not a multiple of block range length
105+ select_block_range_from_db ( 0 , BlockRange :: LENGTH - 1 , "AAAA" ) ,
106+ // Interval is not equal to block range length
107+ select_block_range_from_db ( 0 , BlockRange :: LENGTH * 4 , "AAAA" ) ,
108+ ] {
109+ let res =
110+ BlockRangeRootRecord :: hydrate ( invalid_row) . expect_err ( "Expected hydrate to fail" ) ;
111+
112+ assert ! (
113+ format!( "{res:?}" ) . contains( "Invalid block range" ) ,
114+ "Expected 'Invalid block range' error, got {:?}" ,
115+ res
116+ ) ;
117+ }
118+ }
119+ }
0 commit comments