@@ -1085,4 +1085,237 @@ mod tests {
10851085 42
10861086 ) ;
10871087 }
1088+
1089+ #[ tokio:: test]
1090+ async fn validator_tron_safety_merkle_tree_hook_uses_quorum_for_safety_reads ( ) {
1091+ let domain = dummy_domain ( 1337 , "test-domain" ) ;
1092+ let expected_tree = IncrementalMerkleAtBlock {
1093+ tree : Default :: default ( ) ,
1094+ block_height : Some ( 11 ) ,
1095+ } ;
1096+ let divergent_tree = IncrementalMerkleAtBlock {
1097+ tree : Default :: default ( ) ,
1098+ block_height : Some ( 12 ) ,
1099+ } ;
1100+ let expected_checkpoint = CheckpointAtBlock {
1101+ checkpoint : hyperlane_core:: Checkpoint {
1102+ merkle_tree_hook_address : H256 :: from_low_u64_be ( 11 ) ,
1103+ mailbox_domain : domain. id ( ) ,
1104+ root : H256 :: from_low_u64_be ( 22 ) ,
1105+ index : 7 ,
1106+ } ,
1107+ block_height : Some ( 99 ) ,
1108+ } ;
1109+ let divergent_checkpoint = CheckpointAtBlock {
1110+ checkpoint : hyperlane_core:: Checkpoint {
1111+ merkle_tree_hook_address : H256 :: from_low_u64_be ( 11 ) ,
1112+ mailbox_domain : domain. id ( ) ,
1113+ root : H256 :: from_low_u64_be ( 23 ) ,
1114+ index : 8 ,
1115+ } ,
1116+ block_height : Some ( 100 ) ,
1117+ } ;
1118+
1119+ let mut fallback = MockMerkleTreeHook :: new ( ) ;
1120+ fallback. expect_domain ( ) . return_const ( domain. clone ( ) ) ;
1121+ fallback
1122+ . expect_address ( )
1123+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1124+ fallback. expect_provider ( ) . never ( ) ;
1125+ fallback. expect_count ( ) . once ( ) . return_once ( |_| Ok ( 3 ) ) ;
1126+ fallback. expect_tree ( ) . never ( ) ;
1127+ fallback. expect_latest_checkpoint ( ) . never ( ) ;
1128+ fallback. expect_latest_checkpoint_at_block ( ) . never ( ) ;
1129+
1130+ let mut safety_a = MockMerkleTreeHook :: new ( ) ;
1131+ safety_a. expect_domain ( ) . return_const ( domain. clone ( ) ) ;
1132+ safety_a
1133+ . expect_address ( )
1134+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1135+ safety_a. expect_provider ( ) . never ( ) ;
1136+ safety_a. expect_count ( ) . never ( ) ;
1137+ safety_a. expect_tree ( ) . once ( ) . return_once ( {
1138+ let expected_tree = expected_tree. clone ( ) ;
1139+ move |_| Ok ( expected_tree)
1140+ } ) ;
1141+ safety_a. expect_latest_checkpoint ( ) . once ( ) . return_once ( {
1142+ let expected_checkpoint = expected_checkpoint. clone ( ) ;
1143+ move |_| Ok ( expected_checkpoint)
1144+ } ) ;
1145+ safety_a
1146+ . expect_latest_checkpoint_at_block ( )
1147+ . once ( )
1148+ . with ( mockall:: predicate:: eq ( 42 ) )
1149+ . return_once ( |height| {
1150+ Ok ( CheckpointAtBlock {
1151+ checkpoint : hyperlane_core:: Checkpoint {
1152+ merkle_tree_hook_address : H256 :: from_low_u64_be ( 11 ) ,
1153+ mailbox_domain : 1337 ,
1154+ root : H256 :: from_low_u64_be ( 33 ) ,
1155+ index : 9 ,
1156+ } ,
1157+ block_height : Some ( height) ,
1158+ } )
1159+ } ) ;
1160+
1161+ let mut safety_b = MockMerkleTreeHook :: new ( ) ;
1162+ safety_b. expect_domain ( ) . return_const ( domain. clone ( ) ) ;
1163+ safety_b
1164+ . expect_address ( )
1165+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1166+ safety_b. expect_provider ( ) . never ( ) ;
1167+ safety_b. expect_count ( ) . never ( ) ;
1168+ safety_b. expect_tree ( ) . once ( ) . return_once ( {
1169+ let expected_tree = expected_tree. clone ( ) ;
1170+ move |_| Ok ( expected_tree)
1171+ } ) ;
1172+ safety_b. expect_latest_checkpoint ( ) . once ( ) . return_once ( {
1173+ let expected_checkpoint = expected_checkpoint. clone ( ) ;
1174+ move |_| Ok ( expected_checkpoint)
1175+ } ) ;
1176+ safety_b
1177+ . expect_latest_checkpoint_at_block ( )
1178+ . once ( )
1179+ . with ( mockall:: predicate:: eq ( 42 ) )
1180+ . return_once ( |height| {
1181+ Ok ( CheckpointAtBlock {
1182+ checkpoint : hyperlane_core:: Checkpoint {
1183+ merkle_tree_hook_address : H256 :: from_low_u64_be ( 11 ) ,
1184+ mailbox_domain : 1337 ,
1185+ root : H256 :: from_low_u64_be ( 33 ) ,
1186+ index : 9 ,
1187+ } ,
1188+ block_height : Some ( height) ,
1189+ } )
1190+ } ) ;
1191+
1192+ let mut safety_c = MockMerkleTreeHook :: new ( ) ;
1193+ safety_c. expect_domain ( ) . return_const ( domain. clone ( ) ) ;
1194+ safety_c
1195+ . expect_address ( )
1196+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1197+ safety_c. expect_provider ( ) . never ( ) ;
1198+ safety_c. expect_count ( ) . never ( ) ;
1199+ safety_c
1200+ . expect_tree ( )
1201+ . once ( )
1202+ . return_once ( |_| Ok ( divergent_tree) ) ;
1203+ safety_c
1204+ . expect_latest_checkpoint ( )
1205+ . once ( )
1206+ . return_once ( |_| Ok ( divergent_checkpoint) ) ;
1207+ safety_c
1208+ . expect_latest_checkpoint_at_block ( )
1209+ . once ( )
1210+ . with ( mockall:: predicate:: eq ( 42 ) )
1211+ . return_once ( |height| {
1212+ Ok ( CheckpointAtBlock {
1213+ checkpoint : hyperlane_core:: Checkpoint {
1214+ merkle_tree_hook_address : H256 :: from_low_u64_be ( 11 ) ,
1215+ mailbox_domain : 1337 ,
1216+ root : H256 :: from_low_u64_be ( 44 ) ,
1217+ index : 10 ,
1218+ } ,
1219+ block_height : Some ( height) ,
1220+ } )
1221+ } ) ;
1222+
1223+ let hook = ValidatorTronSafetyMerkleTreeHook {
1224+ fallback : Arc :: new ( fallback) ,
1225+ safety_hooks : vec ! [ Arc :: new( safety_a) , Arc :: new( safety_b) , Arc :: new( safety_c) ] ,
1226+ } ;
1227+
1228+ assert_eq ! ( hook. count( & ReorgPeriod :: None ) . await . unwrap( ) , 3 ) ;
1229+ assert_eq ! (
1230+ hook. tree( & ReorgPeriod :: None ) . await . unwrap( ) . block_height,
1231+ Some ( 11 )
1232+ ) ;
1233+ assert_eq ! (
1234+ hook. latest_checkpoint( & ReorgPeriod :: None )
1235+ . await
1236+ . unwrap( )
1237+ . checkpoint
1238+ . index,
1239+ 7
1240+ ) ;
1241+ assert_eq ! (
1242+ hook. latest_checkpoint_at_block( 42 )
1243+ . await
1244+ . unwrap( )
1245+ . checkpoint
1246+ . index,
1247+ 9
1248+ ) ;
1249+ }
1250+
1251+ #[ tokio:: test]
1252+ async fn validator_tron_safety_merkle_tree_hook_errors_without_quorum ( ) {
1253+ let domain = dummy_domain ( 1337 , "test-domain" ) ;
1254+
1255+ let mut fallback = MockMerkleTreeHook :: new ( ) ;
1256+ fallback. expect_domain ( ) . return_const ( domain. clone ( ) ) ;
1257+ fallback
1258+ . expect_address ( )
1259+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1260+ fallback. expect_provider ( ) . never ( ) ;
1261+ fallback. expect_count ( ) . never ( ) ;
1262+ fallback. expect_tree ( ) . never ( ) ;
1263+ fallback. expect_latest_checkpoint ( ) . never ( ) ;
1264+ fallback. expect_latest_checkpoint_at_block ( ) . never ( ) ;
1265+
1266+ let mut safety_a = MockMerkleTreeHook :: new ( ) ;
1267+ safety_a. expect_domain ( ) . return_const ( domain. clone ( ) ) ;
1268+ safety_a
1269+ . expect_address ( )
1270+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1271+ safety_a. expect_provider ( ) . never ( ) ;
1272+ safety_a. expect_count ( ) . never ( ) ;
1273+ safety_a. expect_tree ( ) . once ( ) . return_once ( |_| {
1274+ Ok ( IncrementalMerkleAtBlock {
1275+ tree : Default :: default ( ) ,
1276+ block_height : Some ( 1 ) ,
1277+ } )
1278+ } ) ;
1279+ safety_a. expect_latest_checkpoint ( ) . never ( ) ;
1280+ safety_a. expect_latest_checkpoint_at_block ( ) . never ( ) ;
1281+
1282+ let mut safety_b = MockMerkleTreeHook :: new ( ) ;
1283+ safety_b. expect_domain ( ) . return_const ( domain. clone ( ) ) ;
1284+ safety_b
1285+ . expect_address ( )
1286+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1287+ safety_b. expect_provider ( ) . never ( ) ;
1288+ safety_b. expect_count ( ) . never ( ) ;
1289+ safety_b. expect_tree ( ) . once ( ) . return_once ( |_| {
1290+ Ok ( IncrementalMerkleAtBlock {
1291+ tree : Default :: default ( ) ,
1292+ block_height : Some ( 2 ) ,
1293+ } )
1294+ } ) ;
1295+ safety_b. expect_latest_checkpoint ( ) . never ( ) ;
1296+ safety_b. expect_latest_checkpoint_at_block ( ) . never ( ) ;
1297+
1298+ let mut safety_c = MockMerkleTreeHook :: new ( ) ;
1299+ safety_c. expect_domain ( ) . return_const ( domain) ;
1300+ safety_c
1301+ . expect_address ( )
1302+ . return_const ( H256 :: from_low_u64_be ( 11 ) ) ;
1303+ safety_c. expect_provider ( ) . never ( ) ;
1304+ safety_c. expect_count ( ) . never ( ) ;
1305+ safety_c. expect_tree ( ) . once ( ) . return_once ( |_| {
1306+ Ok ( IncrementalMerkleAtBlock {
1307+ tree : Default :: default ( ) ,
1308+ block_height : Some ( 3 ) ,
1309+ } )
1310+ } ) ;
1311+ safety_c. expect_latest_checkpoint ( ) . never ( ) ;
1312+ safety_c. expect_latest_checkpoint_at_block ( ) . never ( ) ;
1313+
1314+ let hook = ValidatorTronSafetyMerkleTreeHook {
1315+ fallback : Arc :: new ( fallback) ,
1316+ safety_hooks : vec ! [ Arc :: new( safety_a) , Arc :: new( safety_b) , Arc :: new( safety_c) ] ,
1317+ } ;
1318+
1319+ assert ! ( hook. tree( & ReorgPeriod :: None ) . await . is_err( ) ) ;
1320+ }
10881321}
0 commit comments