Skip to content

Commit 4a41d76

Browse files
committed
fix(validator): add missing emission to burn to preserve weight proportions
When total emission_weight from healthy challenges is < 1.0, the difference must be added to burn (UID 0) BEFORE normalization. This ensures each challenge's weights maintain their correct proportion: - term-challenge (emission=0.5, weight=1.0) -> 50% (not 66%) - bounty-challenge (emission=0.25) -> 25% total - Missing emission (0.25) -> burn Previously, normalization by total accumulated weight (0.75) would incorrectly inflate all weights proportionally.
1 parent dcc363f commit 4a41d76

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

bins/validator-node/src/main.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,37 @@ async fn handle_block_event(
10191019
}
10201020
}
10211021

1022+
// Add missing emission to burn (UID 0) to ensure weights sum to 1.0
1023+
// This preserves the correct proportions for each challenge's emission_weight
1024+
let total_emission: f64 = challenges
1025+
.iter()
1026+
.filter(|c| c.is_healthy)
1027+
.map(|c| c.emission_weight.clamp(0.0, 1.0))
1028+
.sum();
1029+
1030+
if total_emission < 0.999 {
1031+
let missing_emission = 1.0 - total_emission;
1032+
info!(
1033+
"Total emission from healthy challenges: {:.4}, adding {:.4} to burn",
1034+
total_emission, missing_emission
1035+
);
1036+
// Add missing emission to burn for each mechanism that has weights
1037+
// If no mechanisms have weights yet, create one for mechanism 0
1038+
if mechanism_uid_weights.is_empty() {
1039+
mechanism_uid_weights
1040+
.entry(0)
1041+
.or_default()
1042+
.insert(0, missing_emission);
1043+
} else {
1044+
// Distribute missing emission proportionally across mechanisms
1045+
// For simplicity, add to the first mechanism (they share the same burn UID 0)
1046+
if let Some((_, uid_weights)) = mechanism_uid_weights.iter_mut().next()
1047+
{
1048+
*uid_weights.entry(0).or_insert(0.0) += missing_emission;
1049+
}
1050+
}
1051+
}
1052+
10221053
// Convert HashMap<mechanism_id, HashMap<uid, weight_f64>> to Vec<(mech, uids, weights_u16)>
10231054
let mut weights: Vec<(u8, Vec<u16>, Vec<u16>)> = Vec::new();
10241055

@@ -1027,7 +1058,7 @@ async fn handle_block_event(
10271058
continue;
10281059
}
10291060

1030-
// Normalize weights to sum to 1.0, then convert to u16
1061+
// Total should now be ~1.0 after adding missing emission
10311062
let total: f64 = uid_weights.values().sum();
10321063
if total <= 0.0 {
10331064
// Should not happen, but fallback to 100% burn
@@ -1040,6 +1071,7 @@ async fn handle_block_event(
10401071
}
10411072

10421073
let uids: Vec<u16> = uid_weights.keys().copied().collect();
1074+
// Normalize by total (should be ~1.0 now)
10431075
let vals_f64: Vec<f64> = uids
10441076
.iter()
10451077
.map(|uid| uid_weights.get(uid).copied().unwrap_or(0.0) / total)

0 commit comments

Comments
 (0)