use crate::error::GovernanceError;
use crate::governance::types::{
verify_signature, GovernanceAction, GovernanceEffect, GovernanceState, SignedGovernanceMessage,
};
use crate::traits::GovernanceEngine;
pub struct SovereignEngine;
impl GovernanceEngine for SovereignEngine {
fn verify_action(
&self,
state: &mut GovernanceState,
msg: &SignedGovernanceMessage,
current_time_sec: u64,
) -> Result<Option<GovernanceEffect>, GovernanceError> {
if current_time_sec.abs_diff(msg.timestamp_sec) > crate::constants::MAX_AGE_SECONDS {
return Err(GovernanceError::StaleProposal);
}
let root_key = state.get_root_key()?;
let action_bytes = msg.to_canonical_bytes();
let root_signed = msg
.signatures
.iter()
.any(|sig| verify_signature(&root_key, &action_bytes, sig));
if root_signed {
match &msg.action {
GovernanceAction::GrantPremiumName { name, .. } => {
let label = name
.strip_suffix(crate::constants::TLD_SUFFIX)
.unwrap_or(name);
if label.len() != 1 {
return Err(GovernanceError::InvalidPremiumNameLength);
}
}
GovernanceAction::RevokePremiumName { name } => {
let label = name
.strip_suffix(crate::constants::TLD_SUFFIX)
.unwrap_or(name);
if label.len() != 1 {
return Err(GovernanceError::InvalidPremiumNameLength);
}
}
GovernanceAction::GrantInfrastructureName { name, .. } => {
if !crate::types::infrastructure::is_infrastructure_name(name) {
return Err(GovernanceError::InvalidInfrastructureName);
}
}
GovernanceAction::RevokeInfrastructureName { name } => {
if !crate::types::infrastructure::is_infrastructure_name(name) {
return Err(GovernanceError::InvalidInfrastructureName);
}
}
GovernanceAction::RotateRootKey { new_key } => {
if new_key.len() != 1952 {
return Err(GovernanceError::KeyLengthMismatch);
}
}
GovernanceAction::EmergencyHalt | GovernanceAction::EmergencyResume { .. } => {
}
}
let effect = self.execute_action(state, msg, current_time_sec);
return Ok(effect);
}
Err(GovernanceError::InsufficientSignatures)
}
fn execute_action(
&self,
state: &mut GovernanceState,
msg: &SignedGovernanceMessage,
_current_time_sec: u64,
) -> Option<GovernanceEffect> {
let action_hash = GovernanceState::hash_action(msg);
state.executed_hashes.insert(action_hash, msg.timestamp_sec);
match &msg.action {
GovernanceAction::GrantPremiumName {
name,
target_pubkey,
} => Some(GovernanceEffect::PremiumNameGranted {
name: name.clone(),
target_pubkey: target_pubkey.clone(),
}),
GovernanceAction::RevokePremiumName { name } => {
Some(GovernanceEffect::PremiumNameRevoked { name: name.clone() })
}
GovernanceAction::GrantInfrastructureName {
name,
target_pubkey,
} => Some(GovernanceEffect::InfrastructureNameGranted {
name: name.clone(),
target_pubkey: target_pubkey.clone(),
}),
GovernanceAction::RevokeInfrastructureName { name } => {
Some(GovernanceEffect::InfrastructureNameRevoked { name: name.clone() })
}
GovernanceAction::RotateRootKey { new_key } => {
state.active_root_key = Some(new_key.clone());
Some(GovernanceEffect::RootKeyRotated {
new_key: new_key.clone(),
})
}
GovernanceAction::EmergencyHalt => {
if !state.is_halted {
state.is_halted = true;
}
Some(GovernanceEffect::NetworkHalted)
}
GovernanceAction::EmergencyResume { paused_kyns } => {
if state.is_halted {
state.is_halted = false;
state.total_paused_kyns =
state.total_paused_kyns.saturating_add(*paused_kyns);
let end_kyn = msg.timestamp_sec.saturating_sub(crate::constants::KINETIC_GENESIS_TIME) / 3;
let start_kyn = end_kyn.saturating_sub(*paused_kyns);
state.pause_history.push((start_kyn, end_kyn));
}
Some(GovernanceEffect::NetworkResumed)
}
}
}
}