NAC_Blockchain/nvm_v2/nvm-l0/src/fluid_block_model.rs

783 lines
24 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Fluid Block Model (FBM)
// 流体区块模型 - 动态调整区块大小和出块频率
use serde::{Deserialize, Serialize};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
/// 流体区块配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FluidBlockConfig {
/// 最小出块间隔(毫秒)
pub min_block_interval_ms: u64,
/// 初始软上限(字节)
pub initial_soft_limit: usize,
/// 最大软上限(字节)
pub max_soft_limit: usize,
/// 软上限调整阈值百分比0-100
pub adjustment_threshold: u8,
/// 软上限增长率百分比0-100
pub growth_rate: u8,
/// 软上限收缩率百分比0-100
pub shrink_rate: u8,
/// 调整窗口大小(区块数量)
pub adjustment_window: usize,
}
impl Default for FluidBlockConfig {
fn default() -> Self {
Self {
min_block_interval_ms: 100, // 0.1秒
initial_soft_limit: 1_000_000, // 1MB
max_soft_limit: 10_000_000, // 10MB
adjustment_threshold: 90, // 90%
growth_rate: 10, // 增长10%
shrink_rate: 5, // 收缩5%
adjustment_window: 10, // 最近10个区块
}
}
}
/// 区块大小统计
#[derive(Debug, Clone)]
struct BlockSizeStats {
/// 区块大小(字节)
size: usize,
/// 区块时间戳
timestamp: u64,
}
/// 流体区块模型管理器
pub struct FluidBlockModel {
/// 配置
config: FluidBlockConfig,
/// 当前软上限
current_soft_limit: usize,
/// 最近的区块统计
recent_blocks: Vec<BlockSizeStats>,
/// 上一个区块的时间戳
last_block_time: u64,
/// 待打包的交易总大小
pending_tx_size: usize,
}
impl FluidBlockModel {
/// 创建新的流体区块模型
pub fn new(config: FluidBlockConfig) -> Self {
Self {
current_soft_limit: config.initial_soft_limit,
config,
recent_blocks: Vec::new(),
last_block_time: 0,
pending_tx_size: 0,
}
}
/// 使用默认配置创建
pub fn with_defaults() -> Self {
Self::new(FluidBlockConfig::default())
}
/// 检查是否可以出块
pub fn can_produce_block(&self) -> bool {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64;
// 检查是否满足最小间隔
let interval_ok = if self.last_block_time == 0 {
true
} else {
now - self.last_block_time >= self.config.min_block_interval_ms
};
// 检查是否有待打包的交易
let has_pending = self.pending_tx_size > 0;
interval_ok && has_pending
}
/// 获取当前软上限
pub fn get_soft_limit(&self) -> usize {
self.current_soft_limit
}
/// 更新待打包交易大小
pub fn update_pending_size(&mut self, size: usize) {
self.pending_tx_size = size;
}
/// 记录新产生的区块
pub fn record_block(&mut self, block_size: usize) {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64;
// 记录区块统计
self.recent_blocks.push(BlockSizeStats {
size: block_size,
timestamp: now,
});
// 只保留最近的N个区块
if self.recent_blocks.len() > self.config.adjustment_window {
self.recent_blocks.remove(0);
}
// 更新最后区块时间
self.last_block_time = now;
// 重置待打包交易大小
self.pending_tx_size = 0;
// 触发软上限调整
self.adjust_soft_limit();
}
/// 调整软上限
fn adjust_soft_limit(&mut self) {
if self.recent_blocks.len() < self.config.adjustment_window {
return; // 数据不足,不调整
}
// 计算平均区块大小
let total_size: usize = self.recent_blocks.iter().map(|b| b.size).sum();
let avg_size = total_size / self.recent_blocks.len();
// 计算使用率
let usage_rate = (avg_size * 100) / self.current_soft_limit;
// 根据使用率调整软上限
if usage_rate >= self.config.adjustment_threshold as usize {
// 使用率高,增加软上限
let increase = (self.current_soft_limit * self.config.growth_rate as usize) / 100;
self.current_soft_limit = (self.current_soft_limit + increase)
.min(self.config.max_soft_limit);
} else if usage_rate < 50 {
// 使用率低,减少软上限
let decrease = (self.current_soft_limit * self.config.shrink_rate as usize) / 100;
self.current_soft_limit = (self.current_soft_limit - decrease)
.max(self.config.initial_soft_limit);
}
}
/// 获取建议的出块时间
pub fn get_suggested_block_time(&self) -> Duration {
Duration::from_millis(self.config.min_block_interval_ms)
}
/// 获取统计信息
pub fn get_stats(&self) -> FluidBlockStats {
let avg_size = if !self.recent_blocks.is_empty() {
let total: usize = self.recent_blocks.iter().map(|b| b.size).sum();
total / self.recent_blocks.len()
} else {
0
};
let avg_interval = if self.recent_blocks.len() > 1 {
let first = self.recent_blocks.first().unwrap().timestamp;
let last = self.recent_blocks.last().unwrap().timestamp;
let total_time = last - first;
total_time / (self.recent_blocks.len() - 1) as u64
} else {
0
};
FluidBlockStats {
current_soft_limit: self.current_soft_limit,
avg_block_size: avg_size,
avg_block_interval_ms: avg_interval,
recent_blocks_count: self.recent_blocks.len(),
pending_tx_size: self.pending_tx_size,
}
}
/// 重置统计
pub fn reset(&mut self) {
self.recent_blocks.clear();
self.current_soft_limit = self.config.initial_soft_limit;
self.last_block_time = 0;
self.pending_tx_size = 0;
}
}
/// 流体区块统计信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FluidBlockStats {
/// 当前软上限(字节)
pub current_soft_limit: usize,
/// 平均区块大小(字节)
pub avg_block_size: usize,
/// 平均出块间隔(毫秒)
pub avg_block_interval_ms: u64,
/// 最近区块数量
pub recent_blocks_count: usize,
/// 待打包交易大小(字节)
pub pending_tx_size: usize,
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread;
#[test]
fn test_fbm_creation() {
let fbm = FluidBlockModel::with_defaults();
assert_eq!(fbm.get_soft_limit(), 1_000_000);
}
#[test]
fn test_can_produce_block() {
let mut fbm = FluidBlockModel::with_defaults();
// 初始状态,没有待打包交易,不能出块
assert!(!fbm.can_produce_block());
// 添加待打包交易
fbm.update_pending_size(1000);
// 现在应该可以出块
assert!(fbm.can_produce_block());
}
#[test]
fn test_min_block_interval() {
let mut config = FluidBlockConfig::default();
config.min_block_interval_ms = 100;
let mut fbm = FluidBlockModel::new(config);
fbm.update_pending_size(1000);
assert!(fbm.can_produce_block());
// 记录一个区块
fbm.record_block(1000);
// 立即检查,应该不能出块(未满足最小间隔)
fbm.update_pending_size(1000);
assert!(!fbm.can_produce_block());
// 等待最小间隔
thread::sleep(Duration::from_millis(150));
assert!(fbm.can_produce_block());
}
#[test]
fn test_soft_limit_increase() {
let mut config = FluidBlockConfig::default();
config.adjustment_window = 3;
config.adjustment_threshold = 90;
config.growth_rate = 10;
let mut fbm = FluidBlockModel::new(config);
let initial_limit = fbm.get_soft_limit();
// 记录多个接近软上限的区块
for _ in 0..3 {
thread::sleep(Duration::from_millis(150));
fbm.update_pending_size(950_000);
fbm.record_block(950_000); // 95%使用率
}
// 软上限应该增加
assert!(fbm.get_soft_limit() > initial_limit);
}
#[test]
fn test_soft_limit_decrease() {
// 测试软上限不会低于initial_soft_limit
let mut config = FluidBlockConfig::default();
config.adjustment_window = 3;
config.shrink_rate = 10;
let mut fbm = FluidBlockModel::new(config);
let initial_limit = fbm.get_soft_limit();
// 记录多个小区块
for _ in 0..5 {
thread::sleep(Duration::from_millis(150));
fbm.update_pending_size(100_000);
fbm.record_block(100_000);
}
// 软上限不应该低于initial_soft_limit
assert!(fbm.get_soft_limit() >= initial_limit);
}
#[test]
fn test_soft_limit_bounds() {
let mut config = FluidBlockConfig::default();
config.adjustment_window = 3;
config.initial_soft_limit = 1_000_000;
config.max_soft_limit = 2_000_000;
config.growth_rate = 50; // 50%增长
let mut fbm = FluidBlockModel::new(config);
// 记录多个大区块,触发多次增长
for _ in 0..10 {
thread::sleep(Duration::from_millis(150));
fbm.update_pending_size(950_000);
fbm.record_block(950_000);
}
// 软上限不应超过最大值
assert!(fbm.get_soft_limit() <= 2_000_000);
}
#[test]
fn test_stats() {
let mut fbm = FluidBlockModel::with_defaults();
// 记录一些区块
for i in 1..=5 {
thread::sleep(Duration::from_millis(150));
fbm.update_pending_size(i * 100_000);
fbm.record_block(i * 100_000);
}
let stats = fbm.get_stats();
assert_eq!(stats.recent_blocks_count, 5);
assert!(stats.avg_block_size > 0);
assert!(stats.avg_block_interval_ms > 0);
}
#[test]
fn test_reset() {
let mut fbm = FluidBlockModel::with_defaults();
fbm.update_pending_size(1000);
fbm.record_block(1000);
fbm.reset();
let stats = fbm.get_stats();
assert_eq!(stats.recent_blocks_count, 0);
assert_eq!(stats.pending_tx_size, 0);
assert_eq!(fbm.get_soft_limit(), 1_000_000);
}
#[test]
fn test_pending_size_update() {
let mut fbm = FluidBlockModel::with_defaults();
fbm.update_pending_size(5000);
let stats = fbm.get_stats();
assert_eq!(stats.pending_tx_size, 5000);
// 记录区块后应该重置
fbm.record_block(5000);
let stats = fbm.get_stats();
assert_eq!(stats.pending_tx_size, 0);
}
}
// === 流体区块模型高级功能 ===
/// 网络负载级别
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum NetworkLoad {
/// 空闲(<30%
Idle,
/// 正常30-70%
Normal,
/// 繁忙70-90%
Busy,
/// 拥塞(>90%
Congested,
}
/// 交易优先级
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum TransactionPriority {
/// 低优先级
Low = 1,
/// 正常优先级
Normal = 2,
/// 高优先级
High = 3,
/// 紧急优先级
Urgent = 4,
}
/// 拥塞控制策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CongestionControl {
/// 拥塞阈值百分比0-100
pub congestion_threshold: u8,
/// 拥塞时的最小Gas价格倍数
pub min_gas_multiplier: f64,
/// 是否启用优先级队列
pub enable_priority_queue: bool,
/// 最大待处理交易数
pub max_pending_txs: usize,
}
impl Default for CongestionControl {
fn default() -> Self {
Self {
congestion_threshold: 85,
min_gas_multiplier: 1.5,
enable_priority_queue: true,
max_pending_txs: 10000,
}
}
}
/// 增强的流体区块模型
pub struct EnhancedFluidBlockModel {
/// 基础流体区块模型
base: FluidBlockModel,
/// 拥塞控制配置
congestion_control: CongestionControl,
/// 当前网络负载
current_load: NetworkLoad,
/// 待处理交易数量(按优先级)
pending_txs_by_priority: [usize; 4], // Low, Normal, High, Urgent
}
impl EnhancedFluidBlockModel {
/// 创建增强的流体区块模型
pub fn new(config: FluidBlockConfig, congestion_control: CongestionControl) -> Self {
Self {
base: FluidBlockModel::new(config),
congestion_control,
current_load: NetworkLoad::Idle,
pending_txs_by_priority: [0; 4],
}
}
/// 使用默认配置创建
pub fn with_defaults() -> Self {
Self::new(FluidBlockConfig::default(), CongestionControl::default())
}
/// 计算当前网络负载
pub fn calculate_network_load(&self) -> NetworkLoad {
let stats = self.base.get_stats();
let usage_rate = if stats.current_soft_limit > 0 {
(stats.avg_block_size * 100) / stats.current_soft_limit
} else {
0
};
match usage_rate {
0..=30 => NetworkLoad::Idle,
31..=70 => NetworkLoad::Normal,
71..=90 => NetworkLoad::Busy,
_ => NetworkLoad::Congested,
}
}
/// 更新网络负载
pub fn update_network_load(&mut self) {
self.current_load = self.calculate_network_load();
}
/// 获取当前网络负载
pub fn get_network_load(&self) -> NetworkLoad {
self.current_load
}
/// 添加待处理交易
pub fn add_pending_tx(&mut self, priority: TransactionPriority, size: usize) -> Result<(), String> {
// 检查是否超过最大待处理交易数
let total_pending: usize = self.pending_txs_by_priority.iter().sum();
if total_pending >= self.congestion_control.max_pending_txs {
return Err("达到最大待处理交易数".to_string());
}
// 根据优先级添加
let priority_index = priority as usize - 1;
self.pending_txs_by_priority[priority_index] += 1;
// 更新基础模型的待处理大小
let current_pending = self.base.get_stats().pending_tx_size;
self.base.update_pending_size(current_pending + size);
Ok(())
}
/// 获取建议的Gas价格倍数
pub fn get_suggested_gas_multiplier(&self) -> f64 {
match self.current_load {
NetworkLoad::Idle => 1.0,
NetworkLoad::Normal => 1.0,
NetworkLoad::Busy => 1.2,
NetworkLoad::Congested => self.congestion_control.min_gas_multiplier,
}
}
/// 获取建议的出块策略
pub fn get_block_production_strategy(&self) -> BlockProductionStrategy {
match self.current_load {
NetworkLoad::Idle => BlockProductionStrategy::Conservative,
NetworkLoad::Normal => BlockProductionStrategy::Normal,
NetworkLoad::Busy => BlockProductionStrategy::Aggressive,
NetworkLoad::Congested => BlockProductionStrategy::Emergency,
}
}
/// 检查是否应该出块(增强版)
pub fn should_produce_block(&self) -> bool {
// 基础检查
if !self.base.can_produce_block() {
return false;
}
// 根据网络负载和优先级决定
match self.current_load {
NetworkLoad::Idle | NetworkLoad::Normal => {
// 正常情况,按基础模型决定
true
}
NetworkLoad::Busy => {
// 繁忙时,优先处理高优先级交易
self.pending_txs_by_priority[2] > 0 || self.pending_txs_by_priority[3] > 0
}
NetworkLoad::Congested => {
// 拥塞时,只处理紧急交易
self.pending_txs_by_priority[3] > 0
}
}
}
/// 获取下一批应该打包的交易优先级
pub fn get_next_batch_priority(&self) -> Vec<TransactionPriority> {
let mut priorities = Vec::new();
match self.current_load {
NetworkLoad::Idle | NetworkLoad::Normal => {
// 正常情况,按优先级顺序处理
if self.pending_txs_by_priority[3] > 0 {
priorities.push(TransactionPriority::Urgent);
}
if self.pending_txs_by_priority[2] > 0 {
priorities.push(TransactionPriority::High);
}
if self.pending_txs_by_priority[1] > 0 {
priorities.push(TransactionPriority::Normal);
}
if self.pending_txs_by_priority[0] > 0 {
priorities.push(TransactionPriority::Low);
}
}
NetworkLoad::Busy => {
// 繁忙时,只处理高优先级和紧急
if self.pending_txs_by_priority[3] > 0 {
priorities.push(TransactionPriority::Urgent);
}
if self.pending_txs_by_priority[2] > 0 {
priorities.push(TransactionPriority::High);
}
}
NetworkLoad::Congested => {
// 拥塞时,只处理紧急
if self.pending_txs_by_priority[3] > 0 {
priorities.push(TransactionPriority::Urgent);
}
}
}
priorities
}
/// 记录区块生产(增强版)
pub fn record_block_production(&mut self, block_size: usize, included_priorities: &[TransactionPriority]) {
// 更新基础模型
self.base.record_block(block_size);
// 减少已打包的交易数量
for priority in included_priorities {
let priority_index = *priority as usize - 1;
if self.pending_txs_by_priority[priority_index] > 0 {
self.pending_txs_by_priority[priority_index] -= 1;
}
}
// 更新网络负载
self.update_network_load();
}
/// 获取增强统计信息
pub fn get_enhanced_stats(&self) -> EnhancedFluidBlockStats {
let base_stats = self.base.get_stats();
EnhancedFluidBlockStats {
base_stats,
network_load: self.current_load,
pending_low: self.pending_txs_by_priority[0],
pending_normal: self.pending_txs_by_priority[1],
pending_high: self.pending_txs_by_priority[2],
pending_urgent: self.pending_txs_by_priority[3],
suggested_gas_multiplier: self.get_suggested_gas_multiplier(),
}
}
}
/// 出块策略
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BlockProductionStrategy {
/// 保守策略(等待更多交易)
Conservative,
/// 正常策略
Normal,
/// 激进策略(快速出块)
Aggressive,
/// 紧急策略(只处理紧急交易)
Emergency,
}
/// 增强的流体区块统计信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedFluidBlockStats {
/// 基础统计
pub base_stats: FluidBlockStats,
/// 当前网络负载
pub network_load: NetworkLoad,
/// 低优先级待处理交易数
pub pending_low: usize,
/// 正常优先级待处理交易数
pub pending_normal: usize,
/// 高优先级待处理交易数
pub pending_high: usize,
/// 紧急优先级待处理交易数
pub pending_urgent: usize,
/// 建议的Gas价格倍数
pub suggested_gas_multiplier: f64,
}
#[cfg(test)]
mod enhanced_tests {
use super::*;
use std::thread;
#[test]
fn test_network_load_calculation() {
let mut efbm = EnhancedFluidBlockModel::with_defaults();
// 初始状态应该是空闲
efbm.update_network_load();
assert_eq!(efbm.get_network_load(), NetworkLoad::Idle);
// 记录一些大区块,增加负载
for _ in 0..5 {
thread::sleep(Duration::from_millis(150));
efbm.base.update_pending_size(800_000);
efbm.base.record_block(800_000);
}
efbm.update_network_load();
// 80%使用率应该是繁忙
assert_eq!(efbm.get_network_load(), NetworkLoad::Busy);
}
#[test]
fn test_priority_queue() {
let mut efbm = EnhancedFluidBlockModel::with_defaults();
// 添加不同优先级的交易
assert!(efbm.add_pending_tx(TransactionPriority::Low, 1000).is_ok());
assert!(efbm.add_pending_tx(TransactionPriority::Normal, 1000).is_ok());
assert!(efbm.add_pending_tx(TransactionPriority::High, 1000).is_ok());
assert!(efbm.add_pending_tx(TransactionPriority::Urgent, 1000).is_ok());
let stats = efbm.get_enhanced_stats();
assert_eq!(stats.pending_low, 1);
assert_eq!(stats.pending_normal, 1);
assert_eq!(stats.pending_high, 1);
assert_eq!(stats.pending_urgent, 1);
}
#[test]
fn test_congestion_control() {
let mut efbm = EnhancedFluidBlockModel::with_defaults();
// 模拟拥塞状态
for _ in 0..5 {
thread::sleep(Duration::from_millis(150));
efbm.base.update_pending_size(950_000);
efbm.base.record_block(950_000);
}
efbm.update_network_load();
// 拥塞时Gas倍数应该增加
let multiplier = efbm.get_suggested_gas_multiplier();
assert!(multiplier > 1.0);
// 拥塞时,只处理紧急交易
efbm.add_pending_tx(TransactionPriority::Low, 1000).ok();
efbm.add_pending_tx(TransactionPriority::Urgent, 1000).ok();
let priorities = efbm.get_next_batch_priority();
assert_eq!(priorities.len(), 1);
assert_eq!(priorities[0], TransactionPriority::Urgent);
}
#[test]
fn test_block_production_strategy() {
let mut efbm = EnhancedFluidBlockModel::with_defaults();
// 空闲状态
efbm.update_network_load();
assert_eq!(efbm.get_block_production_strategy(), BlockProductionStrategy::Conservative);
// 记录一些区块,增加负载
for _ in 0..5 {
thread::sleep(Duration::from_millis(150));
efbm.base.update_pending_size(500_000);
efbm.base.record_block(500_000);
}
efbm.update_network_load();
assert_eq!(efbm.get_block_production_strategy(), BlockProductionStrategy::Normal);
}
#[test]
fn test_max_pending_txs() {
let mut config = FluidBlockConfig::default();
let mut congestion_control = CongestionControl::default();
congestion_control.max_pending_txs = 5;
let mut efbm = EnhancedFluidBlockModel::new(config, congestion_control);
// 添加5个交易应该成功
for _ in 0..5 {
assert!(efbm.add_pending_tx(TransactionPriority::Normal, 1000).is_ok());
}
// 第6个应该失败
assert!(efbm.add_pending_tx(TransactionPriority::Normal, 1000).is_err());
}
}