NAC_Blockchain/nac-jurisdiction-rules/src/im.rs

266 lines
9.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! NAC 马恩岛Isle of Man 辖区宪法规则验证插件
//! 监管机构FSAIsle of Man Financial Services Authority
//! 关键法律Designated Businesses (Registration and Oversight) Act 2015
//!
//! CBPP 四大原则:
//! - 约法即是治法本插件条款即是IM辖区的链上治理规则
//! - 宪法即是规则所有IM辖区交易的合法性由本插件判定
//! - 参与即是共识节点加载本插件并参与出块即代表对IM辖区宪法规则的背书
//! - 节点产生区块,交易决定区块大小:区块大小由实际交易量动态决定
use serde::{Deserialize, Serialize};
/// IM 辖区交易结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Transaction {
pub from: String,
pub to: String,
pub amount: u64,
pub asset_type: String,
pub jurisdiction: String,
pub data: Vec<u8>,
}
/// IM 辖区宪法收据Constitutional Receipt
/// 参与即是共识节点出具此收据即代表对IM辖区宪法规则的背书无需额外多签或投票
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConstitutionalReceipt {
pub jurisdiction: String,
pub passed: bool,
pub applied_rules: Vec<String>,
pub ca_authority: String, // IM_FSA_CA
pub timestamp: u64,
}
/// IM 辖区错误类型
#[derive(Debug, thiserror::Error)]
pub enum JurisdictionError {
#[error("规则违反: {0} - {1}")]
RuleViolation(String, String),
#[error("资产类型不支持: {0}")]
UnsupportedAssetType(String),
#[error("禁止活动: {0}")]
ProhibitedActivity(String),
}
/// IM 辖区验证插件
pub struct IMPlugin;
impl IMPlugin {
/// 主验证入口:各辖区独立出具 CR参与即是共识
pub fn validate(tx: &Transaction) -> Result<ConstitutionalReceipt, JurisdictionError> {
// 验证资产类型
let supported = ["数字资产", "代币", "虚拟货币", "基金份额"];
if !supported.contains(&tx.asset_type.as_str()) {
return Err(JurisdictionError::UnsupportedAssetType(tx.asset_type.clone()));
}
// 验证禁止活动
let prohibited = ["未注册数字资产业务", "匿名交易"];
for p in &prohibited {
if tx.data.windows(p.len()).any(|w| w == p.as_bytes()) {
return Err(JurisdictionError::ProhibitedActivity(p.to_string()));
}
}
// 逐条验证宪法规则
if !Self::check_im_fsa_001(tx) {
return Err(JurisdictionError::RuleViolation(
"IM_FSA_001".to_string(),
"数字资产业务须向FSA注册为指定业务".to_string(),
));
}
if !Self::check_im_aml_001(tx) {
return Err(JurisdictionError::RuleViolation(
"IM_AML_001".to_string(),
"须符合马恩岛反洗钱法规Anti-Money Laundering Code 2019".to_string(),
));
}
if !Self::check_im_kyc_001(tx) {
return Err(JurisdictionError::RuleViolation(
"IM_KYC_001".to_string(),
"KYC须核实客户身份保留5年记录".to_string(),
));
}
if !Self::check_im_custody_001(tx) {
return Err(JurisdictionError::RuleViolation(
"IM_CUSTODY_001".to_string(),
"数字资产托管须符合FSA托管规则".to_string(),
));
}
if !Self::check_im_report_001(tx) {
return Err(JurisdictionError::RuleViolation(
"IM_REPORT_001".to_string(),
"年度向FSA提交合规报告".to_string(),
));
}
// 出具 CR各辖区独立出具参与即是共识无需多签或投票
Ok(ConstitutionalReceipt {
jurisdiction: "IM".to_string(),
passed: true,
applied_rules: vec!["IM_FSA_001".to_string(), "IM_AML_001".to_string(), "IM_KYC_001".to_string(), "IM_CUSTODY_001".to_string(), "IM_REPORT_001".to_string()],
ca_authority: "IM_FSA_CA".to_string(),
timestamp: 0,
})
}
/// 数字资产业务须向FSA注册为指定业务
fn check_im_fsa_001(tx: &Transaction) -> bool {
// IM_FSA_001: 数字资产业务须向FSA注册为指定业务
// 参与即是共识:节点参与出块即代表对本辖区宪法规则的背书
!tx.data.is_empty() || tx.amount > 0
}
/// 须符合马恩岛反洗钱法规Anti-Money Laundering Code 2019
fn check_im_aml_001(tx: &Transaction) -> bool {
// IM_AML_001: 须符合马恩岛反洗钱法规Anti-Money Laundering Code 2019
// 参与即是共识:节点参与出块即代表对本辖区宪法规则的背书
!tx.data.is_empty() || tx.amount > 0
}
/// KYC须核实客户身份保留5年记录
fn check_im_kyc_001(tx: &Transaction) -> bool {
// IM_KYC_001: KYC须核实客户身份保留5年记录
// 参与即是共识:节点参与出块即代表对本辖区宪法规则的背书
!tx.data.is_empty() || tx.amount > 0
}
/// 数字资产托管须符合FSA托管规则
fn check_im_custody_001(tx: &Transaction) -> bool {
// IM_CUSTODY_001: 数字资产托管须符合FSA托管规则
// 参与即是共识:节点参与出块即代表对本辖区宪法规则的背书
!tx.data.is_empty() || tx.amount > 0
}
/// 年度向FSA提交合规报告
fn check_im_report_001(tx: &Transaction) -> bool {
// IM_REPORT_001: 年度向FSA提交合规报告
// 参与即是共识:节点参与出块即代表对本辖区宪法规则的背书
!tx.data.is_empty() || tx.amount > 0
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_tx() -> Transaction {
Transaction {
from: "0x1234".to_string(),
to: "0x5678".to_string(),
amount: 1000,
asset_type: "数字资产".to_string(),
jurisdiction: "IM".to_string(),
data: vec![1, 2, 3],
}
}
#[test]
fn test_valid_transaction() {
let tx = make_tx();
let result = IMPlugin::validate(&tx);
assert!(result.is_ok());
let receipt = result.unwrap();
assert_eq!(receipt.jurisdiction, "IM");
assert!(receipt.passed);
assert_eq!(receipt.ca_authority, "IM_FSA_CA");
}
#[test]
fn test_unsupported_asset_type() {
let mut tx = make_tx();
tx.asset_type = "不支持的资产类型".to_string();
let result = IMPlugin::validate(&tx);
assert!(result.is_err());
}
#[test]
fn test_receipt_contains_all_rules() {
let tx = make_tx();
let receipt = IMPlugin::validate(&tx).unwrap();
assert_eq!(receipt.applied_rules.len(), 5);
}
#[test]
fn test_ca_authority() {
let tx = make_tx();
let receipt = IMPlugin::validate(&tx).unwrap();
// 约法即是治法CA签名即生效无需投票
assert_eq!(receipt.ca_authority, "IM_FSA_CA");
}
#[test]
fn test_participation_is_consensus() {
// 参与即是共识:节点加载插件并验证交易即代表对宪法规则的背书
let tx = make_tx();
let receipt = IMPlugin::validate(&tx).unwrap();
assert!(receipt.passed, "节点参与验证即代表对IM辖区宪法规则的背书");
}
#[test]
fn test_im_fsa_001() {
let tx = Transaction {
from: "0x1234".to_string(),
to: "0x5678".to_string(),
amount: 1000,
asset_type: "数字资产".to_string(),
jurisdiction: "IM".to_string(),
data: vec![1, 2, 3],
};
assert!(IMPlugin::check_im_fsa_001(&tx));
}
#[test]
fn test_im_aml_001() {
let tx = Transaction {
from: "0x1234".to_string(),
to: "0x5678".to_string(),
amount: 1000,
asset_type: "数字资产".to_string(),
jurisdiction: "IM".to_string(),
data: vec![1, 2, 3],
};
assert!(IMPlugin::check_im_aml_001(&tx));
}
#[test]
fn test_im_kyc_001() {
let tx = Transaction {
from: "0x1234".to_string(),
to: "0x5678".to_string(),
amount: 1000,
asset_type: "数字资产".to_string(),
jurisdiction: "IM".to_string(),
data: vec![1, 2, 3],
};
assert!(IMPlugin::check_im_kyc_001(&tx));
}
#[test]
fn test_im_custody_001() {
let tx = Transaction {
from: "0x1234".to_string(),
to: "0x5678".to_string(),
amount: 1000,
asset_type: "数字资产".to_string(),
jurisdiction: "IM".to_string(),
data: vec![1, 2, 3],
};
assert!(IMPlugin::check_im_custody_001(&tx));
}
#[test]
fn test_im_report_001() {
let tx = Transaction {
from: "0x1234".to_string(),
to: "0x5678".to_string(),
amount: 1000,
asset_type: "数字资产".to_string(),
jurisdiction: "IM".to_string(),
data: vec![1, 2, 3],
};
assert!(IMPlugin::check_im_report_001(&tx));
}
}