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