783 lines
24 KiB
Rust
783 lines
24 KiB
Rust
// 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());
|
||
}
|
||
}
|