Skip to content
This repository was archived by the owner on Jan 27, 2026. It is now read-only.

Commit d4f8664

Browse files
authored
fix(validator): check if work info returned by contract is zero (#581)
* check if work info returned by contract is zero
1 parent 8be9bcf commit d4f8664

3 files changed

Lines changed: 66 additions & 13 deletions

File tree

crates/shared/src/web3/contracts/implementations/work_validators/synthetic_data_validator.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ pub struct WorkInfo {
2020
pub work_units: U256,
2121
}
2222

23+
impl WorkInfo {
24+
pub fn is_valid(&self) -> bool {
25+
self.node_id != Address::ZERO
26+
&& self.work_units != U256::ZERO
27+
&& self.provider != Address::ZERO
28+
}
29+
}
30+
2331
impl<P: alloy_provider::Provider> SyntheticDataWorkValidator<P> {
2432
pub fn new(address: Address, provider: P, abi_file_path: &str) -> Self {
2533
let instance = Contract::new(address, provider, abi_file_path);

crates/validator/src/validators/synthetic_data/mod.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ impl SyntheticDataValidator<WalletProvider> {
414414
let validation_info = self.get_work_validation_info_from_redis(work_key).await?;
415415
Ok(validation_info.map(|info| info.status))
416416
}
417+
417418
#[cfg(test)]
418419
async fn get_work_validation_info_from_redis(
419420
&self,
@@ -483,12 +484,21 @@ impl SyntheticDataValidator<WalletProvider> {
483484
.get(&key)
484485
.await
485486
.map_err(|e| Error::msg(format!("Failed to get work info: {}", e)))?;
486-
work_info
487-
.map(|work_info| {
488-
serde_json::from_str(&work_info)
489-
.map_err(|e| Error::msg(format!("Failed to parse work info: {}", e)))
490-
})
491-
.transpose()
487+
488+
match work_info {
489+
Some(work_info_str) => {
490+
let work_info: WorkInfo = serde_json::from_str(&work_info_str)
491+
.map_err(|e| Error::msg(format!("Failed to parse work info: {}", e)))?;
492+
493+
// Check if work_info has invalid values
494+
if !work_info.is_valid() {
495+
Ok(None)
496+
} else {
497+
Ok(Some(work_info))
498+
}
499+
}
500+
None => Ok(None),
501+
}
492502
}
493503

494504
async fn get_file_name_for_work_key(
@@ -896,7 +906,15 @@ impl SyntheticDataValidator<WalletProvider> {
896906
let pool_id = self.pool_id;
897907
async move {
898908
match validator.get_work_info(pool_id, &work_key).await {
899-
Ok(work_info) => Some((work_key, work_info)),
909+
Ok(work_info) => {
910+
match !work_info.is_valid() {
911+
true => {
912+
error!("Got zero/default work info for key {}, likely not yet in contract", work_key);
913+
None
914+
}
915+
false => Some((work_key, work_info)),
916+
}
917+
}
900918
Err(e) => {
901919
error!("Failed to get work info for {}: {}", work_key, e);
902920
None
@@ -1247,6 +1265,7 @@ impl SyntheticDataValidator<WalletProvider> {
12471265
}
12481266

12491267
pub async fn process_group_status_check(&self, group: ToplocGroup) -> Result<(), Error> {
1268+
println!("processing group status check: {:?}", group);
12501269
let toploc_config = self
12511270
.find_matching_toploc_config(&group.prefix)
12521271
.ok_or(Error::msg(format!(
@@ -1258,6 +1277,8 @@ impl SyntheticDataValidator<WalletProvider> {
12581277
.get_group_file_validation_status(&group.group_file_name)
12591278
.await?;
12601279
let toploc_config_name = toploc_config.name();
1280+
println!("toploc config name: {:?}", toploc_config_name);
1281+
println!("status: {:?}", status);
12611282

12621283
if let Some(metrics) = &self.metrics {
12631284
metrics.record_group_validation_status(
@@ -1282,6 +1303,9 @@ impl SyntheticDataValidator<WalletProvider> {
12821303

12831304
let mut toploc_nodes_to_invalidate = Vec::new();
12841305
let mut nodes_with_wrong_work_unit_claims = Vec::new();
1306+
println!("node_work_units: {:?}", node_work_units);
1307+
println!("total_claimed_units: {:?}", total_claimed_units);
1308+
println!("toploc status: {:?}", status.status);
12851309

12861310
if status.status == ValidationResult::Reject {
12871311
let rejected_nodes = self.handle_group_toploc_rejection(&group, &status).await?;
@@ -1299,6 +1323,15 @@ impl SyntheticDataValidator<WalletProvider> {
12991323
nodes_with_wrong_work_unit_claims.extend(wrong_claim_nodes);
13001324
}
13011325

1326+
println!(
1327+
"toploc_nodes_to_invalidate: {:?}",
1328+
toploc_nodes_to_invalidate
1329+
);
1330+
println!(
1331+
"nodes_with_wrong_work_unit_claims: {:?}",
1332+
nodes_with_wrong_work_unit_claims
1333+
);
1334+
13021335
for work_key in &group.sorted_work_keys {
13031336
if let Some(work_info) = self.get_work_info_from_redis(work_key).await? {
13041337
let node_id_str = work_info.node_id.to_string();

crates/validator/src/validators/synthetic_data/tests/mod.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ async fn test_build_validation_plan() -> Result<(), Error> {
135135
];
136136

137137
let work_info = WorkInfo {
138-
node_id: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(),
138+
node_id: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
139+
provider: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
140+
work_units: U256::from(1000),
139141
..Default::default()
140142
};
141143
for work_key in work_keys.clone() {
@@ -337,7 +339,7 @@ async fn test_group_e2e_accept() -> Result<(), Error> {
337339

338340
const FILE_SHA: &str = "c257e3d3fe866a00df1285f8bbbe601fed6b85229d983bbbb75e19a068346641";
339341
const GROUP_ID: &str = "3450756714426841564";
340-
const NODE_ADDRESS: &str = "0x0000000000000000000000000000000000000000";
342+
const NODE_ADDRESS: &str = "0xA1DDe6E4d2F127960e7C61f90a8b354Bc306bd2a";
341343

342344
let mock_storage = MockStorageProvider::new();
343345
mock_storage
@@ -372,7 +374,7 @@ async fn test_group_e2e_accept() -> Result<(), Error> {
372374
format!("/statusgroup/dataset/samplingn-{}-1-0.parquet", GROUP_ID).as_str(),
373375
)
374376
.with_status(200)
375-
.with_body(r#"{"status": "accept"}"#)
377+
.with_body(r#"{"status": "accept", "input_flops": 1, "output_flops": 1000}"#)
376378
.create();
377379

378380
let storage_provider = Arc::new(mock_storage);
@@ -403,6 +405,8 @@ async fn test_group_e2e_accept() -> Result<(), Error> {
403405

404406
let work_info = WorkInfo {
405407
node_id: Address::from_str(NODE_ADDRESS).unwrap(),
408+
work_units: U256::from(1000),
409+
provider: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
406410
..Default::default()
407411
};
408412
for work_key in work_keys.clone() {
@@ -475,12 +479,12 @@ async fn test_group_e2e_work_unit_mismatch() -> Result<(), Error> {
475479
..Default::default()
476480
};
477481

478-
const HONEST_NODE_ADDRESS: &str = "0x0000000000000000000000000000000000000001";
482+
const HONEST_NODE_ADDRESS: &str = "0x182555b0Ab39EE313f22c07dbe88D950385b1f69";
479483
const HONEST_FILE_SHA: &str =
480484
"c257e3d3fe866a00df1285f8bbbe601fed6b85229d983bbbb75e19a068346641";
481485
const EXCESSIVE_FILE_SHA: &str =
482486
"88e4672c19e5a10bff2e23d223f8bfc38ae1425feaa18db9480e631a4fd98edf";
483-
const EXCESSIVE_NODE_ADDRESS: &str = "0x0000000000000000000000000000000000000002";
487+
const EXCESSIVE_NODE_ADDRESS: &str = "0x182555b0Ab39EE313f22c07dbe88D950385b1f68";
484488
const GROUP_ID: &str = "3456714426841564";
485489

486490
let mock_storage = MockStorageProvider::new();
@@ -562,11 +566,13 @@ async fn test_group_e2e_work_unit_mismatch() -> Result<(), Error> {
562566
let work_info_1 = WorkInfo {
563567
node_id: Address::from_str(HONEST_NODE_ADDRESS).unwrap(),
564568
work_units: U256::from(EXPECTED_WORK_UNITS),
569+
provider: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
565570
..Default::default()
566571
};
567572
let work_info_2 = WorkInfo {
568573
node_id: Address::from_str(EXCESSIVE_NODE_ADDRESS).unwrap(),
569574
work_units: U256::from(EXCESSIVE_WORK_UNITS),
575+
provider: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f67").unwrap(),
570576
..Default::default()
571577
};
572578

@@ -781,6 +787,8 @@ async fn test_incomplete_group_recovery() -> Result<(), Error> {
781787
// Add work info for only the first file (making the group incomplete)
782788
let work_info = WorkInfo {
783789
node_id: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(),
790+
work_units: U256::from(1000),
791+
provider: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
784792
..Default::default()
785793
};
786794
validator
@@ -880,6 +888,8 @@ async fn test_expired_incomplete_group_soft_invalidation() -> Result<(), Error>
880888
// Add work info for only the first file (making the group incomplete)
881889
let work_info = WorkInfo {
882890
node_id: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(),
891+
work_units: U256::from(1000),
892+
provider: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
883893
..Default::default()
884894
};
885895
validator
@@ -981,7 +991,9 @@ async fn test_incomplete_group_status_tracking() -> Result<(), Error> {
981991

982992
// Add work info for only 1 of 3 expected files
983993
let work_info = WorkInfo {
984-
node_id: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(),
994+
node_id: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
995+
work_units: U256::from(1000),
996+
provider: Address::from_str("0x182555b0Ab39EE313f22c07dbe88D950385b1f68").unwrap(),
985997
..Default::default()
986998
};
987999
validator

0 commit comments

Comments
 (0)