Files
aitbc/apps/blockchain-node/src/aitbc_chain/economics/attacks.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

492 lines
19 KiB
Python

"""
Economic Attack Prevention
Detects and prevents various economic attacks on the network
"""
import asyncio
import time
import json
from typing import Dict, List, Optional, Set, Tuple
from dataclasses import dataclass
from enum import Enum
from .staking import StakingManager
from .rewards import RewardDistributor
from .gas import GasManager
class AttackType(Enum):
SYBIL = "sybil"
STAKE_GRINDING = "stake_grinding"
NOTHING_AT_STAKE = "nothing_at_stake"
LONG_RANGE = "long_range"
FRONT_RUNNING = "front_running"
GAS_MANIPULATION = "gas_manipulation"
class ThreatLevel(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
@dataclass
class AttackDetection:
attack_type: AttackType
threat_level: ThreatLevel
attacker_address: str
evidence: Dict
detected_at: float
confidence: float
recommended_action: str
@dataclass
class SecurityMetric:
metric_name: str
current_value: float
threshold: float
status: str
last_updated: float
class EconomicSecurityMonitor:
"""Monitors and prevents economic attacks"""
def __init__(self, staking_manager: StakingManager, reward_distributor: RewardDistributor,
gas_manager: GasManager):
self.staking_manager = staking_manager
self.reward_distributor = reward_distributor
self.gas_manager = gas_manager
self.detection_rules = self._initialize_detection_rules()
self.attack_detections: List[AttackDetection] = []
self.security_metrics: Dict[str, SecurityMetric] = {}
self.blacklisted_addresses: Set[str] = set()
# Monitoring parameters
self.monitoring_interval = 60 # seconds
self.detection_history_window = 3600 # 1 hour
self.max_false_positive_rate = 0.05 # 5%
# Initialize security metrics
self._initialize_security_metrics()
def _initialize_detection_rules(self) -> Dict[AttackType, Dict]:
"""Initialize detection rules for different attack types"""
return {
AttackType.SYBIL: {
'threshold': 0.1, # 10% of validators from same entity
'min_stake': 1000.0,
'time_window': 86400, # 24 hours
'max_similar_addresses': 5
},
AttackType.STAKE_GRINDING: {
'threshold': 0.3, # 30% stake variation
'min_operations': 10,
'time_window': 3600, # 1 hour
'max_withdrawal_frequency': 5
},
AttackType.NOTHING_AT_STAKE: {
'threshold': 0.5, # 50% abstention rate
'min_validators': 10,
'time_window': 7200, # 2 hours
'max_abstention_periods': 3
},
AttackType.LONG_RANGE: {
'threshold': 0.8, # 80% stake from old keys
'min_history_depth': 1000,
'time_window': 604800, # 1 week
'max_key_reuse': 2
},
AttackType.FRONT_RUNNING: {
'threshold': 0.1, # 10% transaction front-running
'min_transactions': 100,
'time_window': 3600, # 1 hour
'max_mempool_advantage': 0.05
},
AttackType.GAS_MANIPULATION: {
'threshold': 2.0, # 2x price manipulation
'min_price_changes': 5,
'time_window': 1800, # 30 minutes
'max_spikes_per_hour': 3
}
}
def _initialize_security_metrics(self):
"""Initialize security monitoring metrics"""
self.security_metrics = {
'validator_diversity': SecurityMetric(
metric_name='validator_diversity',
current_value=0.0,
threshold=0.7,
status='healthy',
last_updated=time.time()
),
'stake_distribution': SecurityMetric(
metric_name='stake_distribution',
current_value=0.0,
threshold=0.8,
status='healthy',
last_updated=time.time()
),
'reward_distribution': SecurityMetric(
metric_name='reward_distribution',
current_value=0.0,
threshold=0.9,
status='healthy',
last_updated=time.time()
),
'gas_price_stability': SecurityMetric(
metric_name='gas_price_stability',
current_value=0.0,
threshold=0.3,
status='healthy',
last_updated=time.time()
)
}
async def start_monitoring(self):
"""Start economic security monitoring"""
log_info("Starting economic security monitoring")
while True:
try:
await self._monitor_security_metrics()
await self._detect_attacks()
await self._update_blacklist()
await asyncio.sleep(self.monitoring_interval)
except Exception as e:
log_error(f"Security monitoring error: {e}")
await asyncio.sleep(10)
async def _monitor_security_metrics(self):
"""Monitor security metrics"""
current_time = time.time()
# Update validator diversity
await self._update_validator_diversity(current_time)
# Update stake distribution
await self._update_stake_distribution(current_time)
# Update reward distribution
await self._update_reward_distribution(current_time)
# Update gas price stability
await self._update_gas_price_stability(current_time)
async def _update_validator_diversity(self, current_time: float):
"""Update validator diversity metric"""
validators = self.staking_manager.get_active_validators()
if len(validators) < 10:
diversity_score = 0.0
else:
# Calculate diversity based on stake distribution
total_stake = sum(v.total_stake for v in validators)
if total_stake == 0:
diversity_score = 0.0
else:
# Use Herfindahl-Hirschman Index
stake_shares = [float(v.total_stake / total_stake) for v in validators]
hhi = sum(share ** 2 for share in stake_shares)
diversity_score = 1.0 - hhi
metric = self.security_metrics['validator_diversity']
metric.current_value = diversity_score
metric.last_updated = current_time
if diversity_score < metric.threshold:
metric.status = 'warning'
else:
metric.status = 'healthy'
async def _update_stake_distribution(self, current_time: float):
"""Update stake distribution metric"""
validators = self.staking_manager.get_active_validators()
if not validators:
distribution_score = 0.0
else:
# Check for concentration (top 3 validators)
stakes = [float(v.total_stake) for v in validators]
stakes.sort(reverse=True)
total_stake = sum(stakes)
if total_stake == 0:
distribution_score = 0.0
else:
top3_share = sum(stakes[:3]) / total_stake
distribution_score = 1.0 - top3_share
metric = self.security_metrics['stake_distribution']
metric.current_value = distribution_score
metric.last_updated = current_time
if distribution_score < metric.threshold:
metric.status = 'warning'
else:
metric.status = 'healthy'
async def _update_reward_distribution(self, current_time: float):
"""Update reward distribution metric"""
distributions = self.reward_distributor.get_distribution_history(limit=10)
if len(distributions) < 5:
distribution_score = 1.0 # Not enough data
else:
# Check for reward concentration
total_rewards = sum(dist.total_rewards for dist in distributions)
if total_rewards == 0:
distribution_score = 0.0
else:
# Calculate variance in reward distribution
validator_rewards = []
for dist in distributions:
validator_rewards.extend(dist.validator_rewards.values())
if not validator_rewards:
distribution_score = 0.0
else:
avg_reward = sum(validator_rewards) / len(validator_rewards)
variance = sum((r - avg_reward) ** 2 for r in validator_rewards) / len(validator_rewards)
cv = (variance ** 0.5) / avg_reward if avg_reward > 0 else 0
distribution_score = max(0.0, 1.0 - cv)
metric = self.security_metrics['reward_distribution']
metric.current_value = distribution_score
metric.last_updated = current_time
if distribution_score < metric.threshold:
metric.status = 'warning'
else:
metric.status = 'healthy'
async def _update_gas_price_stability(self, current_time: float):
"""Update gas price stability metric"""
gas_stats = self.gas_manager.get_gas_statistics()
if gas_stats['price_history_length'] < 10:
stability_score = 1.0 # Not enough data
else:
stability_score = 1.0 - gas_stats['price_volatility']
metric = self.security_metrics['gas_price_stability']
metric.current_value = stability_score
metric.last_updated = current_time
if stability_score < metric.threshold:
metric.status = 'warning'
else:
metric.status = 'healthy'
async def _detect_attacks(self):
"""Detect potential economic attacks"""
current_time = time.time()
# Detect Sybil attacks
await self._detect_sybil_attacks(current_time)
# Detect stake grinding
await self._detect_stake_grinding(current_time)
# Detect nothing-at-stake
await self._detect_nothing_at_stake(current_time)
# Detect long-range attacks
await self._detect_long_range_attacks(current_time)
# Detect front-running
await self._detect_front_running(current_time)
# Detect gas manipulation
await self._detect_gas_manipulation(current_time)
async def _detect_sybil_attacks(self, current_time: float):
"""Detect Sybil attacks (multiple identities)"""
rule = self.detection_rules[AttackType.SYBIL]
validators = self.staking_manager.get_active_validators()
# Group validators by similar characteristics
address_groups = {}
for validator in validators:
# Simple grouping by address prefix (more sophisticated in real implementation)
prefix = validator.validator_address[:8]
if prefix not in address_groups:
address_groups[prefix] = []
address_groups[prefix].append(validator)
# Check for suspicious groups
for prefix, group in address_groups.items():
if len(group) >= rule['max_similar_addresses']:
# Calculate threat level
group_stake = sum(v.total_stake for v in group)
total_stake = sum(v.total_stake for v in validators)
stake_ratio = float(group_stake / total_stake) if total_stake > 0 else 0
if stake_ratio > rule['threshold']:
threat_level = ThreatLevel.HIGH
elif stake_ratio > rule['threshold'] * 0.5:
threat_level = ThreatLevel.MEDIUM
else:
threat_level = ThreatLevel.LOW
# Create detection
detection = AttackDetection(
attack_type=AttackType.SYBIL,
threat_level=threat_level,
attacker_address=prefix,
evidence={
'similar_addresses': [v.validator_address for v in group],
'group_size': len(group),
'stake_ratio': stake_ratio,
'common_prefix': prefix
},
detected_at=current_time,
confidence=0.8,
recommended_action='Investigate validator identities'
)
self.attack_detections.append(detection)
async def _detect_stake_grinding(self, current_time: float):
"""Detect stake grinding attacks"""
rule = self.detection_rules[AttackType.STAKE_GRINDING]
# Check for frequent stake changes
recent_detections = [
d for d in self.attack_detections
if d.attack_type == AttackType.STAKE_GRINDING and
current_time - d.detected_at < rule['time_window']
]
# This would analyze staking patterns (simplified here)
# In real implementation, would track stake movements over time
pass # Placeholder for stake grinding detection
async def _detect_nothing_at_stake(self, current_time: float):
"""Detect nothing-at-stake attacks"""
rule = self.detection_rules[AttackType.NOTHING_AT_STAKE]
# Check for validator participation rates
# This would require consensus participation data
pass # Placeholder for nothing-at-stake detection
async def _detect_long_range_attacks(self, current_time: float):
"""Detect long-range attacks"""
rule = self.detection_rules[AttackType.LONG_RANGE]
# Check for key reuse from old blockchain states
# This would require historical blockchain data
pass # Placeholder for long-range attack detection
async def _detect_front_running(self, current_time: float):
"""Detect front-running attacks"""
rule = self.detection_rules[AttackType.FRONT_RUNNING]
# Check for transaction ordering patterns
# This would require mempool and transaction ordering data
pass # Placeholder for front-running detection
async def _detect_gas_manipulation(self, current_time: float):
"""Detect gas price manipulation"""
rule = self.detection_rules[AttackType.GAS_MANIPULATION]
gas_stats = self.gas_manager.get_gas_statistics()
# Check for unusual gas price spikes
if gas_stats['price_history_length'] >= 10:
recent_prices = [p.price_per_gas for p in self.gas_manager.price_history[-10:]]
avg_price = sum(recent_prices) / len(recent_prices)
# Look for significant spikes
for price in recent_prices:
if float(price / avg_price) > rule['threshold']:
detection = AttackDetection(
attack_type=AttackType.GAS_MANIPULATION,
threat_level=ThreatLevel.MEDIUM,
attacker_address="unknown", # Would need more sophisticated detection
evidence={
'spike_ratio': float(price / avg_price),
'current_price': float(price),
'average_price': float(avg_price)
},
detected_at=current_time,
confidence=0.6,
recommended_action='Monitor gas price patterns'
)
self.attack_detections.append(detection)
break
async def _update_blacklist(self):
"""Update blacklist based on detections"""
current_time = time.time()
# Remove old detections from history
self.attack_detections = [
d for d in self.attack_detections
if current_time - d.detected_at < self.detection_history_window
]
# Add high-confidence, high-threat attackers to blacklist
for detection in self.attack_detections:
if (detection.threat_level in [ThreatLevel.HIGH, ThreatLevel.CRITICAL] and
detection.confidence > 0.8 and
detection.attacker_address not in self.blacklisted_addresses):
self.blacklisted_addresses.add(detection.attacker_address)
log_warn(f"Added {detection.attacker_address} to blacklist due to {detection.attack_type.value} attack")
def is_address_blacklisted(self, address: str) -> bool:
"""Check if address is blacklisted"""
return address in self.blacklisted_addresses
def get_attack_summary(self) -> Dict:
"""Get summary of detected attacks"""
current_time = time.time()
recent_detections = [
d for d in self.attack_detections
if current_time - d.detected_at < 3600 # Last hour
]
attack_counts = {}
threat_counts = {}
for detection in recent_detections:
attack_type = detection.attack_type.value
threat_level = detection.threat_level.value
attack_counts[attack_type] = attack_counts.get(attack_type, 0) + 1
threat_counts[threat_level] = threat_counts.get(threat_level, 0) + 1
return {
'total_detections': len(recent_detections),
'attack_types': attack_counts,
'threat_levels': threat_counts,
'blacklisted_addresses': len(self.blacklisted_addresses),
'security_metrics': {
name: {
'value': metric.current_value,
'threshold': metric.threshold,
'status': metric.status
}
for name, metric in self.security_metrics.items()
}
}
# Global security monitor
security_monitor: Optional[EconomicSecurityMonitor] = None
def get_security_monitor() -> Optional[EconomicSecurityMonitor]:
"""Get global security monitor"""
return security_monitor
def create_security_monitor(staking_manager: StakingManager, reward_distributor: RewardDistributor,
gas_manager: GasManager) -> EconomicSecurityMonitor:
"""Create and set global security monitor"""
global security_monitor
security_monitor = EconomicSecurityMonitor(staking_manager, reward_distributor, gas_manager)
return security_monitor