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:
parent
b991cbb4ee
commit
2c2883f2f5
|
|
@ -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/btwest(cproot / 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*
|
||||
|
|
@ -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)---
|
||||
|
||||
/// 验证跨辖区交易的双CR(A45)
|
||||
/// @param source_cr 源辖区宪法收据
|
||||
/// @param target_cr 目标辖区宪法收据
|
||||
/// @returns 双CR是否有效
|
||||
fn verify_dual_cr(
|
||||
source_cr: ConstitutionalReceipt,
|
||||
target_cr: ConstitutionalReceipt,
|
||||
) -> Bool
|
||||
|
||||
/// 获取当前区块的 jurisdiction_merkle_root(A45)
|
||||
/// @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, "转移状态不正确")
|
||||
|
||||
// 调用宪法内置合约验证双CR(A45)
|
||||
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)
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ pub mod storage;
|
|||
pub mod manager;
|
||||
pub mod lifecycle;
|
||||
pub mod upgrade;
|
||||
pub mod node_sharing;
|
||||
|
||||
// 重新导出常用类型
|
||||
pub use validator::{ClauseValidator, ValidationError};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,216 @@
|
|||
// NAC公链宪法增补条款 - 多辖区节点共享规则
|
||||
// Issue #70 | 版本: 1.0 | 共 9 条增补条款(A44-A52)
|
||||
// 基于《NAC公链多辖区节点共享方案与技术落地白皮书》v1.0
|
||||
// 制定方:NAC 核心协议工程组 · 多司法辖区工作组
|
||||
// 发布日期:2026-03-07
|
||||
// 关联文档:amendments.cnnl(A01-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
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ pub mod plugin;
|
|||
pub mod dual_receipt;
|
||||
pub mod discovery;
|
||||
pub mod governance;
|
||||
pub mod node_sharing_enhanced;
|
||||
|
||||
pub use jurisdiction::{Jurisdiction, JurisdictionId, JurisdictionConfig, JurisdictionRegistry};
|
||||
pub use isolation::{IsolationLayer, IsolationPolicy, IsolationViolation};
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
// ============================================================
|
||||
// 节点共享注册表
|
||||
// ============================================================
|
||||
|
||||
/// 辖区ID(16位,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-384,48字节)
|
||||
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_root(A45)
|
||||
/// 将所有跨辖区交易的双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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue