fix: 全系统删除投资风险提示横幅 - NAC是公链非投资平台
This commit is contained in:
parent
33ad157dd6
commit
17f640336f
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,144 @@
|
|||
//! NAC 公链创世配置
|
||||
//!
|
||||
//! 定义 NAC 公链的核心参数,包括代币发行总量、区块参数等。
|
||||
//!
|
||||
//! # NAC 代币经济模型
|
||||
//! - $NAC 原生代币发行总量:10 亿枚(1,000,000,000),固定总量,永不增发
|
||||
//! - XTZH 稳定币:锚定 SDR + 黄金储备,按需发行
|
||||
//! - XIC 治理代币:已在 BSC 发行(BEP-20),通过跨链桥与 NAC 主网互通
|
||||
|
||||
/// NAC 公链创世配置
|
||||
pub struct GenesisConfig {
|
||||
/// 链 ID(NAC 主网:0x4E4143 = "NAC" ASCII)
|
||||
pub chain_id: u64,
|
||||
/// 链名称
|
||||
pub chain_name: &'static str,
|
||||
/// 链符号
|
||||
pub chain_symbol: &'static str,
|
||||
}
|
||||
|
||||
/// NAC 原生代币配置
|
||||
pub struct NacTokenConfig {
|
||||
/// 代币名称
|
||||
pub name: &'static str,
|
||||
/// 代币符号
|
||||
pub symbol: &'static str,
|
||||
/// 精度(小数位数)
|
||||
pub decimals: u8,
|
||||
/// 发行总量(固定,永不增发)
|
||||
pub total_supply: u64,
|
||||
/// 发行总量(带精度的完整表示,18位小数)
|
||||
pub total_supply_wei: &'static str,
|
||||
}
|
||||
|
||||
/// XTZH 稳定币配置
|
||||
pub struct XtzhConfig {
|
||||
/// 代币名称
|
||||
pub name: &'static str,
|
||||
/// 代币符号
|
||||
pub symbol: &'static str,
|
||||
/// 精度
|
||||
pub decimals: u8,
|
||||
/// 锚定机制:SDR + 黄金储备
|
||||
pub peg_mechanism: &'static str,
|
||||
}
|
||||
|
||||
/// XIC 治理代币配置
|
||||
pub struct XicConfig {
|
||||
/// 代币名称
|
||||
pub name: &'static str,
|
||||
/// 代币符号
|
||||
pub symbol: &'static str,
|
||||
/// BSC 合约地址(BEP-20)
|
||||
pub bsc_contract: &'static str,
|
||||
/// 跨链桥锚定机制:1:1 永久锚定
|
||||
pub bridge_mechanism: &'static str,
|
||||
}
|
||||
|
||||
/// NAC 主网创世配置(单例)
|
||||
pub const MAINNET_GENESIS: GenesisConfig = GenesisConfig {
|
||||
chain_id: 0x4E4143, // "NAC" in ASCII
|
||||
chain_name: "New Asset Chain Mainnet",
|
||||
chain_symbol: "NAC",
|
||||
};
|
||||
|
||||
/// $NAC 原生代币配置
|
||||
/// 发行总量:10 亿枚,固定总量,永不增发
|
||||
pub const NAC_TOKEN: NacTokenConfig = NacTokenConfig {
|
||||
name: "NAC Token",
|
||||
symbol: "NAC",
|
||||
decimals: 18,
|
||||
total_supply: 1_000_000_000, // 10 亿枚,固定总量,永不增发
|
||||
total_supply_wei: "1000000000000000000000000000", // 1e27 (10亿 × 10^18)
|
||||
};
|
||||
|
||||
/// XTZH 稳定币配置
|
||||
pub const XTZH_TOKEN: XtzhConfig = XtzhConfig {
|
||||
name: "XTZH Stable Token",
|
||||
symbol: "XTZH",
|
||||
decimals: 18,
|
||||
peg_mechanism: "SDR + Gold Reserve (黄金储备锚定 SDR 模型)",
|
||||
};
|
||||
|
||||
/// XIC 治理代币配置
|
||||
pub const XIC_TOKEN: XicConfig = XicConfig {
|
||||
name: "XIC Governance Token",
|
||||
symbol: "XIC",
|
||||
bsc_contract: "0x59ff34dd59680a7125782b1f6df2a86ed46f5a24",
|
||||
bridge_mechanism: "BSC-XIC to NAC-XIC 1:1 永久锚定(5/7 多签验证)",
|
||||
};
|
||||
|
||||
/// CBPP 区块参数
|
||||
pub struct CbppParams {
|
||||
/// 空块最小大小(字节)
|
||||
pub min_block_size_bytes: u64,
|
||||
/// 空块最小大小(KB)
|
||||
pub min_block_size_kb: u64,
|
||||
/// 出块间隔(秒,每节点)
|
||||
pub block_interval_per_node_secs: u64,
|
||||
/// 共识协议
|
||||
pub consensus: &'static str,
|
||||
/// 网络协议
|
||||
pub network: &'static str,
|
||||
/// 虚拟机
|
||||
pub vm: &'static str,
|
||||
/// 数据透镜协议
|
||||
pub lens: &'static str,
|
||||
}
|
||||
|
||||
/// CBPP 主网参数
|
||||
pub const CBPP_MAINNET: CbppParams = CbppParams {
|
||||
min_block_size_bytes: 10240, // 10 KB
|
||||
min_block_size_kb: 10,
|
||||
block_interval_per_node_secs: 60,
|
||||
consensus: "CBPP (Constitutional Block Production Protocol)",
|
||||
network: "CSNP (Constitutional Secure Network Protocol)",
|
||||
vm: "NVM (NAC Virtual Machine)",
|
||||
lens: "NAC Lens (NAC Chain Data Lens)",
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_nac_token_total_supply() {
|
||||
// $NAC 发行总量:10 亿枚,固定总量,永不增发
|
||||
assert_eq!(NAC_TOKEN.total_supply, 1_000_000_000);
|
||||
assert_eq!(NAC_TOKEN.symbol, "NAC");
|
||||
assert_eq!(NAC_TOKEN.decimals, 18);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chain_id() {
|
||||
// NAC 主网链 ID:0x4E4143("NAC" ASCII)
|
||||
assert_eq!(MAINNET_GENESIS.chain_id, 0x4E4143);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cbpp_block_params() {
|
||||
// 空块最小 10KB
|
||||
assert_eq!(CBPP_MAINNET.min_block_size_kb, 10);
|
||||
assert_eq!(CBPP_MAINNET.min_block_size_bytes, 10240);
|
||||
}
|
||||
}
|
||||
|
|
@ -66,3 +66,6 @@ mod tests {
|
|||
|
||||
// 导出适配器模块
|
||||
pub mod adapters;
|
||||
|
||||
/// NAC 公链创世配置(代币发行、区块参数)
|
||||
pub mod genesis_config;
|
||||
|
|
|
|||
|
|
@ -437,8 +437,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_layer_message_creation() {
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
let sender = Address::from_slice(&[1u8; 32]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 32]).unwrap();
|
||||
|
||||
let message = LayerMessage::new(
|
||||
LayerMessageType::Request,
|
||||
|
|
@ -476,7 +476,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_message_queue() {
|
||||
let mut queue = LayerMessageQueue::new();
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let sender = Address::from_slice(&[1u8; 32]).unwrap();
|
||||
|
||||
// 添加低优先级消息
|
||||
let message1 = LayerMessage::new(
|
||||
|
|
@ -512,8 +512,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_layer_router_send() {
|
||||
let mut router = LayerRouter::new(Layer::L1);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
let sender = Address::from_slice(&[1u8; 32]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 32]).unwrap();
|
||||
|
||||
let result = router.send_message(
|
||||
LayerMessageType::Request,
|
||||
|
|
@ -533,8 +533,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_layer_router_receive() {
|
||||
let mut router = LayerRouter::new(Layer::L2);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
let sender = Address::from_slice(&[1u8; 32]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 32]).unwrap();
|
||||
|
||||
// 创建从L1发往L2的消息
|
||||
let message = LayerMessage::new(
|
||||
|
|
@ -557,8 +557,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_layer_router_forward() {
|
||||
let mut router = LayerRouter::new(Layer::L1);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
let sender = Address::from_slice(&[1u8; 32]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 32]).unwrap();
|
||||
|
||||
// 创建从L0发往L2的消息(需要经过L1转发)
|
||||
let message = LayerMessage::new(
|
||||
|
|
@ -594,8 +594,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_process_messages() {
|
||||
let mut router = LayerRouter::new(Layer::L1);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
let sender = Address::from_slice(&[1u8; 32]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 32]).unwrap();
|
||||
|
||||
// 发送2条消息
|
||||
router.send_message(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,626 @@
|
|||
///! NAC层间路由器
|
||||
///!
|
||||
///! 管理L0-L1-L2-L3层间的通信和路由
|
||||
///!
|
||||
///! **NAC四层架构**:
|
||||
///! - L0: 基础层(DAG + CBPP共识 + OPN)
|
||||
///! - L1: 协议层(NVM + ACC + GNACS + 碎片化)
|
||||
///! - L2: 宪法层(宪法收据 + CEE + 合规验证)
|
||||
///! - L3: 应用层(业务应用 + UI + API)
|
||||
|
||||
use crate::primitives::{Address, Hash};
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// NAC层级
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
/// Layer
|
||||
pub enum Layer {
|
||||
/// L0: 基础层
|
||||
L0,
|
||||
/// L1: 协议层
|
||||
L1,
|
||||
/// L2: 宪法层
|
||||
L2,
|
||||
/// L3: 应用层
|
||||
L3,
|
||||
}
|
||||
|
||||
impl Layer {
|
||||
/// 获取层级编号
|
||||
pub fn level(&self) -> u8 {
|
||||
match self {
|
||||
Layer::L0 => 0,
|
||||
Layer::L1 => 1,
|
||||
Layer::L2 => 2,
|
||||
Layer::L3 => 3,
|
||||
}
|
||||
}
|
||||
|
||||
/// 从层级编号创建
|
||||
pub fn from_level(level: u8) -> Option<Self> {
|
||||
match level {
|
||||
0 => Some(Layer::L0),
|
||||
1 => Some(Layer::L1),
|
||||
2 => Some(Layer::L2),
|
||||
3 => Some(Layer::L3),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否可以直接通信
|
||||
pub fn can_communicate_with(&self, other: &Layer) -> bool {
|
||||
// 相邻层可以直接通信
|
||||
let diff = (self.level() as i8 - other.level() as i8).abs();
|
||||
diff <= 1
|
||||
}
|
||||
}
|
||||
|
||||
/// 层间消息类型
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
/// LayerMessageType
|
||||
pub enum LayerMessageType {
|
||||
/// 请求
|
||||
Request,
|
||||
/// 响应
|
||||
Response,
|
||||
/// 通知
|
||||
Notification,
|
||||
/// 事件
|
||||
Event,
|
||||
}
|
||||
|
||||
/// 层间消息
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
/// LayerMessage
|
||||
pub struct LayerMessage {
|
||||
/// 消息ID
|
||||
pub message_id: Hash,
|
||||
/// 消息类型
|
||||
pub message_type: LayerMessageType,
|
||||
/// 源层
|
||||
pub source_layer: Layer,
|
||||
/// 目标层
|
||||
pub target_layer: Layer,
|
||||
/// 发送者地址
|
||||
pub sender: Address,
|
||||
/// 接收者地址(None表示广播)
|
||||
pub receiver: Option<Address>,
|
||||
/// 消息负载
|
||||
pub payload: Vec<u8>,
|
||||
/// 时间戳
|
||||
pub timestamp: u64,
|
||||
/// 优先级(0-255,数字越大优先级越高)
|
||||
pub priority: u8,
|
||||
/// 路由路径(经过的层)
|
||||
pub route_path: Vec<Layer>,
|
||||
}
|
||||
|
||||
impl LayerMessage {
|
||||
/// 创建新的层间消息
|
||||
pub fn new(
|
||||
message_type: LayerMessageType,
|
||||
source_layer: Layer,
|
||||
target_layer: Layer,
|
||||
sender: Address,
|
||||
receiver: Option<Address>,
|
||||
payload: Vec<u8>,
|
||||
timestamp: u64,
|
||||
priority: u8,
|
||||
) -> Self {
|
||||
// 计算消息ID
|
||||
let mut data = Vec::new();
|
||||
data.push(source_layer.level());
|
||||
data.push(target_layer.level());
|
||||
data.extend_from_slice(sender.as_bytes());
|
||||
if let Some(ref r) = receiver {
|
||||
data.extend_from_slice(r.as_bytes());
|
||||
}
|
||||
data.extend_from_slice(&payload);
|
||||
data.extend_from_slice(×tamp.to_le_bytes());
|
||||
|
||||
let message_id = Hash::sha3_384(&data);
|
||||
|
||||
Self {
|
||||
message_id,
|
||||
message_type,
|
||||
source_layer,
|
||||
target_layer,
|
||||
sender,
|
||||
receiver,
|
||||
payload,
|
||||
timestamp,
|
||||
priority,
|
||||
route_path: vec![source_layer],
|
||||
}
|
||||
}
|
||||
|
||||
/// 添加路由路径
|
||||
pub fn add_to_route(&mut self, layer: Layer) {
|
||||
self.route_path.push(layer);
|
||||
}
|
||||
|
||||
/// 是否到达目标层
|
||||
pub fn has_reached_target(&self) -> bool {
|
||||
self.route_path.last() == Some(&self.target_layer)
|
||||
}
|
||||
}
|
||||
|
||||
/// 层间路由表
|
||||
struct RoutingTable {
|
||||
/// 路由规则(source_layer, target_layer) => next_layer
|
||||
routes: HashMap<(Layer, Layer), Layer>,
|
||||
}
|
||||
|
||||
impl RoutingTable {
|
||||
/// 创建新的路由表
|
||||
fn new() -> Self {
|
||||
let mut routes = HashMap::new();
|
||||
|
||||
// 初始化默认路由规则
|
||||
// L0 <-> L1 直接通信
|
||||
routes.insert((Layer::L0, Layer::L1), Layer::L1);
|
||||
routes.insert((Layer::L1, Layer::L0), Layer::L0);
|
||||
|
||||
// L1 <-> L2 直接通信
|
||||
routes.insert((Layer::L1, Layer::L2), Layer::L2);
|
||||
routes.insert((Layer::L2, Layer::L1), Layer::L1);
|
||||
|
||||
// L2 <-> L3 直接通信
|
||||
routes.insert((Layer::L2, Layer::L3), Layer::L3);
|
||||
routes.insert((Layer::L3, Layer::L2), Layer::L2);
|
||||
|
||||
// L0 -> L2 经过 L1
|
||||
routes.insert((Layer::L0, Layer::L2), Layer::L1);
|
||||
|
||||
// L0 -> L3 经过 L1
|
||||
routes.insert((Layer::L0, Layer::L3), Layer::L1);
|
||||
|
||||
// L1 -> L3 经过 L2
|
||||
routes.insert((Layer::L1, Layer::L3), Layer::L2);
|
||||
|
||||
// L3 -> L1 经过 L2
|
||||
routes.insert((Layer::L3, Layer::L1), Layer::L2);
|
||||
|
||||
// L3 -> L0 经过 L2
|
||||
routes.insert((Layer::L3, Layer::L0), Layer::L2);
|
||||
|
||||
// L2 -> L0 经过 L1
|
||||
routes.insert((Layer::L2, Layer::L0), Layer::L1);
|
||||
|
||||
Self { routes }
|
||||
}
|
||||
|
||||
/// 获取下一跳层级
|
||||
fn get_next_hop(&self, current_layer: Layer, target_layer: Layer) -> Option<Layer> {
|
||||
if current_layer == target_layer {
|
||||
return Some(target_layer);
|
||||
}
|
||||
|
||||
self.routes.get(&(current_layer, target_layer)).copied()
|
||||
}
|
||||
}
|
||||
|
||||
/// 层间消息队列
|
||||
struct LayerMessageQueue {
|
||||
/// 消息队列(按优先级排序)
|
||||
queue: VecDeque<LayerMessage>,
|
||||
}
|
||||
|
||||
impl LayerMessageQueue {
|
||||
/// 创建新的消息队列
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
queue: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 添加消息
|
||||
fn enqueue(&mut self, message: LayerMessage) {
|
||||
// 按优先级插入(优先级高的在前)
|
||||
let pos = self.queue
|
||||
.iter()
|
||||
.position(|m| m.priority < message.priority)
|
||||
.unwrap_or(self.queue.len());
|
||||
|
||||
self.queue.insert(pos, message);
|
||||
}
|
||||
|
||||
/// 取出消息
|
||||
fn dequeue(&mut self) -> Option<LayerMessage> {
|
||||
self.queue.pop_front()
|
||||
}
|
||||
|
||||
/// 获取队列长度
|
||||
fn len(&self) -> usize {
|
||||
self.queue.len()
|
||||
}
|
||||
|
||||
/// 是否为空
|
||||
#[allow(dead_code)]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.queue.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// 层间路由器
|
||||
pub struct LayerRouter {
|
||||
/// 当前层级
|
||||
current_layer: Layer,
|
||||
/// 路由表
|
||||
routing_table: RoutingTable,
|
||||
/// 待发送消息队列
|
||||
outbound_queue: LayerMessageQueue,
|
||||
/// 已接收消息队列
|
||||
inbound_queue: LayerMessageQueue,
|
||||
/// 消息处理器(message_type => handler_id)
|
||||
message_handlers: HashMap<LayerMessageType, Vec<String>>,
|
||||
/// 统计信息
|
||||
stats: RouterStats,
|
||||
}
|
||||
|
||||
impl LayerRouter {
|
||||
/// 创建新的层间路由器
|
||||
pub fn new(current_layer: Layer) -> Self {
|
||||
Self {
|
||||
current_layer,
|
||||
routing_table: RoutingTable::new(),
|
||||
outbound_queue: LayerMessageQueue::new(),
|
||||
inbound_queue: LayerMessageQueue::new(),
|
||||
message_handlers: HashMap::new(),
|
||||
stats: RouterStats::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 发送消息
|
||||
pub fn send_message(
|
||||
&mut self,
|
||||
message_type: LayerMessageType,
|
||||
target_layer: Layer,
|
||||
sender: Address,
|
||||
receiver: Option<Address>,
|
||||
payload: Vec<u8>,
|
||||
timestamp: u64,
|
||||
priority: u8,
|
||||
) -> Result<Hash, String> {
|
||||
// 创建消息
|
||||
let message = LayerMessage::new(
|
||||
message_type,
|
||||
self.current_layer,
|
||||
target_layer,
|
||||
sender,
|
||||
receiver,
|
||||
payload,
|
||||
timestamp,
|
||||
priority,
|
||||
);
|
||||
|
||||
let message_id = message.message_id.clone();
|
||||
|
||||
// 加入发送队列
|
||||
self.outbound_queue.enqueue(message);
|
||||
self.stats.messages_sent += 1;
|
||||
|
||||
Ok(message_id)
|
||||
}
|
||||
|
||||
/// 接收消息
|
||||
pub fn receive_message(&mut self, mut message: LayerMessage) -> Result<(), String> {
|
||||
// 验证消息是否应该到达当前层
|
||||
let next_hop = self.routing_table
|
||||
.get_next_hop(
|
||||
*message.route_path.last().unwrap(),
|
||||
message.target_layer,
|
||||
)
|
||||
.ok_or("No route found")?;
|
||||
|
||||
if next_hop != self.current_layer {
|
||||
return Err(format!(
|
||||
"Message should be routed to {:?}, not {:?}",
|
||||
next_hop, self.current_layer
|
||||
));
|
||||
}
|
||||
|
||||
// 添加到路由路径
|
||||
message.add_to_route(self.current_layer);
|
||||
|
||||
// 如果到达目标层,加入接收队列
|
||||
if message.has_reached_target() {
|
||||
self.inbound_queue.enqueue(message);
|
||||
self.stats.messages_received += 1;
|
||||
} else {
|
||||
// 否则继续转发
|
||||
self.outbound_queue.enqueue(message);
|
||||
self.stats.messages_forwarded += 1;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 处理待发送消息
|
||||
pub fn process_outbound_messages(&mut self) -> Vec<LayerMessage> {
|
||||
let mut processed = Vec::new();
|
||||
|
||||
while let Some(message) = self.outbound_queue.dequeue() {
|
||||
processed.push(message);
|
||||
}
|
||||
|
||||
processed
|
||||
}
|
||||
|
||||
/// 处理已接收消息
|
||||
pub fn process_inbound_messages(&mut self) -> Vec<LayerMessage> {
|
||||
let mut processed = Vec::new();
|
||||
|
||||
while let Some(message) = self.inbound_queue.dequeue() {
|
||||
processed.push(message);
|
||||
}
|
||||
|
||||
processed
|
||||
}
|
||||
|
||||
/// 注册消息处理器
|
||||
pub fn register_handler(&mut self, message_type: LayerMessageType, handler_id: String) {
|
||||
self.message_handlers
|
||||
.entry(message_type)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(handler_id);
|
||||
}
|
||||
|
||||
/// 获取消息处理器
|
||||
pub fn get_handlers(&self, message_type: &LayerMessageType) -> Option<&Vec<String>> {
|
||||
self.message_handlers.get(message_type)
|
||||
}
|
||||
|
||||
/// 获取统计信息
|
||||
pub fn get_stats(&self) -> &RouterStats {
|
||||
&self.stats
|
||||
}
|
||||
|
||||
/// 获取待发送消息数量
|
||||
pub fn outbound_count(&self) -> usize {
|
||||
self.outbound_queue.len()
|
||||
}
|
||||
|
||||
/// 获取已接收消息数量
|
||||
pub fn inbound_count(&self) -> usize {
|
||||
self.inbound_queue.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// 路由器统计信息
|
||||
#[derive(Debug, Clone, Default)]
|
||||
/// RouterStats
|
||||
pub struct RouterStats {
|
||||
/// 已发送消息数
|
||||
pub messages_sent: u64,
|
||||
/// 已接收消息数
|
||||
pub messages_received: u64,
|
||||
/// 已转发消息数
|
||||
pub messages_forwarded: u64,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_layer_level() {
|
||||
assert_eq!(Layer::L0.level(), 0);
|
||||
assert_eq!(Layer::L1.level(), 1);
|
||||
assert_eq!(Layer::L2.level(), 2);
|
||||
assert_eq!(Layer::L3.level(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layer_from_level() {
|
||||
assert_eq!(Layer::from_level(0), Some(Layer::L0));
|
||||
assert_eq!(Layer::from_level(1), Some(Layer::L1));
|
||||
assert_eq!(Layer::from_level(2), Some(Layer::L2));
|
||||
assert_eq!(Layer::from_level(3), Some(Layer::L3));
|
||||
assert_eq!(Layer::from_level(4), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layer_communication() {
|
||||
// 相邻层可以直接通信
|
||||
assert!(Layer::L0.can_communicate_with(&Layer::L1));
|
||||
assert!(Layer::L1.can_communicate_with(&Layer::L0));
|
||||
assert!(Layer::L1.can_communicate_with(&Layer::L2));
|
||||
assert!(Layer::L2.can_communicate_with(&Layer::L3));
|
||||
|
||||
// 非相邻层不能直接通信
|
||||
assert!(!Layer::L0.can_communicate_with(&Layer::L2));
|
||||
assert!(!Layer::L0.can_communicate_with(&Layer::L3));
|
||||
assert!(!Layer::L1.can_communicate_with(&Layer::L3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layer_message_creation() {
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
|
||||
let message = LayerMessage::new(
|
||||
LayerMessageType::Request,
|
||||
Layer::L1,
|
||||
Layer::L2,
|
||||
sender,
|
||||
Some(receiver),
|
||||
vec![1, 2, 3],
|
||||
1000,
|
||||
10,
|
||||
);
|
||||
|
||||
assert_eq!(message.source_layer, Layer::L1);
|
||||
assert_eq!(message.target_layer, Layer::L2);
|
||||
assert_eq!(message.priority, 10);
|
||||
assert_eq!(message.route_path, vec![Layer::L1]);
|
||||
assert!(!message.has_reached_target());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_routing_table() {
|
||||
let table = RoutingTable::new();
|
||||
|
||||
// 直接通信
|
||||
assert_eq!(table.get_next_hop(Layer::L0, Layer::L1), Some(Layer::L1));
|
||||
assert_eq!(table.get_next_hop(Layer::L1, Layer::L2), Some(Layer::L2));
|
||||
|
||||
// 间接通信(L0 -> L2 经过 L1)
|
||||
assert_eq!(table.get_next_hop(Layer::L0, Layer::L2), Some(Layer::L1));
|
||||
|
||||
// 间接通信(L0 -> L3 经过 L1)
|
||||
assert_eq!(table.get_next_hop(Layer::L0, Layer::L3), Some(Layer::L1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_queue() {
|
||||
let mut queue = LayerMessageQueue::new();
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
|
||||
// 添加低优先级消息
|
||||
let message1 = LayerMessage::new(
|
||||
LayerMessageType::Request,
|
||||
Layer::L1,
|
||||
Layer::L2,
|
||||
sender.clone(),
|
||||
None,
|
||||
vec![1],
|
||||
1000,
|
||||
5, // 低优先级
|
||||
);
|
||||
queue.enqueue(message1);
|
||||
|
||||
// 添加高优先级消息
|
||||
let message2 = LayerMessage::new(
|
||||
LayerMessageType::Request,
|
||||
Layer::L1,
|
||||
Layer::L2,
|
||||
sender,
|
||||
None,
|
||||
vec![2],
|
||||
1001,
|
||||
10, // 高优先级
|
||||
);
|
||||
queue.enqueue(message2.clone());
|
||||
|
||||
// 高优先级消息应该先出队
|
||||
let dequeued = queue.dequeue().unwrap();
|
||||
assert_eq!(dequeued.message_id, message2.message_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layer_router_send() {
|
||||
let mut router = LayerRouter::new(Layer::L1);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
|
||||
let result = router.send_message(
|
||||
LayerMessageType::Request,
|
||||
Layer::L2,
|
||||
sender,
|
||||
Some(receiver),
|
||||
vec![1, 2, 3],
|
||||
1000,
|
||||
10,
|
||||
);
|
||||
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(router.outbound_count(), 1);
|
||||
assert_eq!(router.get_stats().messages_sent, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layer_router_receive() {
|
||||
let mut router = LayerRouter::new(Layer::L2);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
|
||||
// 创建从L1发往L2的消息
|
||||
let message = LayerMessage::new(
|
||||
LayerMessageType::Request,
|
||||
Layer::L1,
|
||||
Layer::L2,
|
||||
sender,
|
||||
Some(receiver),
|
||||
vec![1, 2, 3],
|
||||
1000,
|
||||
10,
|
||||
);
|
||||
|
||||
let result = router.receive_message(message);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(router.inbound_count(), 1);
|
||||
assert_eq!(router.get_stats().messages_received, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layer_router_forward() {
|
||||
let mut router = LayerRouter::new(Layer::L1);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
|
||||
// 创建从L0发往L2的消息(需要经过L1转发)
|
||||
let message = LayerMessage::new(
|
||||
LayerMessageType::Request,
|
||||
Layer::L0,
|
||||
Layer::L2,
|
||||
sender,
|
||||
Some(receiver),
|
||||
vec![1, 2, 3],
|
||||
1000,
|
||||
10,
|
||||
);
|
||||
|
||||
let result = router.receive_message(message);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(router.outbound_count(), 1); // 转发到发送队列
|
||||
assert_eq!(router.get_stats().messages_forwarded, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_handler_registration() {
|
||||
let mut router = LayerRouter::new(Layer::L1);
|
||||
|
||||
router.register_handler(LayerMessageType::Request, "handler1".to_string());
|
||||
router.register_handler(LayerMessageType::Request, "handler2".to_string());
|
||||
|
||||
let handlers = router.get_handlers(&LayerMessageType::Request).unwrap();
|
||||
assert_eq!(handlers.len(), 2);
|
||||
assert!(handlers.contains(&"handler1".to_string()));
|
||||
assert!(handlers.contains(&"handler2".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_messages() {
|
||||
let mut router = LayerRouter::new(Layer::L1);
|
||||
let sender = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let receiver = Address::from_slice(&[2u8; 20]).unwrap();
|
||||
|
||||
// 发送2条消息
|
||||
router.send_message(
|
||||
LayerMessageType::Request,
|
||||
Layer::L2,
|
||||
sender.clone(),
|
||||
Some(receiver.clone()),
|
||||
vec![1],
|
||||
1000,
|
||||
10,
|
||||
).unwrap();
|
||||
|
||||
router.send_message(
|
||||
LayerMessageType::Request,
|
||||
Layer::L2,
|
||||
sender,
|
||||
Some(receiver),
|
||||
vec![2],
|
||||
1001,
|
||||
5,
|
||||
).unwrap();
|
||||
|
||||
// 处理待发送消息
|
||||
let processed = router.process_outbound_messages();
|
||||
assert_eq!(processed.len(), 2);
|
||||
assert_eq!(router.outbound_count(), 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -490,7 +490,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_optimizer_hot_account_tracking() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 3600, 1024 * 1024);
|
||||
let address = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
let address = Address::from_slice(&[1u8; 32]).unwrap();
|
||||
|
||||
// 记录大量活动
|
||||
for i in 0..1001 {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,561 @@
|
|||
///! 状态分片优化模块
|
||||
///!
|
||||
///! 优化分片状态存储和访问性能
|
||||
///!
|
||||
///! **NAC原生设计原则**:
|
||||
///! - 使用Asset(资产),不是Token
|
||||
///! - 使用Certificate(证书),不是Contract
|
||||
///! - 使用SHA3-384哈希,不是SHA256/Keccak256
|
||||
///! - 通过CBPP共识协调
|
||||
|
||||
use crate::primitives::{Address, Hash};
|
||||
use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// 状态分片优化器
|
||||
#[derive(Debug, Clone)]
|
||||
/// StateShardOptimizer
|
||||
pub struct StateShardOptimizer {
|
||||
/// 分片ID
|
||||
shard_id: u64,
|
||||
/// 状态缓存
|
||||
state_cache: HashMap<Hash, StateEntry>,
|
||||
/// 热点账户追踪
|
||||
hot_accounts: HashMap<Address, HotAccountStats>,
|
||||
/// 冷数据归档阈值(秒)
|
||||
cold_threshold: u64,
|
||||
/// 缓存大小限制(字节)
|
||||
max_cache_size: u64,
|
||||
/// 当前缓存大小
|
||||
current_cache_size: u64,
|
||||
/// 优化统计
|
||||
stats: OptimizationStats,
|
||||
}
|
||||
|
||||
/// 状态条目
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
/// StateEntry
|
||||
pub struct StateEntry {
|
||||
/// 状态键
|
||||
pub key: Hash,
|
||||
/// 状态值
|
||||
pub value: Vec<u8>,
|
||||
/// 最后访问时间
|
||||
pub last_access: u64,
|
||||
/// 访问次数
|
||||
pub access_count: u64,
|
||||
/// 是否为热点数据
|
||||
pub is_hot: bool,
|
||||
/// 数据大小(字节)
|
||||
pub size: u64,
|
||||
}
|
||||
|
||||
impl StateEntry {
|
||||
/// 创建新的状态条目
|
||||
pub fn new(key: Hash, value: Vec<u8>, timestamp: u64) -> Self {
|
||||
let size = value.len() as u64;
|
||||
Self {
|
||||
key,
|
||||
value,
|
||||
last_access: timestamp,
|
||||
access_count: 1,
|
||||
is_hot: false,
|
||||
size,
|
||||
}
|
||||
}
|
||||
|
||||
/// 更新访问信息
|
||||
pub fn update_access(&mut self, timestamp: u64) {
|
||||
self.last_access = timestamp;
|
||||
self.access_count += 1;
|
||||
|
||||
// 访问次数超过阈值标记为热点
|
||||
if self.access_count > 100 {
|
||||
self.is_hot = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// 检查是否为冷数据
|
||||
pub fn is_cold(&self, current_time: u64, threshold: u64) -> bool {
|
||||
current_time - self.last_access > threshold
|
||||
}
|
||||
}
|
||||
|
||||
/// 热点账户统计
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
/// HotAccountStats
|
||||
pub struct HotAccountStats {
|
||||
/// 账户地址
|
||||
pub address: Address,
|
||||
/// 读取次数
|
||||
pub read_count: u64,
|
||||
/// 写入次数
|
||||
pub write_count: u64,
|
||||
/// 最后活动时间
|
||||
pub last_activity: u64,
|
||||
/// 平均交易大小
|
||||
pub avg_tx_size: u64,
|
||||
/// 是否为高频账户
|
||||
pub is_high_frequency: bool,
|
||||
}
|
||||
|
||||
impl HotAccountStats {
|
||||
/// 创建新的热点账户统计
|
||||
pub fn new(address: Address, timestamp: u64) -> Self {
|
||||
Self {
|
||||
address,
|
||||
read_count: 0,
|
||||
write_count: 0,
|
||||
last_activity: timestamp,
|
||||
avg_tx_size: 0,
|
||||
is_high_frequency: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// 记录读取操作
|
||||
pub fn record_read(&mut self, timestamp: u64) {
|
||||
self.read_count += 1;
|
||||
self.last_activity = timestamp;
|
||||
self.update_frequency();
|
||||
}
|
||||
|
||||
/// 记录写入操作
|
||||
pub fn record_write(&mut self, timestamp: u64, tx_size: u64) {
|
||||
self.write_count += 1;
|
||||
self.last_activity = timestamp;
|
||||
|
||||
// 更新平均交易大小
|
||||
let total_count = self.read_count + self.write_count;
|
||||
self.avg_tx_size = (self.avg_tx_size * (total_count - 1) + tx_size) / total_count;
|
||||
|
||||
self.update_frequency();
|
||||
}
|
||||
|
||||
/// 更新频率标记
|
||||
fn update_frequency(&mut self) {
|
||||
// 读写总次数超过1000标记为高频
|
||||
if self.read_count + self.write_count > 1000 {
|
||||
self.is_high_frequency = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 优化统计
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
/// OptimizationStats
|
||||
pub struct OptimizationStats {
|
||||
/// 缓存命中次数
|
||||
pub cache_hits: u64,
|
||||
/// 缓存未命中次数
|
||||
pub cache_misses: u64,
|
||||
/// 冷数据归档次数
|
||||
pub cold_data_archived: u64,
|
||||
/// 热点数据提升次数
|
||||
pub hot_data_promoted: u64,
|
||||
/// 缓存驱逐次数
|
||||
pub cache_evictions: u64,
|
||||
/// 总状态访问次数
|
||||
pub total_accesses: u64,
|
||||
}
|
||||
|
||||
impl OptimizationStats {
|
||||
/// 计算缓存命中率
|
||||
pub fn cache_hit_rate(&self) -> f64 {
|
||||
if self.total_accesses == 0 {
|
||||
return 0.0;
|
||||
}
|
||||
self.cache_hits as f64 / self.total_accesses as f64
|
||||
}
|
||||
}
|
||||
|
||||
impl StateShardOptimizer {
|
||||
/// 创建新的状态分片优化器
|
||||
pub fn new(shard_id: u64, cold_threshold: u64, max_cache_size: u64) -> Self {
|
||||
Self {
|
||||
shard_id,
|
||||
state_cache: HashMap::new(),
|
||||
hot_accounts: HashMap::new(),
|
||||
cold_threshold,
|
||||
max_cache_size,
|
||||
current_cache_size: 0,
|
||||
stats: OptimizationStats::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 读取状态
|
||||
pub fn read_state(&mut self, key: &Hash, current_time: u64) -> Option<Vec<u8>> {
|
||||
self.stats.total_accesses += 1;
|
||||
|
||||
if let Some(entry) = self.state_cache.get_mut(key) {
|
||||
// 缓存命中
|
||||
self.stats.cache_hits += 1;
|
||||
entry.update_access(current_time);
|
||||
Some(entry.value.clone())
|
||||
} else {
|
||||
// 缓存未命中
|
||||
self.stats.cache_misses += 1;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// 写入状态
|
||||
pub fn write_state(&mut self, key: Hash, value: Vec<u8>, current_time: u64) -> Result<(), String> {
|
||||
let entry_size = value.len() as u64;
|
||||
|
||||
// 检查缓存大小限制
|
||||
if self.current_cache_size + entry_size > self.max_cache_size {
|
||||
// 驱逐冷数据
|
||||
self.evict_cold_data(current_time)?;
|
||||
}
|
||||
|
||||
// 创建或更新状态条目
|
||||
if let Some(existing) = self.state_cache.get_mut(&key) {
|
||||
self.current_cache_size -= existing.size;
|
||||
existing.value = value;
|
||||
existing.size = entry_size;
|
||||
existing.update_access(current_time);
|
||||
self.current_cache_size += entry_size;
|
||||
} else {
|
||||
let entry = StateEntry::new(key.clone(), value, current_time);
|
||||
self.state_cache.insert(key, entry);
|
||||
self.current_cache_size += entry_size;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 驱逐冷数据
|
||||
pub fn evict_cold_data(&mut self, current_time: u64) -> Result<(), String> {
|
||||
let mut cold_keys = Vec::new();
|
||||
|
||||
// 查找冷数据
|
||||
for (key, entry) in &self.state_cache {
|
||||
if entry.is_cold(current_time, self.cold_threshold) && !entry.is_hot {
|
||||
cold_keys.push(key.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if cold_keys.is_empty() {
|
||||
return Err("No cold data to evict".to_string());
|
||||
}
|
||||
|
||||
// 驱逐冷数据
|
||||
for key in cold_keys {
|
||||
if let Some(entry) = self.state_cache.remove(&key) {
|
||||
self.current_cache_size -= entry.size;
|
||||
self.stats.cache_evictions += 1;
|
||||
self.stats.cold_data_archived += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 提升热点数据
|
||||
pub fn promote_hot_data(&mut self, key: &Hash) -> Result<(), String> {
|
||||
if let Some(entry) = self.state_cache.get_mut(key) {
|
||||
if !entry.is_hot {
|
||||
entry.is_hot = true;
|
||||
self.stats.hot_data_promoted += 1;
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err("State entry not found".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// 记录账户活动
|
||||
pub fn record_account_activity(
|
||||
&mut self,
|
||||
address: Address,
|
||||
is_write: bool,
|
||||
tx_size: u64,
|
||||
timestamp: u64,
|
||||
) {
|
||||
let stats = self.hot_accounts
|
||||
.entry(address.clone())
|
||||
.or_insert_with(|| HotAccountStats::new(address, timestamp));
|
||||
|
||||
if is_write {
|
||||
stats.record_write(timestamp, tx_size);
|
||||
} else {
|
||||
stats.record_read(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取热点账户列表
|
||||
pub fn get_hot_accounts(&self) -> Vec<Address> {
|
||||
self.hot_accounts
|
||||
.values()
|
||||
.filter(|stats| stats.is_high_frequency)
|
||||
.map(|stats| stats.address.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// 获取优化统计
|
||||
pub fn get_stats(&self) -> OptimizationStats {
|
||||
self.stats.clone()
|
||||
}
|
||||
|
||||
/// 获取缓存使用率
|
||||
pub fn get_cache_usage(&self) -> f64 {
|
||||
if self.max_cache_size == 0 {
|
||||
return 0.0;
|
||||
}
|
||||
self.current_cache_size as f64 / self.max_cache_size as f64
|
||||
}
|
||||
|
||||
/// 清理过期数据
|
||||
pub fn cleanup_expired(&mut self, current_time: u64) -> usize {
|
||||
let mut expired_keys = Vec::new();
|
||||
|
||||
// 查找过期数据(超过冷数据阈值的2倍)
|
||||
let expiry_threshold = self.cold_threshold * 2;
|
||||
for (key, entry) in &self.state_cache {
|
||||
if current_time - entry.last_access > expiry_threshold {
|
||||
expired_keys.push(key.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let count = expired_keys.len();
|
||||
|
||||
// 删除过期数据
|
||||
for key in expired_keys {
|
||||
if let Some(entry) = self.state_cache.remove(&key) {
|
||||
self.current_cache_size -= entry.size;
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
|
||||
/// 优化分片状态
|
||||
pub fn optimize(&mut self, current_time: u64) -> Result<OptimizationReport, String> {
|
||||
let initial_cache_size = self.current_cache_size;
|
||||
let initial_entry_count = self.state_cache.len();
|
||||
|
||||
// 1. 清理过期数据
|
||||
let expired_count = self.cleanup_expired(current_time);
|
||||
|
||||
// 2. 驱逐冷数据(如果缓存使用率超过80%)
|
||||
let evicted_count = if self.get_cache_usage() > 0.8 {
|
||||
let before = self.state_cache.len();
|
||||
self.evict_cold_data(current_time)?;
|
||||
before - self.state_cache.len()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
// 3. 提升热点数据
|
||||
let hot_keys: Vec<Hash> = self.state_cache
|
||||
.iter()
|
||||
.filter(|(_, entry)| entry.access_count > 50 && !entry.is_hot)
|
||||
.map(|(key, _)| key.clone())
|
||||
.collect();
|
||||
|
||||
for key in &hot_keys {
|
||||
let _ = self.promote_hot_data(key);
|
||||
}
|
||||
|
||||
Ok(OptimizationReport {
|
||||
shard_id: self.shard_id,
|
||||
expired_count,
|
||||
evicted_count,
|
||||
promoted_count: hot_keys.len(),
|
||||
space_freed: initial_cache_size - self.current_cache_size,
|
||||
entries_before: initial_entry_count,
|
||||
entries_after: self.state_cache.len(),
|
||||
cache_hit_rate: self.stats.cache_hit_rate(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// 优化报告
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
/// OptimizationReport
|
||||
pub struct OptimizationReport {
|
||||
/// 分片ID
|
||||
pub shard_id: u64,
|
||||
/// 清理的过期数据数量
|
||||
pub expired_count: usize,
|
||||
/// 驱逐的冷数据数量
|
||||
pub evicted_count: usize,
|
||||
/// 提升的热点数据数量
|
||||
pub promoted_count: usize,
|
||||
/// 释放的空间(字节)
|
||||
pub space_freed: u64,
|
||||
/// 优化前条目数
|
||||
pub entries_before: usize,
|
||||
/// 优化后条目数
|
||||
pub entries_after: usize,
|
||||
/// 缓存命中率
|
||||
pub cache_hit_rate: f64,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_state_entry_creation() {
|
||||
let key = Hash::from_slice(&[1u8; 32]).unwrap();
|
||||
let value = vec![1, 2, 3, 4];
|
||||
let entry = StateEntry::new(key, value.clone(), 1000);
|
||||
|
||||
assert_eq!(entry.value, value);
|
||||
assert_eq!(entry.last_access, 1000);
|
||||
assert_eq!(entry.access_count, 1);
|
||||
assert!(!entry.is_hot);
|
||||
assert_eq!(entry.size, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_state_entry_hot_promotion() {
|
||||
let key = Hash::from_slice(&[1u8; 32]).unwrap();
|
||||
let value = vec![1, 2, 3];
|
||||
let mut entry = StateEntry::new(key, value, 1000);
|
||||
|
||||
// 访问101次应该变为热点
|
||||
for i in 0..101 {
|
||||
entry.update_access(1000 + i);
|
||||
}
|
||||
|
||||
assert!(entry.is_hot);
|
||||
assert_eq!(entry.access_count, 102); // 初始1次 + 101次
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_state_entry_cold_detection() {
|
||||
let key = Hash::from_slice(&[1u8; 32]).unwrap();
|
||||
let value = vec![1, 2, 3];
|
||||
let entry = StateEntry::new(key, value, 1000);
|
||||
|
||||
// 在阈值内不是冷数据
|
||||
assert!(!entry.is_cold(1500, 1000));
|
||||
|
||||
// 超过阈值是冷数据
|
||||
assert!(entry.is_cold(2001, 1000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_optimizer_read_write() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 3600, 1024 * 1024);
|
||||
let key = Hash::from_slice(&[1u8; 32]).unwrap();
|
||||
let value = vec![1, 2, 3, 4];
|
||||
|
||||
// 写入状态
|
||||
assert!(optimizer.write_state(key.clone(), value.clone(), 1000).is_ok());
|
||||
|
||||
// 读取状态
|
||||
let read_value = optimizer.read_state(&key, 1001);
|
||||
assert_eq!(read_value, Some(value));
|
||||
|
||||
// 验证统计
|
||||
assert_eq!(optimizer.stats.cache_hits, 1);
|
||||
assert_eq!(optimizer.stats.total_accesses, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_optimizer_cache_miss() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 3600, 1024 * 1024);
|
||||
let key = Hash::from_slice(&[1u8; 32]).unwrap();
|
||||
|
||||
// 读取不存在的状态
|
||||
let result = optimizer.read_state(&key, 1000);
|
||||
assert!(result.is_none());
|
||||
|
||||
// 验证统计
|
||||
assert_eq!(optimizer.stats.cache_misses, 1);
|
||||
assert_eq!(optimizer.stats.total_accesses, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_optimizer_evict_cold_data() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 1000, 1024);
|
||||
|
||||
// 写入一些数据
|
||||
for i in 0..5 {
|
||||
let key = Hash::from_slice(&[i; 32]).unwrap();
|
||||
let value = vec![i; 100];
|
||||
optimizer.write_state(key, value, 1000 + i as u64).unwrap();
|
||||
}
|
||||
|
||||
// 等待一段时间后驱逐冷数据
|
||||
assert!(optimizer.evict_cold_data(3000).is_ok());
|
||||
|
||||
// 验证统计
|
||||
assert!(optimizer.stats.cold_data_archived > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_optimizer_hot_account_tracking() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 3600, 1024 * 1024);
|
||||
let address = Address::from_slice(&[1u8; 20]).unwrap();
|
||||
|
||||
// 记录大量活动
|
||||
for i in 0..1001 {
|
||||
optimizer.record_account_activity(address.clone(), i % 2 == 0, 100, 1000 + i);
|
||||
}
|
||||
|
||||
// 验证热点账户
|
||||
let hot_accounts = optimizer.get_hot_accounts();
|
||||
assert_eq!(hot_accounts.len(), 1);
|
||||
assert_eq!(hot_accounts[0], address);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_optimizer_cache_usage() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 3600, 1000);
|
||||
|
||||
// 写入500字节数据
|
||||
let key = Hash::from_slice(&[1u8; 32]).unwrap();
|
||||
let value = vec![1u8; 500];
|
||||
optimizer.write_state(key, value, 1000).unwrap();
|
||||
|
||||
// 验证缓存使用率
|
||||
assert_eq!(optimizer.get_cache_usage(), 0.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_optimizer_cleanup_expired() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 1000, 1024 * 1024);
|
||||
|
||||
// 写入一些数据
|
||||
for i in 0..5 {
|
||||
let key = Hash::from_slice(&[i; 32]).unwrap();
|
||||
let value = vec![i; 10];
|
||||
optimizer.write_state(key, value, 1000).unwrap();
|
||||
}
|
||||
|
||||
// 清理过期数据(超过2000秒)
|
||||
let expired = optimizer.cleanup_expired(4000);
|
||||
assert_eq!(expired, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_optimizer_full_optimization() {
|
||||
let mut optimizer = StateShardOptimizer::new(1, 1000, 1024 * 1024);
|
||||
|
||||
// 写入一些数据
|
||||
for i in 0..10 {
|
||||
let key = Hash::from_slice(&[i; 32]).unwrap();
|
||||
let value = vec![i; 100];
|
||||
optimizer.write_state(key, value, 1000 + i as u64).unwrap();
|
||||
}
|
||||
|
||||
// 访问部分数据使其成为热点(但不超过100次,避免自动标记为hot)
|
||||
for i in 0..3 {
|
||||
let key = Hash::from_slice(&[i; 32]).unwrap();
|
||||
for _ in 0..50 {
|
||||
optimizer.read_state(&key, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行优化
|
||||
let report = optimizer.optimize(4000).unwrap();
|
||||
|
||||
assert_eq!(report.shard_id, 1);
|
||||
assert!(report.promoted_count > 0);
|
||||
assert!(report.cache_hit_rate > 0.0);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue