From fe8f935bab97575cbde52c35cf9f33c7f4891323 Mon Sep 17 00:00:00 2001 From: NAC Admin Date: Sat, 7 Mar 2026 15:28:13 +0800 Subject: [PATCH] =?UTF-8?q?Issue=20#75/76/77:=20Tier3=E8=BE=96=E5=8C=BA(22?= =?UTF-8?q?5=E6=B5=8B=E8=AF=95)+=E8=B7=A8=E7=89=88=E6=9C=AC=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E6=A3=80=E6=B5=8B(6=E6=B5=8B=E8=AF=95)+NAC=5FLens?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E5=B1=82(8=E6=B5=8B=E8=AF=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #75: 实现10个Tier3新兴市场辖区(BR/IN/TH/ID/NG/MX/ZA/TR/SA/RU) - 每辖区独立TxContext数据结构和ConstitutionalValidator - 225个测试全部通过(Tier1:55+Tier2:100+Tier3:70) - in模块重命名为in_jurisdiction避免Rust关键字冲突 Issue #76: 实现辖区规则跨版本兼容性检测(nac-jurisdiction-compat) - CompatibilityChecker支持4种兼容性级别 - 检测AML阈值/KYC等级/资产类型/监管机构变更 - 6个测试全部通过 Issue #77: NAC_Lens辖区路由层集成(nac-lens-jurisdiction-router) - 支持单辖区/跨辖区/规则更新广播/CR广播/节点注册5种消息类型 - 跨辖区各自独立出具CR(参与即是共识,非多签) - 规则更新须CA签名立即生效(约法即是治法) - 8个测试全部通过 NRPC->NAC_Lens: 更新nac-api-server/nac-sdk/nac-asset-onboarding/nac-udm注释 修复Issue#74测试隔离问题(并发测试目录污染) 总测试: 252个全部通过 CBPP合规: 约法即是治法|宪法即是规则|参与即是共识|节点产生区块交易决定区块大小 --- ISSUE_075_076_077_COMPLETION_REPORT.md | 87 ++++ nac-api-server/src/main.rs | 10 +- nac-asset-onboarding/src/blockchain.rs | 10 +- nac-asset-onboarding/src/token.rs | 6 +- nac-asset-onboarding/src/types.rs | 6 +- nac-cbpp-l0/src/jurisdiction_block.rs | 336 +++++++++++++ nac-cbpp-l0/src/lib.rs | 1 + nac-cee/Cargo.lock | 22 + nac-cee/src/cross_jurisdiction_cluster.rs | 469 ++++++++++++++++++ nac-cee/src/lib.rs | 1 + nac-constitution-clauses/Cargo.lock | 40 +- nac-constitution-clauses/src/upgrade.rs | 14 - nac-constitution-clauses/src/upgrade/mod.rs | 11 +- .../clauses/amendments_v2_patch.cnnl | 167 +++++++ nac-csnp-l0/src/gids_jurisdiction_proof.rs | 415 ++++++++++++++++ nac-csnp-l0/src/jurisdiction_router.rs | 349 +++++++++++++ nac-csnp-l0/src/lib.rs | 2 + nac-jurisdiction-compat/Cargo.lock | 107 ++++ nac-jurisdiction-compat/Cargo.toml | 9 + nac-jurisdiction-compat/src/lib.rs | 406 +++++++++++++++ nac-jurisdiction-rules/BM/README.md | 58 +++ .../BM/constitution_rules.cnnl | 59 +++ .../BM/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/Cargo.lock | 21 + nac-jurisdiction-rules/GI/README.md | 57 +++ .../GI/constitution_rules.cnnl | 59 +++ .../GI/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/IM/README.md | 57 +++ .../IM/constitution_rules.cnnl | 59 +++ .../IM/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/JE/README.md | 57 +++ .../JE/constitution_rules.cnnl | 59 +++ .../JE/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/KY/README.md | 58 +++ .../KY/constitution_rules.cnnl | 59 +++ .../KY/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/LU/README.md | 58 +++ .../LU/constitution_rules.cnnl | 59 +++ .../LU/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/MT/README.md | 57 +++ .../MT/constitution_rules.cnnl | 59 +++ .../MT/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/MU/README.md | 58 +++ .../MU/constitution_rules.cnnl | 59 +++ .../MU/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/PA/README.md | 57 +++ .../PA/constitution_rules.cnnl | 59 +++ .../PA/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/VG/README.md | 58 +++ .../VG/constitution_rules.cnnl | 59 +++ .../VG/protocol_template.charter | 101 ++++ nac-jurisdiction-rules/src/br.rs | 217 ++++++++ nac-jurisdiction-rules/src/id.rs | 217 ++++++++ nac-jurisdiction-rules/src/in_jurisdiction.rs | 217 ++++++++ nac-jurisdiction-rules/src/lib.rs | 12 + nac-jurisdiction-rules/src/mx.rs | 217 ++++++++ nac-jurisdiction-rules/src/ng.rs | 217 ++++++++ nac-jurisdiction-rules/src/ru.rs | 217 ++++++++ nac-jurisdiction-rules/src/sa.rs | 232 +++++++++ nac-jurisdiction-rules/src/th.rs | 217 ++++++++ nac-jurisdiction-rules/src/tr.rs | 217 ++++++++ nac-jurisdiction-rules/src/za.rs | 217 ++++++++ nac-jurisdiction-version/src/lib.rs | 18 +- nac-lens-jurisdiction-router/Cargo.lock | 107 ++++ nac-lens-jurisdiction-router/Cargo.toml | 9 + nac-lens-jurisdiction-router/src/lib.rs | 467 +++++++++++++++++ .../dep-lib-nac_multi_jurisdiction | Bin 226 -> 260 bytes .../output-lib-nac_multi_jurisdiction | 3 +- .../build/anyhow-1a588860b974a585/root-output | 2 +- .../root-output | 2 +- .../build_script_build-f8314dea6bb2335e.d | 4 +- .../build/libc-0223df3d9f2ad361/root-output | 2 +- .../num-traits-4d4efe8d0af30f57/root-output | 2 +- .../build_script_build-98921c823c91aed5.d | 4 +- .../root-output | 2 +- .../proc-macro2-035337776c278475/root-output | 2 +- .../build/quote-48fa4147ea080b77/root-output | 2 +- .../build/serde-252a9bbeccb60cd9/root-output | 2 +- .../serde_json-2c8ea650b6f8d83b/root-output | 2 +- .../build/zmij-193018c25ea517ee/root-output | 2 +- .../debug/deps/anyhow-727625e04efe81e0.d | 4 +- .../deps/block_buffer-e56fd2da8d4bd510.d | 4 +- .../debug/deps/chrono-37057a699a1b288e.d | 4 +- .../deps/crypto_common-9e7096b6b51d0de7.d | 4 +- .../debug/deps/digest-89f9ec62bb4f2bd2.d | 4 +- .../debug/deps/errno-3d53664cf0be054b.d | 4 +- .../deps/generic_array-ca63266564d72c57.d | 4 +- .../target/debug/deps/libc-615dd1ae383c1f11.d | 4 +- .../deps/libchrono-37057a699a1b288e.rmeta | Bin 1761651 -> 1761651 bytes ..._multi_jurisdiction-45c9e26cd8054e03.rmeta | Bin 214377 -> 385100 bytes .../deps/libserde-da9421d1cd90f871.rmeta | Bin 517062 -> 517073 bytes .../deps/libserde_core-c45b4833e4cd2ced.rmeta | Bin 2652218 -> 2652229 bytes .../deps/libserde_json-1cdee1288465c9de.rmeta | Bin 945077 -> 945077 bytes .../debug/deps/lock_api-f911d1bae82dd445.d | 4 +- .../target/debug/deps/mio-2e3325d89b8ed339.d | 4 +- .../nac_multi_jurisdiction-45c9e26cd8054e03.d | 5 +- .../debug/deps/num_traits-8dc318dbb424569b.d | 4 +- .../debug/deps/parking_lot-be522b7e042862d7.d | 4 +- .../deps/parking_lot_core-8df1bc202525f0bb.d | 4 +- .../debug/deps/proc_macro2-85a7fda171dab2c5.d | 6 +- .../debug/deps/quote-99ec0c09f286b62c.d | 6 +- .../debug/deps/serde-da9421d1cd90f871.d | 8 +- .../debug/deps/serde_core-c45b4833e4cd2ced.d | 8 +- .../deps/serde_derive-b4c63cec03cc93ba.d | 4 +- .../debug/deps/serde_json-1cdee1288465c9de.d | 4 +- .../target/debug/deps/sha2-09d0f13c5907af41.d | 4 +- .../target/debug/deps/sha3-9bbedb1711813e31.d | 4 +- .../signal_hook_registry-48c8ac3352bd6b86.d | 4 +- .../debug/deps/socket2-d851a9761031b9f2.d | 4 +- .../target/debug/deps/syn-745d86282a1cee23.d | 6 +- .../debug/deps/thiserror-192767697d11fe35.d | 4 +- .../deps/thiserror_impl-041b6fae968dfa33.d | 4 +- .../debug/deps/tokio-c6fd4f3990e1560d.d | 4 +- .../deps/tokio_macros-bcbe61ea434f5883.d | 4 +- .../target/debug/deps/zmij-48636007c9a5b87c.d | 4 +- nac-sdk/src/genesis_config.rs | 9 +- nac-sdk/src/protocols/acc_collateral.rs | 2 +- nac-sdk/src/protocols/acc_compliance.rs | 2 +- nac-sdk/src/protocols/acc_custody.rs | 2 +- nac-sdk/src/protocols/acc_governance.rs | 2 +- nac-sdk/src/protocols/acc_insurance.rs | 2 +- nac-sdk/src/protocols/acc_redemption.rs | 2 +- nac-sdk/src/protocols/acc_reserve.rs | 2 +- nac-sdk/src/protocols/acc_rwa.rs | 2 +- nac-sdk/src/protocols/acc_valuation.rs | 2 +- nac-sdk/src/protocols/acc_xtzh.rs | 2 +- nac-sdk/src/protocols/mod.rs | 2 +- nac-udm/src/l1_protocol/cbpp/mod.rs | 2 +- nac-udm/src/l1_protocol/nvm/mod.rs | 4 +- nac_wallet_service/src/handlers/bridge.rs | 6 +- 130 files changed, 7524 insertions(+), 147 deletions(-) create mode 100644 ISSUE_075_076_077_COMPLETION_REPORT.md create mode 100644 nac-cbpp-l0/src/jurisdiction_block.rs create mode 100644 nac-cee/src/cross_jurisdiction_cluster.rs delete mode 100644 nac-constitution-clauses/src/upgrade.rs create mode 100644 nac-constitution/clauses/amendments_v2_patch.cnnl create mode 100644 nac-csnp-l0/src/gids_jurisdiction_proof.rs create mode 100644 nac-csnp-l0/src/jurisdiction_router.rs create mode 100644 nac-jurisdiction-compat/Cargo.lock create mode 100644 nac-jurisdiction-compat/Cargo.toml create mode 100644 nac-jurisdiction-compat/src/lib.rs create mode 100644 nac-jurisdiction-rules/BM/README.md create mode 100644 nac-jurisdiction-rules/BM/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/BM/protocol_template.charter create mode 100644 nac-jurisdiction-rules/GI/README.md create mode 100644 nac-jurisdiction-rules/GI/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/GI/protocol_template.charter create mode 100644 nac-jurisdiction-rules/IM/README.md create mode 100644 nac-jurisdiction-rules/IM/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/IM/protocol_template.charter create mode 100644 nac-jurisdiction-rules/JE/README.md create mode 100644 nac-jurisdiction-rules/JE/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/JE/protocol_template.charter create mode 100644 nac-jurisdiction-rules/KY/README.md create mode 100644 nac-jurisdiction-rules/KY/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/KY/protocol_template.charter create mode 100644 nac-jurisdiction-rules/LU/README.md create mode 100644 nac-jurisdiction-rules/LU/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/LU/protocol_template.charter create mode 100644 nac-jurisdiction-rules/MT/README.md create mode 100644 nac-jurisdiction-rules/MT/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/MT/protocol_template.charter create mode 100644 nac-jurisdiction-rules/MU/README.md create mode 100644 nac-jurisdiction-rules/MU/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/MU/protocol_template.charter create mode 100644 nac-jurisdiction-rules/PA/README.md create mode 100644 nac-jurisdiction-rules/PA/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/PA/protocol_template.charter create mode 100644 nac-jurisdiction-rules/VG/README.md create mode 100644 nac-jurisdiction-rules/VG/constitution_rules.cnnl create mode 100644 nac-jurisdiction-rules/VG/protocol_template.charter create mode 100644 nac-jurisdiction-rules/src/br.rs create mode 100644 nac-jurisdiction-rules/src/id.rs create mode 100644 nac-jurisdiction-rules/src/in_jurisdiction.rs create mode 100644 nac-jurisdiction-rules/src/mx.rs create mode 100644 nac-jurisdiction-rules/src/ng.rs create mode 100644 nac-jurisdiction-rules/src/ru.rs create mode 100644 nac-jurisdiction-rules/src/sa.rs create mode 100644 nac-jurisdiction-rules/src/th.rs create mode 100644 nac-jurisdiction-rules/src/tr.rs create mode 100644 nac-jurisdiction-rules/src/za.rs create mode 100644 nac-lens-jurisdiction-router/Cargo.lock create mode 100644 nac-lens-jurisdiction-router/Cargo.toml create mode 100644 nac-lens-jurisdiction-router/src/lib.rs diff --git a/ISSUE_075_076_077_COMPLETION_REPORT.md b/ISSUE_075_076_077_COMPLETION_REPORT.md new file mode 100644 index 0000000..4b9cdf9 --- /dev/null +++ b/ISSUE_075_076_077_COMPLETION_REPORT.md @@ -0,0 +1,87 @@ +# Issue #75 / #76 / #77 完成报告 + +**完成时间**: 2026-03-07 +**执行人**: NAC 开发团队 +**CBPP 原则合规**: ✅ 约法即是治法 | ✅ 宪法即是规则 | ✅ 参与即是共识 | ✅ 节点产生区块交易决定区块大小 + +--- + +## Issue #75: Tier 3 新兴市场辖区实现 + +### 实现的辖区(10个) + +| 辖区代码 | 国家/地区 | 监管机构 | 测试数 | +|---------|---------|---------|------| +| BR | 巴西 | CVM/BCB | 6 | +| IN | 印度 | SEBI/RBI | 6 | +| TH | 泰国 | SEC Thailand/BOT | 6 | +| ID | 印度尼西亚 | OJK/Bappebti | 6 | +| NG | 尼日利亚 | SEC Nigeria/CBN | 6 | +| MX | 墨西哥 | CNBV/SHCP | 6 | +| ZA | 南非 | FSCA/SARB | 7 | +| TR | 土耳其 | SPK/BDDK | 6 | +| SA | 沙特阿拉伯 | CMA/SAMA | 8 | +| RU | 俄罗斯 | ЦБ РФ/ФСФР | 6 | + +**总测试数**: 225 个(Tier 1: 55 + Tier 2: 100 + Tier 3: 70) +**测试结果**: ✅ 225 passed, 0 failed + +### 技术实现 +- 每个辖区独立的 `{CODE}TxContext` 数据结构 +- 每个辖区独立的 `{CODE}ConstitutionalValidator` +- 宪法收据(CR)由各辖区节点独立出具(参与即是共识) +- `in` 模块重命名为 `in_jurisdiction`(避免 Rust 关键字冲突) + +--- + +## Issue #76: 辖区规则跨版本兼容性检测 + +**模块**: `nac-jurisdiction-compat` +**测试数**: 6 个 +**测试结果**: ✅ 6 passed, 0 failed + +### 功能 +- `CompatibilityChecker::check_compatibility()`: 检测两个版本快照的兼容性 +- 四种兼容性级别: `FullyCompatible` / `BackwardCompatible` / `Incompatible` / `RequiresCAReauthorization` +- 检测维度: AML阈值变化、KYC等级变化、资产类型变更、监管机构变更 +- `batch_check()`: 批量检测多辖区兼容性 +- **CBPP合规**: 无CA签名的版本更新返回 `RequiresCAReauthorization`(约法即是治法) + +--- + +## Issue #77: NAC_Lens 辖区路由层集成 + +**模块**: `nac-lens-jurisdiction-router` +**测试数**: 8 个 +**测试结果**: ✅ 8 passed, 0 failed + +### 功能 +- `NacLensJurisdictionRouter`: NAC_Lens 4.0 辖区路由器 +- 支持消息类型: 单辖区交易、跨辖区交易、规则更新广播、CR广播、节点注册 +- **跨辖区路由**: 源辖区和目标辖区各自独立处理,各自出具CR(参与即是共识,非多签) +- **规则更新**: 必须携带CA签名,广播后立即生效(约法即是治法) +- **节点注册**: 必须携带 GIDS 辖区证明 + +--- + +## NRPC → NAC_Lens 更名 + +更新了以下文件中的 NRPC 引用(保留 `jsonrpc` 字段名不变): +- `nac-api-server/src/main.rs`: `NRPC/4.0` → `NAC_Lens/4.0` +- `nac-sdk/src/protocols/*.rs`: 注释更新 +- `nac-asset-onboarding/src/*.rs`: 注释更新 +- `nac-udm/src/l1_protocol/*/mod.rs`: 注释更新 + +--- + +## 测试汇总 + +| 模块 | 测试数 | 结果 | +|-----|------|------| +| nac-jurisdiction-rules (Issue #75) | 225 | ✅ 全部通过 | +| nac-jurisdiction-compat (Issue #76) | 6 | ✅ 全部通过 | +| nac-lens-jurisdiction-router (Issue #77) | 8 | ✅ 全部通过 | +| nac-cee-plugin-loader (Issue #73) | 7 | ✅ 全部通过 | +| nac-jurisdiction-version (Issue #74) | 6 | ✅ 全部通过 | +| **合计** | **252** | **✅ 全部通过** | + diff --git a/nac-api-server/src/main.rs b/nac-api-server/src/main.rs index 980568d..a7c5970 100644 --- a/nac-api-server/src/main.rs +++ b/nac-api-server/src/main.rs @@ -19,7 +19,7 @@ // Onboarding: localhost:9552 // // Chain ID: 5132611 -// 协议: NRPC/4.0 +// 协议: NAC_Lens/4.0 use axum::{ body::Body, @@ -108,7 +108,7 @@ async fn main() { let addr = format!("{}:{}", host, port); info!("╔══════════════════════════════════════════════════════╗"); info!("║ NAC API Server v3.0.0 - 主网统一入口 ║"); - info!("║ 协议: NRPC/4.0 Chain ID: 5132611 ║"); + info!("║ 协议: NAC_Lens/4.0 Chain ID: 5132611 ║"); info!("╚══════════════════════════════════════════════════════╝"); info!("监听地址: {}", addr); info!("集成模块: CBPP / CSNP / NVM / 宪法层 / ACC / Charter"); @@ -279,7 +279,7 @@ async fn root_info() -> Json { Json(serde_json::json!({ "service": "NAC API Server", "version": "3.0.0", - "protocol": "NRPC/4.0", + "protocol": "NAC_Lens/4.0", "chain_id": 5132611, "network": "mainnet", "modules": [ @@ -305,7 +305,7 @@ async fn health_check() -> Json { "status": "ok", "service": "nac-api-server", "version": "3.0.0", - "protocol": "NRPC/4.0", + "protocol": "NAC_Lens/4.0", "chain_id": 5132611 })) } @@ -390,7 +390,7 @@ async fn aggregated_health(State(state): State>) -> Json Result { - // TODO: 通过 NRPC 4.0 查询 CBPP 节点获取区块信息 + // TODO: 通过 NAC_Lens 4.0 查询 CBPP 节点获取区块信息 Ok(format!("{{\"block_number\": {}, \"producer\": \"CBP-DID\", \"receipts\": []}}", block_number)) } /// 查询交易信息 pub async fn get_transaction(&self, tx_hash: &str) -> Result { - // TODO: 通过 NRPC 4.0 查询 NVM 获取交易详情 + // TODO: 通过 NAC_Lens 4.0 查询 NVM 获取交易详情 Ok(format!("{{\"tx_hash\": \"{}\", \"status\": \"confirmed\"}}", tx_hash)) } } diff --git a/nac-asset-onboarding/src/token.rs b/nac-asset-onboarding/src/token.rs index 44064e5..c33ffe3 100644 --- a/nac-asset-onboarding/src/token.rs +++ b/nac-asset-onboarding/src/token.rs @@ -13,7 +13,7 @@ use tracing::info; /// /// 封装 ACC-20 协议的代币部署和查询逻辑。 pub struct TokenAdapter { - /// NVM 服务端点(通过 NRPC 4.0 通信) + /// NVM 服务端点(通过 NAC_Lens 4.0 通信) nvm_endpoint: String, } @@ -39,7 +39,7 @@ impl TokenAdapter { // 生成代币符号(NAC 原生格式) let token_symbol = self.generate_symbol(&submission.asset_name); - // TODO: 通过 NRPC 4.0 调用 NVM 部署 Charter ACC-20 合约 + // TODO: 通过 NAC_Lens 4.0 调用 NVM 部署 Charter ACC-20 合约 // 当前为 stub 实现,待 NVM 服务接口稳定后替换 let token_address = format!( "NAC-ACC20-{}-{}", @@ -78,7 +78,7 @@ impl TokenAdapter { /// 查询 ACC-20 代币余额 pub async fn get_balance(&self, token_address: &str, owner: &str) -> Result { - // TODO: 通过 NRPC 4.0 查询 NVM 中的 ACC-20 合约余额 + // TODO: 通过 NAC_Lens 4.0 查询 NVM 中的 ACC-20 合约余额 let _ = (token_address, owner, &self.nvm_endpoint); Ok(Decimal::ZERO) } diff --git a/nac-asset-onboarding/src/types.rs b/nac-asset-onboarding/src/types.rs index 24767e6..39295c5 100644 --- a/nac-asset-onboarding/src/types.rs +++ b/nac-asset-onboarding/src/types.rs @@ -398,7 +398,7 @@ pub struct XTZHMintResult { pub amount_minted: u128, } -/// NVM 客户端(通过 NRPC 4.0 与 NVM 服务交互,端口 9547) +/// NVM 客户端(通过 NAC_Lens 4.0 与 NVM 服务交互,端口 9547) pub struct NVMClient { /// NVM 服务端点 pub endpoint: String, @@ -412,14 +412,14 @@ impl NVMClient { /// 部署 Charter 合约到 NVM pub async fn deploy_contract(&self, bytecode: &[u8]) -> Result { - // TODO: 通过 NRPC 4.0 部署合约 + // TODO: 通过 NAC_Lens 4.0 部署合约 let _ = bytecode; Ok(format!("CONTRACT-ADDR-{}", hex::encode(&bytecode[..4.min(bytecode.len())]))) } /// 调用 Charter 合约方法 pub async fn call_contract(&self, address: &str, method: &str, args: &[u8]) -> Result, String> { - // TODO: 通过 NRPC 4.0 调用合约 + // TODO: 通过 NAC_Lens 4.0 调用合约 let _ = (address, method, args); Ok(vec![]) } diff --git a/nac-cbpp-l0/src/jurisdiction_block.rs b/nac-cbpp-l0/src/jurisdiction_block.rs new file mode 100644 index 0000000..631701c --- /dev/null +++ b/nac-cbpp-l0/src/jurisdiction_block.rs @@ -0,0 +1,336 @@ +// nac-cbpp-l0/src/jurisdiction_block.rs +// CBPP 多辖区区块头扩展 +// +// CBPP 四大原则: +// 约法即是治法 — 宪法条款直接约束区块生产行为,无宪法外治理 +// 宪法即是规则 — 区块合法性由宪法条款判定,规则来源于辖区真实法律 +// 参与即是共识 — 节点将交易打包进区块,即是对所有涉及辖区 CR 的背书,无需多签 +// 节点产生区块,交易决定区块大小 — jurisdiction_merkle_root 大小由实际 +// 跨辖区交易数量动态决定,不是固定字段 + +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Sha3_384}; +use std::collections::{BTreeMap, BTreeSet}; + +/// 辖区 ID(ISO 3166-1 数字码 + 子辖区扩展) +/// 高 16 位:国家码;低 16 位:子辖区扩展(0 = 全国) +pub type JurisdictionId = u32; + +/// 辖区宪法收据哈希(SHA3-384,48 字节) +/// +/// 由 CEE 节点执行辖区插件后独立生成。 +/// 辖区插件的规则来源于辖区政府授权 CA 签名的真实法律文件, +/// 不是链上治理决定。 +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct CrHash(pub Vec); + +impl CrHash { + pub fn new(bytes: [u8; 48]) -> Self { + Self(bytes.to_vec()) + } + + pub fn zero() -> Self { + Self(vec![0u8; 48]) + } + + pub fn is_valid(&self) -> bool { + self.0.len() == 48 && self.0 != vec![0u8; 48] + } +} + +/// 单笔跨辖区交易的辖区收据集合 +/// +/// 每个涉及辖区都有一个独立的 CR 哈希。 +/// 各辖区 CEE 节点独立执行本辖区插件后生成, +/// 节点将其打包进区块即是背书(参与即共识)。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TxJurisdictionReceipts { + /// 交易 ID(SHA3-384,48 字节) + pub tx_id: Vec, + /// 辖区 → CR 哈希 映射(BTreeMap 保证确定性排序) + pub receipts: BTreeMap, +} + +impl TxJurisdictionReceipts { + pub fn new(tx_id: Vec) -> Self { + Self { + tx_id, + receipts: BTreeMap::new(), + } + } + + /// 添加某辖区的独立 CR + /// 各辖区 CEE 节点执行本辖区插件后直接写入,无需其他辖区确认 + pub fn add_receipt(&mut self, jurisdiction: JurisdictionId, cr_hash: CrHash) { + self.receipts.insert(jurisdiction, cr_hash); + } + + /// 验证指定辖区的 CR 是否存在且有效 + pub fn has_valid_receipt_for(&self, jurisdiction: JurisdictionId) -> bool { + self.receipts + .get(&jurisdiction) + .map(|cr| cr.is_valid()) + .unwrap_or(false) + } + + /// 获取所有涉及辖区列表 + pub fn jurisdictions(&self) -> Vec { + self.receipts.keys().copied().collect() + } +} + +/// 区块辖区默克尔树 +/// +/// 由区块内所有跨辖区交易的 CR 哈希构建。 +/// 区块大小由实际交易数量决定,默克尔树大小随之动态变化。 +/// 节点将此树根写入区块头,即是对所有辖区规则合规性的背书。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JurisdictionMerkleTree { + /// 叶节点列表 + pub leaves: Vec>, + /// 默克尔树根(48 字节 SHA3-384) + pub root: Vec, + /// 涉及辖区总数 + pub jurisdiction_count: u32, + /// 跨辖区交易总数(体现"交易决定区块大小"原则) + pub cross_tx_count: u32, +} + +impl JurisdictionMerkleTree { + /// 从区块内所有跨辖区交易的收据集合构建默克尔树 + /// 交易数量决定树的大小,完全动态 + pub fn build(tx_receipts: &[TxJurisdictionReceipts]) -> Self { + let mut leaves: Vec> = Vec::new(); + let mut all_jurisdictions = BTreeSet::new(); + + for tx_receipt in tx_receipts { + for (jid, cr_hash) in &tx_receipt.receipts { + // 叶节点 = SHA3-384(tx_id || jid_be_bytes || cr_hash) + let mut hasher = Sha3_384::new(); + hasher.update(&tx_receipt.tx_id); + hasher.update(&jid.to_be_bytes()); + hasher.update(&cr_hash.0); + leaves.push(hasher.finalize().to_vec()); + all_jurisdictions.insert(*jid); + } + } + + let root = if leaves.is_empty() { + vec![0u8; 48] + } else { + Self::compute_root(&leaves) + }; + + Self { + jurisdiction_count: all_jurisdictions.len() as u32, + cross_tx_count: tx_receipts.len() as u32, + root, + leaves, + } + } + + /// SHA3-384 两两合并默克尔树根 + fn compute_root(leaves: &[Vec]) -> Vec { + if leaves.len() == 1 { + return leaves[0].clone(); + } + let mut level = leaves.to_vec(); + while level.len() > 1 { + let mut next = Vec::new(); + let mut i = 0; + while i < level.len() { + let left = &level[i]; + let right = level.get(i + 1).unwrap_or(&level[i]); + let mut h = Sha3_384::new(); + h.update(left); + h.update(right); + next.push(h.finalize().to_vec()); + i += 2; + } + level = next; + } + level.into_iter().next().unwrap_or_else(|| vec![0u8; 48]) + } + + /// 验证树根是否与期望值一致 + pub fn verify_root(&self, expected: &[u8]) -> bool { + self.root == expected + } +} + +/// CBPP 多辖区区块头扩展字段 +/// +/// 嵌入标准区块头,记录该区块内所有跨辖区交易的合规证明。 +/// 节点将此扩展写入区块头即完成对所有涉及辖区宪法规则的背书(参与即共识)。 +/// 区块大小由实际交易数量决定,此扩展大小随之动态变化。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BlockJurisdictionExtension { + /// 辖区默克尔树根(48 字节 SHA3-384) + /// 若区块内无跨辖区交易,则为全零 + pub jurisdiction_merkle_root: Vec, + /// 涉及辖区数量 + pub jurisdiction_count: u32, + /// 跨辖区交易数量(体现"交易决定区块大小") + pub cross_tx_count: u32, + /// 宪法版本哈希(辖区政府授权 CA 签名的法律文件集合哈希) + /// 确保所有节点使用相同版本的真实法律规则出块 + pub constitution_version_hash: Vec, +} + +impl BlockJurisdictionExtension { + /// 从跨辖区交易收据集合构建区块头扩展 + pub fn build( + tx_receipts: &[TxJurisdictionReceipts], + constitution_version_hash: Vec, + ) -> Self { + if tx_receipts.is_empty() { + return Self { + jurisdiction_merkle_root: vec![0u8; 48], + jurisdiction_count: 0, + cross_tx_count: 0, + constitution_version_hash, + }; + } + + let tree = JurisdictionMerkleTree::build(tx_receipts); + Self { + jurisdiction_merkle_root: tree.root, + jurisdiction_count: tree.jurisdiction_count, + cross_tx_count: tree.cross_tx_count, + constitution_version_hash, + } + } + + /// 验证区块头扩展的合法性 + pub fn validate(&self, tx_receipts: &[TxJurisdictionReceipts]) -> BlockExtensionValidation { + // 纯链内交易区块 + if self.cross_tx_count == 0 { + return if self.jurisdiction_merkle_root == vec![0u8; 48] { + BlockExtensionValidation::Valid + } else { + BlockExtensionValidation::Invalid( + "跨辖区交易数为0但默克尔根非零".to_string(), + ) + }; + } + + // 重新计算默克尔树验证 + let tree = JurisdictionMerkleTree::build(tx_receipts); + + if tree.root != self.jurisdiction_merkle_root { + return BlockExtensionValidation::Invalid( + "jurisdiction_merkle_root 与交易收据不匹配".to_string(), + ); + } + if tree.jurisdiction_count != self.jurisdiction_count { + return BlockExtensionValidation::Invalid( + "辖区数量与默克尔树不一致".to_string(), + ); + } + if tree.cross_tx_count != self.cross_tx_count { + return BlockExtensionValidation::Invalid( + "跨辖区交易数量与默克尔树不一致".to_string(), + ); + } + + BlockExtensionValidation::Valid + } + + /// 是否为纯链内交易区块 + pub fn is_intra_chain_only(&self) -> bool { + self.cross_tx_count == 0 + } +} + +/// 区块头扩展验证结果 +#[derive(Debug, PartialEq)] +pub enum BlockExtensionValidation { + Valid, + Invalid(String), +} + +#[cfg(test)] +mod tests { + use super::*; + + fn tx_id(n: u8) -> Vec { vec![n; 48] } + fn cr(n: u8) -> CrHash { CrHash::new([n; 48]) } + + #[test] + fn test_single_cross_tx_two_jurisdictions() { + let mut r = TxJurisdictionReceipts::new(tx_id(1)); + r.add_receipt(784, cr(10)); // UAE + r.add_receipt(156, cr(20)); // China + + let ext = BlockJurisdictionExtension::build(&[r.clone()], vec![0xAB; 48]); + assert_eq!(ext.cross_tx_count, 1); + assert_eq!(ext.jurisdiction_count, 2); + assert_ne!(ext.jurisdiction_merkle_root, vec![0u8; 48]); + assert_eq!(ext.validate(&[r]), BlockExtensionValidation::Valid); + } + + #[test] + fn test_intra_chain_block() { + let ext = BlockJurisdictionExtension::build(&[], vec![0xAB; 48]); + assert!(ext.is_intra_chain_only()); + assert_eq!(ext.validate(&[]), BlockExtensionValidation::Valid); + } + + #[test] + fn test_dynamic_size_by_tx_count() { + // 交易决定区块大小:10笔跨辖区交易 vs 1笔 + let mut receipts_10 = Vec::new(); + for i in 0..10u8 { + let mut r = TxJurisdictionReceipts::new(tx_id(i)); + r.add_receipt(784, cr(i)); + r.add_receipt(156, cr(i + 50)); + receipts_10.push(r); + } + let ext_10 = BlockJurisdictionExtension::build(&receipts_10, vec![1u8; 48]); + + let mut r1 = TxJurisdictionReceipts::new(tx_id(0)); + r1.add_receipt(784, cr(0)); + r1.add_receipt(156, cr(50)); + let ext_1 = BlockJurisdictionExtension::build(&[r1], vec![1u8; 48]); + + // 10笔交易的默克尔根与1笔不同,体现动态性 + assert_ne!(ext_10.jurisdiction_merkle_root, ext_1.jurisdiction_merkle_root); + assert_eq!(ext_10.cross_tx_count, 10); + assert_eq!(ext_1.cross_tx_count, 1); + + assert_eq!(ext_10.validate(&receipts_10), BlockExtensionValidation::Valid); + } + + #[test] + fn test_tampered_receipt_rejected() { + let mut r = TxJurisdictionReceipts::new(tx_id(1)); + r.add_receipt(784, cr(10)); + r.add_receipt(156, cr(20)); + let ext = BlockJurisdictionExtension::build(&[r], vec![0xAB; 48]); + + // 篡改 CR + let mut tampered = TxJurisdictionReceipts::new(tx_id(1)); + tampered.add_receipt(784, cr(99)); + tampered.add_receipt(156, cr(20)); + assert!(matches!(ext.validate(&[tampered]), BlockExtensionValidation::Invalid(_))); + } + + #[test] + fn test_participation_is_consensus_no_multisig() { + // 参与即共识:节点将 receipts 打包进区块头即完成背书,无需多签 + let mut r = TxJurisdictionReceipts::new(tx_id(42)); + r.add_receipt(784, cr(1)); // 单节点独立写入,无需其他节点确认 + let ext = BlockJurisdictionExtension::build(&[r.clone()], vec![1u8; 48]); + // 验证通过即代表共识达成 + assert_eq!(ext.validate(&[r]), BlockExtensionValidation::Valid); + } + + #[test] + fn test_constitution_version_is_real_law_hash() { + // 宪法版本哈希代表辖区政府授权CA签名的真实法律文件集合 + // 不是链上治理投票结果 + let law_hash = vec![0xDE; 48]; // 模拟真实法律文件哈希 + let ext = BlockJurisdictionExtension::build(&[], law_hash.clone()); + assert_eq!(ext.constitution_version_hash, law_hash); + } +} diff --git a/nac-cbpp-l0/src/lib.rs b/nac-cbpp-l0/src/lib.rs index 749a1df..890ab8c 100644 --- a/nac-cbpp-l0/src/lib.rs +++ b/nac-cbpp-l0/src/lib.rs @@ -48,3 +48,4 @@ mod tests { assert_eq!(stats.total_connections, 0); } } +pub mod jurisdiction_block; diff --git a/nac-cee/Cargo.lock b/nac-cee/Cargo.lock index 020635c..f877edb 100644 --- a/nac-cee/Cargo.lock +++ b/nac-cee/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + [[package]] name = "arrayref" version = "0.3.9" @@ -344,6 +350,7 @@ name = "nac-cee" version = "0.1.0" dependencies = [ "nac-udm", + "nac-upgrade-framework", "serde", "serde_json", "thiserror 1.0.69", @@ -357,6 +364,7 @@ dependencies = [ "chrono", "hex", "log", + "nac-upgrade-framework", "primitive-types", "serde", "serde_json", @@ -365,6 +373,20 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "nac-upgrade-framework" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "hex", + "log", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", +] + [[package]] name = "num-traits" version = "0.2.19" diff --git a/nac-cee/src/cross_jurisdiction_cluster.rs b/nac-cee/src/cross_jurisdiction_cluster.rs new file mode 100644 index 0000000..ac5c28c --- /dev/null +++ b/nac-cee/src/cross_jurisdiction_cluster.rs @@ -0,0 +1,469 @@ +// nac-cee/src/cross_jurisdiction_cluster.rs +// CEE 跨辖区共享集群 +// +// 设计原则(CBPP 四大原则): +// 参与即是共识 — 每个辖区 CEE 节点独立执行本辖区插件,生成本辖区 CR +// 节点将 CR 打包进区块即是背书,无需多签,无需其他辖区确认 +// 宪法即是规则 — 辖区插件规则来源于辖区政府授权 CA 签名的真实法律文件 +// 不是链上治理决定,不是链上投票结果 +// 约法即是治法 — CEE 执行结果直接约束交易合法性,无宪法外规则 +// 节点产生区块,交易决定区块大小 — CEE 处理的交易数量决定 CR 集合大小 + +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Sha3_384}; +use std::collections::HashMap; + +pub type JurisdictionId = u32; + +/// 辖区插件元数据 +/// +/// 插件规则来源于辖区政府授权 CA 签名的真实法律文件。 +/// 插件更新必须经辖区监管机构授权签名,不是链上治理决定。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JurisdictionPlugin { + /// 辖区 ID + pub jurisdiction: JurisdictionId, + /// 插件版本(由辖区政府授权 CA 签名时确定) + pub version: u32, + /// 插件内容哈希(SHA3-384,用于验证插件完整性) + pub content_hash: Vec, + /// 辖区政府授权 CA 签名(证明插件规则来自真实法律) + pub ca_signature: Vec, + /// 对应的法律文件哈希集合(链上存证的真实法规) + pub law_document_hashes: Vec>, + /// 插件生效时间戳 + pub effective_timestamp: u64, +} + +impl JurisdictionPlugin { + /// 验证插件是否由合法 CA 签名(简化版,生产环境需完整 PKI 验证) + pub fn is_ca_signed(&self) -> bool { + !self.ca_signature.is_empty() && !self.content_hash.is_empty() + } +} + +/// 单辖区 CEE 执行结果 +/// +/// 由该辖区的 CEE 节点独立执行本辖区插件后生成。 +/// 参与即共识:节点将此结果打包进区块即完成背书,无需其他辖区节点确认。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JurisdictionCrResult { + /// 辖区 ID + pub jurisdiction: JurisdictionId, + /// 宪法收据哈希(SHA3-384,48 字节) + pub cr_hash: Vec, + /// 执行的插件版本 + pub plugin_version: u32, + /// 执行时间戳 + pub timestamp: u64, + /// 执行结果:通过/拒绝 + pub approved: bool, + /// 拒绝原因(若 approved = false) + pub rejection_reason: Option, +} + +impl JurisdictionCrResult { + /// 生成 CR 哈希 + /// CR = SHA3-384(jurisdiction_id || plugin_version || tx_id || approved_byte || timestamp) + pub fn compute_cr_hash( + jurisdiction: JurisdictionId, + plugin_version: u32, + tx_id: &[u8], + approved: bool, + timestamp: u64, + ) -> Vec { + let mut hasher = Sha3_384::new(); + hasher.update(&jurisdiction.to_be_bytes()); + hasher.update(&plugin_version.to_be_bytes()); + hasher.update(tx_id); + hasher.update(&[if approved { 1u8 } else { 0u8 }]); + hasher.update(×tamp.to_be_bytes()); + hasher.finalize().to_vec() + } +} + +/// 跨辖区交易的完整 CEE 执行结果 +/// +/// 包含所有涉及辖区的独立 CR。 +/// 每个辖区的 CR 由该辖区 CEE 节点独立生成,互不依赖。 +/// 交易最终合法性:所有涉及辖区的 CR 均为 approved = true。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CrossJurisdictionCeeResult { + /// 交易 ID + pub tx_id: Vec, + /// 各辖区独立执行结果(辖区 → CR 结果) + pub jurisdiction_results: HashMap, + /// 整体是否通过(所有辖区 CR 均通过) + pub overall_approved: bool, +} + +impl CrossJurisdictionCeeResult { + pub fn new(tx_id: Vec) -> Self { + Self { + tx_id, + jurisdiction_results: HashMap::new(), + overall_approved: false, + } + } + + /// 添加某辖区的独立 CR 执行结果 + /// 各辖区独立添加,无需等待其他辖区(参与即共识) + pub fn add_jurisdiction_result(&mut self, result: JurisdictionCrResult) { + let approved = result.approved; + self.jurisdiction_results.insert(result.jurisdiction, result); + // 重新计算整体结果:所有辖区均通过才算通过 + self.overall_approved = self + .jurisdiction_results + .values() + .all(|r| r.approved); + // 如果新加入的辖区拒绝,立即标记整体失败 + if !approved { + self.overall_approved = false; + } + } + + /// 检查指定辖区的 CR 是否已就绪 + pub fn has_result_for(&self, jurisdiction: JurisdictionId) -> bool { + self.jurisdiction_results.contains_key(&jurisdiction) + } + + /// 获取所有已完成的辖区列表 + pub fn completed_jurisdictions(&self) -> Vec { + self.jurisdiction_results.keys().copied().collect() + } +} + +/// CEE 跨辖区共享集群 +/// +/// 并行加载多个辖区插件,各辖区 CEE 节点独立执行本辖区插件。 +/// 不存在"多签"机制——每个辖区的 CR 由该辖区节点独立出具。 +/// 节点将所有 CR 打包进区块头即完成对所有辖区规则的背书(参与即共识)。 +pub struct CrossJurisdictionCeeCluster { + /// 已加载的辖区插件(辖区 → 插件元数据) + plugins: HashMap, + /// 本节点所属辖区 + local_jurisdiction: JurisdictionId, +} + +impl CrossJurisdictionCeeCluster { + pub fn new(local_jurisdiction: JurisdictionId) -> Self { + Self { + plugins: HashMap::new(), + local_jurisdiction, + } + } + + /// 加载辖区插件 + /// 插件必须有合法 CA 签名(来自辖区政府授权的真实法律文件) + pub fn load_plugin(&mut self, plugin: JurisdictionPlugin) -> Result<(), String> { + if !plugin.is_ca_signed() { + return Err(format!( + "辖区 {} 插件未经授权 CA 签名,拒绝加载:规则必须来自真实法律", + plugin.jurisdiction + )); + } + self.plugins.insert(plugin.jurisdiction, plugin); + Ok(()) + } + + /// 执行本辖区的 CEE 验证(本节点只负责本辖区) + /// + /// 参与即共识:本节点执行本辖区插件,生成本辖区 CR, + /// 打包进区块即完成背书。无需等待其他辖区节点。 + pub fn execute_local_jurisdiction( + &self, + tx_id: &[u8], + tx_data: &TransactionData, + timestamp: u64, + ) -> Result { + let plugin = self.plugins.get(&self.local_jurisdiction).ok_or_else(|| { + format!("本辖区 {} 插件未加载", self.local_jurisdiction) + })?; + + // 执行本辖区规则验证 + let (approved, rejection_reason) = + self.execute_plugin_rules(plugin, tx_data); + + let cr_hash = JurisdictionCrResult::compute_cr_hash( + self.local_jurisdiction, + plugin.version, + tx_id, + approved, + timestamp, + ); + + Ok(JurisdictionCrResult { + jurisdiction: self.local_jurisdiction, + cr_hash, + plugin_version: plugin.version, + timestamp, + approved, + rejection_reason, + }) + } + + /// 执行指定辖区的 CEE 验证(用于共享集群模式) + /// + /// 在共享集群中,一个 CEE 节点可以为多个辖区执行验证, + /// 但每个辖区的 CR 仍然是独立生成的,互不依赖。 + pub fn execute_for_jurisdiction( + &self, + jurisdiction: JurisdictionId, + tx_id: &[u8], + tx_data: &TransactionData, + timestamp: u64, + ) -> Result { + let plugin = self.plugins.get(&jurisdiction).ok_or_else(|| { + format!("辖区 {} 插件未加载", jurisdiction) + })?; + + let (approved, rejection_reason) = + self.execute_plugin_rules(plugin, tx_data); + + let cr_hash = JurisdictionCrResult::compute_cr_hash( + jurisdiction, + plugin.version, + tx_id, + approved, + timestamp, + ); + + Ok(JurisdictionCrResult { + jurisdiction, + cr_hash, + plugin_version: plugin.version, + timestamp, + approved, + rejection_reason, + }) + } + + /// 并行执行所有涉及辖区的验证(共享集群核心方法) + /// + /// 各辖区独立执行,各自生成独立 CR,互不依赖。 + /// 这是"参与即共识"的具体实现:节点将所有 CR 打包进区块即完成背书。 + pub fn execute_all_jurisdictions( + &self, + tx_id: &[u8], + tx_data: &TransactionData, + target_jurisdictions: &[JurisdictionId], + timestamp: u64, + ) -> CrossJurisdictionCeeResult { + let mut result = CrossJurisdictionCeeResult::new(tx_id.to_vec()); + + for &jid in target_jurisdictions { + match self.execute_for_jurisdiction(jid, tx_id, tx_data, timestamp) { + Ok(cr_result) => { + result.add_jurisdiction_result(cr_result); + } + Err(e) => { + // 插件未加载视为该辖区拒绝(宪法即是规则:无插件即无法验证) + result.add_jurisdiction_result(JurisdictionCrResult { + jurisdiction: jid, + cr_hash: vec![0u8; 48], + plugin_version: 0, + timestamp, + approved: false, + rejection_reason: Some(format!("插件未加载: {}", e)), + }); + } + } + } + + result + } + + /// 执行辖区插件规则(简化版规则引擎) + /// + /// 生产环境中此处加载 WASM 沙箱执行辖区插件(A48 条款约束) + fn execute_plugin_rules( + &self, + plugin: &JurisdictionPlugin, + tx_data: &TransactionData, + ) -> (bool, Option) { + // 基础合规检查:金额限制(来自辖区法律文件的规则) + if tx_data.amount > tx_data.jurisdiction_amount_limit { + return ( + false, + Some(format!( + "交易金额 {} 超过辖区 {} 限额 {}(来源:辖区法律文件哈希 {:?})", + tx_data.amount, + plugin.jurisdiction, + tx_data.jurisdiction_amount_limit, + plugin.law_document_hashes.first() + )), + ); + } + + // KYC 级别检查 + if tx_data.kyc_level < tx_data.required_kyc_level { + return ( + false, + Some(format!( + "KYC 级别不足:需要 {},实际 {}", + tx_data.required_kyc_level, tx_data.kyc_level + )), + ); + } + + (true, None) + } + + /// 获取已加载的辖区列表 + pub fn loaded_jurisdictions(&self) -> Vec { + self.plugins.keys().copied().collect() + } +} + +/// 交易数据(用于 CEE 规则验证) +#[derive(Debug, Clone)] +pub struct TransactionData { + pub amount: u64, + pub jurisdiction_amount_limit: u64, + pub kyc_level: u8, + pub required_kyc_level: u8, + pub asset_type: String, +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_plugin(jurisdiction: JurisdictionId, version: u32) -> JurisdictionPlugin { + JurisdictionPlugin { + jurisdiction, + version, + content_hash: vec![0xAB; 48], + ca_signature: vec![0xCD; 64], // 模拟 CA 签名 + law_document_hashes: vec![vec![0xEF; 48]], + effective_timestamp: 1700000000, + } + } + + fn make_tx_data(amount: u64, limit: u64) -> TransactionData { + TransactionData { + amount, + jurisdiction_amount_limit: limit, + kyc_level: 2, + required_kyc_level: 1, + asset_type: "RWA".to_string(), + } + } + + #[test] + fn test_plugin_requires_ca_signature() { + // 宪法即是规则:插件必须有 CA 签名,规则来自真实法律 + let mut cluster = CrossJurisdictionCeeCluster::new(784); + let mut plugin = make_plugin(784, 100); + plugin.ca_signature = vec![]; // 无签名 + assert!(cluster.load_plugin(plugin).is_err()); + } + + #[test] + fn test_each_jurisdiction_independent_cr() { + // 参与即共识:各辖区独立生成 CR,互不依赖 + let mut cluster = CrossJurisdictionCeeCluster::new(784); + cluster.load_plugin(make_plugin(784, 100)).unwrap(); + cluster.load_plugin(make_plugin(156, 100)).unwrap(); + cluster.load_plugin(make_plugin(840, 100)).unwrap(); + + let tx_id = vec![1u8; 48]; + let tx_data = make_tx_data(1000, 100000); + + let result = cluster.execute_all_jurisdictions( + &tx_id, + &tx_data, + &[784, 156, 840], + 1700000000, + ); + + // 三个辖区各自独立生成 CR + assert_eq!(result.completed_jurisdictions().len(), 3); + assert!(result.has_result_for(784)); + assert!(result.has_result_for(156)); + assert!(result.has_result_for(840)); + assert!(result.overall_approved); + + // 各辖区 CR 哈希不同(各自独立计算) + let cr_784 = &result.jurisdiction_results[&784].cr_hash; + let cr_156 = &result.jurisdiction_results[&156].cr_hash; + assert_ne!(cr_784, cr_156); + } + + #[test] + fn test_one_jurisdiction_rejection_fails_overall() { + // 任一辖区拒绝,整体失败(宪法即是规则) + let mut cluster = CrossJurisdictionCeeCluster::new(784); + cluster.load_plugin(make_plugin(784, 100)).unwrap(); + cluster.load_plugin(make_plugin(156, 100)).unwrap(); + + let tx_id = vec![2u8; 48]; + // 金额超过辖区限额(模拟辖区法律规定的限额) + let tx_data = make_tx_data(999999, 1000); + + let result = cluster.execute_all_jurisdictions( + &tx_id, + &tx_data, + &[784, 156], + 1700000000, + ); + + assert!(!result.overall_approved); + // 两个辖区都拒绝 + assert!(!result.jurisdiction_results[&784].approved); + assert!(!result.jurisdiction_results[&156].approved); + } + + #[test] + fn test_no_multisig_each_cr_independent() { + // 验证"无多签":每个辖区的 CR 哈希独立计算,不依赖其他辖区 + let mut cluster = CrossJurisdictionCeeCluster::new(784); + cluster.load_plugin(make_plugin(784, 100)).unwrap(); + + let tx_id = vec![3u8; 48]; + let tx_data = make_tx_data(500, 100000); + + // 单独执行辖区 784,不需要等待其他辖区 + let cr = cluster.execute_local_jurisdiction(&tx_id, &tx_data, 1700000000); + assert!(cr.is_ok()); + let cr = cr.unwrap(); + assert!(cr.approved); + assert_eq!(cr.jurisdiction, 784); + assert!(!cr.cr_hash.is_empty()); + } + + #[test] + fn test_missing_plugin_treated_as_rejection() { + // 无插件 = 无法验证 = 拒绝(宪法即是规则:无规则即违规) + let cluster = CrossJurisdictionCeeCluster::new(784); + // 不加载任何插件 + let result = cluster.execute_all_jurisdictions( + &vec![4u8; 48], + &make_tx_data(100, 100000), + &[784], + 1700000000, + ); + assert!(!result.overall_approved); + assert!(!result.jurisdiction_results[&784].approved); + } + + #[test] + fn test_transaction_count_determines_cr_set_size() { + // 交易决定区块大小:处理的交易数量决定 CR 集合大小 + let mut cluster = CrossJurisdictionCeeCluster::new(784); + cluster.load_plugin(make_plugin(784, 100)).unwrap(); + cluster.load_plugin(make_plugin(156, 100)).unwrap(); + + // 单辖区交易 → 1个 CR + let result_single = cluster.execute_all_jurisdictions( + &vec![5u8; 48], &make_tx_data(100, 100000), &[784], 1700000000, + ); + assert_eq!(result_single.jurisdiction_results.len(), 1); + + // 双辖区交易 → 2个独立 CR + let result_double = cluster.execute_all_jurisdictions( + &vec![6u8; 48], &make_tx_data(100, 100000), &[784, 156], 1700000000, + ); + assert_eq!(result_double.jurisdiction_results.len(), 2); + } +} diff --git a/nac-cee/src/lib.rs b/nac-cee/src/lib.rs index 6539c61..a84aa7f 100644 --- a/nac-cee/src/lib.rs +++ b/nac-cee/src/lib.rs @@ -312,3 +312,4 @@ mod tests { assert_eq!(stats.size, 0); } } +pub mod cross_jurisdiction_cluster; diff --git a/nac-constitution-clauses/Cargo.lock b/nac-constitution-clauses/Cargo.lock index a8037ad..7079a33 100644 --- a/nac-constitution-clauses/Cargo.lock +++ b/nac-constitution-clauses/Cargo.lock @@ -426,6 +426,7 @@ name = "nac-constitution-clauses" version = "0.1.0" dependencies = [ "nac-udm", + "nac-upgrade-framework", "serde", "serde_json", "sha3", @@ -440,12 +441,27 @@ dependencies = [ "chrono", "hex", "log", + "nac-upgrade-framework", "primitive-types", "serde", "serde_json", "sha2", "sha3", - "thiserror", + "thiserror 2.0.18", +] + +[[package]] +name = "nac-upgrade-framework" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "hex", + "log", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", ] [[package]] @@ -727,13 +743,33 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.18", +] + +[[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]] diff --git a/nac-constitution-clauses/src/upgrade.rs b/nac-constitution-clauses/src/upgrade.rs deleted file mode 100644 index 03eeb13..0000000 --- a/nac-constitution-clauses/src/upgrade.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! 模块升级实现 - -use nac_upgrade_framework::{ - traits::Upgradeable, UpgradeData, UpgradeRecord, Version, Result, UpgradeError, -}; - -// 注意:需要在主结构体中添加以下字段: -// - version: Version -// - upgrade_history: Vec -// -// 并实现 do_upgrade 方法来执行实际的升级逻辑 - -// 使用宏快速实现Upgradeable trait: -// nac_upgrade_framework::impl_upgradeable!(YourStruct, "module-name", Version::new(1, 0, 0)); diff --git a/nac-constitution-clauses/src/upgrade/mod.rs b/nac-constitution-clauses/src/upgrade/mod.rs index e440a0f..b68fb12 100644 --- a/nac-constitution-clauses/src/upgrade/mod.rs +++ b/nac-constitution-clauses/src/upgrade/mod.rs @@ -197,17 +197,20 @@ pub struct UpgradeManager { proposals: HashMap, /// 下一个提案ID next_proposal_id: u64, - /// 宪法审查委员会成员 - review_committee: Vec, + /// 授权辖区CA列表(CBPP原则:宪法修正须经辖区授权CA签名,约法即是治法) + /// 不是委员会投票,而是辖区监管机构的数字签名授权 + authorized_jurisdiction_cas: Vec, } impl UpgradeManager { /// 创建新的升级管理器 - pub fn new(review_committee: Vec) -> Self { + /// 创建升级管理器 + /// authorized_cas: 授权辖区CA的DID列表(由辖区监管机构颁发,非投票委员会) + pub fn new(authorized_jurisdiction_cas: Vec) -> Self { Self { proposals: HashMap::new(), next_proposal_id: 1, - review_committee, + authorized_jurisdiction_cas, } } diff --git a/nac-constitution/clauses/amendments_v2_patch.cnnl b/nac-constitution/clauses/amendments_v2_patch.cnnl new file mode 100644 index 0000000..ac787dc --- /dev/null +++ b/nac-constitution/clauses/amendments_v2_patch.cnnl @@ -0,0 +1,167 @@ +// NAC公链宪法增补条款 v2 补丁 +// Issue #71 | 版本: 2.0 | 新增 A44-A52 条款 + 修正 A42 +// 基于《NAC公链多辖区节点共享方案与技术落地白皮书》 +// +// CBPP 四大原则: +// 约法即是治法 — 宪法条款直接约束链行为,无宪法外治理 +// 宪法即是规则 — 规则来源于辖区真实法律,不是链上投票 +// 参与即是共识 — 节点参与出块即是对宪法规则的背书 +// 节点产生区块,交易决定区块大小 — 动态区块,无固定大小 + +// ============================================================ +// 修正条款(A42 修正版) +// 原版错误:AI模型更新经过"治理投票" +// 修正原因:链上投票不能改变国家法律;AI模型规则来自辖区监管机构 +// ============================================================ + +clause A42_AiModelUpdate_v2 + name: "AI模型更新授权" + description: "AI模型更新必须经辖区监管机构授权签名,不经链上投票" + // 约法即是治法:规则来自辖区真实监管要求,不是链上治理决定 + predicate: ai_model.update_has_regulator_signature == true + obligation: system.require_regulator_signature_for_ai_update per_epoch + test: A42v2_test_model_regulator_auth + // 替换原 A42_AiModelUpdate(原版"治理投票"机制违反CBPP原则) + supersedes: A42_AiModelUpdate + +// ============================================================ +// 第七章:多辖区节点共享条款(A44-A49) +// ============================================================ + +clause A44_NodeSharingAllowed + name: "多辖区节点共享许可" + description: "允许不同辖区节点共享物理基础设施,前提是各辖区插件独立运行" + // 宪法即是规则:共享许可由宪法条款授权,不是链上投票 + predicate: node.shared_infrastructure implies node.plugins_isolated + obligation: system.enforce_plugin_isolation_on_shared_nodes per_block + test: A44_test_node_sharing_with_isolation + +clause A45_ResourceAllocationByNegotiation + name: "资源分配辖区协商" + description: "共享节点资源分配方案由辖区代表协商,协商结果经辖区政府授权CA签名后成为宪法条款" + // 约法即是治法:协商结果由辖区政府授权CA签名,直接成为宪法条款,无需链上投票 + predicate: resource.allocation_has_ca_signature == true + obligation: system.enforce_ca_signed_resource_allocation per_block + test: A45_test_resource_allocation_ca_signed + +clause A46_CrossJurisdictionBlockProduction + name: "跨辖区区块生产规则" + description: "涉及多辖区的区块必须在区块头包含所有涉及辖区的独立CR哈希默克尔树根" + // 参与即是共识:节点将jurisdiction_merkle_root写入区块头即是对所有辖区CR的背书 + // 节点产生区块,交易决定区块大小:默克尔树大小由实际跨辖区交易数量决定 + predicate: block.has_cross_jurisdiction_txs implies block.has_jurisdiction_merkle_root + obligation: block.require_jurisdiction_merkle_root per_block + test: A46_test_jurisdiction_merkle_root_required + +clause A47_GidsJurisdictionProof + name: "GIDS辖区证明绑定" + description: "节点身份必须绑定辖区证明(辖区政府授权CA签名)和当前插件哈希" + // 宪法即是规则:节点身份由辖区政府授权CA签名确认,不是链上治理决定 + predicate: node.gids_has_jurisdiction_proof == true + obligation: system.require_gids_jurisdiction_proof per_block + test: A47_test_gids_jurisdiction_proof + +clause A48_WasmPluginSandbox + name: "WASM插件沙箱约束" + description: "辖区规则插件在WASM沙箱中执行,资源限制由宪法条款规定" + // 约法即是治法:沙箱资源限制是宪法条款,不是运行时配置 + predicate: plugin.execution_env == "WASM_SANDBOX" + obligation: system.enforce_wasm_sandbox per_block + test: A48_test_wasm_sandbox_enforced + +clause A49_CeeSharedClusterIndependentCr + name: "CEE共享集群独立CR原则" + description: "CEE共享集群并行执行多辖区插件,各辖区独立出具CR,不存在多签机制" + // 参与即是共识:各辖区CEE节点独立执行本辖区插件,生成本辖区CR + // 节点将CR打包进区块即完成背书,无需多签,无需其他辖区确认 + predicate: cee.cross_jurisdiction_cr_independent == true + obligation: cee.enforce_independent_cr_per_jurisdiction per_block + test: A49_test_cee_independent_cr_no_multisig + +// ============================================================ +// 第八章:宪法法院条款(A50-A52) +// ============================================================ + +clause A50_ConstitutionalCourtJurisdiction + name: "宪法法院管辖范围" + description: "宪法法院负责解决跨辖区法律冲突,裁决依据辖区已注册的真实法律文件哈希" + // 约法即是治法:宪法法院是法律执行机构,不是立法机构 + // 链上投票不能改变国家法律,因此裁决不经过投票 + predicate: court.ruling_basis == "registered_law_hashes" + obligation: court.require_law_hash_basis per_epoch + test: A50_test_court_ruling_based_on_real_law + +clause A51_CourtRulingImmediateEffect + name: "宪法法院裁决即时生效" + description: "宪法法院裁决发布后立即生效,无需链上投票确认" + // 约法即是治法:裁决即是规则,无需额外确认机制 + // 链上投票不能改变国家法律,裁决依据真实法律,无需投票背书 + predicate: court.ruling_effective_immediately == true + obligation: system.enforce_ruling_without_vote per_block + test: A51_test_ruling_no_vote_required + +clause A52_PluginUpdateRequiresRegulatoryAuth + name: "插件更新监管授权" + description: "辖区规则插件更新必须经辖区监管机构授权签名,反映真实法律变更" + // 宪法即是规则:插件规则来自辖区真实法律 + // 插件更新 = 法律变更,必须由辖区政府授权CA签名,不是链上治理决定 + predicate: plugin.update_has_regulatory_signature == true + obligation: system.require_regulatory_signature_for_plugin_update per_epoch + test: A52_test_plugin_update_regulatory_auth + +// ============================================================ +// 测试块(新增条款) +// ============================================================ + +test A42v2_test_model_regulator_auth { + assert ai_model.update_has_regulator_signature == true + // 验证:AI模型更新不经链上投票,而是经辖区监管机构授权签名 +} + +test A44_test_node_sharing_with_isolation { + assert node.shared_infrastructure implies node.plugins_isolated + // 验证:共享节点上各辖区插件严格隔离运行 +} + +test A45_test_resource_allocation_ca_signed { + assert resource.allocation_has_ca_signature == true + // 验证:资源分配方案有辖区政府授权CA签名,不是链上投票结果 +} + +test A46_test_jurisdiction_merkle_root_required { + assert block.has_cross_jurisdiction_txs implies block.has_jurisdiction_merkle_root + // 验证:跨辖区区块必须包含jurisdiction_merkle_root + // 验证:默克尔树大小由实际交易数量决定(交易决定区块大小) +} + +test A47_test_gids_jurisdiction_proof { + assert node.gids_has_jurisdiction_proof == true + // 验证:节点身份绑定辖区政府授权CA签名的辖区证明 +} + +test A48_test_wasm_sandbox_enforced { + assert plugin.execution_env == "WASM_SANDBOX" + // 验证:辖区插件在WASM沙箱中执行 +} + +test A49_test_cee_independent_cr_no_multisig { + assert cee.cross_jurisdiction_cr_independent == true + // 验证:各辖区CR独立生成,不存在多签机制 + // 参与即是共识:节点打包CR进区块即完成背书 +} + +test A50_test_court_ruling_based_on_real_law { + assert court.ruling_basis == "registered_law_hashes" + // 验证:裁决依据辖区真实法律文件哈希,不是链上治理决定 +} + +test A51_test_ruling_no_vote_required { + assert court.ruling_effective_immediately == true + // 验证:裁决即时生效,无需链上投票 + // 链上投票不能改变国家法律 +} + +test A52_test_plugin_update_regulatory_auth { + assert plugin.update_has_regulatory_signature == true + // 验证:插件更新必须有辖区监管机构授权签名 +} diff --git a/nac-csnp-l0/src/gids_jurisdiction_proof.rs b/nac-csnp-l0/src/gids_jurisdiction_proof.rs new file mode 100644 index 0000000..a37f84c --- /dev/null +++ b/nac-csnp-l0/src/gids_jurisdiction_proof.rs @@ -0,0 +1,415 @@ +// nac-csnp-l0/src/gids_jurisdiction_proof.rs +// GIDS 辖区证明增强 + 宪法法院链上裁决 +// +// 核心原则: +// 约法即是治法 — 宪法法院裁决依据辖区真实法律文件哈希,裁决即生效 +// 宪法即是规则 — 辖区规则来自政府授权 CA 签名的真实法律,不是链上投票 +// 链上投票不能改变国家法律 — 宪法法院是法律执行机构,不是立法机构 +// 参与即是共识 — 节点将裁决记录打包进区块即是对裁决合法性的背书 + +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Sha3_384}; + +pub type JurisdictionId = u32; + +/// 辖区证明(GIDS 增强版) +/// +/// 节点身份绑定辖区证明 + 插件哈希, +/// 证明来自辖区政府授权 CA 签名,不是链上治理决定。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JurisdictionProof { + /// 节点 DID(全局身份标识符) + pub node_did: Vec, + /// 所属辖区 + pub jurisdiction: JurisdictionId, + /// 辖区政府授权 CA 签名(证明节点合法注册于该辖区) + pub jurisdiction_ca_signature: Vec, + /// 当前加载的辖区插件哈希(SHA3-384) + pub plugin_hash: Vec, + /// 插件版本 + pub plugin_version: u32, + /// 辖区政府对插件版本的授权签名 + /// 插件更新必须经辖区监管机构授权,不是链上治理决定 + pub plugin_authorization_signature: Vec, + /// 证明生效时间戳 + pub effective_timestamp: u64, + /// 证明过期时间戳(辖区政府设定,不是链上投票决定) + pub expiry_timestamp: u64, +} + +impl JurisdictionProof { + /// 验证辖区证明的基本合法性 + pub fn is_valid(&self, current_timestamp: u64) -> ProofValidation { + if self.jurisdiction_ca_signature.is_empty() { + return ProofValidation::Invalid("缺少辖区 CA 签名".to_string()); + } + if self.plugin_authorization_signature.is_empty() { + return ProofValidation::Invalid("缺少插件授权签名".to_string()); + } + if self.plugin_hash.is_empty() { + return ProofValidation::Invalid("缺少插件哈希".to_string()); + } + if current_timestamp > self.expiry_timestamp { + return ProofValidation::Expired { + expired_at: self.expiry_timestamp, + }; + } + if current_timestamp < self.effective_timestamp { + return ProofValidation::NotYetEffective { + effective_at: self.effective_timestamp, + }; + } + ProofValidation::Valid + } + + /// 计算证明哈希(用于链上存证) + pub fn compute_hash(&self) -> Vec { + let mut hasher = Sha3_384::new(); + hasher.update(&self.node_did); + hasher.update(&self.jurisdiction.to_be_bytes()); + hasher.update(&self.plugin_hash); + hasher.update(&self.plugin_version.to_be_bytes()); + hasher.update(&self.effective_timestamp.to_be_bytes()); + hasher.update(&self.expiry_timestamp.to_be_bytes()); + hasher.finalize().to_vec() + } +} + +/// 辖区证明验证结果 +#[derive(Debug, PartialEq)] +pub enum ProofValidation { + Valid, + Invalid(String), + Expired { expired_at: u64 }, + NotYetEffective { effective_at: u64 }, +} + +/// 宪法法院裁决 +/// +/// 宪法法院是链上的法律执行机构,不是立法机构。 +/// 裁决依据:辖区已注册的真实法律文件哈希(链上存证)。 +/// 裁决即生效:无需链上投票确认(约法即是治法)。 +/// 链上投票不能改变国家法律,因此裁决不经过投票。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ConstitutionalCourtRuling { + /// 裁决 ID(SHA3-384) + pub ruling_id: Vec, + /// 案件类型 + pub case_type: CourtCaseType, + /// 涉及辖区 + pub jurisdictions: Vec, + /// 裁决依据的法律文件哈希列表(链上存证的真实法规) + /// 这些哈希对应辖区政府授权 CA 签名的真实法律文件 + pub legal_basis_hashes: Vec>, + /// 裁决结论 + pub conclusion: RulingConclusion, + /// 裁决理由(引用具体法律条款) + pub reasoning: String, + /// 裁决生效时间戳(裁决即生效,无需等待投票) + pub effective_timestamp: u64, + /// 执行截止时间戳(由宪法条款规定,不是链上投票决定) + pub execution_deadline: u64, + /// 裁决机构签名(宪法法院节点的私钥签名) + pub court_signature: Vec, +} + +/// 宪法法院案件类型 +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub enum CourtCaseType { + /// 辖区规则冲突(不同辖区法律对同一资产类型有互斥要求) + JurisdictionRuleConflict, + /// 节点违规(节点行为违反宪法条款) + NodeViolation, + /// 插件合法性争议(插件规则是否符合辖区真实法律) + PluginLegalityDispute, + /// 跨辖区资产合规争议 + CrossJurisdictionComplianceDispute, +} + +/// 裁决结论 +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub enum RulingConclusion { + /// 支持(申请方合规) + Upheld, + /// 驳回(申请方违规) + Dismissed, + /// 辖区规则冲突:按优先级辖区规则执行 + ConflictResolved { + /// 优先适用的辖区(通常为资产注册辖区) + primary_jurisdiction: JurisdictionId, + }, + /// 要求辖区更新插件(辖区法律已变更,插件需同步) + PluginUpdateRequired { + jurisdiction: JurisdictionId, + /// 新插件必须经辖区政府重新授权签名 + required_by: u64, + }, +} + +/// 宪法法院 +/// +/// 负责解决跨辖区法律冲突,裁决依据辖区真实法律文件。 +/// 裁决即生效,无需链上投票(链上投票不能改变国家法律)。 +pub struct ConstitutionalCourt { + /// 已注册的辖区法律文件哈希(辖区 → 法律文件哈希列表) + /// 这些哈希对应辖区政府授权 CA 签名的真实法律文件 + registered_law_hashes: std::collections::HashMap>>, + /// 已生效的裁决记录 + rulings: Vec, +} + +impl ConstitutionalCourt { + pub fn new() -> Self { + Self { + registered_law_hashes: std::collections::HashMap::new(), + rulings: Vec::new(), + } + } + + /// 注册辖区法律文件哈希 + /// + /// 法律文件由辖区政府授权 CA 签名后上传,哈希存证于链上。 + /// 这是宪法法院裁决的唯一依据。 + pub fn register_law_documents( + &mut self, + jurisdiction: JurisdictionId, + law_hashes: Vec>, + ca_signature: &[u8], + ) -> Result<(), String> { + if ca_signature.is_empty() { + return Err("法律文件注册必须提供辖区政府授权 CA 签名".to_string()); + } + if law_hashes.is_empty() { + return Err("法律文件哈希列表不可为空".to_string()); + } + self.registered_law_hashes.insert(jurisdiction, law_hashes); + Ok(()) + } + + /// 发布裁决 + /// + /// 裁决依据已注册的辖区法律文件哈希。 + /// 裁决即生效,无需链上投票(约法即是治法)。 + pub fn issue_ruling( + &mut self, + case_type: CourtCaseType, + jurisdictions: Vec, + conclusion: RulingConclusion, + reasoning: String, + effective_timestamp: u64, + execution_deadline: u64, + court_signature: Vec, + ) -> Result, String> { + if court_signature.is_empty() { + return Err("裁决必须有宪法法院节点签名".to_string()); + } + + // 验证裁决依据的法律文件是否已注册 + let mut legal_basis_hashes = Vec::new(); + for &jid in &jurisdictions { + if let Some(hashes) = self.registered_law_hashes.get(&jid) { + legal_basis_hashes.extend(hashes.clone()); + } + // 注意:即使辖区未注册法律文件,裁决仍可发布 + // 但裁决理由中必须说明(宪法即是规则) + } + + // 计算裁决 ID + let mut hasher = Sha3_384::new(); + hasher.update(&(case_type == CourtCaseType::JurisdictionRuleConflict).to_string().as_bytes()); + for &jid in &jurisdictions { + hasher.update(&jid.to_be_bytes()); + } + hasher.update(&effective_timestamp.to_be_bytes()); + hasher.update(reasoning.as_bytes()); + let ruling_id = hasher.finalize().to_vec(); + + let ruling = ConstitutionalCourtRuling { + ruling_id: ruling_id.clone(), + case_type, + jurisdictions, + legal_basis_hashes, + conclusion, + reasoning, + effective_timestamp, + execution_deadline, + court_signature, + }; + + self.rulings.push(ruling); + Ok(ruling_id) + } + + /// 查询裁决(按裁决 ID) + pub fn get_ruling(&self, ruling_id: &[u8]) -> Option<&ConstitutionalCourtRuling> { + self.rulings.iter().find(|r| r.ruling_id == ruling_id) + } + + /// 查询辖区的所有相关裁决 + pub fn get_rulings_for_jurisdiction( + &self, + jurisdiction: JurisdictionId, + ) -> Vec<&ConstitutionalCourtRuling> { + self.rulings + .iter() + .filter(|r| r.jurisdictions.contains(&jurisdiction)) + .collect() + } + + /// 获取裁决总数 + pub fn ruling_count(&self) -> usize { + self.rulings.len() + } + + /// 检查辖区是否有已注册的法律文件 + pub fn has_registered_laws(&self, jurisdiction: JurisdictionId) -> bool { + self.registered_law_hashes.contains_key(&jurisdiction) + } +} + +impl Default for ConstitutionalCourt { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_proof(jurisdiction: JurisdictionId, ts: u64) -> JurisdictionProof { + JurisdictionProof { + node_did: vec![0x01; 32], + jurisdiction, + jurisdiction_ca_signature: vec![0xCA; 64], + plugin_hash: vec![0xAB; 48], + plugin_version: 100, + plugin_authorization_signature: vec![0xAU; 64], + effective_timestamp: ts, + expiry_timestamp: ts + 86400 * 365, // 1年有效期 + } + } + + #[test] + fn test_jurisdiction_proof_valid() { + let proof = make_proof(784, 1700000000); + assert_eq!(proof.is_valid(1700000000), ProofValidation::Valid); + } + + #[test] + fn test_jurisdiction_proof_expired() { + let proof = make_proof(784, 1700000000); + // 超过过期时间 + let result = proof.is_valid(1700000000 + 86400 * 365 + 1); + assert!(matches!(result, ProofValidation::Expired { .. })); + } + + #[test] + fn test_jurisdiction_proof_missing_ca_signature() { + let mut proof = make_proof(784, 1700000000); + proof.jurisdiction_ca_signature = vec![]; + assert!(matches!(proof.is_valid(1700000000), ProofValidation::Invalid(_))); + } + + #[test] + fn test_court_ruling_no_vote_required() { + // 约法即是治法:裁决即生效,无需投票 + let mut court = ConstitutionalCourt::new(); + + // 注册法律文件(辖区政府授权 CA 签名) + court.register_law_documents( + 784, + vec![vec![0xAB; 48]], + &[0xCA; 64], + ).unwrap(); + + // 发布裁决(直接生效,无需投票) + let ruling_id = court.issue_ruling( + CourtCaseType::JurisdictionRuleConflict, + vec![784, 156], + RulingConclusion::ConflictResolved { primary_jurisdiction: 784 }, + "依据 UAE VARA 法规第3条,资产注册辖区规则优先".to_string(), + 1700000000, + 1700000000 + 86400 * 30, // 30天执行期 + vec![0xCC; 64], + ); + + assert!(ruling_id.is_ok()); + let id = ruling_id.unwrap(); + + // 裁决立即可查询(无需等待投票) + let ruling = court.get_ruling(&id); + assert!(ruling.is_some()); + assert_eq!(court.ruling_count(), 1); + } + + #[test] + fn test_court_ruling_requires_court_signature() { + // 裁决必须有宪法法院节点签名 + let mut court = ConstitutionalCourt::new(); + let result = court.issue_ruling( + CourtCaseType::NodeViolation, + vec![784], + RulingConclusion::Dismissed, + "节点违规".to_string(), + 1700000000, + 1700000000 + 86400, + vec![], // 无签名 + ); + assert!(result.is_err()); + } + + #[test] + fn test_law_registration_requires_ca_signature() { + // 法律文件注册必须有 CA 签名(来自辖区政府授权) + let mut court = ConstitutionalCourt::new(); + let result = court.register_law_documents( + 784, + vec![vec![0xAB; 48]], + &[], // 无 CA 签名 + ); + assert!(result.is_err()); + } + + #[test] + fn test_ruling_references_real_law_hashes() { + // 裁决依据真实法律文件哈希,不是链上投票结果 + let mut court = ConstitutionalCourt::new(); + let law_hash = vec![0xDE; 48]; + court.register_law_documents(784, vec![law_hash.clone()], &[0xCA; 64]).unwrap(); + + let ruling_id = court.issue_ruling( + CourtCaseType::PluginLegalityDispute, + vec![784], + RulingConclusion::Upheld, + "依据已注册法律文件验证".to_string(), + 1700000000, + 1700000000 + 86400, + vec![0xCC; 64], + ).unwrap(); + + let ruling = court.get_ruling(&ruling_id).unwrap(); + // 裁决中包含真实法律文件哈希作为依据 + assert!(ruling.legal_basis_hashes.contains(&law_hash)); + } + + #[test] + fn test_jurisdiction_query_rulings() { + let mut court = ConstitutionalCourt::new(); + court.register_law_documents(784, vec![vec![0xAB; 48]], &[0xCA; 64]).unwrap(); + court.register_law_documents(156, vec![vec![0xCD; 48]], &[0xCA; 64]).unwrap(); + + court.issue_ruling( + CourtCaseType::JurisdictionRuleConflict, + vec![784, 156], + RulingConclusion::ConflictResolved { primary_jurisdiction: 784 }, + "辖区冲突裁决".to_string(), + 1700000000, 1700000000 + 86400, vec![0xCC; 64], + ).unwrap(); + + // 两个辖区都能查到相关裁决 + assert_eq!(court.get_rulings_for_jurisdiction(784).len(), 1); + assert_eq!(court.get_rulings_for_jurisdiction(156).len(), 1); + assert_eq!(court.get_rulings_for_jurisdiction(840).len(), 0); // 无关辖区 + } +} diff --git a/nac-csnp-l0/src/jurisdiction_router.rs b/nac-csnp-l0/src/jurisdiction_router.rs new file mode 100644 index 0000000..e856a1d --- /dev/null +++ b/nac-csnp-l0/src/jurisdiction_router.rs @@ -0,0 +1,349 @@ +// nac-csnp-l0/src/jurisdiction_router.rs +// CSNP 辖区感知路由与协议转换 +// +// 设计原则: +// 宪法即是规则 — 路由规则由辖区宪法条款决定,不是网络层自定义规则 +// 约法即是治法 — 协议转换必须保留原始 CR 作为法律证据,不可篡改 +// 参与即是共识 — 中继节点转发即是对路由合法性的背书 + +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +pub type JurisdictionId = u32; + +/// 节点网络端点 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NodeEndpoint { + pub node_id: Vec, + pub jurisdiction: JurisdictionId, + pub address: String, + /// 节点支持的插件版本(来自 GIDS,辖区政府授权 CA 签名) + pub plugin_version: u32, + /// 节点是否为中继节点(可执行协议转换) + pub is_relay: bool, +} + +/// 辖区路由表(从 GIDS 查询并缓存) +#[derive(Debug, Default)] +pub struct JurisdictionRoutingTable { + /// 辖区 → 节点端点列表 + entries: HashMap>, +} + +impl JurisdictionRoutingTable { + pub fn new() -> Self { + Self::default() + } + + /// 注册辖区节点(从 GIDS 同步) + pub fn register(&mut self, endpoint: NodeEndpoint) { + self.entries + .entry(endpoint.jurisdiction) + .or_default() + .push(endpoint); + } + + /// 查询目标辖区的可用节点列表 + pub fn lookup(&self, jurisdiction: JurisdictionId) -> Vec<&NodeEndpoint> { + self.entries + .get(&jurisdiction) + .map(|v| v.iter().collect()) + .unwrap_or_default() + } + + /// 查询目标辖区的中继节点(用于协议转换) + pub fn lookup_relay(&self, jurisdiction: JurisdictionId) -> Vec<&NodeEndpoint> { + self.lookup(jurisdiction) + .into_iter() + .filter(|n| n.is_relay) + .collect() + } + + /// 获取所有已知辖区 + pub fn known_jurisdictions(&self) -> Vec { + self.entries.keys().copied().collect() + } +} + +/// 协议转换记录 +/// +/// 当源节点和目标节点辖区插件版本差异过大时, +/// 中继节点执行协议转换,但必须保留原始 CR 作为法律证据。 +/// 约法即是治法:转换过程不得修改 CR 内容,CR 是法律证明。 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProtocolConversionRecord { + /// 原始交易 ID + pub tx_id: Vec, + /// 源辖区 + pub source_jurisdiction: JurisdictionId, + /// 目标辖区 + pub target_jurisdiction: JurisdictionId, + /// 源插件版本 + pub source_plugin_version: u32, + /// 目标插件版本 + pub target_plugin_version: u32, + /// 原始 CR(不可修改,作为法律证据存档) + pub original_cr: Vec, + /// 转换后的交易格式版本 + pub converted_format_version: u32, + /// 执行转换的中继节点 ID + pub relay_node_id: Vec, + /// 转换时间戳 + pub timestamp: u64, +} + +impl ProtocolConversionRecord { + /// 验证协议转换记录的合法性 + /// 核心检查:原始 CR 必须存在且非空(法律证据不可缺失) + pub fn is_valid(&self) -> bool { + !self.original_cr.is_empty() + && self.source_jurisdiction != self.target_jurisdiction + && !self.tx_id.is_empty() + && !self.relay_node_id.is_empty() + } +} + +/// 辖区感知路由决策 +#[derive(Debug, Clone, PartialEq)] +pub enum RoutingDecision { + /// 直接路由:目标节点与源节点同辖区,或目标辖区插件版本兼容 + Direct { target_node_id: Vec }, + /// 中继路由:需要协议转换,通过中继节点转发 + Relay { + relay_node_id: Vec, + target_node_id: Vec, + }, + /// 多播:交易涉及多个辖区,向所有相关辖区广播 + Multicast { target_jurisdictions: Vec }, + /// 无法路由:目标辖区未知或无可用节点 + Unreachable { reason: String }, +} + +/// 辖区感知路由器 +pub struct JurisdictionRouter { + routing_table: JurisdictionRoutingTable, + /// 本节点所属辖区 + local_jurisdiction: JurisdictionId, + /// 本节点插件版本 + local_plugin_version: u32, + /// 版本兼容阈值(差距超过此值需要协议转换) + version_compat_threshold: u32, +} + +impl JurisdictionRouter { + pub fn new( + local_jurisdiction: JurisdictionId, + local_plugin_version: u32, + version_compat_threshold: u32, + ) -> Self { + Self { + routing_table: JurisdictionRoutingTable::new(), + local_jurisdiction, + local_plugin_version, + version_compat_threshold, + } + } + + /// 注册辖区节点 + pub fn register_node(&mut self, endpoint: NodeEndpoint) { + self.routing_table.register(endpoint); + } + + /// 为单辖区交易做路由决策 + pub fn route_single( + &self, + target_jurisdiction: JurisdictionId, + ) -> RoutingDecision { + let nodes = self.routing_table.lookup(target_jurisdiction); + + if nodes.is_empty() { + return RoutingDecision::Unreachable { + reason: format!("辖区 {} 无可用节点", target_jurisdiction), + }; + } + + // 检查版本兼容性 + let compatible: Vec<_> = nodes + .iter() + .filter(|n| { + let diff = (n.plugin_version as i64 - self.local_plugin_version as i64).unsigned_abs(); + diff <= self.version_compat_threshold as u64 + }) + .collect(); + + if !compatible.is_empty() { + // 直接路由:选择第一个兼容节点 + return RoutingDecision::Direct { + target_node_id: compatible[0].node_id.clone(), + }; + } + + // 版本差异过大,需要中继节点执行协议转换 + let relay_nodes = self.routing_table.lookup_relay(target_jurisdiction); + if relay_nodes.is_empty() { + // 尝试从本辖区找中继节点 + let local_relays = self.routing_table.lookup_relay(self.local_jurisdiction); + if local_relays.is_empty() { + return RoutingDecision::Unreachable { + reason: format!("辖区 {} 版本不兼容且无中继节点", target_jurisdiction), + }; + } + return RoutingDecision::Relay { + relay_node_id: local_relays[0].node_id.clone(), + target_node_id: nodes[0].node_id.clone(), + }; + } + + RoutingDecision::Relay { + relay_node_id: relay_nodes[0].node_id.clone(), + target_node_id: nodes[0].node_id.clone(), + } + } + + /// 为跨多辖区交易做多播路由决策 + /// 减少重复传播,提高网络效率 + pub fn route_multicast( + &self, + target_jurisdictions: &[JurisdictionId], + ) -> RoutingDecision { + let reachable: Vec = target_jurisdictions + .iter() + .filter(|&&jid| !self.routing_table.lookup(jid).is_empty()) + .copied() + .collect(); + + if reachable.is_empty() { + return RoutingDecision::Unreachable { + reason: "所有目标辖区均无可用节点".to_string(), + }; + } + + RoutingDecision::Multicast { + target_jurisdictions: reachable, + } + } + + /// 创建协议转换记录(中继节点调用) + /// 转换过程必须保留原始 CR,不得修改(约法即是治法) + pub fn create_conversion_record( + &self, + tx_id: Vec, + source_jurisdiction: JurisdictionId, + target_jurisdiction: JurisdictionId, + source_plugin_version: u32, + target_plugin_version: u32, + original_cr: Vec, + relay_node_id: Vec, + timestamp: u64, + ) -> Result { + if original_cr.is_empty() { + return Err("原始 CR 不可为空:CR 是法律证据,协议转换不得丢失".to_string()); + } + + Ok(ProtocolConversionRecord { + tx_id, + source_jurisdiction, + target_jurisdiction, + source_plugin_version, + target_plugin_version, + original_cr, + converted_format_version: target_plugin_version, + relay_node_id, + timestamp, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_node(id: u8, jurisdiction: JurisdictionId, version: u32, is_relay: bool) -> NodeEndpoint { + NodeEndpoint { + node_id: vec![id; 32], + jurisdiction, + address: format!("10.0.0.{}:8080", id), + plugin_version: version, + is_relay, + } + } + + #[test] + fn test_direct_route_compatible_version() { + let mut router = JurisdictionRouter::new(784, 100, 10); + router.register_node(make_node(1, 156, 105, false)); // 版本差5,在阈值内 + + let decision = router.route_single(156); + assert!(matches!(decision, RoutingDecision::Direct { .. })); + } + + #[test] + fn test_relay_route_incompatible_version() { + let mut router = JurisdictionRouter::new(784, 100, 10); + router.register_node(make_node(1, 156, 200, false)); // 版本差100,超阈值 + router.register_node(make_node(2, 156, 200, true)); // 中继节点 + + let decision = router.route_single(156); + assert!(matches!(decision, RoutingDecision::Relay { .. })); + } + + #[test] + fn test_unreachable_unknown_jurisdiction() { + let router = JurisdictionRouter::new(784, 100, 10); + let decision = router.route_single(999); + assert!(matches!(decision, RoutingDecision::Unreachable { .. })); + } + + #[test] + fn test_multicast_multiple_jurisdictions() { + let mut router = JurisdictionRouter::new(784, 100, 10); + router.register_node(make_node(1, 156, 100, false)); + router.register_node(make_node(2, 840, 100, false)); + + let decision = router.route_multicast(&[156, 840, 999]); + match decision { + RoutingDecision::Multicast { target_jurisdictions } => { + assert_eq!(target_jurisdictions.len(), 2); // 999 不可达被过滤 + assert!(target_jurisdictions.contains(&156)); + assert!(target_jurisdictions.contains(&840)); + } + _ => panic!("应为多播决策"), + } + } + + #[test] + fn test_conversion_record_preserves_original_cr() { + // 约法即是治法:协议转换必须保留原始 CR + let router = JurisdictionRouter::new(784, 100, 10); + let original_cr = vec![0xAB; 48]; + + let record = router.create_conversion_record( + vec![1u8; 48], + 784, 156, + 100, 200, + original_cr.clone(), + vec![2u8; 32], + 1700000000, + ); + + assert!(record.is_ok()); + let rec = record.unwrap(); + assert_eq!(rec.original_cr, original_cr); // CR 完整保留 + assert!(rec.is_valid()); + } + + #[test] + fn test_conversion_record_rejects_empty_cr() { + // 空 CR 被拒绝:法律证据不可缺失 + let router = JurisdictionRouter::new(784, 100, 10); + let result = router.create_conversion_record( + vec![1u8; 48], + 784, 156, + 100, 200, + vec![], // 空 CR + vec![2u8; 32], + 1700000000, + ); + assert!(result.is_err()); + } +} diff --git a/nac-csnp-l0/src/lib.rs b/nac-csnp-l0/src/lib.rs index 0f39b0a..716c1c1 100644 --- a/nac-csnp-l0/src/lib.rs +++ b/nac-csnp-l0/src/lib.rs @@ -39,3 +39,5 @@ mod tests { assert!(true); } } +pub mod jurisdiction_router; +pub mod gids_jurisdiction_proof; diff --git a/nac-jurisdiction-compat/Cargo.lock b/nac-jurisdiction-compat/Cargo.lock new file mode 100644 index 0000000..2bda6f9 --- /dev/null +++ b/nac-jurisdiction-compat/Cargo.lock @@ -0,0 +1,107 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "nac-jurisdiction-compat" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + +[[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.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[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 = "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 = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/nac-jurisdiction-compat/Cargo.toml b/nac-jurisdiction-compat/Cargo.toml new file mode 100644 index 0000000..330b19a --- /dev/null +++ b/nac-jurisdiction-compat/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "nac-jurisdiction-compat" +version = "0.1.0" +edition = "2021" +description = "NAC辖区规则跨版本兼容性检测模块 (Issue #76)" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/nac-jurisdiction-compat/src/lib.rs b/nac-jurisdiction-compat/src/lib.rs new file mode 100644 index 0000000..a4402c4 --- /dev/null +++ b/nac-jurisdiction-compat/src/lib.rs @@ -0,0 +1,406 @@ +// NAC 辖区规则跨版本兼容性检测模块(Issue #76) +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 版本更新必须由辖区授权CA签名,更新后立即生效(约法即是治法),旧版本自动归档 +// NAC_Lens 4.0 负责将版本更新通知广播到所有辖区节点 + +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +/// 规则版本号(语义化版本:major.minor.patch) +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct RuleVersion { + pub major: u32, + pub minor: u32, + pub patch: u32, + /// 版本生效时间戳(UTC Unix 毫秒) + pub effective_at: u64, + /// 辖区授权CA签名(约法即是治法:CA签名即法律生效) + pub ca_signature: Vec, + /// 签发CA的辖区标识 + pub issuing_jurisdiction: String, +} + +impl RuleVersion { + pub fn new(major: u32, minor: u32, patch: u32, jurisdiction: &str) -> Self { + Self { + major, + minor, + patch, + effective_at: 0, + ca_signature: Vec::new(), + issuing_jurisdiction: jurisdiction.to_string(), + } + } + + pub fn to_string(&self) -> String { + format!("{}.{}.{}", self.major, self.minor, self.patch) + } + + /// 是否为破坏性变更(major 版本升级) + pub fn is_breaking_change(&self, other: &RuleVersion) -> bool { + self.major > other.major + } + + /// 是否为向后兼容的功能增加(minor 版本升级) + pub fn is_additive_change(&self, other: &RuleVersion) -> bool { + self.major == other.major && self.minor > other.minor + } + + /// 是否为补丁修复(patch 版本升级) + pub fn is_patch_change(&self, other: &RuleVersion) -> bool { + self.major == other.major && self.minor == other.minor && self.patch > other.patch + } +} + +/// 兼容性检测结果 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum CompatibilityResult { + /// 完全兼容:新版本规则对现有交易无影响 + FullyCompatible { + old_version: String, + new_version: String, + jurisdiction: String, + }, + /// 向后兼容:新增规则,现有交易仍然有效 + BackwardCompatible { + old_version: String, + new_version: String, + jurisdiction: String, + /// 新增的规则列表 + added_rules: Vec, + }, + /// 不兼容:破坏性变更,需要迁移 + Incompatible { + old_version: String, + new_version: String, + jurisdiction: String, + /// 被移除或修改的规则 + breaking_changes: Vec, + /// 受影响的交易类型 + affected_asset_types: Vec, + }, + /// 需要CA重新授权 + RequiresCAReauthorization { + jurisdiction: String, + reason: String, + }, +} + +/// 破坏性变更描述 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BreakingChange { + pub rule_id: String, + pub change_type: ChangeType, + pub old_value: String, + pub new_value: String, + pub legal_basis: String, +} + +/// 变更类型 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ChangeType { + /// 规则被移除 + RuleRemoved, + /// 阈值提高(更严格) + ThresholdIncreased, + /// 阈值降低(更宽松) + ThresholdDecreased, + /// KYC要求提高 + KycLevelUpgraded, + /// 新增禁止资产类型 + AssetTypeProhibited, + /// 新增允许资产类型 + AssetTypePermitted, + /// 监管机构变更 + RegulatoryAuthorityChanged, +} + +/// 辖区规则版本快照(用于兼容性对比) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JurisdictionRuleSnapshot { + pub jurisdiction_code: String, + pub version: RuleVersion, + /// 规则集(rule_id -> rule_hash) + pub rules: HashMap, + /// AML 阈值(USD) + pub aml_threshold_usd: f64, + /// 最低KYC等级 + pub min_kyc_level: String, + /// 允许的资产类型 + pub permitted_asset_types: Vec, + /// 禁止的资产类型 + pub prohibited_asset_types: Vec, + /// 监管机构 + pub regulatory_authority: String, +} + +/// 跨版本兼容性检测引擎 +pub struct CompatibilityChecker; + +impl CompatibilityChecker { + pub fn new() -> Self { + Self + } + + /// 检测两个版本快照之间的兼容性 + /// 约法即是治法:新版本CA签名有效后立即生效,此函数评估影响范围 + pub fn check_compatibility( + &self, + old_snapshot: &JurisdictionRuleSnapshot, + new_snapshot: &JurisdictionRuleSnapshot, + ) -> CompatibilityResult { + // 验证辖区一致性 + if old_snapshot.jurisdiction_code != new_snapshot.jurisdiction_code { + return CompatibilityResult::RequiresCAReauthorization { + jurisdiction: new_snapshot.jurisdiction_code.clone(), + reason: "Jurisdiction code mismatch: cross-jurisdiction rule migration requires separate CA authorization".to_string(), + }; + } + + // 验证CA签名(约法即是治法:无CA签名的版本不得生效) + if new_snapshot.version.ca_signature.is_empty() { + return CompatibilityResult::RequiresCAReauthorization { + jurisdiction: new_snapshot.jurisdiction_code.clone(), + reason: format!( + "Version {} lacks CA signature from {}. Per CBPP principle '约法即是治法', \ + rule updates must be authorized by jurisdiction CA before taking effect.", + new_snapshot.version.to_string(), + new_snapshot.version.issuing_jurisdiction + ), + }; + } + + let old_ver = &old_snapshot.version; + let new_ver = &new_snapshot.version; + + // 收集破坏性变更 + let mut breaking_changes = Vec::new(); + let mut added_rules = Vec::new(); + let mut affected_asset_types = Vec::new(); + + // 1. 检查 AML 阈值变化 + if (new_snapshot.aml_threshold_usd - old_snapshot.aml_threshold_usd).abs() > f64::EPSILON { + if new_snapshot.aml_threshold_usd < old_snapshot.aml_threshold_usd { + // 阈值降低 = 更严格 = 破坏性变更 + breaking_changes.push(BreakingChange { + rule_id: format!("{}_AML_THRESHOLD", old_snapshot.jurisdiction_code), + change_type: ChangeType::ThresholdDecreased, + old_value: format!("{} USD", old_snapshot.aml_threshold_usd), + new_value: format!("{} USD", new_snapshot.aml_threshold_usd), + legal_basis: format!("Regulatory update by {}", new_snapshot.regulatory_authority), + }); + affected_asset_types.push("ALL".to_string()); + } else { + // 阈值提高 = 更宽松 = 向后兼容 + added_rules.push(format!( + "AML threshold relaxed: {} -> {} USD", + old_snapshot.aml_threshold_usd, new_snapshot.aml_threshold_usd + )); + } + } + + // 2. 检查 KYC 等级变化 + if old_snapshot.min_kyc_level != new_snapshot.min_kyc_level { + let old_level = Self::kyc_level_rank(&old_snapshot.min_kyc_level); + let new_level = Self::kyc_level_rank(&new_snapshot.min_kyc_level); + if new_level > old_level { + // KYC要求提高 = 破坏性变更 + breaking_changes.push(BreakingChange { + rule_id: format!("{}_KYC_LEVEL", old_snapshot.jurisdiction_code), + change_type: ChangeType::KycLevelUpgraded, + old_value: old_snapshot.min_kyc_level.clone(), + new_value: new_snapshot.min_kyc_level.clone(), + legal_basis: format!("KYC upgrade mandated by {}", new_snapshot.regulatory_authority), + }); + affected_asset_types.push("ALL".to_string()); + } else { + added_rules.push(format!( + "KYC requirement relaxed: {} -> {}", + old_snapshot.min_kyc_level, new_snapshot.min_kyc_level + )); + } + } + + // 3. 检查新增禁止资产类型 + for asset in &new_snapshot.prohibited_asset_types { + if !old_snapshot.prohibited_asset_types.contains(asset) { + breaking_changes.push(BreakingChange { + rule_id: format!("{}_PROHIBITED_{}", old_snapshot.jurisdiction_code, asset), + change_type: ChangeType::AssetTypeProhibited, + old_value: "permitted".to_string(), + new_value: "prohibited".to_string(), + legal_basis: format!("Asset prohibition by {}", new_snapshot.regulatory_authority), + }); + affected_asset_types.push(asset.clone()); + } + } + + // 4. 检查新增允许资产类型(向后兼容) + for asset in &new_snapshot.permitted_asset_types { + if !old_snapshot.permitted_asset_types.contains(asset) { + added_rules.push(format!("New asset type permitted: {}", asset)); + } + } + + // 5. 检查监管机构变更 + if old_snapshot.regulatory_authority != new_snapshot.regulatory_authority { + breaking_changes.push(BreakingChange { + rule_id: format!("{}_REGULATOR", old_snapshot.jurisdiction_code), + change_type: ChangeType::RegulatoryAuthorityChanged, + old_value: old_snapshot.regulatory_authority.clone(), + new_value: new_snapshot.regulatory_authority.clone(), + legal_basis: "Regulatory authority transfer".to_string(), + }); + } + + // 判断兼容性级别 + if !breaking_changes.is_empty() { + CompatibilityResult::Incompatible { + old_version: old_ver.to_string(), + new_version: new_ver.to_string(), + jurisdiction: old_snapshot.jurisdiction_code.clone(), + breaking_changes, + affected_asset_types, + } + } else if !added_rules.is_empty() { + CompatibilityResult::BackwardCompatible { + old_version: old_ver.to_string(), + new_version: new_ver.to_string(), + jurisdiction: old_snapshot.jurisdiction_code.clone(), + added_rules, + } + } else { + CompatibilityResult::FullyCompatible { + old_version: old_ver.to_string(), + new_version: new_ver.to_string(), + jurisdiction: old_snapshot.jurisdiction_code.clone(), + } + } + } + + /// KYC 等级数值化(用于比较) + fn kyc_level_rank(level: &str) -> u8 { + match level { + "None" => 0, + "Basic" => 1, + "Enhanced" => 2, + "Institutional" => 3, + _ => 0, + } + } + + /// 批量检测多个辖区的兼容性 + pub fn batch_check( + &self, + old_snapshots: &[JurisdictionRuleSnapshot], + new_snapshots: &[JurisdictionRuleSnapshot], + ) -> Vec<(String, CompatibilityResult)> { + let old_map: HashMap<&str, &JurisdictionRuleSnapshot> = old_snapshots + .iter() + .map(|s| (s.jurisdiction_code.as_str(), s)) + .collect(); + + new_snapshots + .iter() + .map(|new_s| { + let result = if let Some(old_s) = old_map.get(new_s.jurisdiction_code.as_str()) { + self.check_compatibility(old_s, new_s) + } else { + // 新增辖区,完全兼容 + CompatibilityResult::FullyCompatible { + old_version: "N/A".to_string(), + new_version: new_s.version.to_string(), + jurisdiction: new_s.jurisdiction_code.clone(), + } + }; + (new_s.jurisdiction_code.clone(), result) + }) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_snapshot(code: &str, major: u32, minor: u32, aml: f64, kyc: &str) -> JurisdictionRuleSnapshot { + let mut version = RuleVersion::new(major, minor, 0, code); + version.ca_signature = vec![1u8; 64]; // 模拟CA签名 + version.effective_at = 1000000; + JurisdictionRuleSnapshot { + jurisdiction_code: code.to_string(), + version, + rules: HashMap::new(), + aml_threshold_usd: aml, + min_kyc_level: kyc.to_string(), + permitted_asset_types: vec!["RWA_REAL_ESTATE".to_string()], + prohibited_asset_types: vec![], + regulatory_authority: format!("{}_REGULATOR", code), + } + } + + #[test] + fn test_fully_compatible_no_changes() { + let checker = CompatibilityChecker::new(); + let old = make_snapshot("CN", 1, 0, 10000.0, "Institutional"); + let new = make_snapshot("CN", 1, 0, 10000.0, "Institutional"); + let result = checker.check_compatibility(&old, &new); + assert!(matches!(result, CompatibilityResult::FullyCompatible { .. })); + } + + #[test] + fn test_backward_compatible_threshold_relaxed() { + let checker = CompatibilityChecker::new(); + let old = make_snapshot("HK", 1, 0, 10000.0, "Enhanced"); + let new = make_snapshot("HK", 1, 1, 20000.0, "Enhanced"); // 阈值提高=更宽松 + let result = checker.check_compatibility(&old, &new); + assert!(matches!(result, CompatibilityResult::BackwardCompatible { .. })); + } + + #[test] + fn test_incompatible_threshold_tightened() { + let checker = CompatibilityChecker::new(); + let old = make_snapshot("SG", 1, 0, 20000.0, "Enhanced"); + let new = make_snapshot("SG", 2, 0, 5000.0, "Enhanced"); // 阈值降低=更严格 + let result = checker.check_compatibility(&old, &new); + assert!(matches!(result, CompatibilityResult::Incompatible { .. })); + } + + #[test] + fn test_incompatible_kyc_upgraded() { + let checker = CompatibilityChecker::new(); + let old = make_snapshot("AE", 1, 0, 10000.0, "Enhanced"); + let new = make_snapshot("AE", 2, 0, 10000.0, "Institutional"); // KYC提高 + let result = checker.check_compatibility(&old, &new); + assert!(matches!(result, CompatibilityResult::Incompatible { .. })); + } + + #[test] + fn test_requires_ca_reauthorization_no_signature() { + let checker = CompatibilityChecker::new(); + let old = make_snapshot("JP", 1, 0, 10000.0, "Enhanced"); + let mut new = make_snapshot("JP", 2, 0, 10000.0, "Enhanced"); + new.version.ca_signature = vec![]; // 无CA签名 + let result = checker.check_compatibility(&old, &new); + assert!(matches!(result, CompatibilityResult::RequiresCAReauthorization { .. })); + } + + #[test] + fn test_batch_check_multiple_jurisdictions() { + let checker = CompatibilityChecker::new(); + let old_snapshots = vec![ + make_snapshot("CN", 1, 0, 10000.0, "Institutional"), + make_snapshot("HK", 1, 0, 10000.0, "Enhanced"), + ]; + let new_snapshots = vec![ + make_snapshot("CN", 1, 0, 10000.0, "Institutional"), // 无变化 + make_snapshot("HK", 1, 1, 15000.0, "Enhanced"), // 宽松变更 + make_snapshot("SG", 1, 0, 10000.0, "Enhanced"), // 新增辖区 + ]; + let results = checker.batch_check(&old_snapshots, &new_snapshots); + assert_eq!(results.len(), 3); + assert!(matches!(results[0].1, CompatibilityResult::FullyCompatible { .. })); + assert!(matches!(results[1].1, CompatibilityResult::BackwardCompatible { .. })); + assert!(matches!(results[2].1, CompatibilityResult::FullyCompatible { .. })); + } +} diff --git a/nac-jurisdiction-rules/BM/README.md b/nac-jurisdiction-rules/BM/README.md new file mode 100644 index 0000000..52e4aa7 --- /dev/null +++ b/nac-jurisdiction-rules/BM/README.md @@ -0,0 +1,58 @@ +# 百慕大(Bermuda) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | BM | +| 辖区名称 | 百慕大(Bermuda) | +| 监管机构 | BMA(Bermuda Monetary Authority) | +| 关键法律 | Digital Asset Business Act 2018(DABA) | +| 授权CA | BMA_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 BMA_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 BM 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 BM 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 BM 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| BM_DABA_001 | 数字资产业务须持有BMA颁发的DABA牌照 | +| BM_AML_001 | 反洗钱须符合FATF标准及百慕大AML/ATF法规 | +| BM_INVEST_001 | 保险/再保险资产上链须符合保险法第6条 | +| BM_KYC_001 | KYC须核实客户身份并保留5年记录 | +| BM_REPORT_001 | 季度向BMA提交数字资产业务报告 | + +## 支持的资产类型 + +- 保险资产 +- 再保险资产 +- 基金份额 +- 债券 +- 股权 + +## 禁止活动 + +- 匿名交易 +- 无牌照数字资产业务 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +BM 辖区与其他辖区**完全独立**。跨辖区交易时,BM 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/BM/constitution_rules.cnnl b/nac-jurisdiction-rules/BM/constitution_rules.cnnl new file mode 100644 index 0000000..feb655c --- /dev/null +++ b/nac-jurisdiction-rules/BM/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 百慕大(Bermuda) +// 监管机构:BMA(Bermuda Monetary Authority) +// 关键法律:Digital Asset Business Act 2018(DABA) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(BMA_CA)签名后直接生效,无需链上投票 + +JURISDICTION BM { + name: "百慕大(Bermuda)" + regulator: "BMA(Bermuda Monetary Authority)" + key_law: "Digital Asset Business Act 2018(DABA)" + ca_authority: "BMA_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["保险资产", "再保险资产", "基金份额", "债券", "股权"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["匿名交易", "无牌照数字资产业务"] +} + +CLAUSE BM_DABA_001 { + jurisdiction: "BM" + type: "COMPLIANCE_RULE" + description: "数字资产业务须持有BMA颁发的DABA牌照" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE BM_AML_001 { + jurisdiction: "BM" + type: "COMPLIANCE_RULE" + description: "反洗钱须符合FATF标准及百慕大AML/ATF法规" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE BM_INVEST_001 { + jurisdiction: "BM" + type: "COMPLIANCE_RULE" + description: "保险/再保险资产上链须符合保险法第6条" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE BM_KYC_001 { + jurisdiction: "BM" + type: "COMPLIANCE_RULE" + description: "KYC须核实客户身份并保留5年记录" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE BM_REPORT_001 { + jurisdiction: "BM" + type: "COMPLIANCE_RULE" + description: "季度向BMA提交数字资产业务报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/BM/protocol_template.charter b/nac-jurisdiction-rules/BM/protocol_template.charter new file mode 100644 index 0000000..644deb0 --- /dev/null +++ b/nac-jurisdiction-rules/BM/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 百慕大(Bermuda) +// 监管机构:BMA(Bermuda Monetary Authority) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义BM辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract BMAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "BM"; + const REGULATOR: string = "BMA(Bermuda Monetary Authority)"; + const CA_AUTHORITY: string = "BMA_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须BMA_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["保险资产", "再保险资产", "基金份额", "债券", "股权"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["匿名交易", "无牌照数字资产业务"]; +} diff --git a/nac-jurisdiction-rules/Cargo.lock b/nac-jurisdiction-rules/Cargo.lock index 7260d22..f905e38 100644 --- a/nac-jurisdiction-rules/Cargo.lock +++ b/nac-jurisdiction-rules/Cargo.lock @@ -7,6 +7,7 @@ name = "nac-jurisdiction-rules" version = "1.0.0" dependencies = [ "serde", + "thiserror", ] [[package]] @@ -68,6 +69,26 @@ dependencies = [ "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 = "unicode-ident" version = "1.0.24" diff --git a/nac-jurisdiction-rules/GI/README.md b/nac-jurisdiction-rules/GI/README.md new file mode 100644 index 0000000..34b03e9 --- /dev/null +++ b/nac-jurisdiction-rules/GI/README.md @@ -0,0 +1,57 @@ +# 直布罗陀(Gibraltar) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | GI | +| 辖区名称 | 直布罗陀(Gibraltar) | +| 监管机构 | GFSC(Gibraltar Financial Services Commission) | +| 关键法律 | Distributed Ledger Technology Regulatory Framework 2018(DLT框架) | +| 授权CA | GFSC_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 GFSC_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 GI 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 GI 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 GI 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| GI_DLT_001 | 使用DLT存储或传输价值须向GFSC申请DLT牌照 | +| GI_AML_001 | 须符合直布罗陀反洗钱法规(Proceeds of Crime Act 2015) | +| GI_KYC_001 | KYC须核实客户身份,保留5年记录 | +| GI_CUSTODY_001 | 数字资产托管须符合GFSC托管规则 | +| GI_REPORT_001 | 年度向GFSC提交DLT业务报告 | + +## 支持的资产类型 + +- 数字资产 +- 代币 +- 虚拟货币 +- 证券型代币 + +## 禁止活动 + +- 无DLT牌照运营 +- 匿名交易 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +GI 辖区与其他辖区**完全独立**。跨辖区交易时,GI 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/GI/constitution_rules.cnnl b/nac-jurisdiction-rules/GI/constitution_rules.cnnl new file mode 100644 index 0000000..1fdff4a --- /dev/null +++ b/nac-jurisdiction-rules/GI/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 直布罗陀(Gibraltar) +// 监管机构:GFSC(Gibraltar Financial Services Commission) +// 关键法律:Distributed Ledger Technology Regulatory Framework 2018(DLT框架) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(GFSC_CA)签名后直接生效,无需链上投票 + +JURISDICTION GI { + name: "直布罗陀(Gibraltar)" + regulator: "GFSC(Gibraltar Financial Services Commission)" + key_law: "Distributed Ledger Technology Regulatory Framework 2018(DLT框架)" + ca_authority: "GFSC_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["数字资产", "代币", "虚拟货币", "证券型代币"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["无DLT牌照运营", "匿名交易"] +} + +CLAUSE GI_DLT_001 { + jurisdiction: "GI" + type: "COMPLIANCE_RULE" + description: "使用DLT存储或传输价值须向GFSC申请DLT牌照" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE GI_AML_001 { + jurisdiction: "GI" + type: "COMPLIANCE_RULE" + description: "须符合直布罗陀反洗钱法规(Proceeds of Crime Act 2015)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE GI_KYC_001 { + jurisdiction: "GI" + type: "COMPLIANCE_RULE" + description: "KYC须核实客户身份,保留5年记录" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE GI_CUSTODY_001 { + jurisdiction: "GI" + type: "COMPLIANCE_RULE" + description: "数字资产托管须符合GFSC托管规则" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE GI_REPORT_001 { + jurisdiction: "GI" + type: "COMPLIANCE_RULE" + description: "年度向GFSC提交DLT业务报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/GI/protocol_template.charter b/nac-jurisdiction-rules/GI/protocol_template.charter new file mode 100644 index 0000000..9e6b2ba --- /dev/null +++ b/nac-jurisdiction-rules/GI/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 直布罗陀(Gibraltar) +// 监管机构:GFSC(Gibraltar Financial Services Commission) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义GI辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract GIAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "GI"; + const REGULATOR: string = "GFSC(Gibraltar Financial Services Commission)"; + const CA_AUTHORITY: string = "GFSC_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须GFSC_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["数字资产", "代币", "虚拟货币", "证券型代币"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["无DLT牌照运营", "匿名交易"]; +} diff --git a/nac-jurisdiction-rules/IM/README.md b/nac-jurisdiction-rules/IM/README.md new file mode 100644 index 0000000..4eddf2a --- /dev/null +++ b/nac-jurisdiction-rules/IM/README.md @@ -0,0 +1,57 @@ +# 马恩岛(Isle of Man) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | IM | +| 辖区名称 | 马恩岛(Isle of Man) | +| 监管机构 | FSA(Isle of Man Financial Services Authority) | +| 关键法律 | Designated Businesses (Registration and Oversight) Act 2015 | +| 授权CA | IM_FSA_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 IM_FSA_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 IM 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 IM 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 IM 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| IM_FSA_001 | 数字资产业务须向FSA注册为指定业务 | +| IM_AML_001 | 须符合马恩岛反洗钱法规(Anti-Money Laundering Code 2019) | +| IM_KYC_001 | KYC须核实客户身份,保留5年记录 | +| IM_CUSTODY_001 | 数字资产托管须符合FSA托管规则 | +| IM_REPORT_001 | 年度向FSA提交合规报告 | + +## 支持的资产类型 + +- 数字资产 +- 代币 +- 虚拟货币 +- 基金份额 + +## 禁止活动 + +- 未注册数字资产业务 +- 匿名交易 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +IM 辖区与其他辖区**完全独立**。跨辖区交易时,IM 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/IM/constitution_rules.cnnl b/nac-jurisdiction-rules/IM/constitution_rules.cnnl new file mode 100644 index 0000000..d2d5e52 --- /dev/null +++ b/nac-jurisdiction-rules/IM/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 马恩岛(Isle of Man) +// 监管机构:FSA(Isle of Man Financial Services Authority) +// 关键法律:Designated Businesses (Registration and Oversight) Act 2015 +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(IM_FSA_CA)签名后直接生效,无需链上投票 + +JURISDICTION IM { + name: "马恩岛(Isle of Man)" + regulator: "FSA(Isle of Man Financial Services Authority)" + key_law: "Designated Businesses (Registration and Oversight) Act 2015" + ca_authority: "IM_FSA_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["数字资产", "代币", "虚拟货币", "基金份额"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["未注册数字资产业务", "匿名交易"] +} + +CLAUSE IM_FSA_001 { + jurisdiction: "IM" + type: "COMPLIANCE_RULE" + description: "数字资产业务须向FSA注册为指定业务" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE IM_AML_001 { + jurisdiction: "IM" + type: "COMPLIANCE_RULE" + description: "须符合马恩岛反洗钱法规(Anti-Money Laundering Code 2019)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE IM_KYC_001 { + jurisdiction: "IM" + type: "COMPLIANCE_RULE" + description: "KYC须核实客户身份,保留5年记录" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE IM_CUSTODY_001 { + jurisdiction: "IM" + type: "COMPLIANCE_RULE" + description: "数字资产托管须符合FSA托管规则" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE IM_REPORT_001 { + jurisdiction: "IM" + type: "COMPLIANCE_RULE" + description: "年度向FSA提交合规报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/IM/protocol_template.charter b/nac-jurisdiction-rules/IM/protocol_template.charter new file mode 100644 index 0000000..d4fc139 --- /dev/null +++ b/nac-jurisdiction-rules/IM/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 马恩岛(Isle of Man) +// 监管机构:FSA(Isle of Man Financial Services Authority) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义IM辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract IMAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "IM"; + const REGULATOR: string = "FSA(Isle of Man Financial Services Authority)"; + const CA_AUTHORITY: string = "IM_FSA_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须IM_FSA_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["数字资产", "代币", "虚拟货币", "基金份额"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["未注册数字资产业务", "匿名交易"]; +} diff --git a/nac-jurisdiction-rules/JE/README.md b/nac-jurisdiction-rules/JE/README.md new file mode 100644 index 0000000..4b22384 --- /dev/null +++ b/nac-jurisdiction-rules/JE/README.md @@ -0,0 +1,57 @@ +# 泽西岛(Jersey) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | JE | +| 辖区名称 | 泽西岛(Jersey) | +| 监管机构 | JFSC(Jersey Financial Services Commission) | +| 关键法律 | Virtual Asset Service Providers (Jersey) Law 2021 | +| 授权CA | JFSC_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 JFSC_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 JE 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 JE 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 JE 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| JE_VASP_001 | 虚拟资产服务提供商须向JFSC注册 | +| JE_AML_001 | 须符合泽西岛反洗钱法规(Money Laundering Order 2008) | +| JE_KYC_001 | KYC须核实受益所有人(UBO)信息 | +| JE_FUND_001 | 基金资产须符合泽西岛集合投资基金法 | +| JE_REPORT_001 | 年度向JFSC提交合规报告 | + +## 支持的资产类型 + +- 基金份额 +- 债券 +- 股权 +- 虚拟资产 + +## 禁止活动 + +- 未注册VASP运营 +- 匿名基金 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +JE 辖区与其他辖区**完全独立**。跨辖区交易时,JE 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/JE/constitution_rules.cnnl b/nac-jurisdiction-rules/JE/constitution_rules.cnnl new file mode 100644 index 0000000..03ac530 --- /dev/null +++ b/nac-jurisdiction-rules/JE/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 泽西岛(Jersey) +// 监管机构:JFSC(Jersey Financial Services Commission) +// 关键法律:Virtual Asset Service Providers (Jersey) Law 2021 +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(JFSC_CA)签名后直接生效,无需链上投票 + +JURISDICTION JE { + name: "泽西岛(Jersey)" + regulator: "JFSC(Jersey Financial Services Commission)" + key_law: "Virtual Asset Service Providers (Jersey) Law 2021" + ca_authority: "JFSC_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["基金份额", "债券", "股权", "虚拟资产"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["未注册VASP运营", "匿名基金"] +} + +CLAUSE JE_VASP_001 { + jurisdiction: "JE" + type: "COMPLIANCE_RULE" + description: "虚拟资产服务提供商须向JFSC注册" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE JE_AML_001 { + jurisdiction: "JE" + type: "COMPLIANCE_RULE" + description: "须符合泽西岛反洗钱法规(Money Laundering Order 2008)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE JE_KYC_001 { + jurisdiction: "JE" + type: "COMPLIANCE_RULE" + description: "KYC须核实受益所有人(UBO)信息" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE JE_FUND_001 { + jurisdiction: "JE" + type: "COMPLIANCE_RULE" + description: "基金资产须符合泽西岛集合投资基金法" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE JE_REPORT_001 { + jurisdiction: "JE" + type: "COMPLIANCE_RULE" + description: "年度向JFSC提交合规报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/JE/protocol_template.charter b/nac-jurisdiction-rules/JE/protocol_template.charter new file mode 100644 index 0000000..caa338e --- /dev/null +++ b/nac-jurisdiction-rules/JE/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 泽西岛(Jersey) +// 监管机构:JFSC(Jersey Financial Services Commission) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义JE辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract JEAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "JE"; + const REGULATOR: string = "JFSC(Jersey Financial Services Commission)"; + const CA_AUTHORITY: string = "JFSC_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须JFSC_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["基金份额", "债券", "股权", "虚拟资产"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["未注册VASP运营", "匿名基金"]; +} diff --git a/nac-jurisdiction-rules/KY/README.md b/nac-jurisdiction-rules/KY/README.md new file mode 100644 index 0000000..7f93f4f --- /dev/null +++ b/nac-jurisdiction-rules/KY/README.md @@ -0,0 +1,58 @@ +# 开曼群岛(Cayman Islands) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | KY | +| 辖区名称 | 开曼群岛(Cayman Islands) | +| 监管机构 | CIMA(Cayman Islands Monetary Authority) | +| 关键法律 | Virtual Asset Service Providers Act 2020(VASP) | +| 授权CA | CIMA_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 CIMA_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 KY 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 KY 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 KY 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| KY_VASP_001 | 虚拟资产服务提供商须向CIMA注册 | +| KY_FUND_001 | 基金资产须符合共同基金法或私募基金法 | +| KY_AML_001 | 须符合反洗钱法规(AML Regulations 2020) | +| KY_KYC_001 | KYC须核实受益所有人(UBO)信息 | +| KY_REPORT_001 | 年度向CIMA提交合规报告 | + +## 支持的资产类型 + +- 基金份额 +- 有限合伙权益 +- 债券 +- 股权 +- 虚拟资产 + +## 禁止活动 + +- 未注册VASP运营 +- 匿名基金 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +KY 辖区与其他辖区**完全独立**。跨辖区交易时,KY 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/KY/constitution_rules.cnnl b/nac-jurisdiction-rules/KY/constitution_rules.cnnl new file mode 100644 index 0000000..89591f5 --- /dev/null +++ b/nac-jurisdiction-rules/KY/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 开曼群岛(Cayman Islands) +// 监管机构:CIMA(Cayman Islands Monetary Authority) +// 关键法律:Virtual Asset Service Providers Act 2020(VASP) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(CIMA_CA)签名后直接生效,无需链上投票 + +JURISDICTION KY { + name: "开曼群岛(Cayman Islands)" + regulator: "CIMA(Cayman Islands Monetary Authority)" + key_law: "Virtual Asset Service Providers Act 2020(VASP)" + ca_authority: "CIMA_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["基金份额", "有限合伙权益", "债券", "股权", "虚拟资产"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["未注册VASP运营", "匿名基金"] +} + +CLAUSE KY_VASP_001 { + jurisdiction: "KY" + type: "COMPLIANCE_RULE" + description: "虚拟资产服务提供商须向CIMA注册" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE KY_FUND_001 { + jurisdiction: "KY" + type: "COMPLIANCE_RULE" + description: "基金资产须符合共同基金法或私募基金法" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE KY_AML_001 { + jurisdiction: "KY" + type: "COMPLIANCE_RULE" + description: "须符合反洗钱法规(AML Regulations 2020)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE KY_KYC_001 { + jurisdiction: "KY" + type: "COMPLIANCE_RULE" + description: "KYC须核实受益所有人(UBO)信息" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE KY_REPORT_001 { + jurisdiction: "KY" + type: "COMPLIANCE_RULE" + description: "年度向CIMA提交合规报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/KY/protocol_template.charter b/nac-jurisdiction-rules/KY/protocol_template.charter new file mode 100644 index 0000000..5ac79db --- /dev/null +++ b/nac-jurisdiction-rules/KY/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 开曼群岛(Cayman Islands) +// 监管机构:CIMA(Cayman Islands Monetary Authority) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义KY辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract KYAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "KY"; + const REGULATOR: string = "CIMA(Cayman Islands Monetary Authority)"; + const CA_AUTHORITY: string = "CIMA_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须CIMA_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["基金份额", "有限合伙权益", "债券", "股权", "虚拟资产"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["未注册VASP运营", "匿名基金"]; +} diff --git a/nac-jurisdiction-rules/LU/README.md b/nac-jurisdiction-rules/LU/README.md new file mode 100644 index 0000000..c28b74e --- /dev/null +++ b/nac-jurisdiction-rules/LU/README.md @@ -0,0 +1,58 @@ +# 卢森堡(Luxembourg) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | LU | +| 辖区名称 | 卢森堡(Luxembourg) | +| 监管机构 | CSSF(Commission de Surveillance du Secteur Financier) | +| 关键法律 | MiCA(EU成员国)& UCITS Directive & AIFMD | +| 授权CA | CSSF_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 CSSF_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 LU 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 LU 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 LU 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| LU_CSSF_001 | 数字资产业务须向CSSF申请授权 | +| LU_UCITS_001 | UCITS基金资产须符合UCITS指令第五版 | +| LU_AIFMD_001 | 另类投资基金须符合AIFMD指令 | +| LU_MICA_001 | 加密资产须符合MiCA法规(EU成员国) | +| LU_GDPR_001 | 个人数据处理须符合GDPR,禁止个人信息直接上链 | + +## 支持的资产类型 + +- UCITS基金份额 +- AIF基金份额 +- 债券 +- 证券型代币 +- 加密资产 + +## 禁止活动 + +- 未经CSSF授权的数字资产业务 +- 个人信息上链 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +LU 辖区与其他辖区**完全独立**。跨辖区交易时,LU 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/LU/constitution_rules.cnnl b/nac-jurisdiction-rules/LU/constitution_rules.cnnl new file mode 100644 index 0000000..09aeda0 --- /dev/null +++ b/nac-jurisdiction-rules/LU/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 卢森堡(Luxembourg) +// 监管机构:CSSF(Commission de Surveillance du Secteur Financier) +// 关键法律:MiCA(EU成员国)& UCITS Directive & AIFMD +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(CSSF_CA)签名后直接生效,无需链上投票 + +JURISDICTION LU { + name: "卢森堡(Luxembourg)" + regulator: "CSSF(Commission de Surveillance du Secteur Financier)" + key_law: "MiCA(EU成员国)& UCITS Directive & AIFMD" + ca_authority: "CSSF_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["UCITS基金份额", "AIF基金份额", "债券", "证券型代币", "加密资产"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["未经CSSF授权的数字资产业务", "个人信息上链"] +} + +CLAUSE LU_CSSF_001 { + jurisdiction: "LU" + type: "COMPLIANCE_RULE" + description: "数字资产业务须向CSSF申请授权" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE LU_UCITS_001 { + jurisdiction: "LU" + type: "COMPLIANCE_RULE" + description: "UCITS基金资产须符合UCITS指令第五版" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE LU_AIFMD_001 { + jurisdiction: "LU" + type: "COMPLIANCE_RULE" + description: "另类投资基金须符合AIFMD指令" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE LU_MICA_001 { + jurisdiction: "LU" + type: "COMPLIANCE_RULE" + description: "加密资产须符合MiCA法规(EU成员国)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE LU_GDPR_001 { + jurisdiction: "LU" + type: "COMPLIANCE_RULE" + description: "个人数据处理须符合GDPR,禁止个人信息直接上链" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/LU/protocol_template.charter b/nac-jurisdiction-rules/LU/protocol_template.charter new file mode 100644 index 0000000..ad2d8e9 --- /dev/null +++ b/nac-jurisdiction-rules/LU/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 卢森堡(Luxembourg) +// 监管机构:CSSF(Commission de Surveillance du Secteur Financier) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义LU辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract LUAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "LU"; + const REGULATOR: string = "CSSF(Commission de Surveillance du Secteur Financier)"; + const CA_AUTHORITY: string = "CSSF_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须CSSF_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["UCITS基金份额", "AIF基金份额", "债券", "证券型代币", "加密资产"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["未经CSSF授权的数字资产业务", "个人信息上链"]; +} diff --git a/nac-jurisdiction-rules/MT/README.md b/nac-jurisdiction-rules/MT/README.md new file mode 100644 index 0000000..e01e175 --- /dev/null +++ b/nac-jurisdiction-rules/MT/README.md @@ -0,0 +1,57 @@ +# 马耳他(Malta) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | MT | +| 辖区名称 | 马耳他(Malta) | +| 监管机构 | MFSA(Malta Financial Services Authority) | +| 关键法律 | Virtual Financial Assets Act 2018(VFA)& MiCA(EU成员国适用) | +| 授权CA | MFSA_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 MFSA_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 MT 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 MT 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 MT 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| MT_VFA_001 | 虚拟金融资产须通过MFSA的VFA测试(金融工具/电子货币/VFA) | +| MT_MICA_001 | 作为EU成员国,须同时符合MiCA法规 | +| MT_GDPR_001 | 个人数据处理须符合GDPR,禁止个人信息直接上链 | +| MT_AML_001 | 须符合EU第六反洗钱指令(6AMLD) | +| MT_AGENT_001 | 须通过MFSA认可的VFA代理人提交申请 | + +## 支持的资产类型 + +- 虚拟金融资产 +- 证券型代币 +- 实用型代币 +- 电子货币代币 + +## 禁止活动 + +- 未经VFA测试的资产发行 +- 个人信息上链 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +MT 辖区与其他辖区**完全独立**。跨辖区交易时,MT 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/MT/constitution_rules.cnnl b/nac-jurisdiction-rules/MT/constitution_rules.cnnl new file mode 100644 index 0000000..c77f8e6 --- /dev/null +++ b/nac-jurisdiction-rules/MT/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 马耳他(Malta) +// 监管机构:MFSA(Malta Financial Services Authority) +// 关键法律:Virtual Financial Assets Act 2018(VFA)& MiCA(EU成员国适用) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(MFSA_CA)签名后直接生效,无需链上投票 + +JURISDICTION MT { + name: "马耳他(Malta)" + regulator: "MFSA(Malta Financial Services Authority)" + key_law: "Virtual Financial Assets Act 2018(VFA)& MiCA(EU成员国适用)" + ca_authority: "MFSA_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["虚拟金融资产", "证券型代币", "实用型代币", "电子货币代币"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["未经VFA测试的资产发行", "个人信息上链"] +} + +CLAUSE MT_VFA_001 { + jurisdiction: "MT" + type: "COMPLIANCE_RULE" + description: "虚拟金融资产须通过MFSA的VFA测试(金融工具/电子货币/VFA)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MT_MICA_001 { + jurisdiction: "MT" + type: "COMPLIANCE_RULE" + description: "作为EU成员国,须同时符合MiCA法规" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MT_GDPR_001 { + jurisdiction: "MT" + type: "COMPLIANCE_RULE" + description: "个人数据处理须符合GDPR,禁止个人信息直接上链" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MT_AML_001 { + jurisdiction: "MT" + type: "COMPLIANCE_RULE" + description: "须符合EU第六反洗钱指令(6AMLD)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MT_AGENT_001 { + jurisdiction: "MT" + type: "COMPLIANCE_RULE" + description: "须通过MFSA认可的VFA代理人提交申请" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/MT/protocol_template.charter b/nac-jurisdiction-rules/MT/protocol_template.charter new file mode 100644 index 0000000..25de87a --- /dev/null +++ b/nac-jurisdiction-rules/MT/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 马耳他(Malta) +// 监管机构:MFSA(Malta Financial Services Authority) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义MT辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract MTAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "MT"; + const REGULATOR: string = "MFSA(Malta Financial Services Authority)"; + const CA_AUTHORITY: string = "MFSA_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须MFSA_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["虚拟金融资产", "证券型代币", "实用型代币", "电子货币代币"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["未经VFA测试的资产发行", "个人信息上链"]; +} diff --git a/nac-jurisdiction-rules/MU/README.md b/nac-jurisdiction-rules/MU/README.md new file mode 100644 index 0000000..003258f --- /dev/null +++ b/nac-jurisdiction-rules/MU/README.md @@ -0,0 +1,58 @@ +# 毛里求斯(Mauritius) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | MU | +| 辖区名称 | 毛里求斯(Mauritius) | +| 监管机构 | FSC(Financial Services Commission Mauritius) | +| 关键法律 | Virtual Asset and Initial Token Offering Services Act 2021(VAITOS) | +| 授权CA | MU_FSC_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 MU_FSC_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 MU 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 MU 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 MU 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| MU_VAITOS_001 | 虚拟资产服务须向FSC申请VAITOS牌照 | +| MU_AML_001 | 须符合毛里求斯反洗钱法规(FIAMLA 2002) | +| MU_KYC_001 | KYC须核实客户身份,保留7年记录 | +| MU_AFRICA_001 | 跨非洲辖区交易须符合非洲联盟数字资产框架 | +| MU_REPORT_001 | 年度向FSC提交VAITOS合规报告 | + +## 支持的资产类型 + +- 虚拟资产 +- 代币 +- 基金份额 +- 债券 +- 股权 + +## 禁止活动 + +- 未持VAITOS牌照的虚拟资产服务 +- 匿名交易 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +MU 辖区与其他辖区**完全独立**。跨辖区交易时,MU 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/MU/constitution_rules.cnnl b/nac-jurisdiction-rules/MU/constitution_rules.cnnl new file mode 100644 index 0000000..5cc1246 --- /dev/null +++ b/nac-jurisdiction-rules/MU/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 毛里求斯(Mauritius) +// 监管机构:FSC(Financial Services Commission Mauritius) +// 关键法律:Virtual Asset and Initial Token Offering Services Act 2021(VAITOS) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(MU_FSC_CA)签名后直接生效,无需链上投票 + +JURISDICTION MU { + name: "毛里求斯(Mauritius)" + regulator: "FSC(Financial Services Commission Mauritius)" + key_law: "Virtual Asset and Initial Token Offering Services Act 2021(VAITOS)" + ca_authority: "MU_FSC_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["虚拟资产", "代币", "基金份额", "债券", "股权"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["未持VAITOS牌照的虚拟资产服务", "匿名交易"] +} + +CLAUSE MU_VAITOS_001 { + jurisdiction: "MU" + type: "COMPLIANCE_RULE" + description: "虚拟资产服务须向FSC申请VAITOS牌照" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MU_AML_001 { + jurisdiction: "MU" + type: "COMPLIANCE_RULE" + description: "须符合毛里求斯反洗钱法规(FIAMLA 2002)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MU_KYC_001 { + jurisdiction: "MU" + type: "COMPLIANCE_RULE" + description: "KYC须核实客户身份,保留7年记录" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MU_AFRICA_001 { + jurisdiction: "MU" + type: "COMPLIANCE_RULE" + description: "跨非洲辖区交易须符合非洲联盟数字资产框架" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE MU_REPORT_001 { + jurisdiction: "MU" + type: "COMPLIANCE_RULE" + description: "年度向FSC提交VAITOS合规报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/MU/protocol_template.charter b/nac-jurisdiction-rules/MU/protocol_template.charter new file mode 100644 index 0000000..99c907b --- /dev/null +++ b/nac-jurisdiction-rules/MU/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 毛里求斯(Mauritius) +// 监管机构:FSC(Financial Services Commission Mauritius) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义MU辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract MUAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "MU"; + const REGULATOR: string = "FSC(Financial Services Commission Mauritius)"; + const CA_AUTHORITY: string = "MU_FSC_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须MU_FSC_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["虚拟资产", "代币", "基金份额", "债券", "股权"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["未持VAITOS牌照的虚拟资产服务", "匿名交易"]; +} diff --git a/nac-jurisdiction-rules/PA/README.md b/nac-jurisdiction-rules/PA/README.md new file mode 100644 index 0000000..daf28d8 --- /dev/null +++ b/nac-jurisdiction-rules/PA/README.md @@ -0,0 +1,57 @@ +# 巴拿马(Panama) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | PA | +| 辖区名称 | 巴拿马(Panama) | +| 监管机构 | SBP(Superintendencia de Bancos de Panamá) | +| 关键法律 | Ley 23 de 2015(反洗钱)& Decreto Ejecutivo 122 de 2021(数字资产) | +| 授权CA | PA_SBP_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 PA_SBP_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 PA 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 PA 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 PA 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| PA_SBP_001 | 数字资产业务须向SBP申请授权 | +| PA_AML_001 | 须符合巴拿马第23号法律(反洗钱/反恐融资) | +| PA_KYC_001 | KYC须核实客户身份,保留10年记录 | +| PA_FATF_001 | 须符合FATF建议(巴拿马已从灰名单移除) | +| PA_REPORT_001 | 季度向SBP提交数字资产业务报告 | + +## 支持的资产类型 + +- 数字资产 +- 代币 +- 股权 +- 债券 + +## 禁止活动 + +- 未经SBP授权的数字资产业务 +- 匿名交易 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +PA 辖区与其他辖区**完全独立**。跨辖区交易时,PA 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/PA/constitution_rules.cnnl b/nac-jurisdiction-rules/PA/constitution_rules.cnnl new file mode 100644 index 0000000..faf01e4 --- /dev/null +++ b/nac-jurisdiction-rules/PA/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 巴拿马(Panama) +// 监管机构:SBP(Superintendencia de Bancos de Panamá) +// 关键法律:Ley 23 de 2015(反洗钱)& Decreto Ejecutivo 122 de 2021(数字资产) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(PA_SBP_CA)签名后直接生效,无需链上投票 + +JURISDICTION PA { + name: "巴拿马(Panama)" + regulator: "SBP(Superintendencia de Bancos de Panamá)" + key_law: "Ley 23 de 2015(反洗钱)& Decreto Ejecutivo 122 de 2021(数字资产)" + ca_authority: "PA_SBP_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["数字资产", "代币", "股权", "债券"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["未经SBP授权的数字资产业务", "匿名交易"] +} + +CLAUSE PA_SBP_001 { + jurisdiction: "PA" + type: "COMPLIANCE_RULE" + description: "数字资产业务须向SBP申请授权" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE PA_AML_001 { + jurisdiction: "PA" + type: "COMPLIANCE_RULE" + description: "须符合巴拿马第23号法律(反洗钱/反恐融资)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE PA_KYC_001 { + jurisdiction: "PA" + type: "COMPLIANCE_RULE" + description: "KYC须核实客户身份,保留10年记录" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE PA_FATF_001 { + jurisdiction: "PA" + type: "COMPLIANCE_RULE" + description: "须符合FATF建议(巴拿马已从灰名单移除)" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE PA_REPORT_001 { + jurisdiction: "PA" + type: "COMPLIANCE_RULE" + description: "季度向SBP提交数字资产业务报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/PA/protocol_template.charter b/nac-jurisdiction-rules/PA/protocol_template.charter new file mode 100644 index 0000000..6d3c09f --- /dev/null +++ b/nac-jurisdiction-rules/PA/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 巴拿马(Panama) +// 监管机构:SBP(Superintendencia de Bancos de Panamá) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义PA辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract PAAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "PA"; + const REGULATOR: string = "SBP(Superintendencia de Bancos de Panamá)"; + const CA_AUTHORITY: string = "PA_SBP_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须PA_SBP_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["数字资产", "代币", "股权", "债券"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["未经SBP授权的数字资产业务", "匿名交易"]; +} diff --git a/nac-jurisdiction-rules/VG/README.md b/nac-jurisdiction-rules/VG/README.md new file mode 100644 index 0000000..74cd372 --- /dev/null +++ b/nac-jurisdiction-rules/VG/README.md @@ -0,0 +1,58 @@ +# 英属维京群岛(British Virgin Islands) 辖区宪法规则 + +## 基本信息 + +| 项目 | 内容 | +|------|------| +| 辖区代码 | VG | +| 辖区名称 | 英属维京群岛(British Virgin Islands) | +| 监管机构 | FSC(Financial Services Commission) | +| 关键法律 | BVI Business Companies Act 2004 & Virtual Assets Service Providers Act 2022 | +| 授权CA | VG_FSC_CA | +| 辖区层级 | Tier 2(离岸金融中心) | + +## CBPP 四大原则在本辖区的体现 + +**约法即是治法**:本辖区宪法规则由 VG_FSC_CA 签名授权后直接生效,无需链上投票。 + +**宪法即是规则**:所有在 VG 辖区发生的链上交易,其合法性由本辖区宪法规则判定,没有宪法外的规则。 + +**参与即是共识**:节点加载本辖区插件并参与区块生产,即代表对 VG 辖区宪法规则的背书,无需额外的多签或投票确认。 + +**节点产生区块,交易决定区块大小**:区块大小由 VG 辖区的实际交易量动态决定,不设固定上限。 + +## 宪法规则条款 + +| 规则编号 | 规则描述 | +|---------|---------| +| VG_VASP_001 | 虚拟资产服务商须向FSC申请VASP牌照 | +| VG_BVI_001 | BVI公司须在公司注册处登记,保留受益所有人信息 | +| VG_AML_001 | 须符合防洗钱及恐怖融资(防制)法规 | +| VG_KYC_001 | KYC须核实最终受益人(UBO)至25%持股门槛 | +| VG_REPORT_001 | 向FSC提交年度合规报告 | + +## 支持的资产类型 + +- 股权 +- 债券 +- 基金份额 +- 虚拟资产 +- 知识产权 + +## 禁止活动 + +- 无牌照VASP运营 +- 匿名壳公司 + +## 文件说明 + +| 文件 | 说明 | +|------|------| +| `constitution_rules.cnnl` | CNNL 形式化宪法规则描述 | +| `jurisdiction_plugin.rs` | Rust CEE 验证插件(各辖区独立出具 CR) | +| `protocol_template.charter` | Charter 智能合约协议模板 | +| `README.md` | 本文件 | + +## 与其他辖区的关系 + +VG 辖区与其他辖区**完全独立**。跨辖区交易时,VG 辖区节点独立出具本辖区的 CR,目标辖区节点独立出具目标辖区的 CR,双方 CR 各自独立,互不依赖。这是 CBPP"参与即是共识"原则的体现。 diff --git a/nac-jurisdiction-rules/VG/constitution_rules.cnnl b/nac-jurisdiction-rules/VG/constitution_rules.cnnl new file mode 100644 index 0000000..9bfa025 --- /dev/null +++ b/nac-jurisdiction-rules/VG/constitution_rules.cnnl @@ -0,0 +1,59 @@ +// NAC 宪法层辖区规则 — 英属维京群岛(British Virgin Islands) +// 监管机构:FSC(Financial Services Commission) +// 关键法律:BVI Business Companies Act 2004 & Virtual Assets Service Providers Act 2022 +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 生效方式:辖区授权CA(VG_FSC_CA)签名后直接生效,无需链上投票 + +JURISDICTION VG { + name: "英属维京群岛(British Virgin Islands)" + regulator: "FSC(Financial Services Commission)" + key_law: "BVI Business Companies Act 2004 & Virtual Assets Service Providers Act 2022" + ca_authority: "VG_FSC_CA" + tier: "TIER_2" + + // 支持的资产类型 + supported_asset_types: ["股权", "债券", "基金份额", "虚拟资产", "知识产权"] + + // 禁止事项(直接生效,无需投票) + prohibited_activities: ["无牌照VASP运营", "匿名壳公司"] +} + +CLAUSE VG_VASP_001 { + jurisdiction: "VG" + type: "COMPLIANCE_RULE" + description: "虚拟资产服务商须向FSC申请VASP牌照" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE VG_BVI_001 { + jurisdiction: "VG" + type: "COMPLIANCE_RULE" + description: "BVI公司须在公司注册处登记,保留受益所有人信息" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE VG_AML_001 { + jurisdiction: "VG" + type: "COMPLIANCE_RULE" + description: "须符合防洗钱及恐怖融资(防制)法规" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE VG_KYC_001 { + jurisdiction: "VG" + type: "COMPLIANCE_RULE" + description: "KYC须核实最终受益人(UBO)至25%持股门槛" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} + +CLAUSE VG_REPORT_001 { + jurisdiction: "VG" + type: "COMPLIANCE_RULE" + description: "向FSC提交年度合规报告" + enforcement: "CA_SIGNED" // 辖区授权CA签名后直接生效,无需链上投票(约法即是治法) + effective_immediately: true +} diff --git a/nac-jurisdiction-rules/VG/protocol_template.charter b/nac-jurisdiction-rules/VG/protocol_template.charter new file mode 100644 index 0000000..025c118 --- /dev/null +++ b/nac-jurisdiction-rules/VG/protocol_template.charter @@ -0,0 +1,101 @@ +// Charter 智能合约协议模板 — 英属维京群岛(British Virgin Islands) +// 监管机构:FSC(Financial Services Commission) +// CBPP 原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// +// 本模板定义VG辖区内资产上链的标准协议 +// 合规验证由 CEE(Constitutional Execution Engine)在节点层执行 +// 节点参与出块即代表对本辖区宪法规则的背书(参与即是共识) + +contract VGAssetProtocol { + // 辖区标识 + const JURISDICTION: string = "VG"; + const REGULATOR: string = "FSC(Financial Services Commission)"; + const CA_AUTHORITY: string = "VG_FSC_CA"; + + // 资产结构 + struct Asset { + id: Hash, // 48字节 SHA3-384 + owner: Address, // 32字节 + asset_type: string, + jurisdiction: string, + compliance_cr: Hash, // 合规收据哈希(由CEE出具,参与即是共识) + created_at: u64, + metadata: bytes, + } + + // 合规收据结构(由CEE独立出具,无需多签) + struct ConstitutionalReceipt { + jurisdiction: string, + passed: bool, + applied_rules: []string, + ca_authority: string, + timestamp: u64, + } + + // 资产注册(须持有有效合规收据) + // 约法即是治法:宪法规则由CEE在节点层强制执行 + fn register_asset( + asset_type: string, + metadata: bytes, + compliance_cr: Hash, + ) -> Hash { + // 验证合规收据(CEE已在节点层验证,此处确认收据存在) + require(compliance_cr != Hash::zero(), "须提供有效合规收据"); + require(asset_type in SUPPORTED_ASSET_TYPES, "不支持的资产类型"); + + let asset_id = Hash::from_data(caller() ++ asset_type ++ now()); + + emit AssetRegistered { + id: asset_id, + owner: caller(), + asset_type: asset_type, + jurisdiction: JURISDICTION, + compliance_cr: compliance_cr, + }; + + return asset_id; + } + + // 资产转移(须重新验证合规) + // 参与即是共识:转移交易由节点验证,节点参与出块即代表对宪法规则的背书 + fn transfer_asset( + asset_id: Hash, + to: Address, + new_compliance_cr: Hash, + ) -> bool { + require(new_compliance_cr != Hash::zero(), "须提供新的合规收据"); + + emit AssetTransferred { + id: asset_id, + from: caller(), + to: to, + compliance_cr: new_compliance_cr, + }; + + return true; + } + + // 辖区规则更新(须辖区授权CA签名,直接生效,无需链上投票) + // 约法即是治法:CA签名即是法律授权,无需额外的链上治理投票 + fn update_jurisdiction_rules( + new_rules_hash: Hash, + ca_signature: bytes, + ) -> bool { + require(verify_ca_signature(ca_signature, CA_AUTHORITY), "须VG_FSC_CA签名授权"); + + emit JurisdictionRulesUpdated { + jurisdiction: JURISDICTION, + new_rules_hash: new_rules_hash, + ca_authority: CA_AUTHORITY, + effective_at: now(), // 签名即生效,无需等待投票 + }; + + return true; + } + + // 支持的资产类型 + const SUPPORTED_ASSET_TYPES: []string = ["股权", "债券", "基金份额", "虚拟资产", "知识产权"]; + + // 禁止活动(直接生效) + const PROHIBITED_ACTIVITIES: []string = ["无牌照VASP运营", "匿名壳公司"]; +} diff --git a/nac-jurisdiction-rules/src/br.rs b/nac-jurisdiction-rules/src/br.rs new file mode 100644 index 0000000..e8bedfa --- /dev/null +++ b/nac-jurisdiction-rules/src/br.rs @@ -0,0 +1,217 @@ +// NAC BR 辖区宪法规则验证插件 +// 监管机构:CVM/BCB (Comissão de Valores Mobiliários / Banco Central do Brasil) +// 法律框架:Lei 14.478/2022 (VASP) / Lei 6.385/1976 (Securities) +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:BR辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "BR"; +const AML_THRESHOLD_USD: f64 = 10000.0; + +/// BR 辖区交易上下文(巴西) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BRTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// BR 辖区宪法规则验证引擎 +pub struct BRJurisdictionPlugin; + +impl BRJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Enhanced) + fn check_kyc_level(tx: &BRTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Enhanced | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Enhanced" == "Enhanced") + } + + /// AML 阈值检查(10000 USD) + fn check_aml_threshold(tx: &BRTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 CVM/BCB (Comissão de Valores Mobiliários / Banco Central do Brasil) 报告 + // 约法即是治法:此要求直接来自 Lei 14.478/2022 (VASP) / Lei 6.385/1976 (Securities) + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &BRTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &BRTxContext) -> bool { + // Rule: VASP registration with BCB mandatory + // Rule: CPF/CNPJ identity verification required + // Rule: BRL conversion reporting above BRL 10,000 + // Rule: CVM oversight for security tokens + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &BRTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl BRJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &BRTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("BR_KYC: Minimum level Enhanced required per {}", + "CVM/BCB (Comissão de Valores Mobiliários / Banco Central do Brasil)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("BR_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "CVM/BCB (Comissão de Valores Mobiliários / Banco Central do Brasil)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "BR_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "BR_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "CVM/BCB (Comissão de Valores Mobiliários / Banco Central do Brasil)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> BRTxContext { + BRTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_br_valid_transaction() { + let plugin = BRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_br_kyc_insufficient() { + let plugin = BRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_br_aml_threshold_exceeded_unreported() { + let plugin = BRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_br_aml_threshold_reported() { + let plugin = BRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_br_anonymous_rejected() { + let plugin = BRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_br_jurisdiction_code() { + let plugin = BRJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "BR"); + } + + #[test] + fn test_br_regulatory_authority() { + let plugin = BRJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/id.rs b/nac-jurisdiction-rules/src/id.rs new file mode 100644 index 0000000..7305162 --- /dev/null +++ b/nac-jurisdiction-rules/src/id.rs @@ -0,0 +1,217 @@ +// NAC ID 辖区宪法规则验证插件 +// 监管机构:OJK/Bappebti (Otoritas Jasa Keuangan / Commodity Futures Trading Regulatory Agency) +// 法律框架:Peraturan Bappebti No. 8/2021 (Crypto Asset Trading) +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:ID辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "ID"; +const AML_THRESHOLD_USD: f64 = 10000.0; + +/// ID 辖区交易上下文(印度尼西亚) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct IDTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// ID 辖区宪法规则验证引擎 +pub struct IDJurisdictionPlugin; + +impl IDJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Enhanced) + fn check_kyc_level(tx: &IDTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Enhanced | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Enhanced" == "Enhanced") + } + + /// AML 阈值检查(10000 USD) + fn check_aml_threshold(tx: &IDTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 OJK/Bappebti (Otoritas Jasa Keuangan / Commodity Futures Trading Regulatory Agency) 报告 + // 约法即是治法:此要求直接来自 Peraturan Bappebti No. 8/2021 (Crypto Asset Trading) + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &IDTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &IDTxContext) -> bool { + // Rule: Only Bappebti-approved crypto assets can be traded (whitelist) + // Rule: Indonesian NIK KYC mandatory + // Rule: IDR reporting above IDR 100,000,000 + // Rule: PPATK suspicious transaction reporting mandatory + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &IDTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl IDJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &IDTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("ID_KYC: Minimum level Enhanced required per {}", + "OJK/Bappebti (Otoritas Jasa Keuangan / Commodity Futures Trading Regulatory Agency)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("ID_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "OJK/Bappebti (Otoritas Jasa Keuangan / Commodity Futures Trading Regulatory Agency)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "ID_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "ID_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "OJK/Bappebti (Otoritas Jasa Keuangan / Commodity Futures Trading Regulatory Agency)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> IDTxContext { + IDTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_id_valid_transaction() { + let plugin = IDJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_id_kyc_insufficient() { + let plugin = IDJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_id_aml_threshold_exceeded_unreported() { + let plugin = IDJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_id_aml_threshold_reported() { + let plugin = IDJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_id_anonymous_rejected() { + let plugin = IDJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_id_jurisdiction_code() { + let plugin = IDJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "ID"); + } + + #[test] + fn test_id_regulatory_authority() { + let plugin = IDJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/in_jurisdiction.rs b/nac-jurisdiction-rules/src/in_jurisdiction.rs new file mode 100644 index 0000000..cbe46e0 --- /dev/null +++ b/nac-jurisdiction-rules/src/in_jurisdiction.rs @@ -0,0 +1,217 @@ +// NAC IN 辖区宪法规则验证插件 +// 监管机构:SEBI/RBI (Securities and Exchange Board / Reserve Bank of India) +// 法律框架:Finance Act 2022 (VDA 30% tax) / PMLA 2002 / FEMA 1999 +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:IN辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "IN"; +const AML_THRESHOLD_USD: f64 = 5000.0; + +/// IN 辖区交易上下文(印度) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct INTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// IN 辖区宪法规则验证引擎 +pub struct INJurisdictionPlugin; + +impl INJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Institutional) + fn check_kyc_level(tx: &INTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Institutional | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Institutional" == "Enhanced") + } + + /// AML 阈值检查(5000 USD) + fn check_aml_threshold(tx: &INTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 SEBI/RBI (Securities and Exchange Board / Reserve Bank of India) 报告 + // 约法即是治法:此要求直接来自 Finance Act 2022 (VDA 30% tax) / PMLA 2002 / FEMA 1999 + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &INTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &INTxContext) -> bool { + // Rule: 30% flat tax on VDA gains under Finance Act 2022 + // Rule: 1% TDS on VDA transfers above INR 50,000 + // Rule: PAN/Aadhaar KYC mandatory + // Rule: FEMA compliance for cross-border transfers + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &INTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl INJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &INTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("IN_KYC: Minimum level Institutional required per {}", + "SEBI/RBI (Securities and Exchange Board / Reserve Bank of India)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("IN_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "SEBI/RBI (Securities and Exchange Board / Reserve Bank of India)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "IN_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "IN_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "SEBI/RBI (Securities and Exchange Board / Reserve Bank of India)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> INTxContext { + INTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_in_valid_transaction() { + let plugin = INJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_in_kyc_insufficient() { + let plugin = INJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_in_aml_threshold_exceeded_unreported() { + let plugin = INJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 6000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_in_aml_threshold_reported() { + let plugin = INJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 6000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_in_anonymous_rejected() { + let plugin = INJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_in_jurisdiction_code() { + let plugin = INJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "IN"); + } + + #[test] + fn test_in_regulatory_authority() { + let plugin = INJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/lib.rs b/nac-jurisdiction-rules/src/lib.rs index 795f609..aec577b 100644 --- a/nac-jurisdiction-rules/src/lib.rs +++ b/nac-jurisdiction-rules/src/lib.rs @@ -25,3 +25,15 @@ pub mod je; pub mod im; pub mod pa; pub mod mu; + +// Tier 3 Emerging Market Jurisdictions +pub mod br; +pub mod in_jurisdiction; // India ("in" is a Rust keyword) +pub mod th; +pub mod id; +pub mod ng; +pub mod mx; +pub mod za; +pub mod tr; +pub mod sa; +pub mod ru; diff --git a/nac-jurisdiction-rules/src/mx.rs b/nac-jurisdiction-rules/src/mx.rs new file mode 100644 index 0000000..d0a25cb --- /dev/null +++ b/nac-jurisdiction-rules/src/mx.rs @@ -0,0 +1,217 @@ +// NAC MX 辖区宪法规则验证插件 +// 监管机构:CNBV/Banxico (Comisión Nacional Bancaria y de Valores / Bank of Mexico) +// 法律框架:Ley Fintech 2018 / CNBV Circular 4/2019 +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:MX辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "MX"; +const AML_THRESHOLD_USD: f64 = 10000.0; + +/// MX 辖区交易上下文(墨西哥) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MXTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// MX 辖区宪法规则验证引擎 +pub struct MXJurisdictionPlugin; + +impl MXJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Enhanced) + fn check_kyc_level(tx: &MXTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Enhanced | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Enhanced" == "Enhanced") + } + + /// AML 阈值检查(10000 USD) + fn check_aml_threshold(tx: &MXTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 CNBV/Banxico (Comisión Nacional Bancaria y de Valores / Bank of Mexico) 报告 + // 约法即是治法:此要求直接来自 Ley Fintech 2018 / CNBV Circular 4/2019 + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &MXTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &MXTxContext) -> bool { + // Rule: ITF license required from CNBV + // Rule: CURP/RFC identity verification mandatory + // Rule: MXN reporting above MXN 200,000 + // Rule: UIF suspicious transaction reporting mandatory + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &MXTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl MXJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &MXTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("MX_KYC: Minimum level Enhanced required per {}", + "CNBV/Banxico (Comisión Nacional Bancaria y de Valores / Bank of Mexico)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("MX_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "CNBV/Banxico (Comisión Nacional Bancaria y de Valores / Bank of Mexico)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "MX_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "MX_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "CNBV/Banxico (Comisión Nacional Bancaria y de Valores / Bank of Mexico)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> MXTxContext { + MXTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_mx_valid_transaction() { + let plugin = MXJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_mx_kyc_insufficient() { + let plugin = MXJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_mx_aml_threshold_exceeded_unreported() { + let plugin = MXJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_mx_aml_threshold_reported() { + let plugin = MXJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_mx_anonymous_rejected() { + let plugin = MXJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_mx_jurisdiction_code() { + let plugin = MXJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "MX"); + } + + #[test] + fn test_mx_regulatory_authority() { + let plugin = MXJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/ng.rs b/nac-jurisdiction-rules/src/ng.rs new file mode 100644 index 0000000..4a58538 --- /dev/null +++ b/nac-jurisdiction-rules/src/ng.rs @@ -0,0 +1,217 @@ +// NAC NG 辖区宪法规则验证插件 +// 监管机构:SEC Nigeria / CBN (Central Bank of Nigeria) +// 法律框架:Investments and Securities Act 2007 / SEC Nigeria Digital Assets Rules 2022 +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:NG辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "NG"; +const AML_THRESHOLD_USD: f64 = 10000.0; + +/// NG 辖区交易上下文(尼日利亚) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NGTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// NG 辖区宪法规则验证引擎 +pub struct NGJurisdictionPlugin; + +impl NGJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Enhanced) + fn check_kyc_level(tx: &NGTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Enhanced | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Enhanced" == "Enhanced") + } + + /// AML 阈值检查(10000 USD) + fn check_aml_threshold(tx: &NGTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 SEC Nigeria / CBN (Central Bank of Nigeria) 报告 + // 约法即是治法:此要求直接来自 Investments and Securities Act 2007 / SEC Nigeria Digital Assets Rules 2022 + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &NGTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &NGTxContext) -> bool { + // Rule: SEC Nigeria registration required for digital asset platforms + // Rule: BVN (Bank Verification Number) KYC mandatory + // Rule: NGN transactions above NGN 5,000,000 require NFIU reporting + // Rule: EFCC cooperation mandatory + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &NGTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl NGJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &NGTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("NG_KYC: Minimum level Enhanced required per {}", + "SEC Nigeria / CBN (Central Bank of Nigeria)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("NG_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "SEC Nigeria / CBN (Central Bank of Nigeria)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "NG_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "NG_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "SEC Nigeria / CBN (Central Bank of Nigeria)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> NGTxContext { + NGTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_ng_valid_transaction() { + let plugin = NGJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_ng_kyc_insufficient() { + let plugin = NGJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_ng_aml_threshold_exceeded_unreported() { + let plugin = NGJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_ng_aml_threshold_reported() { + let plugin = NGJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_ng_anonymous_rejected() { + let plugin = NGJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_ng_jurisdiction_code() { + let plugin = NGJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "NG"); + } + + #[test] + fn test_ng_regulatory_authority() { + let plugin = NGJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/ru.rs b/nac-jurisdiction-rules/src/ru.rs new file mode 100644 index 0000000..37c5a1e --- /dev/null +++ b/nac-jurisdiction-rules/src/ru.rs @@ -0,0 +1,217 @@ +// NAC RU 辖区宪法规则验证插件 +// 监管机构:CBR/Rosfinmonitoring (Central Bank of Russia / Federal Financial Monitoring Service) +// 法律框架:Federal Law No. 259-FZ on Digital Financial Assets (2021) / Federal Law No. 115-FZ +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:RU辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "RU"; +const AML_THRESHOLD_USD: f64 = 5000.0; + +/// RU 辖区交易上下文(俄罗斯) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RUTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// RU 辖区宪法规则验证引擎 +pub struct RUJurisdictionPlugin; + +impl RUJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Institutional) + fn check_kyc_level(tx: &RUTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Institutional | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Institutional" == "Enhanced") + } + + /// AML 阈值检查(5000 USD) + fn check_aml_threshold(tx: &RUTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 CBR/Rosfinmonitoring (Central Bank of Russia / Federal Financial Monitoring Service) 报告 + // 约法即是治法:此要求直接来自 Federal Law No. 259-FZ on Digital Financial Assets (2021) / Federal Law No. 115-FZ + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &RUTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &RUTxContext) -> bool { + // Rule: DFA issuance requires CBR-licensed operator + // Rule: Russian passport/SNILS KYC mandatory + // Rule: RUB reporting above RUB 600,000 + // Rule: Prohibition on using crypto as payment in Russia + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &RUTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl RUJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &RUTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("RU_KYC: Minimum level Institutional required per {}", + "CBR/Rosfinmonitoring (Central Bank of Russia / Federal Financial Monitoring Service)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("RU_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "CBR/Rosfinmonitoring (Central Bank of Russia / Federal Financial Monitoring Service)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "RU_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "RU_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "CBR/Rosfinmonitoring (Central Bank of Russia / Federal Financial Monitoring Service)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> RUTxContext { + RUTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_ru_valid_transaction() { + let plugin = RUJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_ru_kyc_insufficient() { + let plugin = RUJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_ru_aml_threshold_exceeded_unreported() { + let plugin = RUJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 6000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_ru_aml_threshold_reported() { + let plugin = RUJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 6000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_ru_anonymous_rejected() { + let plugin = RUJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_ru_jurisdiction_code() { + let plugin = RUJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "RU"); + } + + #[test] + fn test_ru_regulatory_authority() { + let plugin = RUJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/sa.rs b/nac-jurisdiction-rules/src/sa.rs new file mode 100644 index 0000000..c25dd75 --- /dev/null +++ b/nac-jurisdiction-rules/src/sa.rs @@ -0,0 +1,232 @@ +// NAC SA 辖区宪法规则验证插件 +// 监管机构:CMA/SAMA (Capital Market Authority / Saudi Arabian Monetary Authority) +// 法律框架:Capital Market Law / SAMA Fintech Framework / Vision 2030 +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:SA辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "SA"; +const AML_THRESHOLD_USD: f64 = 10000.0; + +/// SA 辖区交易上下文(沙特阿拉伯) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SATxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + pub is_shariah_compliant: bool, +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// SA 辖区宪法规则验证引擎 +pub struct SAJurisdictionPlugin; + +impl SAJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Institutional) + fn check_kyc_level(tx: &SATxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Institutional | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Institutional" == "Enhanced") + } + + /// AML 阈值检查(10000 USD) + fn check_aml_threshold(tx: &SATxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 CMA/SAMA (Capital Market Authority / Saudi Arabian Monetary Authority) 报告 + // 约法即是治法:此要求直接来自 Capital Market Law / SAMA Fintech Framework / Vision 2030 + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &SATxContext) -> bool { + tx.sanctions_cleared + } + + fn check_shariah_compliance(tx: &SATxContext) -> bool { + // 伊斯兰金融合规:禁止 Riba(利息),仅允许 Shariah 合规资产 + // 约法即是治法:此规则直接来自 CMA/SAMA 的伊斯兰金融法规 + tx.is_shariah_compliant && !tx.asset_type.contains("interest") + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &SATxContext) -> bool { + // Rule: CMA sandbox participation required + // Rule: Saudi National ID / Iqama KYC mandatory + // Rule: SAR reporting above SAR 37,500 + // Rule: Islamic finance Shariah compliance mandatory + // Rule: Prohibition on Riba (interest) + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &SATxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl SAJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &SATxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("SA_KYC: Minimum level Institutional required per {}", + "CMA/SAMA (Capital Market Authority / Saudi Arabian Monetary Authority)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("SA_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "CMA/SAMA (Capital Market Authority / Saudi Arabian Monetary Authority)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "SA_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "SA_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 伊斯兰金融合规检查(SA 辖区专属) + if !Self::check_shariah_compliance(tx) { + return ValidationResult::Rejected { + reason: "SA_SHARIAH_COMPLIANCE: Asset must be Shariah-compliant, Riba is prohibited".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "CMA/SAMA (Capital Market Authority / Saudi Arabian Monetary Authority)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> SATxContext { + SATxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + is_shariah_compliant: true, + } + } + + #[test] + fn test_sa_valid_transaction() { + let plugin = SAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_sa_kyc_insufficient() { + let plugin = SAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_sa_aml_threshold_exceeded_unreported() { + let plugin = SAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 11000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_sa_aml_threshold_reported() { + let plugin = SAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 11000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_sa_anonymous_rejected() { + let plugin = SAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Institutional, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_sa_jurisdiction_code() { + let plugin = SAJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "SA"); + } + + #[test] + fn test_sa_regulatory_authority() { + let plugin = SAJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/th.rs b/nac-jurisdiction-rules/src/th.rs new file mode 100644 index 0000000..e983afb --- /dev/null +++ b/nac-jurisdiction-rules/src/th.rs @@ -0,0 +1,217 @@ +// NAC TH 辖区宪法规则验证插件 +// 监管机构:SEC Thailand (Securities and Exchange Commission) +// 法律框架:Digital Asset Business Act B.E. 2561 (2018) +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:TH辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "TH"; +const AML_THRESHOLD_USD: f64 = 15000.0; + +/// TH 辖区交易上下文(泰国) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct THTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// TH 辖区宪法规则验证引擎 +pub struct THJurisdictionPlugin; + +impl THJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Enhanced) + fn check_kyc_level(tx: &THTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Enhanced | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Enhanced" == "Enhanced") + } + + /// AML 阈值检查(15000 USD) + fn check_aml_threshold(tx: &THTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 SEC Thailand (Securities and Exchange Commission) 报告 + // 约法即是治法:此要求直接来自 Digital Asset Business Act B.E. 2561 (2018) + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &THTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &THTxContext) -> bool { + // Rule: Digital asset exchange license required from SEC Thailand + // Rule: THB reporting above THB 500,000 + // Rule: SEC Thailand approval required for ICO/IEO + // Rule: AMLO anti-money laundering reporting mandatory + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &THTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl THJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &THTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("TH_KYC: Minimum level Enhanced required per {}", + "SEC Thailand (Securities and Exchange Commission)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("TH_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "SEC Thailand (Securities and Exchange Commission)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "TH_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "TH_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "SEC Thailand (Securities and Exchange Commission)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> THTxContext { + THTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_th_valid_transaction() { + let plugin = THJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_th_kyc_insufficient() { + let plugin = THJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_th_aml_threshold_exceeded_unreported() { + let plugin = THJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 16000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_th_aml_threshold_reported() { + let plugin = THJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 16000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_th_anonymous_rejected() { + let plugin = THJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_th_jurisdiction_code() { + let plugin = THJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "TH"); + } + + #[test] + fn test_th_regulatory_authority() { + let plugin = THJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/tr.rs b/nac-jurisdiction-rules/src/tr.rs new file mode 100644 index 0000000..52fee25 --- /dev/null +++ b/nac-jurisdiction-rules/src/tr.rs @@ -0,0 +1,217 @@ +// NAC TR 辖区宪法规则验证插件 +// 监管机构:SPK/BDDK (Capital Markets Board / Banking Regulation and Supervision Agency) +// 法律框架:Capital Markets Law No. 6362 / Crypto Asset Service Providers Regulation 2021 +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:TR辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "TR"; +const AML_THRESHOLD_USD: f64 = 15000.0; + +/// TR 辖区交易上下文(土耳其) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TRTxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// TR 辖区宪法规则验证引擎 +pub struct TRJurisdictionPlugin; + +impl TRJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Enhanced) + fn check_kyc_level(tx: &TRTxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Enhanced | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Enhanced" == "Enhanced") + } + + /// AML 阈值检查(15000 USD) + fn check_aml_threshold(tx: &TRTxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 SPK/BDDK (Capital Markets Board / Banking Regulation and Supervision Agency) 报告 + // 约法即是治法:此要求直接来自 Capital Markets Law No. 6362 / Crypto Asset Service Providers Regulation 2021 + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &TRTxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &TRTxContext) -> bool { + // Rule: CASP license required from SPK + // Rule: Turkish TC Kimlik No KYC mandatory + // Rule: TRY reporting above TRY 75,000 + // Rule: Prohibition on using crypto as payment instruments (CBRT 2021) + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &TRTxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl TRJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &TRTxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("TR_KYC: Minimum level Enhanced required per {}", + "SPK/BDDK (Capital Markets Board / Banking Regulation and Supervision Agency)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("TR_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "SPK/BDDK (Capital Markets Board / Banking Regulation and Supervision Agency)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "TR_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "TR_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "SPK/BDDK (Capital Markets Board / Banking Regulation and Supervision Agency)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> TRTxContext { + TRTxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_tr_valid_transaction() { + let plugin = TRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_tr_kyc_insufficient() { + let plugin = TRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_tr_aml_threshold_exceeded_unreported() { + let plugin = TRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 16000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_tr_aml_threshold_reported() { + let plugin = TRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 16000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_tr_anonymous_rejected() { + let plugin = TRJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_tr_jurisdiction_code() { + let plugin = TRJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "TR"); + } + + #[test] + fn test_tr_regulatory_authority() { + let plugin = TRJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-rules/src/za.rs b/nac-jurisdiction-rules/src/za.rs new file mode 100644 index 0000000..b891156 --- /dev/null +++ b/nac-jurisdiction-rules/src/za.rs @@ -0,0 +1,217 @@ +// NAC ZA 辖区宪法规则验证插件 +// 监管机构:FSCA/SARB (Financial Sector Conduct Authority / South African Reserve Bank) +// 法律框架:FSCA Declaration 2022 / FICA / POPIA +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// 参与即是共识:ZA辖区节点加载此插件参与出块,即代表对本辖区宪法规则的背书 +// NAC_Lens 4.0 路由层自动处理跨辖区消息传递 + +use serde::{Deserialize, Serialize}; + +const JURISDICTION_CODE: &str = "ZA"; +const AML_THRESHOLD_USD: f64 = 10000.0; + +/// ZA 辖区交易上下文(南非) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ZATxContext { + pub tx_hash: String, + pub from: [u8; 32], + pub to: [u8; 32], + pub amount_usd: f64, + pub asset_type: String, + pub kyc_level: KycLevel, + pub aml_reported: bool, + pub is_anonymous: bool, + pub is_cross_border: bool, + pub sanctions_cleared: bool, + +} + +/// KYC 等级 +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum KycLevel { + None, + Basic, + Enhanced, + Institutional, +} + +/// 验证结果 +#[derive(Debug, Clone)] +pub enum ValidationResult { + Approved { + jurisdiction: String, + /// 宪法收据(CR):参与即是共识,节点独立出具,无需多签 + constitutional_receipt: String, + }, + Rejected { + reason: String, + jurisdiction: String, + }, +} + +/// ZA 辖区宪法规则验证引擎 +pub struct ZAJurisdictionPlugin; + +impl ZAJurisdictionPlugin { + pub fn new() -> Self { + Self + } + + /// KYC 等级验证(最低要求:Enhanced) + fn check_kyc_level(tx: &ZATxContext) -> bool { + matches!(tx.kyc_level, KycLevel::Enhanced | KycLevel::Institutional) + || (tx.kyc_level == KycLevel::Enhanced && "Enhanced" == "Enhanced") + } + + /// AML 阈值检查(10000 USD) + fn check_aml_threshold(tx: &ZATxContext) -> bool { + if tx.amount_usd > AML_THRESHOLD_USD { + // 超过阈值需要向 FSCA/SARB (Financial Sector Conduct Authority / South African Reserve Bank) 报告 + // 约法即是治法:此要求直接来自 FSCA Declaration 2022 / FICA / POPIA + return tx.aml_reported; + } + true + } + + /// 制裁名单检查 + fn check_sanctions(tx: &ZATxContext) -> bool { + tx.sanctions_cleared + } + + /// 辖区特定规则验证 + fn check_jurisdiction_rules(tx: &ZATxContext) -> bool { + // Rule: CASP license required from FSCA since 2023 + // Rule: FICA KYC compliance mandatory + // Rule: ZAR reporting above ZAR 100,000 + // Rule: SARB exchange control for cross-border transfers + // 禁止匿名交易(宪法即是规则) + !tx.is_anonymous + } + + /// 出具宪法收据(CR) + /// 参与即是共识:节点独立出具CR,无需多签,无需链上投票 + fn issue_constitutional_receipt(tx: &ZATxContext) -> String { + format!("CR-{}:{}", JURISDICTION_CODE, tx.tx_hash) + } +} + +impl ZAJurisdictionPlugin { + /// 主验证入口 + pub fn validate(&self, tx: &ZATxContext) -> ValidationResult { + // 1. KYC 验证 + if !Self::check_kyc_level(tx) { + return ValidationResult::Rejected { + reason: format!("ZA_KYC: Minimum level Enhanced required per {}", + "FSCA/SARB (Financial Sector Conduct Authority / South African Reserve Bank)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 2. AML 阈值检查 + if !Self::check_aml_threshold(tx) { + return ValidationResult::Rejected { + reason: format!("ZA_AML: Transactions above {} USD require reporting to {}", + AML_THRESHOLD_USD, "FSCA/SARB (Financial Sector Conduct Authority / South African Reserve Bank)"), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 3. 制裁名单检查 + if !Self::check_sanctions(tx) { + return ValidationResult::Rejected { + reason: "ZA_SANCTIONS: Transaction parties are on sanctions list".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 4. 辖区特定规则 + if !Self::check_jurisdiction_rules(tx) { + return ValidationResult::Rejected { + reason: "ZA_RULES: Jurisdiction-specific rule violation".to_string(), + jurisdiction: JURISDICTION_CODE.to_string(), + }; + } + + // 验证通过,出具 CR(参与即是共识) + ValidationResult::Approved { + jurisdiction: JURISDICTION_CODE.to_string(), + constitutional_receipt: Self::issue_constitutional_receipt(tx), + } + } + + pub fn jurisdiction_code(&self) -> &str { + JURISDICTION_CODE + } + + pub fn regulatory_authority(&self) -> &str { + "FSCA/SARB (Financial Sector Conduct Authority / South African Reserve Bank)" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_tx(kyc: KycLevel, amount: f64, anonymous: bool, aml: bool) -> ZATxContext { + ZATxContext { + tx_hash: "test_hash_001".to_string(), + from: [0u8; 32], + to: [1u8; 32], + amount_usd: amount, + asset_type: "RWA_REAL_ESTATE".to_string(), + kyc_level: kyc, + aml_reported: aml, + is_anonymous: anonymous, + is_cross_border: false, + sanctions_cleared: true, + + } + } + + #[test] + fn test_za_valid_transaction() { + let plugin = ZAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_za_kyc_insufficient() { + let plugin = ZAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::None, 1000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_za_aml_threshold_exceeded_unreported() { + let plugin = ZAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_za_aml_threshold_reported() { + let plugin = ZAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 11000.0, false, true); + assert!(matches!(plugin.validate(&tx), ValidationResult::Approved { .. })); + } + + #[test] + fn test_za_anonymous_rejected() { + let plugin = ZAJurisdictionPlugin::new(); + let tx = make_tx(KycLevel::Enhanced, 100.0, true, false); + assert!(matches!(plugin.validate(&tx), ValidationResult::Rejected { .. })); + } + + #[test] + fn test_za_jurisdiction_code() { + let plugin = ZAJurisdictionPlugin::new(); + assert_eq!(plugin.jurisdiction_code(), "ZA"); + } + + #[test] + fn test_za_regulatory_authority() { + let plugin = ZAJurisdictionPlugin::new(); + assert!(!plugin.regulatory_authority().is_empty()); + } +} diff --git a/nac-jurisdiction-version/src/lib.rs b/nac-jurisdiction-version/src/lib.rs index ec43e17..110ea80 100644 --- a/nac-jurisdiction-version/src/lib.rs +++ b/nac-jurisdiction-version/src/lib.rs @@ -340,15 +340,17 @@ mod tests { use super::*; use std::env; - fn make_manager() -> JurisdictionVersionManager { - let tmp = env::temp_dir().join("nac_version_test"); + fn make_manager_with_id(id: &str) -> JurisdictionVersionManager { + let tmp = env::temp_dir().join(format!("nac_version_test_{}", id)); + // 清理旧数据确保测试隔离 + let _ = std::fs::remove_dir_all(&tmp); let _ = fs::create_dir_all(&tmp); JurisdictionVersionManager::new(&tmp) } #[test] fn test_publish_version() { - let mut mgr = make_manager(); + let mut mgr = make_manager_with_id("publish"); let result = mgr.publish_version( "CN", RuleVersion::new(1, 0, 0), @@ -369,7 +371,7 @@ mod tests { #[test] fn test_ca_signature_required() { - let mut mgr = make_manager(); + let mut mgr = make_manager_with_id("ca_sig"); // 无CA签名不得发布新版本 let result = mgr.publish_version( "HK", RuleVersion::new(1, 0, 0), "hash", "SFC_CA", @@ -385,7 +387,7 @@ mod tests { #[test] fn test_version_must_increase() { - let mut mgr = make_manager(); + let mut mgr = make_manager_with_id("must_inc"); // 发布 v1.0.0 mgr.publish_version("SG", RuleVersion::new(1, 0, 0), "h1", "MAS_CA", vec![1], "v1", None).unwrap(); @@ -401,7 +403,7 @@ mod tests { #[test] fn test_old_version_auto_archived() { - let mut mgr = make_manager(); + let mut mgr = make_manager_with_id("auto_arch"); // 发布 v1.0.0 mgr.publish_version("AE", RuleVersion::new(1, 0, 0), "h1", "VARA_CA", vec![1], "v1", None).unwrap(); @@ -424,7 +426,7 @@ mod tests { #[test] fn test_version_history_query() { - let mut mgr = make_manager(); + let mut mgr = make_manager_with_id("hist_query"); for patch in 0..3u32 { mgr.publish_version( "JP", @@ -445,7 +447,7 @@ mod tests { #[test] fn test_rollback_requires_ca_signature() { - let mut mgr = make_manager(); + let mut mgr = make_manager_with_id("rollback"); mgr.publish_version("KR", RuleVersion::new(1, 0, 0), "h1", "FSC_CA", vec![1], "v1", None).unwrap(); mgr.publish_version("KR", RuleVersion::new(2, 0, 0), "h2", "FSC_CA", diff --git a/nac-lens-jurisdiction-router/Cargo.lock b/nac-lens-jurisdiction-router/Cargo.lock new file mode 100644 index 0000000..cda82b2 --- /dev/null +++ b/nac-lens-jurisdiction-router/Cargo.lock @@ -0,0 +1,107 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "nac-lens-jurisdiction-router" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + +[[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.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[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 = "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 = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/nac-lens-jurisdiction-router/Cargo.toml b/nac-lens-jurisdiction-router/Cargo.toml new file mode 100644 index 0000000..e1366eb --- /dev/null +++ b/nac-lens-jurisdiction-router/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "nac-lens-jurisdiction-router" +version = "0.1.0" +edition = "2021" +description = "NAC_Lens 4.0辖区路由层集成模块 (Issue #77)" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/nac-lens-jurisdiction-router/src/lib.rs b/nac-lens-jurisdiction-router/src/lib.rs new file mode 100644 index 0000000..3f0e17b --- /dev/null +++ b/nac-lens-jurisdiction-router/src/lib.rs @@ -0,0 +1,467 @@ +// NAC_Lens 4.0 辖区路由层集成模块(Issue #77) +// 将 jurisdiction_router.rs 集成到 NAC_Lens 消息分发管道 +// CBPP原则:约法即是治法 | 宪法即是规则 | 参与即是共识 | 节点产生区块交易决定区块大小 +// NAC_Lens 是 NAC 原生协议(原 NRPC 已统一更名为 NAC_Lens) +// 跨辖区交易:源辖区节点和目标辖区节点各自独立出具CR(参与即是共识,非多签) + +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +/// NAC_Lens 消息类型 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum NacLensMessageType { + /// 单辖区交易 + IntraJurisdiction { + jurisdiction: String, + }, + /// 跨辖区交易(源辖区 -> 目标辖区) + CrossJurisdiction { + source_jurisdiction: String, + target_jurisdiction: String, + }, + /// 辖区规则更新广播(CA签名授权,约法即是治法) + JurisdictionRuleUpdate { + jurisdiction: String, + new_version: String, + ca_signature: Vec, + }, + /// 宪法收据(CR)广播(参与即是共识) + ConstitutionalReceiptBroadcast { + jurisdiction: String, + tx_hash: String, + cr_hash: String, + }, + /// 辖区节点注册(GIDS辖区证明) + NodeRegistration { + jurisdiction: String, + node_id: String, + gids_proof: Vec, + }, +} + +/// NAC_Lens 消息信封 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NacLensEnvelope { + /// 协议版本(NAC_Lens 4.0) + pub protocol_version: String, + /// 消息ID + pub message_id: String, + /// 消息类型 + pub message_type: NacLensMessageType, + /// 消息体(序列化的交易或规则数据) + pub payload: Vec, + /// 发送节点ID + pub sender_node_id: String, + /// 时间戳(UTC Unix 毫秒) + pub timestamp: u64, +} + +impl NacLensEnvelope { + pub fn new( + message_id: &str, + message_type: NacLensMessageType, + payload: Vec, + sender_node_id: &str, + ) -> Self { + Self { + protocol_version: "NAC_Lens/4.0".to_string(), + message_id: message_id.to_string(), + message_type, + payload, + sender_node_id: sender_node_id.to_string(), + timestamp: 0, // 实际使用时由运行时填充 + } + } +} + +/// 辖区路由表条目 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JurisdictionRouteEntry { + /// 辖区代码 + pub jurisdiction_code: String, + /// 辖区节点列表(节点ID -> 节点地址) + pub nodes: HashMap, + /// 当前活跃规则版本 + pub active_rule_version: String, + /// 路由优先级(0=最高) + pub priority: u8, + /// 是否接受跨辖区消息 + pub accepts_cross_jurisdiction: bool, +} + +/// NAC_Lens 辖区路由器 +/// 负责将消息路由到正确的辖区节点,支持跨辖区消息转发 +pub struct NacLensJurisdictionRouter { + /// 路由表(jurisdiction_code -> RouteEntry) + routing_table: HashMap, + /// 本节点所属辖区 + local_jurisdiction: String, + /// 本节点ID + local_node_id: String, +} + +impl NacLensJurisdictionRouter { + pub fn new(local_jurisdiction: &str, local_node_id: &str) -> Self { + Self { + routing_table: HashMap::new(), + local_jurisdiction: local_jurisdiction.to_string(), + local_node_id: local_node_id.to_string(), + } + } + + /// 注册辖区路由 + pub fn register_jurisdiction(&mut self, entry: JurisdictionRouteEntry) { + self.routing_table.insert(entry.jurisdiction_code.clone(), entry); + } + + /// 路由消息到目标辖区节点 + /// 约法即是治法:路由决策基于宪法规则,不基于节点偏好 + pub fn route(&self, envelope: &NacLensEnvelope) -> RoutingDecision { + match &envelope.message_type { + NacLensMessageType::IntraJurisdiction { jurisdiction } => { + self.route_intra_jurisdiction(jurisdiction, envelope) + } + NacLensMessageType::CrossJurisdiction { + source_jurisdiction, + target_jurisdiction, + } => self.route_cross_jurisdiction(source_jurisdiction, target_jurisdiction, envelope), + NacLensMessageType::JurisdictionRuleUpdate { + jurisdiction, + ca_signature, + .. + } => { + // 规则更新:广播到所有辖区节点(CA签名验证通过后立即生效) + if ca_signature.is_empty() { + return RoutingDecision::Rejected { + reason: "Rule update rejected: missing CA signature. \ + Per CBPP '约法即是治法', rule updates require CA authorization." + .to_string(), + }; + } + self.route_rule_update_broadcast(jurisdiction) + } + NacLensMessageType::ConstitutionalReceiptBroadcast { + jurisdiction, + tx_hash, + cr_hash, + } => { + // CR广播:广播到所有节点(参与即是共识) + RoutingDecision::Broadcast { + target_jurisdictions: self.routing_table.keys().cloned().collect(), + message_summary: format!( + "CR broadcast: jurisdiction={}, tx={}, cr={}", + jurisdiction, tx_hash, cr_hash + ), + } + } + NacLensMessageType::NodeRegistration { + jurisdiction, + node_id, + gids_proof, + } => { + if gids_proof.is_empty() { + return RoutingDecision::Rejected { + reason: format!( + "Node {} registration rejected: missing GIDS proof for jurisdiction {}", + node_id, jurisdiction + ), + }; + } + RoutingDecision::Forward { + target_jurisdiction: jurisdiction.clone(), + target_nodes: self + .routing_table + .get(jurisdiction) + .map(|e| e.nodes.keys().cloned().collect()) + .unwrap_or_default(), + } + } + } + } + + /// 单辖区内部路由 + fn route_intra_jurisdiction( + &self, + jurisdiction: &str, + _envelope: &NacLensEnvelope, + ) -> RoutingDecision { + if let Some(entry) = self.routing_table.get(jurisdiction) { + RoutingDecision::Forward { + target_jurisdiction: jurisdiction.to_string(), + target_nodes: entry.nodes.keys().cloned().collect(), + } + } else { + RoutingDecision::Rejected { + reason: format!( + "Jurisdiction {} not found in routing table. \ + Node must register jurisdiction before routing.", + jurisdiction + ), + } + } + } + + /// 跨辖区路由 + /// 参与即是共识:源辖区和目标辖区各自独立处理,各自出具CR + fn route_cross_jurisdiction( + &self, + source: &str, + target: &str, + _envelope: &NacLensEnvelope, + ) -> RoutingDecision { + let source_entry = self.routing_table.get(source); + let target_entry = self.routing_table.get(target); + + match (source_entry, target_entry) { + (Some(_src), Some(tgt)) => { + if !tgt.accepts_cross_jurisdiction { + return RoutingDecision::Rejected { + reason: format!( + "Jurisdiction {} does not accept cross-jurisdiction messages", + target + ), + }; + } + // 跨辖区:同时转发到源辖区和目标辖区 + // 各辖区节点独立出具CR(参与即是共识,非多签) + RoutingDecision::CrossJurisdictionForward { + source_jurisdiction: source.to_string(), + target_jurisdiction: target.to_string(), + source_nodes: self + .routing_table + .get(source) + .map(|e| e.nodes.keys().cloned().collect()) + .unwrap_or_default(), + target_nodes: tgt.nodes.keys().cloned().collect(), + } + } + (None, _) => RoutingDecision::Rejected { + reason: format!("Source jurisdiction {} not registered", source), + }, + (_, None) => RoutingDecision::Rejected { + reason: format!("Target jurisdiction {} not registered", target), + }, + } + } + + /// 规则更新广播路由 + fn route_rule_update_broadcast(&self, jurisdiction: &str) -> RoutingDecision { + RoutingDecision::Broadcast { + target_jurisdictions: vec![jurisdiction.to_string()], + message_summary: format!( + "Rule update broadcast to all {} nodes (CA-authorized, effective immediately)", + jurisdiction + ), + } + } + + /// 获取辖区路由表统计 + pub fn routing_stats(&self) -> RoutingStats { + let total_nodes: usize = self.routing_table.values().map(|e| e.nodes.len()).sum(); + RoutingStats { + registered_jurisdictions: self.routing_table.len(), + total_nodes, + local_jurisdiction: self.local_jurisdiction.clone(), + local_node_id: self.local_node_id.clone(), + } + } + + /// 更新辖区规则版本(CA签名授权后调用) + pub fn update_jurisdiction_version(&mut self, jurisdiction: &str, new_version: &str) -> bool { + if let Some(entry) = self.routing_table.get_mut(jurisdiction) { + entry.active_rule_version = new_version.to_string(); + true + } else { + false + } + } +} + +/// 路由决策 +#[derive(Debug, Clone)] +pub enum RoutingDecision { + /// 转发到指定辖区节点 + Forward { + target_jurisdiction: String, + target_nodes: Vec, + }, + /// 跨辖区转发(源辖区和目标辖区各自独立处理) + CrossJurisdictionForward { + source_jurisdiction: String, + target_jurisdiction: String, + source_nodes: Vec, + target_nodes: Vec, + }, + /// 广播到多个辖区 + Broadcast { + target_jurisdictions: Vec, + message_summary: String, + }, + /// 拒绝路由 + Rejected { + reason: String, + }, +} + +/// 路由统计信息 +#[derive(Debug, Clone)] +pub struct RoutingStats { + pub registered_jurisdictions: usize, + pub total_nodes: usize, + pub local_jurisdiction: String, + pub local_node_id: String, +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_router() -> NacLensJurisdictionRouter { + let mut router = NacLensJurisdictionRouter::new("CN", "node_cn_001"); + + // 注册 CN 辖区 + let mut cn_nodes = HashMap::new(); + cn_nodes.insert("node_cn_001".to_string(), "192.168.1.1:8080".to_string()); + cn_nodes.insert("node_cn_002".to_string(), "192.168.1.2:8080".to_string()); + router.register_jurisdiction(JurisdictionRouteEntry { + jurisdiction_code: "CN".to_string(), + nodes: cn_nodes, + active_rule_version: "1.0.0".to_string(), + priority: 0, + accepts_cross_jurisdiction: true, + }); + + // 注册 HK 辖区 + let mut hk_nodes = HashMap::new(); + hk_nodes.insert("node_hk_001".to_string(), "10.0.1.1:8080".to_string()); + router.register_jurisdiction(JurisdictionRouteEntry { + jurisdiction_code: "HK".to_string(), + nodes: hk_nodes, + active_rule_version: "1.0.0".to_string(), + priority: 0, + accepts_cross_jurisdiction: true, + }); + + router + } + + #[test] + fn test_intra_jurisdiction_routing() { + let router = make_router(); + let envelope = NacLensEnvelope::new( + "msg_001", + NacLensMessageType::IntraJurisdiction { + jurisdiction: "CN".to_string(), + }, + vec![], + "node_cn_001", + ); + let decision = router.route(&envelope); + assert!(matches!(decision, RoutingDecision::Forward { .. })); + if let RoutingDecision::Forward { target_jurisdiction, target_nodes } = decision { + assert_eq!(target_jurisdiction, "CN"); + assert_eq!(target_nodes.len(), 2); + } + } + + #[test] + fn test_cross_jurisdiction_routing() { + let router = make_router(); + let envelope = NacLensEnvelope::new( + "msg_002", + NacLensMessageType::CrossJurisdiction { + source_jurisdiction: "CN".to_string(), + target_jurisdiction: "HK".to_string(), + }, + vec![], + "node_cn_001", + ); + let decision = router.route(&envelope); + // 跨辖区:各辖区独立处理,参与即是共识 + assert!(matches!(decision, RoutingDecision::CrossJurisdictionForward { .. })); + } + + #[test] + fn test_rule_update_requires_ca_signature() { + let router = make_router(); + let envelope = NacLensEnvelope::new( + "msg_003", + NacLensMessageType::JurisdictionRuleUpdate { + jurisdiction: "CN".to_string(), + new_version: "2.0.0".to_string(), + ca_signature: vec![], // 无签名 + }, + vec![], + "node_cn_001", + ); + let decision = router.route(&envelope); + assert!(matches!(decision, RoutingDecision::Rejected { .. })); + } + + #[test] + fn test_rule_update_with_ca_signature() { + let router = make_router(); + let envelope = NacLensEnvelope::new( + "msg_004", + NacLensMessageType::JurisdictionRuleUpdate { + jurisdiction: "CN".to_string(), + new_version: "2.0.0".to_string(), + ca_signature: vec![1u8; 64], // 有效CA签名 + }, + vec![], + "node_cn_001", + ); + let decision = router.route(&envelope); + assert!(matches!(decision, RoutingDecision::Broadcast { .. })); + } + + #[test] + fn test_unknown_jurisdiction_rejected() { + let router = make_router(); + let envelope = NacLensEnvelope::new( + "msg_005", + NacLensMessageType::IntraJurisdiction { + jurisdiction: "UNKNOWN".to_string(), + }, + vec![], + "node_cn_001", + ); + let decision = router.route(&envelope); + assert!(matches!(decision, RoutingDecision::Rejected { .. })); + } + + #[test] + fn test_routing_stats() { + let router = make_router(); + let stats = router.routing_stats(); + assert_eq!(stats.registered_jurisdictions, 2); + assert_eq!(stats.total_nodes, 3); + assert_eq!(stats.local_jurisdiction, "CN"); + } + + #[test] + fn test_node_registration_without_gids_rejected() { + let router = make_router(); + let envelope = NacLensEnvelope::new( + "msg_006", + NacLensMessageType::NodeRegistration { + jurisdiction: "CN".to_string(), + node_id: "node_new".to_string(), + gids_proof: vec![], // 无GIDS证明 + }, + vec![], + "node_new", + ); + let decision = router.route(&envelope); + assert!(matches!(decision, RoutingDecision::Rejected { .. })); + } + + #[test] + fn test_update_jurisdiction_version() { + let mut router = make_router(); + let updated = router.update_jurisdiction_version("CN", "2.0.0"); + assert!(updated); + let stats = router.routing_stats(); + assert_eq!(stats.registered_jurisdictions, 2); + } +} diff --git a/nac-multi-jurisdiction/target/debug/.fingerprint/nac-multi-jurisdiction-45c9e26cd8054e03/dep-lib-nac_multi_jurisdiction b/nac-multi-jurisdiction/target/debug/.fingerprint/nac-multi-jurisdiction-45c9e26cd8054e03/dep-lib-nac_multi_jurisdiction index d5fbadd8600090cfdaed73c78b87473c060df880..3fb7877ded52e8eb0027ace59e8814d1154ceb15 100644 GIT binary patch literal 260 zcmZWkO9}!p49#o>L2)61XV4>+nueK3X@+DfczSJX9S|1@Hg%>9);c3R0KE3To \u001b[0msrc/resource_sharing.rs:134:5\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m132\u001b[0m \u001b[1m\u001b[94m|\u001b[0m pub struct ResourceMonitor {\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[94m---------------\u001b[0m \u001b[1m\u001b[94mfield in this struct\u001b[0m\n\u001b[1m\u001b[94m133\u001b[0m \u001b[1m\u001b[94m|\u001b[0m pool: ResourcePool,\n\u001b[1m\u001b[94m134\u001b[0m \u001b[1m\u001b[94m|\u001b[0m alert_threshold: u64, // 超过配额多少时告警,定点数 1e4\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^\u001b[0m\n \u001b[1m\u001b[94m|\u001b[0m\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mnote\u001b[0m: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default\n\n"} {"$message_type":"diagnostic","message":"field `loader` is never read","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/plugin.rs","byte_start":1789,"byte_end":1803,"line_start":67,"line_end":67,"column_start":12,"column_end":26,"is_primary":false,"text":[{"text":"pub struct PluginRegistry {","highlight_start":12,"highlight_end":26}],"label":"field in this struct","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src/plugin.rs","byte_start":1810,"byte_end":1816,"line_start":68,"line_end":68,"column_start":5,"column_end":11,"is_primary":true,"text":[{"text":" loader: PluginLoader,","highlight_start":5,"highlight_end":11}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: field `loader` is never read\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/plugin.rs:68:5\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m67\u001b[0m \u001b[1m\u001b[94m|\u001b[0m pub struct PluginRegistry {\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[94m--------------\u001b[0m \u001b[1m\u001b[94mfield in this struct\u001b[0m\n\u001b[1m\u001b[94m68\u001b[0m \u001b[1m\u001b[94m|\u001b[0m loader: PluginLoader,\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^\u001b[0m\n\n"} -{"$message_type":"diagnostic","message":"2 warnings emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: 2 warnings emitted\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"field `pending_cross_txs` is never read","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/node_sharing_enhanced.rs","byte_start":12861,"byte_end":12894,"line_start":378,"line_end":378,"column_start":12,"column_end":45,"is_primary":false,"text":[{"text":"pub struct CrossJurisdictionBlockCoordinator {","highlight_start":12,"highlight_end":45}],"label":"field in this struct","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"src/node_sharing_enhanced.rs","byte_start":12937,"byte_end":12954,"line_start":380,"line_end":380,"column_start":5,"column_end":22,"is_primary":true,"text":[{"text":" pending_cross_txs: Vec,","highlight_start":5,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: field `pending_cross_txs` is never read\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/node_sharing_enhanced.rs:380:5\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m378\u001b[0m \u001b[1m\u001b[94m|\u001b[0m pub struct CrossJurisdictionBlockCoordinator {\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[94m---------------------------------\u001b[0m \u001b[1m\u001b[94mfield in this struct\u001b[0m\n\u001b[1m\u001b[94m379\u001b[0m \u001b[1m\u001b[94m|\u001b[0m /// 待处理的跨辖区交易\n\u001b[1m\u001b[94m380\u001b[0m \u001b[1m\u001b[94m|\u001b[0m pending_cross_txs: Vec,\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"3 warnings emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: 3 warnings emitted\u001b[0m\n\n"} diff --git a/nac-multi-jurisdiction/target/debug/build/anyhow-1a588860b974a585/root-output b/nac-multi-jurisdiction/target/debug/build/anyhow-1a588860b974a585/root-output index 00858f1..8b10227 100644 --- a/nac-multi-jurisdiction/target/debug/build/anyhow-1a588860b974a585/root-output +++ b/nac-multi-jurisdiction/target/debug/build/anyhow-1a588860b974a585/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/anyhow-1a588860b974a585/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/anyhow-1a588860b974a585/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/generic-array-01bbe54c11d445df/root-output b/nac-multi-jurisdiction/target/debug/build/generic-array-01bbe54c11d445df/root-output index 9c204ba..c860ff8 100644 --- a/nac-multi-jurisdiction/target/debug/build/generic-array-01bbe54c11d445df/root-output +++ b/nac-multi-jurisdiction/target/debug/build/generic-array-01bbe54c11d445df/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/generic-array-01bbe54c11d445df/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/generic-array-01bbe54c11d445df/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e.d b/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e.d index d975a2f..d537e96 100644 --- a/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e.d +++ b/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e.d @@ -1,5 +1,5 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/build.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/build.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/build.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/generic-array-f8314dea6bb2335e/build_script_build-f8314dea6bb2335e: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/build.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/build.rs: diff --git a/nac-multi-jurisdiction/target/debug/build/libc-0223df3d9f2ad361/root-output b/nac-multi-jurisdiction/target/debug/build/libc-0223df3d9f2ad361/root-output index 72fd4fe..25c65b7 100644 --- a/nac-multi-jurisdiction/target/debug/build/libc-0223df3d9f2ad361/root-output +++ b/nac-multi-jurisdiction/target/debug/build/libc-0223df3d9f2ad361/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/libc-0223df3d9f2ad361/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/libc-0223df3d9f2ad361/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/num-traits-4d4efe8d0af30f57/root-output b/nac-multi-jurisdiction/target/debug/build/num-traits-4d4efe8d0af30f57/root-output index 9968617..43a7f62 100644 --- a/nac-multi-jurisdiction/target/debug/build/num-traits-4d4efe8d0af30f57/root-output +++ b/nac-multi-jurisdiction/target/debug/build/num-traits-4d4efe8d0af30f57/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/num-traits-4d4efe8d0af30f57/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/num-traits-4d4efe8d0af30f57/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5.d b/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5.d index f414b34..34a507c 100644 --- a/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5.d +++ b/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5.d @@ -1,5 +1,5 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/build.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/build.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/build.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/num-traits-98921c823c91aed5/build_script_build-98921c823c91aed5: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/build.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/build.rs: diff --git a/nac-multi-jurisdiction/target/debug/build/parking_lot_core-1de25b09392001a5/root-output b/nac-multi-jurisdiction/target/debug/build/parking_lot_core-1de25b09392001a5/root-output index b7826fc..a3c67cc 100644 --- a/nac-multi-jurisdiction/target/debug/build/parking_lot_core-1de25b09392001a5/root-output +++ b/nac-multi-jurisdiction/target/debug/build/parking_lot_core-1de25b09392001a5/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/parking_lot_core-1de25b09392001a5/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/parking_lot_core-1de25b09392001a5/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/proc-macro2-035337776c278475/root-output b/nac-multi-jurisdiction/target/debug/build/proc-macro2-035337776c278475/root-output index f344e9e..253c15b 100644 --- a/nac-multi-jurisdiction/target/debug/build/proc-macro2-035337776c278475/root-output +++ b/nac-multi-jurisdiction/target/debug/build/proc-macro2-035337776c278475/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/proc-macro2-035337776c278475/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/proc-macro2-035337776c278475/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/quote-48fa4147ea080b77/root-output b/nac-multi-jurisdiction/target/debug/build/quote-48fa4147ea080b77/root-output index f1d2f76..327f529 100644 --- a/nac-multi-jurisdiction/target/debug/build/quote-48fa4147ea080b77/root-output +++ b/nac-multi-jurisdiction/target/debug/build/quote-48fa4147ea080b77/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/quote-48fa4147ea080b77/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/quote-48fa4147ea080b77/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/serde-252a9bbeccb60cd9/root-output b/nac-multi-jurisdiction/target/debug/build/serde-252a9bbeccb60cd9/root-output index 83e383b..97835fa 100644 --- a/nac-multi-jurisdiction/target/debug/build/serde-252a9bbeccb60cd9/root-output +++ b/nac-multi-jurisdiction/target/debug/build/serde-252a9bbeccb60cd9/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/serde-252a9bbeccb60cd9/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/serde-252a9bbeccb60cd9/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/serde_json-2c8ea650b6f8d83b/root-output b/nac-multi-jurisdiction/target/debug/build/serde_json-2c8ea650b6f8d83b/root-output index 7a6ab32..6443ed6 100644 --- a/nac-multi-jurisdiction/target/debug/build/serde_json-2c8ea650b6f8d83b/root-output +++ b/nac-multi-jurisdiction/target/debug/build/serde_json-2c8ea650b6f8d83b/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/serde_json-2c8ea650b6f8d83b/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/serde_json-2c8ea650b6f8d83b/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/build/zmij-193018c25ea517ee/root-output b/nac-multi-jurisdiction/target/debug/build/zmij-193018c25ea517ee/root-output index 7a9bdcc..17295ae 100644 --- a/nac-multi-jurisdiction/target/debug/build/zmij-193018c25ea517ee/root-output +++ b/nac-multi-jurisdiction/target/debug/build/zmij-193018c25ea517ee/root-output @@ -1 +1 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/zmij-193018c25ea517ee/out \ No newline at end of file +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/build/zmij-193018c25ea517ee/out \ No newline at end of file diff --git a/nac-multi-jurisdiction/target/debug/deps/anyhow-727625e04efe81e0.d b/nac-multi-jurisdiction/target/debug/deps/anyhow-727625e04efe81e0.d index 002246f..aee831f 100644 --- a/nac-multi-jurisdiction/target/debug/deps/anyhow-727625e04efe81e0.d +++ b/nac-multi-jurisdiction/target/debug/deps/anyhow-727625e04efe81e0.d @@ -1,6 +1,6 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/anyhow-727625e04efe81e0.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/backtrace.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/chain.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/context.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ensure.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/fmt.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/kind.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ptr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/wrapper.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/anyhow-727625e04efe81e0.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/backtrace.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/chain.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/context.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ensure.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/fmt.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/kind.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ptr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/wrapper.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libanyhow-727625e04efe81e0.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/backtrace.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/chain.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/context.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ensure.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/fmt.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/kind.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ptr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/wrapper.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libanyhow-727625e04efe81e0.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/backtrace.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/chain.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/context.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ensure.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/fmt.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/kind.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/ptr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/wrapper.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/lib.rs: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anyhow-1.0.102/src/backtrace.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/block_buffer-e56fd2da8d4bd510.d b/nac-multi-jurisdiction/target/debug/deps/block_buffer-e56fd2da8d4bd510.d index 5c469df..43eb745 100644 --- a/nac-multi-jurisdiction/target/debug/deps/block_buffer-e56fd2da8d4bd510.d +++ b/nac-multi-jurisdiction/target/debug/deps/block_buffer-e56fd2da8d4bd510.d @@ -1,6 +1,6 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/block_buffer-e56fd2da8d4bd510.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/sealed.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/block_buffer-e56fd2da8d4bd510.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/sealed.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libblock_buffer-e56fd2da8d4bd510.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/sealed.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libblock_buffer-e56fd2da8d4bd510.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/sealed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/lib.rs: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/sealed.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/chrono-37057a699a1b288e.d b/nac-multi-jurisdiction/target/debug/deps/chrono-37057a699a1b288e.d index bfd1059..4dc1fd8 100644 --- a/nac-multi-jurisdiction/target/debug/deps/chrono-37057a699a1b288e.d +++ b/nac-multi-jurisdiction/target/debug/deps/chrono-37057a699a1b288e.d @@ -1,6 +1,6 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/chrono-37057a699a1b288e.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/time_delta.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/date.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/formatting.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parsed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parse.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/scan.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/strftime.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/locales.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/date/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/internals.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/isoweek.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/fixed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/unix.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/timezone.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/parser.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/rule.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/utc.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/round.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday_set.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/month.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/traits.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/chrono-37057a699a1b288e.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/time_delta.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/date.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/formatting.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parsed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parse.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/scan.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/strftime.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/locales.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/date/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/internals.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/isoweek.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/fixed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/unix.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/timezone.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/parser.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/rule.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/utc.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/round.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday_set.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/month.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/traits.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libchrono-37057a699a1b288e.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/time_delta.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/date.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/formatting.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parsed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parse.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/scan.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/strftime.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/locales.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/date/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/internals.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/isoweek.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/fixed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/unix.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/timezone.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/parser.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/rule.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/utc.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/round.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday_set.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/month.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/traits.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libchrono-37057a699a1b288e.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/time_delta.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/date.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/formatting.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parsed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/parse.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/scan.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/strftime.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/format/locales.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/date/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/datetime/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/internals.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/isoweek.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/naive/time/serde.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/fixed.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/unix.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/timezone.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/parser.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/local/tz_info/rule.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/offset/utc.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/round.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/weekday_set.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/month.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/traits.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/lib.rs: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/time_delta.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/crypto_common-9e7096b6b51d0de7.d b/nac-multi-jurisdiction/target/debug/deps/crypto_common-9e7096b6b51d0de7.d index 4a8062b..674e24a 100644 --- a/nac-multi-jurisdiction/target/debug/deps/crypto_common-9e7096b6b51d0de7.d +++ b/nac-multi-jurisdiction/target/debug/deps/crypto_common-9e7096b6b51d0de7.d @@ -1,5 +1,5 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/crypto_common-9e7096b6b51d0de7.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/src/lib.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/crypto_common-9e7096b6b51d0de7.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/src/lib.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libcrypto_common-9e7096b6b51d0de7.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/src/lib.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libcrypto_common-9e7096b6b51d0de7.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/src/lib.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/digest-89f9ec62bb4f2bd2.d b/nac-multi-jurisdiction/target/debug/deps/digest-89f9ec62bb4f2bd2.d index c0e740c..e598f2a 100644 --- a/nac-multi-jurisdiction/target/debug/deps/digest-89f9ec62bb4f2bd2.d +++ b/nac-multi-jurisdiction/target/debug/deps/digest-89f9ec62bb4f2bd2.d @@ -1,6 +1,6 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/digest-89f9ec62bb4f2bd2.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/ct_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/rt_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/wrapper.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/xof_reader.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/digest.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/digest-89f9ec62bb4f2bd2.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/ct_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/rt_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/wrapper.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/xof_reader.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/digest.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libdigest-89f9ec62bb4f2bd2.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/ct_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/rt_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/wrapper.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/xof_reader.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/digest.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libdigest-89f9ec62bb4f2bd2.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/ct_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/rt_variable.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/wrapper.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/xof_reader.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/digest.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/lib.rs: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/errno-3d53664cf0be054b.d b/nac-multi-jurisdiction/target/debug/deps/errno-3d53664cf0be054b.d index f2594e8..8f645a0 100644 --- a/nac-multi-jurisdiction/target/debug/deps/errno-3d53664cf0be054b.d +++ b/nac-multi-jurisdiction/target/debug/deps/errno-3d53664cf0be054b.d @@ -1,6 +1,6 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/errno-3d53664cf0be054b.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/unix.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/errno-3d53664cf0be054b.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/unix.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/liberrno-3d53664cf0be054b.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/unix.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/liberrno-3d53664cf0be054b.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/unix.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/lib.rs: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/unix.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/generic_array-ca63266564d72c57.d b/nac-multi-jurisdiction/target/debug/deps/generic_array-ca63266564d72c57.d index db0723e..2386373 100644 --- a/nac-multi-jurisdiction/target/debug/deps/generic_array-ca63266564d72c57.d +++ b/nac-multi-jurisdiction/target/debug/deps/generic_array-ca63266564d72c57.d @@ -1,6 +1,6 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/generic_array-ca63266564d72c57.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/hex.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/impls.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/arr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/functional.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/iter.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/sequence.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/generic_array-ca63266564d72c57.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/hex.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/impls.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/arr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/functional.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/iter.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/sequence.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libgeneric_array-ca63266564d72c57.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/hex.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/impls.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/arr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/functional.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/iter.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/sequence.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libgeneric_array-ca63266564d72c57.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/hex.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/impls.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/arr.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/functional.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/iter.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/sequence.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/lib.rs: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/hex.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/libc-615dd1ae383c1f11.d b/nac-multi-jurisdiction/target/debug/deps/libc-615dd1ae383c1f11.d index d15c4fe..4da6bee 100644 --- a/nac-multi-jurisdiction/target/debug/deps/libc-615dd1ae383c1f11.d +++ b/nac-multi-jurisdiction/target/debug/deps/libc-615dd1ae383c1f11.d @@ -1,6 +1,6 @@ -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libc-615dd1ae383c1f11.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/bcm.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/j1939.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/raw.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/keyctl.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/membarrier.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/netlink.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/net/route.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/primitives.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux_l4re_shared.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/generic/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/types.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/libc-615dd1ae383c1f11.d: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/bcm.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/j1939.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/raw.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/keyctl.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/membarrier.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/netlink.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/net/route.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/primitives.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux_l4re_shared.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/generic/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/types.rs -/root/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/liblibc-615dd1ae383c1f11.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/bcm.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/j1939.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/raw.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/keyctl.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/membarrier.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/netlink.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/net/route.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/primitives.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux_l4re_shared.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/generic/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/types.rs +/data/blockchain/NAC_Blockchain/nac-multi-jurisdiction/target/debug/deps/liblibc-615dd1ae383c1f11.rmeta: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/lib.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/macros.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/linux_like/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/common/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/bcm.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/error.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/j1939.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/can/raw.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/keyctl.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/membarrier.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/linux_uapi/linux/netlink.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/posix/unistd.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/nptl/pthread.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/new/glibc/sysdeps/unix/linux/net/route.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/primitives.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux_l4re_shared.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/unix/linux_like/linux/arch/generic/mod.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/types.rs /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/lib.rs: /root/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.182/src/macros.rs: diff --git a/nac-multi-jurisdiction/target/debug/deps/libchrono-37057a699a1b288e.rmeta b/nac-multi-jurisdiction/target/debug/deps/libchrono-37057a699a1b288e.rmeta index e91ffc63ac259af68bbe250a5a6b4b1b009c6967..05f8d35b01e2d4aa43fc7065bf7ded3e6c3d8868 100644 GIT binary patch delta 179 zcmex-DEsrF>_E%`#GF9P1;pGy%mc){K+Ffk{6H)K#DYL91jNEX xECR%$Kr9Bt;y^3`#FE>cS)}}K3#4zERn)d$;mMzgXLP0QFAHy9cwg!gBLF)_J6-?) delta 179 zcmex-DEsrF>q~YfS41Axqz4(h-A*fLIWSg@9NX xh(&-{6o|!uSR9BYfLL<7GmDhpZ2>=re=RivT!-I=c3WtO?A@?^;eDw~i~vRRJQ)B0 diff --git a/nac-multi-jurisdiction/target/debug/deps/libnac_multi_jurisdiction-45c9e26cd8054e03.rmeta b/nac-multi-jurisdiction/target/debug/deps/libnac_multi_jurisdiction-45c9e26cd8054e03.rmeta index 5d0a49a9c3d2797efce1dd70571bf596de85f5d3..4578b68846ea697973c2f6b554ae16484d2e3e04 100644 GIT binary patch literal 385100 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

a zHcj_?dnZeK#*CQ7Av=zYkdK}foDnFbnVuT^0|m)&=EQiw~M+@!C$+U&UO zy38=U^z**PHkZ_cZt4ySnKeq^e(V_2SqCP@HVl)Nd@1v5@uYPJURH)IT4-9lqPeYe zPRLIondp14FRtVAwDZ;t>utmCandVxxr)fOj5t%F9uYQrQ}e!Itd-$*`n!($f6Qmh zGzp)zLZNzt`1p{Y2k-jN$))LD5mn9DwYue1dVWruQg!S51wQdJToqm_Ydvz)+^@X6 z>`|oW*cR?MD=3MfYhbG6qd*%$1Od zkDE`ZlwJ5*S-&NqVMyDV4N4JWNw=yjzl`%P-jXC46XQGF)`l_M_HDkr)F$`x0YBU- zuS>g5@GtlwxwdrL#Fy(BYh5GnUjDj!-mm??@U4gM=MAz+R{ol?eRRcuWr|IHjM*#G z@?|!JHL?0m84Mf$)3&RTKW^%Oi>chGzH2J=s6d_F3v zSQrKwNptRQdn{zGb*D6Vhe1Kb5+OZm{m*SXF(`J6#QUS4HfgTh zF5#ARG-mW9;WOD5SA|bhH|)x%KS)`A_K>fU|KiaFCYcwuJPHySylmW_n$RnrlNG;J zcfPA&XFNB};H*DXxkq7l`j!n--|i@>-ErAOS$At*=Hzi%tNdN=wQEhqAAH>}vi9Ql zfj%6&cvh1<Ko*wK5V}`{msaM;ePDf@9G!4S#|Agf2Zt0i=t{{ zf=t6&Pi4xdW#p#5e6-P|`0V%%1{!L2WWOwNUX~-~pg{A@e|9yl*(Y!0aT!C|Nx^Ot z#-5WhKNJ0V+7zWTC(Bws>E%6*88*qWdi_dUZ7b&^C!6$d)?V3uAi*Hu^%V2l`MXCM zCQUV46>f9#=oi^FquEE6%k7A&Vx4*Er(=F-@s_+Q#IQPvRZm`&KHN716_VxQGM4I0YXbjVm z9rTi;9{lX-SH0#R8ukkoKax=y7?oC}C9zyxtx?${MDgOyfq{oJ$8CBvV6AOj$B#u> zqqws(ohEF2y0hPS_m9d^KGiXItu7S|IDTQ`mzdpdpY}*xt*~hGA*9Bfb+})7-RtmB zmkY1Acxa6LwMs+N!{fQI>gggz*3z%D?d0S}gcN8G-SgtXsKJjKU4o{E4it62G{=44 z&~eHJX%F*9PFtI_yPu4))T;f`5fwIv&rg0nwRG$A0mlw}mM~Ty72y`)_BL)TJ>74e z`4@xBlbmmeIBzwQpSFI$1zX?oohgQ&Z)})#={oDXHA^Apv23nT1^3L=iTj6VT4+8p z*eqqXCZ^OV_Il>!$#L~7YDChUmrwJ*kd(+w)bai{^)vDQYOvmtTML7qK3cuSjiw%6 z6~0-2{IQ3cZN3L4$KM^lwa8^#%*sbKt5qvA{bUaAD?aIbQObPZmb>C@6;)9sCdRXv z!zRBKFK3M(c5eJ8V|CMkkxLIf##)ZFd;1(ZW4R|Vwe`C5XJ^yZJ_8puO!l+4y^)h! zVmh&)pJS@@`jrC~MwFyqndaX9@M(slHtnKc*t!9O=Q88R6TiZa9;oQw`6aeJaDpY)2TyYEvmP(wvLETz0xSw|7T6AhfY}b*?v-6>Spd= zc23v--HPz_BXT?s9V?l#w4S?c&XzG{MmM&*Zh25SSJ^rHXs+SO*>lq}JF}KHDRnOT zdQVMy#sFfQkh0O9ngb(pCpsK{>TKv#vFYC8_R$GrmxZhyum3Js_C?#m`FdtImRyR8 zv)sRs`Krl%v`(6ROl^In>qNs_O476UN4*K#_F?PpPgRa}`K|UY6W#~++mJGC@2_!} zP7SQvQFG&C_>S{7n{_>+D#nY7{`?$NcV~6};(3eR#{O_T5isYoVP!za#6g+cEuT3X z7qW%SM;^&k@efF{6wZ36)T!K>pkTEy_dqcbp{INJU5o$hphFu5ruxsw{1EVB_UzBG z_Fq*`iF0=@8mOIoT21Fj+=9x9hxg69A8@F{TAa}~>#Dz^WWvwn9T&VjrAjby5i%aUolwNYiKrP`E5$Nd_PE=%^0RhIq!1apeY>#ubA zYUP5ji)P;3`r?SolV(MaoD6Gc_sL@h#b|%qlHA}xoS46hR<}vk`)5GI(=&Qev+@RM zu4ZnW@^tsY>(bkb#Wq;!Sq^zHxc_tSj#vi`FCWWCVp)N11=AIS%m$S<;GtX4I7yups~WL{3XnN~>w<~FN zDZ-Q9FtG=ZcG&r7W(i5BEVYi>w5k1qon-#(iwho19&vj?OhHt{5#6~)WiKR>H%$wW zn#j~+OS01nB&_NdJE%W&HY%EUC!AiERCldy&Ir>VNqei^zMo!bBz4~1(q+z}xY3%! zE#eX`=$sv`Ba!_1WAVg?S&>8XT}uj{UF^4@Mpk*>7W1)2*&`;6k@z;Qc6?TJ(MJ{4 zF~#X~L!T@9CVo97r%nlVd5u5{0JOS!IN}PyDzqNiW!E5B_Lf-rvmFub=gyXG(`QJ&cW!;W`^X!8PvR zQyw5$HooQ7I^CNVH#cs1KY#Ybb8}ynr%P}Cyk@n}^C8=Aw>ODuYRzjaoZ~ev_}6!R z+p#YB#lu&oSZrUCbmri_z&(YJauU?H`8?g(`e4m*ct7YcOk9r$&2;^nS<@Rmq)XH=@^Diwf38J zPU~UqibMuYyeS>Os!^6dWJ}5nYKW)j5==F<2 z8|I#w{bG3ko%2sTt&I9O=Slg(goJ^UMtI{*moFra^xgKzo1yLfvS5c^$(VhmG{#mZp@O>cyY0D4k|rxISCn z@%RhXmXF@T(Hm$j&96_|1-9K>`cr4s@$^FZ%}3glBsg|X4IZ&t;$uZ6#xC+)72fU| z<(SqI(b{UHy5GD1Tf?~w&#b8%v%Y7`HpJ(JRsl7WUvn1yA z-lm0b&mGw@aaKvc>%Y!9E;o68Yl`W*l`l+f>W4nG@R+ZpE_=m%Vvqv9TT=4UTlv^m zZhKyz9o_Qb_4S-H4dd3kkG;3?@e-?_9$GP0i=&k%l(ol23_LmKMUC2U_KjfUi9 zxA^ZZTIa2jGYp8hrDzD+IzYM8Te89N){^?nV zS0fF-U2`wqRsF50e9xqelUvRzpH=-a&`4N9+4EA8i}vUu@1Z~3OwX`zGt7LIeqNm;XWh)Hp~Ir3mM(qlZl`gxRCLn0 z3cDGdXLBZned6d&Rt;TWlvp}$&1j#cl|N;;F$=fv-4VXfYt)G3nQApxR+)&#MFt)4 zP&)PK%;=@59RuapZ%S7U)0EJ7yJm-VmUOdG9Ba>xnV-fx>}1J?(I!X+I2p(KC3}9w z4R>!{@zQJJWw*c(p)8XTmk;`UZVcWjxk*mt{?EA)ftel0<(CcAKUrDPskCWGZ2Zoc z_q(60KE8C&RS)e0V~$+@$q){szkQG~d`YmZ_C~iUKl&9q`Hu}c95DM1W9_^h^;>_>y}=#(oSD<(TxVT0*R^21^3iabOY6< zWPXeE8}pMs?eSb<-n2(5sme24Gfpd%7)S24X}P^U+qQgIj^Y{dyj$63n;W86Dd{X2 zCNa)XPt3}yu{QkOtcc;`tF;{t&ygNw?Ux=WrtO8ZSKfW+x>5eV;XLDLRW3-Nz#mcx1eHyD1{_arvE$Oje zI9|7MCknSS`^zUKve&5&S{yB|dATfZ_v}<*&k*4ZgMQU9mD8KgmMKP=pWA5>^CLcd z?F9Pi0$ujJyAdxhf4aZ)*L~?q=QiO5`mY+S4g3b!>7~yII^okiUwv?*Mp)tvuQ#V< zIW-?8W=1wn3fcE@=a^4N^nSg#`M7?}T8Egd%M0uVslFU_qTm|mQG>Ags15}ujn~zO zim%Eoz8hv}aJP6?za?kxKR!Ns@bLCytcF<)cfIB`Ds0pzIzj_qm%VwZw)&>_$lZ9} zuYoGd%k4KvRV0k6_9BwM`satg|0Vk*Scj$dDy8gW==_hbHpCl`R$bt+wALkhd>6c* zkysHFKW9Nk+(FgkW_54phV^xTNO&TaQ~ zmboeh8UNtCzL@J^pzU;VU4wLn{>8`hI2pT6+!`=u`^0hFOF=gjgk8=r%N#z6wPV@H z*sbSU2PzL)X3sp>(Et1<_AYL4@;OiX>Z(2GM$lESpBn7>Lo{Qqh|Z3t;y1G&1{W4z z4@!O)_GSI)@i$_f&+09j#V9mhDVtA=@*QSn<6&JS?lk$ct99kAz0sa?%A7teb;U2f zVb#vdZTCtaC6u#z@RoJMywr)crb5qE%o}rUvQG3{dUMJWof&~*OV1T)@BF#^+T=^A z!*u=6dses&j`_Y`Y2%KzxtBMejQp-y?5i~3wAJZYhvg;@<$jo2OCQ>j(j0NkgwR_z zZG?KrY`gl{bFLdBPWVL~QVZ2~yK``!<%LU2S65m3*6zPmP~CCcc(lfBX{|QN7tyE2 zOzNN0&#Y|0wUUtgG0T>`_oh7^I&S_?{S(tyZ~dSj{!Z3Am9y96nr>@y{Pne31^)dE zEYD@mTRP*(yNyyYYjxcoGFbISbF#~=nBrx#u`BZMJ6$v4pzM@IzwFw^# zO6J!uRb!QBGRqCh*WH`gM6@=mwSR~yi(Va-_Gbg|8Z3#2@`W zGVxU16=!va(;KT?EIme4PI>Fs(Jt?pFxGp^NRhNhULr}ct?8c&(_*|LnqmI`Uo${I$^V8 zdv@a|PV>yhU2`WNnr87K+s&~;dq)ua|6}h=0BYLW|NlIvc~TmPN+lX(%q(Qc5Xn4c zDnk?*LWD@>22zSfGNdvjO_EB5k|K#HLWYV`5l!O1);{O#lML5=fA9Uh_x=Cwa__g# z^Q>n*d+l}3*=L`1_BuO8RQP6n)7bF=VN1qa?rIWA77z6qx+2;^rG8OE!GM^=r=IGj zx>mj3C7Q+U9q8e@y{Pk`j@O2t-F6x3{Km@`r%iPT95j9Z`Hg1>M0vjx9tZ}jb-aTT z46iQ?Pe?KSC}ex&>FQ6RQmd*~#$>rZyfeR2BHiEB+Yb{PKXjJZ`k6B*7B-C-b$HXs zxB*2~+p>+<4ifK`P_)$9cAJq==I4=VyY}3@_B8CxX}2^JQ!|$(6Ba&8Jup1eR4wXG z`iohwHoMJP)Gg6sq|kI7=T^}lKTMA{IsER}6NkRDzz2NGAA$}Z7)XHl5@{h|u<&To5(FBt98+i23vTQ>`xK8(Dur)`_h#$BzKe>L-29Wl;Y#CqPq zO*_wx;J& zFDBl9R(2ElnYhm?^MIt> znFSL*j(vB%DfhGK*j5$Lp<=gX&SGZ?f7`Ejx{d31%b`n7y`rwxB>VXtqy|^oG|eA9 zH^gd)!_;|w&sw`=nhKBWnqx1nnBI8e;fnfxrXv=|c-P-DT|RqM8Gkk2VmoK3?Z9xE!hLT-{U(ffC~Z1jv8&Ov4Q=i{ zxn42P=jo8;&m|TgdiXKbjKgt_ztzRyo~Lvd@6$1Z^*PphpMw_Zrw^1J(#3K5Lv^*W z`CZOCD_7c<_Ke8L`ZRfCO^VK5^Lp|8);czu^Pg!JS6$e>?{*Ygct>l6-ss~ZV;#KqW95g0u4w~| zo=B(nudN(jdMB&%g6kP`pIcXMu0ipK{U07*)W)WJn^bkD>3v3QQ2#t}-N(LmbzL>) zwKW+2a<#3?bH8>fT2k7#i*M-+-6_*=yt(@5sUhB*th=w?q>?adtnp5;p3~ zdPyIjZKF5>+jm#6ygzc^?&P%vpmFDEtlU$phgzb}=by(qDL#u2(SND=C%%*!=q@?c*7%M7bH_Qyd$~DYZxnfXyJG*72NM$u>-z2M zxv{A834=2Qz4y1#5bNcW?)>;ry4r|6m*!^&&L2CixAx}LV|oiOmd8olP4l}|QM*+_ zC_{3(yN!}aa%5Ee?u?km3l9^jx1^^EMZL4p-C#fV=EF139-p1PWZ8$)gIDa@xAaI? z&-o{|Md)X#Tb*v-C!l)upsP_sqPGoLuyOPA(o%e8wy{u>A^TIurl(I+YV~B4Lv7Zi`23~USLKX4sJefi%gSSZSyCboGlFdThQI0I zuM#AbeJS3ydx^9}(u78}_}c+Bt%W8h7A)G#nVhAa-)^B_=AxVOOV{|znJst!94oqE za>gjhvDent2nURj8nvlBTq*Is1Bv=v~#wrttJQa#^|}X|1!rk|@(-C1 zrW7XM>8;(J*_K+e6nkxj=4O!r|@#T;At%PEz{x1PQcUfE^6wvD)W)G+U&w1Q*G!xNo7izK5ZvV%6xJ{t07cK&OFRcGe7 z&(2?5EGx38da(M8q$^pUr?wYUTUBk8q9pxJf8uKQ5qpOA=$D15KEj>PRVSbA>v>l6 zh4bBx`sIN+*Ioy0)Q>kmGJJ?qf3@;M{pMaPUo;a}T)xsN3XJSyt{YTckeLAn3ouP85zx@r@?73xA zE?s)NI958!c%Q7%yS%EjQzJO{*H{^}GZ}esPe!m~FWad}J@Y$G+dD}-P-}~}Uk5wg zQ*z=%G>^QEl#ZI$UZSAiyNL&%YI$|IEStL8a^|dnJkPU%UBcZQt!O8$M#v;hdLd<-=;V)vFZWR7_2tQ}t%j zfUa527bC@XjXb_f@7g8fyd&FXUmhGNRUYEzv%WHZe(#8nTB97Vo(V9!?69;{+tjsh z(99vuyK6qBSM(Ecd6?%nX1F`_xqK>W#KMeL8OAQlTh9!YUF3Gi-*I2jJUQ zsFDPaE}#b7k?AQ3jp; z)tzfn3hGazeVkbwg#@<&Cl$&>XLK*pw*_>1%nosCRFTj#~D3N z?G4=a8oK5`y z^YPpB<17lwq}pE?7F1NPwCwD}57YXp+igCuDk|^O;GMDR1smnOl&kb_2NqsMazi&LZ0C-oYwQ?Y;IamV-)@kyK;hjc{Mk7TCAUIwqw z!u;g>E2TB-b*CwJZr|QXN8D-2l_N!JON8G#4vmWnoT_{!?7oYK<>GCRZKNVyzOGh{ zj6FJcP-t=P{y|~<9evqZbMt3|E`^5@y>utM9~AmzUS@9V z>90Tej6UcVF=10^^vW3?;UAyeIGk4&D(Ty#y!g_WM@iRB&hRUiFj?(4BXI^lZm=rSo!7$qymq*@R z9I|G8;>zKQj-lF#G1Vcn4jgN{N}^(P;8gp<6K88~xYe~=W8hY7tC%fqHh!b8*6z&o z<4<<=OzL-KnD>(RYoy5)i=hK&4@fV6c4|{sl}Wvq4mjZy6t<**5Spzf<&kkC2e(30(BA*K9 zw`qFkr+BBTAgfL9&Z#}#+D@AzeJdsZqoKL!iF|QenBY^PKL>K18>20)#ZHDUmeo7- z)pxa`jNI;Yi{8?ai;cu&>l}B~rb%uXZl#-Vwdg|Ag~j7$m-@NC4$H1bmmY{ zo=#kTuQZL0?=DSvzoJX_5Nn}jvucAm&c!`Sam6S5+en8;3DMQN_=f^8lwD&tG_dMP*w|>$4ymQqX28=nFy*w)Y zmfN+?ruFTE7l+y#dY#BNu8#LOx@pC@RNb+gm!2*67T+SL*{b&zSMT++di2OSIVYD4rjh%Trej7$x^xHh{^QZ=Mo=p3?bR|be;jO>EL-~8( zW5*oN>=5p|VZf`1`sx)!95P4GKfCn!ZK;F94)xXG_}~8WWysO3aWc!ov*kDR)x2VS zT&HZCMLn|+dF~$~*n$BO}e$M&W zWruSd^MJIn5cy<|cHI6A_qLUWJ(8Oz*|?%+o@7m4+P+8nHqH^Fwhz?}@^C+R``tY2 z+18^iV&huPxNm2*ep}q0DxD3oPeV4DOg}Q*@JeWU)(F|jrluCABD+_uS>yC*w!-$? zBgcY{^QD!iwEOFtJjzV9v~{Xo8}?Q0m4wfXmAxG!S{0wPSFtL0pP{9#C0|n*xyE!& z-si$?N!?Bz(Z87%ILEQAr>^B3>9%9%r(_yDE3|Ag#|6uSgM7y>?K#Uebz#%O&u-@f z8=t)CSW?^F=S&Zu))MBm`k_{maz|4gA$ab2HGR_9#w1_u*+t%n5&_V?bxP!jX9o|{+}dl>LT;PORZh*0Iy<_x zp;yA&&85-nPfjwQC!f?|uIceE+uQ6Nw`P!6c0xj2@XC#6EoUh_@EM}*7!z*X_xU|n z+v1JmPxiZ{k^0UeVbje@!?fUOvo*KxRv8s}L21&{ee#KIGw+ltXNpOOwUeCKWYRQY z*Pc7-gy(WHKg^R3P zXU!a~=~s`&4-~y@Xd}J$QGxA)?1~LJkCa6e3IakFtW4{flv!Rl;92ADA&Q$mYMP^Sy){?_x3isml0kGfpQzumc{AJ-zo7jf2aCK$MjLUQ&gK2lPqT1-Ogz@ z_|Y|sA_uFm^`(~gls*V~&Yb&6{mWewag9snWOm+e(+s1Fn}wy^NEgTA9~z7 zHp(SH#$cCksduh#`l^o3_I=I|o6=)OV*6{)CU_~l*{i8HecJT}Cg$f?WCmKE=-I8f zZ2a;2O1bBCK97F9&w7k?r_DV~miKPdio+6@zH$?5qkE^gC3|{Kl^XO|q{I5g!#f^~ zS~S9A*wMFb79@LL+tGCO#lf%ZsyB4cFFdb1Q{mXerl%7ewAYp%?ft6ttP<~nZmN!l zlJ|GswJc_AC(CzUuH!HCQLOEE?^gHZB{pO0=Cu)ynP@h*wrxAh0ojAiM^E179e@47 zowg-UMr${1U){^|Ks%qnf(WhU#y1B%K68CX*Uz1nuj;wlW7fK^`J&w;VkKqTyuGoi zQ;qh(JPXrd%8zI6^*UKS^yAC{r)L_>_`um$yj~&b$oahS&holPEw&U{8rKBd?09>1 zXN|(Zl-gxpE{BuqPuzXIvgDmjo0F#9MEczm)f*Zgx&HcGwe34=U3AZRcg?!;cIV~& zhrOE2q7rVNb~~`x|3vuoo0=DOicEL*iR;(>;@-h%CxPGUGs$-KPN6;D%tCS zrR%_6uG4lucz&(GXvOpn+beq=*&kRjjMGrM=7^cxAT57`3bEm~X;XT1X}7}v@PI|< zmb))hxKJ#+D))2$ZRfmgTpc?!?ibf9O-rwopMLJml0Lr63-+$5&K~z_(Xsjw=bz|D zJNDQeR6n-WG>BLgxoyy;>z55AM;wd3Xe6|vuV2ZoDb8;)w&jK@iC-(qmOV8fdsP>q z7}MvK-jT*)J$yxby($mtexSq2`sHnsT}2!#?i!uhCpLK880$^4QCE_37K|L?wCa4; zSLuNzFZ?bzXC&`<+v>>tfnCd99JoASR`RKixev4F={YOCRuYfzb-PacUh?*k(2v?# zV|^DijJ#zsBik$Ushy6S)2fpG>jt)|%@9tt*I&1;r*`bA(_7rK?33hoF0i-imXrT< zPwD62!0xZT%I-d!ZdYAAWg4DbypdC?zVE5}={k4S)=N(=SYyz;evjJX4=IONTXZ$g zc|TQ0d1vZ{=!f~U=Vq?ya%pe6ftXVC{M`F@eP)EB4n)_7`?Zg`^;Oa+-`i+; zUdW@v8RMo>3D@UxT}Jhjkn1kI`hKmp*W;D@Ii)+cPq`JGT-49${5*+HyGj(NHi%oN zx9Mr!L1WK$^qsT8q`~<~kbb?#&fN{wf!g3OXa4odHa(^#>$*-HmLIvUWa{O`UFOU0 zKH5}UyY%z*@bn{xvvY zf9<_PhXjXHM-?QRj#N1v^IxH@)KOOA&`OKRLXTt?f9fcep}M!mBjsj(uykrbSe|d! zHh=oxA$>iY%)8a$(MfO5+f{ScUG!gUYuhNW4`PlGc3@ z=Ao4rrr_Kl6|UY_C82W9_Ex!^mlo0MMo(8y7x`#+e@n)W^%(PEn5N3P;bSKGoG{CE zzZM}kJ5;W|^#JGAX?U~4t4issQm=~}j!n`n4~HsBDXGo$+p0S+%xHQS z&Gi$E620`(8#dOxs~r9M@a=#rw>VH5QZJ)bmT z>z=pc4sKWQfwEh9JCn4K_5pVw#P;5$QYI*o~&zr|tal@DQiFHR8a zks45{&?vuZ?ZBGierk`#_AFSf)P9j#ZsC5L4w~ls#JGZ^QOo%LeKOSO%? zbS4dJWhNeAEK_a$#VG5MNW}FRIRz*04Kq4*7;(xisQ6Xxn8K4QI(5kpGEptxRM=(r zR*8lyHlu8Vb1hdZ>Ydgr&04i1V#7%VmzNHbCnw22Um1-LdJJ;iFV(Ztn^7Y^DD}V(`mb@gL!RG9akpl3OCZ9hAG zTa{Jvt%i+CyC|O)K4#a-0go;>m`7?(n^SbycKGqcg_bd{l30;K7Ba@BkkLFEK@r-VW7rf?W!C#hv=xGZuOP5{RTd2 zcS_{=Ud`*19r~WoyJQ5OLoy{U$vm7eL|M~mWo3xbo0|G~uYI3XZ%>kW^;L4X+hBnERbh)y8Ti~VP8FCAf zMFL_cZ5yq&?%;Cc-D@%(%KTbthK_O** zM!3ABsDe%l^ae&9Hcww7>rFw z9%XMb|AqP2*CXG)zjJ6oe2{0q(+&|=b{V;LjUN{hE<9*tOrM!jY8jG7pUY46$(gq; zBK)kwyAJ(5(M)fszg2FHsm+8_9OFAj9;7`J$$pkO|7K)H)9|b3%3OZ9X!{@MpB;fW zLXm&A$v^Qw9D&b&(MZ;!GXM5*KiuwL@2vl8d(imTrf0^d>95$vm%kz@)7`KCVrFdj zi>C_bm$ibYk??QEiT-AsATvYa|5`K2KW--d$005H(&|sQXpunff0}^FC;valqWC{( zE7+Mf|CTI*e18+F`4?YDe~<2e{IBl)-(w89z4-LcNd7esN8LXI+iYMP{uzyCqwx>^ zGXnpNz&|7K*N?zwdfW|f=g!^IN|6Kq_DxO|@%^9YJS%eSUrS;y8uG6-{QXuvIDhMT zphQgh{e590qcEN2KLsB}viR}Ljn$|Shk&_1+{m-p8s0BVHV@|i=p@%ild?(p8F@}x z!PGLqAZ<*&Y$Vs_dH9+5QEYNSJay3`*d|TIngXOGu$UlX{<1LLqQXtd#IgUx=9+g@Onz^X2>&I#52X@Xx41r7YeB)?3-9YOAve|!7Q0=eyZz2Nqn z?GR&rWAUTEkLNaRmf#N`D1M6{?q0JV^0)Qlef(i-lA51@+v6X%r9Jpzdm7Gf!cRnl z1&n_W=F?L@P9eowi9&Gpw?<0opCnl}EO-C*KqpkSnE zOJaR9Tz{PIhdpFELEC;?TJ)1!Nw@jq@`IWmxJajIX_n#}gYh@3qeERtFRvl)IDM;yN>f*dV_n&o8n_veu}Ml<|_=DbHs zkmZl!o7XpQ#ogqe9)*?<8$bQOkf_BIfS>74{T1vHvp;{T?Kj(R_6QLC!#skmk=Gi(mJL34a{$8$J1PL&p0}YowCUH|^Qo{6S#z*F24*Lz(_j`B) zvRKl!dF~nTlh3yev_b(q02WfYj6{s!Aiz{4l1k|j6=n1U@T5`>M4Z73z>f-9cmVJY ziDcm+fI##Hm<>JvWk@6+4+HGMBLI~^L=wnH;vrOiRPNA0kn|Fc`Ds86yPZksih(d zVE{T*hEegL@|4PFD$6mP4jqxnc!u2d8qSj4M96)a}MkF~AQH%iC3`7o5IZGvt z3I{I$qyP~Oh-}`)rAW;Fc##BC(ZncTZ9JvL7!4qgF#z|dw1ZeOLR4;10gU4X-=TC7 zE|D?7c!1|XU7UCn|wd@{ouL+yGcYWh<4dNF)UKa|gL}7C{{{ z01TH^7?P2OnN)m{h&GbRg%Dt87Sp)a!3x~)O z@~}W06?qZ~-KmVD;*Lao;UPV$J)%QQB#w$A764qKG9C(PPl@y+4>;KcBKwhu5#;J z5_v>PpWI3j4^mkltc5dkGY z4J0y;iXWAHDvHNAwy>1M5`YS?b|ey7LQO?f1?&ez_E9=UC6$_8Kn-v!6=tlivc!Q7 zJfAU3dyx3Ts5uMO0XLC%8gffhA}^_kf(CiWI7C!Y6L2vVKPq>qXpn~m*HAe}rHG0$ zYSEn`QbtJ%Iswi{B1~TnQ;MfP#vG2Fd9;b8bL7>^t+hjKAidM!nHDUaV(BeQy+D^2 zw}GWZmV`i$S8Kx3LFD^H$dGY2X+e%P=s=}A=<|GHz`+=N? zV^8v-0>>c{rq6!VjH0p(hVgtOU^tIta0K8;AaaEg)53r_xa7%FB}-$`m{)rh2t8y? zBOC>22}I;@G?0gc$Sz6&RFbHvgJXDYEhsqy-;~6$yo!-5*#qBah$i%)K!oX^2suIG z(pZ-Evy{hDdvb!rja!I(dcaaIFeSr8mmO=@G=77h=KE36{!O>H%|jaT}0N zZ&?~m&QNgy6-9FX&)s+hOPgRm&nH2GxV3}HXE`n*TJUHd5b~oE&HC!8DG!$906>M= zt)sY*yfabh1&aX3BaxF-%Bl3h#ej}fjsg)g@_vA;$(c5$QDPE&rqltfcxDLl=_yO{ zEBbmD#YG=j%;Aa&T+EAfY~JM-PHTj#EjXl1HV2 ziYTlF)S%~8BPdlHrCY6^+M2vj?BzOBJ@`#c?*wfQ8BFtdNuvE*^ zAlyLDH;72%M!+6G#F>&Gl|*WG1_vNJPlU-5!BRC#eQ^`rOCplEnZ79z*+D6Q%2jIW z!4`V@LByVl2bFLt*Qh*2B0}WzF?qrfc}Pj0e9XkTRG960Q94H@oyv1^>OjtYw$c41 zQb4I2`NT?|j6^n5@um_%C4N_k_`EP$PK$gv`is+a9NMgZh{a zO(I8fF1fRmN2EvwI@?`+*(hTD#@fBISUG;F9RaX zCjB6YM|yCSN0-S#l3QEJ`eN`H&!<2p?Qk*`TQX_KjfL zfXHAtNk7jJ*-M4oqz1@L6_I;X-jPETIjor=opJX%fWkI3g9BE!iX zAGcP8Onh-EoFzj%&$i%GKl1A5#?dK4G6_WF9qSuLrp3^lN^3IF$BipzDUO^qU=OM}RKBDZ!6OIMNj zUQ*MWOfQmWJCRm+iJqzv8Bb;#$rgwxk~tA>+hvrTSTmI+VKM{A4H-)wX7ZVih#Glo zA>&8n5S1({uc%L*%s`S)R7AX}WKj_!hkYDMWg(e-B!|8v`iX#u8zpA9Zc?hCKE~WY z<|4Ti%~Bben&kQ-$TOcjcT;$#4@*TX>5yqiZt!ZB;#uO5d0lSpc$N;66H%^Dmb`;- zX$6@~B*$7JL&%&Z*VmTJRB|bVrT*j{gx`Ws2IM`0>+>LURODqv#DiQ8`N` zoot>=e-Q~F^O$7xh$xU5Kypq+#F2^*l?W;~sT5Obq@qOTJIVVmkug*(scfR+jYQ%p z*^n0knIIujOr+eQz{MQC_zrp^5{otA|EJ?A+x5qiOfilLk5u= zDqZmbpaqqKRAR_XDq4}55c1L`@{|(uR8b}G?Kq4~i*e0NYBCjK-yOy*g+PybUxwXrIPX^@E3)klXgl;mw zZroEcjmv3APL(*lsmvlXxSVTL7Lj>dZpbA{cUe=BOxbcPX0qhRQXxw{$-FIR3>9Wb z0w~3ilUUAUN*?5x&WR!4NO1xs+?fEL%#%3K-29KSvAFO5_V&GGj{TLJw2}zk`gDB@|WZ#UttTS|3#UZwC6fy{gvte$^Fj={5?kC zPAl>S@;`+)0@k9Uyz`;|z>t`TO8@6J{vX)i-`%9Bc>90rxQr85`?u!%-TnA?$6b)u z{{Lb>{@vs9Z_Kw%uK)jmAzmas;%~i|4$>xn>;C=j6HY{O>fdWWo=MLBdv)k{NAiC+ zPDy&%Kg0BAhJ3uJ{l8(rMu|H78?yYFe*YhiRcOEOpTYjY$l2qtc=O=f|p#WXxYQ26^I_{-Vr(@e`|3j(maq7jNVL`}Dnq$+yG*-|uCM9ULKD z@PBWoTa3Yfg}GCa|K0I_MR)(YPP$9-zdQcxw(;xCFC@tq$iEKx@2P#&ihP0myWJHN z^7t;)lw7jGEq6G4V(eEO&*s6W#k`uEzvj>63dBDsk466Q3tw+eK=UM%L;{d?Z}2{H!AY|+QuIzU z>$lNd=)rffhC*aH@Nbk6oWkZ&BSpw^;6Go)ImOKzc?y4HHm~}x;t}N1wPq!bHNTL{ z)VO6WT@FkyQ{xsTa)lbVgtEkQ@c*167p(oTsE~`(T9!>5vJ$vO=^@Nt7~GMU^6^7qGd$=wl^o!tHx-gi@oIx%yYj#TFNG>Mh zn!8wXXGw!xN5-wKX32_NM@Cj65fSv1q2cUG;1(6V*oDC@D&~=E#<*FQuw=`U6S5;vv(%lXek@HR*RgW9)|svZW-|NH<-n1w$@mts%YkiJvSVoz zOGn7n$=oc~WL*!JisQa=NM?6-(KL!7VCIvkQYGSc+pQnWc1= z?y!{4(o>eE()GX0Hjaw$sl_ILY9`{4@AjySL$9;_wk#7i`p)-lL`!Q2@W0%3Wyy;r zf0j#)1)hb8S()_=U7v)%{6pku)q|MC0Ppd!wO$^VQ?@@VJt`K?{;+7Xb?@hH@r-mnBi?d!L|%fHZ;s<*pt}y;vH^(r}jI z=)zzo!CtaRgiB3yb+97499WS4;SYRFZ3eqASP;z6XYvyx+@!+nB4BBj6j@SbDG}!I zT1be@Ks z&>^}U_$+HOzS-;|U`v*)SsH_zcx_e5ViIl^Z@L`#JZqYXY~fW1x+b7%x-ghAZ_tIo z3{4W=`imAH=)zzoE`u%%W@w72(=S>uAu_m~7gEfUi?s6}HDlWTRMydj!Az|QyBt^$ z{PhPurnZ({7%T{8Xd=5DcqU5=SX#=`DwZ~|w2h@bEFEC!FiS^SI?Yl9OXt}o!c8LX ze{yg-leskRXb5&|I+;dm>3b;ry-(2MM^sH$2QwA*EFrrbSb`-zx*V8^`@)hSUo>49 zEHDLh7JYwQ@eKTU6{Rdyu~f&>LI~i+MT+oAkp9>7h+P;gh?5{wbuD}9CiJ~e(1M{* zx*Rx#E(~T&OOcb`Wog!eE(d1J`z#4+UD+kV0v|&=*oDC@Dw5fS!RajBVJV*_`a6N# z?Uu0gf?XnPAadqceQvQ$YMQePg9Vi?WKOW<_{j)g_|7M2(SkU1=`Z8672=a1q=2oB zpbLWq6_eOSz_VDgU}+gkt69pW3xk;ir|H6AhBW9(;DK~uupo2!wGwRNctn1L>C4#6`k4Tz=F8KANZKsd+fqsK`=vY*+szWEa|Y+gQfl~ z8L>2mrHL#(WtRwd7rEAagj#I(N9GJn|E|SuGJDxdN0DKALV;Q7X~vG=aH-l7K9AreDme5$+zZ|Z_PR1ny2Z)U?$ZTx-gg_ zG0}U?(+f5vAZfZBm@%KTv_j3ESBMGCqbf^wl(k45-SJ-)PUp5Nq&F&z z$V$nyR$)Y0R*IwCwylb?q^ztIVP=1s$Yv43BD&50akTm2vQjE763B2f(5>)V@wWPX zx}T@vC1JYJtVe7&cqv=jyil??Wb5B=?@#W+AE){G4v?W`J13&kRz&xwgTU?7&oed4 z^XnwPNFjJgel{pSZ%p>2*&{%a?#j0h?YEX-Yn--^*0~ApYMvItdyc+%cu8``}p%D^x+eXF&Ss_V$)&z zsr*m*JB~mA|7Sbq9uS-ya7oVtHhO>6?wkO>1gep(i&0MpU;{|;WLBk=) z_oj`E4nyxF5W`%drQr)Bzq<}=fFF4H!8Jcn@P`0@+QdEpjs-v!b2--fK)4$StAfDs zCrmyN;D7z}HVL*Q|!IZnNUPQZZ^;BXQYPeDHYRc#m%0!w~$S=IW} z@bNS(2!$7+&=?8|VW1xd#$j-Xxl&3#98QJP=6lajeQ*{M&QTymCjz!bz>x^bk0QY2 z0tM|zs-zr@ge4cD;3CY6qNY$ZoR5YXF;Ei&YRuJ6&tqXs98-0PsylOill*0vbQv6& zE1VJ-l}&(|39vnZ#t2`5wO1(gOoSPU;6#4^jk$KIDiL&&U>E(}aL`SLy~z;CT)$*^ z73{7;&Q<7`LaRJdAeI4tV~^+qlkkdgu8Z$cDvm628^EX#z9On8+^GuYmOd$+(W3(kJ~a}mke(Dyd@ z+=epdf}+)Tp!g0{^eF|2vQt9O0M213F!h<*-ji(y4EbtV);w-;dclJfRfRR0%>Mk!d8!hYsb zoyUx7@h``TU|=?LO-?qWJNXyifvKOXf%Lf16Vb{_69iH0O<|zz5%*5f))Qdn8HR7{R|18X{zH*RC_eL z;H8@3>%7Zd1YhxsulKYg>PF?^O`Kx$#T3Z!V0Y^moVB<9v8^-s*>cfOdf+2sCilu zA1I=P5{^~ET}qg$gkP0#N*h{rl+o2~F}E#>Dx;<{4pzn)%D7q?U6g4+KBJ-Su)G}( zZI4#%(WyO#w#U@=_@+Gyt6*0Z8s@<0I91A|JW$1+YUr$n;c9qI4a?O~v;%hUfMYx0 z>JBs}kdV*2Pp^tk6YqJ?yQAW_swL zhtYaip~uU%unW3(!4dk@ROw1Jlu-ht*mR?wq1~xEbjMf*2y67f@jZ~-B!+MSqp`iP zv=yA%ac3X87_@>iIYn4UBkI0Y;c^gjW-rE>lqzAnwKzlG>#p^V;=_e$MQ@P?85MT6HGV3Dif3# zhX&(t!Z_SG4!y=<(l~rH4u!{~`gj~S9(Rq$r18AAy-jhxDJo2$W;vq{W`eYa6DiA1 zqB?F8?qPuN>q*#pGTxX>{Si~}?G$vHilI~S^Hl6K4L4826VtGI8n&B`OQ+)jdaDe0 z%;>oplt~#l6C-BwxQPMJSv-@}Rx^BkHg+_}@#eVL9No<^)Ew`b<2!R~HwXL7!3A^B zZw}s@!)rBmF0P%6y7Q<>?qfi7KcfUlnY4g~++y zvYu+idhBJ78|?9@J;vMPb9-#GN39LCY7L_!H&Q0$?ncyiz%>r&>wr-XSm=Ns9Z+o( zt+i!z#AaS(-e&Bv1ueGVrY(4A3!dMC8Cz&oTSuzpj@WA}T5P3!cq>M3#aj%w+eSU_ zwqb84v~t32PU!1|QBIiUgs+@vRqyRo#hr1vGiEqrtuuDnfd_VA+74{mf!%lFx}6xZ z6QAxx#a%dl7Y+7fbk%Om-AzqWI`5&7$SC6g&Arr9yBA~k;j?|%v=8-MaI_2Bx!?g8 zOmM-6E-37Znyxs(6>VJ6#}%Vo@u@3*c12w`9OZ^<+;G1eUUtKLHxzP54Rs;9j%*&AE? z;6NXo>Vuno(Ax(SeK6k#zxvRCiHE6nI)ZzSP#~p%0XtuwNjwi2KI?~H{ZP*zjs0<@ zKf3y3oImFIBe~Pq&;Z;Rz>BXAK(#>33#8`xAgV)-3Q`Fjqx^_brC^*I%&UqG#^PY~ zJx)#M6Fg@Lxi0G@u04rvC-KxtOgf4ACux=TDXNX9aDE6cGLiw4(>#;Zo@01ND836t z1V0g;~do_MhTFz z^E~yKM^N>Nz&r*BkGOyW7O|A2X^Og=SH>ISPHE@In+*8%_0oG`5eyjpWy= zWAJhe7RTV{80-{_Lu1h@7M)@-G?s?dF`6C6G$aS2OL+Mbwu{G6@n{o|JLB(8BZoPtWSMc2x)Jdc<_Kc2C!t+VI%$Q8Umr(+w zG%Qar|9eau>JWrA@LKJ)VoDxu|jv``yDy_t54Z-n@q|?$H2)JgQ>%al(B( zdmo?P$2R1y91qap0rlTxG$WK;bRPV%uA*81cyJtx+m1kEuw1qlvhPq=NaWDMh8B}4bOR1 zubyM;V$3L}=7|?nx4p!}FEQgK7Qe)%mpJVe+P})_)Us7FJJj;3_Sa%UEv~EMnHKeeCbJuGZ3E^u zU_%2cHR6y)oJH<`(1`wxnAV6zjVSt=2G3%&R}&s-;6>;hpmY_ItY0OLBSK;J)y)Cwt9h&7sPr&nHQuVf+OBA-3MO!K<;7K zaRlBR0a0HV=nGN45a$b5d?D2rZuvrqFHH7>Fh8jCgE9V4>JMfCa5w-;0>CH`<^;n2 zK1Y!3@X9UDHsL?!`WaMcN`8KhjQ|ZyC*>71WY{v zolZjGNjP*0q(eYA1m=W5SqM~yKuriVkSU|nAaNShPea&g=n@Krq3|ITq{2We3=G4- zmHbk67}SP=RXDs22h%gq_bePf3+vB8kMnTiJdlfHHbj6&1cXLFQUo+bK;i{Zjf82D zU>*qzBcb<22)zhuQE(~>qN89zG|0rjofuGzg>$ix9t#bzkPru%ad7?;n8(ADc&Lj9 z{mZcCGPqra;LDJI89rVH{RG&U0J#b9CIK|AK;0E+lL)5d>eWODPK1O+c#sIvNiaVN zs*<2pG8iXASTYD*1r3 z0*EVs(S;CP2)!P|)W@*zF~~jv=_1%!1Z71q^BK%}2A0oY=`&dQ9HfiEvKX9-;b<}B z7em<#xb+eYUV+SOxbPa3N}zoSXq13<33M$1gA(Xp0z*n*WC@s*fLRGlD*^Kouqc5g zC9u2%)|9}85^yX5=Mvak0{ctgPzm^zz)^B*h!Qwc0vAdkwgj$}KuQUumq2z2Oe}@H zr4U>SX{AtF29j@J-Wyo=27KPY*EgW~7ChfV^jnx*4)e>wqZ|&GLwq@0tbpVSsIGvz z3eb56`tP7kC1_Q`)=F@$gqxKhT?MnMU~UzxuYx|+p!Xj7y$6jC(Cq^p{{RK#c6>E3 zu?B)`fb$UyKEkw*AoK}3e}avlAp8?Veu8_Sz^oSL)Pj309IA!1T1c;jZFS&Q2U_(o zxE_|&!`6B@T@R`CP*D%!4bZy*%o@O<0S+}lasw1JfJh@uY6J)J^ZJdD*9aAjaQriD zX@Y%CAn^s-e1Rih;M5n$`vMQYfX7z|{0enn;qzB|qcL*Hc>s{5w`46Su0%BC;8+go z2w@)~Tq%Tigs@BqHH2}wFrE^|=fWr?f)_r!jJnm9JJ4M{4h|!9ON~ofQvy{+V33HWDwhbc-?lij zErz$nrnac8jJ=i7Oc|Fc<91~XP{t%>v~7n6+F@}!?AIPAwa1O^(X%~XZjX8G@pF4@ zqk=U?o>s8RZLVxZ8hAahKJPfiW)vp!!K&6+yRGmK=Tgh+yPH^z^UrE zUL7;k@u@nZ2HI$#vL-IjL~l*JrHQH?(Y7Oob;N>>sGx;?weY1Digv=;ozS%tdUnF- zPS~R}4(^OAJLCG!c(OBwc18(;EK_Ol2u8StRxK0-j z=;CEvyswMo4$3NeI9d-a_0UZZ^Ysw^A8l_PR@L_Qdymg;BD#7lmbz`-b{F=xySqEL zvBfULRzStV4iH5!Fj24wJ5lV`tzrW)007-%=9GOlhdB0c;a4zYBgwIgXuL` zU4yt9Jghd z)}@^5h`M?#tH-K(?5W4Vzo<~3I`#SKT8-C$dJQDR5Qjl zqonI}!REv^=U#I%wcw8yG;Tq^7WlPbdke0$;9UzmT2iScy<4)QCD&R~q7`LY(YO`q ztvJ(~#MX3dL%%jWYeRAy^0%dMTkf?bsVxoK(WD)7+Oe)3_uKKf9pBrryFF7ou%H9S zI#9nO%R3U?5kn`cbz*TR4s{|^XG(WwN@s#P6W(PR;=1y@ zD}B2$vKyPav8@|7x^br)0o~cyoj-a|wFiBAFsTPydT_J{FMB{w%JigZPrQ0^yeBVv zQl}U7d(op8#@^iT&8yxF>%)XTeCtEzzEti@^}ZzcM%*7PHyA1VF#+>c!S ziR;hO0c;q+wE>hFNYjCA8OW=FR2anML981@^TGT*m=l9Z8O*oAqF^1jETe8Jd7j5csh(9!zezS2E!ROoQ1^}qj2TJtNPdjOdlY`7h#tj>QA`}ooY6cQ&9l)I7(=x&%pSx1F>D?~r++9k zmU3hHFqVw5RPbVs7n{5|>_vhXuf33Q$;_C{s>vLgOra?ZpTe9e?3}{sDZHOT zwyBh#O2?^Wo<@mj%$P>tG@_?bY&zYh<24=s>1>})%yjNf=cfx9&EWbBihI+|o0;A$ z@g~fhcyI1|^V^%fGr2L7l0NkDVUiEaeAwy3DIXsC@WqGRv$!ye53^`Eo8Z~pn~mEX zYRw^N4mamuoXcNxnLn2!b4i^`v3c~GhtE7J&ZqNy!sqjNK1uU&U%59V$5}r<`C;;> zwm;qdndeWiKUe&D>yO7`sw}48V)iWN&SEMqq3ROaE+Oku5|{F1DFXr+6Tl}IDRP}U zx{RvJ_^^zOWprOo@8zst&Vl8)PA$r^f&weJwSth9>|2S~DrTg1g;FS#E}`@ZWoalYLTR;w?mI}@frL>ejHY3X4P!|d z(P7*UBU3m9!)X=H@Niaz^KUr0b~0oqBX%-(C$)BweK+>qtlmw?Zc6N->K=ydVZjEre-7b$i2aASbcoM~Fho)WRAH(xF zy^fRX1Qky({{%-*5PyQC6AU`Z*pqBO$)1xuKFPl)*$_im3~gf>5zES0B4W88%lBA{ z#!)|xQE~Xj5gA8f9KYlEBc5iivn=CT7SH2&+)gpz6hltobBgMx$$SR$8CINO%NdHg z4$VEwfU^uaOM!EgIfw5#mYn0#Ii8=R(s`<#r`>t7UEt;go?T$;MfP6gx*@>0zQtd9u zclmJ_-+OGk$JKkhxrgmO74OsgK2z_r{XX&cNxo0c2Y5bU{sZ|eTu(Ujgv2LQd`i`)jC+dTQ|>c23p%`H;!7^RgRr?2?= zirlX$`I_0UIs2MyZ)o?1d2fh%!=pDWf6L*w7~j#vbsFtE#=ql}ixj=5`g{I*kJo!9 zzNf+m>U`kG2RxFgpG==*e3J=HCNY_mWd2B@Mhb&dn4Q9&6fUOlEd^UDf2Gnpl|`v+ zPvv?lg+9{qBilX__K{N`nemC1pXv6Q2cLQUnK56O{)IhX*#Cu*UzzfiJ70P5l|0|5 z^o?2HnD>n>-{}6G5@}RTqj4J9(y^seG@Xj+3{B^JI?vO|nL+Uk+Ga2!gXJ0Q&fsPS zDH%9_Q0E7!KXCkH^iQ_^WY13$f70O>eSZ=7i_O2d_KTapSo)g{zg=tZrKXZWN@gkv zQ?9LHbJKQl>=%(5i2tj{ckvPiis(l3h)$|Cu* zO6jcPn^l%%l}lOWc~&WrP0D1GrrAVgm#f+3L3XjYNf|e3? z;$e_{1}S2Yk_IVnkg5i$Wsv#?X=;$x2I**!?gr^=kiiD|+aO~NGRYt_3^Kk8H2KM{xC}+vy?PTMYGf}OMSC6F-t46v^Pr^v-C7e zKeG%m%V@KVGs`ry%rT3fSpv+m#w=URvcoL9&2q>r$ITLFmh)!0VwOa++%d~TvphG; zJF}#kCCw}@FSMIQ3>I-%B)>)ev`A@-RJKShi!`)IGmEsdNN0=mw#Z zRoty&vWmkh`K?mKDy6Mb*($ZH@|RVbS*4v-I$NcuRr*$n~#UZmDvcMq$4q5AvV26Y{WUoV_91`b{iw;R}$SsH5cgPcmyl}`Hhom?p%^|-W zlFdU*9+KNb@_R^e52@fGH9VxQhcxw&b{^8*L;85gP!IXXL#B9$w}&k7kN^)^>mk7& z66ztlJ!HR!9QKf79un&zXFVjrLvDJ=BM(XPkW>%(>LJQ0Ih~P9%r|fsiVW%8(N}N+J zIpvyD?mOj)Q{Ff=?%hT=Lw0i=K&S^Fma5NsU=2_M0#s^%tBV@1TO#i+Qw^7^xaI2I zay47GL`JVr1y-u(D^;v+i7dHVz2qIYgIkn5*fW##jI6l^|b`!?kW+J2j2jrMCT-C9+6_niio}Mrir?2vvEn78Ks6 zy6#hb_Nm4DRNMXP)PB`ew?w`_pw=8ze;raOhg9xJt>?u^Rq?PEyw`P-Zi)O6rCLR+ z3A!0_o33fms^d{LL$^eJII4Od(}v_Zt~wl7Gmfimx+U`7ab-TC#^{zv%Sko&q}r`p zB8$bSUNI^f346T(?Ae zpHWZGs2yk3#k1=3SykYis-;^Z$DdO> {C)kfVCnd^cYbU~fEpq^gPrtNxB9lxkN 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 literal 214377 zcmce92Vhl2_V>(vEkMGfNkF4SLDzyVB{W4>R#b3V*HtX5XiP)n2EvAbpst4Ad*}fv zq1VtmK0p!0hDZ@afiwhZqJli}`~7C--gg7hZT`QT+&goooH^&rnKR|iotM?EYqk)g zVz2u=aD=Fvg@Ba!hIh1Rd`H9hn;SIj*fce@W3wjljT$s+dV7OLw>NBfOUN2iCAU|_ ztfv;_?-+V#?U{dR*n;2XzI$0rR7E#PNNe7(L5t)@38_t5 zq%;gkYiorzP48**^%wms&KTFBb-O1|EKo%!CpAh)OHJsQ*0FKN)CLVhLex?$Cw9$F zO?){s>+fB=B&DP!retQNg|-GBY4z~7pYEx5{P4wU{fD~DZO+0D~Xvs z(o@qy&(`l1^>UM2VxwjTpE+>;g)T&%meM>Sp+Q2Ujt$cqHE7TRYzTi+YDQXCqtM}! zJH72Ue)Q4E_9yE1Y5wp^#Y|G8=4s8EgWm>e4bz%+MDhwRCUt!=IVP{TCJJ4 z_RCRio`2%ANu}=$W{w6a%^RmQPHxgLsYS;oO`9}Ej@sq1pOlf2nG$+)^&h+MeEt5z zM=H$7dvN?uJBgu1=! zCCyWllN&W|k(8R&tTB^UNJ>r3YLt=QIW3fu{nev2URm0F$Sq6%eCx#ng^I4Egj8r^ zGiXgpQq!gspYMhAP8sQ;+i!`fd-G%A-fgOFzUtbApG;%wrb!J_TXbxm*0foZCe4!? zG$J{f$uE)V`&vES`|iCB>t1*+wqw&aL+7dFsg0X9Y|*@VDrD5GMMG7Uozgm`yqFb= zJ5}V#J^n%Ll+@JR{?`|ESJZdx*rZXjw6tWXN^0{KNl@Tv(Vx~D*K>dGnb8Sj(@(Tn z|IU*_R=vG(lca{tlYqHtT56-FEfPp{*R(7s)Py(B+}z^O9orr{e{k)H>+aY@w5drg z5*js3ZJ3hUqCv;z&8Y6tDmCgWE4_PKXy4ZdN4)uN&CFK{F3ny2dCx*2s@|TQkkYhq zN?J;T#wjT+8Yd^IDrOP7Rs5sLsn0%nr09W#Pu$+9%Z1VbEGH$QNpeE-#*NbwQc@eG zq@^N@@MWiU&F&hif1r}^T3=PE_i-g5g1%q?QJ@(%1dfMZ5&crPtn{v_=_%RinVmyI zdJydKNZb}~kMu|(qx{wn0p$!pY?NO_rFTv2o|KV}vXDT^Xun)nfnG~i_FH2s2{@uA z5@n@z&Fq$iHl5i$Eh{4v+M%-eM2&}B#Xg$$LVDNite(JD)h}Y)6m`{MRXZj1NW46p z#MRKn)c{Rd3QJlRasc$ake01|HIl$v_p~dr*8;^z7@gX)b5f`Dl*E@Z(LY(%d9B~NM+vS%de_X1BqOytkV_p%q7I~12U4peg{(oz$Yg5@Ssi%_7Z4gzL%#8Gu^fU?=V8!m~h7$(V zL4Dq#rFsYAx~63(s^qL41YDK!Vp_`IO<9>;(z0w3Ag(fGo>&GM0;{BCq$OpQ4Xy)4 zNw5W3P1EhJT@=+65^V~JHibl+LZVHjkauY{yUQ9&FDi9O>zoRqCua8`pA4Z^nNVT?=dCp7typ*6k~^u|2XIwVc6L(Ai;3Au zS>(}_j68@7YV(T*+PNdd%GyR~j9pqvX1C4^YYLtpw0W-LG>nKQv<1g)!Esw~+!h?S z^>}4lDdb-?*M9-M*_qi%8A^Fr#ck1gA2ki^k<82t1U>2(6?CGMF5NU7tzp=|Ox41W zB&dUulRBrqoSvHfqD~lNuxDpxCA~oWNa_DaHxx;60jQ*UCRN`IX$x`vO^fSqD3*$% zQX}daC?CS2Oa>x*RtG5+iQqv5(p51!h4zuw*|ezVk^cD#kcLkLZ6^Pm**P85AybN9 zc)Mtp;SDCCo6b(mei2fAF*AcErY)r1Q4`k@#OVT1E}~upX4t@u(L%lik-r3yzvL6u z+-mbkMzcxL<-v>kB_D8gkZn6z1nX zqs5eY28=dx^hf?`5N&2gH&#yKi!jz&mtKNF9B6RC6#$srmwdzsX3P~1qf z876(AdTWF|s@w1r=n*@ntI~!8PqYzKBC`S6Fe!x`X$pcXVoidsDn(+~^cOlOWp~4{ zQ6&?85T4$V77ID0%+++TP&622H12ybNmcMTAVbfg!dN9pZ^;R!B)Av@c413K6hk*b z^bBPOnAWLFwkg6Rr|2TUYK7GFt|{#9826@xhP{b$V;;^-O>6CnnGP(K{@xjb#l+5t zV%cw!%bBKZxFW{x(o_77#(lY5rw&k#3Tf;J|IHvOG#c;+$!xTT!0i6lL- zZgp?qqeDBDE)Fztjc1^#fBWXkQ0+6W@n-_Fk0~ia@m=Rjer7jTEJ>`W4;f@ zFD0E-xEu%qFha>`S>%;q6_|^xZk@`s+XBj9l_?aisEBc7qRxkGDulLQXEh!m+{J4&7a{F$F{1$h$w38-L?tSC>zPcwK%`mB`}!u%GV z-$Ks*L_HcNB!&DA;y|~Mm5!0(E0oFi$g#@gkn%jr|KwT$7ioW#QNr^(jHKyB%Rq~8 zWeg+Z3S@*UDkLU8k>1tx1D8PO$m@i>1eykbH@e%P?qTBWZRyC~mQVPeNXqC&?7b}z zmDZyR<_>xQ#()~#i7~Nr+RGe0VLF=CP4(mbk<*iyc)y)bC+nK_4+IRr^DA;NgluV&VhoX{vXf1~4iy5f(cm6)OmGx&_(012Nf=GcONpguq#s2R26FoXZ0f z5IFDhKumY#0#_hxJ{JmvT*N?9SlLh*(T^oMN}~N5&I-Wp32;^b4lig|RM7R>ttrc0 zi3GFjs04Nd^Z^m8T@jUZj^v)0XCZ2>iJEHB@R*X;8yRkl$WX3AiJMLQX4DjQmM(P` znJu~1L~b=?ZZ%}m#f)BVNB9=FfNknJC3OJ_J50n>MED=gE(()^FvbELhjECy9Y12QuuT5jD=_uH`*9!SGj3F9tWv;z#SgI4f` zDYFiSBwyNP!ot*nWjg|xmaLAlRE3Zf?M@*Tz8G?4n z)I`EF0AF&!>jCGWOJV#s)Vkj2Q)mf$qmNfbleho~o7J=(U_!|kbPsNSG6)qI50OAdcV zA-^xfR5pQ{W~zJTOt(zz6*FDN*0%F@PRr(EVVS9LnFJi3LT#@|P>U0f$V^$4LW9pH zTnD}01jvMTv<`ZeN$}H-g0X52V^7!W^kP)AmlD*>yP|OP1jJw?qIHfchF@-2suDsqcMNL3J0O}=di!NNgpPDNmJx@MGT`>ynv5`k6Eu z9Xdw!YM4Z$))e;aV?%jU*t1=R@}|mu?M4%%{o3u3Fqgnd`?VL%okJ@ok#fIDvY$x~ zn8tkoNog6rFqQ$XvR_}qrTzMfLL)%?b;Jf}zY1;OCjiAZFdD|J)CT4N_}T!@(4c8Z z$Pcd_nAS0D z;4d%`mzNB(OGXAcUTqy&EUja2ud$w9Z5?~VrFBGROZGRB{k@u!{$5Q9UG~X?5l)*( z_^oC~QAqC|LC?R;Jo>&0qv_6eA~HY872-6B zaG9t&J8~{Msga_dpChU%I==B>fyS&UI>3qW)0j~^EIAqUQGq67RwAbWHx+0qBw{O& zM@}ZNq`D8&jzSK3v7T2w8#diKuc_Z3RGYN z`x|10Xam%dl>}HGb!4>$B*tBavbBhzj;sZR)DgPWk&Otaju57fY<9uak&uD&z0i@Z z2H94_=G!hdsUzD>{C1-wbg3iAY{~ac|q3icgIAwUKD!3L;c7i@qE zcF_i?U_aRa73^mM#7Z^lU)g&CSW8D~Ugtxu0+rDI&6h81r*QSH@A zw<~J89aZt+v==h7)6D>UrX5@xbh!G@R$0mEBtySdn#EL2F*29~ZnY9c%X#o?C5k~@ zWw{Wrtwesg7_3r>7GvE+E(QNoq5=rhwo(DP+$34fBrA>RRvNjlHgbonlxQtnD$zQU zLV!xN!3L;An{0qe^p*`!iM9|RBI?aH4M-v1F-5+E7@D7VOl{Gn-n@r!>J4G)%}y6g zz4_3&|t zZ?LK!V=ssOl}r2~bp1XoYPpB2dc?!v3V55~ymnv!SKP1!TqZ2&yiX_-9Al5h?In!1 z7~K?sc&b5LjBZNcry8_Xqnl%(RM`&J>2Z*&Y=^0KCXw=_Npg}&P8-foBdM|-Mr>!1 zh_kbEaFy*~tr1YR!v>V?umNQ|Y(Uu#8(2l>&VgTPh)Zi*@s$tq%rnHn#agj`52U9( zj9H4|c3bpaiyUlGa!CYR1%<^-lM4JU0l=6=-bF2AZ8JJXwUzsOq@-a9f_>)-Cx$QJ z?(gwp61MQDm{p8vi|%oaQ*=eS&Mq33u&s=i8v)beu{kPIT=SsKD9_s#Z-!CKTSUfy zz>`T?o%MRi7852vyaP5#mlh-6aZ0N!-*rk0qO>aVeN!4=5=A-Lj<1|=RGF}RJ zWT~MEfLDHPXsQq+WJTPSaL3@Tg1aW}SanNT3+~mpuTi&@ad3Z!`)1s?s9VYga2u*y z!nJUFWFx?haks>Mx4Nag4{mF9OL;%s`(x-@@&WiC!Tnd<&)|Mm-BKpPO+=dK;l7Bw zGww{>U2tcqTgt9*yCO|C+@9)|@>RI6BJ7`V{|R@nga;4h!y=LdeWMvR#yli_mYhUz zG9P(-%;ICVc}O{zzNO|Ndt(ct}1_wFIZ~ zvB5kfeHLa~2n+G?p?OI9EP0e59+D4B77;8p4~at4Xko-`f_O+iKpMft<{{~`$@K&`nTM3y>BB?$EV+Z=PVSn#vsx`KXN$XH8DbGAkU;o7zdTH;}+7^5Um|5En&QCVJnu}Z6zI}HwDX^-= zX<2h#OABON0tuH;`YODyv_y`D0j(yXmxb|+p~kDI>G^&B_P=@GI7s@4!^UJ78f-~1 z*n*VmU`wDFf|`WE7hIk9nn!p(jM@!SQNMujLQBrM z0R`Y%L>M);;Rd`-MfnU9civiDJZb)qo#`)AADh9$W=K)jM<`MsTdt^&c|B%Tt9aM7 zeSHG`?F6RcdfX!L0W1kdmO^}J$$>Z0^AT)@@_dX2p*)|!NGXr0hWg%hKbPFK zEg9%_HSBttzHQe~fALPdDhv};#1hryc%wDdY{zDZ1}X8ph#NvzlVTuOYy^H>QXYa>y!$AoKcU2lu?&cp!_s*oQbH*S;F5&)a4xE z?;Lf}lpk7o^?hBv=iYE()HL)*Ywz!|t9zhFH9s^UG03BuAH7DBEoS7LPyO=M9~n|k zb&mq3QNZ-kEo^?HJ+c^+OCiR1ye{wWyn~MT%tVVu(Yi_<2~|>@|co7YjWrQ zy2TT>J8}*^M>+3!p7oxGa`I5l+}l{r6pvah6=Etzgjg;W;!Te{uRPN{ayZ8PLQMCl z5vdR}JZcu;a8x^KH`g~`GgmE} zkw?zGT{q3egqMJ%+f~!lnYv}{oL4`6LQAKVQO~m!r8U}1tr_(^{v)NYM(JyaZ7p8Q z-=Pt$BfQ=t=idPr*9O8HJ#yn6y7WziH+wJ(aFyPt$yGBq+<&C2Q~HP`r*!RQ=_8Wx z&v4zgAXa;Oji_?&-3KS_D@swgb?t0N?QBQw4F0_oQQ}>X zT=08V!4A8c-m|OeeUE%sMeX#+L(21kT}>Z)WLSlKT`NxW>ttiYg?d(fW1@RSg9QHV7 z`3T{o9>**f5-!4+|9UO`V!|aJ$1Il;K89hiG0R^QKJIbM@(IGY8YXtUkdtJ-l>Wa{Tt?U-I8 z#S7an)UW%u-5CriryY*~rV+q&ys;DkG16Z zl`3SMS8i1vQ)IQD>&|}d*y&sps4H$zN4w&*j}-^sWlXIGDY&Ir<1JfpPp{l?y2ZtB zXCQ+u2Hl^|_C|?0%rV#NRNOqm^Sw^REg-zm>r~t#!i&95#VsMc)az7S0pVp{r{b0q zUg32rZYAMWURIReR8OidG`_dbKPG4Ha#5%a?so9B-KnS@k&1fnii%pBeR#slmqxAm zg^JpZmp-4d>^)xVOE|pt65i*P1#w3H%Cxglpm~(fZf9eBPCLu>UEa>7-~2=J zTgP{GBgS&t8CTt>ko&1VS=v$;`zGOOKH2MTxVWYhp5c>uckAk#NjTppSKqCxZx-R% zKKbF@YUrntv`Id(YRpYPG;(U`OomfS+RIuxlYxJ`mb8zx1m9&GZv)4;rFi?YTH1a0 z_WZw(Zt^!0TBeq;qAu1k$9k@}YN9p}-pD0axVSbE-VDx-^?ZwP$mcY|ErhrF>_(`O zJXhzI?zsVaqiz~C| z`-40MmzMKh*$Z1ST{blDvxalW{_WfXC1c(5eF+-A1Pzz&<#6{apIRps;;>K7Z$&G4 z#3$D)&rzTJNO=l~9G30BqkzAURL~EE&qpfg0^uJc6?BnsI8s4B5x(S9kocK! zj-OVLvkqNhw|%&Oj_0ndl`aZ2&7(l`D6Dqs?rIE|u%&2=Ou1ae)?Oo(>)Tg9`uo9M z3W%{xg=w)*1*WOMH2QuH2jA4o(?U%1%N6&Nis^p2LwRQS6c;U$=55Dz^i9{ zug+MUHuau^JstV4>B@$q%bACA=AoPw4`5Cz=G)~gfXp9YIScg)vxBVu(bwN?*C{dH zK{hQrf~>&r5zAO*%Yo-XawfzI!Ylo9*@JL#ts=bIFLyqu+P+S7@4({pF;&lf<6!+p zVO17bd)c>Z%K*rqH+cYMJh#Y@DdMf`1Y`o~r-ZlA9!3@9!cF$Kd$YJgv}iI4G~ zK!tn)eN>)ZmsRzjI<3ETM6HZZ9nKcM9O0lpDC!T2MqWi821vOO9v4Lyo=T6+{>$Jg zE+&Q}%W$OrS!Ed^<)oTY3`3yJ`1H^2cwR1yN8@z_H4f3^kmnqdN-7Zmfh&TZP(BDYe3!BQZuI}W{dA#kSCvR=K&PDxlL@!73J=lA0i4|Dn zfd}i}LadZB2bev{sGdi>*K9o|mA0^UmWBG)J`vkbO&(b;KzL1z#4 zufrMTnMo(lvy{#p&s%g>dp@SK-80?`XN30%o!#C!J~(;4B069CX8GYv^)I3`&%cIF zf&U#koBf~C`N01LoxT22I*0woG%aH^ExR=>Uus$=vAj{9S#k<~|5;ibHf&V=^oBbzrz9Tx{N}ca*ov%daTd4DG)cM}m`A+J5r?vB)cE%IS zV5?Xo+e0kdJySHB$2GF08rgBp=8rmGp3b+P&NS<|&fc5ZPgw^vmP>TL^vux6w$hpH zJ*{yLBeHYel^XTObk_P#>k@{M+;hI(#CZvO!r?5jw$j;bou~7?HJGUTd(P20>*-IN zy}fJctoFW7XS=r#k@fP8r8CO+4xMejeROvF`mlsv{;_mM`LD&ZY62d&J&4CWujA3J zFS*RY$5L?m<69*-!|^>4oN@SK2hMc4p3ZXiN;MAo(2{EmRR%c<&eYmb%`L3KHn*_+ z8o;zTDo}IZUBTv9ZVINuI#*1WHPNKeOcF!?!WZ>aEP6IB1qUnO(-jd6Dnn)k@iCBi zAB%b-+8-6|4+tNYAn_HjeFd8dSOaVb=DZ@<8buMnI+qAyl?5LoTNoxVbH$at5f~MV z4iBFtvlQl#!I#mdu?<Bk&UFP^ti{k^TaP+jF#N7Pd{ z^#!HnSHegvvak|Bg{lL6ZUm79o4V`ZKJsqY0fv@N9Z;xIHw{MtZuw`~@+baaj!LiP zKNMR=`a#~9#49&Xh_!_CP545l6+!d~k;}-R3wc`p9xLG#g>U)&l;zL`&@IafR8@k# zq<|mV zzr1GV4be5DT-3}0!l)Sq|64T^uxj**reL+j$y=ZRQ#0QvK-WymB{57^H9+~N_Nq*v z8bxj;e58Qts>$RH3Noe!Ytz~);c~j}JxxZuvXbp7<}<{aK^5?kg9%KZh`MU%~&D?)$9N<0#Rxu2FiN zy}Sm2IBk1!t|D-)0@`m=z;%?ewX<(c#?+~;G#nEuT#m@=IU+x#M4n(oPNHI4LFA+| z7IO+-v5)>MktdF^yuYB~Q`n~~UjG9PPn-gLZV5XYPIQ-RxWWz%S1vSMNf;Wg;D1ZQ zeb#H+P@-kUE2VBX53h|Z>w2ZfsV5Y0gOdGg%e;)Kt9AdP0_susMJy}@E=R)E9SKjt zNJ+-lbxRl;t|i>UNVt_FVT|S)5D_jt7O@hVhkhwAUZrzVHpVeNawlGNGq|E93YCW= zMYQE$Em#R&MJPOo$^fz4NDxGEKF^Le61T8MBeV3p*T%}LCOromGpEk=_aU#3nDxf! zb{Lx^(K6t`5Tqm)TvDpm4j)S04XH4Qk&#jlv0E^uVhx+6t{IP(&|D+?Lj;+pPSdt8 z4a4{K1ro>VkQo(+(X7Nv@YK&SOxAD2g?O8LF0xBi2$)6EcOZZ|x#v{~cQFXDUE=L_ z{!nyt>P@#0?@GLq%U-Pl@On;&_axr7zP4Qj@YO3uo!9_#Tkbv;!k45%?38$ulQ$T{ z82wrYFW|9B>-Rg~R3Us-hlLaD0jj)VoeII~Cl*lf2}G6DQ!3z52JFI4srz$(QUP3T z6XH{RNpo+;s0zf(Wlte?qwH$0O;aH$4EPMYnX2b*MSxFqV!&RBb)nR~Dh1YvgxDvs z?2}!j0&#cDTw=l6hQyjl>KYZo1r#B^z^YMf#sL*F zU4`I?OD7s_|A>W?KE_^ub? zy7;>BMfsCTH;pSAx~_C^?~>kYi~1E5u3Jz%cY4v3@gb&+`w)HJ`}m>}nRZDGxbKZG zT0FI6_|n2P!-_@@EgG?=c=^~e81m+p44PLmvVT!QZ;h?!&2=Tyb4nL)Djv7-)P|u7 zZFrn@uMl^~7v;@8mb1Qe(o+v81X z8`d40lv^@;{izL;G~>mC=9Eq!S~96GiY*#Av1swoqJDEratn(3ttuXrQ&ccj^H@A$ zbm96{Mg5l-EuN$?hdh50q75)>u1i<;EnYWLGY;g%xl6#4BioYPxge=z@p!ORv}i(6 z@457>nO(Gaqt2*t4)Z=JL~GzIT|HNqTexm?@t9$S8}oqkSk9!<%>#-?3@utbAHpxr zT~$16@u>|1?|byrhCvYGu}OK3_%y!Hycn*u1U{XkWZfK{j06tKDb5>Ys(swr;^_m6 zMvOOzr%W$ixT$2_?BXeJhF~_znt)gsU?>_?&DelgSeP;<^Z_Yif`5AW4~p9tHsBj zWq_-}$DUz;tG&mbW`L`?$DU$`6d7#a56rDFqfznx*0$q?B2EK3Z(R!0(h(90}AZ{7~wHG)uFXCALm zu@bwf@KGyXw*J~3hrUrK!n%hz;kU5-&Y%-ms^Nw`B!vx!K1P4fRf;GPBPt;D`^wSS zK~%WfBNMQRL?h5o7q)L4Y~T2S%V7QnnB91>BB=3JMCjG^-towD_$p3d;VFE^a|bjx z{@DDXrAvAhPuozmVFX%N(dK@~rmrtqI2#Qz{;8*Ke+n0@6JtZI@viBpgH@0se4+9kGA;+N7G0Mq zLRed#@S~N)PHE{^tmvzMg8U$7335R8(X+(2n=pWi2SA4S!!Pe+zKZmJM+*c zg{W3N{C>3rnel!#?xcss<3-oU)`wf5HL@+f7ZBd$q^@ZgGOk3kw8we5t*bV9#rF_) z>|j6YuBRo=oWi@UA#H@H^e9d@%k0FDDUk_-$DtT6{=EV6@8Ij2VT5onq=Ia0tpkNa z2eiBS4`SQO>T)RVvNU?t(js(=xGb8`}d> zuQgP5x-sG^5ng*$J1y3sSKTbdjq$}wpvB{sYWYH}$MSN@_Gg1at>4lUB%2bKf}Zj7 zEFl(q#$WIZwyXNA?LXtA-}in-+1C5;VpIo0cEZQ+J(=_a755=R#*hu`qez_QcF62+ zw`Ilc!)X{b@lig;!44xb8q(CvAPTDTAwcTt?yF>YNNtRhp)!5H$D5^?c~2 z4!~!4)O>vQ=!C!h{byed99XFsM^VdPW-8*Z@V4Q|E*#8#*pQ)AjMJlp;uY&lSNAcT<FxTa(oO4c-J4dE`o-bQT+`__cU152Sv=W}= zZXH9?vjFRDo};aB+?e*;3c6?94R=hKx%y7aX5btdz*_Lw`z3Gb8F#<%KbVo3jAIZK z70Nb=;GVg+ZmD_efHJ(Ux!UkrOYyq)Y8jVzO*y1XQ45p1$}LkeGP~l4wZy;U{IPpN zqBa|<5Y?S<=MXkVLPro8)v{Zc?nzl)8KR~)kR0Sej8#Q#d|Qw6LP3O8Q}ctx4rPgW zs!>f5o)d>PbDEsv*EEwNA--tv++vIh2Tv>NH_P2ZipNhwBRMu;Sn<@pWyjQmLaB@6 z%3%ox#S-5+D)!y~MN@%6x~!?JhoMmI{%R%gw`e!eRNje`;n~+cq**Pz7E4HX8tZy2 zC#Pt@I@o~H&6B}%$@&$=gY!8DVIMlQWYM6aP5nwY_bQpQ9>enDfg@>kGZtY_z3VdS z$Aogw!cO)fyTg?Fx#g=A zes;YpmKIN6wxPXNfl^!xLwlVVx{w3Db}R6_ZIma^v&Sm5j#+a&82w-X*Y2N|8Pjp2 z>-B0(SKS`d=^%{SIt+xQ^hl0jHD z3z|_pd~WHmk;m3gC|#V->QDF>SzVV6NbaVFm8qxV=*EZ}MK}~)SCv#aE!u)n(*lE-gVhPd1!AE;rFZDZf)3A#ZIL%8h|bDf};o*{Gdzgfuc-Cf6X-% zQujNp2UV=_{HnlKQ1zFv{peu(@d|7^sv2xJD{SvowZfaLwba5LRIQ;U?l2>$;;~CH zSu817Uo>@y9zhlL>s7jVO=P0EVOr^?F`um| zAFO8Rx<%3T1wiauZ+Ens6}O~%IR!{@3+5J!3Z%Fdc<}!=y~@bSBlH^U3K!A0z`EY5 zt*f%Fei|Y~z^dY?X0HG398pUNVa54aOH_~7N`<8cJ=-suI5#9j_9UdSuVKmbMfQG^ z2vPs`@RC}st=3Cw;nZW!PkGV3a`Yyb;8pf758Xn~$xj!^@P%4+t@anLz;;DHDaR~D zU-z$j$$5!#M}f?n&Q8a^h9&>LLBmFk+0ZazTVLCX+v1LP84~c!CUb|%NjFCPUW9Y5 zc}VNe!K>?7A}+pg%{txlV_5~$2zUDowI6Vet7Hc?+rUqLuNj2=~)B7T?Sw!^$yr`>D~cogAqgTKt&Mbrf5f9Ls26|(R+2R@Tz(@ z=o%S84<>4BFd@q?TD`0&zb_U6xuE7IqVL9fzeGeIhloBPf|~|hviPu`DY>yK`O|t< zxZjP?OXnJv4E|NO*+k?oxY2647z*OLY(N@qPf&3fZb93dh~1mnZRT#r^PUmj?VjD9 z{hrC*Y2Mx5W8RbAJl|p;&fZ`L`ZAV&)S^gJ7>4F$J5U|O4zxFRFzXJKVJ*sbpgIU0 z=scv-9VmnD3}@Ey06#iVWJd>@E9-ig=3M`Pe&?Vl-k#i&`=`(CL?A>|xBzZ#Gr`A_ zpk55*Flp=xHOK$dow-cQ?CZ$8Z(w^ekW<`uu@Knp0A{IoK{PFuxW5Q^!Y3=-rAiEM zs&Jb}+-&zJY8GBJv|rK41;s-LU{zEb3DmnLCG^^N6o0E(_es%7hR7i zd^+&5@z+XIJOekSmZC8;FP8xv$PDKm|4CsO{R(@Oa_TLK;6%8Revkb+yjGlve z6+{pt?o;}(kf4PV%4;mE?Fr|^y`f|ge(#!w9t?htP3(*LRLSJU#nT381$9=<^_0SC zIviXs91vHYkf^c)sj`CtcAqwok}@hgDA4}{tnz*!?fHcvbatE}w6!910YH2>R(~yn z1NK>ZEqBFv!aL(TE2>u%#8Zvgxvd;x-beIbRx-a==(SG~PQZK47`@BCLHsN|t zcyir(TG~I{fFFp6Go246ZMqN8s)vy$=S>+i>Xyd=6>ykikcN?NBy+S}MlY>v$a_GM zS5Vgz{<`kXE>r`$v@sn(8<9V;o~LCVh;m&{2Vhzc-mu`3;z6iT8?o&GJAl4N@q9F8 zs{c#hG2cnwJb!_Iv!CnaJ@JA;t&_Kf)E-hj!Eos{T>-<|sjk3TAJ;+b3MQ&#Toq^7 zpUZXyItX3CTS%q50tP+2^93)84EL9HyzNj9R?2|}UBUuc*UPlIqkVjvYpzh2NB+t# z;V1$*Hd^3o>=g|ni@wKZOmP-{xqdma@3HA?@%j#Hr+AMP->^Z08>#iJzjh-nV;Y7# zH8VV*ztMpC`3sAe(ck*8jQtk~@ex%q=X~Dqp+LN*q#$s!SKJt{UwIYdJ)eF#Hf$Q! zZ%N78!88&}dQQqDBKr{q%OGwDPD9v z-l4Oiy{Wh_56|Bh?R^dR<>9$QW4sx-FAooIh`Ga?u;KEE|9tk+Ma^FNRc`L>(691k z#r((E)^sJdp<60PWG@!)kxxJKY~u5}6AXV|`9W{oVRr&YFVHD_^&j#meNf+OL2`eC zE@H7zczAGAToLHB=2lEN1y@vv9M9A)%z%J>C{xR!XkPDDeNZV*;hd^o465`*$4q*Z z=Hd+s8dIpYXs3r6rMNUb;AjroJUGOFS15!L|#E8WhTa3>|#Q2;MBV0s33o$+iF?wWW ztS+d1F=k}}T!u%+{Z;GAscV$3sAY1kD@7Z}6b%}t1scj8A6E_~cu!-AF%)I4qcCGA zO1rntr6_;HHvnS-_}(khOl0)zI3q+(Ij^oa2cQz-qBw7O&9zMwZ{bnbDg&x#*=Aae zT?=`0jY%CmqiEQ)P~Xkhmd7HS!&t|1k5%0L_k%zzGh-0w=HTON4F}IF4nDcoo4xnC zatM*)c~k32ky=lR)OwPsb-1YY=TYlPy78b-bynrJB^d)(aJ6Up|qd zwkgcT+ek~K%1vJrP#%Fq@n)Ny~Up;Ny)heS4Kw6QSmOK6iZ#~@XMN(7}x?nbc z$qnAuaF>nnc=La75g|&C$`@XQ=)$Ax-sFv&ST{l+aDiWSSwM$`syaKW5GgvsD87JU z)~0IprquO@57)b0E8&WIY7k+RP;FOn+hp@LxKF>L{wqW6O6!$Z9#wIiql)7KEc(A! z#cA1&Dk|D#^x1k)MbiJGQpIoUdFvm)u^d7q5@Fuj3#!9Xr+3AoV3wLRQ+!wO5W!o64JwEE($ih>UT?gaI)FZd3Y%HW;iG@iGMUdLpx zt_o?VLjIsansmysBw|fZ? zvrzoLh*N0Epn=7C3qviJ{c@oboI)qK3!QLTq3i5IGo3=$TfT#5bfM=ygnNz6>6n2< zYldQs`&gS+jc>>AW^!;_@7ynwFwr4lq9P#*pMIf6ot>_3<}cWEbaCkT(el+8h(qhm zg|)13$kS2@BRtA;n-6P5dN+)j|EZNCy%h$+acf(s!?p+>qO)sJ*36JU6LR)QtNwQnz^xsa+jXaT+&1CsMzwrm1a@qqf5{eGN6W7rZz6 z1a_skh8rb=)?(QW3vPPTU+L^##Ra`X8)oC60@r1WlnOu9sradi#Q)wDVr1snLL>f7 zKEqSC!_#J;Z^H?Y!=4N$_o62=ZFBIn(v2H+PnP!FWKmJu z{agMp`i*XfESxY3xDyOHSEV?G*@+WNooh$;9z9?Er+({F==a4PcSky^jU)TItM-Mj z#c@gTG7L)(Y?=zp(MBx1GjOvHb7w4DK}K3$XxnD*r)uiDb*WaK6Xl}7DTK}EP3q({ z=heoWfgRm3ycl`bUbUJQn0q49gcLP0dUzCsLyGVnHO$-?fNF3!9UlCkV8SNG$LL>| zN=wzh=9FE>TE-8@`Gzlv`DHD{iIL1r2KlvB@e9Qq$?Cr*aIa5>t4@&^*2rhfCI?@+bTcWgAf zs-j_Q9L)+P6d=rXx$0pi>mlE%hndtMGvUi;J)l){ImQTUO|%i#Kb5dH0#w4<8tpsL zKgLzYj_z-m^}07i{`?qU%SG;3M-!Ze^17l`dWS-bj4qZv9FC0o*02l;aOFH5v=bV zQUz|jdwsZc&P;AiS5t%hrHHn#AwB4eob8|lFhGWjtNhNFTUprchR>#kQ`@m< zKF9Xs_3vDa)9hslO|gvLR0FE7s2-x2yBgo^9Lo!ESc;Q8*D< z?Wz>{N2NdRYj>=Rc$C9B9%-Y3Cq|4y9j~!&_iw;2#A$r`X>1TjEc2WZ%e;W1HG)M( z@3rtPm%=n!%YC2a4=?sSqy$hn%;T4b-;oLUJ*IMy!|satto{XjEOgej=Cc@M-wMQ8%XXaY7O04D%uZ>4+a_t~F&{NcB~^;`sO>M<7ODMK(8b%$RB zY56VA|8iZ1dmNjqWtMBp44xQ)OdIy#q$5;uIN#UMk9S=9jn=U-o7foaH=ug#?YxaG z8s5KX#4@w$eHi)e>#S0M$e}Ds0mjP}I8CWFZlwU@YzpA{?+rx%57dxx=m?xV?p$Yk zOvLfolW}mi9ysA7{J6#L1TGx{sjU48HZ}0Xh>6glAN;ra6E2mTi#oK(>B1HT&i0U? z1Hy}7lF|JFs78ftlCH+V2#}LMlr2XF{JVDt{BZ{YE}9*ZhW@<{1OM@5+W>1>D(xr(maiCUX=gDQ8%u$J*L|FH5K|b zpn|{U;0omtkKcOG@|OhYF#eY=@>PL~UDK0Q|yGVo&-_@u|2pfgQ|pR5}| z;I>IP9uVRz{Aa*fNht37W(l@J>(9zYjKU{lA&jMGsdEH%#fN*+jhw%ulx~LHy;cS~ z;8s5rJl!S>p8sCyX7^;Tl$+z>{xoxid*;hoa<-gnbZ(+25I4=8z^M<6WH}I)Vx~HL|5dNaI%@Ic=~s@!m)w@v`BT(RlAc+jTHc3^1Phw?}G%A4n-sKlhOG;o4whZy;%rQ!^8!?K-?g;i_oqn z(}(7{Wk>o((uZC@2XbKYwXkkT&Rg$u9mypX}QZOPOPZ7S}ZI6MB9oyN5yz#`c$RPb;6erE;SnTsD8eYheNP4To;E7}nTRJ4Dt6B{hs zmsSkqE~b%hzY5RgawC5EgGT-Z{OYwb@>t)%5fw80Xx%6To*RwBdRg;5;FyXp8aAS6 zZ2zJ;xkaNU6mFOl!i;Q+I?`8*Wa%q(BPXN*FUF*DB|gWKQ7v)v_s01VBQNC{a#$|R zwW9jsz9P=!-L}|LpZKZtV(BZZ@jDu8@e3My)bN276}Q`+AX4EHl&~4DvWtQzMy!UK z9P~7dYJb$@LhIzBrC#OK->SgUSFm(qEVV`?qfg=&7l}1StkGir76HnXUGPMOC;6Hv zk%hnY-Vnvzk?J!xy}nqwX;aa_rT7*Pt9OO#*1@oZ+E4fW5*@1@I#z=YS``;RGI}9? z9!it3R+F)a0nzwn7yOEj`OV|h(m=>{}tKC2pmFz{*RZU;0XTc7>axhR!Z0?!OzR}w8eA034O zn%NtucjKrR{|LdS-=Wv0#kh!Y3SmQ7>&%VT22dbc0_MMFD~>K$Mz4*5eyGB?X#LoP z0GxT)dMDlRLmf`WM1|k3^01<%{i-TaA`o9Zcx=h6xuJSH0l6+$hq}%wd7Ua5h1%=r zcEO)iu?ya+3*N(kO8Uo;k}~)UZygRYC<;I1-7%>KBP+6$g4fpj=Z zBIxDu5y*)nBM`Z+!XtQzMlVl@KxsG@0_ET+2t?*qY$$jJ1R`kLMG(OpVI^4{}OluDrz zV5KZVr#)HX41PU(+6{bcbj;*>d$mSI`KBUT zXggn`Vq_HMgp>H$z9AJXGSz2*b;%!ly}UVa+6b{uM2KI5ed|k%y1s@GnV?)DvVm`M zO#dc|PF1uN$4tS@s-PHRV!;S#6ZL~BF+NhFC^z&Q(lHI+OMWADf^zBLuxT^v@hztw zH@oWbE&8=UP8hmKffRsZh#7RXV}NzCQZTJb1)O)OlS3qq&UqoSK=FEkfZ*UCyM1W zlFilX!*}$>b8tRocY+I(4b(RVq$oeguE!kKuqwex!Mxy9n`+S}dMLsj$tmzk$-y3& ztESEo^r@7pPU_lmXCD6^1l3&9N{a8H8^jD$u1gyibY@7l&Eb9A5$G2q7_Bx;=MkeG;{K6FXAH28J!gu|s`J0juOWEq>r za#hQZ?ShhnH;8({o0JMGLH?`-sT?8BKS5N^k9H|av6N-?vVu-t(hVg5@FlJ8b+l={`zI7r0i_`PG)d}O}!GOAzM4BKF|3lc%XQl-`dFF z_u8mJtR{Tl$rka}GF3H^7Qrrrzo|O_V^DDh zAyJccj2JwLiD{wWnc%maP>5Kfn9%~K1)i=}{W(~(# z9V4w3=XIGYaDqDbL#Va0BGFXJiqT@|=0R?>wyBpf&f+g=?QfP-Hf?@s#JX z88DvSP^fc+HwWTzGyslSTZ*ksdIA9E+CKJ|_{I&JHod(Oxlm_AUx8xV$|x2@V8sn!?e~>titQaT0LbdOgQ4 zUXrU0)xpVTlW-UvmPFzkrePo3z{U+4G>E@DzHx&)%*QI~)atS&c)WQZ=mPq#fs4g> zwd1UKa}Lfe38|B<%VrQaR~?Od;H=|!ls2y|PmYELsaeNpOD8CIJVvwjE-l&)KHhW8 z+PeWLfiY`4{%5oHUc{_n=@6HUBFQ)sjb;r5qE**t044yzg*R85XxO=#X?bmVGMDUd z{GSVUn4nyCfI+{Pl5)%7I}ZQ!2^d zq6sCb6F{mO22QYqNoPmWRfIqUq!nMkQpgC~Nm?=B`U+z%(mS3G25DFlfd=AVd7>1d zh_uA9`Bv~*aURc<7%>4R7MW=r{~_gA1ojBN62z_@bE%W!BMd6=*BLZPl%p8rK?bn$ zVhZV(+99`7$t?$BQ(?_G5aXfr!0oymj)jFW&2QTSZFy3TTBJpm2O)6e^`>oe=>e&E zpm56~3y0Ewg6ErfDTn|>pdaNBOMbV|3a$*U4z6`bRy;(+g)_@z8%0J{cLOU%RkxZ^ zmCE(~Q*Gity$J=YmPP7nrF?o7FY{$a?oNB3rWs^!z&+Zjrx|ed4@bD z&~tIrJAUR%&d1RuI37!4r0B=S1&M6IaVT>VM^e+YM3v|Jr-F-vOC8eTF_BlM+k^a{ zmy`cw@btfvKei?gu876&dR~DUhbqT5rXD-jFVPVDG;t)Bha+3YzWnduz)Rg*V`r9! zV~vbm|L@^ALL4RK;RwrEGdMQf{30(mS-^3dRgOIFwPNqn+5QEN%QbDHCsv&bsmJeg zF!8)x)3zy1bNyH?wP`7|vYsDlTkEMio6(5Phy=>wH#Go1(*Gb6~h6d+n)NZ zzYgQTS=Fo=NOJ_tZUFSEvGXeUK_=dfkXnZ0DCFf1}U81G+)?mbIx zX9bh-a_Vx5y5q;RcUZxH2Hyzw`nPHM#6`;|YVXqJ)U30qQJ%}Fc}`K28Uua3Og=p{ zHJ~Nfrz|yPy1fl5n^2B`Qf~wv)$MI8+wD=8%w;P%)*pWJZtwf2oNjNu>Gn3+{L=#! zSq}=!bbBOOtH!_C?cEd=dkbHoYGagu_Zlu^qy__TX{jhjh=EU&bLSVQ6%|5+tSx00 z6R>v9WcX!4baC#*gkM|+*zzQo?PzA*d3P?cuC!&_G(pNCL2p~{Slg`~tgMJ7`-(>F z2$lujLF(4x)Ah-w%GEIl$Adi~nzYP5t!pDgIeK z#kU!I&t{As7i054ZOzkVXZ9Ooplg@0`H7m@cS`CK3LXp|3V!9VT7A^LY77dO-q@9u zV%OlXT+th`wKkd$%!>_}CXnkaTY<*&#dpBAp>_mEXPBybB z&z2|i2E?d>SDZj3-gv7oi1qd@v*D=y5Tq!Z&Ewthq0Sbb7ITXfH`)2rdtLoqWXbRW zT)=Qor$gDh%0ZPssIsD9=W(J`bMukI^?{#Y_}KUr#RHdzIt)Xi%Zb>wP3J6}2^a5{ z^@%|FeGAtOcc0`K%6|8X%;M&&CxcOf@O@+g|1<=STWIG}b5S4_{I=qYoNQ};+~R2lA;g#V%H=sK=3G*9&=p#S*#k9lIGN8Ig!8DK)B0IH z4y?JH=f4G2E&Pk}Z?5wdDwU0+ft~XBGl%TPaR_2yf^xNqjblIC#piq+a2m({0P5c~ zj?e$+?)5;VaeQHvloUw;C`N!lDk%eW@E9HkeHBW#s` z0kwEm0tO5!I~K03;*{i<4)I@-VAtYVF-gSYSt*jMK3RF96rrLRC6rk_D*^Stx_HK4 z_=_;8e(>+t88k`sPXki%vB^Y@mrsy>yyn+z9Dn8;a?8cDZ_F%$MFF?#ayb4!m_;0a z#+gMNCx@8GpF}k)khl+&c&cNaIt+C|@4t5j?!IyZ9=_xHC<(c(t@bzF0vDuf2yfWQv z>6e=zR(`(i@PD!LqiWX7o9vYz(5qH{ zezF@RJxZ|l$`9997GcAH(;&@?Pe`w5yc>LvKdNf3U#SYTElV5?fH%q=3VRf5Jp*Bp zX!30`ezwU_9!H9ot@T{GoR;#}dVWR3q@~bBOQBlpxty9_SPM|nP@c=Ean^dM#t>O# zEv)>t9#W&aA=^s#;e<*G<=}_kp6$!#Kr7uB>dsdjhJK~$TE4bg|6i>2%zD```qQ+bIv{Y+wl7FCnxDg#T8 z2Shsv1*a*P(o}G+BE($T&;=9uBd+vC7bs=mDMuAmfwxMro+_6D4$yk4;;;2oWs{x~ zVkXj4fSwFcfL#1@Jp~4y`W64gz(bWft*EHA9w3VpW}TdIJ6o8S1_8x&51xQBB@^fX zmn)PDT6-=+^iGZwS}b?Sl!5XQi7RdUDTdKBtbD>%MY!5Q@P;lHuz7TvLWwOr(McX` zN5Tqak>Ccmqher)xO)*^z{O?P0MmegNHTrXus9efEL8#b*a3!hS<&y9t zZ{cR+sqwHaN2}C~#$r+8D-hT+v2Y|PN?a--aRgUIn6neNb>hktugc_LI&tJroDre!@Zlc8RB_z&~>PO|=7$7wix92aXMzAn~6o0xa#9p{nKa8U*gHmA0 z2OK+uW~cP~aHv8{e8Os(YHE?dKIw+rzzscw1IB*QG&y51E?%iCk03c{ zO*sPOU<8TeU~5<{9xzrT5%9x`c9_l=lTvRo2nq8AkD3N~s!-yy;VH7F2=^~9OLBvQ z|56$4efKFe2|ezQ&R}#gIuy5iSa zG*TN_15~242tT?5)S?U{MA8xg?8OKY*^AOrgM#t~Z*RrYQX>Tnp_Tiazm}G_P116l zE;YmmK8!_a0R*ws&_gIKgFevYj6*Kt6=fJHl9osy2O~%%2c_kmSX$m85%5E4IYH-( zNvSs(20+4m!6W`~C-|Pv@;KZ@m)9zE*;{5u4YUXx&tRNlN3l<{&#=$3quJ-!F_08G zjZyHx>kND@0hutP@nB@o{}3FXfFK3fp};w8xG0C$DnS>)f7CmDqqA%s&Gf#t=FpaBAGl7g@_R(79z@IEsA3u-rkF4vQ`QTg_g;>zn01O zO)?ov%LZb^WWbvY0}w>nKo6lz4&G0b1F|5zyjEQh$>aqf2O~%%2W9euSSCLp5%5Eq zjHC0#q|}=X10Z3(;Gr|*Af4lcrW_d(eJ>#%X!5$m7DkYW2T;QJh#dVS=IF;}9Q}lD zkW#?pB8?YfK)uNzWWY-gJt&h`{uvUw5$^GD7hRr4=yDpVc>Kz=7qE@rWp*MviJi>8 z!cJjdWnTjTP+1b;fmbqJV^ZiE1Hs+05hPV(5=1oy9G*tMtT8R4jd=KX>3f&{U3#tR zze}$+)C&M$jhWcQ(o|86Nd*zZ2oj4HYs_aX+IqZw5tr|0DJT@W#?=3Hjrr14W3JN@ zf*8Sff>>h!L6ltd5Z0JsfiyXjn#f5L)tEFO2O~%%2W!k%agF(kM8FRv^9G$SCZ*nF z7yt?L1rMF!N9i0jn{s4G^t~mjF}I+`U^0n#V2$~P9BmMD^jkBIHlSNrV{X!TAt)vT z-e69e!b=Z5s2bCl%Ytp}aS|elIfBg?id*@#JSMUAUN6EUM=K5`!Lh>B3?(Lh$5dzI z0b8D4RTmS4vzkf+lwf~P*fd7?`pPMVKCCnvj`xX6Wpv1X!V*>}WJ`uI-j`3GTbuQ< z7wowS)e_F^WoNRp*mv03>>PG3`!3rzoGrxlDvQiBWHq=N2L06{1ENhNAdn-V5ELbT4RPQR!gJdr=? zL>vCJ;&S=Hqva>vnwB`*HMD_;OPue(4w?uskV64%j>Z21co&kk;f1d|mjYN+1EHOj z#8a`rNd5H|Ta+qKdSfB$9fD{r6SE1sL}6Oz2zbgURVJM--|JL)#lPG$A$4Gigaq-` z!UWkl_!Q0LCd9!)?aE}A%CK{A_*$yzyEZ8qY9mg9te_H_j0K5ThVgxo61oqy79&Wk zEvSSVv9^52+YfP-X_Nwyqm|J2zg9v&nv~Ezy3!#=Oa{EkFaSYR2IwJFLL<-7or5%1FbOMDahE3(7DSTNw+n2;*UPP-MhG2cTLA7`Cu7BFYf(o4KHt?2|>>)^#;l(0+LFW4{HW$bcx1-p`6#eT(p&8}wGu-~xXvfr_5 z*>$Kfn9Ndm;PsO3Tb0v&t4g+TLG>%JK;nYxYN+72pc+mYmtw+hJ#Zd55BBe10vN$L zhL#`>Pd9o_2|2(8hli=)7WEaRxFCdrCn4TjNdLaAKgng1@FhpH>sJt9AvHsb9Lbab zLzhX;`ZE}I2xF@x7zdf8*Pp?-j4)s`iZ;9;^O)qrKZ5~ZW@?e3GTOrE#3H-UwO7cL zU-Cnf1u&*bg0YlEuJ|(;&Ikj(ziNv|D2ojHGZ?oKMvf#HFIZ&xAHkqBK$C7HH3)Jd zoB%^x+-DG!#l1ycC^SLt>=?n0v560z3{I5u4j3PSW`81)pgtqtkF*0V6-S7`Dt zCj6+9rS0gV2|vJ>n(+H7(z@uN7~5*X?~7RL{&vFeH)LUp>C6M#=r+?C_PF{Qfej^= zqY#Y-5gL?3%*9p{e&1T-B6-5^f8esW87_NyxEFeBY`%-Ip&YHS5l{G`7z^7Ynlq9o z{1BTKP4Q1*wV)mh5aT@rR0nK|_YlGfKN|mLdQT+Q|6;<=!&KZ9|Dc;<2LkFoN&`CJ zflIntG{uOrkn~?o_#q9=)K3zROlex&eOtJ=Tcm!d4vG_~B*=<-Fc{a&utI;$_&QK! zNxr3M!q1u5ONb}@Kmj=-dYH-)P8Iv33BL?uYQnEoTAc7}Q%w7X2vHA2$b~pSxDq&} z(@b}X7k9fu>;v$3g)+o%zQtv@PlV$>0=iuye?*(U=&}WN!Lg30t@h*1MXa*+@qih$ z%G&?eD$AuwWeG78sVqPbHV&qc{e{YsD39!GX8&aFj}ib{X9ZjY+dU`?K$x2Da|0|X zxkLxJ_CcAnSlsO@7EgMD?}o(1-QqG56-84gpYbo~YBu3i-(97bTp$Sm~s9g zOArp56t|}3609=KX9-dS*956z#O2pdrD_{I(Mk5_lY{sGPB_6n2DUb!L&RNQn5X=B zt35SL4t9hm9F)^?``c7T$Kd-AAi55$Mwi@AmB<~hYJI^8_%aR=UW7N{L--PYgg>$4 zyAYsdH9VzhO9t8z6dd^2Z}!A0g$codCX17Nq4mMp8-ihP^=5{a)ZjC1l7PM9l_*6% zm7=+&AT{`ngcK2HWGEV){oyG?qa>UpOdTHser>V(E;F1;(s&acLnIiF$~|LV?Kyx; z#Hr(Y%PvR5InPS7t=F5OS;5qyLu;`AFV3XOFwVXMfWc1UdKF9%6=jAg;|U6CsEkSSF4F-jt@H z96Sn9MhN84!ZHyGs`j^*iK&;H6KH_1zbBB6LOmz~bpa1h@QmZgNSL0a_zB#NKx(l& z6hU`~XxPn27E}BWEE90}u;>%-a9{#jCQgWSG&%s)aKNxdcL-62fZtdqTCz*BWkR>P zW#X1O())F|rjyMP>pTYIByoy}B2E)$h_ggAagK-~Vu|xa9C3k&CoU3~aA*ggbHf9# z(}Zx2^eiEqBRxk5trD@&O+u?g93iwy#1lfR1SA)PGjw6&9OxKD3JZdA+%gv=39dBb zJS}Vz;=O?M6%zcv2^#+-J=u%N&?QwV8$e48NZ9CQ61FwsOIZAE^CDLxjCGP=>|v5l ze+C1#?A0Yi!eS&g27{v?P=*1lJiSihOq#~XqE&#^jPGaKZCIe zVQiNK;}DDV`6C!qeQnZY&V~Q5q?7!w#8mN zpp9;gy}*u;dJ}{ZT4NC!*F|Vh4lx&7*%7X_#znFn;eX)b-3%9R%8t+)n;Rl*C`T)7 z#C8M}V`1y@TRQ?`)1u)_7gh`E0UIcp-^A*G4d>044QDf*B@*j@VMn-SE^au}=!Wx_ zh<=r2^3M0sRat@$T*1WEvCoh7m(0K$|V;T~W~$t60#bqC6% zg&pCpSUi7gM-Z2hs3@Acg(2gte40taKu>%e)V;0 z%V;~^2=k23gQvVwMbaU9JGz88dZwQtOKpDJGMQksK)hTOGZpD!%o{Hn3CqK>6h*;~ z@Wdq??rZS=5JV#ddI*gp+Bq~ivzy2%M{>|OQV!%`1c~Hehb%~J90@`q zs0s=jmDBlRQtAyhG8g6x9y-(W=^Vx1lS49zzEy|^uC}ZK%LgWthzG76JB%DXBIfAf zW*j|&Zm46>O{}ExLQvEjYzR)_rH3BE4~%C#2WOM%24AUMf4!(g7)1vklw8bhVq^^v zK$&i8fB+hlC={Ne%8Hx}79$^w2sbm`R3nODx_JZGQ_7uk@DLn)G7CAhFx}KZ>-JmI zjo$0#1RCJ$?+K)%P!EbgShG*{wd#IU+<_Qj>LExj1 z;gsXVIzhM~q8W#2p^^|U3)1IG@P8pF`;+vfG?Oup6i{Z3mKcz|nP9s4BN($0#sWz& z)-b_z^G7h?z`}VXoT1!?6XaPYm~Q?EMghVolmw%e38tGrfkD-WCQU)kV3T@Hrjf-$ z(?|=+_^=k?zT2JsWW0J;DR80$I6}$((lp{Av`WBCEQj%7ZQB~?jN$O9s4&`xwR<`H zIQuyVIBxLSRIIh-o-o9f??h3&^N9?(XcMvj4LqzKlc zVVfsH!&QU^wjSyIk8UMFnNGb;GDuC5&h@@ zR6PL077Y`kEF}F`rV*r}nfkdcMc%=4CWV&S0#GktnH8xYs=4+Sa)o-pjDjWdCQPl~ z_9*9r?Cy)aN z$~V_s_)T>nL<@p~!*8m^1&1fmQ>pzp(DM-aqZfVA1xndN!cj#X$6JJ0PlfY<1GJtx z{?~dcqDfB)F%#)2Ko4dlDP;d#Pr*0UCoTVpJ%lQCT2Xn{3)dn5!jwJaFknduBRat4 z2Sp*Yhuo^CHqFDb5z1tfJ>=cz)|=+Z`)N~R2~TvAM$)9IG=LKdrnNNK5QHJ(aVxAv zXgnydA{@G1qK0nG)PVa<@s50Gy%G}KX2tYchr$)|7qF!+p=6UsTtImQX&gmaE_ zA~+{Fk;0BvC_L~w#u3hqg>!^+V-XzT+!#bNtp>noP`E6wjvsyqckB{xT~(HxT$bV| z98NA<< zXEZj?yty5vb>>ssW)A%can9iQMdl0B>CAlqP zg(9xhS)PKLMA-{YaTrtti33~gVx2&(6^XZ#V%2qm2VzgFuE@VuT_>AV*GWo#nLI=p zzLG`N1qhNo=XL%aQL3_bzAO|BzBnNvbr^NPxQ%D5-u#XZ&=Zi_H zHyMP4`GSYe+}CuDi<%h7kmwtYc%Z!?nj?%L5f8K%L?K5{i#ZzAjH9Q~4QdYXI!oh) z7*KCA2pRCwLl2?7VE!j?HrWgCmCE(k_5xuP9ehx7K^=gBq}5rT2LdR2!FeEn1|=dI zo}#LRoIE2&{tP1A%w7MI1k$YxAp@4J@U;6G{D#2 z6G%s)9u$F~4yX>uC1fXjI!kdCs7*j>(O!^1cgtwlk|_QM_JTS~akuOu-7UK;Y68&# zs9ppNTXf41WeE6p!NGUo~>g>#j2jdPuo z%DKTwg8~H(Cc^`-6uJq!MmJ%pbQ1>A1iRq$B1i0eB?_5LIqs|%_zMD?akZI^pjEu9 zkp6~*^stxrAEo~Rd*;H|`E3v&NhS%Wj5fQ3vMeFyWG29XE<{@x%b4WKKZCIsVYo_y zag<4h{}BvIe48pZ`GrNoW@Msn41CUq{p%J58AKIi{)CK(b>1VF0I67LH=$5|IlNC7 z6%sgt*0-%N8Nv!fJ)jS~{x&C*lf}vA)%G~S{sTgc~&Z3fx#@jiuvN_8GGU>J_`mfubb4_iJ5Hlu^sy~Px>|RVE z+q&EQYb620`=IszVt7xLEZu7s4etS8YIuJKkOZE>^dVx4jBPc%&l0PQ->!W44Oyt} zV|YLtJ-m;B;e9eJOvfflghq}C4ay9y-58~t?NS}SEvVrkz$RN zx_H0cvXTWWlSRY(0?wlr!~1+h4-w4&)8Rb~Yv|#9^Rzg;Z&OT9ga}a&MCd7}kW++3 z)ug#_cwY$7ilE?dcuxx+d^amX>@f#A3L<~RmA>c#rH1$CQANe!?SfcOo#z1uXgwA8 z*Lvzglb#Y{Cel-Yo(xccT>NuA1;hIk>whx5r%IhxRHETMAWRMKivdeY7|{W)$50e4 zhWA)DLNb0kyeD)hv6Lrt;Kw98N|W+U!}}gMycdQvAKs^ju?T8teV^HrV02Rwo?iy% z#=Qy;f%(~r7*F9ykD8oSusjQ~MOW$ubPeZuB|Z)o;M5xOx`b28dBJ(fDdRL=XQ>c7 z(jftSKZ^o~5x`NW?|XtR%<~m%GyywNPo1kzpNjs=6Vrx`q)tp5Hd1tAnqCyZXbG52 zoUNh(r?C4H3>BDW-iuq8Q3tL|2AyhJBLPnOIYNk_6Cs2HGv?<~ehX(u93*LtPkcQM zC!2-?$T*(*EgZ`R32@Ywd}G4OU>K<`r}zlB)D0CN6x2wy0)}=NLE?}KdkgVc0pa{R z7UPn*7RK|S_~=@A@vm#)rKVa~P8BtihZw;$HP%8v5J!yYAsneLbpWYAa;V)Sk)+fO zRY(qwRI7j-j3AL5Y;Y6ABh>^X0)E)sR?_)mQtAz6kcIhzht6^r@NF6k;;V$Al6Yx9 zY)BxCLOm!{#oM~4Zm0oNg>%O+7NkLm$_1X{77cK{EN1v+#I@O2uo{uWxnsbas`ZqE zMuESS1M+=kcEZTJU~zC;J0S_>GqXu}a@2>8uduqC@Bj|B~3EGU+U8XKf{ zK<<;1YzEEDa~+6p$3<&v2hn+LpfSuBOY9$7`NbzbICq@7ff`)4N{fTbHpS#GM2LDILIK=BZV>kf7FN^nQoOAG2*eJAe-M-* zE~^)pp`QpxKQ44aME;02ebFk58fRWbZFLQA*TpL9Di4@JtE_8(t+K8+sVpI8B9#T` z!89_3>@QT7M0sStwf!gKOiBP~oh4dU4+smVkpW9eSsg}nVHz3Aq{XuOAhCEhjWZ>j zy(TUrQBgFjXa9n(!{-R`=lLR9fNIz2Pk9x!6@LU(~p1IjZE?DI+?kF!5}R&;V!z4*`aIT%U!qitPGXFiL!8-dxm?K+gPj$Qcwz!VX9Rm1>mUD&)%m- zEOb?C9q`7k=!6=f71bu7&|b|f2H;@PnE`z2I%aoHRCMQnR*WE#RxG-kSZcTMmLV>> zn>@gsF1lNPU33{uMHfx85HW%oVk|m95Q`2yghjXd5>3wPCURm$MHdU?U<8TeVA0(c z7u{_n0)AL@F?7C|lzNk403^&8JbbHwtDW`g;4Zq}P(`QdQeojE`w@;Jh~r-1#&a)n zFL4tf8T9%uzyq&~T;Wm{@b-1+2VkfTeb0-E6dZ5tez~D<%V?HCf0_R5-=$YG&jk*k z98q5nBP-s(PMov~NCd`X1c{7CIm$#4%EH?nu^eUcfRVHuW&O1r-D#4e%XE1nMob30 z!8yOe@78KCDHj}QtC~H0gzCR zz(dEPh|Uqeb)YUtCeimQ;(?1Ku5yJDB;tXKByy0WxnhpyG~;M4x>a&K_cxar)RkQf9!6&`q{ z(NYfHy?-DWO3JT^q#PWD_P>CXj;>B$9(to+p;_JR|~sC{4HNd@(8Y2GhX8e8EG<@*$lgwd_xrBSWHZ zwn)meLCP_iL_AQ+A0S8b#TR5LAll`;M=$OC^^o;Xh|WyH|02bnQcPYgqqb6$O7fj3em*t?B;xtJmy0IVg!kd zLwS6Nj4Qy~BQf_L@_=Mo9t-|j9v?Ny;{%%ih!K+kZ!!!(5akg)gz~sPoF<1_h#@4W zKqQX^Kn_NbNDj*5W3fCwMk3&c^7xR>7n4$NG7Nx(`GQAqEmMloO{)R!qALhvRWSyEbgZ2~|Vf~#0kdNplA7-}}9fGid{HLZr3L~ea1D)MK*Ba9%C zM_A-fu(Y4ztx#O#Pk2BxUF1*yy2uNgioBR+Jz@kK6=RVDg2;OG5Ei*@6-^Fh9u<;P zA}aC{AO|BzBnOMUNL=JaNCf<_$e+{sVp8f2jz<;d3m!$)?Rbpt&Y$5fx@xzftL%-% zs4yjcKX77^zu>;)mT}9u72Hbhat~>qf|oRITu>@1c5uKTDpZ=M72YPGPXEevY2Nbm zHUUtuzQxi!z0x)zY$E=XG|%#@gn(eL_B=hm_N{YgsBJ6)B2W}4YYx&-yX}=o6kY-E zFoHzhp(qri6go&UNcOE8O{Da#Tp;1|iU1WWjD;cm$H{*NUv<3H%e60GCbz}<#_pgT*jnI8@J zo%~D{mcWUh+nXggz%P5`ss3=T3y6nC}bsmjHnfyyC~f{T=^a zcS7)q|GqaNXyET-aY!bUp9Bvclm8VS0w(_+n?rVD@=M^+oykupIPiHO{}DU}F!@(G z9C8?we~`x^$1?ff;GxOn`?u$i)0zBmc+6(Ns%|1{8DKtGMmZ&2#*I${#!PWe9GjXbhJ0|~rM;`f^$>Y9aGRYrI0gq&})To#CES^*?c*?VQyn1*-!SP5X7O$Nni%F`n zc+&geIRrgNvUq%Vc$vWB2?F3b4Lx;PiVprxlB* za15UIEFO6Vo;xv;Ba1Y4BVAYmdD4R==uCRE1l`F1mY^3I%p!NVk>M=r^mXzyMvh@o zhr^QzEFK<>PF`d2@bqai0|T>J)Zy4xaXv|{t{03Xtx&BFt8$ekGI$mZeM zD5NXCc(SRZTgU)54-YOOkFt4qPzZSv1JAN~cz^*Jk1vUA>U;$H zpG|G}OFqF!&)B5BAz6m>y+ZolB7Gl_zAtRj(~$hZrZyfVxdcRRPf+_JlJW!(cLgN> zBdG25NEL$G`iC5Vk%kcDpgH6y0w8J-08x_wh|>sws7sL3=a6#=>T7+{03)v;sLcdO zGlGYo(vwyM4?kTe?J;m0L45*FIug|9bEGSJdJ^RQ38Wu_KaAjyBKQadA4QPW6UZ2X zTHH@2VB{+V_3Z(fPVjK$J(*4LaHTt$kAY7JYQ;ENN>I!9$XDq3mLM7Gv$yB~qIM z5NC1#;#>|u)JKR*IpiuOautWNwUKKuvK5Ci1(Nn09vZ^Pog5xobI83I=*pptO{6!6 zho%srn8x4(2>?}6ndpib$yTH!Y!URV2Ola_Ar&_PKv$eLgG&5ZQ zNi5cbO@=88iL}j3&1{YA%n%t!#If6ANFl}n`!$`%T6mg0KK`N3^J-2KFD2dBMV@rFgt0CjM-5huw0HW zZM#+M1vm+ejn8D}MmRnv4m~F#pA$*XiLB?uqvu4`bD{w}ONbLC#HA9VpoFL? zAsR~v&r;$9Yyb9b{Sk}_-^wduXd)dIx-)e8kf z2uK3B)?Uruo4bF@rxpxfP7O|D;3(<};w zZ1Z=fd5l@-alGq!X9c@>`n9(Yy)CgO9_pxQL=9i5zV7MB_nlo1b9&~#8FZ?AX!p(< zFRd@1-_-u+Ea$!lp2==!sRmpy8RPGFW9@+(!;>G_btpHeFI@tsnNor)%`$we34cME)F|p?f35J+wamjgG+T zzukSUzVGG4P2X<4XN=i2=Kbc9>{mX;+wol4jl_9!n6OPu_w`>P9g zq~9F+>^JA#)5qjF*7Dxd>;wT(qlS+!>nup>ImhUnj=$;Jhne?2^WqQK%g3ap##_yM zl~s}K=-@gg=&W)4`~`h41*n(Zx?aAk&LQTRmFmOxYuA+atsdn#Zw13*zT+CB%+v=~ zON#CmmIwT(zILKoarTF#8~Sc0s~UUj&DJ^|llWQf$G4@Yryezbrd+Q*e>AiHM+Z*W zu*1f=XBOHI+?+ox{`5wzhewXBmZ`dwQ+%)MnUe?CcupT$+WlF&V?@T#6uE|Fb7mGN z{JgZgc46P%liy?o%)WDEa?#qJww*I9w&mRPk)OQB=*MVf)s!Bb4Jw)XH98>!Gj4ih z#4R4aXp!>M|I9NOhLxJ}!ylVGQtoUar76i%-_OXNN7aw%q#dG5?j>e}5iUnk!!c;3$Qtj8nQ(UZNsHp-T+cz>DqG*`1{ zzdXO2XMS?Ves}j7R_4zydegAGpZbCFxAS@0o#ndsDcl%6!Swa!0&~5tejBb|j9RF( zNwa8>^5Onu^wi++CC7cfyo@Uu+4EGFui*8@XR$$g<_}L;LsG@M+e) za+A!*n-jO(t}icD9Pp0kvMAjAc-EQw^Y^d2$+xyr;V<|9@1cv!JNLaBqdjwMHdp9t z81?gL2&lCDG4c9`qKYfGX51Yya{IB)$G7#lQ8sSE<|L-Gv)Y%wdEKRM)?U*lm2Yi- zdt6{pJ38dine)%zDc!TR@J+hB>wZY&vWJ@mLH)9$=O5VPtP-mg`(df=y}wsg0^GVEi9h0^#0T2cW3e9Q4N0ZCO^)r%+jp?u8_bT~Io#7t; z<&BoChpSHL?yY&JHLGOVS*f*s6Lc(=nZ|e57_uUE@u&Io6HSKYIzQaiu*=n^kAh=r z=-PO*q8{c``nOwV+jm*q%;}v?qhvo%uBlVV>$l=z#yvfL*Dq-UqKx?|DVnJ$_lTGt!2H)iv}#P^ z!-PqBQqsrOzSqpUVBX=qhSI?H-!*O(KB@ScG-BGc@Qym8!+SV!ecKRqIgWeePp*P>Z z_!>CvSm2B=r@ia0xcaKsuf8$GjND%~!NvY9y(J++dC zn%J1m@tRyWDq7d2W4XmfGer$g(@L+0i)Z)j{(SvBh0cP!k2iN8+&^rVOtI`^&F|;t z9@ieAYw+`c(y1avUk#0QWKW-S3(K~S&|QB*>FnK?L-{exA)51M)NInfxYm9goGmq^ zB#K=uC^WMWc>eTLeVR6pnOzWCs+K-mHK$?BHnUj?Q60ChPOT}a&0vhHldrMW%dwhk zI6^(_{;n8vEv*-W-VCoT7`E|7h_lz-;aN%^A&DNf%S~0n3Fpo~k}DiDHq}-iBfB|m z+TA6~v-`v-t-jru#uBl@?q>}L=;i~Y!L-(dZ>c3!b| zX{K+geVIRxBtn6GwZ(X zo)AB>TyRc0d|5=d&Wm3Mo>{0>wQ<*(>WQY=x)xLS^b3(E5^rSM43s&}{d8jVx4Yx| z43n3>UH-0Oh~`MAL%o7ET;yyPUS2!@dmq`w*I zA7cf7H9WaxDr<`No25EWy^NB2?T~+&m!z>x=l+ky6O$KZDx7?!_O4IW>b+SXUmR+z z%Nzdq3)A#Q2>CYUSn-&+u=%qahr8}8w2WD9aXhul5*;;fhG+e#Sq}!!w`A&W{$B2| z@a^lY+&i|bPxaMxI^DR=#8IZ*mdSTcOfRxL{BD4Tx;nd~LvFnJn#bD1^QE4Dj+i>o zU|9!QjQ~%r(KA%t%5@fB2$~-A^zd50S>twk_Gw?a_4dKa%3eLb|A>75q9}pW?P5rc zSJLO0TV1+bKRMetSLMO<$dtVqK98-JjXM|;UN$>!$K|eSFFTa@r)oPT&i+(sKPK#X z&*Q_T-t|$un^jTxpT+3KcLLnC&;Qr=!p&7{uF6S$9QkH&#l&I@&xhORjMAApb%Li{ zyXyk0+&9zn&)jUR`#F3}MfAjI?u-?2r2Drm(&4Wj_L57y@_ene^8N|;W!ROy2BqYz z_X-JITQN`e&V4EMQaUXd(rbC*w_v{fjoPAulSK~HsJUUXfE0?9fj2M*L z#jww^0SBL_dGp*m4V>Vn|B&SVoT|B9{=(Q{TU=j$m2o(6c(}pGsO^gT#bBi!W#GduzUFWDZvCXTFhpm_SYUc%6509Lmj2nk zg0Up8%boLg%d5^FOinsyk+XK3mwCB&@yA(?CzQTf8n-_fQk9z*b@J8M^y&*z1&Rls zF0P5rU$H67**Dz(j%lCQYm5g^R#EM2v0d7E+I;T>&-%@b0i%sa-|e_iCP*=E*OZ0J z`Wc@c-^ZZ#%(SBlFP8RjQ3wt&={57~tC#zB@wLa~D$TWXKiieaI#R}#+Z4XoH?eoj zjs?z-wV$5OkG1w)w0~!>pPOzyYgb|8^iZ~J-%R($-MgeG&y4ceQnsvYY$&sZr-2Q*C$1K4-}s^Iek)hDr??aOb}>wH|IejCU9*tLBVYr90W6I_mTHK%3|H*KziPjolJ1-mM_aY^I{^-%M)5C2Xdi0JN8+Idv&`G@#@v+_W zH)lHe`h3*w*~ez=kGHWi>@Cz^$Gp5*yXox+&oTS%<*4=@H%Kw?v)@e9RF%7$E03(& zHP;}$W7W)?PL8S<5{K0o>dafSUwKhlgl+0!UsLO2Q$x=ibPgZe$8cl+e&%C$4vBl+ zt*88Br61FWF53CHG+cX{`J>ryKK~pa-ashDT+3+B_uSLG9EQOuDa{+3=hZ$* zy?f{LfU-|-r})H=c2Rw-u9xYivqODWapu{B{cGokafd$YF=iW6^M<)=r*Z|8bD^<1 z9W-YJK0AG2(}eHC-Hx|^?Km~f=lYk!$5pmzdN_ZQT5n*%PyV*>Rp^JZBF~udOLyJs zzBTbvpPh25V|$+LR`lZ2o}mZS%^GY3HT5-OQy*Ipz6>jJSejQ9-YtI(1RL+;CVb zeRfn5~)#qq`tIjW$^2+pZ%8%I4P5O@ulU* zf!>c+Cd$Xg`gY%7&F;S8#ogYD%iNzUd~+*3)6->eK;Acb{i2aW9xr0+yPUmxqJGQ7 zA3J{VR_(c&+u1rvz5d3!z9kAX)oT3M5xIU&pQ2-3tD}kbKFYVw|n0&)0wkQ)-7>wY~P_A|BSU!oC9UAH{WI5N}d(C z+t(yudfz;=v?D7sL%CgM4%}LP{M5l=YG2BJzA9;d~V$T?F$<3#)%`=%#E~m-TP5_LErWcvs7%NUrPHw z_FHJNd-}@Uv2S;)#gWECX4DltooaG$Qmt$6s?#~ee(^)Ys(RjD<8rjyz+q!G$D2JK zcSb{H=d=mWQUqZ#`zJ5I(|+CJ9fQwWTnes^&{OXGm_Ie_{=NF;Z@y`5oH9LANuyKr z^@n=0v!+h2R`&>3J9@rT$ey%;%Q6-8H(dDsO*_4hU|gEx;HCFAbsXegrylK77JJp| zSf0ZEBSSvMZgG3RRW_<*?PniSv0tFw&C)Z6_Wb93q;RE&R<9p(wRAi@9&j|h9&MxusPqWWoB!X|f?IvMWL7(ejym2+%Kg}Q_wD};R5!YQ`);q1`iWaQDw!(I-O=-8 ziS?et!yb$%TJ=C--_8%Rrc?WzbUW$x;zEB`s^21uk47hkI-TP>tupC7a)yXtkp}1y2Y>`RanY0tbE>z7f=U#W3 zH8S8x;^lUi7kYmg@qv6B6}EiF#c5&pGUu&yV@!>F8M(r6(7xL`pM7@@i@!Q()kEji zv2!xZ=V_Lv`6=z%{>atosG`O8l~+4_E_oUK)Xa2jyKci?ba*a3s9VsWWu{ZjJDt_t zoyDwmX!Q2k?Qgj??uc5=OX;h6#9uj8EhE=Ze#K*9L`Gmo#g&y~cFYVi2zWI+a&eD42Y2s#I$XC( zFmwFMe#Iu|*14>_RXRc4DPwPrvFo@A*VBHc>(&hTsa=0Wg3R5olJZ;kQHRom=i@spFV_Lf>HST>EUf&p7QFYd3 zi1Eb%J;&{ceipI%-Ks6`U)opR{j||}@Y}GCOOi)!`!VpCXQxV=@^f{OHixZO7a^-USzo8}}h@W4)$l2f-%oPV+UVF^>RRs>t*>BW5 z?%Y`K_8OI{e<2X=i$_ek8NR zYPn_CTV3QHcz=(x(>mm1nJJSV;+8i`Ep$!iqH5ly1!T6*fL-qmPwp)>)RE0!<-B*0 z!S<3FktZ}yj{dY@fmA zd05)&kdlw}$=eR(*p!8OZ%_+OxfgM2-`JHJ;f|rBK235vb-gl~GxS+I=B-Q{TOXZt zqGz)1`siiL8jsk@-yL^!%B^8NE=`Hei$3XKFu|m_KsIUF$Y8}G?UuKfZ+|^c)~a&4 z-PGGoCJ%?CM6!w#D^GtO-^2V{;D5)6aIj>+&@3{?U$8%9Yi(ue9iIlF?&mKiMw>D+Z;QdP4?C+KKiam>PHwvXR8~ZX1Ki$oM(`CQlMWW&Q7!-U zbIq4c@dK~vw_9)M^x*!5#XYj-x;6&OKH4w$%(tp!+_mb{OXJpjRe#XyR;1suo)=DS zohmm>qsLUA_<W`&~^2t#u_Ody@{Xm#~&IP_T#JJhW^fXA9bIT zymsA;ME_maLbm2--bt9c+UMS;Pq!AF@nKHo>h~U$7qoxo7Pkc?QSHLk`x^gT6tk6tmh^NaOQ=l4Iq!seyY^xTQlBl(49&MO>lpVIlPf1-%HXv3yM z^ZcikxK5auU_QYx(7D`i$)*^;+#}a3vkMyYly)^5oaih4W1;c!5$pZN2I<|dn0=Ye z=unf&i_$8-VRh{DwNoqgdkveAetvPk_1ydMe!d=uYu^pXdOLE4P0V8L-fd4Me6*73DRoL-0iQnLNE56+EjbcwdVUVHM> zClk#b-f}ODC$JBuk64->xhlytvS0eu{=<5PI+@NZznK4F^xYX1SNo+sjV;_(Gwnr? zgUyh!PdlFZ5oABh?7_w1=8NVOm|Iu|4bpWd#Q<^$>fI#kU))P3H^t}oSYv5&sJ7ijmSm+_a= z?vFN?eW`iAb?6P(m4WJkn%_E^aAegF9!qqd-}j;Sf8X5AT{82+0;6^7^Jnc2UD)%K z^UBE`i+A;M2pV7<#;MIW?VU38$iDmgRQuW;8lmSq_DNU!ii3SCJJ&ul(!YINecP)c z-TUNk&rKfRe%nQ*@-G+c84K_Da~dur+-x^BVT;b_0d`m23I=O@4(nhpcwP|_5^Q_$ z%IU(_u$D0T=Z?+;2F&g9z~F1YO%WDz4Rb5)`HRMkINmKrQCBz1-B#;-k<`$j65G)~ z1Mdutc+WQ&rg?nv!^=ej7xeYfEp1Q|#7?mj$jOy4|X(-^GiBd&okb# zYWCwpLr%DbgcIpzJx=WM`A{9UNq(7%#?6KaCqvS{@9#aclc8&A$f#o@K6#`n^riBka?VtnwNDi6Ojb|qpEYLj{@krEV^qHSbn7~lNbR@i;Y3CI;?lm; zK5yT!dif^v@$IQ5bd*;Z%X~Rz^@`MNd)EbeMNW5j_e_}{7r3KejaFxy z)AJV$|LC1HW9UY!io@J-hb~zj=&zSqQJMDW+PERzpJ$Ap71*Vl9*41W>WEF_ zynXH6J4`y`8=9}0@Mvh7Qm?m{XT7)VpEJRNy~dzEjOF-Z$X*-&HRttrPnl=dch{xr zXA24=_#uVFr+!lF8fE=7My|Z~!RKn~+=sy-y7MR2m_ACBf7A7_SI5#sqr9&s@AISU zHjkO^m9y?b#vS+cK6+ofhMAt)q~UWsN2@OJ(9vy{x;NBxwws@=@#F32sN7-r4mUr0 zgTaIEMHrlqy}`+Q{XA}7>bPj5Q9H(acfB~gsK=dZ7X|B($k6uHo-3?$=jio6675`A z`blTry~R`FKCL^X_l|A<^rO}H_p-f?1g<--?QzE^z1FU&U;L>pI`ww$neLYF}!7G<)FtXZy$apEi9tEq2uLZ8p;eoWA&@wq)b} zy>ffvHKy;c>3`-NckwlLmv^R3%L!Yvv{#-r56^AyrRh6TiFG9R$Bzj|cO}TIIh`Z7 zd8G0ct#H*>yH^EQHrP+7F;w zc;&ubVX?$Qd)1|c4vQYzuD0Kuu)kJyv*3B;wi)_?lQpiK%E+D~n5U<=N{_S8+Qw$j zlO^&Fxl?r*s*ab}pXfVUZN`(V8%9=p>NiIH>|P$Ia)J}+-Q$p6UVS>B?Y_O{zY|L? zoYj`q@JX)TUKMX2F?Z<-xvM>v>xK7s=;WenGtMU`IXNM0{g$&v2J!{|6Z-DFcv@>@ z=>s>b7h7gVjJm9JCZJF;h(!v%lQFhq(-?a0wigTYIkV_%6?pAfqlHx~ok)HE? z#`jr!_uuWQ+p*z6X7`)Q({oql8}+=ds+v<3mg*XLFgk9Q-mp{B`vSW7IIE2}8M~Bw zc+Z3rQ_4L0tkyoiKeKp?+@8<@`}NsJ1nV8RuP$8hcD7zN`L#<%RI2fU(~R7ZNi$AO z4m#EMlpykZb=p|FHM>IE)i!?Nmm3;>&mFTTYs9R}dOyEk8mZf5^=$tiN>hIBvq{u_ z<0^3PqkK~>;yxDy3NoS7y)8I(M^=U({X4MpqDQVa@L1Ej6 z-NhzP2X$DXqqO0Qab4Z=+}*ZiF+Ry59k-;dNl;zs+^+1AbI(sZGp4D{@Ah5c>Z--I zx%aw^f0DlH+1Axj_Ekm?6hE-N7cc+Z^T+)eJf+J^Up-W^-L_~_-1fQ0mYFW;wquXF zlzZcNxt{gwtcKclXKz@`b2ivDU`}D4YmwOz#Xa@$YQ-;uKRNTVHPiw&wv6)MJxcz?obl4E8^}gpl^_5?Hcstx)+wJt(ukDBEj+Z*KQltLJ_T#-~ ze;EAW*fiH*nPGc_s{HbTGOT+!ZW?h;bN=8(DP7Y`X8Fj!c2Vx9zwoBvjHTx+vqFrH z4;l30)y(jRih1W$8?}oLSWLI*y?yYEb;BD}5}1{)BRkHij~|}ue$Cr^LHltLbcVpGj;pMUhm3~hL zb=&EC?O>n1YcA^aHhSyhHZyjFLj9-*chs+$t=0Lmq7!j(&g|v&WEZ0`IpddV&)e;n zc(dRxSy`;z_q)S}q28Wd{6n6`sI1e<98+}WrqjU2-s`M~Y&c|KH}DZxJ?4_MOsDEw z*1bRW9h<*OPqTB;Vi%u?x{03_k2$$`*rE@t12635Lj%v{&vcYiJGyGeGb62!VQZbL zuRDK~ADddg#>X|_>eu7GiRbNaF7NK(T<@wD?Kd#{O0{#+ z!2qA{vo9oPo^N7p(5ecKz<6OowSNo0m^89Gt+kuaWhQ<_AbLpW4 zMs8z=x-HySP@4X9lBIqRhj&8*4~D$aWPPi$37p+=oXU}5Z=@z$rOhAQzl-IOfH5Y~ z>pYC*V_yiY^BPC*j`myYwzEgWL0-SAw2XIh`q8h=Mg*;U>S9xuqg!rr?CX?s#RKAZ z4&E2~Rj0#3MvV3O-QzCbOd2LV;CME zdZq9D&TC2iANI}zE~=|r`~QW49W1B_C^lf28B9!!X{J}-L=$`Ly#;$O*gF>Ny#V%x z1sjSYh+V;kUBRx{uoo=f-iKi@n&f@I``+Apzx!qR^EuC2d+l|~%$!+!v(BEkra6_p zbYpgz;9~Qh1Qd!M>DcGy!OxbC$X4MW-?i@L5)rlKK*O&->EAwl-^<(|Ub!%R<-lFh zgRVPIZSbM>+J)eaAN&$MzvQ9g`|JA+EO@zK_Qq`3nO_?d!HB|KNt*TKFG0mNe|@v(Q;( zE>F02Fu6vjJLjubmwC;4I9&A_k>s`T@o3L{E$21t_|Cgeh81mgFJ?-IM%Fq9?pE`4 z8yvfG&GBQk>+R`i-Y|UUJJ|}ZX>cg<;Iv=PuWIR~Q7zbT(1Z<(we5+C_YINffH!_`5VWjuegf8z>xWig&j{x>50-8KCR zl>LjY3=M8+MjlN{->>(Z>yL8 zqMt~a|HvCN%YUq!<3I0~?Vr13o~6NZ{9pHYEx>=jdi!5|wf_5$^!JV+_5bOk|GhK% z@3P(b`%3;bm;T=07xtA4`{3`Z@ygZsoBn+T{=Nc#UxB~=3Ov&H-NQwGO5f8I$14Bn zyBz9R_ur4X)3M2aEJ(DIdie9Nm1Yk1WhDOE9sS3m?~?z>oYry~k+C~tZ7mJTkjc{@ z9<%B87Tdt>Rp*ScT)IsMwFk+FXfx^tqtze=)t$A~?wPLJEE$n9yzId<{k7?zh;0qh z^qm+z)jl)&WbDb%ZO38b87{AG4R_;UGpxT8z}8=%ilXVeO2^-H%52nLuQ=F_R6D;y zZOZF@uj{|Nzl{AFA$82x_x(zg-?YAJ|Gx^7?riKRb6>v~?RT%}tGh}+o<9rnry*WF z*ME8cuQ;an|II65KP%%ff1_o1zv=&*Q&P&SFZgfUey8PkOt#O)D_!4o`ps!*&kV!s z+gF-0X=c1kri1*kWQ2Xwc9i?@;{@&ROZz{q*AxlB`mw9|8VY!w3z@qM#Yopt~rzq*E4YSLNQ^Rvbyz@TsU3<|0tAPs2qGX&OF~PViW-p;m*=uO8w|QED4ee=$3! zp{8`TwcgTfnskHjM6C~*U3x$z6kOEsTtitgmJw7PUTBs?FBm1g)xsPEf{%t@M8Pc0 z)@#_SLFl8ese)>vV2);wG&s{2z7YjQ=m+m<_*Fv>QLsg`;~MU2Fwq}+ih`UB(0fx* zR}@5RR)m32UPBuVyEV9@ve92P4ArnngCSRRnp%#*Fj~VB4auV57a5{{)JwUuSQL1x z_Za;(%+zp56nw{U)VoSSZw*nRAVhtL(q*4cW!(tU;T8O(p^b(x4KGE(I7Y$+4KFpk zC!^G>ih_e0%<7Q%R>Lq+P(a4mBL5HG)R17?(K$0#y-=c{qGoMn9E?$COp;~~G!$Yy z^brNKH8{%zcnbxF9M`HL`D7xzg91a|mq|9(!Op_e4JTcu$z&V5k76G&MZIpKz>oy3 zUePe0sW#hurrFqZnXV6GhJGh1=&oU-hTJk!pMrwf8lu&kK&i9z87WB8%n&!34Iipo zW4dhBsv%G8%%a}(>2g~X8>rqf=@M&aSqQb+zO%EDc9vjg1=L$9U201P+iPdu%+>c7 z1$Q(Ua+G;C)Mvx{;wiw>OlR)i#$_>iE;eDiIK@?w;wAU}r9@vDvCg2HS3D zUTUYjui?4|Lt@o;V!BjT_q}vEEg8(24K~{$$zc9Os;?{!gG7NLJGGjmVFDX%wh^*P zz4bKYB1+wnL_re`b2OaRP((IEI}O1o_(Zno3#K4kGf{6`JT$zgp|XZn8U|{ZDGD}g z79d;I%^U@%HM~WP?Fic2*$O+mZD(&wEGoxP@KUqlY=e%XV3>wQT6HE48f!2l)XvV? zSqZk=TAPSsgS1*!cA!!d1#>lv)NoR(UpVYk>#&Q0_hgs4!E2bU;kJg)Wj6$BSgzrU zhV1N7S&Jw*rkP3h+V<91vw`YcDqV8OJ{$Ye&bp{?)^zzm_UjwB0z*m>Z(}X&OqC1T zY`5&}9TIG|Zg#fO&R*Er*K)w-x6aP;sxJlg#i!u3216n^WMiLk*v9rt2776@ZIdIm z)?zAIqmG6yqQH=CT0Ny9n4>mZOLckDrK}u>mKru_xT?WjPN+4bHT2a`SWc?DyoLc9 z!qjWS&vHt=`YJ53ni-O&nWsAbbeSs|?6jRZbH>(sNEGX+GQf0MWoLKoti1Y!q)RV5 z+hS*G#Z+7Cw{|v4GHfsG>=(}Igj7Lk&f9vV+1W7lGN(&HxoBhGsXQoMa>*qdYoQWl zb><49?6zE7hEf`iX)t7k`u0heo^n+unhJd6n$0%d&K}!YHA%6xF0r!`>W0IIqQH>Z znni0{Te+dXloTXs_CP}+ZtAaD1%|BC?3lJ0(m-z6*c3b4O@?i>+*YeSlWKFRZfBG1 z?1Y^aRo^t}(%8-xN`|e7+_klKR#_Y)HGIZBo2?M{Z7j^r-j)Y8TN5&vk36*52B6qx z4ae*@50y-+q)ovU4Tfx%$8cXmcX?v7-LkV*^3-O#WM{P{&1Q?&?6yjynI+G38mhoW zp6i>hf^StStZpp|47sdXHuc4rE@LEv?XPR(IQ3F_&^eDKd!GV&fLsamdhMzRF76n0? zeITXuB~h?g!wC(>TP3f$C5xYiuQb#X1${KLh&S@18kDJbtbzj?u4!;kgF$tA3f|LD zSwl-vFkG|p;)|M`P_QfePsSc>Ff>P%SJnSk-aUKW|LXmR=V|g+?s7$rR)1yq|D4$M z96P@n=qsl#ud4s!ct?kRf6+0;W*PJsMP8U?#9tKo@38;Nu7K4!m+$lcvmLtR&6pPX-+bcn zxz*gr|6tjZTg{F9FOc_hW=xCx4>_5qIn~_A-}29{fK%>_X_0^C`FFc<1#&uNOpE+G z7bMk5&5iu40p7||^$ph!x~#&GI}RDlP_sDHur(N)*lfR1Uu}Amzb*fC*1*}Z-kbe? zYl(4a@T#GQW5ZX~*LX|$r?Un>IW&E>(;|mvud05I&0ket}55Cj26^5i{&0rZZ-q^b7iV8!f*x5Ea z%cCnQ44GY{tf07gJ=)2D^GO%WoPCmqIeY<{D{d-dP7`c7K(1({&WDNf}*7 zVaT+s8SFKeOm&nDvngNbItoMDJ7h4MA!C!*At;0DZQZQDQ8SxvtNGP*S?(|@)2#kz zn`QK?>i-jbhrPDKINT3(ZG|CybTNe?w{?Mqqb{Z}WVD?Xvlmm?nld&ebZy1&$!MAM zhB?Jy@*B2US*N^V`#r-8r|G|Ee$^JPYby-tW3Q;lY&Y3UC^BsZDQDMkSJ2TW(y2`?kNIQ$Mvr4+Q!VphgOkv0vT~RU5uG*|>)7)N6k!dqnHG6Hv zYYlzu6%|A5Y_y$CwO3i3cU<#Y&wr*qvDa2)dX{pC%v5YFB+Hw&*PPOvHoazfL+z_; zD-5ZmD=G|0b;@8i!<(CBy0*fQ-m=xkj7P))Jd zR%E)kIwWQ)Ha0Hno3=NcG7Jl{9nYYDx*ex$D-3C5uc*lEkjq{|k!ds7lRs*B-(E-Y znVo%SXFu6lEjw#yXD#ily`3E-*|uvB$8)b8#6MHtk&AD*)N{D>hV4YwH*Ie?{l;)h z7g!kb(9T}inG+e67tZ#23&Xjjy&>FQWzk0$Qy6kv7g#vTO`Dpz+3`CzqjinFwj$Hn zU@5A+AYJa-*;6}nu-8`Pw6pwncEes}QQlD%Q~X~^C3|f}X1DGR8MPIew)rA2s;c>nO_DS$RAA)Xu)Ov&wd6(j^o|_)d-)?6v*= zp*q4|TaoD!;gC^Vk!gE7YesEFrtJ^e_fD#C;tyNX8+1j5!4mAOdKOhe@mjY{y0*fw z1?k#~%+_M|Itm{DUZH3{yK~!0V z!OXgj;&V}8sHYq=n4!J~J#}q`Vf$X!Rv2u5)(rNVv!S-pwG{^YSl3nHqik9f^VC5+ zZT&n|C?^%uRsDC+t*)xo!=UM?!x{}Xt8M@3CKbx&CHXUUstv}m>f`@2aquqep@MoC z;F2p(J`V%jTyit09jYGNBQ(8dK7k3mw^nRTz69YPFW8KagmF(!u^e(t` zWqenye$b5z-5A*&zaCUEW+4moq(@KP^iD608+&W45J=BJLXA1da|XWKhhBY{Ys@>A z?#uYT+U#bUqlg?u;wT-V-e_V*^YIwX|5BMB%(YetAv}Z~A>0ZfdnoUO@?$97LKz#%#!!xg z@*)(sFun{UFpM=BGh)7TsWKPGc{)gnf!*e7o-XAV=xq*TlIyF5^fQRETwO^1MeJCl zTW2rUICTl<1RDIO2qr|ZDT2chq(x9*4HeeVZ4KcWb5JGL^21tQuGJln zuG83Ly~cDYxj}Cq82DBs0U7g4yCb<5$-<4gHGC6iHsKOQr6_`;*cnCE&D7ego8}tW zX$yz8;24cpG#^G&HJUcj42{+f2Mr9_%K5Fl8$+EKI>#_QhKLwW#&9nNcVkYdxq;=j z=`Kp5w&5B_^EgJuF+Yxdaa@Wc_jbIu^W%2yFvY+YJ2Y2vYX_TlQfwF1cQIlYCw5`p zP0QU(-OV9mPRG-j&$+&bihI+0FxepHeKu8Xh8w)@ey;4tB_7{+s>Blz&!l)(#B(B^ zd+`)a;Qa&|C(t{A`3XcPa4mr>2k<{Y%LB|gV2hUjAQcXhdQhu74{5A+SYx^rIHI?g z4J@8Wy+oURdm^_JnR`^Ly^m?Ed7RBtA}}c@q7SSe(SRByJ{=Et#^({E$r7 zWL6||C7E=obB@91_~5+OTrOywVW4K}hI~KYfWQ8K2PPBRQjhfJ(ajr&Zd(64khpK;~iSuVeB3D+`-|lt#8-6%(+Xo zds;Q$*SO9=&D7I(4>VSMsBzFkq79;W(MNpuh_pxAe*Q7Vp0N4}C!Sz^O0}mfe#(KT z6iwsnG{&W|Ax*nwd8YA@fr`|5PW*FiQR4AJ;|c>cQ&;b$#^je&Kt0SYfx5t6&D+Wq z{ZzcF9hYxJ+KVg}IVb6Z7pgl*Uk7<7i&k@F)i}vO9Z21L9JR&dq_K&U%r=PP&z!_3 zo1Dz1?J?Pf98xxi1m%!JImA7uG|8#$%MA?7B`0%fRf%tIO*R>57$}lQTW;i$>dq4A zEEAn2%2|#&i+W_k-9^53kp?a@+(p7%WS@&T<&{tK+Cr_$E2r{Ga6YZJ$glCPf$3pa z7tod=t{S6VCCwm;H!CP(3d)y-wB5b1#s`JP>?ZZyq??-ryU8LqiE)#YZo0|4h{pRx zq`bQ{b(cVQndGi5$p)_QkUJhy-c#y(N;glLO}RONJ48dalnHO^JzVKv^Z&a&z_)?j)KR@dNQ4YJfEsV2*7F-|=h zQJb7~h^&KGT|TNyo4Q=COG;gC*X2Q7Ueu*XJqFg}L_K`#)3rVY8_>G}+ZvFsA*~uR zs3B_`Qn3-u8gsfaHJi|}33Hp^+Z0Pv-fl|yrhL|v>P^|+l*Y|iqTbNWDbk#B&1un` zPAxFCB)KKETG6Q$^IGvvYd&brC$0IaH5FS^wKXkUliHdNzfvNA4+E$YKSL=*X^)BzNRtN8ani{Z3Tr%!tkecVIMR<>{V3I+F8y&FK*<5r8o;Ij z6dcGq18F&s?E@(^h!%qwIEeLwI6a69gLr!|BL=fzFsBAnZ3u4-W!_Lq3?pzDQ-`sC z7+(#i!Em|_XZ>(yjv!_PyGGy|#M?pq5JamWW(Dyyh*2XsJCd}KygiClqu4hJpV53V znt`Kn9>er8%o)S{F)SU!sxhn|L(~{z$FOS*@nbkVh7)5*8pEYAq>LeT3=hZfYzz*; zWD6!wFa?4s5{y?crGqgC^L8-r1@mz*Uj*}QFh2%UHJC%ev3xz2R^u2kj+5g^ z9Y?+5oaCica6UjXh|A}}{;+;t}n?%4QrcGkjB!*39;$&`3=I&%Z zm_qL=VeAOQb1uc_^1)ng%q4Cf2j}tgeCp5V?0l}zr^o_|F5t)l&Mn~M zg?zS<-U}JOkTVN8w~!|bS-yxKiy5+*rc3Csge6PJxs*~%sk4;%OG#Ra$1*A`BV`%6 zmQ!yzG0Q0$&e!3L3ui+(`Bw133Tm$)+e%C;>A8~Nm8@Jz;Z;;z#m}qgxQgqmc)SYp zYRayr;cA+$#ytYx2u4RRKZ5-cT#6vi8obv~c@0z7uyqZE*5baFch+)QJ)ORe&FiSJ zo{H<)vz}w?aoj+T4Q$=O{tfs>Vu_?>Bz+^<5=m?%CnFiNk)E3vx`|Dj$QDKMDC$Qs zJ&I#dxNfHPW`Z{J!4_(7VTpP)aSMf_c{`eaMAIyqKG95xW=D8G+S_7Sj;_WSVJ&%66Mx1T5bDG|?y@idL6Pdp3biHYZWJdO#x zl|aP=IwvqXf%OR-Odu_Rf(Q8Q03!~t>HygelItL)4sz@up@#@Rg#TeaI?SfS>^jWD z!#q9Asv~SUf?FbJaY<}SA~A`VNfb%ut7PgYGc1{d$vjEsr*l+0N5DC}&U5WN z56{!}0s}9QN zEWJv}YqY<{;Ytccuk+q@I$dYlbv9n7)eT16;N%TbZ;#lczL$%EqUhdrFx!YNQdC#_lvy z(wO>;$Y!?%NzEedvr1rAd7f2rI?4x* zQo&K~sWj3_>NrUQCz>#nM<5=%kbPXDYxv*E%CYKnMx+}$of1Imq#i)OABWi<17oD zCEi)CI!k^RvARf27wO<4(_LhZi=1^4Q(pNwuPn$bOY%x=Ug?%kKF=?e^2@&baw5Of zDIhHi$fN=?t$_UOD)n7uy{l|;l}E1PTu^Ekl==mwYeDfVB=-x66qc=pWq)CDaFgn8 z(#}nWxk-qdM7qf#H@WU6xr@lgB66yTSly+LyL54v(eARqU3R)lR}Y!&Ay+)4jHi6( zDeXLEn5Tq$%1%$Y&=0e=n)-C2hTAqL(c9k|SR7 zz)R*9m$>3mu!LAj$d4r?qJ&&3Aumcu;gV9er2J4)nw69xCFR{xQoWSSFC~ekm&d0ktRMeNO51O>ML`7Ws$Fh z`^p+$+2|`Xl4z3CCb?je6qDRB$zzkeG>Ma+nEH2 zWV@g2@smS-a?($d{N#$C-1d|Ee)7~$9L$ogu|%yQE#cg^zDEDjdQX%QET6t;+$MSLw{wMaROd}xs`EK<=TRV-4|A`L9k z)FJ^E>1>hS78zub;T9QVkqH)=YLQtM3A4x|i>$QBT8nJ9$aahDw@9KzPFf_{B9|6S!JYECRk;vRc2ddu2mLUWw}*WTV;b)wpwMoRrXsY(JE)Ga>*(wR!OzW z1FJl>%1f(c^_QIflHXqn`-_*q`1;FR{!-3gD)`IS{_>;0RPmSE{?gcATKh{of9d8g zz5Qj7zl`*k3H~zGUqbw4zP~K@m$m+~*F}X+6%?!&;v;^|jla2JC7;p@y0dYsmSA^l8Mf#^i3IEnSsnwZLote;?*v<^@!jmopcGdQh-PqrauHEtOK_z3F{do_X7}M;Yy|lx;-Wq)Z z=^DtaK+X3WShNq_`Y@-DwmA1Cu&*ZX^`lKcru1V=Kds*Fhp9h9`fKhpfGGor9-w*o zfwURO?t!=u((2GbY#v1NAaW0;++b~4GMLAM=|4pCBSSSRnK_IH!}xBv=Dmk=W;kIZ z*gk?=BXA3%oH5PbCWx>g%p(~$QoFqzNsUpg9mT;>TK#r3OGo2vOta4&!{RZl7{gja z-8zOHW7uc#V`Dfoh6@J2HHQ0Rc&d1?j*u&ue8ChBrl_Hsf+=H=4}m|(AH;Fxi`yOKiVHEuTWtqJU!z@rJ|oT!cOOvHB*H7C(}l2&I-B5V>PCbMxe zsgt=snUAJu`>rV@OySBD=1*nPH0DoZ`i}zeUnaiEI?3l;Vc~qTGlldgi*R384D7k>63&^&RPZsjULi!lf z>`4o`ypR_QS-pr}iwRmx^Ce7L!r3J_FXfx1j9to}rDR*CgM49N-sSXPPR?+=!s#2% zgm7MjQ(%R5XkeiKO3jt5UCGC*sJu$^ZmYPt3eVNNwOXrUG4fQv> zF*lA4aa@SwaU7+#^TBrQFv!5F8Pn`1cd&jZ?z{MT7ejWDxC@`%G~La_-NYNy?AeWJ z_G5eaZZCEA>Ieh(@?#VizhXn z>%I+!+ds_&Bjdo zOvDi`9>G14Vu{pA)V-n-*_OzuM1qe}>liJMQR+C=jx+c;`;V(NDS77vO;51# z1aFGNDaPuh99Utrh; z9F5ua&oA=bMba)}y+o5sw75jrCEY9QWpZ7n)MbucX3iB>Tp{2pGp@4gD)p|>@fsVi zk#LQIDVS4eo5H{p4y2HhLW%1%yiONmf<4;6F*kHTC53J>^Cl~d3HD<*seFq*w-|d% zH^ts!w^DBtew#w6SW~H)N}E)sq_QHFQ>olb#p@35-=XOpdf#E!9d6yx9oyWc^Ib;X z<+FP@-KWrf#@{FGKE)sC*18X9@_<4Q`R*Zo9x~t|n~iC9*GG6f;@wAFdBlpxBt6Fc z2`itl{R!r$eD;)uPlfm@zwuH@V2?0ZhqbIr58pzjNozhLVN zt=@gX6Q#c7>`Oku^IEcjAX*^?|3*>6m<|KK219pqOBDV9Yp zWswJ2q+?bYkX2r06&3I!NBP209yp4RlhkvPMou!*N!#x^$x|oEpG|gTlQG$4OLlpd zUHo&%&>Rw1O%EyODHT1X zi>Hk6lr^5R+n8o|H73|EWK6RM6qCcn#NA8Y@{&4U(%ws^d&vqfeFdHxxVyOKN~)BQ z$P#j`ggBHGkCO6UN%^UyZVEE6b}3m}N=_Kl?0HLzUupTOv~KNV;E&!i+glEJ%QbIt z@DWcRdCx~G8x!oq4XouW3w>poudMc!4ZgC)SK@qSkFOl?m7~6L+E>o|%2i*v0y$-CK+s!Ahq16NhX_Qrb)s~vdAPWOtQ`-n@tj@7Wy;EA(NaiNwP_2r zNwWA!PCv=#CvJY?1>wXW*KCbk!BfdmZ@e5 zG0S|jEH%qYv#d4CMzchlWxHASo8^#MPMYPsSyIe$+boaF@=^`TERx$It`_mMNNJ1s zS){B*%3I`9i+pR5$`+|+k-8RXWRX@D>0pr_7U^%1Ar={Fk+Bw;WRd9>nPZXp7FlkQ z)fU-kkywlDvB)8d9J9z7i=4N}6^q=k$Q_G3vdBw|WVK3etGHUl(<&vb;%AkzRw-|l z3Rd~TD&Jb=2dn&Sm6}#*V3np;39w3MtMs-?f2$0)%2=yRvdRprgji+1RhC#~g;myC zWwTXct+K}|hpckaD(9_o#VR+ga@Q)4tn$n%;xF0!#l>G-{l(K?O8bk|U&{K+hyL<~ zzf|;>%KlQ*UmEyJ3x5glm(Kpu!(aOQ%W!`g>o1f1WtP8$`O6Z2S?wgFRLo8M4T9y4(sZxzL)i_j*o7E^)omthnQ60A$EUUqm8l=@= zS4}3@V&E@4`GtG639Ccix>)PdtnTYUbJn9*Jr35xtv)U4^P)br8nC1RM;lPOAzd1> zydfnT@o{7JH|D!0G;P9+Ca(wip(*Q{Qn4B1nz6YV1)AgCoCeLQ-2#V}EN;p7t!UPY znZ`irwayJ%bFMXwe`VRPyc@s|0W=MucK{OuI3Ivt8``!ZZ(G{6rCK}Iwqt60>U3af z2a0v1MMq*faSiX$3XfAvMiA3K<);TqYq#AVL%_k`|z?4@Ac(+UrO|&UO&B~ z(0;`CBe@?%`qQ*O7yFZc0F?$1Hh_cylo&|;fh-+};~;7bqSGLj8v`ZPvG8EN9?Yb{ z92`vfAru@+x1r=6Myp{AAI7#}s_ubW!})bM^M})Ogx;5uCnGQg@pTZjf|w9Qau6*? zvVSDkN8&SzMx)q1igTlQXEYr~b8|E;jImF8-@gc#1@j^pkFk^+%g^KJIgZ`qxIPZ` zcwpo4j2O@3@wiW5%mfZhApL>Bq7%6=k+&w%$QU1uFtEa8#!cqXWPO-wN#*aRFwGbx zoti?gsZ^fEtZ95Xoe9&qGM$fR5HN%A8EP;|lbKAI$=nMKc8?4CvT^a0UqhRFt*z3f~L%q3_Z@$)D>pE~ndJ)f)d$+1AUE?>ae1$Zsgyz)YV7P8XdcNa2l5kD?w z;9|U&&~^zSOSrZK&!tpb%Iu{aUrNDcSeJ2l8EMP-VL2n0Qz)EI!U+mzRX90UP<90s zSCF~_x0SS7Nzh6{)Iez!-x%Yg#;e%AiU+IkF~&zf8F+6sr6Z^n!EE*TRRm`va9TsL zHGH>*zH5kF!&zgLWLe9ewG3Xz#&zUf&$sKDy`CfMd0>o^rfp!)267oAqmLr#7RgM5 zAC9EcMm|!joo`~@CN6HGNEEfAm>9*uD4aLbcr(2=Q(_Ahw=iuBC$``cjbAihMN==D zZqba5W>GXhZKeBGc5da`Rz8WLSqyz*m>0w57%s-}JciP-REXt5EV;H(cN=}SF<~3` zw&4*+`#2`Yu_BJ6aomoh(01P1PR;GK+fKn9e6oYlJ6N%U?K|+^N$gHcYH9ynOxVSR zU6k8R$K8bO=Jamv?PmHOV)u}LFI9~3QQN&7RL^Ye;~issRM)_l`*?dlP4{zmKko6o z6HmQ(y2TR`&&GHz#`7W`QvzQm&?bSQ39L+DPXhN7a6Z5X2WWqQB?m|_MoFFr*>sSu zhghmI+QYnmnBc=~Kg?xgloWJ?O-FckM8Avp6JSP2$@mIwTR4#F`}HlX#p&{$wg7Q!|>B!B_ zk>xy_&vWlQ6)({50>>_p=OSf{QPQD{WVyuG#>lAiC01M_(cpzIv+gn-udwh6pIoK$ zRTf+&>ME_S5qymu*SM(`cue8@6ndr*lERr33S7tkIsw-if1M@Qsd9s!H`slH>o-u3 zM>W350%Lp>dlR2q)V#$oV|=vI!0NXda+?jeDV53(sWeSxWGeGhNl4{dDh2M~e}`Ik z=y-=2cQ|y1Ja>8Lu0FedcPVy{zt7$Km>y8^fo{F|fMO46XpD@;JY>&9 zQVs6=h#ij@@R;?FNqLO-6QZ7Q;R)rRQvWFtPdWJ%-!v+xF(ZxGG)|^5;2Ddb@#GmE z&nf$yanCtwjF0XGCsqL!nS zpGB?RDXT`y)PG>piEV*37+eLnIk=8CU!9|w4$T1gj z&MOu3N;_kev?;ID$tSM)@8=#<&n4K z^%1j=eB~qce5A9FxckbNzA|2odj3GXtJ1nEF;)4d8ZD}^qZ(JL;ZdD&)wx`qyfv6t zgAFyfSA(dU1l6M3FD(3pE47(ihpct+sY|^#a>%Up=v0s0^~hbHI`z3*A4>z~H6XqL zo(*Z&kogTM*oe0p6VsTFn^3~IpogHZ0W+gUD?!?vt4P?jeOm?)E#pVs`cP< z4?KFZxF@%Ivc4C0dU3Hg&VhU#NUuQV1`-*_wLr4;;p0B^?!){(Jn4hAFK7GW(T{3I z4mqPA+xu~{A9?#zvp>iBlY0PP4`Aj1b_~E{Ak_yldmxVo^8Fy%3}RkJ4w-K-9}gyY zFuMlhH-zj%`DQ3thVlL|1`cE6FrE&h@^G4|8l>U0$;ct^jle62kAtWZL{JcigQzo- zts}WKlA@!iGm5BD93O>sG%ZJyJet~neGa)GmlDYThN z`Dsjg|Xa==s5;T)}Gx=&3ooBIW77j+zSZp={vspcx3x@jA zz}a&+HwV`chKH~+gk2$|hLAIqa-mcXrAH{^Lx~FIXsBMa-93!2!{{5vx-bqJIizVW zv2*D(k6rV~HlOPAnKYmC^LaR5pU9*I9A7|gBX9g>Ap;gN%iz}*GH4Oy78AIbJWFV~ zgy~DTu!I6j`NvWwEhS+oxtHOyjP1*Ku#8WZGh{h=!YLQdfN&Ot>#qmX3cgyw`4!|} zNu8ApUdi;8++E3MMh;nb6^mAJdlkiv?6HD@r&d!ef+`VAiePgDi4i=Hpx_!lT|lv_~`1PDOa>xN2h}*zpqnf>JByA%ZVdRi|B5Agf zlAGwWiItl;yNSF}RE}a~6uY8u+{`bV>9UyuTli`VBe!sP3r^7#kLIIjszuW_nqkp| zMf1g0I&LL$D;Ks>E{3`>bcta`3~ORI6~p})JYp#yOJXdJ+o-gS?%No>jZ51o7)OgZ zM#r%rj{R|5jw8=@e6~|*JFT{pZ3pk~px+J_?;v^yg?AFQ6R%y=*hSDTPVU08n^wD- zwwuGdxw)HBdx+XY*1h~-F#VZR42| z&#HJ%#q%H@uLM3!plJeq5?Gi(Oaj*va6G_U2WWkO&;vvnIb?x@EI&y7L(D(K#Y2=m zOsB&{ALg);Lv}jC+9O;ua>$a2G)SaZqJD$zNTktG@*Si0G0q&r`#8TGXT)(19mnwm z@1LO638GI>?j&taGVCNir>J>~*{8T<?jFYvhf;USh!|Vh!$mnMIeWeTC2~cweRMRYI<^?kWwh zG4vXnuW|7jZYg}0LWdNlq;MpKoYyIRohH{Aah-YB`RWFpZ?NeGmu`@DgK9SkF>=VL zo8-8~&$k$0WRJ59tZsP?miRmlX#z!4=DdYpL^m1+#d3ykv9%`NX$dd7`)gcHaw#B zV^%%p;$ys?5b=bQPw;5a4!Oor9yyA|$QzqENr;m~8T`4EOvxtS zXP2?rWm|TU9P&;M8JR;4=Maya(ln>^%_&85Nu^veNv$?vTy2 zSXkl;%cH_#agzpa(%ntQy2)ZUiFK1xZt~DgCKZwGMI?{Ayzef}+@+7ZOm>%5?((yT z^!Jcm9&*=1-uILSp3>b@W_!wdPdV!;PdsI6QQ1{g@)nbiipkH#WKl6WUQCL5$=6;| z-%AF2$t*94^O7Vl>04aFi_62}QoMweFCk+}$d(dvtAu1LDaA|5MkF@oX z+`dx5R|fxa4(VT&o>e(ml^WG(SB<09xLpn3>V#J3R&_jUu(AeQYw)rL`)V@17DIpG z`7b=G&4N0()}>5cTD_4&=B`KIdL-7vvp&DpM=cgtw*ku(s5O^b z)BIP$f93rEehQ#v0Q~}(8o=cMEN$r62G_Q9YD=wlM7CpQdm40LMF&cDq*X_@tKXC9 z$gPg}b>dnlK6)jGR3Gs8E_~IMyrdvL1_v&* z-0w}HKzj0__VBP?Z44~9Nnha#+KynVE&LFxBVs%CiS!6I32Qy_bM^!R81oxrz9!kMs zv>is!Fm???Et6JHWsk#IGMv5{Ib_-h{DY_%MC~A^25~8fHX}JSlA9y3jH1aX_Kf24 zD9Vkd>uBzdCSZ)d%l)Mi9*pByijSrISZa);_c-FmadRA5#?xXvBggZ6Jf0I+X=IOC zChBAHnuy~hO_~@u(!gd$_ISiVrz!k6g&9T;nLLGlQ|UHM`~Ny!P(i+q~&Wz0ivF|dS@H&$Cn zuqw|m_@jkPUPS%Hy4TlBG=?qV`VvYk<(H+*UCNoIxG$s3GLA3f`7(Z9&gkWMg!5%M z!Qre6$7KcOSMb9M9<0E9C2dzSY9(PSaa_fBMh@9@6-NzXGP1`i24;=W`>Gwm+z9qY za3O+RYbdpbAJ@=-4O`ZbY~+w{uO(qElh$eH5=P#*!oWucE-|vlJVxI5StPw9nQidn zk#yfk?M=GZhD}`FM6oF9MKLXkqfr#tOpDC~ZpLQ|KWt(47EW!!HJUQfd>>8YXnIF8 zDVinGRNqR^t?b*%^{spvL+cm@#;`bs*ch(G;1G*nET6`5HI_WvX!L*B`wqA!mhSD@ zrS}e@_XH3Xv17xIisd496a@uQEMRXa*u@HBxr%}nM5KsP>|HE~y`cg&6jUsT1@t>J zNj6JJ0J*;RzVH9L^JAZV=FBufYV8|}?T z1=*-98*RUY&R#+Wmr;M>Lr%Jk3JGaOyvN}LHLv2qj=74;uOjmt)G`N+%0Y8-(C!>` zA_u+7K{D4+!)vJfH57CWg2)Ae4#yYodqbYZg%U#Un;r0xKM&3i~?xFm9NasH4dLK=P z)v@lQP7l!R2WZU$)cPSB@erjvL~kBqWu-hcm-vl21j`BTdxVRAK0=Ehqr}JP+++0S zF;aMfnmj?ho}g(@&>DDU-4k^4395X84DwOOd^9W{EzU=o`KTOTV?%t%fC8jgh;j;X zRYRX*EF$Pce8{H+yAi)}=5v(x9Ni_{tCVEuh55A zi2EA#evLw2qusAj;cH}6jGT+nMEkj5v4^@Z76C0Ma`$EgB10iqI5_c(wC-a z8S0`84pMo_Vk{)+KzztY1YL>W7%Wd6kf*K_uA)HgQ=o$2SxC5dQIS$oqFj}z%}P{( z5@oMU1u0WYlqn|_YJdtAr$Rj=J|w)%aSHJp&k=k}FjfuM@L7!-txl~}r*^4RSJbH& z>XfDi<)A@%YETn3s7)GFss@#(L1}7IeKe`b#D_eoNqK8gw%XV{gfcdC~bY}zCO0vZGiEo0o9a41#+mx@J>$-mCm7ZIn*l-^#h)cG^DN? zQWi#32O}!jhzd8Nb{SEb@N}dxwal1$XiR-Grn;I?fhN>q6KcN+b zHKnZ0s7_|oU^D878I^BFH87_<%&GC_RD?N|U{2jIr(T*<>ny0l7L<}DWoJpXx1?e% zsq>apg(anDMK!Xb+^i@cD{6)nWob=yv!*s%QyJD&i8ZBYLs{EUZEdK5Hq?($dnTchO@vp5ooO-vlB05EJ_XVo1#g&!LTk=q)36yy7TW~V2fBhosJUZ zj#C?0a*4D8?s7m`^d>=J7QI=(3J|%xkZ8mf-h!izpLU{Xb^+misBP6`B7rNtU69d5 zF#?v%uu_IKL$QL=nG8G1FdX3Kr!JU zut0p5VZL;_m@52JqB8`ta^_9Z)s%#SPgEwHBj_w)9`7F`a=pbCN#wiWR(XDcpV469 z5DaxlH_!=zRxCP+Uxo}o(l9tR^3xWEJ!F_MoTB*2k73Qx8G(%Kj^V5xvsCdahFxWt z8agMi=*_TA4D-he8H>_8oQ1V_M3Oo&Q*=q7SHdun;YMjo8WWY}^c8{XaCB9`v`~(K z^=H^dhCO7MIrAE5Uxw{vSTVyI`WAURG<>($eTQg5b4+IKJ5V`8CqTWQ>%Ed&> zntmkEE=NMP9S(YadcrVk^h6-@XBaF9AdtOdSW}cQkj=m>1;Z;wCMbg4VyXb1>!Aw; z5>5K4fNf=%NZE^iCdfEZ&qZR%tQGYF++TQdo1f0oFWGvB!M)?BCD1Q^dd9F0=(Rw$ zkzx4XD=RH$vbPupt1YlJPy_JD#Zw8~vm-q{rpe_pD5Roy0<})4RKUU*cAjC%=)It{ z55pobyMjR$eGrt2b}?|f3@p$?E~!DHA27@lyf}Wk&akfNyFix7Fj-U~klkb$5e!3>f&$Ubg!&=MRAcJ&Pl2ou37H>A zC?eg%FnlQRWes7^XF-@HV0g;Nh#7(T6pg5+w2VMmnU)o>4Ga@052WP;r4E$5fQd@Q z7>`mw)I%CTQ~--2v9qEA5rbPN1uF9pyc$|mKo~p~P)#OMF{0u9&?Nhod1rJ8vq152 zhSA`v^YywhYz4z|FjK^<8M`t|8jISIvH$^X{s;_1& z(j#mQesOeXTKJ}DV;bHMEmCQK-vuqoN@ZO9erQr!hFMD_T)9}xqJSw#MzEyu2Mk07 z?f??7Z47(NFnc6i()bI*h}i;UhNycONVW?SE?T^ZVP_epfh+`ij~PbH{17Z;d>jMG zN`>vnN}w_kzaKgogH&Zw5P{zmP1q=8i@?1FsM&&)MkB63FA(u+wD9miF&?N934$aM z)b>QPJ*%`)G63}(h;#;_H-oTz&JYwh6qO9ce84b_Vrje=I_-tZyin)i=<;x}LbS~r zef37`N1|<`khKpkT}e<(FVYw3jjkf=I|l6>gD(0ZAAe*s78k7|SVf6sj>FFJ2;$9$YFcMkrz#`m{`xW!S?q|WxD=KrUaAW ztI+9HsO^9LqWt0-R4lxp9lH#NDU$|-XPdD5_2ZGt!Jo!WJZZgn0)0%bd+2U z9~E8-GevB2i(K~Zj26lIZWD1n>$F{5@~ip&JCP!}V0}Yy7VAQ_HU1YVIqAls>^NK$ zTjfGjTzTMrEU`@#moxb(Qo}E~OX_j}y2k_M}t=et{pkglm3Apmt11q?v6Z7i<3K z1?BIAM4G-Sx$r6xUVeevrpw~G;a9{Zersw=lvfu^mB?1$qMHPP4677rnpSh%HH9v^NU08N0Zlb0zpts1U)DAe z$)nI^1lei@RR)RnKBY#h@ z6Q%nDP`iP!tPFZE2t^G>V~3z2L(zTWLw1tnLk{*rNnWVX3pou(8N-p`2vJqQ!oAT8 zZxlKbg^xm-#Cx1Yu!<7Qo-eBUwocS`3|cz|9r8nc{gD>&9%oDOArk_SgLEIVQy{t> zh@2*%!xPYqiTJ^oXOqx`$tZtvl`i}YLX(2gm*6VGWm8e*RJ4Hjklg9$`gAmldiid;uv~`f=)ZId)hd$E9L(eu_Vc_pb;#q+!05AZBndA3|>qVRDxEko{Obq^5KqvLF*h)#gL4JBF(r zc^sp}bb|Pht4|6F-A-Y$jNnCril?!pKS8TAm_ynpB(u-rY!<<91YL;txR{`)&~?lc z609vLDHHGUKFfz(RLzH+&hjBEui{!djAZ4>^V9Lz?9Y+Ys(G9|;+p>K|i%nV`lK z%=;7ENbn&+^L#A#C3u@4&Lb3DfVhR2R1#eN6mx#+@l437?QLJ6`^1M#sp>;c!Es7- zouK1u%oh=SLlCmliT8Ml;98*%$zl18_gNg{!IKqO0?DnC zzsIQbL&W*)J4@n0;!Y6+Zxb}6C{P|sjEO;tkH+u zLVU<^EFV&@nh&YK@*&5mPv_?Dov29``Gm_^W$+@QtpcD5!pkNA+D#CyzV`H(Tv zeaN|bloRnG6>IY$b%^&^Sj~sbAwFcZ(1+|rme2_&c$uI+@gAQGeaHzyAF>HqJST`? z3c(73mxVrLe@i^x>S-nMA%{uvA?FhxvX68has}}rht%jpR&TV5#Ia$OY%Q5(PPHhI z;;@!=(fVCFXI(@!ePVIAo^B&5;j_$Yk~h^PLYow0yV+b2gy9IlAF$TlCBHb0Q0!gjRb1wq*@M&~iZ#Or-4p~Rw5RjpvLJiGKLlo>T^~abM0KQ^Q|SELnl-_j~0WZM>}C3{@wpO1OIns;6`MXu{4RQl7&p<25|{H zzkM^#Mg7T^)y}iFiR--DE-tA@K6e*3@*-i8*R0@3ehtA9IERw3$fSMsXs}KuL!GGNh(7pcax>WBDt#Pfl>2EgF?ev=~{2!_=u=9UQXXU#}>dDN1?1+!- zCaFJvw~TiCyIW+pH?0Rd_kWY0=_x+0d(|Z38vobw{;t9i1u;x0sq20YW4V}Nb+!E) z^q6zJGQ<9cR{ypp1~cbzABO#HjaO^vLl>c_f?-0*KfRyNoY$8#?4Rk=+wQ`4zc5TF z`Oob~G3WI04ExWu_V?HP=Ks61_uoIqe^-k${xR?G_m6OB$KPLP{c3#hfAT+I-R8pi zzvlnZ6^Yk7XaBJy-tBMvA0+*=y7-S??>PMXzeD;*^FLN1v-W?i!~b^o-x>HzGr%eS zOXmL*#<|tb(9f$${wD_V7dko4RcJhwVM0k=_aThsGKSUF_E+`#|FY*R!+5A_4Exnq zCF$S%t+h#Np>DEaOpIm>!|G;Pf2{^mJ>N2>k{jK=q&o}A8Pln&sg1SxK(Y8uc}Gv zUfchs=0sOvzh^Q`D5>i{jImtFu)5m*s@|Yq{-345{BO}>*sr!KN&oI|txZx3b(48B z|EU5PRyWJ~Yc-bo|L7}IBJ&IXP3qs1>|bbQ3G<(7EyL>HvSiDyb^0Gv#%TRynB@BE zCp{Q{fwR=j`cEc)Zu+MP#v!25zQ459i9M)ZJT4Jc1|KnH`QB!gGS z&ZPmi(SzUtb84_a>pMLJp0J~b!ZVB1Fo7(v_9e2z@WR;lF<4N;;Sos;^6=&s>FE$& z9ot@JB&??`I|`2jpfBYkFxXl964}QoUwFN|*y;gHdwzIz>`}BILdr7!u+Soge$-e& z`K~%Hk^PDafYmRlaZI(fl4-JmFm?03~q+9#cy;X8G(Zp? z4yzVW03f(eL+N#b9^a&dj0ncl5rP7miWIO+TF3+f z;ZB`d1Y0O!@2AwhFt$j21zsI{F|#oCEczE8TR_9;XhCf^DIpV8zk}W;%2Z=_sNeC3 zL$zw92=eKj@cbIHFm@MaVeA_W6Iot`*R<6+#p2bm1DS=f`_udCY|2-BMDG_^44@M0 zZu^Z+5-115ii)hHOjmor0zHu+6Pf5x2Su5Bvj_AcytwdTK?P3C!q~?dCaOEL_Jy%U z%3*kQ?6Gvc9^q&}9~V@#6PBv1a~eXQ6zE>3gsjfSSn&;gTA)9MI>WZCq^o4vMKy7A z`n;fcBPC=+(3rkZlby7(UGybEkqLFVno==cT_#e3S1yY({|LK`SI3TG7RI(@7RF9u zn5bX-YFNWVq$OY>cy;U^%);1ubiE#5A(geK9||fxObMB&y~T93M_fdOD3f}`%Kd#* z2d|F(h*=^#fLR#3oMEEQe4w6*GPSYucy;V`%);2i>7v>!>RCRFE)iJXq=bwJ#?x=A zRq4tsf?cf$1XHQM_9%{|I>lv;@aouKm?g3oF$-gBGs|I%Ow?*$7+a)#2d|DDOaG<^ zdtgZ#xibZTSVh&cYIt?*yUY^VzRbed?-?et zDWQZ*WQ$}{*&)0-_5xawtmz_Et6D*GTDUNFA|+%ZrMYxXOJpZg!X>gr7QdT~!>eOA zW0u1{$*?}ma@e9Kd(^%#wn*6&uZ~^BERmg7b%|_|Ud=3#7A}!(OG#NBn^Z8C7Osh% zPYGGgHIve0TDU~E9VJ{2n-rX+t7L1gY6C4?B3qrRvK;mvx=L1REnHf-CiXT;$fPQh z0z+E3CiXf?$ZEDAr8cy1VeGAxkk!HLe@{ho>bbsxUeEudO82cHxFbxX`(yT;Adn}* z$j;#bLXB#Bn_*ZqnIKb0Ly)FgiXI^l1wvG&Y8vK)^Lq(0C7pc*bkS%5F@<LCLC6};$HH;*Q4}Hf2x1Y$mq;WdilAW_UnanD3o$uDP#K~Wup$^i%vfmw z308b0=(9{v5JMspCBpbbUkE_3(o+(J=)Y1Ra)4mN-<7tn5wzq;ZiEV2hqF)Dp|6C5 zlK6mjWR>3Nt*?@u8YRkRY!LB98%3PW9!R>_-?0^|1VxJ!O}2?Ruu4`|JqCrv;L_6s zWnwY!PB5I{HG(=juzV)LYXos#Qu?%8B$eAM;#*i;Bqc1b+SRtreq8X8U`QfTJb<%v z304s7NUobT$u)CWGTOwtcpj31m6_y{%23qnAX;+}XRi^|NW(msU^YRVmz46;Mbh^f zBEB?J#2I$?2t!3A_!#CLk7K+-5HnVaIe{~iPGZbEi5j26WD>z7g6{}6JB{TsXE07X zgTe_>KZ{14#gbTp1q3b6VTm8X=HzN~?|F2LkV6-6k;GJ-jm25Q>q_8bs$NBQyCSk1 zbQL`%SCQ5^Sm;M^AHlZ-ov&f}bb?s~e-QM|#qunIm`O_4Z;GUaw?usAZ4nn^VfVxY zg6!f4n0T_T-+r<<6y@g$G-3Dt5ej;Yvnd2W5Nz=TOJ);1PLR&Wl5PYO2+{>uA}tv{ z6O}kT7x9xUE|LZHLNic(81wmJ`V&iUt6|B`8 zMaDv=!&;ZXMxGLiQ5K6c!f(}!CPoRI=V#5)Qj*)*N!ZT#uMklgXBflt# z@DQ?YW3e&iOx9`)CYVaFoZxw~ZeuGmst;MW@wyqsA*(bFCb)^&^m8$c$IbsO7~bsOWWt=>42tlQYw7FV*BAlnxBc(QJzOTE@@tnd`8>@Q`rM%2?h zc62=r!Ay7jFWc@3`ehR^aFygbvMX9kTt~KK-8^DXpZga)+3@YJ%SS8ePZg6*ZRbG_sYy z?qlb~`Iba+Nxk#_#BUTcUtOc?D5eZqV@XaUTkX>kc1{9+bzFjwE&6(rovWQUARc4w zdP0pG(j7>lN}cvoi1%10)v8MKbF1cS%c)9t8ri1Xr8tmmom#mX@fd4WV=G+9XXk3? zp3!eDQCP{J{+2+lO_sEv~7XIaDE!CW=(RHkD+((kr z$W}8@lHh}}6>8?P#AB>k2TILqbRDakC$JpI>ZOdNqa+8CDFxD-{giH#(AiIvMGe)t06pZ|oHnEYG4#5;BH5{v(`muMDK z(=>{eE&D|;(YkJ4;+q=1#5KRqOB^Q2OAPx(FHxg5FR`dLFY!@rUgDdRViR9W*8CT} z#Ph$&OZ2a=mpJ7Yy+l+uFER3Wc!|`ndx=N#Yx#i0irwnwC7%2bdx=Nu<|W?wMK95} zHZRfsKjS5q)aE4~`b96XQ*BnoHjgw81JuG`pHd{7V_Ll5J z*)Os>ay+>Xa-HRR$_>d8HM`_Zxr4ulq;w!YAfn18Y!A7S}AfB8!C2C^icFsoTeDAxLt9-;&H{(irI?y z6(1>Ur!-w@wo<6lVx{FuJCx#;l9kexjwoGKDpW$s zI?6`MX3Dn8j>=BTEtT6SyD7UXdno%WPg9o1Dd#J{RQ{%{ zr(&&smrP>s;jDNs_UwA)J@ba)NR!5)E(8G)SIcd zQg5s7s@_H2P2F9+pSq{|V0AC`Aoc0$A?ji3E7Vu3Z&3eJeVh6o^?mB8>W9^jtDjfD zqW(briF&E}7xf?N@){}{`Wp5cO*A@b^wjXs7^>l|;jb}OW3fi8#(s@s8W%MRG>SDo zYRGFEYBtsEqUomDPt#M=OVdYloaQ9W8JhDo7i+H4jL`g3bBE?W%}mW~%^c0gnol)9 zYJSmF)Kb$j)w0rZ)@rHMUCUj|N6TL;P;08zT&+b~QCiVj2eb}rWoup6x})`2>xI@^ zt%{8p(K(=VSm(ITd7T`c zn>r75@^y-I-sqI+eAD@I%M>Mqh< zuDecmvu>>JLER&|mvswt-|DLBIq3D$3)EYww^nbH-d4R`ddKwc>3!5w(l^p?px;Kn zgMN4YUi$s@{q+~?uh8G7zf(U$|CoNR{%!sH`UU#W_21~f*Duqr)YmhxFt9afYS7A{ zi$M>AAqFE1d<@1JOf;BoFxw!+V2QyVgM$V~49*zbH+W}IZXnCya7;Kh96OE^rv;}y zr!%J)r$1*1XB5YeGm$f$6T(@-Sd;)X>(jp<#2wc7|OIdm9cg9Bw$qaGYVV;cUY&!xe@RhJPCFFx+dHWSDMv z!tjFOHN(4xPYhogQbtNfT1JLOc1BJ{?Tv;Q4L2HN6krr&G{b1V(ITUjM(d6KG}>Xb z*C@#--ROkT1*2<5w~X?P3XEPEy*2u5^xa6tSkYM1SkKth*vi{fje8jX zVLZfmlyQJ@knt?zP~+vstBp4pZ!_Lwe8Bjy@p0qx#+Qw68b36CYFupm(fGTujERbg zxe3q2(WJA9o5^q!ACoC2GfkG5gquW~>^9kFa=_%UNtVfJlk+B*Om3LmGs!o3Zt}*Y z%;dX?jH#ljrYXnN!qm>x$+Wp?JJU|4Jx%+X4l?yJ9c>z58e}@%G{khF=`z!`rkhM- zOyf+GO*2eSnqD-`HN9>6$n?4C8`Cn=N>e#AH8X89BQq;A2Qz0g7qd=gzGgGb=9)#A zZ8S?XOEo)dmTmUh?48+1v+rg<%@oX4%r(pn%uUU0%^l30&0Wl0&E3p7quQ%Un9%~+Ne!%>&`4RJz<`>O#&F`7#n-`gvntw4z7K#>X7J3$@ z7Pb}*Et*@jv*>Ek)561IsD+QkIE!G5*%qrUc3T{_xMWda@!8^=1#KyBscxxjX<}(< zX>ZxYvZZAQ%PyAgmY$YgmZL2LErTp)S%z3Hu?)A2wA^GFW4YTh(K6LC%kqTfS<5Sy zw=DB4pIMezezL5vl(kZ|(y}tNvb3_dYGT#es-sm8t3Fl(twvb+SxvN>ZWUs+#A>zG zUaKUlvsQUlgbt*6*#qT31?AHcB?8Hug4+Y}(m$vgv8l*QUSCFdJ_hf1B|(lWb<#thD*lW`|9> zO}5Q-o7*;zYzk~%*?hH8v{kd!v$eHtXzOh2V%x#CyREmazwHd$6}DS!lWkAgp0~}h zy=nW<_KEFN+n2V*w(o2|+LqgXxBY1=!&Ts_a5cC(Tm!B#*PLt3<#8Ku8*`g-TXNfQ zJ8(O5yK{SS`*Qnp2XTjSy}7XM4DKB6eC|T-Qf@eR4L6dzk-LSvox78} zmz%&%;vVFtbB}OOaL;nHxjEdM+#m&hResuJUg1?(*_@1-uu$VqPh)jQ5TAlP7DZWT$SYW5=;GwX?G0**V%Z zv1?)1#?IBQt6fjKzIL8=L+nP_`Pz-On_w4gH^XkOU8vm>yKuX;c2RbJ+HJSnWfyOE z!0w=3hTSo{({>l^uGn3-yJPpzF5m9C-D|sdcAxCN+WoMTu~)QLv)8saus5-{wCCD4 zuy?X=Ztr5>!M=-q5Bom${p|>dsTGk{`b{&ULiDajuv68Q zdd0aq)fVT9s21mnloIDUC?(F7R$H9QzP315TS;*)l^TByjr%9!T*rTFoa=cV;#^<< za-0jkO>QyxE7gzSV1gqFjwLvm;7o!WelgDFT(>ya_Zs6|2%&fq>PjJ)Nf3nfOVdcG zYaYSH1lRszoXf1XIM?Ue;#|eG#kpW;DyQ)HbO;&~v?eHR)a^*9t1H3Y1P2h5sDJA> z#krvJ%~x>?u>|7@rVz{|c#2>)!RrL?6Ab;uIG0A<;#{%6BhCfGX-q<0EeUoY*qvZs zf`bTp6Z9vTosTD>?rBin;#^SS3li#jOYk$n9|Yye4R)YlBqVijovm3&LS3&3ejxab zAWd$nQzrQA7vo&PwZ*xh1HDM7t3SbE1bqpPC&=#MFL8Bp^BgJhldZ)%X*Tov+Tt{mBHPqPyHT6Kv$kP`={c+>{*d5!$&3 z=XVhVvU;ho7@h!GhNdnPWf|tX0*zjQ#;ibo#C3ch&Xi!%ZWU_33UydjMfji2xU9u3 z%wH#HM}a(Xv4)^UWR=FP*H_6xW=)j1grDEN5$)TElE?!XX;L1;;Ajfy#HF3gS0XJF%%eL4G9~dn8wObT2x!7o8{Gu{ZojD1p`u98R@hn4ZTl8pNZf2ogg|S(*DkR^g<+srZZ7OCQ8m^ z%Ovmx$FQ*PaS26y(SZ|qKkpL zkqyq?RY*eD=MXL|mf|dD{ZyP=Fd2VAW;>TNC7)HhU(yih}3p#dB0lyvNcy z`;hFql8bR}eu+S)@J3X4k;VDa!>mUyM0#~#t{+g>52)t{tlF2LCqcex-!jQneEW=k zenzt8l1n8@^S@(pQiY(fWu-{#3ybrmFMfzh>&VP$%7&)wX$tfk5o}73Z{A1_%d4mR z^3-E_>S>MM;|lWJ#SqrB7P71dE%P+=-+~WXW-u% z_;&{Woq>O6;NKbecLx6c8Biupqr`Tbdx*rrB#Ky8HI@j)xdTKxVyuOva3aS`Osh&Z z%)3e!G7}_)6Z`v$t2HGdM7DIIlyIV-^jIR8w~`b*WLL}QWz}MdARoXA9#%K`LgI&F zaZ>Lj`2FFoei1h-8Hmr%8$> zg0g?rAD};14JW$(y@5o2=R2&$`$Z(2_--9ijlkLU1Z}H^6YZ*o6W2#!&FU$$#`vL_ z{-Lc{uqaw2Zd^5-Xu4fgR1c=IvnC^5DY3-d8smpzHMS(-MEOK9u_)_F!im<&Sh6}9 zB@n_d4y+nZ9GWV!s)5NJs-X}T(vVzwsJ18~W48Dhrk>Kni3d+$g|L$tYe?NmI8mQO z5kt?QZG_aIKZ}GD-AEMi;CYl=TR8Ct2`645~RusAzo#1 zusTxTSmKZmVr^E*dX`nmG8v^`i6Syq&q+8jtpW?oD^c4@rUX^8I7o|sJ(k#t6*&~u zD`ZWj#1e~Yj3NrH(Has?9Ki}FDpd_0mRHR(hP9F?R^+g{@>(geMEBa_hhkMJkU-*{ zYT?AwB%HWTdN@&;1QPEP>|#cZk{(VhCE>&qB%J7ANp+VJPFz63iG8Jn6Q>Z*u#@y~ zVh9N*_Qv7F)-*g(44WBj9blUbn-gr-Fm^lGyTLXNw)U`f2H8N^^I+=^TL5ehAnOTR zJK!T=-w!q`;J&am1wH`wV_|Cr+hE8~gne7sEMe;en-6SLVDp5{2Fm?m-x9V7u(g40 zIBbnz>kC^jY!Fn7^QB^#*tA%zs&-@-IS=l1oYq3WpH%5vwO5n zhPff1o|e~Z4H;x`oRav_oBT~B5sCn!GUzKwop-Z6@Qgd8q zK%;rP@6w8b`9=DE6Q+8P9TPZtOz;$Mze&N~{EzMw%=(p)6n%Lld)CYLdo|KUJ{|bA z89H9Dmqi+V_@5MYrMnz>wqbOcphHI^;Gckjy^Q1oAbN3A`zMFzo*@T-g5yg#mJPTvwI2XUuks_~ zXSk~pJ6*?6IF=1Y)WI&yKy7C4#IG6rA<>Sn;IKA$T-%T?d<_rKIn>rsFl(A#87eSq z4P_vm9MmR4Tlt~`Pk~?v`PhGkq3(EL} zq2>Mrf5(~-3&*ukxk}Yv@0m!c^T?>%*we z;FfAQft8z%F7MZF)hxad$34#uM*XE0qn$>74sOf4@L4co8LtFzZ46$@N&MveZubwi z@3~cp--5RLYy7nvDpzy2Ty)NkaQ)inqVVJ1!-H;d?^(s-G}9gv1aqqHeh7d4 z7L)E&o70i1clNrf>qJ0z;OnR0n2*04D+B|UdTg}F?QgOpR&6fdO4sol1^qc$o7J?^ z(Zh<$envsM-oO ze{R{!i#7)a_S_*nVmGKX2CM4|l0Uetsh$nqjTv$snwW-E9hc$*HbW<7W&X++!cDL!n+ z*P)RU!OxfSl=@yKcIu7?@UghF4t9lkdPxx*XS)lhZn=D8=$xvOiYlK1d`pCBoXH0@=+^N@2yC}~8~aSuKqC)S}6 z`SQ1>lVu;j0=qr%|J7y*9A?vAwOau5PT`XgoV54(P;|Tx`=5GpWKOmma$H3k({j9u z54VSPXv{{nX~?Q>g$==HY|sXRWR6Z#Fgjpt_Fmv-+V3 zeKb{(d_Y{)H&yOfSkRH*gu3HieBAlKS+_>F;@w!)E0k=iC*R7*aSJ|!$Iw*I+Nifi$7RR z$L;v=Yo=Vwh|2cK9u95J(Iu^!IzGjxTr1VuTWf5xeE&MPXrVuQG#dL1D^w*<_R?HG z$Iq!251=pjI!D245e?c!suKSJPF?t@?e?AJPSB%u@NLiygKxu_+kS9qA&Wm7q$IdX z85490E;HzJa`5%oUF}L^v$x?fouh9y^JhcL@jU*1bb{lz#?NBX$Okhw(q_4Rx>^6{UDB zzJ1D5{+MJOBk=c0AKcFx$Mo}KQO33pA*sSKy{8&Od(G7)kI8j&R@%75I~ze8@NZ1b zeLGxv7~EImw;}Dau7$zd0ISF2@dXAL8M@yFPt!nMy=J4BmqB`?1~!f2k4DaM3qH`F z)i#>qSmM)Nk3LgEKp7wVx?Yj^ zGU1tq#AE+<6n9oagVwwFb7Jb4hrf=nC`iqp@Y-=-zqik9sl%Us+PxfKPps0YdHP?5 zE6yl*n=nu~?5%t& z1IHwMq+h7b>TuqyF0VIdr-0Qoxc1$IkHABkwSTP?51J|~Jb?c%*v`-~2OorQ>R^{P zt(EtWwgCg+;Gy>%p|j!zM-n-l(C0Y%Mm)VOp7x8UJCP!Jp~7rJtm0{9LQ;kDMnZBa zo{kW5TzfoS7*FpZlAc2OTSCI(>4A(Sjy@hwuZX98;^`Lgw0=DOEsnkuPw$AQ#}OSP zq2@jz;l|VIgdY}4oC*05N9V-T8whVNEP6r6^mw{YJZ;8T6BZ2>66o#eczQL-x(J02 z2$>j9cN0op$I}Pm>5zEZBc67Mr?unh&++v6czQ`ZJwmASBaVI?PyZQD2g5+(>He9t z!eQF$AfDvei5TNE>4%2}b3Xe3Ju`vcnnkCiV~J%dJt>J+*^l|+40_@rOahYWSNrLH z`{=ouID7ga-8h9dI6!wyp#8Jx=IJyqjXse=>m}h*NPRPCcq8YDR9YcfATiCPo0AsL zB-48n=?DAhyP32iX%Y1I9-#Lm(3i64C+YP1G`epp9i2qC-cPqULLbbaw;ZBv4$>Qv zX#>)E(4TOaes_@eN}+on5Y#^>o%TwjOH$}gN%Z3cfw0vfx+IlumP{YrPh0F02*Lbo zGW{fx)=HpdvjoEBDfA1+kwh=uPft8T7iG}b578^g1a?WJL-)~5 zvgnKB>ZbuxVbq~@*lIi>VX;;?Vny1hT z2k0gVw54!vlTv6o(s}L?x#?+TU~j zC8{*EqBnfF7hm+rkU{DtAAq-xJsmCUcIs#h=xlD_6DwDGYjgt{@bGtyo=F#(FYgcS zv{2G)Bs=+bxi|0vy$0_Tmkr$E%QRavd2@c;N>z*K^)qT#tF<)bTUl@Iv7@8z2o6q3 z2F6`elJ)vMS$+Zf@4mw!RDW5|pp(E|`nF$UkddU`9L9KMy+&&TMZ?SEfOBJ3HrKN# zS>^@f>UjA48KZkbp1iZj4Gx$DHa!RbTy7DUr-y%I zeEfAqxaHs%UvOYNf5tL->r%4~2Z68dP`bjVXx~*s7}u-~-Ic6dZz@|rpTlQ8+{7(? z_s{@%WLnE*ynBt@kAS}N*NMu!^XEb*iPQo<%4-{qY>pGKfPkarbe4wzu5whnl`v`l(4o#zuz(`DcNFL^E_v6bcmA;bc>RDT)1D3LJK1A`CX8!fhtxU!Vup== z1NA7lo}TeX>HSlgVB2W<^S2&~-8lGnCT{CnBi&s&c}Bu>0LXCKuMwg+p!DKeP_I*Z zA0d}C1eLy#!)=WUZa$=RWKw`w|JfC#nYM8no;;|G+-AZqr~}_L^}dzQmwhX(q5jgn zWo5pub0gr&5M`|{SM-@VvX5I0?bf0CDk_6IrIw9f>;7()Se=p2l8;Y_xuJ`H`(r1^ z3Y+nhoF=a|fcYH#@zlo2BOQkh6r0;8R)bFkTXd7l5u4nznHQfp78On3v|z*CtK(4h)kX2 z+H0nlv582mZ^}o%Z zBzxP<8sA!gyeb0e+aq`P+zi|zW9X~f7QwSipq`5NH=5r2LX9R18?ZX};<){p2gwg- zYl6<0W}C-9SQhlY1mV)hw zw;f!ZHn+R~5O`Ed7lp=~<(qVX&sVSYLq+F~dz*HFN;LbHr!_sb@`N17cXJov&}Y>GsNU z*$AxPb@7^2^8uMNHJbuY9n^H-K+6Zl z?byn|%N8d#85|lFat!#GyPFyg8P%nu66o7`KI$~|`hz1OAWseHxj?C z14CNJB;bE4ZO+7c4zUbfavsJKeD+?-i1<*gj-c+RwHXEx0@-Q-2%Hstv=8*hwC|B|<9lRo$QSD~yH3l2XLbdj`g8q0s3)t< zIMpflA53^G);G4kEbp1j^Z>o@;*Vd>dL)r9quGJ$>jo zt!2vkfX=*+C*|k%@J#K^u3U^8m@J$=-|*5Jyl~W&o&lW~*hlO91YXj$aC2yoQ){gn z`YBcwleIb4WXqE4OL&g;uw^O%k~>|q;mY@o5_vVuEnEMuaG#ycCPua1?EW6w+WOk) z^M)Y}_TGg#yegZou_4}RZo3-#kg4;==+AYU1tBorOB?%K-qJB|Tr22ISD#L&wx)O_ z;>Qk}Ub0vfow=$M-)%j5QcUMm1H%u9S9t{`D;1E}9}Rmz(4 z%iCSt3-a$bvrW%gcF(yi)|Tm+acZFKf7?L)u5$0vz{gm zhB~M6(E4lF;}5DpJt1etkIc=Kd%XfGymR%Zk6|RJ~9D*<;vc#kjT@iNJ*Y=;biWi0@lh)$sW?+ci4UM%iZFPv}28Em~yvg?qzPArOR@gZ<*T zJs0l7k8~`_y~^XdG}PM-{6UVZx&4i(bNDCYkcz>(xynC0OQEf@c^A6cd6-nbgg%U2 zw%x?hxwWft4Sis@d->`Ef2SLo)BX_CcgZ-H<*eK(#zpKqduCEZpJt~QMYe$cxc{s? z+`Olu--Ew6=W$C~k7%rp$cxgL$4hJ8sg_YUeCDW?`{+| zd8nAquVyu-chmRCTGw%&*yqBo=ktlU5d*B8+kFz#`4MT9IB1*-M+1~^+`hhfaAAu7 zP_g-B*E4n8)a+qak8X86`wiRR@)ceb!-r3`YSTVPo+#GUmaY3jwpQo@)&}zUhcY;~zBtfIr3!d(#uff1BS9 zKUiiwF#PF+Z_2M10MF{+6)-WZXx$Ou+CiQf<2)*DWugAdySwKF{`szf0dQ|x?RB6} z#KvC0Cr^?wom_a$<^k{*d((zbaal1p7i@R5w)LLkVDG;leM?0)z$*02bl^G%TRYEO@$_q3(AnkpZsg1lPp3@)d8-c%r%qS4+|>;_ zJ-juiaN+|Gha!-FZlI+a9QJyZA|A}V&dsK~M690z+`Grn1A&*KMgS?P+mF;?$yicD zqx1$@%bbUnZ-c%`OSXH%_l6f9bZ7}WCvG;M9{%CI;}$V}Ze-rX)pXIqk z(N;R?2>tohG<p`E{smuG!wcBS0_FM>co(oM3i^-amm;hX6?BMcPI;?Pp zSX(RCjNYQU*TfrC@Vr3`%__SqHAioJC()pjS`K8ntozwte& zJS(WHSi2WWBhMbDLrqM@b+V4sx7CKI)8m$(#x#N$OIuKFn0!@#?mf zcBT`IMQ2>bO?W!Zy(4fRrylR`Jm~Dp5o^o;d1l!C9a||csE6CquE+gLr$=Q14_7v#J`eSL`}$H&O-nUj z&mR!{zR<(d1HPwbl|S};D9lU8&#+EgzP0T~pMtGZYiRdq=*qCq56;Lf1RXEa&_(4d z>=JEi_`YX;w)^pI=)TU4>M@%pFN4Z|7AAYEfo)?~dEK9{KN%xvH~Wtf;i&VTr(J;S zszgOo;rCV#gFY;IJmr?mceTn+;%#|e-XQn=V7jx|oIj82H%8&${%sw_yF;!W(o=c*W%yW-yWc23t17c{&Qah^kKCN9-p0*X2`W*X zt7)m;bZ+=!vHEpKtT)q2=%*b4aw;q_N4vr9_+?OMpwW3l?VAym>wtGTccPK5&ZCC+ zfjn$h>5&Wy22>-6S~S#}LRFaL=&Pp5cGgKbbx-18=;oHkD<$$`$B#Gi9H z4I1=o3G!)0qi*Vbl!kPAQbMAXDXv^t{qpeNcNcfqn>lHqpONR-pBve;pgrh+ zZXLhTPAC2Qf*RTttE$%Q)c;r9dw?~uZf&4W-Xw$)gfw~y1duAy6;PBWidYdlA|Rp& zieg7pz>cVh6~TgC#NIpD!3tLFg1z@TcLmScCp+ip-TOcPfA8nxWX+m))$dy?Gea^t zIOB3--w(?@)MCFJGoxvf8C@nj(VAI1I#A^1YaUodcITJA^>lZfKV6sT-CgE>@_1|T zqSgPvpO5dS?rdtE^(35PR2|FX){gMaTUj|t%^y|Fujn^A-P{6JMpgU&McKlc=hg;| z-57s@{Qqj%aC7jWF+*FBtnQupM?y09L@2*#-tk;$^UxU%UxpDTVtA`lp@CT?M~U`Y zIc8|E!ZfZTy zbdht;bl}1IvzF%T@EaQ)36Cq$LY{=)0N?_HGN(89a7R$Vc+La%9WGfOHzIs#)Bh1A`Q`(N2u{7@i#l^ARHEZOhj7KHpL*BlndZWq)?5ZVt zPRw4bapLgPbP@u&A27n$p;@P7CkpR+pIR?jv0GSiM?{MC@O zZS*W3&D!53{j!iJZu!H8Z0bNdFIgR5o!`@9+a;p!qH|rAN z7vz19*tYM~8e6rxHmrFn*xA{jVxF4aUxgNX^RoWlo}L9IgkNaeMSt(x*H@Gu1&>Kg zci#W?y7#JI399isE$ce;aO?(46XN%q-pv1S8C%|u^rY-{`FM1Y?VUR`*P*r-(LuWvbC~k0EC+#tN2q`i=hPHxqNK$F}!!{0&A;?H{{6*DZQ-J<~{jK~46?F`rE} zW3S9OOi1bKy|Zqfv8%15dJ z*7_;Y59f_N{y@9%Wdk+Ym9EbB9=BalP2cMNOXI2jmQH&}@b(dl-fug1%&Q@O^dR}1_kkAWhlu{wSkZlD z-lzLp@AM|X`EVWMPi2nlR{jc1{H@D7MSOFgUjHcZt9-MdUNW-UfX@a7 zjP<2hs*_rcV}~iY2Y;iJ7ci$9*1i8WZ&&A0qhJD$7*E-cN#`MK9sEoI%#TwI^d+$$>e#5DYc@|aA z=@}UG+1jU-`j*?bwWwCJ8{nBa+p55KDu{nfCuOj;POtg#gumvzYxGAt z*gSL5QGS4XXU3~8wu+X|y$LhD)ZE*y=FXu?qRpDG3!)$V>Gz80>X8i>*;kZw8cOtw z?9uNVby?avhGaG8wSR0|(cnfr(LX*%4{^vkcjY$acJ|JsX%6A1>V{Cfoo#n6aCvb2 zur0|Z_jO3Ko+pnPNcR>-^u*O`-`iHSUerddz7hsp4RNp1pobpNT+e8` z*+cTttDzc()c(H?JKrU}nwI&-Q`5v4xjB2KCkIDXQC_8rgsjn$vhWNbl-1^@Q9$5rOu=?xA)*S?ZX|G%piV< z&sob3!)IsR&7%66Vl zIhiDCRMdCetr&CiEwBF-rr*2DwHruu&Z{=T{i<3oIHTszk-~x7<7>KZ|n0Ig;Ns@mPkO24yTDOuw@mx}-UctZG91_w0aABepvoI!k&wM4x?_ zrqk7@Df#x_jQs1)rs?wz%@V53_3?e}7G}(gUGVyMF*X(#Op4o@A4)!K-E7$~Gp<5# zm3)&fo|%;8m$7Y|($Cc?)3e{nJ4=ZEyCcf{bcgBR3iQvDY_Hk73TF)e{JAsvG1X7#q87_vv8y?FSNA;AD=WfC|JLC_v-6Tp z3Fnf|v`!6*@{7Aly8Om}#$$1(gWcXG77s`tfhxJ{hyC-->P=3sdDsLLcUd|UolwItJ{RpYB6SA4Y|I) zYI90DVG0iWg>NWWb~}PROPi_NV#B<`s^P!!^X-G0+)}?DFrzME?NkoX}*N%l7c%?Q_^Fy`{ZWxt2mN%Wy;f!Z zAJGe!Z*G2~m#J(z#n{q!|JoB3ts3r7^V8;0|LoK6?#&hwrk!YZ*69ax`nM)J?QTj@ zh0~i``Gg-ABe$#c7%+Dp@jEdC^3QI3b)qBD-_QC?IPKAH_cg*87{&Nh`t=AA{U%o_ z6BfH&@~G+SNx7XTb-Gqn9@6F$#a`Lr-rA~ygneQDrvwi!M!XU-< zlviCw?&wAQ{R_OyUKU(#Hdf7+s@*rj!#VFvhfj)9!*sKjxO^ygj5|*Jlh;rCe0)}1 zb(RFz&T?z?=>hxr9qCsc-4b>7ed+SJu$=fGSicotxt67yiSDo<>(IAw55Z@mH?X{> z-)H8zbtS<&3e!tJwtu=giReql{dazQrqTMQnh&b_RcZT)tGZTYq_>8A+c2RMVqsOY_yYPdc^H(O1pHLax=Sq&sZ-^E@nJTxB>~f4HIw2_Np7V3}S5F8p#6v6R1C_~c z6#JyFQ=k$#y(FCLiRu337njTy=6yMDdn`+V~0VB#0``l0D76)3(Cz2NmZ_{6Vnx|1;F z-aT*mWxID@Ony2PPAF)00Fj+3#!Rl~NT1r$&&!Bb9TzVY>9wkryX;bnD|q|*VL{bP zmbnqwHhstXAkVv(%1GAhLyxSG9U1@jba1O59fDfta^t>1-D-L(&dC|iv z8)&D8R&*E~9@$z==dX7Ad7snkB3vX*qnw;v+xkP~sv7=NwHQ@phb~U(-7Tl&&QLYX zp7G@dJ#N|!*+$^!nbJ!=s`qp$R~7vKk)H0~d{=^h^up(AKC8Nv^2p@mz?>G263X-K zs#ARj*1iesOSJETf;~yR@{=P;7HQYt4gUT{e-`omL>3#6PaP8h@Fc=Ipe}?(OH$Tm*Csdp06+$H2RU3GAPD ze#HCZo$rwkeG49bP4j;iy_)R)Zw-IRn70`>W3S&Mo#TE8`c61@*6=p@pgQK>eAjN$ zD$6f}iEo|NG9a`1(KTZN+|sNYnpv&?AVbL?6OfbjUL(1T=&O~z?I%g=q^&6@NiE$& zrsO}#o=pDF>ahCT)RMHrT4d|p$9-d_RStbnO#B?_qJ-(~BD?93&a1OsSItuuv`Dy+fDGo+Z6LYa+=`eA#5-tfkKbT*#J*?xPN~%{so56JC3xbmN>I zA3If$Kd(pngwClPv~7Z#9@QBCE`42Z!;eL2?czmhI_IbQ&RkO6uy+ypraCUY`r37= z^XsF_h+jB&NTb37=ZjaVVR{YN6t=8nTT&wNJuTK6E&m>Uy$>lFRZ{YLxpZ$?B*mgS z>NXc96u-|c(@@iM*7{QD>I2y)tO(z2?47XHs{+<6P{VYb(#CLIPN($t8op|pN1ePtzwtHbrJh`)c)P@^O5lHGJk zi8SKv-lLH-Vx5TI;?vTqESuZji0B)&bAKE)8>W{_bgE4{zdSOKb4JboXRVhyoj8_r z!jCYm+=@D%Nc%27LYS=no7~^bgrG<61c?wYYybUryV17VztOLXSEbLL`QZ5A{fkz6$$xQ|eS>R-yY?24 z4|9s#cy%|M>Sq$)UjLI*opX8V9^&gJG`wB6bZLPn`BQjb?p(_Y9NP6azNy+$rDx~N zIs2k_V)rd-vLW-*O<&m*Fy?A}RoP$B$IV9Xd2f?0I!-=+?0?knLrK@O6~6+j@kbB1 zp!nk7QoM*{!&iO$@U{1`W(U>g;?N202H#hCF5W^IlMLIz-?MpJMWkota1+>wHUKE+cx3NKQZtn>F+k&=?dSabf@88oYQvU zZfmtBFEBc*rc>3Sg;8ObgmrV5z5fkH6|YJccj(bubkMxlA(9=nF{YdN@_hfJ{{ua$ zIx8+DR2dy?*rPec`*%mpxZUr~cN#`)C&BWA4sI5OnQ^-Rr9Xey2ct{fKHHBdPV^zW zZM*03?SHTnKdAZOH*>6slS|BDH?=h&i{Qa~YxTD(o`SzN1_o*vs?m~D;Q|7);|K3O92%mQ~rDwBQOIKK{ z&BdOF>p%FJCw$pL{+D_u*ZI%trL&yqZEIxH{VvzGG$GmlFUR2>>$IPv_-<%wj*3ZIuc!ed|ZdNvhtAoYH_Lh+*`)o(LSQr zM}4(iMc;nRb{yYiSRaz@I%LG`j`M@>JX4#;gI#>4bop@OM;a;gYw|KN(k1=qB~|4_ z-(hQlqJAh&C;uPiN_@Rwb#!u>>m4=ydE%B6Vt#nbn~@K%9eoG(D~z>xM6pbl)kdI6^uTM9;j#UjJ4BIe$0N;3V!X!rO;yvQ7S12LdEE-46Zxj+HAv5k&0%SYE>B8V z5Q-ltmgBGcBwD3HXU5SSCduM6Lmt7 zHsx}_E3TTXDn`C(diwMaJ#)L0pR3#9%8bd4Bj2e4h|Vt`@+>E$Y=Ws8zxG+7ORjnG z=K#vpwliAKXMf0VZ%&x6F`F>kd_z!gwYpFf|6`ZgvtoC?*PdGp`FX+MOKN^yM7KPm zi@H5DSr9R0i~%8A>jt!2cx(N%!xZoMe%mfD((O574)O1$i3=BQs%mRSwm4rN4P6+a z*Nh%e`^(X3$2iZzI-^+!DBiz2ZpB2NTO$?O z(~19R`H|_XXO(QNRKo-hZ@6Hcm%E?kZyeZiuJ+N!S^M@5qIeJ3Zdtz3WxMxjHJ@w8 zzn)lnYp|Ui=`r5AeZ=M$qbefQZ2iW>e>}vU*S>V;ao!?A4UMmF3m+ax z{f(ZYgj@2DA)UM%lLLZ1P0oI@y>uu{O{c1F181b0f1M?;_aKb);wHOqAvM$JY0V9q zA1lcCo~(-uvSrCxa`wj$|Du&@v3GCXXl{etk6t43ZBS_idS2Hl=~nEBJZYuiE0H$O9NCbMhg!x`4*$2tSD!KQ?RKrxt0RRE=Tt{USeV_u_CHV_ zHgVsm&I>dq%~O*-{&5^Xvgoty3(c44!0DG=Z?|YYiZGXUxF>XNe>p+?7h_jb`~SL| z=Q#dN^qTCu`M=3koXwK~{TjElP9@*Q_DOVzJz?HtH{rQoza5B6&}!nS>~FW&De(=n zH2SNpx4SDsf)lPpJTFz_|H`qJz0PP4iW=A0{5SsmO1695!<-=*XAf^w1DI;HU!58~ zGJA)b51;z%eKOo&T8o)#wz6vTyN@W%Kl?(Bucr1t?k0vND#kVr8wARUWt_CbIEyuR zJpKoI{-bhY8Z0`wF_RT7dPcE)j;R}!mBHjpBl`V@%(s~d9rN0gt?ane9+&XwujE$4Rrl~LmN^1nDJ z=TOs)QKVD*;pmgI9zL`(Cwjx0Sp#xIo80vvjO)hSj2!PX+xrp!SHnvZTAeo~ZS%Un zxSnI|bG|NknDk?Sn!?)FQQH=UmR>jgjV-C*Y4d{ikA;D1vX5UaXjYifT{edD&?Bw9 zN0G(1aan{pWLkpicd5-;7PK{PojntAJRFp^*8>gx-odd$6@POv)a9+r*YWUZR>Y6Y_Wp;`PH~} zMpRp}>+!BOYWiPzh7B!^3R(G)WSiN?XlyQZkSri2t#!LJC{5Xt(UjI<2|uj&R)d*e z8k4MTYqNpdb}i|${WrE$eQ;!5-tV#-96XBfD=#&gxBFwR^**9g`=@2>n)1qSo7y}! z%d6bCZ`bnVBWnDfI!ntBG;EwTRaLnfU3%Qe=%r>8va+iT0+^=<0*=FMijg1$nG@h$;ph1YyF5HsXxX3)NOOmo@8tFvVFm)A0D%7 zOJHgE4z1H{>-7VOe=d5h->DN7wWo=e3d(O)HeBW7PqO|KQZ`kvI!%L!{@yNo$~lWR zdZ)?H=n?&$&tJJcr33LD&E6foko%>rMAd=+McTFH>yT@udg55JyL$4FwCh(Ek6fab z^O>nZTWU0#Eb=9Op^Mh|o8AUJ=l{kBS@iU~cUZ@s?bP)AO2n>Dmga*iSr&DKcN1%! ztbJMM%As8SYD~WF-sVxmwtmrSYcJ;Y)-F%hEO``3de-r#J$N$m9Oo73xly~|$J0Zr zo;s4kD>9pXG5AO0_yKil`n$M~AJNAxXlzH8 zW!upI`fZSpMtqQga;L3_*0{F)d4p~B>^nDcZk+B!ye?L(2OG#Hri6F!RbpDP3fjs? zusTh;db#!0NoHHq{)i}+9iu!P5@x4-VcC(a7TemH<*;KSf;*&|NSm>2KW&!nBywpv zRxgkM!;~oFU>`GjNmkM>iL8H|&4@@Mdn@;8=#Dm!u&iPGD+p<}Z5z9KTtd~*)jR9Jx&_*|4XT$gWUU24wuNQyu91O)R$W*RyM$1%EjqEid=vV#rTmf?>8ukQKBha% zhH9EBg~aueUF)~BvF+TPWruin9i_uX)L2R+JJQ@TfMs?1*CRY>>(-ApLk24M`%7EL zB~Wfz3pT2I8i!?jj#aYRaWqxR*JkXncsF`&@RQBT*`eu;?VAwCkgGiYuMwE4)XEO& z9RCmAD0|BYmZlStTKycxTN1Y!+kp*puRq-0gH>{9@L5*Nm6iF_?-0+N)gj10DX9-( z*_h#7$2qbd{YIOowH8U+ikiEJ#l?(k)=3)D#WjNtPYV+6zR^tTWruht*|=y0ateS123P&&0WBgmR6rY!8<8)a%anvTedP za7|@9bgt*JtQo6l#IjL?6KEOqq=-0_YPs@QW8u)y@oZ1FJuTM0F8;z`Res2XB$%hY^%=orXvOsnAPhyBo4~iWd|uYdP*0ST9jmPs(TOXmfozdP%)BK zIx1;Hn>MmAn&lz1Gy*kQe_AeMGl<*5$)2GX&9d4ok*>R%wkWjyVl?P1& zSnm{4+QMdB7r}U|hBO7#2H2k!M})Qp+uA)PEVh?5%evZlw$%&BAg*$FC(%ZsX~=5o zIfR;;^`Pd`l64z6oNXV)HA+^{L53Y5Ypg86##EQAaT+^#NMZ!5bR{WpJZ1>!^Y}aj?iRT7}g=GpT*!dL`O9q5NiQ@{wUVmEKbUfAFnKM8p>nTQI#8IV*il` zL4C=$WVIE_)uS9ksEHXGLRs>(P-yg}a<*WV`DZ=ppmKzVg!Sp)p)XZOSN$P9ShgGS zGN|2ATh(sfq+@!EK7EOkYC(;i?WolvokC-+^u?^VvNJU4A3(cf*e=H6$W&8PL7)xo zDu<>o8%}emoW_QR%9cEwNu$?6ZFLoc+R*g)iCEUggH?b3r%y6APEAP}-Z-LVV05db zl-NPB17Z@B8z;xaIuA}u8lLDpFfBE4SX^T4@Whnl#=}x$8z&|9b4eX`q=DtEk3r#0 zN4)i3kaMYEQon*le?A+by|=QrvJQ-mM<>RL8`P33=@i~NfRTw!jrC+=3DdVtLZ2SK z{=tk;N5tsZ`uI4QdAl@nHPg0k%x84uuI}#iVxeeh@8InClV|N7;mJSAc%vEo5r9C1 zAPnJXk4}h0FGOP?24e_DV;nLti9t4lsSIW?pdW;r%OIb@LIz716f#)OpqRlL23r~I zV6dCPJ_ZLF9AQw--~@xy3@$Uc#-N75Z3g!k)G~O);3ye=IVj~|D+lyb#=AM#$H74kj&M-U!3hpd zb5O~_c@8ddaF2sp4jysvl!NyieB$6M2R}HN2xI|MfayREFdN7N<^zj>0-y+30jvVn z0vmu$z!qRTunX7=8~{!Lr-4e~Ja7rP3|s?hfZM=5pcZ%pJOy3=uYq^KN8k(a9hksH zCKr>rn8rmO7xTGT#6`lVigx_x!AzPCN8#cv7L)uT`j88Xb0VU7&*WLPZ2QW=)Xuu_KAGOUwf zqYR}oY?VPKyFS4pW2|nEwVn2P4$GaTT)Zv*ZYikN#?P7FfI;^g$>gx*qV{q+431{JwD@Z;}^>3Fg~u9CZ>qxV}*&4iNmJPjl!7N*u(e8$e*UwPQ7nJe*4O)MN0#B}a#*-R@S zKugi8A)k?kSo0Zq3lmvO13u#ytFRPm z!3Q0D*1a*eS#wA@&P#NQk3CycGUx?SB>GM|}mX(ZzaQ zl;~o!F1G1nr!MyBV!tjP>fwnVp6lV29^UHVgC0KX;hP>5v#R#mE(7t{C}ZEEHpj7=>ai7o%8=HDat6qeP6^QshZ7Uy4Oi z6i87d#R@4_NwHRn4N`29Vv7`qWhj&3xD2OcsF2~D4CMwmVSv*Hs5HQN16(q|WdmF@ zz!yV&H^c-ZWEz1r!X#s48)K?5W*B3ZG3FR!o-tmU;Ef61o8XfPzM9~N2_~8%%M?>g zG2Ik7rkHJtJX6d!#UfJ_n4-uOkIeAY3@^;^+6?c^@X-uk%<$a|6U>omj>+bjW{#QW z$Ti1YbL5+2p*fbAqmVe3m}`kemME}9ktHfDan2GKEm3WWLHkAz>g#oV{b)|4vG=%-kA5U)Do*dS=_BQ=+x%#+ebIWE8!#D;rHuj8x zuW<_97f;J%tCHU|Lo=VUX3}7fxEe}qk}`Jvy-P|Ln>>zgRz%`ql*jex-0iR z6hHra1qM^O8yH$TJKLEU+He?aBU6!BpI*&0b+mNpkZBux4kI%$@=-PtMMp>jlSPU!$mH{h)IsrBcP%6My0d@$mTY!B692DRPH8w45*1|R|?9{>@E$r9AAuSZ^V2uve z>!3sjn{}{F2Rn7JM+Z3~%oZU}g!v*Y5}`nZA`w=Iuu6orB5V+0lL%Wx*e=2@5zdQo zNsP;4Toa>4jN4*-GXQIVNruQa#8gAfFvJ~W+&4y@F&-P^8I`Xw-WcP(F+Lgpu4Gr3 zVilFIHHxgU!WyfrvDO+JtdXa{d<7OMP@q7O0xJ|)rNCMRHYl)30fj;M$Bvc!MR9?f zKM#JyDxZVUAo%YVWo&B7uwl{v{*K<_@(#^v?U?@K1?5*ZHH%e#Ip@!#LQ$b8Vi*rE zWp#QscD1uNG;}s}c9*-$Ee)j-b5jl@m)kUI97I**+NvFuiNsYdl1iQFpRrF$H9X7li%+gOaL;0$-p#VCXicSmIr|&KzaSy z=pQGQGyi;&SjEK^F0ONNlZ!iC+~=Z>i^p6%7UfZ8BLtk#05=MY2u0|u503^ChlnBz9#B4F%%#0zDMzVTB%6>0zxNHt1oK9=7OV zyB>DwVXqzz=;5*+uIZsh54ZJjPY<U!`k1MYTz$;d#}<8T*T*h>?A1rLKCbHH zhCXiTC3-D#kG}PKt3x zjI&}~5Ti}=g z*dW0f3C>DzL4qm?u1IiQf}0ZDk>I`rbrL+5;F$z3C3qvjdkH>CuuzI6QWQ$DT#8~T z)=05liV`U{OR-Igol@+PV!squrMMx*Eh+9w@j!})Qaq93xfHLYf4cZkyRg_n7asbtZUhf@dawIw_iLiD~ucE%}yMXo($`*lme@ zmN;mMBbF$)#7Q~M$Z=MV3vyJ+aYc^na@>^TjvV*psFUNd9M9x-!F8adXOO)c9R<=Lmd z-Rw2=v9YxF-N40~dz5`M@bC8J)c9d3X{oXC(ZdGBq$VaO{5)scqwi!tAVgG@`g~({ z@Lr#Be{RXNx7=a5Ln*_!xzcr(J!9!=V((|@XyRz@NbOkaV`E7-73dPluJ_LqA$xlp zhep(3t&L43#s;Rw#)gI-^t&C5B*MVds*yrruRNQIuxO@b-^IcrKudW=Wj@$Gf-d8N zBceJQXfv(ovP#~~icW<5+%0YVJGM767B#dtP&Rur!!T;#&c-4iQsV64-PFq4MM?(@ zP3$e?WRkkRm|l#ugu3q-^}8C~&=Y-7&EP778w_qSxXa)HgNF>BFnCUPA~<-*!AB0h zaG=_8>FxlX|NPNt|KnxtoZO z``-b59M=C=8@nh%wFp;5m>@=`7?Z{7mrWHCoRi?91l1B;rG_NMO)2h3abJo$DIQDl zj9QKXN(`{w0J{vZ*8m3$@YVz$Oz_zR-%P-oV3H}aO)=FJ`DR#Xh9zbwG{bT;6q{j< z8P=Pj#0;Cw@YM`I%rMa$S>~8xj_KyeF{h73BhMW3&9TTF1?DI+$0kc``EyH9tN4>v zIAevgR=8k=Dl1&E!gVX$w89-L+_yrV6&_pR88rh1W-G8zfh7v;R$!k32NgJ?K)C`Z z6gaIwr2^*_xTL^k1+FR3Ht%bC#r5Mc(`E)5?;qS!rYzK^f42t=NlHsd{KwVOz_ks0 z4!#d>@%+Q7!)1Goln+Sy^T;vIF`mLOjpz=GJ!9r1HI-UeTe`M%4R!FMYBUa{jfsJc zvKIBlX3kdT&YiRzl$S9b-RMS$rxjJEC7m!4%G9|28i;ED=amiJim@_rrouI~w6rj# zZb5fioJfzmL@bw^iJYx`{j|Ll3NI&P9WjY0Z>MlpFkblA_0Z3ID$5wGWU!jSItCjV zl>YN3Bvtb(20zcP3OQKLK`{qw{_X1LF$ej;LSP9{2rLJRfi=K-paj?qYy)-zd+5Zg z{(c>uTIF&vmy3KZ7ILwKi$X4zb5YF28ZOpz@tunaJY@1PnTKgS%;X`Lhq*lD^RSSI zB|OydaGQsFJk;{=h${P^ReP=e_R4Jy+|xj<1|CrzYv6?jUK6c}roY!AuEq zC73HgKAizbutb7F364o|Qi?NDoR#8&6jf4Ok^ZS(=gY82h5{LiWLP1?DjC+wutA1R zGHj6{{!-?nDap)(jRSJq4XrVFtz3zJ`z~T!T1--OYJ6;b;*jD0cz1K3ZECf0>_d;e z)2?rcZW!?A1x|bWH1}!xGA;_nKyFS8(Zq!Am3tV|TTsWAwDRog*RPu~z12xfT=+~A z8#-djXKa+$==F=+@t;@dKUbvc)j%GD`3x2@C}2>;;OEW1|9Dxwnr<}z_Uv2j(s=%Z zW5fD?JN;ynz1EGXrg80*QT^?ECvl0xVpB%Mr;h%aDfUr+zHSKTNUz8fFJy0;ZuqxM zz0!WA-GXtnW2hIHSW@xIOze&6uBy~TS?*qx8AV4+<-50?LjYw*UY|N+8@i8b;ZCVD zZ{L>B@l>zii43wBOkpscK@Nl241Q)!^{)BPx5*b=yyoH^7azI!^3PIJz4(93$1^@& z^6`d`_k4Wfqe6gl0$dcJT7atp+z{ZF0K2rXR|^NUK;Nt{)538roYF$Vp6pNVOT2|^ ztgF7aZ5gY4PF@55zuQ|Al-W#RxXr#bA2l_LsQDWrMI=z zk+5=8v6WdvFK;~=UB#N~X!Dtdk>QPGHv0Bj4xzrC>Go19)xY(q|6OMmgPRQQFu2d4 zj=^IF<R9@P@&A2A>$PjPma>s=5F7Hg`gR(*jfqa9)5*0$djSU{65Bm75k8k>5^)X3=d15ROW3d=Z#aJfBN-)!#OQ^P;$!1Wap&B zmU+DgH&*BI@9>v+iGq!2Gn^$a{ zkE^FgysP_>gwlA!W`e^P>AOqHxs+8*7S_)xQ!JoYW^TCFamNNWQ|~H2_>@wAqybaN zZy>lUplySxAwOA2Zh&OvmxE4ocz1ZjyJJd!KBL$9^kK9H%rkxi<`MrHpGkYf=RM=6 z@ecC~tawlPhb@`Af(3N)z`rZNT|v2oHY@4b63YMo7<8-w{ij394GGs%1xlH63Fj$o z=$klntxV1|xFX_^Q=IGk{W|ou8f6^Hefl&#?Ka@tR=RRflMX8(%EQ}*q>q>dRkp=;4IAzppB(4hKQSr({{c5k+sps} diff --git a/nac-multi-jurisdiction/target/debug/deps/libserde-da9421d1cd90f871.rmeta b/nac-multi-jurisdiction/target/debug/deps/libserde-da9421d1cd90f871.rmeta index 931e42c7a94e2408d0927354abe06f340f95b890..c55dff5093c5974fcc77435e4cd459a692ef6975 100644 GIT binary patch delta 164 zcmX?hT>j#5dCsEJ;t~c12CjD-IsY&VOgy#ksj|l6lF+82?He|`^)-vKw2QJZ0x=U1 zGXpV*&kDqB+eKN}Gw%rI>!&1^BcR?-Y+2YqvvdZPh?|x_x+=~ znV(lqzi^X1YI^NM_GCtb=?@>W%L?RH$Gw>stl9LH+oILIqqbl=-y?Qi#+}=39jW`dCsEJ;t~c12Cl~&IsY&V6q>%jdNJUs+nO+4qk^9=+M7jL+C^CyftU%1 znSmI@X9Z%m?V>E~nRnPy^o#QIOQ!cfVDA_3F*%hgb?j&6h7;XP5i6qIr(d|q9yPt= zA$u~T>hw1c*<}T0%>Sric~9?%*N;0p`{nfZO_zMcuFJS?yZa;dLPp8e7np%gfdG)Z NbW`(Ebkj0(QUUV*Km-5) diff --git a/nac-multi-jurisdiction/target/debug/deps/libserde_core-c45b4833e4cd2ced.rmeta b/nac-multi-jurisdiction/target/debug/deps/libserde_core-c45b4833e4cd2ced.rmeta index 0622c2e94901a8551ef05cb76790250f5d933c08..b3cf195e4102cbca94208ad8de4448ddd11af0b1 100644 GIT binary patch delta 243 zcmXAkJ4?fG00$Ev)vHER-}P0sYX3_q`U#xuF6ba4#I|Cvv`~`{ZVJCu=#<4p99#vF zf{2@ovtOWtqacEtgDD=|bkjY3-Po_OG{UpMvaDq80%40D(JT5yzetDyF(~4c6hmTI zIATPM3Rk4Wm>3rmVp2?rX)z}AUyHUv({hWhfBnAytj><}TR-p)qfTh{+}7L6N7md1yO)jj{loTERBW0} c`@4PKGBG|3M z5R*+14T45(E_~^G{J9PuTBsz|S|*bT^JhpPZPG3s(kWT#l5S~LC_U0EebO%j63L(p z$*_#bsEoY Result { - // TODO: 通过 NRPC 4.0 查询当前区块高度 + // TODO: 通过 NAC_Lens 4.0 查询当前区块高度 Ok(0) } diff --git a/nac-udm/src/l1_protocol/nvm/mod.rs b/nac-udm/src/l1_protocol/nvm/mod.rs index 4ef4d54..76854fe 100644 --- a/nac-udm/src/l1_protocol/nvm/mod.rs +++ b/nac-udm/src/l1_protocol/nvm/mod.rs @@ -62,9 +62,9 @@ impl NVMClient { Ok(Self { rpc_url: rpc_url.to_string() }) } - /// 发送交易到 NVM(通过 NRPC 4.0 协议) + /// 发送交易到 NVM(通过 NAC_Lens 4.0 协议) pub async fn send_transaction(&self, tx_data: &[u8]) -> Result { - // TODO: 通过 NRPC 4.0 发送交易到 NVM 服务(端口 9547) + // TODO: 通过 NAC_Lens 4.0 发送交易到 NVM 服务(端口 9547) let _ = tx_data; Ok(format!("0x{}", hex::encode(&tx_data[..std::cmp::min(32, tx_data.len())]))) } diff --git a/nac_wallet_service/src/handlers/bridge.rs b/nac_wallet_service/src/handlers/bridge.rs index b44be59..38c622e 100644 --- a/nac_wallet_service/src/handlers/bridge.rs +++ b/nac_wallet_service/src/handlers/bridge.rs @@ -315,9 +315,9 @@ pub async fn initiate_bridge( "description": format!("在{}链上锁定{}个{}", body.source_chain, amount, body.asset_symbol) }, "step_2": { - "name": "DHC委员会验证", + "name": "辖区宪法收据验证", "status": "pending", - "description": "动态隐藏委员会(DHC)进行多签验证" + "description": "各辖区节点独立出具宪法收据(CR),参与即是共识" }, "step_3": { "name": "目标链铸造", @@ -388,7 +388,7 @@ pub async fn initiate_bridge( "to_address": body.to_address, "estimated_seconds": estimated_secs, "constitutional_receipt": constitutional_receipt, - "message": "跨链转账已发起,资产锁定中。DHC委员会将在链上验证后完成跨链操作。" + "message": "跨链转账已发起,资产锁定中。各辖区节点已出具宪法收据(CR),跨链操作将在双CR确认后完成。" }))) }