Files
aitbc/apps/blockchain-node/src/aitbc_chain/consensus/slashing.py
aitbc c876b0aa20 feat: implement AITBC mesh network deployment infrastructure
 Phase 0: Pre-implementation checklist completed
- Environment configurations (dev/staging/production)
- Directory structure setup (logs, backups, monitoring)
- Virtual environment with dependencies

 Master deployment script created
- Single command deployment with validation
- Progress tracking and rollback capability
- Health checks and deployment reporting

 Validation script created
- Module import validation
- Basic functionality testing
- Configuration and script verification

 Implementation fixes
- Fixed dataclass import in consensus keys
- Fixed async function syntax in tests
- Updated deployment script for virtual environment

🚀 Ready for deployment: ./scripts/deploy-mesh-network.sh dev
2026-04-02 12:08:15 +02:00

139 lines
5.6 KiB
Python

"""
Slashing Conditions Implementation
Handles detection and penalties for validator misbehavior
"""
import time
from typing import Dict, List, Optional, Set
from dataclasses import dataclass
from enum import Enum
from .multi_validator_poa import Validator, ValidatorRole
class SlashingCondition(Enum):
DOUBLE_SIGN = "double_sign"
UNAVAILABLE = "unavailable"
INVALID_BLOCK = "invalid_block"
SLOW_RESPONSE = "slow_response"
@dataclass
class SlashingEvent:
validator_address: str
condition: SlashingCondition
evidence: str
block_height: int
timestamp: float
slash_amount: float
class SlashingManager:
"""Manages validator slashing conditions and penalties"""
def __init__(self):
self.slashing_events: List[SlashingEvent] = []
self.slash_rates = {
SlashingCondition.DOUBLE_SIGN: 0.5, # 50% slash
SlashingCondition.UNAVAILABLE: 0.1, # 10% slash
SlashingCondition.INVALID_BLOCK: 0.3, # 30% slash
SlashingCondition.SLOW_RESPONSE: 0.05 # 5% slash
}
self.slash_thresholds = {
SlashingCondition.DOUBLE_SIGN: 1, # Immediate slash
SlashingCondition.UNAVAILABLE: 3, # After 3 offenses
SlashingCondition.INVALID_BLOCK: 1, # Immediate slash
SlashingCondition.SLOW_RESPONSE: 5 # After 5 offenses
}
def detect_double_sign(self, validator: str, block_hash1: str, block_hash2: str, height: int) -> Optional[SlashingEvent]:
"""Detect double signing (validator signed two different blocks at same height)"""
if block_hash1 == block_hash2:
return None
return SlashingEvent(
validator_address=validator,
condition=SlashingCondition.DOUBLE_SIGN,
evidence=f"Double sign detected: {block_hash1} vs {block_hash2} at height {height}",
block_height=height,
timestamp=time.time(),
slash_amount=self.slash_rates[SlashingCondition.DOUBLE_SIGN]
)
def detect_unavailability(self, validator: str, missed_blocks: int, height: int) -> Optional[SlashingEvent]:
"""Detect validator unavailability (missing consensus participation)"""
if missed_blocks < self.slash_thresholds[SlashingCondition.UNAVAILABLE]:
return None
return SlashingEvent(
validator_address=validator,
condition=SlashingCondition.UNAVAILABLE,
evidence=f"Missed {missed_blocks} consecutive blocks",
block_height=height,
timestamp=time.time(),
slash_amount=self.slash_rates[SlashingCondition.UNAVAILABLE]
)
def detect_invalid_block(self, validator: str, block_hash: str, reason: str, height: int) -> Optional[SlashingEvent]:
"""Detect invalid block proposal"""
return SlashingEvent(
validator_address=validator,
condition=SlashingCondition.INVALID_BLOCK,
evidence=f"Invalid block {block_hash}: {reason}",
block_height=height,
timestamp=time.time(),
slash_amount=self.slash_rates[SlashingCondition.INVALID_BLOCK]
)
def detect_slow_response(self, validator: str, response_time: float, threshold: float, height: int) -> Optional[SlashingEvent]:
"""Detect slow consensus participation"""
if response_time <= threshold:
return None
return SlashingEvent(
validator_address=validator,
condition=SlashingCondition.SLOW_RESPONSE,
evidence=f"Slow response: {response_time}s (threshold: {threshold}s)",
block_height=height,
timestamp=time.time(),
slash_amount=self.slash_rates[SlashingCondition.SLOW_RESPONSE]
)
def apply_slashing(self, validator: Validator, event: SlashingEvent) -> bool:
"""Apply slashing penalty to validator"""
slash_amount = validator.stake * event.slash_amount
validator.stake -= slash_amount
# Demote validator role if stake is too low
if validator.stake < 100: # Minimum stake threshold
validator.role = ValidatorRole.STANDBY
# Record slashing event
self.slashing_events.append(event)
return True
def get_validator_slash_count(self, validator_address: str, condition: SlashingCondition) -> int:
"""Get count of slashing events for validator and condition"""
return len([
event for event in self.slashing_events
if event.validator_address == validator_address and event.condition == condition
])
def should_slash(self, validator: str, condition: SlashingCondition) -> bool:
"""Check if validator should be slashed for condition"""
current_count = self.get_validator_slash_count(validator, condition)
threshold = self.slash_thresholds.get(condition, 1)
return current_count >= threshold
def get_slashing_history(self, validator_address: Optional[str] = None) -> List[SlashingEvent]:
"""Get slashing history for validator or all validators"""
if validator_address:
return [event for event in self.slashing_events if event.validator_address == validator_address]
return self.slashing_events.copy()
def calculate_total_slashed(self, validator_address: str) -> float:
"""Calculate total amount slashed for validator"""
events = self.get_slashing_history(validator_address)
return sum(event.slash_amount for event in events)
# Global slashing manager
slashing_manager = SlashingManager()