dig_network_block/
emission_config.rs

1//! Consensus emission configuration.
2//!
3//! This module defines `ConsensusEmissionConfig`, which controls how proposer
4//! and attester reward weights are assigned when building required consensus
5//! emissions for a block.
6//!
7//! Validation helpers ensure obvious configuration mistakes are surfaced (e.g.,
8//! non-zero attester share with zero attesters).
9
10use thiserror::Error;
11
12/// Configuration for consensus emissions.
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct ConsensusEmissionConfig {
15    /// Fixed proposer share (e.g., 12 for 12.5%).
16    pub proposer_reward_share: u64,
17    /// Total attester share that will be equally split among attesters using
18    /// integer division; remainder (if any) is undistributed.
19    pub attester_reward_share: u64,
20}
21
22impl ConsensusEmissionConfig {
23    /// Create a new config.
24    pub fn new(proposer_reward_share: u64, attester_reward_share: u64) -> Self {
25        Self {
26            proposer_reward_share,
27            attester_reward_share,
28        }
29    }
30
31    /// Validate the config against a given number of attesters.
32    ///
33    /// Policy: if there are zero attesters, `attester_reward_share` must be 0;
34    /// otherwise the split would be undefined.
35    pub fn validate_for_attesters(&self, attesters_len: usize) -> Result<(), EmissionConfigError> {
36        if attesters_len == 0 && self.attester_reward_share > 0 {
37            return Err(EmissionConfigError::NonZeroAttesterShareWithNoAttesters);
38        }
39        Ok(())
40    }
41}
42
43/// Errors that can be produced by configuration validation.
44#[derive(Debug, Error)]
45pub enum EmissionConfigError {
46    /// `attester_reward_share > 0` while there are zero attesters.
47    #[error("non-zero attester share configured but no attesters provided")]
48    NonZeroAttesterShareWithNoAttesters,
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn validate_zero_attesters_policy() {
57        let cfg = ConsensusEmissionConfig::new(12, 0);
58        assert!(cfg.validate_for_attesters(0).is_ok());
59
60        let cfg_bad = ConsensusEmissionConfig::new(12, 1);
61        let err = cfg_bad.validate_for_attesters(0).unwrap_err();
62        match err {
63            EmissionConfigError::NonZeroAttesterShareWithNoAttesters => {}
64        }
65    }
66
67    #[test]
68    fn validate_with_attesters_ok() {
69        let cfg = ConsensusEmissionConfig::new(12, 88);
70        assert!(cfg.validate_for_attesters(3).is_ok());
71    }
72}