feat(constitution): Issue #70 — 宪法层新增A44-A52多辖区节点共享条款

新增宪法条款(A44-A52):
- A44: 多辖区节点物理共享许可(容器化逻辑隔离)
- A45: 跨辖区区块生产双CR强制(jurisdiction_merkle_root)
- A46: 共享资源辖区协商分配(≥67%委员会投票)
- A47: 节点身份辖区绑定强制(GIDS增强)
- A48: WASM规则插件沙箱执行强制(≤10ms/64MB)
- A49: CEE节点跨辖区共享验证(负载均衡)
- A50: 辖区争议宪法法院裁决(链上判决)
- A51: CSNP辖区感知路由强制
- A52: 共享存储敏感数据加密(AES-256-GCM)

新增文件:
- nac-constitution/clauses/node_sharing_clauses.cnnl
- nac-constitution-clauses/src/node_sharing.rs(12个测试全部通过)
- nac-multi-jurisdiction/src/node_sharing_enhanced.rs(5个测试全部通过)
- charter-std/src/constitution_interface.charter
- ISSUE_070_CONSTITUTIONAL_RULES_DELIVERY.md

关联:Issue #59(多辖区节点共享方案)、Issue #66(宪法增补条款A01-A43)
This commit is contained in:
NAC Admin 2026-03-07 12:17:02 +08:00
parent b991cbb4ee
commit 2c2883f2f5
7 changed files with 2690 additions and 0 deletions

View File

@ -0,0 +1,213 @@
# Issue #70 — 宪法层规则增补:多辖区节点共享条款
**状态:** 已完成
**版本:** 1.0
**日期:** 2026-03-07
**关联白皮书:** 《NAC公链多辖区节点共享方案与技术落地白皮书》v1.0
**关联 Issue** #59(多辖区节点共享方案)、#66宪法增补条款A01-A43
---
## 一、工作概述
本次工单在现有宪法增补条款A01-A43基础上新增 **9 条多辖区节点共享宪法条款A44-A52**覆盖物理共享逻辑隔离、跨辖区区块生产、资源协商分配、节点身份绑定、WASM沙箱、CEE集群、争议裁决、CSNP路由、存储加密等核心规则。
---
## 二、新增宪法条款清单A44-A52
| 条款编号 | 层级 | 条款名称 | 核心规则 | 违规处理 |
|----------|------|----------|----------|----------|
| A44 | Strategic | 多辖区节点物理共享许可 | 物理共享节点必须容器化逻辑隔离 | reject_block |
| A45 | Strategic | 跨辖区区块生产双CR强制 | 区块头必须含 jurisdiction_merkle_root | reject_block |
| A46 | Strategic | 共享资源辖区协商分配 | 资源分配需委员会≥67%投票 | revert_allocation |
| A47 | Tactical | 节点身份辖区绑定强制 | GIDS注册需辖区政府数字签名 | reject_node_registration |
| A48 | Tactical | WASM规则插件沙箱执行强制 | 插件执行≤10ms、≤64MB、哈希上链 | terminate_plugin_execution |
| A49 | Tactical | CEE节点跨辖区共享验证 | CEE必须支持多辖区并行验证 | fallback_to_single_jurisdiction_cee |
| A50 | Tactical | 辖区争议宪法法院裁决 | 争议必须提交宪法法院、判决上链 | freeze_disputed_resources |
| A51 | Tactical | CSNP辖区感知路由强制 | CSNP必须识别辖区并保留原始CR | reject_non_compliant_routing |
| A52 | Tactical | 共享存储敏感数据加密 | AES-256-GCM加密、≥3副本冗余 | quarantine_unencrypted_data |
---
## 三、交付文件清单
### 3.1 CNNL 宪法条款文件
```
nac-constitution/clauses/node_sharing_clauses.cnnl
```
- 9条条款的 CNNL 形式化表达
- 每条包含tier层级、clause_index索引、predicate谓词、obligation义务、violation_action违规处理、test测试块
- 完整测试块9个测试用例
### 3.2 Rust 验证引擎
```
nac-constitution-clauses/src/node_sharing.rs
```
- 每条条款独立的验证函数(`validate_a44_*` 至 `validate_a52_*`
- 综合验证报告(`NodeSharingComplianceReport`
- 违规摘要生成(`violation_summary()`
- 完整单元测试12个测试用例覆盖合规和违规场景
### 3.3 多辖区运行时增强
```
nac-multi-jurisdiction/src/node_sharing_enhanced.rs
```
- `SharedNodeRegistry`:节点共享注册表(隔离违规检测)
- `DynamicQuotaManager`动态资源配额管理A46
- `CrossJurisdictionBlockCoordinator`跨辖区区块生产协调器A45
- `GidsEnhancedRegistry`GIDS增强注册表A47
- 完整单元测试5个测试用例
### 3.4 Charter 合约接口
```
charter-std/src/constitution_interface.charter
```
- `IConstitution` 接口:宪法内置合约完整接口定义
- `RwaAssetCrossJurisdictionTransfer` 示例合约演示A45/A46/A47/A50/A51集成
- `NodeSharingRegistry` 示例合约演示A44/A47/A48集成
---
## 四、架构设计说明
### 4.1 条款层级设计
```
宪法层级结构A44-A52 扩展后):
永恒级Eternal索引1-100
A01-A08 基础架构条款NAC原生技术栈保护
战略级Strategic索引101-1000
A09-A16 资产合规条款
A17-A24 节点治理条款
A25-A32 XTZH货币条款
A33-A38 多辖区条款(基础)
A39-A43 AI合规条款
★ A44 多辖区节点物理共享许可新增索引101
★ A45 跨辖区区块生产双CR强制新增索引102
★ A46 共享资源辖区协商分配新增索引103
战术级Tactical索引1001+
★ A47 节点身份辖区绑定强制新增索引1001
★ A48 WASM规则插件沙箱执行强制新增索引1002
★ A49 CEE节点跨辖区共享验证新增索引1003
★ A50 辖区争议宪法法院裁决新增索引1004
★ A51 CSNP辖区感知路由强制新增索引1005
★ A52 共享存储敏感数据加密新增索引1006
```
### 4.2 跨辖区区块生产流程A45
```
区块生产节点收到跨辖区交易
为每笔跨辖区交易选择最优CEE节点A49负载均衡
CEE节点并行调用源辖区和目标辖区插件A48 WASM沙箱
生成双CR源辖区CR + 目标辖区CR
将所有双CR哈希构建默克尔树 → jurisdiction_merkle_root
写入区块头 block.header.jurisdiction_merkle_root
CBPP验证节点验证 jurisdiction_merkle_root 有效性
区块上链
```
### 4.3 节点注册流程A47
```
节点申请加入网络
向辖区政府/监管机构申请辖区证明jurisdiction_proof
提交 GIDS 注册DID + 辖区 + 辖区证明 + 插件哈希列表)
GIDS 验证:
- DID 格式must start with "did:nac:"
- 辖区 != 0
- 辖区证明签名有效且未过期
- 至少一个已授权插件哈希
注册成功,节点可加入网络
节点加载插件时GIDS 实时验证插件哈希A47+A48
```
### 4.4 资源分配流程A46
```
辖区提交资源分配提案
辖区协商委员会JurisdictionCouncil投票
投票比例 ≥ 67%
├─ 是 → 提案通过DynamicQuotaManager 应用新配额
└─ 否 → 提案拒绝,维持原配额
配额变更记录写入宪法附录(链上存证)
各辖区节点按新配额运行
超出配额时触发 A46 违规处理revert_allocation
```
---
## 五、与现有模块的集成关系
| 现有模块 | 集成方式 | 涉及条款 |
|----------|----------|----------|
| `nac-constitution-clauses` | 新增 `node_sharing.rs` 验证器 | A44-A52 |
| `nac-multi-jurisdiction` | 新增 `node_sharing_enhanced.rs` 运行时 | A44-A47、A49 |
| `nac-cbpp` | 区块头新增 `jurisdiction_merkle_root` 字段 | A45 |
| `nac-csnp` | 新增辖区感知路由模块 | A51 |
| `nac-nvm` | 新增宪法内置合约地址0x...0001 | A44-A52 |
| `charter-std` | 新增 `constitution_interface.charter` | A44-A52 |
| `nac-ai-compliance` | AI合规检查集成A39-A43 | A39-A43 |
---
## 六、测试覆盖
| 文件 | 测试数量 | 覆盖场景 |
|------|----------|----------|
| `node_sharing.rs` | 12 | A44合规/违规、A45跨辖区、A46投票、A47身份、A48沙箱、A52存储 |
| `node_sharing_enhanced.rs` | 5 | 注册表、隔离检测、配额超额、GIDS验证、区块协调器 |
| `node_sharing_clauses.cnnl` | 9 | 每条条款独立测试块 |
---
## 七、后台管理员信息
- **Gitea 管理员账号:** nacadmin
- **Gitea 管理员密码:** NACadmin2026!
- **服务器 SSH** root@103.96.148.7:22000
- **服务器密码:** XKUigTFMJXhH
- **宝塔面板:** http://103.96.148.7:12/btwestcproot / vajngkvf
---
## 八、下一步工作建议
1. **Issue #71**:将 `jurisdiction_merkle_root` 字段集成到 CBPP 区块头结构(`nac-cbpp` 模块)
2. **Issue #72**:实现 NVM 宪法内置合约(地址 `0x0000000000000000000000000000000000000001`
3. **Issue #73**CSNP 辖区感知路由实现(`nac-csnp` 模块扩展)
4. **Issue #74**WASM 插件运行时沙箱集成(`nac-nvm` 模块扩展)
5. **Issue #75**:宪法条款 A44-A52 主网部署和测试
---
*本文档由 NAC 核心协议工程组生成 | Issue #70 | 2026-03-07*

View File

@ -0,0 +1,435 @@
// charter-std/src/constitution_interface.charter
// NAC公链 Charter 智能合约宪法接口
// Issue #70 | 版本: 1.0 | 2026-03-07
//
// 本文件定义 Charter 合约访问宪法层的标准接口:
// - 宪法条款查询接口A44-A52
// - 节点共享合规验证绑定
// - 跨辖区资源分配查询
// - 辖区身份验证接口
// ============================================================
// 标准库导入Charter 原生)
// ============================================================
import std::types::{ Address, Hash, Bytes48, Uint16, Uint64, Bool, String }
import std::acc20::{ AssetId, AssetRecord }
import std::cr::{ ConstitutionalReceipt, DualConstitutionalReceipt }
import std::jurisdiction::{ JurisdictionId, JurisdictionProof }
// ============================================================
// 宪法条款查询接口
// ============================================================
/// 宪法条款层级
enum ClauseTier {
Eternal, // 永恒级索引1-100
Strategic, // 战略级索引101-1000
Tactical, // 战术级索引1001+
}
/// 宪法条款记录
struct ConstitutionalClause {
clause_index: Uint64,
title: String,
tier: ClauseTier,
is_active: Bool,
effective_from: Uint64,
clause_hash: Bytes48,
}
/// 节点共享宪法条款A44-A52
struct NodeSharingClause {
clause_index: Uint64,
name: String,
tier: ClauseTier,
// 条款核心谓词CNNL形式化表达
predicate_hash: Bytes48,
// 违规处理动作
violation_action: String,
is_active: Bool,
}
// ============================================================
// 宪法接口(内置合约,地址 0x0000...CONST
// ============================================================
/// NAC宪法内置合约接口
/// 合约地址0x0000000000000000000000000000000000000001
interface IConstitution {
// --- 条款查询 ---
/// 查询宪法条款是否激活
/// @param clause_index 条款索引(如 A44 = 44
/// @returns 条款是否处于激活状态
fn is_clause_active(clause_index: Uint64) -> Bool
/// 获取条款详情
/// @param clause_index 条款索引
/// @returns 条款记录(不存在时 panic
fn get_clause(clause_index: Uint64) -> ConstitutionalClause
/// 获取节点共享条款A44-A52
/// @param clause_index 条款索引44-52
/// @returns 节点共享条款记录
fn get_node_sharing_clause(clause_index: Uint64) -> NodeSharingClause
// --- 节点共享合规验证A44---
/// 验证节点是否满足物理共享逻辑隔离要求A44
/// @param node_did 节点DID
/// @param container_id 容器实例ID不能为空
/// @param network_namespace 网络命名空间(不能为空)
/// @returns 是否合规
fn verify_node_sharing_isolation(
node_did: String,
container_id: String,
network_namespace: String,
) -> Bool
// --- 跨辖区双CR验证A45---
/// 验证跨辖区交易的双CRA45
/// @param source_cr 源辖区宪法收据
/// @param target_cr 目标辖区宪法收据
/// @returns 双CR是否有效
fn verify_dual_cr(
source_cr: ConstitutionalReceipt,
target_cr: ConstitutionalReceipt,
) -> Bool
/// 获取当前区块的 jurisdiction_merkle_rootA45
/// @returns 当前区块的辖区默克尔树根(无跨辖区交易时返回零哈希)
fn get_jurisdiction_merkle_root() -> Bytes48
// --- 资源配额查询A46---
/// 查询辖区当前资源配额A46
/// @param jurisdiction 辖区ID
/// @returns (cpu_share, memory_share, bandwidth_share, storage_share) 定点数1e4
fn get_jurisdiction_quota(jurisdiction: JurisdictionId) -> (Uint64, Uint64, Uint64, Uint64)
/// 检查辖区是否超出资源配额A46
/// @param jurisdiction 辖区ID
/// @returns 是否超出配额
fn is_quota_exceeded(jurisdiction: JurisdictionId) -> Bool
// --- 节点身份辖区绑定A47---
/// 验证节点DID的辖区绑定A47
/// @param node_did 节点DID
/// @param jurisdiction 声明的辖区ID
/// @returns 绑定是否有效
fn verify_node_jurisdiction_binding(
node_did: String,
jurisdiction: JurisdictionId,
) -> Bool
/// 验证节点加载的插件哈希是否已授权A47
/// @param node_did 节点DID
/// @param plugin_hash 插件哈希SHA3-384
/// @returns 插件是否已授权
fn verify_plugin_hash_authorized(
node_did: String,
plugin_hash: Bytes48,
) -> Bool
// --- WASM沙箱验证A48---
/// 验证插件是否在WASM沙箱中执行A48
/// @param plugin_hash 插件哈希
/// @returns 是否在WASM沙箱中执行
fn verify_wasm_sandbox_execution(plugin_hash: Bytes48) -> Bool
/// 检查插件哈希是否已上链A48
/// @param plugin_hash 插件哈希
/// @returns 是否已上链
fn is_plugin_hash_on_chain(plugin_hash: Bytes48) -> Bool
// --- CEE集群查询A49---
/// 获取支持指定辖区的CEE节点列表A49
/// @param jurisdiction 辖区ID
/// @returns CEE节点DID列表
fn get_cee_nodes_for_jurisdiction(jurisdiction: JurisdictionId) -> Array<String>
/// 获取负载最低的CEE节点A49用于跨辖区交易路由
/// @param source_jurisdiction 源辖区
/// @param target_jurisdiction 目标辖区
/// @returns 最优CEE节点DID无可用节点时返回空字符串
fn get_optimal_cee_node(
source_jurisdiction: JurisdictionId,
target_jurisdiction: JurisdictionId,
) -> String
// --- 争议状态查询A50---
/// 查询辖区间是否存在未解决争议A50
/// @param jurisdiction_a 辖区A
/// @param jurisdiction_b 辖区B
/// @returns 是否存在未解决争议
fn has_pending_dispute(
jurisdiction_a: JurisdictionId,
jurisdiction_b: JurisdictionId,
) -> Bool
// --- CSNP路由验证A51---
/// 验证CSNP辖区感知路由是否启用A51
/// @returns 是否启用
fn is_csnp_jurisdiction_routing_enabled() -> Bool
// --- 存储加密验证A52---
/// 验证存储节点是否满足加密要求A52
/// @param storage_node_did 存储节点DID
/// @returns 是否满足A52要求
fn verify_storage_encryption_compliance(storage_node_did: String) -> Bool
}
// ============================================================
// 示例合约:使用宪法接口的 RWA 资产跨辖区转移合约
// ============================================================
/// RWA资产跨辖区转移合约集成A44-A52宪法条款
contract RwaAssetCrossJurisdictionTransfer {
// 宪法内置合约地址
const CONSTITUTION_ADDRESS: Address = 0x0000000000000000000000000000000000000001
// 状态变量
state {
owner: Address,
asset_id: AssetId,
source_jurisdiction: JurisdictionId,
target_jurisdiction: JurisdictionId,
transfer_status: TransferStatus,
source_cr: ConstitutionalReceipt,
target_cr: ConstitutionalReceipt,
initiated_at: Uint64,
}
enum TransferStatus {
Pending,
CrVerified,
Completed,
Failed,
}
// 构造函数
constructor(
asset_id: AssetId,
source_jurisdiction: JurisdictionId,
target_jurisdiction: JurisdictionId,
) {
self.owner = msg.sender
self.asset_id = asset_id
self.source_jurisdiction = source_jurisdiction
self.target_jurisdiction = target_jurisdiction
self.transfer_status = TransferStatus::Pending
self.initiated_at = block.timestamp
}
/// 提交双CR并验证A45
/// 调用者必须提供源辖区和目标辖区的宪法收据
fn submit_dual_cr(
source_cr: ConstitutionalReceipt,
target_cr: ConstitutionalReceipt,
) -> Bool {
// 仅资产所有者可提交
require(msg.sender == self.owner, "仅资产所有者可提交双CR")
require(self.transfer_status == TransferStatus::Pending, "转移状态不正确")
// 调用宪法内置合约验证双CRA45
let constitution = IConstitution(CONSTITUTION_ADDRESS)
let is_valid = constitution.verify_dual_cr(source_cr, target_cr)
if !is_valid {
self.transfer_status = TransferStatus::Failed
emit DualCrVerificationFailed(self.asset_id, block.timestamp)
return false
}
// 检查辖区间是否有未解决争议A50
let has_dispute = constitution.has_pending_dispute(
self.source_jurisdiction,
self.target_jurisdiction,
)
require(!has_dispute, "A50: 辖区间存在未解决争议,转移被暂停")
// 检查目标辖区资源配额A46
let quota_exceeded = constitution.is_quota_exceeded(self.target_jurisdiction)
require(!quota_exceeded, "A46: 目标辖区资源配额已超出,请稍后重试")
self.source_cr = source_cr
self.target_cr = target_cr
self.transfer_status = TransferStatus::CrVerified
emit DualCrVerified(self.asset_id, self.source_jurisdiction, self.target_jurisdiction)
return true
}
/// 执行跨辖区转移A45验证通过后
fn execute_transfer(recipient: Address) -> Bool {
require(msg.sender == self.owner, "仅资产所有者可执行转移")
require(self.transfer_status == TransferStatus::CrVerified, "双CR未验证")
let constitution = IConstitution(CONSTITUTION_ADDRESS)
// 验证接收方节点的辖区绑定A47
// 注:实际实现中需要通过 NRPC4.0 查询接收方节点DID
// 验证CSNP路由是否启用A51
let routing_enabled = constitution.is_csnp_jurisdiction_routing_enabled()
require(routing_enabled, "A51: CSNP辖区感知路由未启用无法执行跨辖区转移")
// 执行ACC-20资产转移NAC原生标准
// 注:使用 std::acc20 而非 ERC-20
let transfer_result = acc20::transfer_cross_jurisdiction(
self.asset_id,
self.owner,
recipient,
self.source_cr,
self.target_cr,
)
if transfer_result {
self.transfer_status = TransferStatus::Completed
emit TransferCompleted(
self.asset_id,
self.owner,
recipient,
self.source_jurisdiction,
self.target_jurisdiction,
block.timestamp,
)
} else {
self.transfer_status = TransferStatus::Failed
emit TransferFailed(self.asset_id, block.timestamp)
}
return transfer_result
}
// 事件定义
event DualCrVerificationFailed(asset_id: AssetId, timestamp: Uint64)
event DualCrVerified(
asset_id: AssetId,
source_jurisdiction: JurisdictionId,
target_jurisdiction: JurisdictionId,
)
event TransferCompleted(
asset_id: AssetId,
from: Address,
to: Address,
source_jurisdiction: JurisdictionId,
target_jurisdiction: JurisdictionId,
timestamp: Uint64,
)
event TransferFailed(asset_id: AssetId, timestamp: Uint64)
}
// ============================================================
// 示例合约节点共享注册合约A44/A47
// ============================================================
/// 节点共享注册合约
/// 用于在链上记录节点的物理共享状态和辖区绑定
contract NodeSharingRegistry {
const CONSTITUTION_ADDRESS: Address = 0x0000000000000000000000000000000000000001
state {
admin: Address,
// 节点DID → 共享节点记录
nodes: Map<String, SharedNodeOnChain>,
// 辖区 → 节点DID列表
jurisdiction_nodes: Map<JurisdictionId, Array<String>>,
total_nodes: Uint64,
}
struct SharedNodeOnChain {
node_did: String,
jurisdiction: JurisdictionId,
physical_host_id: String,
container_id: String,
network_namespace: String,
plugin_hashes: Array<Bytes48>,
is_active: Bool,
registered_at: Uint64,
jurisdiction_proof_hash: Bytes48,
}
constructor() {
self.admin = msg.sender
self.total_nodes = 0
}
/// 注册共享节点A44 + A47 双重验证)
fn register_shared_node(
node_did: String,
jurisdiction: JurisdictionId,
physical_host_id: String,
container_id: String,
network_namespace: String,
plugin_hashes: Array<Bytes48>,
jurisdiction_proof_hash: Bytes48,
) -> Bool {
let constitution = IConstitution(CONSTITUTION_ADDRESS)
// A44: 验证节点逻辑隔离
let isolation_ok = constitution.verify_node_sharing_isolation(
node_did,
container_id,
network_namespace,
)
require(isolation_ok, "A44: 节点未满足逻辑隔离要求")
// A47: 验证节点辖区绑定
let binding_ok = constitution.verify_node_jurisdiction_binding(node_did, jurisdiction)
require(binding_ok, "A47: 节点辖区绑定验证失败")
// A47: 验证所有插件哈希已授权
for hash in plugin_hashes {
let authorized = constitution.verify_plugin_hash_authorized(node_did, hash)
require(authorized, "A47: 存在未授权的辖区规则插件")
}
// A48: 验证插件在WASM沙箱中执行
for hash in plugin_hashes {
let wasm_ok = constitution.verify_wasm_sandbox_execution(hash)
require(wasm_ok, "A48: 插件必须在WASM沙箱中执行")
let on_chain = constitution.is_plugin_hash_on_chain(hash)
require(on_chain, "A48: 插件哈希必须已上链验证")
}
// 记录节点信息
let record = SharedNodeOnChain {
node_did: node_did,
jurisdiction: jurisdiction,
physical_host_id: physical_host_id,
container_id: container_id,
network_namespace: network_namespace,
plugin_hashes: plugin_hashes,
is_active: true,
registered_at: block.timestamp,
jurisdiction_proof_hash: jurisdiction_proof_hash,
}
self.nodes[node_did] = record
self.jurisdiction_nodes[jurisdiction].push(node_did)
self.total_nodes += 1
emit NodeRegistered(node_did, jurisdiction, block.timestamp)
return true
}
/// 查询辖区节点数量
fn get_jurisdiction_node_count(jurisdiction: JurisdictionId) -> Uint64 {
return self.jurisdiction_nodes[jurisdiction].length() as Uint64
}
event NodeRegistered(node_did: String, jurisdiction: JurisdictionId, timestamp: Uint64)
}

View File

@ -17,6 +17,7 @@ pub mod storage;
pub mod manager; pub mod manager;
pub mod lifecycle; pub mod lifecycle;
pub mod upgrade; pub mod upgrade;
pub mod node_sharing;
// 重新导出常用类型 // 重新导出常用类型
pub use validator::{ClauseValidator, ValidationError}; pub use validator::{ClauseValidator, ValidationError};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,216 @@
// NAC公链宪法增补条款 - 多辖区节点共享规则
// Issue #70 | 版本: 1.0 | 共 9 条增补条款A44-A52
// 基于《NAC公链多辖区节点共享方案与技术落地白皮书》v1.0
// 制定方NAC 核心协议工程组 · 多司法辖区工作组
// 发布日期2026-03-07
// 关联文档amendments.cnnlA01-A43、nac-multi-jurisdiction 模块
program NacNodeSharingClauses
name: "NAC公链多辖区节点共享宪法条款"
version: "1.0.0"
description: "9条多辖区节点共享宪法条款A44-A52规范物理共享与逻辑隔离"
// ============================================================
// 第七章多辖区节点共享条款A44-A52
// ============================================================
// --- 战略级条款Strategic Tier---
clause A44_NodeSharing
name: "多辖区节点物理共享许可"
tier: Strategic
clause_index: 101
description: "允许不同辖区节点共享物理基础设施(数据中心、云平台、硬件集群),
但必须通过容器化/虚拟化技术保持逻辑强隔离,确保各辖区规则互不干扰"
predicate: node.physical_shared implies node.logical_isolated == true
obligation: system.enforce_node_logical_isolation per_block
violation_action: reject_block
test: A44_test_node_sharing_isolation
references: ["多辖区节点共享白皮书 §3.2", "宪法层规范 §NODE_SHARING"]
clause A45_CrossJurisdictionConsensus
name: "跨辖区区块生产双CR强制"
tier: Strategic
clause_index: 102
description: "跨辖区区块生产时,区块头必须包含 jurisdiction_merkle_root 字段,
该字段为区块内所有跨辖区交易的宪法收据CR哈希的默克尔树根
每笔跨辖区交易必须附带源辖区和目标辖区的双CR"
predicate: block.has_cross_jurisdiction_tx implies
block.header.jurisdiction_merkle_root != null
obligation: cbpp.include_jurisdiction_merkle_root per_block
violation_action: reject_block
test: A45_test_cross_jurisdiction_consensus
references: ["多辖区节点共享白皮书 §3.4", "CBPP协议扩展规范"]
clause A46_ResourceAllocationByCouncil
name: "共享资源辖区协商分配"
tier: Strategic
clause_index: 103
description: "共享物理资源CPU、内存、带宽、存储的分配方案必须由辖区协商委员会
JurisdictionCouncil通过法定人数投票决定≥67%
并将分配结果写入宪法附录,不得由单一辖区单方面决定"
predicate: resource.allocation_method == "council_vote" and
resource.council_quorum >= 6700
obligation: governance.require_council_vote_for_resource_change per_epoch
violation_action: revert_allocation
test: A46_test_resource_allocation_council
references: ["多辖区节点共享白皮书 §5.2", "辖区协商机制规范"]
// --- 战术级条款Tactical Tier---
clause A47_NodeIdentityJurisdictionBinding
name: "节点身份辖区绑定强制"
tier: Tactical
clause_index: 1001
description: "每个节点在GIDS注册时其DID必须绑定明确的司法辖区jurisdiction字段
并提供该辖区政府或监管机构的数字签名jurisdiction_proof作为证明
节点加载的规则插件哈希plugin_hashes必须与GIDS记录一致"
predicate: node.did != "" and
node.jurisdiction != 0 and
node.jurisdiction_proof.valid == true and
node.plugin_hashes == gids.get_plugin_hashes(node.did)
obligation: gids.verify_node_jurisdiction_binding per_block
violation_action: reject_node_registration
test: A47_test_node_identity_binding
references: ["多辖区节点共享白皮书 §3.1", "GIDS增强规范"]
clause A48_WasmPluginSandbox
name: "WASM规则插件沙箱执行强制"
tier: Tactical
clause_index: 1002
description: "辖区规则插件必须以WASM模块形式在沙箱中执行
沙箱必须满足:无主机文件系统/网络访问、
执行时间上限10ms、内存上限64MB
插件哈希必须存储在IPFS并上链验证"
predicate: plugin.execution_env == "WASM_SANDBOX" and
plugin.max_execution_ms <= 10 and
plugin.max_memory_mb <= 64 and
plugin.hash_on_chain == true
obligation: system.enforce_wasm_sandbox_limits per_block
violation_action: terminate_plugin_execution
test: A48_test_wasm_sandbox
references: ["多辖区节点共享白皮书 §3.3", "WASM沙箱安全规范"]
clause A49_CeeSharedCluster
name: "CEE节点跨辖区共享验证"
tier: Tactical
clause_index: 1003
description: "宪法执行引擎CEE节点可配置为同时支持多个辖区的验证逻辑
通过并行调用所有相关辖区插件并汇总结果签发多签名宪法收据CR
CEE节点必须通过GIDS中的负载均衡列表选择防止单点故障"
predicate: cee.supports_multi_jurisdiction == true and
cee.parallel_plugin_execution == true and
cee.registered_in_gids == true
obligation: cee.enable_multi_jurisdiction_verification per_block
violation_action: fallback_to_single_jurisdiction_cee
test: A49_test_cee_shared_cluster
references: ["多辖区节点共享白皮书 §3.6", "CEE集群规范"]
clause A50_JurisdictionDisputeResolution
name: "辖区争议宪法法院裁决"
tier: Tactical
clause_index: 1004
description: "跨辖区节点争议(资源抢占、规则冲突、身份冒充等)必须提交至宪法法院裁决;
宪法法院根据全球细则和辖区插件条款作出最终判决;
判决结果通过链上投票确认后方可执行"
predicate: dispute.resolution_path == "constitutional_court" and
dispute.judgment_on_chain == true and
dispute.chain_vote_confirmed == true
obligation: governance.route_cross_jurisdiction_dispute_to_court per_epoch
violation_action: freeze_disputed_resources
test: A50_test_dispute_resolution
references: ["多辖区节点共享白皮书 §5.3", "宪法法院裁决规范"]
clause A51_CsnpJurisdictionAwareRouting
name: "CSNP辖区感知路由强制"
tier: Tactical
clause_index: 1005
description: "CSNP网络层必须支持辖区感知路由节点发送交易前查询目标地址辖区信息
跨辖区交易选择目标辖区中继节点转发;
协议转换时必须保留原始CR作为证据"
predicate: csnp.jurisdiction_aware_routing == true and
csnp.cross_jurisdiction_relay == true and
csnp.preserves_original_cr == true
obligation: csnp.enforce_jurisdiction_aware_routing per_block
violation_action: reject_non_compliant_routing
test: A51_test_csnp_routing
references: ["多辖区节点共享白皮书 §3.5", "CSNP扩展规范"]
clause A52_SharedStorageDataPrivacy
name: "共享存储敏感数据加密"
tier: Tactical
clause_index: 1006
description: "在物理共享存储环境中敏感数据法律文件哈希、KYC信息、辖区密钥
必须加密存储,仅授权节点可解密;
区块链数据分片存储时必须通过冗余编码保证可用性最低3副本"
predicate: storage.sensitive_data_encrypted == true and
storage.authorized_access_only == true and
storage.redundancy_copies >= 3
obligation: storage.enforce_encryption_and_redundancy per_epoch
violation_action: quarantine_unencrypted_data
test: A52_test_shared_storage_privacy
references: ["多辖区节点共享白皮书 §3.7", "§4 安全与隐私保护"]
// ============================================================
// 测试块
// ============================================================
test A44_test_node_sharing_isolation {
// 物理共享节点必须有逻辑隔离标志
assert node.physical_shared == true implies node.logical_isolated == true
assert node.container_isolated == true
assert node.network_namespace_isolated == true
}
test A45_test_cross_jurisdiction_consensus {
// 跨辖区区块必须包含 jurisdiction_merkle_root
assert block.has_cross_jurisdiction_tx == true implies
block.header.jurisdiction_merkle_root != null
// 跨辖区交易必须有双CR
assert cross_tx.source_cr.valid == true
assert cross_tx.target_cr.valid == true
}
test A46_test_resource_allocation_council {
// 资源分配必须经过委员会投票
assert resource.allocation_proposal.council_approved == true
assert resource.allocation_proposal.vote_ratio >= 6700
}
test A47_test_node_identity_binding {
// 节点DID必须绑定辖区
assert node.did != ""
assert node.jurisdiction != 0
assert node.jurisdiction_proof.signature_valid == true
assert node.plugin_hashes.len() > 0
}
test A48_test_wasm_sandbox {
// WASM沙箱限制验证
assert plugin.execution_env == "WASM_SANDBOX"
assert plugin.max_execution_ms <= 10
assert plugin.max_memory_mb <= 64
}
test A49_test_cee_shared_cluster {
// CEE多辖区支持验证
assert cee.supports_multi_jurisdiction == true
assert cee.gids_registered == true
}
test A50_test_dispute_resolution {
// 争议解决路径验证
assert dispute.resolution_path == "constitutional_court"
}
test A51_test_csnp_routing {
// CSNP辖区感知路由验证
assert csnp.jurisdiction_aware_routing == true
assert csnp.preserves_original_cr == true
}
test A52_test_shared_storage_privacy {
// 共享存储加密验证
assert storage.sensitive_data_encrypted == true
assert storage.redundancy_copies >= 3
}

View File

@ -21,6 +21,7 @@ pub mod plugin;
pub mod dual_receipt; pub mod dual_receipt;
pub mod discovery; pub mod discovery;
pub mod governance; pub mod governance;
pub mod node_sharing_enhanced;
pub use jurisdiction::{Jurisdiction, JurisdictionId, JurisdictionConfig, JurisdictionRegistry}; pub use jurisdiction::{Jurisdiction, JurisdictionId, JurisdictionConfig, JurisdictionRegistry};
pub use isolation::{IsolationLayer, IsolationPolicy, IsolationViolation}; pub use isolation::{IsolationLayer, IsolationPolicy, IsolationViolation};

View File

@ -0,0 +1,798 @@
// nac-multi-jurisdiction/src/node_sharing_enhanced.rs
// Issue #70: 多辖区节点共享增强实现
// 版本: 1.0 | 2026-03-07
// 基于《NAC公链多辖区节点共享方案与技术落地白皮书》v1.0
//
// 本模块实现多辖区节点共享的核心运行时逻辑:
// - 节点共享注册表SharedNodeRegistry
// - 资源配额动态调整DynamicQuotaManager
// - 跨辖区区块生产协调器CrossJurisdictionBlockCoordinator
// - WASM插件运行时WasmPluginRuntime
// - CEE共享集群管理器CeeClusterManager
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
// ============================================================
// 节点共享注册表
// ============================================================
/// 辖区ID16位ISO3166-1 + 子辖区扩展)
pub type JurisdictionId = u16;
/// 节点共享注册表
/// 管理所有物理共享节点的逻辑隔离状态
pub struct SharedNodeRegistry {
/// 节点ID → 共享节点记录
nodes: HashMap<String, SharedNodeRecord>,
/// 辖区ID → 节点ID列表
jurisdiction_nodes: HashMap<JurisdictionId, Vec<String>>,
}
/// 共享节点记录
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SharedNodeRecord {
/// 节点唯一标识
pub node_id: String,
/// 节点DID
pub did: String,
/// 所属辖区
pub jurisdiction: JurisdictionId,
/// 物理主机标识(相同主机的节点共享物理资源)
pub physical_host_id: String,
/// 容器实例ID
pub container_id: String,
/// 网络命名空间ID
pub network_namespace: String,
/// 存储卷ID
pub storage_volume_id: String,
/// 已加载的辖区插件哈希
pub plugin_hashes: Vec<Vec<u8>>,
/// 节点状态
pub status: NodeStatus,
/// 资源使用统计
pub resource_usage: ResourceUsageStats,
/// 注册时间戳
pub registered_at: u64,
/// 最后心跳时间
pub last_heartbeat: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum NodeStatus {
Active,
Inactive,
Suspended, // 因违规暂停
Quarantined, // 因安全问题隔离
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ResourceUsageStats {
pub cpu_usage_millicores: u64,
pub memory_usage_mb: u64,
pub bandwidth_usage_mbps: u64,
pub storage_usage_gb: u64,
pub last_updated: u64,
}
impl SharedNodeRegistry {
pub fn new() -> Self {
SharedNodeRegistry {
nodes: HashMap::new(),
jurisdiction_nodes: HashMap::new(),
}
}
/// 注册共享节点A44/A47验证后调用
pub fn register_node(&mut self, record: SharedNodeRecord) -> Result<(), RegistryError> {
// 验证节点未重复注册
if self.nodes.contains_key(&record.node_id) {
return Err(RegistryError::NodeAlreadyRegistered(record.node_id.clone()));
}
// 验证辖区有效
if record.jurisdiction == 0 {
return Err(RegistryError::InvalidJurisdiction);
}
// 验证容器隔离A44
if record.container_id.is_empty() {
return Err(RegistryError::MissingContainerIsolation);
}
if record.network_namespace.is_empty() {
return Err(RegistryError::MissingNetworkNamespace);
}
// 更新辖区节点索引
self.jurisdiction_nodes
.entry(record.jurisdiction)
.or_insert_with(Vec::new)
.push(record.node_id.clone());
self.nodes.insert(record.node_id.clone(), record);
Ok(())
}
/// 获取同一物理主机上的所有节点(用于资源争用检测)
pub fn get_nodes_on_host(&self, host_id: &str) -> Vec<&SharedNodeRecord> {
self.nodes
.values()
.filter(|n| n.physical_host_id == host_id)
.collect()
}
/// 获取辖区的所有活跃节点
pub fn get_active_nodes_for_jurisdiction(
&self,
jurisdiction: JurisdictionId,
) -> Vec<&SharedNodeRecord> {
self.jurisdiction_nodes
.get(&jurisdiction)
.map(|ids| {
ids.iter()
.filter_map(|id| self.nodes.get(id))
.filter(|n| n.status == NodeStatus::Active)
.collect()
})
.unwrap_or_default()
}
/// 检测同一物理主机上的辖区隔离违规
pub fn detect_isolation_violations(&self, host_id: &str) -> Vec<IsolationViolation> {
let host_nodes = self.get_nodes_on_host(host_id);
let mut violations = Vec::new();
// 检查是否有节点缺少网络命名空间隔离
for node in &host_nodes {
if node.network_namespace.is_empty() {
violations.push(IsolationViolation {
node_id: node.node_id.clone(),
violation_type: ViolationType::MissingNetworkNamespace,
description: format!(
"节点 {} 在物理主机 {} 上缺少网络命名空间隔离",
node.node_id, host_id
),
});
}
}
// 检查是否有多个辖区节点共享同一网络命名空间违反A44
let mut namespace_jurisdictions: HashMap<String, Vec<JurisdictionId>> = HashMap::new();
for node in &host_nodes {
namespace_jurisdictions
.entry(node.network_namespace.clone())
.or_insert_with(Vec::new)
.push(node.jurisdiction);
}
for (namespace, jurisdictions) in &namespace_jurisdictions {
if jurisdictions.len() > 1 {
let unique_jurisdictions: std::collections::HashSet<_> = jurisdictions.iter().collect();
if unique_jurisdictions.len() > 1 {
violations.push(IsolationViolation {
node_id: format!("namespace:{}", namespace),
violation_type: ViolationType::SharedNetworkNamespace,
description: format!(
"网络命名空间 {} 被多个辖区({:?}共享违反A44逻辑隔离要求",
namespace, jurisdictions
),
});
}
}
}
violations
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
}
#[derive(Debug, Clone)]
pub struct IsolationViolation {
pub node_id: String,
pub violation_type: ViolationType,
pub description: String,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ViolationType {
MissingNetworkNamespace,
SharedNetworkNamespace,
MissingStorageIsolation,
ResourceQuotaExceeded,
UnauthorizedPluginLoaded,
}
#[derive(Debug, Clone)]
pub enum RegistryError {
NodeAlreadyRegistered(String),
InvalidJurisdiction,
MissingContainerIsolation,
MissingNetworkNamespace,
}
// ============================================================
// 动态资源配额管理器
// ============================================================
/// 动态资源配额管理器A46
pub struct DynamicQuotaManager {
/// 辖区ID → 当前配额
quotas: HashMap<JurisdictionId, DynamicQuota>,
/// 配额变更历史
change_history: Vec<QuotaChangeRecord>,
/// 总物理资源
total_resources: PhysicalResources,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DynamicQuota {
pub jurisdiction: JurisdictionId,
/// CPU配额毫核
pub cpu_millicores: u64,
/// 内存配额MB
pub memory_mb: u64,
/// 带宽配额Mbps
pub bandwidth_mbps: u64,
/// 存储配额GB
pub storage_gb: u64,
/// 配额生效时间
pub effective_from: u64,
/// 配额来源提案ID
pub proposal_id: u64,
}
#[derive(Debug, Clone)]
pub struct PhysicalResources {
pub total_cpu_millicores: u64,
pub total_memory_mb: u64,
pub total_bandwidth_mbps: u64,
pub total_storage_gb: u64,
}
#[derive(Debug, Clone)]
pub struct QuotaChangeRecord {
pub jurisdiction: JurisdictionId,
pub old_quota: Option<DynamicQuota>,
pub new_quota: DynamicQuota,
pub changed_at: u64,
pub proposal_id: u64,
}
impl DynamicQuotaManager {
pub fn new(total_resources: PhysicalResources) -> Self {
DynamicQuotaManager {
quotas: HashMap::new(),
change_history: Vec::new(),
total_resources,
}
}
/// 应用经委员会投票通过的资源分配提案A46
pub fn apply_allocation_proposal(
&mut self,
proposal_id: u64,
allocations: HashMap<JurisdictionId, DynamicQuota>,
timestamp: u64,
) -> Result<(), QuotaError> {
// 验证总配额不超过物理资源
let total_cpu: u64 = allocations.values().map(|q| q.cpu_millicores).sum();
let total_memory: u64 = allocations.values().map(|q| q.memory_mb).sum();
let total_bandwidth: u64 = allocations.values().map(|q| q.bandwidth_mbps).sum();
let total_storage: u64 = allocations.values().map(|q| q.storage_gb).sum();
if total_cpu > self.total_resources.total_cpu_millicores {
return Err(QuotaError::CpuOverAllocation {
requested: total_cpu,
available: self.total_resources.total_cpu_millicores,
});
}
if total_memory > self.total_resources.total_memory_mb {
return Err(QuotaError::MemoryOverAllocation {
requested: total_memory,
available: self.total_resources.total_memory_mb,
});
}
if total_bandwidth > self.total_resources.total_bandwidth_mbps {
return Err(QuotaError::BandwidthOverAllocation {
requested: total_bandwidth,
available: self.total_resources.total_bandwidth_mbps,
});
}
if total_storage > self.total_resources.total_storage_gb {
return Err(QuotaError::StorageOverAllocation {
requested: total_storage,
available: self.total_resources.total_storage_gb,
});
}
// 应用配额变更
for (jurisdiction, new_quota) in allocations {
let old_quota = self.quotas.remove(&jurisdiction);
self.change_history.push(QuotaChangeRecord {
jurisdiction,
old_quota: old_quota.clone(),
new_quota: new_quota.clone(),
changed_at: timestamp,
proposal_id,
});
self.quotas.insert(jurisdiction, new_quota);
}
Ok(())
}
/// 检查辖区是否超出配额
pub fn check_quota_violation(
&self,
jurisdiction: JurisdictionId,
usage: &ResourceUsageStats,
) -> Vec<String> {
let mut violations = Vec::new();
if let Some(quota) = self.quotas.get(&jurisdiction) {
if usage.cpu_usage_millicores > quota.cpu_millicores {
violations.push(format!(
"辖区 {} CPU使用{}m超出配额{}m",
jurisdiction, usage.cpu_usage_millicores, quota.cpu_millicores
));
}
if usage.memory_usage_mb > quota.memory_mb {
violations.push(format!(
"辖区 {} 内存使用({}MB超出配额{}MB",
jurisdiction, usage.memory_usage_mb, quota.memory_mb
));
}
if usage.bandwidth_usage_mbps > quota.bandwidth_mbps {
violations.push(format!(
"辖区 {} 带宽使用({}Mbps超出配额{}Mbps",
jurisdiction, usage.bandwidth_usage_mbps, quota.bandwidth_mbps
));
}
if usage.storage_usage_gb > quota.storage_gb {
violations.push(format!(
"辖区 {} 存储使用({}GB超出配额{}GB",
jurisdiction, usage.storage_usage_gb, quota.storage_gb
));
}
}
violations
}
}
#[derive(Debug, Clone)]
pub enum QuotaError {
CpuOverAllocation { requested: u64, available: u64 },
MemoryOverAllocation { requested: u64, available: u64 },
BandwidthOverAllocation { requested: u64, available: u64 },
StorageOverAllocation { requested: u64, available: u64 },
}
// ============================================================
// 跨辖区区块生产协调器A45
// ============================================================
/// 跨辖区区块生产协调器
pub struct CrossJurisdictionBlockCoordinator {
/// 待处理的跨辖区交易
pending_cross_txs: Vec<PendingCrossJurisdictionTx>,
/// CEE集群辖区ID → CEE节点列表
cee_cluster: HashMap<JurisdictionId, Vec<CeeNodeInfo>>,
}
#[derive(Debug, Clone)]
pub struct PendingCrossJurisdictionTx {
pub tx_hash: Vec<u8>,
pub source_jurisdiction: JurisdictionId,
pub target_jurisdiction: JurisdictionId,
pub source_cr: Option<ConstitutionalReceiptRef>,
pub target_cr: Option<ConstitutionalReceiptRef>,
pub submitted_at: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConstitutionalReceiptRef {
/// CR哈希SHA3-38448字节
pub cr_hash: Vec<u8>,
/// 签发辖区
pub issuing_jurisdiction: JurisdictionId,
/// 签发CEE节点DID
pub issuing_cee_did: String,
/// 签发时间戳
pub issued_at: u64,
/// CEE签名
pub cee_signature: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct CeeNodeInfo {
pub did: String,
pub endpoint: String,
pub supported_jurisdictions: Vec<JurisdictionId>,
pub current_load: u64,
pub is_available: bool,
}
impl CrossJurisdictionBlockCoordinator {
pub fn new() -> Self {
CrossJurisdictionBlockCoordinator {
pending_cross_txs: Vec::new(),
cee_cluster: HashMap::new(),
}
}
/// 注册CEE节点到集群
pub fn register_cee_node(&mut self, node: CeeNodeInfo) {
for jurisdiction in &node.supported_jurisdictions {
self.cee_cluster
.entry(*jurisdiction)
.or_insert_with(Vec::new)
.push(node.clone());
}
}
/// 为跨辖区交易选择最优CEE节点负载均衡
pub fn select_cee_for_cross_tx(
&self,
source: JurisdictionId,
target: JurisdictionId,
) -> Option<&CeeNodeInfo> {
// 优先选择同时支持源辖区和目标辖区的CEE节点A49
let all_cee: Vec<&CeeNodeInfo> = self
.cee_cluster
.values()
.flatten()
.filter(|n| {
n.is_available
&& n.supported_jurisdictions.contains(&source)
&& n.supported_jurisdictions.contains(&target)
})
.collect();
// 按负载排序,选择负载最低的节点
all_cee.into_iter().min_by_key(|n| n.current_load)
}
/// 构建区块的 jurisdiction_merkle_rootA45
/// 将所有跨辖区交易的双CR哈希构建成默克尔树
pub fn build_jurisdiction_merkle_root(
&self,
cross_tx_receipts: &[(&ConstitutionalReceiptRef, &ConstitutionalReceiptRef)],
) -> Option<Vec<u8>> {
if cross_tx_receipts.is_empty() {
return None;
}
// 将所有CR哈希连接后计算SHA3-384
// 实际实现中应使用标准默克尔树算法
use sha3::{Digest, Sha3_384};
let mut hasher = Sha3_384::new();
for (source_cr, target_cr) in cross_tx_receipts {
hasher.update(&source_cr.cr_hash);
hasher.update(&target_cr.cr_hash);
}
let result = hasher.finalize();
let mut root = vec![0u8; 48];
root.copy_from_slice(&result);
Some(root)
}
/// 验证区块的跨辖区合规性A45
pub fn verify_block_cross_jurisdiction_compliance(
&self,
cross_tx_count: u32,
jurisdiction_merkle_root: Option<Vec<u8>>,
receipts: &[(&ConstitutionalReceiptRef, &ConstitutionalReceiptRef)],
) -> CrossJurisdictionComplianceResult {
let mut violations = Vec::new();
if cross_tx_count > 0 {
// 必须有 jurisdiction_merkle_root
if jurisdiction_merkle_root.is_none() {
violations.push(
"A45: 含跨辖区交易的区块缺少 jurisdiction_merkle_root".to_string(),
);
}
// 每笔跨辖区交易必须有双CR
if receipts.len() != cross_tx_count as usize {
violations.push(format!(
"A45: 跨辖区交易数量({})与双CR数量({})不匹配",
cross_tx_count,
receipts.len()
));
}
// 验证每个CR的签名不为空
for (i, (source_cr, target_cr)) in receipts.iter().enumerate() {
if source_cr.cee_signature.is_empty() {
violations.push(format!("A45: 第{}笔交易源辖区CR缺少CEE签名", i + 1));
}
if target_cr.cee_signature.is_empty() {
violations.push(format!("A45: 第{}笔交易目标辖区CR缺少CEE签名", i + 1));
}
}
}
CrossJurisdictionComplianceResult {
passed: violations.is_empty(),
violations,
}
}
}
#[derive(Debug, Clone)]
pub struct CrossJurisdictionComplianceResult {
pub passed: bool,
pub violations: Vec<String>,
}
// ============================================================
// GIDS增强节点身份辖区绑定A47
// ============================================================
/// GIDS增强注册表支持辖区绑定
pub struct GidsEnhancedRegistry {
/// DID → 节点身份记录
identities: HashMap<String, GidsNodeIdentity>,
/// 辖区ID → DID列表
jurisdiction_index: HashMap<JurisdictionId, Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GidsNodeIdentity {
pub did: String,
pub jurisdiction: JurisdictionId,
pub public_key: [u8; 32],
/// 辖区政府授权的数字签名Ed25519
pub jurisdiction_proof_signature: Vec<u8>,
/// 辖区证明签发机构DID
pub proof_issuer_did: String,
/// 辖区证明过期时间
pub proof_expires_at: u64,
/// 已授权的插件哈希列表
pub authorized_plugin_hashes: Vec<Vec<u8>>,
/// 节点角色
pub node_role: NodeRole,
/// 注册时间
pub registered_at: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum NodeRole {
Validator, // 验证节点
CeeNode, // 宪法执行引擎节点
RelayNode, // 中继节点CSNP
StorageNode, // 存储节点
FullNode, // 全节点
}
impl GidsEnhancedRegistry {
pub fn new() -> Self {
GidsEnhancedRegistry {
identities: HashMap::new(),
jurisdiction_index: HashMap::new(),
}
}
/// 注册节点身份A47验证后调用
pub fn register_identity(
&mut self,
identity: GidsNodeIdentity,
current_timestamp: u64,
) -> Result<(), GidsError> {
// 验证DID格式
if identity.did.is_empty() || !identity.did.starts_with("did:nac:") {
return Err(GidsError::InvalidDid(identity.did.clone()));
}
// 验证辖区
if identity.jurisdiction == 0 {
return Err(GidsError::InvalidJurisdiction);
}
// 验证辖区证明未过期
if identity.proof_expires_at < current_timestamp {
return Err(GidsError::JurisdictionProofExpired);
}
// 验证签名不为空
if identity.jurisdiction_proof_signature.is_empty() {
return Err(GidsError::MissingJurisdictionProof);
}
// 验证至少有一个授权插件
if identity.authorized_plugin_hashes.is_empty() {
return Err(GidsError::NoAuthorizedPlugins);
}
// 更新辖区索引
self.jurisdiction_index
.entry(identity.jurisdiction)
.or_insert_with(Vec::new)
.push(identity.did.clone());
self.identities.insert(identity.did.clone(), identity);
Ok(())
}
/// 验证节点加载的插件哈希是否已授权A47
pub fn verify_plugin_hashes(
&self,
did: &str,
loaded_hashes: &[Vec<u8>],
) -> Result<(), GidsError> {
let identity = self.identities.get(did)
.ok_or_else(|| GidsError::NodeNotFound(did.to_string()))?;
for hash in loaded_hashes {
if !identity.authorized_plugin_hashes.contains(hash) {
return Err(GidsError::UnauthorizedPlugin(hash.clone()));
}
}
Ok(())
}
/// 获取辖区的所有节点DID列表
pub fn get_jurisdiction_nodes(&self, jurisdiction: JurisdictionId) -> Vec<&str> {
self.jurisdiction_index
.get(&jurisdiction)
.map(|dids| dids.iter().map(|s| s.as_str()).collect())
.unwrap_or_default()
}
}
#[derive(Debug, Clone)]
pub enum GidsError {
InvalidDid(String),
InvalidJurisdiction,
JurisdictionProofExpired,
MissingJurisdictionProof,
NoAuthorizedPlugins,
NodeNotFound(String),
UnauthorizedPlugin(Vec<u8>),
}
// ============================================================
// 单元测试
// ============================================================
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_shared_node_registry_register() {
let mut registry = SharedNodeRegistry::new();
let record = SharedNodeRecord {
node_id: "node-001".to_string(),
did: "did:nac:node001".to_string(),
jurisdiction: 784, // UAE
physical_host_id: "host-01".to_string(),
container_id: "container-abc123".to_string(),
network_namespace: "netns-node001".to_string(),
storage_volume_id: "vol-node001".to_string(),
plugin_hashes: vec![vec![0u8; 48]],
status: NodeStatus::Active,
resource_usage: ResourceUsageStats::default(),
registered_at: 1000000,
last_heartbeat: 1000000,
};
assert!(registry.register_node(record).is_ok());
assert_eq!(registry.node_count(), 1);
}
#[test]
fn test_isolation_violation_detection() {
let mut registry = SharedNodeRegistry::new();
// 两个不同辖区的节点共享同一网络命名空间(违规)
let node1 = SharedNodeRecord {
node_id: "node-001".to_string(),
did: "did:nac:node001".to_string(),
jurisdiction: 784, // UAE
physical_host_id: "host-01".to_string(),
container_id: "container-001".to_string(),
network_namespace: "shared-netns".to_string(), // 共享命名空间
storage_volume_id: "vol-001".to_string(),
plugin_hashes: vec![vec![0u8; 48]],
status: NodeStatus::Active,
resource_usage: ResourceUsageStats::default(),
registered_at: 1000000,
last_heartbeat: 1000000,
};
let node2 = SharedNodeRecord {
node_id: "node-002".to_string(),
did: "did:nac:node002".to_string(),
jurisdiction: 156, // China
physical_host_id: "host-01".to_string(),
container_id: "container-002".to_string(),
network_namespace: "shared-netns".to_string(), // 同一命名空间
storage_volume_id: "vol-002".to_string(),
plugin_hashes: vec![vec![1u8; 48]],
status: NodeStatus::Active,
resource_usage: ResourceUsageStats::default(),
registered_at: 1000000,
last_heartbeat: 1000000,
};
registry.register_node(node1).unwrap();
registry.register_node(node2).unwrap();
let violations = registry.detect_isolation_violations("host-01");
assert!(!violations.is_empty());
assert!(violations.iter().any(|v| v.violation_type == ViolationType::SharedNetworkNamespace));
}
#[test]
fn test_dynamic_quota_manager_over_allocation() {
let total = PhysicalResources {
total_cpu_millicores: 16000,
total_memory_mb: 32768,
total_bandwidth_mbps: 1000,
total_storage_gb: 2000,
};
let mut manager = DynamicQuotaManager::new(total);
let mut allocations = HashMap::new();
allocations.insert(784u16, DynamicQuota {
jurisdiction: 784,
cpu_millicores: 10000,
memory_mb: 20000,
bandwidth_mbps: 600,
storage_gb: 1200,
effective_from: 1000000,
proposal_id: 1,
});
allocations.insert(156u16, DynamicQuota {
jurisdiction: 156,
cpu_millicores: 8000, // 总计18000 > 16000超额
memory_mb: 15000,
bandwidth_mbps: 500,
storage_gb: 900,
effective_from: 1000000,
proposal_id: 1,
});
let result = manager.apply_allocation_proposal(1, allocations, 1000000);
assert!(matches!(result, Err(QuotaError::CpuOverAllocation { .. })));
}
#[test]
fn test_gids_enhanced_registry() {
let mut registry = GidsEnhancedRegistry::new();
let identity = GidsNodeIdentity {
did: "did:nac:validator001".to_string(),
jurisdiction: 784,
public_key: [0u8; 32],
jurisdiction_proof_signature: vec![1u8; 64],
proof_issuer_did: "did:nac:uae-adgm-gov".to_string(),
proof_expires_at: u64::MAX,
authorized_plugin_hashes: vec![vec![0u8; 48]],
node_role: NodeRole::Validator,
registered_at: 1000000,
};
assert!(registry.register_identity(identity, 1000000).is_ok());
// 验证已授权插件
assert!(registry.verify_plugin_hashes("did:nac:validator001", &[vec![0u8; 48]]).is_ok());
// 验证未授权插件
assert!(registry.verify_plugin_hashes("did:nac:validator001", &[vec![1u8; 48]]).is_err());
}
#[test]
fn test_cross_jurisdiction_block_coordinator() {
let coordinator = CrossJurisdictionBlockCoordinator::new();
// 无跨辖区交易的区块应通过验证
let result = coordinator.verify_block_cross_jurisdiction_compliance(0, None, &[]);
assert!(result.passed);
// 有跨辖区交易但缺少 jurisdiction_merkle_root 应失败
let result = coordinator.verify_block_cross_jurisdiction_compliance(1, None, &[]);
assert!(!result.passed);
}
}