@@ -36,17 +36,25 @@ impl SqLiteEntity for BlockRangeRootRecord {
36
36
Self : Sized ,
37
37
{
38
38
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) ;
40
41
let merkle_root = row. read :: < & str , _ > ( 2 ) ;
41
42
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
+
42
50
Ok ( Self {
43
- range : BlockRange :: from_block_number ( start ) ,
51
+ range,
44
52
merkle_root : MKTreeNode :: from_hex ( merkle_root)
45
53
. map_err ( |e| HydrationError :: InvalidData (
46
54
format ! (
47
55
"Field block_range.merkle_root (value={merkle_root}) is incompatible with hex representation. Error = {e}" )
48
56
)
49
- ) ?,
57
+ ) ?,
50
58
} )
51
59
}
52
60
@@ -58,3 +66,54 @@ impl SqLiteEntity for BlockRangeRootRecord {
58
66
] )
59
67
}
60
68
}
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