Skip to content

Commit 63010ef

Browse files
author
Nam's Office Computer
committed
test(validator): cover tron safety quorum hook
1 parent c0034f9 commit 63010ef

1 file changed

Lines changed: 233 additions & 0 deletions

File tree

rust/main/agents/validator/src/validator.rs

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)