218 lines
7.0 KiB
Rust
218 lines
7.0 KiB
Rust
// 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());
|
||
}
|
||
}
|