/// NAC ACC-1643 协议实现 /// 基于GNACS的文档管理与法律披露协议 mod error; mod types; pub use error::{Acc1643Error, Result}; pub use types::*; use sha3::{Digest, Sha3_384}; use std::collections::HashMap; /// ACC-1643 文档管理协议 #[derive(Debug)] pub struct Acc1643 { /// 文档存储(doc_id -> AssetDocument) documents: HashMap, /// 文档类型索引(doc_type -> vec) type_index: HashMap>, /// 文档Merkle根 documents_root: [u8; 16], /// 角色权限(简化实现) roles: HashMap>, /// 合法文档类型白名单 valid_doc_types: Vec, } impl Acc1643 { /// 创建新的ACC-1643实例 pub fn new() -> Self { let mut valid_types = Vec::new(); valid_types.push("Prospectus".to_string()); valid_types.push("AuditReport".to_string()); valid_types.push("LegalOpinion".to_string()); valid_types.push("FinancialStatement".to_string()); valid_types.push("ComplianceReport".to_string()); Self { documents: HashMap::new(), type_index: HashMap::new(), documents_root: [0u8; 16], roles: HashMap::new(), valid_doc_types: valid_types, } } /// 设置文档(首次上传或更新) pub fn set_document( &mut self, operator: &str, doc_type: String, uri: String, content_hash: [u8; 48], supersedes: [u8; 48], receipt_hash: [u8; 32], ) -> Result<[u8; 48]> { // 检查权限 if !self.has_role("ISSUER", operator) { return Err(Acc1643Error::Unauthorized { operator: operator.to_string(), required_role: "ISSUER".to_string(), }); } // 验证文档类型 if !self.valid_doc_types.contains(&doc_type) { return Err(Acc1643Error::InvalidDocumentType { doc_type }); } // 验证宪法收据(简化实现) if receipt_hash == [0u8; 32] { return Err(Acc1643Error::InvalidConstitutionalReceipt { receipt_hash: hex::encode(receipt_hash), }); } // 计算文档ID let doc_id = self.calculate_doc_id(&uri, &content_hash, Self::current_timestamp()); let doc_id_hex = hex::encode(doc_id); // 检查是否已存在 if self.documents.contains_key(&doc_id_hex) { return Err(Acc1643Error::DocumentAlreadyExists { doc_id: doc_id_hex }); } // 确定版本号 let version = if supersedes == [0u8; 48] { 1 } else { let supersedes_hex = hex::encode(supersedes); if let Some(old_doc) = self.documents.get(&supersedes_hex) { old_doc.version + 1 } else { return Err(Acc1643Error::DocumentNotFound { doc_id: supersedes_hex, }); } }; // 创建文档 let document = AssetDocument { doc_id, doc_type: doc_type.clone(), uri, content_hash, timestamp: Self::current_timestamp(), version, supersedes, is_active: true, }; // 存储文档 self.documents.insert(doc_id_hex.clone(), document); // 更新类型索引 self.type_index .entry(doc_type) .or_insert_with(Vec::new) .push(doc_id_hex); // 更新Merkle根 self.update_documents_root(); Ok(doc_id) } /// 批量设置文档(原子操作) pub fn set_documents( &mut self, operator: &str, inputs: Vec, receipt_hash: [u8; 32], ) -> Result> { let mut doc_ids = Vec::new(); for input in inputs { let doc_id = self.set_document( operator, input.doc_type, input.uri, input.content_hash, input.supersedes, receipt_hash, )?; doc_ids.push(doc_id); } Ok(doc_ids) } /// 移除文档(标记为无效) pub fn remove_document( &mut self, operator: &str, doc_id: &[u8; 48], receipt_hash: [u8; 32], ) -> Result<()> { // 检查权限 if !self.has_role("ISSUER", operator) { return Err(Acc1643Error::Unauthorized { operator: operator.to_string(), required_role: "ISSUER".to_string(), }); } // 验证宪法收据 if receipt_hash == [0u8; 32] { return Err(Acc1643Error::InvalidConstitutionalReceipt { receipt_hash: hex::encode(receipt_hash), }); } let doc_id_hex = hex::encode(doc_id); // 查找文档 let document = self.documents.get_mut(&doc_id_hex).ok_or_else(|| { Acc1643Error::DocumentNotFound { doc_id: doc_id_hex.clone(), } })?; // 标记为无效 document.is_active = false; // 更新Merkle根 self.update_documents_root(); Ok(()) } /// 获取文档详情 pub fn get_document(&self, doc_id: &[u8; 48]) -> Result { let doc_id_hex = hex::encode(doc_id); self.documents .get(&doc_id_hex) .cloned() .ok_or_else(|| Acc1643Error::DocumentNotFound { doc_id: doc_id_hex }) } /// 获取指定类型的最新文档 pub fn get_latest_document(&self, doc_type: &str) -> Result { let doc_ids = self.type_index.get(doc_type).ok_or_else(|| { Acc1643Error::InvalidDocumentType { doc_type: doc_type.to_string(), } })?; let mut latest: Option = None; for doc_id_hex in doc_ids { if let Some(doc) = self.documents.get(doc_id_hex) { if doc.is_active { if let Some(ref current_latest) = latest { if doc.version > current_latest.version { latest = Some(doc.clone()); } } else { latest = Some(doc.clone()); } } } } latest.ok_or_else(|| Acc1643Error::DocumentNotFound { doc_id: format!("latest of type {}", doc_type), }) } /// 获取所有文档ID(分页) pub fn get_all_documents(&self, offset: usize, limit: usize) -> Vec<[u8; 48]> { self.documents .values() .skip(offset) .take(limit) .map(|doc| doc.doc_id) .collect() } /// 验证文档是否属于资产且未被篡改 pub fn verify_document( &self, doc_id: &[u8; 48], uri: &str, content_hash: &[u8; 48], ) -> Result { let document = self.get_document(doc_id)?; // 验证URI和内容哈希 if document.uri != uri { return Ok(false); } if &document.content_hash != content_hash { return Ok(false); } // 验证文档ID let expected_id = self.calculate_doc_id(uri, content_hash, document.timestamp); if expected_id != *doc_id { return Ok(false); } Ok(true) } /// 获取文档Merkle根 pub fn documents_root(&self) -> [u8; 16] { self.documents_root } /// 计算文档ID(SHA3-384(uri+contentHash+timestamp)) fn calculate_doc_id(&self, uri: &str, content_hash: &[u8; 48], timestamp: u64) -> [u8; 48] { let mut hasher = Sha3_384::new(); hasher.update(uri.as_bytes()); hasher.update(content_hash); hasher.update(×tamp.to_be_bytes()); let result = hasher.finalize(); let mut doc_id = [0u8; 48]; doc_id.copy_from_slice(&result); doc_id } /// 更新文档Merkle根 fn update_documents_root(&mut self) { // 简化实现:对所有文档ID进行哈希 let mut hasher = Sha3_384::new(); let mut doc_ids: Vec<_> = self.documents.keys().collect(); doc_ids.sort(); for doc_id in doc_ids { hasher.update(doc_id.as_bytes()); } let result = hasher.finalize(); self.documents_root[..16].copy_from_slice(&result[..16]); } /// 检查角色权限 fn has_role(&self, role: &str, account: &str) -> bool { if let Some(accounts) = self.roles.get(role) { accounts.contains(&account.to_string()) } else { false } } /// 授予角色 pub fn grant_role(&mut self, role: &str, account: &str) { self.roles .entry(role.to_string()) .or_insert_with(Vec::new) .push(account.to_string()); } /// 获取当前时间戳 fn current_timestamp() -> u64 { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs() } } impl Default for Acc1643 { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use super::*; fn create_test_acc1643() -> Acc1643 { let mut acc1643 = Acc1643::new(); acc1643.grant_role("ISSUER", "issuer1"); acc1643 } #[test] fn test_set_document() { let mut acc1643 = create_test_acc1643(); let content_hash = [1u8; 48]; let doc_id = acc1643 .set_document( "issuer1", "Prospectus".to_string(), "ipfs://QmTest".to_string(), content_hash, [0u8; 48], [1u8; 32], ) .unwrap(); let document = acc1643.get_document(&doc_id).unwrap(); assert_eq!(document.doc_type, "Prospectus"); assert_eq!(document.version, 1); assert!(document.is_active); } #[test] fn test_document_versioning() { let mut acc1643 = create_test_acc1643(); // 创建第一个版本 let content_hash_v1 = [1u8; 48]; let doc_id_v1 = acc1643 .set_document( "issuer1", "Prospectus".to_string(), "ipfs://QmTest1".to_string(), content_hash_v1, [0u8; 48], [1u8; 32], ) .unwrap(); // 创建第二个版本 let content_hash_v2 = [2u8; 48]; let doc_id_v2 = acc1643 .set_document( "issuer1", "Prospectus".to_string(), "ipfs://QmTest2".to_string(), content_hash_v2, doc_id_v1, [1u8; 32], ) .unwrap(); let doc_v2 = acc1643.get_document(&doc_id_v2).unwrap(); assert_eq!(doc_v2.version, 2); assert_eq!(doc_v2.supersedes, doc_id_v1); } #[test] fn test_remove_document() { let mut acc1643 = create_test_acc1643(); let content_hash = [1u8; 48]; let doc_id = acc1643 .set_document( "issuer1", "Prospectus".to_string(), "ipfs://QmTest".to_string(), content_hash, [0u8; 48], [1u8; 32], ) .unwrap(); acc1643.remove_document("issuer1", &doc_id, [1u8; 32]).unwrap(); let document = acc1643.get_document(&doc_id).unwrap(); assert!(!document.is_active); } #[test] fn test_get_latest_document() { let mut acc1643 = create_test_acc1643(); // 创建多个版本 let doc_id_v1 = acc1643 .set_document( "issuer1", "Prospectus".to_string(), "ipfs://QmTest1".to_string(), [1u8; 48], [0u8; 48], [1u8; 32], ) .unwrap(); let _doc_id_v2 = acc1643 .set_document( "issuer1", "Prospectus".to_string(), "ipfs://QmTest2".to_string(), [2u8; 48], doc_id_v1, [1u8; 32], ) .unwrap(); let latest = acc1643.get_latest_document("Prospectus").unwrap(); assert_eq!(latest.version, 2); } #[test] fn test_verify_document() { let mut acc1643 = create_test_acc1643(); let content_hash = [1u8; 48]; let uri = "ipfs://QmTest".to_string(); let doc_id = acc1643 .set_document( "issuer1", "Prospectus".to_string(), uri.clone(), content_hash, [0u8; 48], [1u8; 32], ) .unwrap(); let is_valid = acc1643.verify_document(&doc_id, &uri, &content_hash).unwrap(); assert!(is_valid); // 验证错误的内容哈希 let wrong_hash = [2u8; 48]; let is_valid = acc1643.verify_document(&doc_id, &uri, &wrong_hash).unwrap(); assert!(!is_valid); } #[test] fn test_documents_root_update() { let mut acc1643 = create_test_acc1643(); let root_before = acc1643.documents_root(); acc1643 .set_document( "issuer1", "Prospectus".to_string(), "ipfs://QmTest".to_string(), [1u8; 48], [0u8; 48], [1u8; 32], ) .unwrap(); let root_after = acc1643.documents_root(); assert_ne!(root_before, root_after); } }