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

Commit 5a25777

Browse files
authored
imp(validator): ability to pick invalidation type for rejection (#542)
* ability to pick invalidation type for rejection
1 parent f401ed4 commit 5a25777

8 files changed

Lines changed: 1510 additions & 1414 deletions

File tree

crates/validator/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ $([ "$DISABLE_TOPLOC_INVALIDATION" = "true" ] && echo "--disable-toploc-invalida
4242
$([ ! -z "$INCOMPLETE_GROUP_GRACE_PERIOD_MINUTES" ] && echo "--incomplete-group-grace-period-minutes $INCOMPLETE_GROUP_GRACE_PERIOD_MINUTES") \
4343
$([ ! -z "$VALIDATOR_PENALTY" ] && echo "--validator-penalty $VALIDATOR_PENALTY") \
4444
$([ "$DISABLE_HARDWARE_VALIDATION" = "true" ] && echo "--disable-hardware-validation") \
45+
$([ ! -z "$TOPLOC_INVALIDATION_TYPE" ] && echo "--toploc-invalidation-type $TOPLOC_INVALIDATION_TYPE") \
46+
$([ ! -z "$WORK_UNIT_INVALIDATION_TYPE" ] && echo "--work-unit-invalidation-type $WORK_UNIT_INVALIDATION_TYPE") \
4547
"$@"' > /entrypoint.sh && \
4648
chmod +x /entrypoint.sh
4749

crates/validator/src/main.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use url::Url;
3131
use validators::hardware::HardwareValidator;
3232
use validators::synthetic_data::SyntheticDataValidator;
3333

34+
use crate::validators::synthetic_data::types::InvalidationType;
3435
// Track the last time the validation loop ran
3536
static LAST_VALIDATION_TIMESTAMP: AtomicI64 = AtomicI64::new(0);
3637
// Maximum allowed time between validation loops (2 minutes)
@@ -179,6 +180,14 @@ struct Args {
179180
#[arg(long, default_value = "0")]
180181
incomplete_group_grace_period_minutes: u64,
181182

183+
/// Optional: toploc invalidation type
184+
#[arg(long, default_value = "hard")]
185+
toploc_invalidation_type: InvalidationType,
186+
187+
/// Optional: work unit invalidation type
188+
#[arg(long, default_value = "hard")]
189+
work_unit_invalidation_type: InvalidationType,
190+
182191
/// Optional: Validator penalty in whole tokens
183192
/// Note: This value will be multiplied by 10^18 (1 token = 10^18 wei)
184193
#[arg(long, default_value = "200")]
@@ -359,6 +368,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
359368
args.use_grouping,
360369
args.disable_toploc_invalidation,
361370
args.incomplete_group_grace_period_minutes,
371+
args.toploc_invalidation_type,
372+
args.work_unit_invalidation_type,
362373
Some(metrics_ctx.clone()),
363374
))
364375
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
use super::*;
2+
3+
impl SyntheticDataValidator<WalletProvider> {
4+
pub async fn soft_invalidate_work(&self, work_key: &str) -> Result<(), Error> {
5+
info!("Soft invalidating work: {}", work_key);
6+
7+
if self.disable_chain_invalidation {
8+
info!("Chain invalidation is disabled, skipping work soft invalidation");
9+
return Ok(());
10+
}
11+
12+
// Special case for tests - skip actual blockchain interaction
13+
#[cfg(test)]
14+
{
15+
info!("Test mode: skipping actual work soft invalidation");
16+
let _ = &self.prime_network;
17+
Ok(())
18+
}
19+
20+
#[cfg(not(test))]
21+
{
22+
let work_info = self
23+
.get_work_info_from_redis(work_key)
24+
.await?
25+
.ok_or_else(|| Error::msg("Work info not found for soft invalidation"))?;
26+
let work_key_bytes = hex::decode(work_key)
27+
.map_err(|e| Error::msg(format!("Failed to decode hex work key: {}", e)))?;
28+
29+
// Create 64-byte payload: work_key (32 bytes) + work_units (32 bytes)
30+
let mut data = Vec::with_capacity(64);
31+
data.extend_from_slice(&work_key_bytes);
32+
33+
// Convert work_units to 32-byte representation
34+
let work_units_bytes = work_info.work_units.to_be_bytes::<32>();
35+
data.extend_from_slice(&work_units_bytes);
36+
37+
match self
38+
.prime_network
39+
.soft_invalidate_work(self.pool_id, data)
40+
.await
41+
{
42+
Ok(_) => Ok(()),
43+
Err(e) => {
44+
error!("Failed to soft invalidate work {}: {}", work_key, e);
45+
Err(Error::msg(format!("Failed to soft invalidate work: {}", e)))
46+
}
47+
}
48+
}
49+
}
50+
51+
pub async fn invalidate_work(&self, work_key: &str) -> Result<(), Error> {
52+
info!("Invalidating work: {}", work_key);
53+
54+
if let Some(metrics) = &self.metrics {
55+
metrics.record_work_key_invalidation();
56+
}
57+
58+
if self.disable_chain_invalidation {
59+
info!("Chain invalidation is disabled, skipping work invalidation");
60+
return Ok(());
61+
}
62+
63+
#[cfg(test)]
64+
{
65+
info!("Test mode: skipping actual work invalidation");
66+
let _ = &self.prime_network;
67+
let _ = &self.penalty;
68+
Ok(())
69+
}
70+
71+
#[cfg(not(test))]
72+
{
73+
let data = hex::decode(work_key)
74+
.map_err(|e| Error::msg(format!("Failed to decode hex work key: {}", e)))?;
75+
match self
76+
.prime_network
77+
.invalidate_work(self.pool_id, self.penalty, data)
78+
.await
79+
{
80+
Ok(_) => Ok(()),
81+
Err(e) => {
82+
error!("Failed to invalidate work {}: {}", work_key, e);
83+
Err(Error::msg(format!("Failed to invalidate work: {}", e)))
84+
}
85+
}
86+
}
87+
}
88+
89+
pub async fn invalidate_according_to_invalidation_type(
90+
&self,
91+
work_key: &str,
92+
invalidation_type: InvalidationType,
93+
) -> Result<(), Error> {
94+
match invalidation_type {
95+
InvalidationType::Soft => self.soft_invalidate_work(work_key).await,
96+
InvalidationType::Hard => self.invalidate_work(work_key).await,
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)