NAC_Blockchain/nvm_v2/acc-protocol/src/acc_insurance.rs

621 lines
18 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.

// ACC-Insurance: 资产保险协议Insurance Protocol
//
// NAC原生的资产保险标准用于风险管理和保险保障
// 100% NAC原生协议不是任何现有标准的实现
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// 保险状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum InsuranceStatus {
/// 活跃
Active,
/// 已暂停
Suspended,
/// 已过期
Expired,
/// 已终止
Terminated,
}
/// 理赔状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ClaimStatus {
/// 待审核
Pending,
/// 审核中
UnderReview,
/// 已批准
Approved,
/// 已拒绝
Rejected,
/// 已支付
Paid,
}
/// 保险类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum InsuranceType {
/// 财产保险
Property,
/// 责任保险
Liability,
/// 信用保险
Credit,
/// 智能合约保险
SmartContract,
/// 其他
Other(String),
}
/// 保险策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InsurancePolicy {
/// 保单ID
pub policy_id: String,
/// 资产ID
pub asset_id: String,
/// 被保险人地址
pub insured: String,
/// 保险公司地址
pub insurer: String,
/// 保险类型
pub insurance_type: InsuranceType,
/// 保险金额USD以分为单位
pub coverage_amount: u128,
/// 保费USD以分为单位
pub premium: u128,
/// 免赔额USD以分为单位
pub deductible: u128,
/// 保险状态
pub status: InsuranceStatus,
/// 生效时间
pub effective_date: u64,
/// 到期时间
pub expiration_date: u64,
/// 创建时间
pub created_at: u64,
/// 更新时间
pub updated_at: u64,
/// 保险条款
pub terms: Vec<String>,
}
/// 理赔申请
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClaimRequest {
/// 理赔ID
pub claim_id: String,
/// 保单ID
pub policy_id: String,
/// 申请人地址
pub claimant: String,
/// 理赔金额USD以分为单位
pub claim_amount: u128,
/// 理赔状态
pub status: ClaimStatus,
/// 申请时间
pub filed_at: u64,
/// 批准时间
pub approved_at: Option<u64>,
/// 支付时间
pub paid_at: Option<u64>,
/// 实际赔付金额
pub payout_amount: Option<u128>,
/// 理赔描述
pub description: String,
/// 证据哈希列表
pub evidence_hashes: Vec<[u8; 32]>,
/// 审核备注
pub notes: Vec<String>,
}
/// 保险错误类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum InsuranceError {
/// 保单不存在
PolicyNotFound,
/// 保单已存在
PolicyAlreadyExists,
/// 理赔申请不存在
ClaimNotFound,
/// 理赔申请已存在
ClaimAlreadyExists,
/// 保单已过期
PolicyExpired,
/// 保单已暂停
PolicySuspended,
/// 理赔金额超过保险金额
ClaimExceedsCoverage,
/// 未授权操作
Unauthorized,
/// 保费未支付
PremiumNotPaid,
}
/// 保险状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InsuranceState {
/// 保单映射 (policy_id -> InsurancePolicy)
pub policies: HashMap<String, InsurancePolicy>,
/// 资产保单映射 (asset_id -> policy_id)
pub asset_policies: HashMap<String, String>,
/// 被保险人保单列表 (insured -> [policy_ids])
pub insured_policies: HashMap<String, Vec<String>>,
/// 理赔申请映射 (claim_id -> ClaimRequest)
pub claims: HashMap<String, ClaimRequest>,
/// 保单理赔列表 (policy_id -> [claim_ids])
pub policy_claims: HashMap<String, Vec<String>>,
}
/// ACC-Insurance接口
pub trait ACCInsurance {
/// 创建保单
fn create_policy(&mut self, policy: InsurancePolicy) -> Result<(), InsuranceError>;
/// 获取保单
fn get_policy(&self, policy_id: &str) -> Result<InsurancePolicy, InsuranceError>;
/// 获取资产的保单
fn get_asset_policy(&self, asset_id: &str) -> Result<InsurancePolicy, InsuranceError>;
/// 提交理赔申请
fn file_claim(&mut self, claim: ClaimRequest) -> Result<(), InsuranceError>;
/// 获取理赔申请
fn get_claim(&self, claim_id: &str) -> Result<ClaimRequest, InsuranceError>;
/// 批准理赔
fn approve_claim(&mut self, claim_id: &str, payout_amount: u128) -> Result<(), InsuranceError>;
/// 拒绝理赔
fn reject_claim(&mut self, claim_id: &str, reason: String) -> Result<(), InsuranceError>;
/// 支付理赔
fn pay_claim(&mut self, claim_id: &str) -> Result<(), InsuranceError>;
/// 续保
fn renew_policy(&mut self, policy_id: &str, new_expiration: u64) -> Result<(), InsuranceError>;
/// 暂停保单
fn suspend_policy(&mut self, policy_id: &str) -> Result<(), InsuranceError>;
/// 恢复保单
fn resume_policy(&mut self, policy_id: &str) -> Result<(), InsuranceError>;
/// 终止保单
fn terminate_policy(&mut self, policy_id: &str) -> Result<(), InsuranceError>;
/// 获取被保险人的保单列表
fn get_insured_policies(&self, insured: &str) -> Vec<InsurancePolicy>;
/// 获取保单的理赔历史
fn get_policy_claims(&self, policy_id: &str) -> Vec<ClaimRequest>;
/// 检查保单是否有效
fn is_policy_valid(&self, policy_id: &str) -> bool;
}
/// ACC-Insurance标准实现
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InsuranceToken {
state: InsuranceState,
}
impl InsuranceToken {
/// 创建新的保险管理器
pub fn new() -> Self {
Self {
state: InsuranceState {
policies: HashMap::new(),
asset_policies: HashMap::new(),
insured_policies: HashMap::new(),
claims: HashMap::new(),
policy_claims: HashMap::new(),
},
}
}
/// 获取状态的可变引用
pub fn state_mut(&mut self) -> &mut InsuranceState {
&mut self.state
}
/// 获取状态的不可变引用
pub fn state(&self) -> &InsuranceState {
&self.state
}
/// 检查保单状态
fn check_policy_status(&self, policy: &InsurancePolicy) -> Result<(), InsuranceError> {
match policy.status {
InsuranceStatus::Expired => Err(InsuranceError::PolicyExpired),
InsuranceStatus::Suspended => Err(InsuranceError::PolicySuspended),
InsuranceStatus::Terminated => Err(InsuranceError::PolicyExpired),
_ => Ok(()),
}
}
}
impl Default for InsuranceToken {
fn default() -> Self {
Self::new()
}
}
impl ACCInsurance for InsuranceToken {
fn create_policy(&mut self, mut policy: InsurancePolicy) -> Result<(), InsuranceError> {
// 检查保单是否已存在
if self.state.policies.contains_key(&policy.policy_id) {
return Err(InsuranceError::PolicyAlreadyExists);
}
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
policy.created_at = now;
policy.updated_at = now;
policy.status = InsuranceStatus::Active;
let policy_id = policy.policy_id.clone();
let asset_id = policy.asset_id.clone();
let insured = policy.insured.clone();
// 保存保单
self.state.policies.insert(policy_id.clone(), policy);
// 更新资产保单映射
self.state
.asset_policies
.insert(asset_id, policy_id.clone());
// 更新被保险人保单列表
self.state
.insured_policies
.entry(insured)
.or_insert_with(Vec::new)
.push(policy_id);
Ok(())
}
fn get_policy(&self, policy_id: &str) -> Result<InsurancePolicy, InsuranceError> {
self.state
.policies
.get(policy_id)
.cloned()
.ok_or(InsuranceError::PolicyNotFound)
}
fn get_asset_policy(&self, asset_id: &str) -> Result<InsurancePolicy, InsuranceError> {
let policy_id = self
.state
.asset_policies
.get(asset_id)
.ok_or(InsuranceError::PolicyNotFound)?;
self.get_policy(policy_id)
}
fn file_claim(&mut self, mut claim: ClaimRequest) -> Result<(), InsuranceError> {
// 检查理赔申请是否已存在
if self.state.claims.contains_key(&claim.claim_id) {
return Err(InsuranceError::ClaimAlreadyExists);
}
// 获取保单并检查状态
let policy = self.get_policy(&claim.policy_id)?;
self.check_policy_status(&policy)?;
// 检查理赔金额
if claim.claim_amount > policy.coverage_amount {
return Err(InsuranceError::ClaimExceedsCoverage);
}
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
claim.filed_at = now;
claim.status = ClaimStatus::Pending;
let claim_id = claim.claim_id.clone();
let policy_id = claim.policy_id.clone();
// 保存理赔申请
self.state.claims.insert(claim_id.clone(), claim);
// 更新保单理赔列表
self.state
.policy_claims
.entry(policy_id)
.or_insert_with(Vec::new)
.push(claim_id);
Ok(())
}
fn get_claim(&self, claim_id: &str) -> Result<ClaimRequest, InsuranceError> {
self.state
.claims
.get(claim_id)
.cloned()
.ok_or(InsuranceError::ClaimNotFound)
}
fn approve_claim(&mut self, claim_id: &str, payout_amount: u128) -> Result<(), InsuranceError> {
let mut claim = self.get_claim(claim_id)?;
if claim.status != ClaimStatus::Pending && claim.status != ClaimStatus::UnderReview {
return Err(InsuranceError::Unauthorized);
}
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
claim.status = ClaimStatus::Approved;
claim.approved_at = Some(now);
claim.payout_amount = Some(payout_amount);
self.state.claims.insert(claim_id.to_string(), claim);
Ok(())
}
fn reject_claim(&mut self, claim_id: &str, reason: String) -> Result<(), InsuranceError> {
let mut claim = self.get_claim(claim_id)?;
if claim.status != ClaimStatus::Pending && claim.status != ClaimStatus::UnderReview {
return Err(InsuranceError::Unauthorized);
}
claim.status = ClaimStatus::Rejected;
claim.notes.push(format!("Rejected: {}", reason));
self.state.claims.insert(claim_id.to_string(), claim);
Ok(())
}
fn pay_claim(&mut self, claim_id: &str) -> Result<(), InsuranceError> {
let mut claim = self.get_claim(claim_id)?;
if claim.status != ClaimStatus::Approved {
return Err(InsuranceError::Unauthorized);
}
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
claim.status = ClaimStatus::Paid;
claim.paid_at = Some(now);
self.state.claims.insert(claim_id.to_string(), claim);
Ok(())
}
fn renew_policy(&mut self, policy_id: &str, new_expiration: u64) -> Result<(), InsuranceError> {
let mut policy = self.get_policy(policy_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
policy.expiration_date = new_expiration;
policy.status = InsuranceStatus::Active;
policy.updated_at = now;
self.state.policies.insert(policy_id.to_string(), policy);
Ok(())
}
fn suspend_policy(&mut self, policy_id: &str) -> Result<(), InsuranceError> {
let mut policy = self.get_policy(policy_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
policy.status = InsuranceStatus::Suspended;
policy.updated_at = now;
self.state.policies.insert(policy_id.to_string(), policy);
Ok(())
}
fn resume_policy(&mut self, policy_id: &str) -> Result<(), InsuranceError> {
let mut policy = self.get_policy(policy_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
policy.status = InsuranceStatus::Active;
policy.updated_at = now;
self.state.policies.insert(policy_id.to_string(), policy);
Ok(())
}
fn terminate_policy(&mut self, policy_id: &str) -> Result<(), InsuranceError> {
let mut policy = self.get_policy(policy_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
policy.status = InsuranceStatus::Terminated;
policy.updated_at = now;
self.state.policies.insert(policy_id.to_string(), policy);
Ok(())
}
fn get_insured_policies(&self, insured: &str) -> Vec<InsurancePolicy> {
self.state
.insured_policies
.get(insured)
.map(|policy_ids| {
policy_ids
.iter()
.filter_map(|id| self.state.policies.get(id).cloned())
.collect()
})
.unwrap_or_default()
}
fn get_policy_claims(&self, policy_id: &str) -> Vec<ClaimRequest> {
self.state
.policy_claims
.get(policy_id)
.map(|claim_ids| {
claim_ids
.iter()
.filter_map(|id| self.state.claims.get(id).cloned())
.collect()
})
.unwrap_or_default()
}
fn is_policy_valid(&self, policy_id: &str) -> bool {
if let Ok(policy) = self.get_policy(policy_id) {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("mainnet: handle error")
.as_secs();
policy.status == InsuranceStatus::Active && now < policy.expiration_date
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_policy() -> InsurancePolicy {
InsurancePolicy {
policy_id: "POL-001".to_string(),
asset_id: "RWA-001".to_string(),
insured: "alice".to_string(),
insurer: "insurer1".to_string(),
insurance_type: InsuranceType::Property,
coverage_amount: 1000000_00,
premium: 10000_00,
deductible: 5000_00,
status: InsuranceStatus::Active,
effective_date: 1234567890,
expiration_date: 1234567890 + 31536000,
created_at: 0,
updated_at: 0,
terms: vec!["Term 1".to_string(), "Term 2".to_string()],
}
}
fn create_test_claim() -> ClaimRequest {
ClaimRequest {
claim_id: "CLAIM-001".to_string(),
policy_id: "POL-001".to_string(),
claimant: "alice".to_string(),
claim_amount: 50000_00,
status: ClaimStatus::Pending,
filed_at: 0,
approved_at: None,
paid_at: None,
payout_amount: None,
description: "Test claim".to_string(),
evidence_hashes: vec![[1u8; 32]],
notes: Vec::new(),
}
}
#[test]
fn test_create_policy() {
let mut insurance = InsuranceToken::new();
let policy = create_test_policy();
assert!(insurance.create_policy(policy).is_ok());
}
#[test]
fn test_file_claim() {
let mut insurance = InsuranceToken::new();
let policy = create_test_policy();
insurance.create_policy(policy).expect("mainnet: handle error");
let claim = create_test_claim();
assert!(insurance.file_claim(claim).is_ok());
}
#[test]
fn test_approve_and_pay_claim() {
let mut insurance = InsuranceToken::new();
let policy = create_test_policy();
insurance.create_policy(policy).expect("mainnet: handle error");
let claim = create_test_claim();
insurance.file_claim(claim).expect("mainnet: handle error");
assert!(insurance.approve_claim("CLAIM-001", 45000_00).is_ok());
assert_eq!(
insurance.get_claim("CLAIM-001").expect("mainnet: handle error").status,
ClaimStatus::Approved
);
assert!(insurance.pay_claim("CLAIM-001").is_ok());
assert_eq!(
insurance.get_claim("CLAIM-001").expect("mainnet: handle error").status,
ClaimStatus::Paid
);
}
#[test]
fn test_renew_policy() {
let mut insurance = InsuranceToken::new();
let policy = create_test_policy();
insurance.create_policy(policy).expect("mainnet: handle error");
let new_expiration = 1234567890 + 63072000; // 2 years
assert!(insurance.renew_policy("POL-001", new_expiration).is_ok());
assert_eq!(
insurance.get_policy("POL-001").expect("mainnet: handle error").expiration_date,
new_expiration
);
}
#[test]
fn test_suspend_and_resume_policy() {
let mut insurance = InsuranceToken::new();
let policy = create_test_policy();
insurance.create_policy(policy).expect("mainnet: handle error");
assert!(insurance.suspend_policy("POL-001").is_ok());
assert_eq!(
insurance.get_policy("POL-001").expect("mainnet: handle error").status,
InsuranceStatus::Suspended
);
assert!(insurance.resume_policy("POL-001").is_ok());
assert_eq!(
insurance.get_policy("POL-001").expect("mainnet: handle error").status,
InsuranceStatus::Active
);
}
}