NAC_Blockchain/nac-lens-jurisdiction-router/src/lib.rs

468 lines
16 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.

// NAC_Lens 4.0 辖区路由层集成模块Issue #77
// 将 jurisdiction_router.rs 集成到 NAC_Lens 消息分发管道
// CBPP原则约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小
// NAC_Lens 是 NAC 原生协议(原 NRPC 已统一更名为 NAC_Lens
// 跨辖区交易源辖区节点和目标辖区节点各自独立出具CR参与即是共识非多签
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// NAC_Lens 消息类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum NacLensMessageType {
/// 单辖区交易
IntraJurisdiction {
jurisdiction: String,
},
/// 跨辖区交易(源辖区 -> 目标辖区)
CrossJurisdiction {
source_jurisdiction: String,
target_jurisdiction: String,
},
/// 辖区规则更新广播CA签名授权约法即是治法
JurisdictionRuleUpdate {
jurisdiction: String,
new_version: String,
ca_signature: Vec<u8>,
},
/// 宪法收据CR广播参与即是共识
ConstitutionalReceiptBroadcast {
jurisdiction: String,
tx_hash: String,
cr_hash: String,
},
/// 辖区节点注册GIDS辖区证明
NodeRegistration {
jurisdiction: String,
node_id: String,
gids_proof: Vec<u8>,
},
}
/// NAC_Lens 消息信封
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NacLensEnvelope {
/// 协议版本NAC_Lens 4.0
pub protocol_version: String,
/// 消息ID
pub message_id: String,
/// 消息类型
pub message_type: NacLensMessageType,
/// 消息体(序列化的交易或规则数据)
pub payload: Vec<u8>,
/// 发送节点ID
pub sender_node_id: String,
/// 时间戳UTC Unix 毫秒)
pub timestamp: u64,
}
impl NacLensEnvelope {
pub fn new(
message_id: &str,
message_type: NacLensMessageType,
payload: Vec<u8>,
sender_node_id: &str,
) -> Self {
Self {
protocol_version: "NAC_Lens/4.0".to_string(),
message_id: message_id.to_string(),
message_type,
payload,
sender_node_id: sender_node_id.to_string(),
timestamp: 0, // 实际使用时由运行时填充
}
}
}
/// 辖区路由表条目
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JurisdictionRouteEntry {
/// 辖区代码
pub jurisdiction_code: String,
/// 辖区节点列表节点ID -> 节点地址)
pub nodes: HashMap<String, String>,
/// 当前活跃规则版本
pub active_rule_version: String,
/// 路由优先级0=最高)
pub priority: u8,
/// 是否接受跨辖区消息
pub accepts_cross_jurisdiction: bool,
}
/// NAC_Lens 辖区路由器
/// 负责将消息路由到正确的辖区节点,支持跨辖区消息转发
pub struct NacLensJurisdictionRouter {
/// 路由表jurisdiction_code -> RouteEntry
routing_table: HashMap<String, JurisdictionRouteEntry>,
/// 本节点所属辖区
local_jurisdiction: String,
/// 本节点ID
local_node_id: String,
}
impl NacLensJurisdictionRouter {
pub fn new(local_jurisdiction: &str, local_node_id: &str) -> Self {
Self {
routing_table: HashMap::new(),
local_jurisdiction: local_jurisdiction.to_string(),
local_node_id: local_node_id.to_string(),
}
}
/// 注册辖区路由
pub fn register_jurisdiction(&mut self, entry: JurisdictionRouteEntry) {
self.routing_table.insert(entry.jurisdiction_code.clone(), entry);
}
/// 路由消息到目标辖区节点
/// 约法即是治法:路由决策基于宪法规则,不基于节点偏好
pub fn route(&self, envelope: &NacLensEnvelope) -> RoutingDecision {
match &envelope.message_type {
NacLensMessageType::IntraJurisdiction { jurisdiction } => {
self.route_intra_jurisdiction(jurisdiction, envelope)
}
NacLensMessageType::CrossJurisdiction {
source_jurisdiction,
target_jurisdiction,
} => self.route_cross_jurisdiction(source_jurisdiction, target_jurisdiction, envelope),
NacLensMessageType::JurisdictionRuleUpdate {
jurisdiction,
ca_signature,
..
} => {
// 规则更新广播到所有辖区节点CA签名验证通过后立即生效
if ca_signature.is_empty() {
return RoutingDecision::Rejected {
reason: "Rule update rejected: missing CA signature. \
Per CBPP '约法即是治法', rule updates require CA authorization."
.to_string(),
};
}
self.route_rule_update_broadcast(jurisdiction)
}
NacLensMessageType::ConstitutionalReceiptBroadcast {
jurisdiction,
tx_hash,
cr_hash,
} => {
// CR广播广播到所有节点参与即是共识
RoutingDecision::Broadcast {
target_jurisdictions: self.routing_table.keys().cloned().collect(),
message_summary: format!(
"CR broadcast: jurisdiction={}, tx={}, cr={}",
jurisdiction, tx_hash, cr_hash
),
}
}
NacLensMessageType::NodeRegistration {
jurisdiction,
node_id,
gids_proof,
} => {
if gids_proof.is_empty() {
return RoutingDecision::Rejected {
reason: format!(
"Node {} registration rejected: missing GIDS proof for jurisdiction {}",
node_id, jurisdiction
),
};
}
RoutingDecision::Forward {
target_jurisdiction: jurisdiction.clone(),
target_nodes: self
.routing_table
.get(jurisdiction)
.map(|e| e.nodes.keys().cloned().collect())
.unwrap_or_default(),
}
}
}
}
/// 单辖区内部路由
fn route_intra_jurisdiction(
&self,
jurisdiction: &str,
_envelope: &NacLensEnvelope,
) -> RoutingDecision {
if let Some(entry) = self.routing_table.get(jurisdiction) {
RoutingDecision::Forward {
target_jurisdiction: jurisdiction.to_string(),
target_nodes: entry.nodes.keys().cloned().collect(),
}
} else {
RoutingDecision::Rejected {
reason: format!(
"Jurisdiction {} not found in routing table. \
Node must register jurisdiction before routing.",
jurisdiction
),
}
}
}
/// 跨辖区路由
/// 参与即是共识源辖区和目标辖区各自独立处理各自出具CR
fn route_cross_jurisdiction(
&self,
source: &str,
target: &str,
_envelope: &NacLensEnvelope,
) -> RoutingDecision {
let source_entry = self.routing_table.get(source);
let target_entry = self.routing_table.get(target);
match (source_entry, target_entry) {
(Some(_src), Some(tgt)) => {
if !tgt.accepts_cross_jurisdiction {
return RoutingDecision::Rejected {
reason: format!(
"Jurisdiction {} does not accept cross-jurisdiction messages",
target
),
};
}
// 跨辖区:同时转发到源辖区和目标辖区
// 各辖区节点独立出具CR参与即是共识非多签
RoutingDecision::CrossJurisdictionForward {
source_jurisdiction: source.to_string(),
target_jurisdiction: target.to_string(),
source_nodes: self
.routing_table
.get(source)
.map(|e| e.nodes.keys().cloned().collect())
.unwrap_or_default(),
target_nodes: tgt.nodes.keys().cloned().collect(),
}
}
(None, _) => RoutingDecision::Rejected {
reason: format!("Source jurisdiction {} not registered", source),
},
(_, None) => RoutingDecision::Rejected {
reason: format!("Target jurisdiction {} not registered", target),
},
}
}
/// 规则更新广播路由
fn route_rule_update_broadcast(&self, jurisdiction: &str) -> RoutingDecision {
RoutingDecision::Broadcast {
target_jurisdictions: vec![jurisdiction.to_string()],
message_summary: format!(
"Rule update broadcast to all {} nodes (CA-authorized, effective immediately)",
jurisdiction
),
}
}
/// 获取辖区路由表统计
pub fn routing_stats(&self) -> RoutingStats {
let total_nodes: usize = self.routing_table.values().map(|e| e.nodes.len()).sum();
RoutingStats {
registered_jurisdictions: self.routing_table.len(),
total_nodes,
local_jurisdiction: self.local_jurisdiction.clone(),
local_node_id: self.local_node_id.clone(),
}
}
/// 更新辖区规则版本CA签名授权后调用
pub fn update_jurisdiction_version(&mut self, jurisdiction: &str, new_version: &str) -> bool {
if let Some(entry) = self.routing_table.get_mut(jurisdiction) {
entry.active_rule_version = new_version.to_string();
true
} else {
false
}
}
}
/// 路由决策
#[derive(Debug, Clone)]
pub enum RoutingDecision {
/// 转发到指定辖区节点
Forward {
target_jurisdiction: String,
target_nodes: Vec<String>,
},
/// 跨辖区转发(源辖区和目标辖区各自独立处理)
CrossJurisdictionForward {
source_jurisdiction: String,
target_jurisdiction: String,
source_nodes: Vec<String>,
target_nodes: Vec<String>,
},
/// 广播到多个辖区
Broadcast {
target_jurisdictions: Vec<String>,
message_summary: String,
},
/// 拒绝路由
Rejected {
reason: String,
},
}
/// 路由统计信息
#[derive(Debug, Clone)]
pub struct RoutingStats {
pub registered_jurisdictions: usize,
pub total_nodes: usize,
pub local_jurisdiction: String,
pub local_node_id: String,
}
#[cfg(test)]
mod tests {
use super::*;
fn make_router() -> NacLensJurisdictionRouter {
let mut router = NacLensJurisdictionRouter::new("CN", "node_cn_001");
// 注册 CN 辖区
let mut cn_nodes = HashMap::new();
cn_nodes.insert("node_cn_001".to_string(), "192.168.1.1:8080".to_string());
cn_nodes.insert("node_cn_002".to_string(), "192.168.1.2:8080".to_string());
router.register_jurisdiction(JurisdictionRouteEntry {
jurisdiction_code: "CN".to_string(),
nodes: cn_nodes,
active_rule_version: "1.0.0".to_string(),
priority: 0,
accepts_cross_jurisdiction: true,
});
// 注册 HK 辖区
let mut hk_nodes = HashMap::new();
hk_nodes.insert("node_hk_001".to_string(), "10.0.1.1:8080".to_string());
router.register_jurisdiction(JurisdictionRouteEntry {
jurisdiction_code: "HK".to_string(),
nodes: hk_nodes,
active_rule_version: "1.0.0".to_string(),
priority: 0,
accepts_cross_jurisdiction: true,
});
router
}
#[test]
fn test_intra_jurisdiction_routing() {
let router = make_router();
let envelope = NacLensEnvelope::new(
"msg_001",
NacLensMessageType::IntraJurisdiction {
jurisdiction: "CN".to_string(),
},
vec![],
"node_cn_001",
);
let decision = router.route(&envelope);
assert!(matches!(decision, RoutingDecision::Forward { .. }));
if let RoutingDecision::Forward { target_jurisdiction, target_nodes } = decision {
assert_eq!(target_jurisdiction, "CN");
assert_eq!(target_nodes.len(), 2);
}
}
#[test]
fn test_cross_jurisdiction_routing() {
let router = make_router();
let envelope = NacLensEnvelope::new(
"msg_002",
NacLensMessageType::CrossJurisdiction {
source_jurisdiction: "CN".to_string(),
target_jurisdiction: "HK".to_string(),
},
vec![],
"node_cn_001",
);
let decision = router.route(&envelope);
// 跨辖区:各辖区独立处理,参与即是共识
assert!(matches!(decision, RoutingDecision::CrossJurisdictionForward { .. }));
}
#[test]
fn test_rule_update_requires_ca_signature() {
let router = make_router();
let envelope = NacLensEnvelope::new(
"msg_003",
NacLensMessageType::JurisdictionRuleUpdate {
jurisdiction: "CN".to_string(),
new_version: "2.0.0".to_string(),
ca_signature: vec![], // 无签名
},
vec![],
"node_cn_001",
);
let decision = router.route(&envelope);
assert!(matches!(decision, RoutingDecision::Rejected { .. }));
}
#[test]
fn test_rule_update_with_ca_signature() {
let router = make_router();
let envelope = NacLensEnvelope::new(
"msg_004",
NacLensMessageType::JurisdictionRuleUpdate {
jurisdiction: "CN".to_string(),
new_version: "2.0.0".to_string(),
ca_signature: vec![1u8; 64], // 有效CA签名
},
vec![],
"node_cn_001",
);
let decision = router.route(&envelope);
assert!(matches!(decision, RoutingDecision::Broadcast { .. }));
}
#[test]
fn test_unknown_jurisdiction_rejected() {
let router = make_router();
let envelope = NacLensEnvelope::new(
"msg_005",
NacLensMessageType::IntraJurisdiction {
jurisdiction: "UNKNOWN".to_string(),
},
vec![],
"node_cn_001",
);
let decision = router.route(&envelope);
assert!(matches!(decision, RoutingDecision::Rejected { .. }));
}
#[test]
fn test_routing_stats() {
let router = make_router();
let stats = router.routing_stats();
assert_eq!(stats.registered_jurisdictions, 2);
assert_eq!(stats.total_nodes, 3);
assert_eq!(stats.local_jurisdiction, "CN");
}
#[test]
fn test_node_registration_without_gids_rejected() {
let router = make_router();
let envelope = NacLensEnvelope::new(
"msg_006",
NacLensMessageType::NodeRegistration {
jurisdiction: "CN".to_string(),
node_id: "node_new".to_string(),
gids_proof: vec![], // 无GIDS证明
},
vec![],
"node_new",
);
let decision = router.route(&envelope);
assert!(matches!(decision, RoutingDecision::Rejected { .. }));
}
#[test]
fn test_update_jurisdiction_version() {
let mut router = make_router();
let updated = router.update_jurisdiction_version("CN", "2.0.0");
assert!(updated);
let stats = router.routing_stats();
assert_eq!(stats.registered_jurisdictions, 2);
}
}