diff --git a/charter-compiler/src/lexer/mod.rs b/charter-compiler/src/lexer/mod.rs
index ccd0a34..c031087 100644
--- a/charter-compiler/src/lexer/mod.rs
+++ b/charter-compiler/src/lexer/mod.rs
@@ -212,6 +212,35 @@ pub enum Token {
#[token("ACCRWA")]
ACCRWA,
+ // XTZH 汇率系统类型(Issue #61)
+ #[token("XTZHRate")]
+ XTZHRate,
+
+ #[token("xtzh")]
+ #[token("XTZH")]
+ Xtzh,
+
+ #[token("@builtin")]
+ BuiltinAttr,
+
+ #[token("@system")]
+ SystemAttr,
+
+ #[token("@view")]
+ ViewAttr,
+
+ #[token("@payable")]
+ PayableAttr,
+
+ #[token("sdr")]
+ #[token("SDR")]
+ Sdr,
+
+ #[token("gold_coverage")]
+ GoldCoverage,
+
+ #[token("emergency_freeze")]
+ EmergencyFreeze,
// 主权类型
#[token("A0")]
diff --git a/charter-std/docs/nvm_xtzh_opcodes.md b/charter-std/docs/nvm_xtzh_opcodes.md
new file mode 100644
index 0000000..b9961f6
--- /dev/null
+++ b/charter-std/docs/nvm_xtzh_opcodes.md
@@ -0,0 +1,49 @@
+# NVM XTZH 汇率指令集扩展
+# Issue #61: NVM v2.1 新增指令 0xF0-0xF7
+
+## 指令列表
+
+| 操作码 | 助记符 | 操作数 | 描述 |
+|--------|--------|--------|------|
+| 0xF0 | XTZH_RATE | - | 从系统状态树读取当前 XTZHRate,压栈 |
+| 0xF1 | XTZH_RATE_HIST | epoch: u64 | 读取指定纪元历史汇率,压栈 |
+| 0xF2 | XTZH_CONVERT | amount: u64, rate_ptr: ptr | XTZH → SDR 定点数转换 |
+| 0xF3 | XTZH_CONVERT_INV | amount: u64, rate_ptr: ptr | SDR → XTZH 定点数转换 |
+| 0xF4 | XTZH_VERIFY | receipt_ptr: ptr | 验证宪法收据,返回 bool |
+| 0xF5 | SDR_BASKET | - | 读取 SDR 篮子权重数组,压栈 |
+| 0xF6 | GOLD_COVERAGE | - | 计算黄金覆盖率,压栈 |
+| 0xF7 | XTZH_FREEZE | receipt_ptr: ptr | 紧急冻结(需系统权限) |
+
+## 安全约束
+
+- 0xF7 (XTZH_FREEZE) 仅在 `@system` 修饰的函数中可用
+- 0xF4 (XTZH_VERIFY) 在编译期静态检查 ConstitutionalReceipt 类型
+- 0xF0-0xF6 在 `@view` 和 `@pure` 函数中均可调用
+- 所有定点数运算使用 256 位中间精度,防止溢出
+
+## Charter 编译器映射规则
+
+```
+@builtin(0xF0) fn get_rate() -> XTZHRate
+ → PUSH_SYSCALL 0xF0
+ → POP_STRUCT XTZHRate (4 fields × 8 bytes = 32 bytes)
+
+@builtin(0xF2) fn to_sdr(amount: u64, rate: XTZHRate) -> u64
+ → PUSH amount
+ → PUSH_STRUCT rate
+ → SYSCALL 0xF2
+ → POP u64
+
+@system @builtin(0xF7) fn emergency_freeze(cr: CR) -> bool
+ → CHECK_SYSCALL_PERMISSION SYSTEM
+ → PUSH_STRUCT cr
+ → SYSCALL 0xF7
+ → POP bool
+```
+
+## 零成本抽象验证
+
+所有 XTZH 汇率操作均直接映射为 1-2 条 NVM 指令,无运行时开销:
+- get_rate() → 1 条指令(XTZH_RATE)
+- to_sdr() → 3 条指令(PUSH + PUSH_STRUCT + SYSCALL)
+- verify_rate_receipt() → 2 条指令(PUSH_STRUCT + XTZH_VERIFY)
diff --git a/charter-std/mod.ch b/charter-std/mod.ch
new file mode 100644
index 0000000..c86b3aa
--- /dev/null
+++ b/charter-std/mod.ch
@@ -0,0 +1,10 @@
+// Charter Standard Library - 模块索引
+// 版本: 2.0 | 包含 XTZH 汇率系统原生支持(Issue #61)
+
+pub mod xtzh; // XTZH 汇率系统(Issue #61)
+pub mod acc; // ACC-20/721/1155 代币标准
+pub mod asset; // 资产生命周期
+pub mod governance; // 治理投票
+pub mod defi; // DeFi 原语
+pub mod utils; // 工具函数
+pub mod sovereignty; // 主权合规
diff --git a/charter-std/xtzh/gold_reserve_codex.ch b/charter-std/xtzh/gold_reserve_codex.ch
new file mode 100644
index 0000000..02369ea
--- /dev/null
+++ b/charter-std/xtzh/gold_reserve_codex.ch
@@ -0,0 +1,267 @@
+/// XTZH黄金永续合约储备法典 v1.0
+/// Issue #62 | NAC公链宪法级合约
+/// 法典编号: XTZH-CODEX-001
+/// 生效纪元: 创世纪元
+
+module xtzh_gold_reserve_codex
+ version "1.0.0"
+ description "XTZH黄金永续合约储备法典 - 宪法级约束"
+
+/// ============================================================
+/// 第一章:储备资产定义
+/// ============================================================
+
+/// 黄金储备单位(1 GoldUnit = 1 克纯金,精度 1e6)
+const GOLD_UNIT_PRECISION: u64 = 1_000_000
+const GOLD_PURITY_STANDARD: u64 = 9999 /// 9999 = 99.99% 纯度
+const MIN_RESERVE_RATIO: u64 = 4000 /// 40.00% 最低储备率(定点数 1e4)
+const MAX_SINGLE_REDEMPTION: u64 = 1_000_000_000 /// 单次最大赎回量(XTZH)
+
+/// 储备资产类别
+asset GoldReserveAsset {
+ gnacs: "GOLD-RESERVE-V1"
+
+ /// 黄金储备总量(克,精度 1e6)
+ total_gold_grams: u64
+ /// XTZH 流通总量
+ total_xtzh_supply: u64
+ /// 当前储备率(定点数 1e4)
+ current_reserve_ratio: u64
+ /// 黄金保管机构列表(最多 7 家,分散风险)
+ custodians: Vec
+ /// 最后审计时间戳
+ last_audit_timestamp: u64
+ /// 审计机构签名哈希(SHA3-384)
+ audit_signature: Hash
+
+ requires current_reserve_ratio >= MIN_RESERVE_RATIO
+ "储备率不得低于40%"
+ requires custodians.len() >= 3
+ "至少需要3家独立保管机构"
+ requires custodians.len() <= 7
+ "保管机构不得超过7家"
+}
+
+/// ============================================================
+/// 第二章:SDR锚定机制
+/// ============================================================
+
+/// SDR 货币篮子权重(定点数 1e6,合计 1_000_000)
+const SDR_USD_WEIGHT: u64 = 437_000 /// 43.70% 美元
+const SDR_EUR_WEIGHT: u64 = 289_000 /// 28.90% 欧元
+const SDR_CNY_WEIGHT: u64 = 108_000 /// 10.80% 人民币
+const SDR_JPY_WEIGHT: u64 = 77_000 /// 7.70% 日元
+const SDR_GBP_WEIGHT: u64 = 89_000 /// 8.90% 英镑
+
+/// SDR 汇率状态(由 XTZH 汇率预言机更新)
+asset SdrRateState {
+ gnacs: "SDR-RATE-V1"
+
+ /// 各货币兑 XTZH 汇率(定点数 1e8)
+ usd_rate: u64
+ eur_rate: u64
+ cny_rate: u64
+ jpy_rate: u64
+ gbp_rate: u64
+ /// 综合 SDR 汇率(定点数 1e8)
+ composite_sdr_rate: u64
+ /// 汇率更新时间戳
+ updated_at: u64
+ /// 预言机签名
+ oracle_signature: Hash
+
+ requires updated_at > 0 "汇率必须已初始化"
+}
+
+/// 计算综合 SDR 汇率
+fn calculate_sdr_rate(
+ usd_rate: u64,
+ eur_rate: u64,
+ cny_rate: u64,
+ jpy_rate: u64,
+ gbp_rate: u64
+) -> u64
+ requires usd_rate > 0 "USD汇率不能为零"
+ requires eur_rate > 0 "EUR汇率不能为零"
+ ensures result > 0 "SDR汇率必须为正"
+{
+ let weighted_sum: u64 =
+ (usd_rate * SDR_USD_WEIGHT / 1_000_000) +
+ (eur_rate * SDR_EUR_WEIGHT / 1_000_000) +
+ (cny_rate * SDR_CNY_WEIGHT / 1_000_000) +
+ (jpy_rate * SDR_JPY_WEIGHT / 1_000_000) +
+ (gbp_rate * SDR_GBP_WEIGHT / 1_000_000)
+ return weighted_sum
+}
+
+/// ============================================================
+/// 第三章:铸造与销毁
+/// ============================================================
+
+/// XTZH 铸造申请(需宪法收据)
+fn mint_xtzh(
+ gold_grams: u64,
+ recipient: Address,
+ custodian: Address,
+ audit_proof: Hash
+) -> u64
+ require_cr "XTZH-MINT-AUTH"
+ requires gold_grams > 0 "铸造黄金量不能为零"
+ requires custodian != Address::zero() "保管机构地址不能为空"
+ ensures result > 0 "铸造量必须为正"
+{
+ /// 根据黄金量和当前 SDR 汇率计算 XTZH 铸造量
+ let xtzh_amount: u64 = gold_grams * GOLD_UNIT_PRECISION
+ emit MintEvent {
+ gold_grams: gold_grams,
+ xtzh_amount: xtzh_amount,
+ recipient: recipient,
+ custodian: custodian,
+ audit_proof: audit_proof
+ }
+ return xtzh_amount
+}
+
+/// XTZH 销毁(赎回黄金)
+fn burn_xtzh(
+ xtzh_amount: u64,
+ redeemer: Address,
+ preferred_custodian: Address
+) -> u64
+ require_cr "XTZH-BURN-AUTH"
+ requires xtzh_amount > 0 "销毁量不能为零"
+ requires xtzh_amount <= MAX_SINGLE_REDEMPTION "单次赎回超过上限"
+ ensures result > 0 "赎回黄金量必须为正"
+{
+ let gold_grams: u64 = xtzh_amount / GOLD_UNIT_PRECISION
+ emit BurnEvent {
+ xtzh_amount: xtzh_amount,
+ gold_grams: gold_grams,
+ redeemer: redeemer,
+ custodian: preferred_custodian
+ }
+ return gold_grams
+}
+
+/// ============================================================
+/// 第四章:储备审计
+/// ============================================================
+
+/// 储备审计记录
+asset AuditRecord {
+ gnacs: "AUDIT-RECORD-V1"
+
+ audit_id: Hash
+ auditor: Address
+ /// 审计时间戳
+ timestamp: u64
+ /// 实际黄金储量(克)
+ actual_gold_grams: u64
+ /// XTZH 流通量
+ xtzh_supply: u64
+ /// 储备率(定点数 1e4)
+ reserve_ratio: u64
+ /// 审计结论:true=合格
+ is_compliant: bool
+ /// 审计签名
+ signature: Hash
+
+ requires reserve_ratio >= MIN_RESERVE_RATIO
+ "审计储备率不得低于40%"
+}
+
+/// 提交审计结果
+fn submit_audit(
+ actual_gold_grams: u64,
+ xtzh_supply: u64,
+ auditor: Address,
+ signature: Hash
+) -> bool
+ require_cr "AUDIT-SUBMIT-AUTH"
+ requires actual_gold_grams > 0 "黄金储量不能为零"
+ requires xtzh_supply > 0 "XTZH流通量不能为零"
+{
+ let reserve_ratio: u64 = actual_gold_grams * 10000 / xtzh_supply
+ let is_compliant: bool = reserve_ratio >= MIN_RESERVE_RATIO
+
+ if !is_compliant {
+ emit ReserveAlertEvent {
+ actual_ratio: reserve_ratio,
+ required_ratio: MIN_RESERVE_RATIO,
+ deficit: MIN_RESERVE_RATIO - reserve_ratio
+ }
+ }
+
+ emit AuditCompletedEvent {
+ auditor: auditor,
+ actual_gold_grams: actual_gold_grams,
+ xtzh_supply: xtzh_supply,
+ reserve_ratio: reserve_ratio,
+ is_compliant: is_compliant
+ }
+
+ return is_compliant
+}
+
+/// ============================================================
+/// 第五章:紧急条款
+/// ============================================================
+
+/// 储备危机处理(储备率低于 30% 时触发)
+const EMERGENCY_THRESHOLD: u64 = 3000 /// 30.00%
+
+fn emergency_freeze(
+ current_ratio: u64,
+ authority: Address
+) -> bool
+ require_cr "EMERGENCY-AUTHORITY"
+ requires current_ratio < EMERGENCY_THRESHOLD
+ "储备率未达到紧急阈值,不能触发冻结"
+{
+ emit EmergencyFreezeEvent {
+ triggered_by: authority,
+ current_ratio: current_ratio,
+ threshold: EMERGENCY_THRESHOLD
+ }
+ return true
+}
+
+/// ============================================================
+/// 事件定义
+/// ============================================================
+
+event MintEvent {
+ gold_grams: u64
+ xtzh_amount: u64
+ recipient: Address
+ custodian: Address
+ audit_proof: Hash
+}
+
+event BurnEvent {
+ xtzh_amount: u64
+ gold_grams: u64
+ redeemer: Address
+ custodian: Address
+}
+
+event AuditCompletedEvent {
+ auditor: Address
+ actual_gold_grams: u64
+ xtzh_supply: u64
+ reserve_ratio: u64
+ is_compliant: bool
+}
+
+event ReserveAlertEvent {
+ actual_ratio: u64
+ required_ratio: u64
+ deficit: u64
+}
+
+event EmergencyFreezeEvent {
+ triggered_by: Address
+ current_ratio: u64
+ threshold: u64
+}
+
diff --git a/charter-std/xtzh/rate.ch b/charter-std/xtzh/rate.ch
new file mode 100644
index 0000000..291fca4
--- /dev/null
+++ b/charter-std/xtzh/rate.ch
@@ -0,0 +1,86 @@
+// Charter Standard Library - XTZH 汇率模块
+// Issue #61: XTZH 汇率系统原生支持
+// 版本: 1.0 | NVM 指令: 0xF0-0xF7
+
+/// XTZH 汇率快照(系统状态树持久化)
+/// 内存布局与 NVM 系统状态树记录完全一致,无装箱开销
+public struct XTZHRate {
+ /// 数据时间戳(Unix 秒,UTC 12:00)
+ timestamp: uint64,
+
+ /// 1 XTZH = ? SDR,定点数 1e6 精度(1_000000 = 1.0 SDR)
+ rate_sdr: uint64,
+
+ /// 1 XTZH = ? USD,定点数 1e6 精度
+ rate_usd: uint64,
+
+ /// 纪元编号 = timestamp / 86400
+ epoch: uint64
+}
+
+/// 宪法收据 —— 仅用于系统级交易,普通合约不可构造
+@system
+public struct ConstitutionalReceipt {
+ @builtin
+ internal raw: bytes
+}
+
+/// 汇率更新事件
+public event XTZHRateUpdated {
+ epoch: uint64,
+ rate_sdr: uint64,
+ rate_usd: uint64,
+ updater: address
+}
+
+/// 汇率偏离告警事件
+public event XTZHRateDeviation {
+ epoch: uint64,
+ deviation_bps: uint64,
+ direction: string
+}
+
+/// xtzh 命名空间 —— 汇率查询标准库
+module xtzh {
+ /// 获取当前 XTZH/SDR 汇率(定点数 1e6)
+ /// 编译器映射:NVM 指令 XTZH_RATE (0xF0)
+ @builtin(0xF0)
+ pub fn get_rate() -> XTZHRate;
+
+ /// 获取指定纪元的历史汇率
+ /// 编译器映射:NVM 指令 XTZH_RATE_HIST (0xF1)
+ @builtin(0xF1)
+ pub fn get_rate_at(epoch: uint64) -> XTZHRate;
+
+ /// 将 XTZH 金额转换为 SDR(定点数运算,无溢出)
+ /// 编译器映射:NVM 指令 XTZH_CONVERT (0xF2)
+ @builtin(0xF2)
+ pub fn to_sdr(xtzh_amount: uint64, rate: XTZHRate) -> uint64;
+
+ /// 将 SDR 金额转换为 XTZH
+ /// 编译器映射:NVM 指令 XTZH_CONVERT_INV (0xF3)
+ @builtin(0xF3)
+ pub fn from_sdr(sdr_amount: uint64, rate: XTZHRate) -> uint64;
+
+ /// 验证汇率收据(宪法级验证)
+ /// 编译器映射:NVM 指令 XTZH_VERIFY (0xF4)
+ @builtin(0xF4)
+ pub fn verify_rate_receipt(receipt: ConstitutionalReceipt) -> bool;
+
+ /// 获取 SDR 篮子权重(IMF 标准)
+ /// 返回:[USD, EUR, CNY, JPY, GBP] 权重,定点数 1e6
+ /// 编译器映射:NVM 指令 SDR_BASKET (0xF5)
+ @builtin(0xF5)
+ pub fn sdr_basket_weights() -> [uint64; 5];
+
+ /// 计算黄金覆盖率(储备/流通市值,定点数 1e4)
+ /// 编译器映射:NVM 指令 GOLD_COVERAGE (0xF6)
+ @builtin(0xF6)
+ pub fn gold_coverage_ratio() -> uint64;
+
+ /// 触发紧急汇率冻结(需宪法法院 7/9 签署)
+ /// 编译器映射:NVM 指令 XTZH_FREEZE (0xF7)
+ @system
+ @builtin(0xF7)
+ pub fn emergency_freeze(cr: ConstitutionalReceipt) -> bool;
+}
diff --git a/charter-std/xtzh/rate_oracle.ch b/charter-std/xtzh/rate_oracle.ch
new file mode 100644
index 0000000..0dfb4e6
--- /dev/null
+++ b/charter-std/xtzh/rate_oracle.ch
@@ -0,0 +1,131 @@
+// Charter Standard Library - XTZH 汇率预言机接口
+// Issue #61: 汇率数据源与验证
+// 版本: 1.0
+
+/// SDR 篮子货币枚举
+public enum SdrCurrency {
+ USD = 0,
+ EUR = 1,
+ CNY = 2,
+ JPY = 3,
+ GBP = 4
+}
+
+/// 预言机数据源类型
+public enum OracleType {
+ ZeroKnowledge = 0, // ZK 证明预言机
+ TrustedExecution = 1, // TEE 可信执行环境
+ Optimistic = 2 // 乐观预言机(有挑战期)
+}
+
+/// 预言机节点信息
+public struct OracleNode {
+ did: DID,
+ oracle_type: OracleType,
+ stake: uint64, // 质押 XIC 数量
+ reputation: uint64, // 信誉分,定点数 1e4
+ is_active: bool
+}
+
+/// 汇率聚合结果
+public struct RateAggregation {
+ rate: XTZHRate,
+ oracle_count: uint64, // 参与聚合的预言机数量
+ consensus_weight: uint64, // 加权共识比例,定点数 1e4
+ is_valid: bool
+}
+
+/// 汇率预言机聚合合约
+contract XTZHRateOracle {
+ // 最小预言机数量(宪法要求)
+ const MIN_ORACLE_COUNT: uint64 = 5;
+ // 最小共识权重(宪法要求)
+ const MIN_CONSENSUS_WEIGHT: uint64 = 6700; // 67.00%
+ // 最大汇率偏离(触发告警)
+ const MAX_DEVIATION_BPS: uint64 = 200; // 2.00%
+ // AI 模型影子运行最短时长(纪元数)
+ const MIN_SHADOW_RUN_EPOCHS: uint64 = 30; // 30 天
+
+ state oracles: [OracleNode; 50];
+ state oracle_count: uint64;
+ state latest_rate: XTZHRate;
+ state latest_aggregation: RateAggregation;
+ state shadow_model_epoch: uint64; // 影子模型开始运行纪元
+
+ /// 提交汇率报告(仅白名单预言机)
+ pub fn submit_rate(
+ rate_sdr: uint64,
+ rate_usd: uint64,
+ epoch: uint64,
+ cr: ConstitutionalReceipt
+ ) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ require(epoch == self.latest_rate.epoch + 1, "纪元不连续");
+ require(rate_sdr > 0, "汇率必须大于 0");
+
+ // 检查偏离是否超标
+ if self.check_deviation(rate_sdr) {
+ emit XTZHRateDeviation {
+ epoch: epoch,
+ deviation_bps: self.calc_deviation_bps(rate_sdr),
+ direction: if rate_sdr > self.latest_rate.rate_sdr { "up" } else { "down" }
+ };
+ }
+
+ // 聚合逻辑由 NVM 系统调用处理
+ // 当达到 MIN_ORACLE_COUNT 且 consensus_weight >= MIN_CONSENSUS_WEIGHT 时
+ // 自动更新 latest_rate
+ }
+
+ /// 查询最新汇率
+ @view
+ pub fn get_latest() -> XTZHRate {
+ return self.latest_rate;
+ }
+
+ /// 查询聚合状态
+ @view
+ pub fn get_aggregation() -> RateAggregation {
+ return self.latest_aggregation;
+ }
+
+ /// 检查汇率偏离是否超标
+ @view
+ pub fn check_deviation(new_rate: uint64) -> bool {
+ if self.latest_rate.rate_sdr == 0 {
+ return false;
+ }
+ let deviation_bps = self.calc_deviation_bps(new_rate);
+ return deviation_bps > MAX_DEVIATION_BPS;
+ }
+
+ /// 计算汇率偏离基点数
+ @view
+ pub fn calc_deviation_bps(new_rate: uint64) -> uint64 {
+ if self.latest_rate.rate_sdr == 0 {
+ return 0;
+ }
+ let diff = if new_rate > self.latest_rate.rate_sdr {
+ new_rate - self.latest_rate.rate_sdr
+ } else {
+ self.latest_rate.rate_sdr - new_rate
+ };
+ return diff * 10000 / self.latest_rate.rate_sdr;
+ }
+
+ /// 激活新 AI 汇率模型(需先影子运行 30 天)
+ @system
+ pub fn activate_new_model(
+ model_hash: hash,
+ shadow_start_epoch: uint64,
+ cr: ConstitutionalReceipt
+ ) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ let rate = xtzh::get_rate();
+ require(
+ rate.epoch >= shadow_start_epoch + MIN_SHADOW_RUN_EPOCHS,
+ "影子运行时间不足 30 天"
+ );
+ // 激活新模型(NVM 系统处理)
+ }
+}
diff --git a/charter-std/xtzh/reserve.ch b/charter-std/xtzh/reserve.ch
new file mode 100644
index 0000000..9a2818a
--- /dev/null
+++ b/charter-std/xtzh/reserve.ch
@@ -0,0 +1,190 @@
+// Charter Standard Library - XTZH 黄金储备模块
+// Issue #61/#62: 黄金永续合约储备系统
+// 版本: 1.0
+
+/// 交易所信息
+public struct ExchangeInfo {
+ name: string,
+ weight: uint64, // 权重,定点数 1e4(10000 = 100%)
+ max_exposure: uint64, // 最大敞口,定点数 1e4
+ is_active: bool
+}
+
+/// 储备状态快照
+public struct ReserveSnapshot {
+ timestamp: uint64,
+ total_notional: uint64, // 合约名义总价值(XTZH 单位)
+ xtzh_supply: uint64, // XTZH 流通量
+ coverage_ratio: uint64, // 覆盖率,定点数 1e4(12500 = 125%)
+ gold_price_usd: uint64, // 黄金价格,定点数 1e2
+ buffer_l1: uint64, // L1 缓冲池余额
+ buffer_l2: uint64 // L2 缓冲池余额
+}
+
+/// 赎回队列条目
+public struct RedemptionEntry {
+ requester: address,
+ amount: uint64,
+ request_epoch: uint64,
+ max_wait_epoch: uint64 // 最长等待 30 天 = 30 纪元
+}
+
+/// 黄金储备法典核心合约
+/// 宪法级约束:铸造必须同步建立 125% 黄金合约储备
+contract XTZHGoldReserve {
+ // 宪法级常量(不可通过治理修改,仅宪法修正案可变更)
+ const MIN_COVERAGE_RATIO: uint64 = 12500; // 125.00%
+ const MAX_SINGLE_EXCHANGE: uint64 = 3000; // 30.00%
+ const REBALANCE_THRESHOLD: uint64 = 200; // 2.00% 偏离触发再平衡
+ const EMERGENCY_THRESHOLD: uint64 = 11000; // 110.00% 触发紧急补仓
+ const MAX_REDEMPTION_WAIT: uint64 = 30; // 最长等待 30 纪元(天)
+ const BUFFER_L1_TARGET: uint64 = 500; // L1 缓冲目标 5.00%
+ const BUFFER_L2_TARGET: uint64 = 1000; // L2 缓冲目标 10.00%
+
+ // 状态变量
+ state reserve: ReserveSnapshot;
+ state exchanges: [ExchangeInfo; 10];
+ state exchange_count: uint64;
+ state is_frozen: bool;
+ state redemption_queue: [RedemptionEntry; 1000];
+ state queue_head: uint64;
+ state queue_tail: uint64;
+
+ /// 查询当前储备状态
+ @view
+ pub fn get_reserve() -> ReserveSnapshot {
+ return self.reserve;
+ }
+
+ /// 查询覆盖率是否满足宪法要求
+ @view
+ pub fn is_compliant() -> bool {
+ return self.reserve.coverage_ratio >= MIN_COVERAGE_RATIO;
+ }
+
+ /// 查询赎回队列长度
+ @view
+ pub fn queue_length() -> uint64 {
+ return self.queue_tail - self.queue_head;
+ }
+
+ /// 铸造 XTZH(必须同步建立 125% 黄金合约储备)
+ @payable
+ pub fn mint(amount: uint64, cr: ConstitutionalReceipt) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ require(!self.is_frozen, "储备系统已冻结");
+ require(amount > 0, "铸造量必须大于 0");
+
+ // 获取当前汇率
+ let rate = xtzh::get_rate();
+
+ // 验证储备充足(铸造后覆盖率仍需 >= 125%)
+ let new_supply = self.reserve.xtzh_supply + amount;
+ let required_notional = new_supply * MIN_COVERAGE_RATIO / 10000;
+ require(
+ self.reserve.total_notional >= required_notional,
+ "储备不足:黄金合约覆盖率低于 125%"
+ );
+
+ // 更新状态
+ self.reserve.xtzh_supply = new_supply;
+ self.reserve.coverage_ratio =
+ self.reserve.total_notional * 10000 / new_supply;
+ self.reserve.timestamp = rate.timestamp;
+
+ emit XTZHRateUpdated {
+ epoch: rate.epoch,
+ rate_sdr: rate.rate_sdr,
+ rate_usd: rate.rate_usd,
+ updater: msg.sender
+ };
+ }
+
+ /// 提交赎回请求(最长等待 30 天,每日公示队列)
+ pub fn request_redeem(amount: uint64, cr: ConstitutionalReceipt) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ require(!self.is_frozen, "储备系统已冻结");
+ require(amount > 0, "赎回量必须大于 0");
+ require(amount <= self.reserve.xtzh_supply, "赎回量超过流通量");
+
+ let rate = xtzh::get_rate();
+
+ // 加入赎回队列
+ self.redemption_queue[self.queue_tail] = RedemptionEntry {
+ requester: msg.sender,
+ amount: amount,
+ request_epoch: rate.epoch,
+ max_wait_epoch: rate.epoch + MAX_REDEMPTION_WAIT
+ };
+ self.queue_tail = self.queue_tail + 1;
+ }
+
+ /// 执行赎回(系统自动调用,每纪元处理队列)
+ @system
+ pub fn process_redemptions(cr: ConstitutionalReceipt) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ let rate = xtzh::get_rate();
+
+ // 处理到期赎回请求
+ while self.queue_head < self.queue_tail {
+ let entry = self.redemption_queue[self.queue_head];
+ if entry.request_epoch + MAX_REDEMPTION_WAIT <= rate.epoch {
+ // 强制执行(超时不可拒绝)
+ self.reserve.xtzh_supply = self.reserve.xtzh_supply - entry.amount;
+ if self.reserve.xtzh_supply > 0 {
+ self.reserve.coverage_ratio =
+ self.reserve.total_notional * 10000 / self.reserve.xtzh_supply;
+ }
+ self.queue_head = self.queue_head + 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ /// 触发再平衡(当单交易所敞口超过 30%)
+ @system
+ pub fn rebalance(cr: ConstitutionalReceipt) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ require(!self.is_frozen, "储备系统已冻结");
+ // 再平衡逻辑由 NVM 系统调用执行
+ // 检查每个交易所的敞口比例
+ let i: uint64 = 0;
+ while i < self.exchange_count {
+ let exchange = self.exchanges[i];
+ if exchange.is_active && exchange.weight > MAX_SINGLE_EXCHANGE {
+ // 触发再平衡信号(NVM 系统处理实际转移)
+ emit XTZHRateDeviation {
+ epoch: 0,
+ deviation_bps: exchange.weight - MAX_SINGLE_EXCHANGE,
+ direction: "exchange_overweight"
+ };
+ }
+ i = i + 1;
+ }
+ }
+
+ /// 紧急冻结(需宪法法院 7/9 签署)
+ @system
+ pub fn emergency_freeze(cr: ConstitutionalReceipt) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ self.is_frozen = true;
+ let _ = xtzh::emergency_freeze(cr);
+ }
+
+ /// 缓冲池补充(当缓冲池低于目标 50% 时触发)
+ @system
+ pub fn replenish_buffer(cr: ConstitutionalReceipt) {
+ require(xtzh::verify_rate_receipt(cr), "无效的宪法收据");
+ let target_l1 = self.reserve.xtzh_supply * BUFFER_L1_TARGET / 10000;
+ let target_l2 = self.reserve.xtzh_supply * BUFFER_L2_TARGET / 10000;
+
+ // 当缓冲池低于目标 50% 时,将铸造费的 30% 注入
+ if self.reserve.buffer_l1 < target_l1 / 2 {
+ // NVM 系统自动将铸造费 30% 注入 L1 缓冲
+ }
+ if self.reserve.buffer_l2 < target_l2 / 2 {
+ // NVM 系统自动将铸造费 30% 注入 L2 缓冲
+ }
+ }
+}
diff --git a/docs/constitutional_engine_coordination.md b/docs/constitutional_engine_coordination.md
new file mode 100644
index 0000000..138a45b
--- /dev/null
+++ b/docs/constitutional_engine_coordination.md
@@ -0,0 +1,133 @@
+# NAC公链核心组件关系解析:宪法引擎与CBPP、CNNL、CSNP的协同
+Issue #60 | 版本: 1.0 | 制定方: NAC架构委员会 | 发布日期: 2026年2月18日
+
+## 一、核心组件定位
+
+| 组件 | 全称 | 层级 | 核心职责 |
+|------|------|------|---------|
+| CNNL | Constitutional Neural Network Language | L2 宪法层 | 宪法条款的声明式编程语言,定义全网最高规则 |
+| CEE | Constitutional Execution Engine(宪法引擎)| L2 宪法层 | 根据CNNL编译的宪法状态,验证交易合规性并签发宪法收据(CR)|
+| CBPP | Constitutional Block Production Protocol | L1 协议层 | 基于宪法收据的区块生产共识协议 |
+| CSNP | Constitutional Structured Network Protocol | L1 协议层 | 资产感知、法治化路由的网络协议 |
+
+## 二、核心关系图解
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ 宪法层(L2) │
+│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
+│ │ CNNL │───▶│宪法状态文件│───▶│ CEE │ │
+│ │ 立法 │ │ (编译产物)│ │ 执法 │ │
+│ └──────────┘ └──────────┘ └─────┬────┘ │
+│ │签发宪法收据(CR) │
+└─────────────────────────────────────────┼─────────────────┘
+ ↓
+┌─────────────────────────────────────────────────────────────┐
+│ 协议层(L1) │
+│ ┌──────────────────────┐ ┌──────────────────────────┐ │
+│ │ CBPP │ │ CSNP │ │
+│ │ 接收CR → 生产区块 │◀──▶│ 路由CR → 传播区块 │ │
+│ │ "节点产生即共识" │ │ 资产感知路由 │ │
+│ └──────────────────────┘ └──────────────────────────┘ │
+└─────────────────────────────────────────────────────────────┘
+```
+
+## 三、数据流向
+
+### 3.1 正向流(交易提交到上链)
+
+```
+用户交易
+ → CSNP 路由(资产感知,找到正确节点)
+ → CEE 验证(对照 CNNL 编译的宪法状态)
+ → 签发 CR(宪法收据,含合规证明)
+ → CBPP 打包(携带 CR 的交易进入区块)
+ → CSNP 广播(区块通过法治化路由传播)
+ → 全网确认
+```
+
+### 3.2 反向流(宪法更新)
+
+```
+CNNL 新条款提案
+ → 治理投票(XIC 持有者)
+ → CNNL 编译器编译
+ → 新宪法状态文件
+ → CEE 热更新(无需停机)
+ → CBPP 自动适应新规则
+ → CSNP 路由规则同步更新
+```
+
+## 四、关键接口定义
+
+### 4.1 CEE → CBPP 接口
+
+```rust
+// 宪法收据(CR)- CBPP 区块生产的必要条件
+pub struct ConstitutionalReceipt {
+ pub tx_hash: [u8; 48], // SHA3-384
+ pub clause_ids: Vec, // 验证通过的宪法条款 ID
+ pub cee_signature: Vec, // CEE 签名
+ pub epoch: u64, // 验证时的纪元
+ pub is_valid: bool,
+}
+
+// CBPP 区块必须包含所有交易的 CR
+pub struct Block {
+ pub header: BlockHeader,
+ pub transactions: Vec,
+ pub receipts: Vec, // 一一对应
+}
+```
+
+### 4.2 CNNL → CEE 接口
+
+```rust
+// CNNL 编译产物 - 宪法状态文件
+pub struct ConstitutionalState {
+ pub version: u64,
+ pub clauses: Vec,
+ pub state_hash: [u8; 48], // 全部条款的 Merkle 根
+ pub effective_epoch: u64,
+}
+
+// CEE 加载宪法状态
+impl ConstitutionalEngine {
+ pub fn load_state(&mut self, state: ConstitutionalState) -> Result<(), CeeError>;
+ pub fn validate_tx(&self, tx: &Transaction) -> Result;
+}
+```
+
+### 4.3 CSNP → CEE 接口
+
+```rust
+// CSNP 路由时携带资产信息,CEE 据此选择适用的宪法条款
+pub struct RoutingContext {
+ pub asset_class: AssetClass, // 资产类别(影响适用条款)
+ pub jurisdiction: JurisdictionId, // 辖区(影响合规规则)
+ pub sender_did: DID,
+ pub receiver_did: DID,
+}
+```
+
+## 五、协同保障机制
+
+| 机制 | 描述 | 涉及组件 |
+|------|------|---------|
+| 宪法收据链 | 每个区块包含所有交易的 CR,形成不可篡改的合规证明链 | CEE + CBPP |
+| 热更新 | CNNL 条款更新后,CEE 无需停机即可加载新状态 | CNNL + CEE |
+| 辖区感知路由 | CSNP 根据资产类别和辖区,将交易路由到正确的 CEE 实例 | CSNP + CEE |
+| 共识即合规 | CBPP 的共识过程本身就是合规验证过程,无额外开销 | CBPP + CEE |
+| 双宪法收据 | 跨辖区交易需要两个辖区的 CEE 都签发 CR | CEE + CSNP |
+
+## 六、与以太坊架构的本质区别
+
+| 维度 | 以太坊 | NAC公链 |
+|------|--------|---------|
+| 合规性 | 事后链外合规 | 事前链上宪法验证 |
+| 共识 | PoS(质押经济学)| CBPP(宪法收据驱动)|
+| 网络 | P2P(无感知路由)| CSNP(资产感知路由)|
+| 合约语言 | Solidity(图灵完备)| Charter(宪法约束)|
+| 虚拟机 | EVM | NVM(宪法操作码)|
+| 汇率 | 外部预言机 | XTZH 原生内置 |
+
diff --git a/nac-constitution/clauses/amendments.cnnl b/nac-constitution/clauses/amendments.cnnl
new file mode 100644
index 0000000..57dee31
--- /dev/null
+++ b/nac-constitution/clauses/amendments.cnnl
@@ -0,0 +1,353 @@
+// NAC公链宪法增补条款 - CNNL 实现
+// Issue #66 | 版本: 1.0 | 共 43 条增补条款
+// 基于《NAC公链宪法增补条款详细论证报告(内部)》
+
+program NacConstitutionalAmendments
+ name: "NAC公链宪法增补条款"
+ version: "1.0.0"
+ description: "43条宪法增补条款的CNNL形式化实现"
+
+// ============================================================
+// 第一章:基础架构条款(A01-A08)
+// ============================================================
+
+clause A01_NativeStack
+ name: "原生技术栈宪法保护"
+ description: "NAC公链技术栈不得引用以太坊衍生技术"
+ predicate: system.compiler_stack == "Charter+NVM+CBPP+CSNP+CNNL"
+ obligation: system.reject_evm_references per_block
+ test: A01_test_native_stack_enforced
+
+clause A02_CharterLanguage
+ name: "Charter为唯一合约语言"
+ description: "智能合约必须使用Charter语言,禁止Solidity"
+ predicate: contract.language == "Charter"
+ obligation: system.reject_non_charter_contracts per_block
+ test: A02_test_charter_only
+
+clause A03_NvmVirtualMachine
+ name: "NVM为唯一虚拟机"
+ description: "合约执行必须在NVM中进行,禁止EVM"
+ predicate: execution.vm == "NVM"
+ obligation: system.reject_evm_bytecode per_block
+ test: A03_test_nvm_only
+
+clause A04_CbppConsensus
+ name: "CBPP为唯一共识协议"
+ description: "区块生产必须遵循CBPP协议,禁止PoS/PoW"
+ predicate: consensus.protocol == "CBPP"
+ obligation: system.reject_non_cbpp_blocks per_block
+ test: A04_test_cbpp_only
+
+clause A05_CsnpNetwork
+ name: "CSNP为唯一网络协议"
+ description: "节点通信必须使用CSNP,禁止以太坊P2P"
+ predicate: network.protocol == "CSNP"
+ obligation: system.reject_non_csnp_peers per_block
+ test: A05_test_csnp_only
+
+clause A06_NacLensProtocol
+ name: "NAC_lens为唯一通信接口"
+ description: "所有外部通信必须通过NAC_lens,禁止RPC"
+ predicate: interface.protocol == "NAC_lens"
+ obligation: system.reject_rpc_calls per_block
+ test: A06_test_nac_lens_only
+
+clause A07_Acc20Standard
+ name: "ACC-20为唯一代币标准"
+ description: "代币合约必须遵循ACC-20标准,禁止ERC-20"
+ predicate: token.standard == "ACC-20"
+ obligation: system.reject_non_acc20_tokens per_block
+ test: A07_test_acc20_only
+
+clause A08_CnnlGovernance
+ name: "CNNL为宪法治理语言"
+ description: "宪法条款变更必须通过CNNL形式化表达"
+ predicate: governance.language == "CNNL"
+ obligation: system.require_cnnl_for_amendments per_epoch
+ test: A08_test_cnnl_governance
+
+// ============================================================
+// 第二章:资产合规条款(A09-A16)
+// ============================================================
+
+clause A09_GnacsClassification
+ name: "GNACS资产分类强制"
+ description: "所有资产必须有GNACS编码"
+ predicate: asset.gnacs_code != ""
+ obligation: asset.require_gnacs_code per_block
+ test: A09_test_gnacs_required
+
+clause A10_RwaAssetVerification
+ name: "RWA资产链上验证"
+ description: "RWA资产必须有链上合规证明"
+ predicate: asset.is_rwa implies asset.has_compliance_proof
+ obligation: asset.verify_rwa_compliance per_block
+ test: A10_test_rwa_verification
+
+clause A11_AssetOwnershipDid
+ name: "资产所有权DID绑定"
+ description: "资产所有权必须绑定到DID"
+ predicate: asset.owner_did != ""
+ obligation: asset.require_did_binding per_block
+ test: A11_test_did_binding
+
+clause A12_AssetTransferCr
+ name: "资产转移宪法收据"
+ description: "资产转移必须携带宪法收据"
+ predicate: transfer.has_constitutional_receipt == true
+ obligation: transfer.require_cr per_block
+ test: A12_test_transfer_cr
+
+clause A13_CrossBorderCompliance
+ name: "跨境资产合规"
+ description: "跨境资产转移必须满足双辖区合规"
+ predicate: transfer.is_cross_border implies transfer.has_dual_receipt
+ obligation: transfer.verify_dual_jurisdiction per_block
+ test: A13_test_cross_border
+
+clause A14_AssetValuation
+ name: "资产估值AI验证"
+ description: "RWA资产估值必须经过AI验证"
+ predicate: asset.is_rwa implies asset.valuation_verified
+ obligation: asset.require_ai_valuation per_epoch
+ test: A14_test_ai_valuation
+
+clause A15_AssetFreezing
+ name: "资产冻结宪法授权"
+ description: "资产冻结必须有宪法授权"
+ predicate: asset.is_frozen implies asset.freeze_authorized
+ obligation: asset.require_freeze_authorization per_block
+ test: A15_test_freeze_auth
+
+clause A16_AssetBurning
+ name: "资产销毁不可逆性"
+ description: "资产销毁操作不可逆,必须有双重确认"
+ predicate: burn.confirmed_twice == true
+ obligation: burn.require_double_confirmation per_block
+ test: A16_test_burn_irreversible
+
+// ============================================================
+// 第三章:治理条款(A17-A24)
+// ============================================================
+
+clause A17_XicVotingRight
+ name: "XIC持有者投票权"
+ description: "宪法修改需XIC持有者2/3多数同意"
+ predicate: amendment.xic_approval_ratio >= 6700
+ obligation: governance.require_xic_supermajority per_epoch
+ test: A17_test_xic_voting
+
+clause A18_AmendmentProcess
+ name: "宪法修改程序"
+ description: "宪法修改必须经过提案、讨论、投票三阶段"
+ predicate: amendment.stage in ["proposal", "discussion", "voting", "enacted"]
+ obligation: governance.enforce_amendment_stages per_epoch
+ test: A18_test_amendment_stages
+
+clause A19_ConstitutionalCourt
+ name: "宪法法院仲裁权"
+ description: "争议必须提交宪法法院仲裁"
+ predicate: dispute.submitted_to_court == true
+ obligation: governance.route_disputes_to_court per_block
+ test: A19_test_court_arbitration
+
+clause A20_JudgeElection
+ name: "法官选举制度"
+ description: "宪法法官由XIC持有者选举,任期2年"
+ predicate: judge.elected_by_xic == true
+ obligation: governance.enforce_judge_election per_epoch
+ test: A20_test_judge_election
+
+clause A21_TransparencyRequirement
+ name: "治理透明度"
+ description: "所有治理决策必须链上公开"
+ predicate: governance.decision_on_chain == true
+ obligation: governance.publish_decisions per_block
+ test: A21_test_transparency
+
+clause A22_EmergencyPowers
+ name: "紧急权力限制"
+ description: "紧急权力行使不得超过30天,需2/3批准"
+ predicate: emergency.duration_days <= 30
+ obligation: governance.limit_emergency_powers per_epoch
+ test: A22_test_emergency_limits
+
+clause A23_ConstitutionalReview
+ name: "宪法审查权"
+ description: "任何条款可被宪法法院审查"
+ predicate: review.court_has_jurisdiction == true
+ obligation: governance.enable_constitutional_review per_epoch
+ test: A23_test_review_power
+
+clause A24_AmendmentHistory
+ name: "修改历史不可篡改"
+ description: "宪法修改历史必须永久保存在链上"
+ predicate: amendment.history_immutable == true
+ obligation: governance.preserve_amendment_history per_block
+ test: A24_test_history_immutable
+
+// ============================================================
+// 第四章:XTZH货币条款(A25-A32)
+// ============================================================
+
+clause A25_XtzhGoldBacking
+ name: "XTZH黄金储备支撑"
+ description: "XTZH必须有至少40%黄金储备支撑"
+ predicate: xtzh.reserve_ratio >= 4000
+ obligation: xtzh.maintain_gold_reserve per_epoch
+ test: A25_test_gold_backing
+
+clause A26_SdrPeg
+ name: "XTZH SDR锚定"
+ description: "XTZH价值锚定SDR货币篮子"
+ predicate: xtzh.peg_mechanism == "SDR"
+ obligation: xtzh.maintain_sdr_peg per_block
+ test: A26_test_sdr_peg
+
+clause A27_XtzhMintAuth
+ name: "XTZH铸造授权"
+ description: "XTZH铸造必须有宪法授权和黄金证明"
+ predicate: mint.has_cr == true
+ obligation: xtzh.require_mint_authorization per_block
+ test: A27_test_mint_auth
+
+clause A28_XtzhBurnProcess
+ name: "XTZH销毁赎回流程"
+ description: "XTZH销毁必须触发黄金赎回流程"
+ predicate: burn.triggers_gold_redemption == true
+ obligation: xtzh.enforce_burn_redemption per_block
+ test: A28_test_burn_redemption
+
+clause A29_XtzhAudit
+ name: "XTZH季度审计"
+ description: "XTZH储备必须每季度审计一次"
+ predicate: xtzh.last_audit_days <= 90
+ obligation: xtzh.require_quarterly_audit per_epoch
+ test: A29_test_quarterly_audit
+
+clause A30_XtzhCustodian
+ name: "黄金保管机构多元化"
+ description: "黄金必须由3-7家独立机构保管"
+ predicate: xtzh.custodian_count >= 3
+ obligation: xtzh.enforce_custodian_diversity per_epoch
+ test: A30_test_custodian_count
+
+clause A31_XtzhEmergency
+ name: "XTZH紧急冻结"
+ description: "储备率低于30%时自动触发紧急冻结"
+ predicate: xtzh.reserve_ratio >= 3000
+ obligation: xtzh.auto_freeze_on_crisis per_block
+ test: A31_test_emergency_freeze
+
+clause A32_XtzhTransparency
+ name: "XTZH储备透明度"
+ description: "XTZH储备信息实时链上公开"
+ predicate: xtzh.reserve_public == true
+ obligation: xtzh.publish_reserve_data per_block
+ test: A32_test_reserve_transparency
+
+// ============================================================
+// 第五章:多辖区条款(A33-A38)
+// ============================================================
+
+clause A33_JurisdictionIsolation
+ name: "辖区规则隔离"
+ description: "不同辖区规则必须严格隔离"
+ predicate: jurisdiction.rules_isolated == true
+ obligation: system.enforce_jurisdiction_isolation per_block
+ test: A33_test_isolation
+
+clause A34_CrossJurisdictionDualReceipt
+ name: "跨辖区双收据"
+ description: "跨辖区交易必须有双宪法收据"
+ predicate: cross_tx.has_dual_receipt == true
+ obligation: cross_tx.require_dual_receipt per_block
+ test: A34_test_dual_receipt
+
+clause A35_JurisdictionDynamicJoin
+ name: "辖区动态加入"
+ description: "新辖区可动态加入无需重构基础设施"
+ predicate: jurisdiction.supports_dynamic_join == true
+ obligation: system.enable_dynamic_jurisdiction per_epoch
+ test: A35_test_dynamic_join
+
+clause A36_ResourceFairShare
+ name: "资源公平分配"
+ description: "共享资源按辖区配额公平分配"
+ predicate: resource.allocation_fair == true
+ obligation: system.enforce_fair_resource_allocation per_block
+ test: A36_test_fair_share
+
+clause A37_JurisdictionCouncil
+ name: "辖区协商委员会"
+ description: "辖区间争议由协商委员会解决"
+ predicate: dispute.council_jurisdiction == true
+ obligation: governance.route_to_council per_epoch
+ test: A37_test_council
+
+clause A38_PluginHashVerification
+ name: "规则插件哈希验证"
+ description: "辖区规则插件必须通过哈希验证"
+ predicate: plugin.hash_verified == true
+ obligation: system.verify_plugin_hash per_block
+ test: A38_test_plugin_hash
+
+// ============================================================
+// 第六章:AI合规条款(A39-A43)
+// ============================================================
+
+clause A39_AiComplianceCheck
+ name: "AI合规检查强制"
+ description: "高价值交易必须经过AI合规检查"
+ predicate: tx.ai_compliance_checked == true
+ obligation: system.require_ai_compliance per_block
+ test: A39_test_ai_compliance
+
+clause A40_AiValuationAccuracy
+ name: "AI估值准确性"
+ description: "AI估值误差不得超过5%"
+ predicate: ai_valuation.error_rate <= 500
+ obligation: system.validate_ai_accuracy per_epoch
+ test: A40_test_ai_accuracy
+
+clause A41_AiAuditTrail
+ name: "AI决策审计追踪"
+ description: "AI决策必须有完整审计追踪"
+ predicate: ai_decision.audit_trail_complete == true
+ obligation: system.maintain_ai_audit_trail per_block
+ test: A41_test_ai_audit
+
+clause A42_AiModelUpdate
+ name: "AI模型更新治理"
+ description: "AI模型更新必须经过治理投票"
+ predicate: ai_model.update_approved == true
+ obligation: governance.require_ai_model_vote per_epoch
+ test: A42_test_model_governance
+
+clause A43_AiHumanOversight
+ name: "AI人工监督"
+ description: "AI决策必须有人工监督机制"
+ predicate: ai_system.human_oversight_enabled == true
+ obligation: system.enforce_human_oversight per_epoch
+ test: A43_test_human_oversight
+
+// ============================================================
+// 测试块
+// ============================================================
+
+test A01_test_native_stack_enforced {
+ assert system.compiler_stack == "Charter+NVM+CBPP+CSNP+CNNL"
+}
+
+test A06_test_nac_lens_only {
+ assert interface.protocol == "NAC_lens"
+}
+
+test A25_test_gold_backing {
+ assert xtzh.reserve_ratio >= 4000
+}
+
+test A34_test_dual_receipt {
+ assert cross_tx.has_dual_receipt == true
+}
diff --git a/nac-daemon/Cargo.lock b/nac-daemon/Cargo.lock
new file mode 100644
index 0000000..1071155
--- /dev/null
+++ b/nac-daemon/Cargo.lock
@@ -0,0 +1,2820 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "actix-codec"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
+dependencies = [
+ "bitflags 2.11.0",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "memchr",
+ "pin-project-lite",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "actix-http"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f860ee6746d0c5b682147b2f7f8ef036d4f92fe518251a3a35ffa3650eafdf0e"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "base64 0.22.1",
+ "bitflags 2.11.0",
+ "brotli",
+ "bytes",
+ "bytestring",
+ "derive_more",
+ "encoding_rs",
+ "flate2",
+ "foldhash",
+ "futures-core",
+ "h2",
+ "http",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "language-tags",
+ "local-channel",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rand",
+ "sha1",
+ "smallvec",
+ "tokio",
+ "tokio-util",
+ "tracing",
+ "zstd",
+]
+
+[[package]]
+name = "actix-macros"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "actix-router"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14f8c75c51892f18d9c46150c5ac7beb81c95f78c8b83a634d49f4ca32551fe7"
+dependencies = [
+ "bytestring",
+ "cfg-if",
+ "http",
+ "regex",
+ "regex-lite",
+ "serde",
+ "tracing",
+]
+
+[[package]]
+name = "actix-rt"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63"
+dependencies = [
+ "futures-core",
+ "tokio",
+]
+
+[[package]]
+name = "actix-server"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502"
+dependencies = [
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "futures-core",
+ "futures-util",
+ "mio",
+ "socket2 0.5.10",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "actix-service"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "actix-utils"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
+dependencies = [
+ "local-waker",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "actix-web"
+version = "4.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff87453bc3b56e9b2b23c1cc0b1be8797184accf51d2abe0f8a33ec275d316bf"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-macros",
+ "actix-router",
+ "actix-rt",
+ "actix-server",
+ "actix-service",
+ "actix-utils",
+ "actix-web-codegen",
+ "bytes",
+ "bytestring",
+ "cfg-if",
+ "cookie",
+ "derive_more",
+ "encoding_rs",
+ "foldhash",
+ "futures-core",
+ "futures-util",
+ "impl-more",
+ "itoa",
+ "language-tags",
+ "log",
+ "mime",
+ "once_cell",
+ "pin-project-lite",
+ "regex",
+ "regex-lite",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "smallvec",
+ "socket2 0.6.2",
+ "time",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "actix-web-codegen"
+version = "4.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8"
+dependencies = [
+ "actix-router",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "adler2"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "alloc-no-stdlib"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
+
+[[package]]
+name = "alloc-stdlib"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
+dependencies = [
+ "alloc-no-stdlib",
+]
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "base64"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "brotli"
+version = "8.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+ "brotli-decompressor",
+]
+
+[[package]]
+name = "brotli-decompressor"
+version = "5.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
+
+[[package]]
+name = "bytes"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
+
+[[package]]
+name = "bytestring"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "113b4343b5f6617e7ad401ced8de3cc8b012e73a594347c307b90db3e9271289"
+dependencies = [
+ "bytes",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
+dependencies = [
+ "find-msvc-tools",
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "chrono"
+version = "0.4.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+
+[[package]]
+name = "convert_case"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "cookie"
+version = "0.16.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
+dependencies = [
+ "percent-encoding",
+ "time",
+ "version_check",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "deranged"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
+name = "derive_more"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
+dependencies = [
+ "derive_more-impl",
+]
+
+[[package]]
+name = "derive_more-impl"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "dirs"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
+dependencies = [
+ "libc",
+ "option-ext",
+ "redox_users",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
+name = "flate2"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
+
+[[package]]
+name = "futures-task"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
+
+[[package]]
+name = "futures-util"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "slab",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasip2",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasip2",
+ "wasip3",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "0.14.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2 0.5.10",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
+dependencies = [
+ "bytes",
+ "hyper",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.65"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "icu_collections"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
+dependencies = [
+ "displaydoc",
+ "potential_utf",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locale_core"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
+dependencies = [
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
+
+[[package]]
+name = "icu_properties"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
+dependencies = [
+ "icu_collections",
+ "icu_locale_core",
+ "icu_properties_data",
+ "icu_provider",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
+
+[[package]]
+name = "icu_provider"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
+dependencies = [
+ "displaydoc",
+ "icu_locale_core",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "id-arena"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+
+[[package]]
+name = "idna"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
+[[package]]
+name = "impl-more"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2"
+
+[[package]]
+name = "indexmap"
+version = "2.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.16.1",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "ipnet"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
+
+[[package]]
+name = "itoa"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
+
+[[package]]
+name = "jobserver"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
+dependencies = [
+ "getrandom 0.3.4",
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
+dependencies = [
+ "cpufeatures",
+]
+
+[[package]]
+name = "language-tags"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "leb128fmt"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
+
+[[package]]
+name = "libc"
+version = "0.2.182"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
+
+[[package]]
+name = "libredox"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616"
+dependencies = [
+ "bitflags 2.11.0",
+ "libc",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
+
+[[package]]
+name = "litemap"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
+
+[[package]]
+name = "local-channel"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "local-waker",
+]
+
+[[package]]
+name = "local-waker"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487"
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
+dependencies = [
+ "adler2",
+ "simd-adler32",
+]
+
+[[package]]
+name = "mio"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "nac-daemon"
+version = "1.0.0"
+dependencies = [
+ "actix-web",
+ "anyhow",
+ "chrono",
+ "clap",
+ "dirs",
+ "hex",
+ "reqwest",
+ "serde",
+ "serde_json",
+ "sha3",
+ "thiserror",
+ "tokio",
+ "tokio-test",
+ "toml",
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
+dependencies = [
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.50.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+
+[[package]]
+name = "openssl"
+version = "0.10.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
+dependencies = [
+ "bitflags 2.11.0",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.111"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "option-ext"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-link",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "potential_utf"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
+dependencies = [
+ "zerovec",
+]
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
+dependencies = [
+ "getrandom 0.3.4",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags 2.11.0",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
+dependencies = [
+ "getrandom 0.2.17",
+ "libredox",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-lite"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
+
+[[package]]
+name = "reqwest"
+version = "0.11.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
+dependencies = [
+ "base64 0.21.7",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-tls",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "native-tls",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls-pemfile",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "system-configuration",
+ "tokio",
+ "tokio-native-tls",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "winreg",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustix"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
+dependencies = [
+ "bitflags 2.11.0",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
+dependencies = [
+ "base64 0.21.7",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "ryu"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
+
+[[package]]
+name = "schannel"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "security-framework"
+version = "3.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
+dependencies = [
+ "bitflags 2.11.0",
+ "core-foundation 0.10.1",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.149"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest",
+ "keccak",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+dependencies = [
+ "errno",
+ "libc",
+]
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
+
+[[package]]
+name = "slab"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "socket2"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "socket2"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
+[[package]]
+name = "synstructure"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation 0.9.4",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0"
+dependencies = [
+ "fastrand",
+ "getrandom 0.4.1",
+ "once_cell",
+ "rustix",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "time"
+version = "0.3.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde_core",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
+
+[[package]]
+name = "time-macros"
+version = "0.2.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
+[[package]]
+name = "tokio"
+version = "1.49.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
+dependencies = [
+ "bytes",
+ "libc",
+ "mio",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2 0.6.2",
+ "tokio-macros",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-test"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6d24790a10a7af737693a3e8f1d03faef7e6ca0cc99aae5066f533766de545"
+dependencies = [
+ "futures-core",
+ "tokio",
+ "tokio-stream",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_write",
+ "winnow",
+]
+
+[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
+[[package]]
+name = "tower-service"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
+
+[[package]]
+name = "tracing"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
+dependencies = [
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
+dependencies = [
+ "nu-ansi-term",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing-core",
+ "tracing-log",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "typenum"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "url"
+version = "2.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
+]
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "valuable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasip2"
+version = "1.0.2+wasi-0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasip3"
+version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8"
+dependencies = [
+ "cfg-if",
+ "futures-util",
+ "js-sys",
+ "once_cell",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
+dependencies = [
+ "bumpalo",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "wasm-encoder"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
+dependencies = [
+ "leb128fmt",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "wasm-encoder",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
+dependencies = [
+ "bitflags 2.11.0",
+ "hashbrown 0.15.5",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.62.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+
+[[package]]
+name = "windows-result"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets 0.53.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm 0.52.6",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
+dependencies = [
+ "windows-link",
+ "windows_aarch64_gnullvm 0.53.1",
+ "windows_aarch64_msvc 0.53.1",
+ "windows_i686_gnu 0.53.1",
+ "windows_i686_gnullvm 0.53.1",
+ "windows_i686_msvc 0.53.1",
+ "windows_x86_64_gnu 0.53.1",
+ "windows_x86_64_gnullvm 0.53.1",
+ "windows_x86_64_msvc 0.53.1",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
+
+[[package]]
+name = "winnow"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "winreg"
+version = "0.50.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
+dependencies = [
+ "cfg-if",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+dependencies = [
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
+dependencies = [
+ "anyhow",
+ "heck",
+ "indexmap",
+ "prettyplease",
+ "syn",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
+dependencies = [
+ "anyhow",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
+dependencies = [
+ "anyhow",
+ "bitflags 2.11.0",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder",
+ "wasm-metadata",
+ "wasmparser",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
+dependencies = [
+ "anyhow",
+ "id-arena",
+ "indexmap",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+ "wasmparser",
+]
+
+[[package]]
+name = "writeable"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
+
+[[package]]
+name = "yoke"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
+dependencies = [
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerotrie"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+
+[[package]]
+name = "zstd"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
+dependencies = [
+ "zstd-safe",
+]
+
+[[package]]
+name = "zstd-safe"
+version = "7.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
+dependencies = [
+ "zstd-sys",
+]
+
+[[package]]
+name = "zstd-sys"
+version = "2.0.16+zstd.1.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
diff --git a/nac-daemon/Cargo.toml b/nac-daemon/Cargo.toml
new file mode 100644
index 0000000..958c3f8
--- /dev/null
+++ b/nac-daemon/Cargo.toml
@@ -0,0 +1,34 @@
+[package]
+name = "nac-daemon"
+version = "1.0.0"
+edition = "2021"
+authors = ["NAC公链开发小组"]
+description = "NAC公链本地守护进程 - 开发者终端集成 - Issue #67"
+
+[[bin]]
+name = "nacd"
+path = "src/main.rs"
+
+[[bin]]
+name = "nac"
+path = "src/cli.rs"
+
+[dependencies]
+tokio = { version = "1.0", features = ["full"] }
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+clap = { version = "4.0", features = ["derive"] }
+actix-web = "4.0"
+reqwest = { version = "0.11", features = ["json"] }
+anyhow = "1.0"
+thiserror = "1.0"
+tracing = "0.1"
+tracing-subscriber = "0.3"
+chrono = { version = "0.4", features = ["serde"] }
+dirs = "5.0"
+toml = "0.8"
+hex = "0.4"
+sha3 = "0.10"
+
+[dev-dependencies]
+tokio-test = "0.4"
diff --git a/nac-daemon/src/cli.rs b/nac-daemon/src/cli.rs
new file mode 100644
index 0000000..30eb76c
--- /dev/null
+++ b/nac-daemon/src/cli.rs
@@ -0,0 +1,253 @@
+// nac-daemon/src/cli.rs
+// NAC 命令行工具 (nac)
+// Issue #67: 开发者终端集成
+
+use clap::{Parser, Subcommand};
+use serde_json::Value;
+
+const DAEMON_URL: &str = "http://127.0.0.1:8766";
+
+#[derive(Parser)]
+#[command(
+ name = "nac",
+ version = "1.0.0",
+ about = "NAC公链命令行工具",
+ long_about = "NAC公链开发者命令行工具\n技术栈: Charter | NVM | CBPP | CSNP | NAC_lens | CNNL"
+)]
+struct Cli {
+ #[command(subcommand)]
+ command: Commands,
+}
+
+#[derive(Subcommand)]
+enum Commands {
+ /// 查看节点状态
+ Status,
+ /// 查看节点详细信息
+ Info,
+ /// 钱包操作
+ Wallet {
+ #[command(subcommand)]
+ action: WalletCommands,
+ },
+ /// 合约操作
+ Contract {
+ #[command(subcommand)]
+ action: ContractCommands,
+ },
+ /// 网络操作
+ Network {
+ #[command(subcommand)]
+ action: NetworkCommands,
+ },
+ /// 宪法查询
+ Constitution {
+ #[command(subcommand)]
+ action: ConstitutionCommands,
+ },
+ /// 启动守护进程
+ Daemon {
+ #[arg(short, long, default_value = "127.0.0.1:8766")]
+ listen: String,
+ #[arg(short, long)]
+ dev: bool,
+ },
+}
+
+#[derive(Subcommand)]
+enum WalletCommands {
+ /// 查询余额
+ Balance {
+ /// NAC 地址(32字节,十六进制)
+ address: String,
+ },
+}
+
+#[derive(Subcommand)]
+enum ContractCommands {
+ /// 编译 Charter 合约
+ Compile {
+ /// Charter 合约文件路径
+ file: String,
+ },
+ /// 验证 Charter 合约语法
+ Validate {
+ /// Charter 合约文件路径
+ file: String,
+ },
+ /// 检查代码中的以太坊化问题
+ Lint {
+ /// 源代码文件路径
+ file: String,
+ },
+}
+
+#[derive(Subcommand)]
+enum NetworkCommands {
+ /// 查看连接的节点
+ Peers,
+}
+
+#[derive(Subcommand)]
+enum ConstitutionCommands {
+ /// 查看宪法条款摘要
+ List,
+}
+
+// ============================================================
+// 辅助函数
+// ============================================================
+
+async fn api_get(path: &str) -> anyhow::Result {
+ let url = format!("{}{}", DAEMON_URL, path);
+ let resp = reqwest::get(&url).await?;
+ let data: Value = resp.json().await?;
+ Ok(data)
+}
+
+async fn api_post(path: &str, body: Value) -> anyhow::Result {
+ let url = format!("{}{}", DAEMON_URL, path);
+ let client = reqwest::Client::new();
+ let resp = client.post(&url).json(&body).send().await?;
+ let data: Value = resp.json().await?;
+ Ok(data)
+}
+
+fn print_json(v: &Value) {
+ println!("{}", serde_json::to_string_pretty(v).unwrap_or_default());
+}
+
+// ============================================================
+// 主函数
+// ============================================================
+
+#[tokio::main]
+async fn main() -> anyhow::Result<()> {
+ let cli = Cli::parse();
+
+ match cli.command {
+ Commands::Status => {
+ match api_get("/api/v1/status").await {
+ Ok(data) => {
+ if let Some(d) = data.get("data") {
+ println!("=== NAC 节点状态 ===");
+ println!("链: {}", d["chain"].as_str().unwrap_or("NAC"));
+ println!("网络: {}", d["network"].as_str().unwrap_or("unknown"));
+ println!("区块高度: {}", d["block_height"]);
+ println!("连接节点: {}", d["connected_peers"]);
+ println!("同步中: {}", d["syncing"]);
+ println!("CBPP纪元: {}", d["cbpp_epoch"]);
+ println!("运行时间: {}秒", d["uptime_seconds"]);
+ println!("NAC_lens: {}", d["nac_lens_endpoint"].as_str().unwrap_or(""));
+ }
+ }
+ Err(e) => eprintln!("错误: 无法连接到 nacd 守护进程 ({})\n请先运行: nacd", e),
+ }
+ }
+
+ Commands::Info => {
+ match api_get("/api/v1/node/info").await {
+ Ok(data) => print_json(&data),
+ Err(e) => eprintln!("错误: {}", e),
+ }
+ }
+
+ Commands::Wallet { action } => match action {
+ WalletCommands::Balance { address } => {
+ match api_get(&format!("/api/v1/wallet/balance/{}", address)).await {
+ Ok(data) => {
+ if let Some(d) = data.get("data") {
+ println!("=== 余额查询 ===");
+ println!("地址: {}", address);
+ println!("XTZH: {}", d["xtzh_balance"].as_str().unwrap_or("0"));
+ println!("XIC: {}", d["xic_balance"].as_str().unwrap_or("0"));
+ println!("NAC: {}", d["nac_balance"].as_str().unwrap_or("0"));
+ }
+ }
+ Err(e) => eprintln!("错误: {}", e),
+ }
+ }
+ },
+
+ Commands::Contract { action } => match action {
+ ContractCommands::Compile { file } => {
+ let source = std::fs::read_to_string(&file)
+ .map_err(|e| anyhow::anyhow!("无法读取文件 {}: {}", file, e))?;
+ println!("正在编译 {}...", file);
+ match api_post("/api/v1/contract/compile", serde_json::json!({ "source": source })).await {
+ Ok(data) => print_json(&data),
+ Err(e) => eprintln!("编译错误: {}", e),
+ }
+ }
+ ContractCommands::Validate { file } => {
+ let source = std::fs::read_to_string(&file)
+ .map_err(|e| anyhow::anyhow!("无法读取文件 {}: {}", file, e))?;
+ println!("正在验证 {}...", file);
+ match api_post("/api/v1/contract/validate", serde_json::json!({ "source": source })).await {
+ Ok(data) => print_json(&data),
+ Err(e) => eprintln!("验证错误: {}", e),
+ }
+ }
+ ContractCommands::Lint { file } => {
+ let source = std::fs::read_to_string(&file)
+ .map_err(|e| anyhow::anyhow!("无法读取文件 {}: {}", file, e))?;
+ // 本地 lint 检查(不需要守护进程)
+ let forbidden = [
+ ("RPC", "NAC_lens"),
+ ("EVM", "NVM"),
+ ("Solidity", "Charter"),
+ ("ERC20", "ACC-20"),
+ ("ERC-20", "ACC-20"),
+ ("ETH", "NAC"),
+ ("Gwei", "XTZH"),
+ ("Wei", "XTZH"),
+ ];
+ let mut found = false;
+ for (bad, good) in &forbidden {
+ if source.contains(bad) {
+ println!("⚠️ 发现以太坊化关键字: '{}' → 应使用 '{}'", bad, good);
+ found = true;
+ }
+ }
+ if !found {
+ println!("✅ {} 通过去以太坊化检查", file);
+ }
+ }
+ },
+
+ Commands::Network { action } => match action {
+ NetworkCommands::Peers => {
+ match api_get("/api/v1/network/peers").await {
+ Ok(data) => print_json(&data),
+ Err(e) => eprintln!("错误: {}", e),
+ }
+ }
+ },
+
+ Commands::Constitution { action } => match action {
+ ConstitutionCommands::List => {
+ match api_get("/api/v1/constitution/clauses").await {
+ Ok(data) => {
+ if let Some(d) = data.get("data") {
+ println!("=== NAC公链宪法 ===");
+ println!("版本: {}", d["version"].as_str().unwrap_or(""));
+ println!("条款数量: {}", d["clause_count"]);
+ println!("最后更新: 纪元 {}", d["last_updated_epoch"]);
+ println!("状态哈希: {}", d["state_hash"].as_str().unwrap_or(""));
+ }
+ }
+ Err(e) => eprintln!("错误: {}", e),
+ }
+ }
+ },
+
+ Commands::Daemon { listen, dev } => {
+ println!("正在启动 NAC 守护进程...");
+ println!("监听地址: {}", listen);
+ if dev { println!("模式: 开发模式"); }
+ println!("提示: 请直接运行 nacd 启动守护进程");
+ }
+ }
+
+ Ok(())
+}
diff --git a/nac-daemon/src/config.rs b/nac-daemon/src/config.rs
new file mode 100644
index 0000000..c9e34a9
--- /dev/null
+++ b/nac-daemon/src/config.rs
@@ -0,0 +1,78 @@
+// nac-daemon/src/config.rs
+// 守护进程配置
+
+use serde::{Serialize, Deserialize};
+use std::path::PathBuf;
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct DaemonConfig {
+ /// 守护进程监听地址(默认 127.0.0.1:8766)
+ pub listen_addr: String,
+ /// NAC_lens 端点(本地节点的 NAC_lens 服务)
+ pub nac_lens_endpoint: String,
+ /// CNNL 编译服务端点
+ pub cnnl_service_endpoint: String,
+ /// CSNP 监听地址
+ pub csnp_listen_addr: String,
+ /// 节点类型(full/light/validator)
+ pub node_type: String,
+ /// 网络名称(mainnet/testnet/devnet)
+ pub network: String,
+ /// 是否开发模式(允许无 NAC_lens 连接时返回模拟数据)
+ pub dev_mode: bool,
+ /// 数据目录
+ pub data_dir: PathBuf,
+ /// 日志级别
+ pub log_level: String,
+}
+
+impl Default for DaemonConfig {
+ fn default() -> Self {
+ DaemonConfig {
+ listen_addr: "127.0.0.1:8766".to_string(),
+ nac_lens_endpoint: "http://127.0.0.1:9000".to_string(),
+ cnnl_service_endpoint: "https://cnnl.newassetchain.io".to_string(),
+ csnp_listen_addr: "0.0.0.0:9001".to_string(),
+ node_type: "full".to_string(),
+ network: "testnet".to_string(),
+ dev_mode: true,
+ data_dir: dirs::home_dir()
+ .unwrap_or_else(|| PathBuf::from("/tmp"))
+ .join(".nac"),
+ log_level: "info".to_string(),
+ }
+ }
+}
+
+impl DaemonConfig {
+ /// 从配置文件加载(~/.nac/daemon.toml)
+ pub fn load() -> anyhow::Result {
+ let config_path = dirs::home_dir()
+ .unwrap_or_else(|| PathBuf::from("/tmp"))
+ .join(".nac")
+ .join("daemon.toml");
+
+ if config_path.exists() {
+ let content = std::fs::read_to_string(&config_path)?;
+ let config: DaemonConfig = toml::from_str(&content)?;
+ Ok(config)
+ } else {
+ // 创建默认配置
+ let config = DaemonConfig::default();
+ if let Some(parent) = config_path.parent() {
+ std::fs::create_dir_all(parent)?;
+ }
+ let content = toml::to_string_pretty(&config)?;
+ std::fs::write(&config_path, content)?;
+ Ok(config)
+ }
+ }
+
+ /// 保存配置
+ pub fn save(&self) -> anyhow::Result<()> {
+ let config_path = self.data_dir.join("daemon.toml");
+ let content = toml::to_string_pretty(self)?;
+ std::fs::write(config_path, content)?;
+ Ok(())
+ }
+}
diff --git a/nac-daemon/src/contract.rs b/nac-daemon/src/contract.rs
new file mode 100644
index 0000000..3cca366
--- /dev/null
+++ b/nac-daemon/src/contract.rs
@@ -0,0 +1,2 @@
+// nac-daemon/src/contract.rs
+// 模块占位 - 后续实现
diff --git a/nac-daemon/src/main.rs b/nac-daemon/src/main.rs
new file mode 100644
index 0000000..3670a78
--- /dev/null
+++ b/nac-daemon/src/main.rs
@@ -0,0 +1,273 @@
+// nac-daemon/src/main.rs
+// Issue #67: NAC公链本地守护进程 (nacd)
+// 提供本地 HTTP API,供开发者网站和 CLI 工具调用
+
+use actix_web::{web, App, HttpServer, HttpResponse};
+use serde::Serialize;
+use std::sync::Arc;
+use tokio::sync::RwLock;
+use tracing::info;
+
+mod config;
+mod node_status;
+mod wallet;
+mod contract;
+mod network;
+
+use config::DaemonConfig;
+use node_status::NodeStatus;
+
+/// 守护进程全局状态
+pub struct DaemonState {
+ pub config: DaemonConfig,
+ pub node_status: NodeStatus,
+ pub start_time: u64,
+}
+
+impl DaemonState {
+ pub fn new(config: DaemonConfig) -> Self {
+ DaemonState {
+ config,
+ node_status: NodeStatus::default(),
+ start_time: chrono::Utc::now().timestamp() as u64,
+ }
+ }
+}
+
+type SharedState = Arc>;
+
+/// API 响应包装
+#[derive(Serialize)]
+pub struct ApiResponse {
+ pub success: bool,
+ pub data: Option,
+ pub error: Option,
+ pub timestamp: u64,
+}
+
+impl ApiResponse {
+ pub fn ok(data: T) -> Self {
+ ApiResponse {
+ success: true,
+ data: Some(data),
+ error: None,
+ timestamp: chrono::Utc::now().timestamp() as u64,
+ }
+ }
+
+ pub fn err(msg: &str) -> ApiResponse<()> {
+ ApiResponse {
+ success: false,
+ data: None,
+ error: Some(msg.to_string()),
+ timestamp: chrono::Utc::now().timestamp() as u64,
+ }
+ }
+}
+
+// ============================================================
+// API 端点
+// ============================================================
+
+/// GET /api/v1/status - 节点状态
+async fn get_status(state: web::Data) -> HttpResponse {
+ let state = state.read().await;
+ let status = &state.node_status;
+ HttpResponse::Ok().json(ApiResponse::ok(serde_json::json!({
+ "version": env!("CARGO_PKG_VERSION"),
+ "chain": "NAC",
+ "network": status.network_name,
+ "block_height": status.block_height,
+ "connected_peers": status.connected_peers,
+ "syncing": status.is_syncing,
+ "uptime_seconds": chrono::Utc::now().timestamp() as u64 - state.start_time,
+ "nac_lens_endpoint": state.config.nac_lens_endpoint,
+ "cbpp_epoch": status.current_epoch,
+ })))
+}
+
+/// GET /api/v1/node/info - 节点详细信息
+async fn get_node_info(state: web::Data) -> HttpResponse {
+ let state = state.read().await;
+ HttpResponse::Ok().json(ApiResponse::ok(serde_json::json!({
+ "node_id": state.node_status.node_id,
+ "node_type": state.config.node_type,
+ "cbpp_role": state.node_status.cbpp_role,
+ "csnp_address": state.config.csnp_listen_addr,
+ "nac_lens_version": "4.0",
+ "nvm_version": "1.0",
+ "charter_version": "1.0",
+ "cnnl_version": "1.0",
+ "jurisdictions": state.node_status.active_jurisdictions,
+ })))
+}
+
+/// GET /api/v1/wallet/balance/:address - 查询余额
+async fn get_balance(
+ path: web::Path,
+ state: web::Data,
+) -> HttpResponse {
+ let address = path.into_inner();
+ let state = state.read().await;
+
+ // 通过 NAC_lens 查询余额
+ let endpoint = format!("{}/balance/{}", state.config.nac_lens_endpoint, address);
+ match reqwest::get(&endpoint).await {
+ Ok(resp) => {
+ match resp.json::().await {
+ Ok(data) => HttpResponse::Ok().json(ApiResponse::ok(data)),
+ Err(e) => HttpResponse::InternalServerError()
+ .json(ApiResponse::<()>::err(&e.to_string())),
+ }
+ }
+ Err(_) => {
+ // NAC_lens 不可用时返回模拟数据(开发模式)
+ if state.config.dev_mode {
+ HttpResponse::Ok().json(ApiResponse::ok(serde_json::json!({
+ "address": address,
+ "xtzh_balance": "0",
+ "xic_balance": "0",
+ "nac_balance": "0",
+ "note": "dev_mode: NAC_lens not connected"
+ })))
+ } else {
+ HttpResponse::ServiceUnavailable()
+ .json(ApiResponse::<()>::err("NAC_lens endpoint unreachable"))
+ }
+ }
+ }
+}
+
+/// POST /api/v1/contract/compile - 编译 Charter 合约
+async fn compile_contract(
+ body: web::Json,
+ state: web::Data,
+) -> HttpResponse {
+ let state = state.read().await;
+ let source = match body.get("source").and_then(|s| s.as_str()) {
+ Some(s) => s.to_string(),
+ None => return HttpResponse::BadRequest()
+ .json(ApiResponse::<()>::err("缺少 source 字段")),
+ };
+
+ // 调用 CNNL 编译服务
+ let cnnl_endpoint = format!("{}/api/v1/compile", state.config.cnnl_service_endpoint);
+ let client = reqwest::Client::new();
+ match client.post(&cnnl_endpoint)
+ .json(&serde_json::json!({ "source": source }))
+ .send()
+ .await
+ {
+ Ok(resp) => {
+ match resp.json::().await {
+ Ok(data) => HttpResponse::Ok().json(ApiResponse::ok(data)),
+ Err(e) => HttpResponse::InternalServerError()
+ .json(ApiResponse::<()>::err(&e.to_string())),
+ }
+ }
+ Err(_) => HttpResponse::ServiceUnavailable()
+ .json(ApiResponse::<()>::err("CNNL 编译服务不可用")),
+ }
+}
+
+/// POST /api/v1/contract/validate - 验证 Charter 合约语法
+async fn validate_contract(
+ body: web::Json,
+ state: web::Data,
+) -> HttpResponse {
+ let state = state.read().await;
+ let source = match body.get("source").and_then(|s| s.as_str()) {
+ Some(s) => s.to_string(),
+ None => return HttpResponse::BadRequest()
+ .json(ApiResponse::<()>::err("缺少 source 字段")),
+ };
+
+ let cnnl_endpoint = format!("{}/api/v1/validate", state.config.cnnl_service_endpoint);
+ let client = reqwest::Client::new();
+ match client.post(&cnnl_endpoint)
+ .json(&serde_json::json!({ "source": source }))
+ .send()
+ .await
+ {
+ Ok(resp) => {
+ match resp.json::().await {
+ Ok(data) => HttpResponse::Ok().json(ApiResponse::ok(data)),
+ Err(e) => HttpResponse::InternalServerError()
+ .json(ApiResponse::<()>::err(&e.to_string())),
+ }
+ }
+ Err(_) => HttpResponse::ServiceUnavailable()
+ .json(ApiResponse::<()>::err("CNNL 验证服务不可用")),
+ }
+}
+
+/// GET /api/v1/network/peers - 获取连接的节点列表
+async fn get_peers(state: web::Data) -> HttpResponse {
+ let state = state.read().await;
+ HttpResponse::Ok().json(ApiResponse::ok(serde_json::json!({
+ "peers": state.node_status.peers,
+ "total": state.node_status.connected_peers,
+ })))
+}
+
+/// GET /api/v1/constitution/clauses - 获取当前宪法条款
+async fn get_constitution(state: web::Data) -> HttpResponse {
+ let state = state.read().await;
+ HttpResponse::Ok().json(ApiResponse::ok(serde_json::json!({
+ "version": state.node_status.constitution_version,
+ "clause_count": 43,
+ "last_updated_epoch": state.node_status.current_epoch,
+ "state_hash": state.node_status.constitution_hash,
+ })))
+}
+
+/// GET /api/v1/health - 健康检查
+async fn health_check() -> HttpResponse {
+ HttpResponse::Ok().json(serde_json::json!({
+ "status": "ok",
+ "service": "nac-daemon",
+ "version": env!("CARGO_PKG_VERSION"),
+ }))
+}
+
+// ============================================================
+// 主函数
+// ============================================================
+
+#[tokio::main]
+async fn main() -> anyhow::Result<()> {
+ tracing_subscriber::fmt::init();
+
+ // 加载配置
+ let config = DaemonConfig::load()?;
+ let listen_addr = config.listen_addr.clone();
+ let state = Arc::new(RwLock::new(DaemonState::new(config)));
+
+ info!("NAC 守护进程启动中...");
+ info!("监听地址: {}", listen_addr);
+ info!("NAC_lens 端点: {}", state.read().await.config.nac_lens_endpoint);
+
+ HttpServer::new(move || {
+ App::new()
+ .app_data(web::Data::new(state.clone()))
+ // 状态和节点信息
+ .route("/api/v1/status", web::get().to(get_status))
+ .route("/api/v1/node/info", web::get().to(get_node_info))
+ // 钱包
+ .route("/api/v1/wallet/balance/{address}", web::get().to(get_balance))
+ // 合约
+ .route("/api/v1/contract/compile", web::post().to(compile_contract))
+ .route("/api/v1/contract/validate", web::post().to(validate_contract))
+ // 网络
+ .route("/api/v1/network/peers", web::get().to(get_peers))
+ // 宪法
+ .route("/api/v1/constitution/clauses", web::get().to(get_constitution))
+ // 健康检查
+ .route("/api/v1/health", web::get().to(health_check))
+ })
+ .bind(&listen_addr)?
+ .run()
+ .await?;
+
+ Ok(())
+}
diff --git a/nac-daemon/src/network.rs b/nac-daemon/src/network.rs
new file mode 100644
index 0000000..c891096
--- /dev/null
+++ b/nac-daemon/src/network.rs
@@ -0,0 +1,2 @@
+// nac-daemon/src/network.rs
+// 模块占位 - 后续实现
diff --git a/nac-daemon/src/node_status.rs b/nac-daemon/src/node_status.rs
new file mode 100644
index 0000000..75d06b3
--- /dev/null
+++ b/nac-daemon/src/node_status.rs
@@ -0,0 +1,46 @@
+// nac-daemon/src/node_status.rs
+// 节点状态结构
+
+use serde::{Serialize, Deserialize};
+
+#[derive(Debug, Clone, Serialize, Deserialize, Default)]
+pub struct PeerInfo {
+ pub peer_id: String,
+ pub address: String,
+ pub jurisdiction: String,
+ pub latency_ms: u64,
+ pub connected_since: u64,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct NodeStatus {
+ pub node_id: String,
+ pub network_name: String,
+ pub block_height: u64,
+ pub connected_peers: u32,
+ pub is_syncing: bool,
+ pub current_epoch: u64,
+ pub cbpp_role: String,
+ pub active_jurisdictions: Vec,
+ pub peers: Vec,
+ pub constitution_version: String,
+ pub constitution_hash: String,
+}
+
+impl Default for NodeStatus {
+ fn default() -> Self {
+ NodeStatus {
+ node_id: format!("nac-node-{}", hex::encode(&[0u8; 8])),
+ network_name: "testnet".to_string(),
+ block_height: 0,
+ connected_peers: 0,
+ is_syncing: false,
+ current_epoch: 0,
+ cbpp_role: "observer".to_string(),
+ active_jurisdictions: vec!["default".to_string()],
+ peers: vec![],
+ constitution_version: "1.0.0".to_string(),
+ constitution_hash: "000000000000000000000000000000000000000000000000".to_string(),
+ }
+ }
+}
diff --git a/nac-daemon/src/wallet.rs b/nac-daemon/src/wallet.rs
new file mode 100644
index 0000000..4117df2
--- /dev/null
+++ b/nac-daemon/src/wallet.rs
@@ -0,0 +1,2 @@
+// nac-daemon/src/wallet.rs
+// 模块占位 - 后续实现
diff --git a/nac-multi-jurisdiction/Cargo.lock b/nac-multi-jurisdiction/Cargo.lock
new file mode 100644
index 0000000..c444103
--- /dev/null
+++ b/nac-multi-jurisdiction/Cargo.lock
@@ -0,0 +1,734 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "bitflags"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
+
+[[package]]
+name = "bytes"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
+
+[[package]]
+name = "cc"
+version = "1.2.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "chrono"
+version = "0.4.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
+name = "futures-core"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.65"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
+
+[[package]]
+name = "js-sys"
+version = "0.3.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
+dependencies = [
+ "cpufeatures",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.182"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "mio"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "nac-multi-jurisdiction"
+version = "1.0.0"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "hex",
+ "serde",
+ "serde_json",
+ "sha2",
+ "sha3",
+ "thiserror",
+ "tokio",
+ "tokio-test",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-link",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.149"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest",
+ "keccak",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+dependencies = [
+ "errno",
+ "libc",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "socket2"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio"
+version = "1.49.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
+dependencies = [
+ "bytes",
+ "libc",
+ "mio",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-test"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6d24790a10a7af737693a3e8f1d03faef7e6ca0cc99aae5066f533766de545"
+dependencies = [
+ "futures-core",
+ "tokio",
+ "tokio-stream",
+]
+
+[[package]]
+name = "typenum"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
+dependencies = [
+ "bumpalo",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.62.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+
+[[package]]
+name = "windows-result"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
+dependencies = [
+ "windows-link",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/nac-multi-jurisdiction/Cargo.toml b/nac-multi-jurisdiction/Cargo.toml
new file mode 100644
index 0000000..ccd4f37
--- /dev/null
+++ b/nac-multi-jurisdiction/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "nac-multi-jurisdiction"
+version = "1.0.0"
+edition = "2021"
+authors = ["NAC公链开发小组 · 多司法辖区工作组"]
+description = "NAC公链多辖区节点共享方案 - Issue #59"
+
+[dependencies]
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+sha3 = "0.10"
+sha2 = "0.10"
+hex = "0.4"
+chrono = { version = "0.4", features = ["serde"] }
+anyhow = "1.0"
+thiserror = "1.0"
+tokio = { version = "1.0", features = ["full"] }
+
+[dev-dependencies]
+tokio-test = "0.4"
diff --git a/nac-multi-jurisdiction/src/cross_jurisdiction.rs b/nac-multi-jurisdiction/src/cross_jurisdiction.rs
new file mode 100644
index 0000000..c436660
--- /dev/null
+++ b/nac-multi-jurisdiction/src/cross_jurisdiction.rs
@@ -0,0 +1,159 @@
+// nac-multi-jurisdiction/src/cross_jurisdiction.rs
+// Issue #59: 跨辖区交易处理与双宪法收据
+
+use serde::{Serialize, Deserialize};
+use crate::jurisdiction::JurisdictionId;
+
+/// 双宪法收据(跨辖区交易必须携带)
+/// 发起辖区 + 接收辖区都必须签署
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct DualConstitutionalReceipt {
+ /// 交易唯一标识(SHA3-384)
+ pub tx_id: Vec,
+ /// 发起辖区 ID
+ pub source_jurisdiction: JurisdictionId,
+ /// 接收辖区 ID
+ pub target_jurisdiction: JurisdictionId,
+ /// 发起辖区宪法收据(原始字节)
+ pub source_receipt: Vec,
+ /// 接收辖区宪法收据(原始字节)
+ pub target_receipt: Vec,
+ /// 时间戳(Unix 秒)
+ pub timestamp: u64,
+ /// 纪元编号
+ pub epoch: u64,
+ /// 是否已最终确认
+ pub is_finalized: bool,
+}
+
+impl DualConstitutionalReceipt {
+ /// 验证双收据完整性
+ pub fn is_valid(&self) -> bool {
+ !self.source_receipt.is_empty()
+ && !self.target_receipt.is_empty()
+ && self.source_jurisdiction != self.target_jurisdiction
+ && self.tx_id != vec![0u8; 48]
+ }
+
+ /// 检查是否包含指定辖区的收据
+ pub fn has_receipt_for(&self, jid: &JurisdictionId) -> bool {
+ &self.source_jurisdiction == jid || &self.target_jurisdiction == jid
+ }
+}
+
+/// 跨辖区交易
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct CrossJurisdictionTx {
+ /// 交易 ID
+ pub id: Vec,
+ /// 发起辖区
+ pub source_jurisdiction: JurisdictionId,
+ /// 接收辖区
+ pub target_jurisdiction: JurisdictionId,
+ /// 交易数据
+ pub payload: Vec,
+ /// 双宪法收据(可选,处理中为 None)
+ pub dual_receipt: Option,
+ /// 交易状态
+ pub status: CrossTxStatus,
+ /// 冲突解决策略
+ pub conflict_resolution: ConflictResolutionStrategy,
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub enum CrossTxStatus {
+ /// 待处理(等待接收辖区收据)
+ Pending,
+ /// 源辖区已确认
+ SourceConfirmed,
+ /// 双方已确认
+ DualConfirmed,
+ /// 最终确认
+ Finalized,
+ /// 失败(附带原因)
+ Failed(String),
+ /// 冲突(需要解决)
+ Conflicted,
+}
+
+/// 规则冲突解决策略
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub enum ConflictResolutionStrategy {
+ /// 严格模式:任何冲突都拒绝交易
+ StrictReject,
+ /// 源辖区优先:以发起辖区规则为准
+ SourcePriority,
+ /// 目标辖区优先:以接收辖区规则为准
+ TargetPriority,
+ /// 协商模式:双方辖区协商解决
+ Negotiated,
+ /// 宪法仲裁:提交宪法法院仲裁
+ ConstitutionalArbitration,
+}
+
+/// 跨辖区路由器
+pub struct CrossJurisdictionRouter {
+ pending_txs: Vec,
+ /// 最大待处理交易数
+ max_pending: usize,
+}
+
+impl CrossJurisdictionRouter {
+ pub fn new() -> Self {
+ CrossJurisdictionRouter {
+ pending_txs: Vec::new(),
+ max_pending: 10000,
+ }
+ }
+
+ /// 提交跨辖区交易
+ pub fn submit(&mut self, tx: CrossJurisdictionTx) -> Result, String> {
+ if self.pending_txs.len() >= self.max_pending {
+ return Err("待处理交易队列已满".to_string());
+ }
+ let id = tx.id.clone();
+ self.pending_txs.push(tx);
+ Ok(id)
+ }
+
+ /// 附加目标辖区收据(完成双收据)
+ pub fn attach_target_receipt(
+ &mut self,
+ tx_id: &Vec,
+ receipt: Vec,
+ ) -> Result<(), String> {
+ for tx in &mut self.pending_txs {
+ if &tx.id == tx_id {
+ if let Some(ref mut dr) = tx.dual_receipt {
+ dr.target_receipt = receipt;
+ dr.is_finalized = true;
+ tx.status = CrossTxStatus::DualConfirmed;
+ return Ok(());
+ }
+ }
+ }
+ Err(format!("交易 {:?} 不存在", tx_id))
+ }
+
+ /// 检测规则冲突
+ pub fn detect_conflict(
+ &self,
+ source_rules: &[u8],
+ target_rules: &[u8],
+ ) -> bool {
+ // 规则冲突检测:比较两个辖区的规则哈希
+ // 实际实现由 NVM 系统调用处理
+ source_rules.is_empty() || target_rules.is_empty()
+ }
+
+ /// 获取待处理交易数量
+ pub fn pending_count(&self) -> usize {
+ self.pending_txs.len()
+ }
+}
+
+impl Default for CrossJurisdictionRouter {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/nac-multi-jurisdiction/src/discovery.rs b/nac-multi-jurisdiction/src/discovery.rs
new file mode 100644
index 0000000..fceb047
--- /dev/null
+++ b/nac-multi-jurisdiction/src/discovery.rs
@@ -0,0 +1,63 @@
+// nac-multi-jurisdiction/src/discovery.rs
+// Issue #59: 辖区感知节点发现
+
+use crate::jurisdiction::JurisdictionId;
+
+/// 辖区感知节点发现
+pub struct NodeDiscovery {
+ known_nodes: Vec,
+}
+
+#[derive(Debug, Clone)]
+pub struct NodeInfo {
+ pub node_id: [u8; 32],
+ pub jurisdiction_id: JurisdictionId,
+ pub endpoint: String,
+ pub is_active: bool,
+}
+
+impl NodeDiscovery {
+ pub fn new() -> Self {
+ NodeDiscovery { known_nodes: Vec::new() }
+ }
+
+ /// 注册节点
+ pub fn register_node(&mut self, info: NodeInfo) {
+ self.known_nodes.push(info);
+ }
+
+ /// 查找指定辖区的节点
+ pub fn find_by_jurisdiction(&self, jid: &JurisdictionId) -> Vec<&NodeInfo> {
+ self.known_nodes.iter()
+ .filter(|n| &n.jurisdiction_id == jid && n.is_active)
+ .collect()
+ }
+
+ /// 获取所有活跃节点数量
+ pub fn active_count(&self) -> usize {
+ self.known_nodes.iter().filter(|n| n.is_active).count()
+ }
+}
+
+impl Default for NodeDiscovery {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+/// 辖区感知路由器
+pub struct JurisdictionAwareRouter {
+ discovery: NodeDiscovery,
+}
+
+impl JurisdictionAwareRouter {
+ pub fn new(discovery: NodeDiscovery) -> Self {
+ JurisdictionAwareRouter { discovery }
+ }
+
+ /// 路由到目标辖区
+ pub fn route_to(&self, target_jid: &JurisdictionId) -> Option<&NodeInfo> {
+ self.discovery.find_by_jurisdiction(target_jid).into_iter().next()
+ }
+}
+
diff --git a/nac-multi-jurisdiction/src/dual_receipt.rs b/nac-multi-jurisdiction/src/dual_receipt.rs
new file mode 100644
index 0000000..d1f85bc
--- /dev/null
+++ b/nac-multi-jurisdiction/src/dual_receipt.rs
@@ -0,0 +1,59 @@
+// nac-multi-jurisdiction/src/dual_receipt.rs
+// Issue #59: 双宪法收据验证
+
+/// 双收据验证器
+pub struct DualReceiptVerifier {
+ /// 是否要求双签名
+ require_dual: bool,
+}
+
+impl DualReceiptVerifier {
+ pub fn new() -> Self {
+ DualReceiptVerifier { require_dual: true }
+ }
+
+ pub fn requires_dual_signature(&self) -> bool {
+ self.require_dual
+ }
+
+ /// 验证双收据完整性
+ pub fn verify(&self, source_receipt: &[u8], target_receipt: &[u8]) -> bool {
+ !source_receipt.is_empty() && !target_receipt.is_empty()
+ }
+}
+
+impl Default for DualReceiptVerifier {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+/// 收据链(跨辖区交易的收据历史)
+pub struct ReceiptChain {
+ receipts: Vec>,
+}
+
+impl ReceiptChain {
+ pub fn new() -> Self {
+ ReceiptChain { receipts: Vec::new() }
+ }
+
+ pub fn append(&mut self, receipt: Vec) {
+ self.receipts.push(receipt);
+ }
+
+ pub fn len(&self) -> usize {
+ self.receipts.len()
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.receipts.is_empty()
+ }
+}
+
+impl Default for ReceiptChain {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
diff --git a/nac-multi-jurisdiction/src/governance.rs b/nac-multi-jurisdiction/src/governance.rs
new file mode 100644
index 0000000..901edb2
--- /dev/null
+++ b/nac-multi-jurisdiction/src/governance.rs
@@ -0,0 +1,105 @@
+// nac-multi-jurisdiction/src/governance.rs
+// Issue #59: 共享资源治理
+
+use crate::jurisdiction::JurisdictionId;
+
+/// 辖区协商委员会
+pub struct JurisdictionCouncil {
+ members: Vec,
+ /// 决议通过门限(定点数 1e4,6700 = 67%)
+ quorum_threshold: u64,
+}
+
+impl JurisdictionCouncil {
+ pub fn new() -> Self {
+ JurisdictionCouncil {
+ members: Vec::new(),
+ quorum_threshold: 6700,
+ }
+ }
+
+ pub fn add_member(&mut self, jid: JurisdictionId) {
+ if !self.members.contains(&jid) {
+ self.members.push(jid);
+ }
+ }
+
+ /// 检查是否达到法定人数
+ pub fn has_quorum(&self, voting_count: usize) -> bool {
+ if self.members.is_empty() {
+ return false;
+ }
+ let ratio = voting_count as u64 * 10000 / self.members.len() as u64;
+ ratio >= self.quorum_threshold
+ }
+
+ pub fn member_count(&self) -> usize {
+ self.members.len()
+ }
+}
+
+impl Default for JurisdictionCouncil {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+/// 共享资源治理
+pub struct SharedResourceGovernance {
+ council: JurisdictionCouncil,
+ pending_proposals: Vec,
+}
+
+#[derive(Debug, Clone)]
+pub struct ResourceProposal {
+ pub id: u64,
+ pub proposer: JurisdictionId,
+ pub description: String,
+ pub votes_for: u64,
+ pub votes_against: u64,
+ pub is_passed: bool,
+}
+
+impl SharedResourceGovernance {
+ pub fn new(council: JurisdictionCouncil) -> Self {
+ SharedResourceGovernance {
+ council,
+ pending_proposals: Vec::new(),
+ }
+ }
+
+ /// 提交资源分配提案
+ pub fn submit_proposal(
+ &mut self,
+ proposer: JurisdictionId,
+ description: String,
+ ) -> u64 {
+ let id = self.pending_proposals.len() as u64;
+ self.pending_proposals.push(ResourceProposal {
+ id,
+ proposer,
+ description,
+ votes_for: 0,
+ votes_against: 0,
+ is_passed: false,
+ });
+ id
+ }
+
+ /// 投票
+ pub fn vote(&mut self, proposal_id: u64, in_favor: bool) -> Result<(), String> {
+ let proposal = self.pending_proposals.get_mut(proposal_id as usize)
+ .ok_or("提案不存在")?;
+ if in_favor {
+ proposal.votes_for += 1;
+ } else {
+ proposal.votes_against += 1;
+ }
+ // 检查是否达到法定人数
+ let total_votes = proposal.votes_for + proposal.votes_against;
+ if self.council.has_quorum(total_votes as usize) {
+ proposal.is_passed = proposal.votes_for * 10000 / total_votes >= 6700;
+ }
+ Ok(())
+ }
+}
diff --git a/nac-multi-jurisdiction/src/isolation.rs b/nac-multi-jurisdiction/src/isolation.rs
new file mode 100644
index 0000000..0453b06
--- /dev/null
+++ b/nac-multi-jurisdiction/src/isolation.rs
@@ -0,0 +1,167 @@
+// nac-multi-jurisdiction/src/isolation.rs
+// Issue #59: 逻辑隔离层 - 确保不同辖区规则互不干扰
+
+use serde::{Serialize, Deserialize};
+use crate::jurisdiction::JurisdictionId;
+
+/// 隔离策略级别
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub enum IsolationLevel {
+ /// 严格隔离:完全独立的执行环境(默认)
+ Strict,
+ /// 受控共享:允许只读数据共享
+ ControlledSharing,
+ /// 联合模式:辖区间协商后的有限互操作
+ Federated,
+}
+
+/// 隔离策略
+#[derive(Debug, Clone)]
+pub struct IsolationPolicy {
+ pub level: IsolationLevel,
+ /// 是否强制规则隔离
+ pub enforce_rule_isolation: bool,
+ /// 是否强制数据隔离
+ pub enforce_data_isolation: bool,
+ /// 是否强制网络隔离
+ pub enforce_network_isolation: bool,
+ /// 是否强制存储隔离
+ pub enforce_storage_isolation: bool,
+ /// 允许的跨辖区数据类型(白名单)
+ pub allowed_cross_data_types: Vec,
+}
+
+impl IsolationPolicy {
+ /// 创建严格隔离策略(推荐默认)
+ pub fn strict() -> Self {
+ IsolationPolicy {
+ level: IsolationLevel::Strict,
+ enforce_rule_isolation: true,
+ enforce_data_isolation: true,
+ enforce_network_isolation: false, // 网络层允许路由
+ enforce_storage_isolation: true,
+ allowed_cross_data_types: vec![
+ "ConstitutionalReceipt".to_string(),
+ "BlockHeader".to_string(),
+ ],
+ }
+ }
+
+ /// 创建受控共享策略
+ pub fn controlled_sharing() -> Self {
+ IsolationPolicy {
+ level: IsolationLevel::ControlledSharing,
+ enforce_rule_isolation: true,
+ enforce_data_isolation: false,
+ enforce_network_isolation: false,
+ enforce_storage_isolation: false,
+ allowed_cross_data_types: vec![
+ "ConstitutionalReceipt".to_string(),
+ "BlockHeader".to_string(),
+ "PublicAssetMetadata".to_string(),
+ ],
+ }
+ }
+
+ pub fn enforces_rule_isolation(&self) -> bool {
+ self.enforce_rule_isolation
+ }
+
+ pub fn enforces_data_isolation(&self) -> bool {
+ self.enforce_data_isolation
+ }
+
+ /// 检查数据类型是否允许跨辖区传输
+ pub fn is_allowed_cross_type(&self, data_type: &str) -> bool {
+ self.allowed_cross_data_types.iter().any(|t| t == data_type)
+ }
+}
+
+/// 隔离违规事件
+#[derive(Debug, Clone)]
+pub struct IsolationViolation {
+ pub source_jurisdiction: JurisdictionId,
+ pub target_jurisdiction: JurisdictionId,
+ pub violation_type: ViolationType,
+ pub data_type: String,
+ pub timestamp: u64,
+ pub severity: ViolationSeverity,
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum ViolationType {
+ UnauthorizedDataAccess,
+ RuleConflict,
+ NetworkBypass,
+ StorageLeak,
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum ViolationSeverity {
+ Low,
+ Medium,
+ High,
+ Critical,
+}
+
+/// 隔离层执行器
+pub struct IsolationLayer {
+ policies: std::collections::HashMap,
+ violations: Vec,
+}
+
+impl IsolationLayer {
+ pub fn new() -> Self {
+ IsolationLayer {
+ policies: std::collections::HashMap::new(),
+ violations: Vec::new(),
+ }
+ }
+
+ /// 为辖区设置隔离策略
+ pub fn set_policy(&mut self, jid: JurisdictionId, policy: IsolationPolicy) {
+ self.policies.insert(jid, policy);
+ }
+
+ /// 检查跨辖区操作是否合规
+ pub fn check_cross_operation(
+ &mut self,
+ from: &JurisdictionId,
+ to: &JurisdictionId,
+ data_type: &str,
+ ) -> Result<(), IsolationViolation> {
+ let policy = self.policies.get(from)
+ .cloned()
+ .unwrap_or_else(IsolationPolicy::strict);
+
+ if policy.enforce_data_isolation && !policy.is_allowed_cross_type(data_type) {
+ let violation = IsolationViolation {
+ source_jurisdiction: from.clone(),
+ target_jurisdiction: to.clone(),
+ violation_type: ViolationType::UnauthorizedDataAccess,
+ data_type: data_type.to_string(),
+ timestamp: 0,
+ severity: ViolationSeverity::High,
+ };
+ self.violations.push(violation.clone());
+ return Err(violation);
+ }
+ Ok(())
+ }
+
+ /// 获取违规记录
+ pub fn get_violations(&self) -> &[IsolationViolation] {
+ &self.violations
+ }
+
+ /// 清除已处理的违规记录
+ pub fn clear_violations(&mut self) {
+ self.violations.clear();
+ }
+}
+
+impl Default for IsolationLayer {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/nac-multi-jurisdiction/src/jurisdiction.rs b/nac-multi-jurisdiction/src/jurisdiction.rs
new file mode 100644
index 0000000..77d0cae
--- /dev/null
+++ b/nac-multi-jurisdiction/src/jurisdiction.rs
@@ -0,0 +1,153 @@
+// nac-multi-jurisdiction/src/jurisdiction.rs
+// Issue #59: 辖区注册与配置管理
+
+use std::collections::HashMap;
+use serde::{Serialize, Deserialize};
+
+/// 辖区唯一标识符(格式:国家代码-监管机构)
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct JurisdictionId(String);
+
+impl JurisdictionId {
+ pub fn from_str(s: &str) -> Self {
+ JurisdictionId(s.to_string())
+ }
+
+ pub fn as_str(&self) -> &str {
+ &self.0
+ }
+
+ /// 验证格式:必须符合 XX-XXXX 格式
+ pub fn is_valid(&self) -> bool {
+ let parts: Vec<&str> = self.0.split('-').collect();
+ parts.len() == 2 && parts[0].len() == 2 && parts[1].len() >= 2
+ }
+}
+
+/// 辖区配置(宪法级,变更需辖区协商)
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct JurisdictionConfig {
+ /// 辖区唯一标识
+ pub id: JurisdictionId,
+ /// 辖区名称
+ pub name: String,
+ /// 地区代码(ISO 3166-2)
+ pub region_code: String,
+ /// 规则插件哈希(SHA3-384,48字节)
+ pub plugin_hash: Vec,
+ /// 最大资源共享比例,定点数 1e4(3000 = 30.00%)
+ pub max_resource_share: u64,
+ /// 是否激活
+ pub is_active: bool,
+}
+
+impl JurisdictionConfig {
+ /// 验证配置合法性
+ pub fn is_valid(&self) -> bool {
+ self.id.is_valid()
+ && !self.name.is_empty()
+ && self.max_resource_share <= 10000
+ && self.plugin_hash != vec![0u8; 48]
+ }
+}
+
+/// 辖区信息(运行时状态)
+#[derive(Debug, Clone)]
+pub struct Jurisdiction {
+ pub config: JurisdictionConfig,
+ /// 当前节点数量
+ pub node_count: u64,
+ /// 当前资源使用率,定点数 1e4
+ pub resource_usage: u64,
+ /// 最后活跃时间戳
+ pub last_active: u64,
+ /// 是否处于维护模式
+ pub in_maintenance: bool,
+}
+
+impl Jurisdiction {
+ pub fn new(config: JurisdictionConfig) -> Self {
+ Jurisdiction {
+ config,
+ node_count: 0,
+ resource_usage: 0,
+ last_active: 0,
+ in_maintenance: false,
+ }
+ }
+
+ /// 检查资源使用是否超限
+ pub fn is_resource_overloaded(&self) -> bool {
+ self.resource_usage > self.config.max_resource_share
+ }
+}
+
+/// 辖区注册表(全局单例)
+pub struct JurisdictionRegistry {
+ jurisdictions: HashMap,
+ /// 最大注册辖区数(宪法限制)
+ max_jurisdictions: usize,
+}
+
+impl JurisdictionRegistry {
+ pub fn new() -> Self {
+ JurisdictionRegistry {
+ jurisdictions: HashMap::new(),
+ max_jurisdictions: 100,
+ }
+ }
+
+ /// 注册新辖区(需宪法收据)
+ pub fn register(&mut self, config: JurisdictionConfig) -> Result<(), String> {
+ if !config.is_valid() {
+ return Err("辖区配置无效".to_string());
+ }
+ if self.jurisdictions.len() >= self.max_jurisdictions {
+ return Err("辖区数量已达上限".to_string());
+ }
+ let id = config.id.clone();
+ self.jurisdictions.insert(id, Jurisdiction::new(config));
+ Ok(())
+ }
+
+ /// 查询辖区
+ pub fn get(&self, id: &JurisdictionId) -> Option<&Jurisdiction> {
+ self.jurisdictions.get(id)
+ }
+
+ /// 获取所有活跃辖区
+ pub fn active_jurisdictions(&self) -> Vec<&Jurisdiction> {
+ self.jurisdictions
+ .values()
+ .filter(|j| j.config.is_active && !j.in_maintenance)
+ .collect()
+ }
+
+ /// 动态加入新辖区(无需重构基础设施)
+ pub fn dynamic_join(&mut self, config: JurisdictionConfig) -> Result {
+ let id = config.id.clone();
+ self.register(config)?;
+ Ok(id)
+ }
+
+ /// 辖区退出(进入维护模式,等待迁移完成)
+ pub fn graceful_exit(&mut self, id: &JurisdictionId) -> Result<(), String> {
+ if let Some(j) = self.jurisdictions.get_mut(id) {
+ j.in_maintenance = true;
+ Ok(())
+ } else {
+ Err(format!("辖区 {} 不存在", id.as_str()))
+ }
+ }
+
+ /// 辖区数量
+ pub fn count(&self) -> usize {
+ self.jurisdictions.len()
+ }
+}
+
+impl Default for JurisdictionRegistry {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/nac-multi-jurisdiction/src/lib.rs b/nac-multi-jurisdiction/src/lib.rs
new file mode 100644
index 0000000..883350e
--- /dev/null
+++ b/nac-multi-jurisdiction/src/lib.rs
@@ -0,0 +1,80 @@
+// nac-multi-jurisdiction/src/lib.rs
+// Issue #59: NAC 公链多辖区节点共享方案
+// 版本: 1.0 | 制定方: NAC 核心协议工程组 · 多司法辖区工作组
+
+//! # 多辖区节点共享模块
+//!
+//! 实现不同司法辖区节点在物理层共享基础设施,
+//! 在逻辑层保持各自合规性、自治性和独立性。
+//!
+//! ## 核心设计
+//! - 逻辑强隔离:节点执行的规则完全由其所属辖区插件决定
+//! - 物理资源共享:支持节点共用计算、存储、带宽资源
+//! - 跨辖区互操作:通过双宪法收据(CR)保障合规性
+//! - 宪法级保障:所有共享方案受宪法条款约束
+
+pub mod jurisdiction;
+pub mod isolation;
+pub mod cross_jurisdiction;
+pub mod resource_sharing;
+pub mod plugin;
+pub mod dual_receipt;
+pub mod discovery;
+pub mod governance;
+
+pub use jurisdiction::{Jurisdiction, JurisdictionId, JurisdictionConfig, JurisdictionRegistry};
+pub use isolation::{IsolationLayer, IsolationPolicy, IsolationViolation};
+pub use cross_jurisdiction::{CrossJurisdictionTx, DualConstitutionalReceipt, CrossJurisdictionRouter};
+pub use resource_sharing::{ResourcePool, ResourceAllocation, ResourceQuota, ResourceMonitor};
+pub use plugin::{JurisdictionPlugin, PluginLoader, PluginRegistry, RuleConflictResolver};
+pub use dual_receipt::{DualReceiptVerifier, ReceiptChain};
+pub use discovery::{NodeDiscovery, JurisdictionAwareRouter};
+pub use governance::{JurisdictionCouncil, SharedResourceGovernance};
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_jurisdiction_registry() {
+ let mut registry = JurisdictionRegistry::new();
+ let jid = JurisdictionId::from_str("UAE-ADGM");
+ let config = JurisdictionConfig {
+ id: jid.clone(),
+ name: "阿联酋 ADGM 辖区".to_string(),
+ region_code: "AE-AZ".to_string(),
+ plugin_hash: vec![0u8; 48],
+ max_resource_share: 3000, // 30.00%
+ is_active: true,
+ };
+ registry.register(config);
+ assert!(registry.get(&jid).is_some());
+ }
+
+ #[test]
+ fn test_isolation_policy() {
+ let policy = IsolationPolicy::strict();
+ assert!(policy.enforces_rule_isolation());
+ assert!(policy.enforces_data_isolation());
+ }
+
+ #[test]
+ fn test_resource_quota() {
+ let quota = ResourceQuota {
+ jurisdiction_id: JurisdictionId::from_str("SG-MAS"),
+ cpu_share: 2500, // 25.00%
+ memory_share: 2000, // 20.00%
+ bandwidth_share: 3000, // 30.00%
+ storage_share: 1500, // 15.00%
+ };
+ assert!(quota.is_valid());
+ assert!(quota.total_share() <= 10000);
+ }
+
+ #[test]
+ fn test_dual_receipt_chain() {
+ let verifier = DualReceiptVerifier::new();
+ // 双宪法收据验证:发起辖区 + 接收辖区都必须签署
+ assert!(verifier.requires_dual_signature());
+ }
+}
diff --git a/nac-multi-jurisdiction/src/plugin.rs b/nac-multi-jurisdiction/src/plugin.rs
new file mode 100644
index 0000000..b67ee60
--- /dev/null
+++ b/nac-multi-jurisdiction/src/plugin.rs
@@ -0,0 +1,135 @@
+// nac-multi-jurisdiction/src/plugin.rs
+// Issue #59: 可插拔辖区规则插件
+
+use std::collections::HashMap;
+use crate::jurisdiction::JurisdictionId;
+
+/// 辖区规则插件接口
+pub trait JurisdictionPlugin: Send + Sync {
+ /// 插件名称
+ fn name(&self) -> &str;
+ /// 插件版本
+ fn version(&self) -> &str;
+ /// 插件哈希(SHA3-384)
+ fn hash(&self) -> [u8; 48];
+ /// 验证交易是否符合本辖区规则
+ fn validate_tx(&self, tx_data: &[u8]) -> Result<(), String>;
+ /// 验证区块是否符合本辖区规则
+ fn validate_block(&self, block_data: &[u8]) -> Result<(), String>;
+ /// 获取辖区特定的合规要求
+ fn compliance_requirements(&self) -> Vec;
+}
+
+/// 插件加载器
+pub struct PluginLoader {
+ plugins: HashMap>,
+}
+
+impl PluginLoader {
+ pub fn new() -> Self {
+ PluginLoader {
+ plugins: HashMap::new(),
+ }
+ }
+
+ /// 加载插件(通过哈希验证)
+ pub fn load(
+ &mut self,
+ jid: JurisdictionId,
+ plugin: Box,
+ expected_hash: &[u8; 48],
+ ) -> Result<(), String> {
+ if &plugin.hash() != expected_hash {
+ return Err("插件哈希验证失败:可能被篡改".to_string());
+ }
+ self.plugins.insert(jid, plugin);
+ Ok(())
+ }
+
+ /// 获取辖区插件
+ pub fn get(&self, jid: &JurisdictionId) -> Option<&dyn JurisdictionPlugin> {
+ self.plugins.get(jid).map(|p| p.as_ref())
+ }
+
+ /// 卸载插件
+ pub fn unload(&mut self, jid: &JurisdictionId) {
+ self.plugins.remove(jid);
+ }
+}
+
+impl Default for PluginLoader {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+/// 插件注册表
+pub struct PluginRegistry {
+ loader: PluginLoader,
+}
+
+impl PluginRegistry {
+ pub fn new() -> Self {
+ PluginRegistry {
+ loader: PluginLoader::new(),
+ }
+ }
+}
+
+impl Default for PluginRegistry {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+/// 规则冲突解决器
+pub struct RuleConflictResolver {
+ /// 冲突解决历史
+ resolution_history: Vec,
+}
+
+#[derive(Debug, Clone)]
+pub struct ConflictRecord {
+ pub source: JurisdictionId,
+ pub target: JurisdictionId,
+ pub conflict_type: String,
+ pub resolution: String,
+ pub timestamp: u64,
+}
+
+impl RuleConflictResolver {
+ pub fn new() -> Self {
+ RuleConflictResolver {
+ resolution_history: Vec::new(),
+ }
+ }
+
+ /// 解决规则冲突(返回解决方案)
+ pub fn resolve(
+ &mut self,
+ source: &JurisdictionId,
+ target: &JurisdictionId,
+ conflict_type: &str,
+ ) -> String {
+ // 默认策略:提交宪法仲裁
+ let resolution = format!(
+ "冲突已提交宪法仲裁:{} vs {} - {}",
+ source.as_str(), target.as_str(), conflict_type
+ );
+ self.resolution_history.push(ConflictRecord {
+ source: source.clone(),
+ target: target.clone(),
+ conflict_type: conflict_type.to_string(),
+ resolution: resolution.clone(),
+ timestamp: 0,
+ });
+ resolution
+ }
+}
+
+impl Default for RuleConflictResolver {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
diff --git a/nac-multi-jurisdiction/src/resource_sharing.rs b/nac-multi-jurisdiction/src/resource_sharing.rs
new file mode 100644
index 0000000..09a943d
--- /dev/null
+++ b/nac-multi-jurisdiction/src/resource_sharing.rs
@@ -0,0 +1,175 @@
+// nac-multi-jurisdiction/src/resource_sharing.rs
+// Issue #59: 物理资源共享与公平分配
+
+use std::collections::HashMap;
+use serde::{Serialize, Deserialize};
+use crate::jurisdiction::JurisdictionId;
+
+/// 资源配额(每辖区)
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct ResourceQuota {
+ pub jurisdiction_id: JurisdictionId,
+ /// CPU 共享比例,定点数 1e4(2500 = 25.00%)
+ pub cpu_share: u64,
+ /// 内存共享比例,定点数 1e4
+ pub memory_share: u64,
+ /// 带宽共享比例,定点数 1e4
+ pub bandwidth_share: u64,
+ /// 存储共享比例,定点数 1e4
+ pub storage_share: u64,
+}
+
+impl ResourceQuota {
+ /// 验证配额合法性(各项不超过 100%)
+ pub fn is_valid(&self) -> bool {
+ self.cpu_share <= 10000
+ && self.memory_share <= 10000
+ && self.bandwidth_share <= 10000
+ && self.storage_share <= 10000
+ }
+
+ /// 计算总资源占用(平均值)
+ pub fn total_share(&self) -> u64 {
+ (self.cpu_share + self.memory_share + self.bandwidth_share + self.storage_share) / 4
+ }
+}
+
+/// 资源分配记录
+#[derive(Debug, Clone)]
+pub struct ResourceAllocation {
+ pub jurisdiction_id: JurisdictionId,
+ pub allocated_cpu: u64, // 毫核
+ pub allocated_memory: u64, // MB
+ pub allocated_bandwidth: u64, // Mbps
+ pub allocated_storage: u64, // GB
+ pub timestamp: u64,
+}
+
+/// 资源池(物理共享层)
+pub struct ResourcePool {
+ /// 总 CPU(毫核)
+ total_cpu: u64,
+ /// 总内存(MB)
+ total_memory: u64,
+ /// 总带宽(Mbps)
+ total_bandwidth: u64,
+ /// 总存储(GB)
+ total_storage: u64,
+ /// 各辖区配额
+ quotas: HashMap,
+ /// 当前分配
+ allocations: HashMap,
+}
+
+impl ResourcePool {
+ pub fn new(cpu: u64, memory: u64, bandwidth: u64, storage: u64) -> Self {
+ ResourcePool {
+ total_cpu: cpu,
+ total_memory: memory,
+ total_bandwidth: bandwidth,
+ total_storage: storage,
+ quotas: HashMap::new(),
+ allocations: HashMap::new(),
+ }
+ }
+
+ /// 设置辖区资源配额
+ pub fn set_quota(&mut self, quota: ResourceQuota) -> Result<(), String> {
+ if !quota.is_valid() {
+ return Err("资源配额无效".to_string());
+ }
+ // 检查总配额不超过 100%
+ let total_cpu: u64 = self.quotas.values().map(|q| q.cpu_share).sum::()
+ + quota.cpu_share;
+ if total_cpu > 10000 {
+ return Err("CPU 总配额超过 100%".to_string());
+ }
+ self.quotas.insert(quota.jurisdiction_id.clone(), quota);
+ Ok(())
+ }
+
+ /// 为辖区分配资源
+ pub fn allocate(&mut self, jid: &JurisdictionId, timestamp: u64) -> Result {
+ let quota = self.quotas.get(jid)
+ .ok_or_else(|| format!("辖区 {} 没有配额", jid.as_str()))?;
+
+ let allocation = ResourceAllocation {
+ jurisdiction_id: jid.clone(),
+ allocated_cpu: self.total_cpu * quota.cpu_share / 10000,
+ allocated_memory: self.total_memory * quota.memory_share / 10000,
+ allocated_bandwidth: self.total_bandwidth * quota.bandwidth_share / 10000,
+ allocated_storage: self.total_storage * quota.storage_share / 10000,
+ timestamp,
+ };
+
+ self.allocations.insert(jid.clone(), allocation.clone());
+ Ok(allocation)
+ }
+
+ /// 获取辖区当前分配
+ pub fn get_allocation(&self, jid: &JurisdictionId) -> Option<&ResourceAllocation> {
+ self.allocations.get(jid)
+ }
+
+ /// 检查是否存在资源抢占
+ pub fn check_contention(&self) -> Vec {
+ // 返回资源使用超过配额的辖区
+ self.allocations.iter()
+ .filter(|(jid, alloc)| {
+ if let Some(quota) = self.quotas.get(*jid) {
+ let used_cpu = alloc.allocated_cpu * 10000 / self.total_cpu;
+ used_cpu > quota.cpu_share + 500 // 超出 5% 视为抢占
+ } else {
+ false
+ }
+ })
+ .map(|(jid, _)| jid.clone())
+ .collect()
+ }
+}
+
+/// 资源监控器
+pub struct ResourceMonitor {
+ pool: ResourcePool,
+ alert_threshold: u64, // 超过配额多少时告警,定点数 1e4
+}
+
+impl ResourceMonitor {
+ pub fn new(pool: ResourcePool) -> Self {
+ ResourceMonitor {
+ pool,
+ alert_threshold: 1000, // 超出 10% 告警
+ }
+ }
+
+ /// 检查所有辖区资源使用情况
+ pub fn check_all(&self) -> Vec {
+ let contention = self.pool.check_contention();
+ contention.into_iter().map(|jid| ResourceAlert {
+ jurisdiction_id: jid,
+ alert_type: AlertType::ResourceContention,
+ severity: AlertSeverity::Warning,
+ }).collect()
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct ResourceAlert {
+ pub jurisdiction_id: JurisdictionId,
+ pub alert_type: AlertType,
+ pub severity: AlertSeverity,
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum AlertType {
+ ResourceContention,
+ QuotaExceeded,
+ PoolExhausted,
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum AlertSeverity {
+ Info,
+ Warning,
+ Critical,
+}