766 lines
20 KiB
Plaintext
766 lines
20 KiB
Plaintext
///! # 链上登记系统
|
||
///!
|
||
///! On-Chain Registry System
|
||
///! 管理资产和主权的链上登记
|
||
///!
|
||
///! **版本**: v1.0
|
||
///! **模块**: charter-std/sovereignty/registry.ch
|
||
|
||
use asset::gnacs::GNACSCode;
|
||
use sovereignty::rules::SovereigntyType;
|
||
use utils::crypto::sha3_384_hash;
|
||
|
||
// ============================================================================
|
||
// 登记类型枚举
|
||
// ============================================================================
|
||
|
||
/// 登记类型
|
||
pub enum RegistryType {
|
||
/// 资产登记
|
||
Asset,
|
||
|
||
/// 主权登记
|
||
Sovereignty,
|
||
|
||
/// 抵押登记
|
||
Collateral,
|
||
|
||
/// 知识产权登记
|
||
IntellectualProperty,
|
||
|
||
/// 转让登记
|
||
Transfer,
|
||
|
||
/// 变更登记
|
||
Modification
|
||
}
|
||
|
||
/// 登记状态
|
||
pub enum RegistryStatus {
|
||
/// 待审核
|
||
Pending,
|
||
|
||
/// 已批准
|
||
Approved,
|
||
|
||
/// 已拒绝
|
||
Rejected,
|
||
|
||
/// 已撤销
|
||
Revoked,
|
||
|
||
/// 已过期
|
||
Expired
|
||
}
|
||
|
||
// ============================================================================
|
||
// 登记记录结构
|
||
// ============================================================================
|
||
|
||
/// 登记记录
|
||
struct RegistryRecord {
|
||
/// 登记ID
|
||
registry_id: Hash,
|
||
|
||
/// 登记类型
|
||
registry_type: RegistryType,
|
||
|
||
/// 资产ID
|
||
asset_id: Hash,
|
||
|
||
/// 登记人
|
||
registrant: Address,
|
||
|
||
/// GNACS编码
|
||
gnacs_code: u48,
|
||
|
||
/// 主权类型
|
||
sovereignty_type: SovereigntyType,
|
||
|
||
/// 登记数据(JSON格式)
|
||
data: String,
|
||
|
||
/// 文档哈希列表
|
||
document_hashes: Vec<Hash>,
|
||
|
||
/// 登记状态
|
||
status: RegistryStatus,
|
||
|
||
/// 登记时间
|
||
registered_at: Timestamp,
|
||
|
||
/// 批准时间
|
||
approved_at: Option<Timestamp>,
|
||
|
||
/// 批准人
|
||
approver: Option<Address>,
|
||
|
||
/// 有效期
|
||
valid_until: Option<Timestamp>,
|
||
|
||
/// 备注
|
||
notes: String
|
||
}
|
||
|
||
/// 主权登记信息
|
||
struct SovereigntyRegistry {
|
||
/// 资产ID
|
||
asset_id: Hash,
|
||
|
||
/// 主权类型
|
||
sovereignty_type: SovereigntyType,
|
||
|
||
/// 主权持有人
|
||
holder: Address,
|
||
|
||
/// 主权份额(基点,0-10000)
|
||
share: u16,
|
||
|
||
/// 开始时间
|
||
start_time: Timestamp,
|
||
|
||
/// 结束时间(可选)
|
||
end_time: Option<Timestamp>,
|
||
|
||
/// 登记ID
|
||
registry_id: Hash
|
||
}
|
||
|
||
/// 抵押登记信息
|
||
struct CollateralRegistry {
|
||
/// 抵押品资产ID
|
||
collateral_asset_id: Hash,
|
||
|
||
/// 债权人
|
||
creditor: Address,
|
||
|
||
/// 债务人
|
||
debtor: Address,
|
||
|
||
/// 抵押金额
|
||
amount: u256,
|
||
|
||
/// 抵押期限
|
||
term: Duration,
|
||
|
||
/// 清算条件
|
||
liquidation_conditions: String,
|
||
|
||
/// 登记ID
|
||
registry_id: Hash
|
||
}
|
||
|
||
// ============================================================================
|
||
// 登记事件
|
||
// ============================================================================
|
||
|
||
/// 登记创建事件
|
||
event RegistryCreated {
|
||
registry_id: Hash,
|
||
registry_type: RegistryType,
|
||
asset_id: Hash,
|
||
registrant: Address,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
/// 登记批准事件
|
||
event RegistryApproved {
|
||
registry_id: Hash,
|
||
approver: Address,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
/// 登记拒绝事件
|
||
event RegistryRejected {
|
||
registry_id: Hash,
|
||
approver: Address,
|
||
reason: String,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
/// 登记撤销事件
|
||
event RegistryRevoked {
|
||
registry_id: Hash,
|
||
revoker: Address,
|
||
reason: String,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
// ============================================================================
|
||
// 链上登记系统
|
||
// ============================================================================
|
||
|
||
/// 链上登记系统
|
||
certificate OnChainRegistry {
|
||
/// 登记记录存储 (registry_id => record)
|
||
let _records: Map<Hash, RegistryRecord>;
|
||
|
||
/// 资产登记索引 (asset_id => registry_ids)
|
||
let _asset_registries: Map<Hash, Vec<Hash>>;
|
||
|
||
/// 主权登记存储 (asset_id => sovereignty_registries)
|
||
let _sovereignty_registries: Map<Hash, Vec<SovereigntyRegistry>>;
|
||
|
||
/// 抵押登记存储 (asset_id => collateral_registries)
|
||
let _collateral_registries: Map<Hash, Vec<CollateralRegistry>>;
|
||
|
||
/// 登记人索引 (registrant => registry_ids)
|
||
let _registrant_index: Map<Address, Vec<Hash>>;
|
||
|
||
/// 管理员地址
|
||
let _admin: Address;
|
||
|
||
/// 登记官员集合
|
||
let _registrars: Set<Address>;
|
||
|
||
// ========== 构造函数 ==========
|
||
|
||
constructor() {
|
||
self._admin = msg.sender;
|
||
self._registrars.insert(msg.sender);
|
||
}
|
||
|
||
// ========== 资产登记 ==========
|
||
|
||
/// 创建资产登记
|
||
///
|
||
/// # 参数
|
||
/// - `asset_id`: 资产ID
|
||
/// - `gnacs_code`: GNACS编码
|
||
/// - `sovereignty_type`: 主权类型
|
||
/// - `data`: 登记数据(JSON格式)
|
||
/// - `document_hashes`: 文档哈希列表
|
||
///
|
||
/// # 返回
|
||
/// - `Hash`: 登记ID
|
||
pub fn register_asset(
|
||
asset_id: Hash,
|
||
gnacs_code: u48,
|
||
sovereignty_type: SovereigntyType,
|
||
data: String,
|
||
document_hashes: Vec<Hash>
|
||
) -> Hash {
|
||
require(!asset_id.is_zero(), "Invalid asset ID");
|
||
require(!data.is_empty(), "Data cannot be empty");
|
||
|
||
// 验证GNACS编码
|
||
let gnacs = GNACSCode::from_u48(gnacs_code);
|
||
require(gnacs.validate(), "Invalid GNACS code");
|
||
|
||
// 生成登记ID
|
||
let registry_id = self._generate_registry_id(
|
||
asset_id,
|
||
msg.sender,
|
||
RegistryType::Asset
|
||
);
|
||
|
||
let record = RegistryRecord {
|
||
registry_id: registry_id,
|
||
registry_type: RegistryType::Asset,
|
||
asset_id: asset_id,
|
||
registrant: msg.sender,
|
||
gnacs_code: gnacs_code,
|
||
sovereignty_type: sovereignty_type,
|
||
data: data,
|
||
document_hashes: document_hashes,
|
||
status: RegistryStatus::Pending,
|
||
registered_at: block.timestamp,
|
||
approved_at: None,
|
||
approver: None,
|
||
valid_until: None,
|
||
notes: String::new()
|
||
};
|
||
|
||
self._records[registry_id] = record;
|
||
|
||
// 更新索引
|
||
if !self._asset_registries.contains_key(asset_id) {
|
||
self._asset_registries[asset_id] = Vec::new();
|
||
}
|
||
self._asset_registries[asset_id].push(registry_id);
|
||
|
||
if !self._registrant_index.contains_key(msg.sender) {
|
||
self._registrant_index[msg.sender] = Vec::new();
|
||
}
|
||
self._registrant_index[msg.sender].push(registry_id);
|
||
|
||
emit RegistryCreated {
|
||
registry_id: registry_id,
|
||
registry_type: RegistryType::Asset,
|
||
asset_id: asset_id,
|
||
registrant: msg.sender,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return registry_id;
|
||
}
|
||
|
||
// ========== 主权登记 ==========
|
||
|
||
/// 创建主权登记
|
||
///
|
||
/// # 参数
|
||
/// - `asset_id`: 资产ID
|
||
/// - `sovereignty_type`: 主权类型
|
||
/// - `holder`: 主权持有人
|
||
/// - `share`: 主权份额(基点)
|
||
/// - `end_time`: 结束时间(可选)
|
||
///
|
||
/// # 返回
|
||
/// - `Hash`: 登记ID
|
||
pub fn register_sovereignty(
|
||
asset_id: Hash,
|
||
sovereignty_type: SovereigntyType,
|
||
holder: Address,
|
||
share: u16,
|
||
end_time: Option<Timestamp>
|
||
) -> Hash {
|
||
require(!asset_id.is_zero(), "Invalid asset ID");
|
||
require(!holder.is_zero(), "Invalid holder");
|
||
require(share > 0 && share <= 10000, "Invalid share");
|
||
|
||
// 生成登记ID
|
||
let registry_id = self._generate_registry_id(
|
||
asset_id,
|
||
msg.sender,
|
||
RegistryType::Sovereignty
|
||
);
|
||
|
||
// 创建主权登记信息
|
||
let sovereignty_registry = SovereigntyRegistry {
|
||
asset_id: asset_id,
|
||
sovereignty_type: sovereignty_type,
|
||
holder: holder,
|
||
share: share,
|
||
start_time: block.timestamp,
|
||
end_time: end_time,
|
||
registry_id: registry_id
|
||
};
|
||
|
||
// 存储主权登记
|
||
if !self._sovereignty_registries.contains_key(asset_id) {
|
||
self._sovereignty_registries[asset_id] = Vec::new();
|
||
}
|
||
self._sovereignty_registries[asset_id].push(sovereignty_registry);
|
||
|
||
// 创建登记记录
|
||
let data = format!(
|
||
"{{\"holder\":\"{}\",\"share\":{},\"sovereignty_type\":\"{}\"}}",
|
||
holder, share, sovereignty_type
|
||
);
|
||
|
||
let record = RegistryRecord {
|
||
registry_id: registry_id,
|
||
registry_type: RegistryType::Sovereignty,
|
||
asset_id: asset_id,
|
||
registrant: msg.sender,
|
||
gnacs_code: 0, // 主权登记不需要GNACS
|
||
sovereignty_type: sovereignty_type,
|
||
data: data,
|
||
document_hashes: Vec::new(),
|
||
status: RegistryStatus::Pending,
|
||
registered_at: block.timestamp,
|
||
approved_at: None,
|
||
approver: None,
|
||
valid_until: end_time,
|
||
notes: String::new()
|
||
};
|
||
|
||
self._records[registry_id] = record;
|
||
|
||
// 更新索引
|
||
if !self._asset_registries.contains_key(asset_id) {
|
||
self._asset_registries[asset_id] = Vec::new();
|
||
}
|
||
self._asset_registries[asset_id].push(registry_id);
|
||
|
||
emit RegistryCreated {
|
||
registry_id: registry_id,
|
||
registry_type: RegistryType::Sovereignty,
|
||
asset_id: asset_id,
|
||
registrant: msg.sender,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return registry_id;
|
||
}
|
||
|
||
// ========== 抵押登记 ==========
|
||
|
||
/// 创建抵押登记
|
||
///
|
||
/// # 参数
|
||
/// - `collateral_asset_id`: 抵押品资产ID
|
||
/// - `creditor`: 债权人
|
||
/// - `debtor`: 债务人
|
||
/// - `amount`: 抵押金额
|
||
/// - `term`: 抵押期限
|
||
/// - `liquidation_conditions`: 清算条件
|
||
///
|
||
/// # 返回
|
||
/// - `Hash`: 登记ID
|
||
pub fn register_collateral(
|
||
collateral_asset_id: Hash,
|
||
creditor: Address,
|
||
debtor: Address,
|
||
amount: u256,
|
||
term: Duration,
|
||
liquidation_conditions: String
|
||
) -> Hash {
|
||
require(!collateral_asset_id.is_zero(), "Invalid collateral asset ID");
|
||
require(!creditor.is_zero(), "Invalid creditor");
|
||
require(!debtor.is_zero(), "Invalid debtor");
|
||
require(amount > 0, "Amount must be positive");
|
||
|
||
// 生成登记ID
|
||
let registry_id = self._generate_registry_id(
|
||
collateral_asset_id,
|
||
msg.sender,
|
||
RegistryType::Collateral
|
||
);
|
||
|
||
// 创建抵押登记信息
|
||
let collateral_registry = CollateralRegistry {
|
||
collateral_asset_id: collateral_asset_id,
|
||
creditor: creditor,
|
||
debtor: debtor,
|
||
amount: amount,
|
||
term: term,
|
||
liquidation_conditions: liquidation_conditions.clone(),
|
||
registry_id: registry_id
|
||
};
|
||
|
||
// 存储抵押登记
|
||
if !self._collateral_registries.contains_key(collateral_asset_id) {
|
||
self._collateral_registries[collateral_asset_id] = Vec::new();
|
||
}
|
||
self._collateral_registries[collateral_asset_id].push(collateral_registry);
|
||
|
||
// 创建登记记录
|
||
let data = format!(
|
||
"{{\"creditor\":\"{}\",\"debtor\":\"{}\",\"amount\":{},\"term\":{}}}",
|
||
creditor, debtor, amount, term
|
||
);
|
||
|
||
let record = RegistryRecord {
|
||
registry_id: registry_id,
|
||
registry_type: RegistryType::Collateral,
|
||
asset_id: collateral_asset_id,
|
||
registrant: msg.sender,
|
||
gnacs_code: 0,
|
||
sovereignty_type: SovereigntyType::D0, // 抵押主权
|
||
data: data,
|
||
document_hashes: Vec::new(),
|
||
status: RegistryStatus::Pending,
|
||
registered_at: block.timestamp,
|
||
approved_at: None,
|
||
approver: None,
|
||
valid_until: Some(block.timestamp + term),
|
||
notes: liquidation_conditions
|
||
};
|
||
|
||
self._records[registry_id] = record;
|
||
|
||
// 更新索引
|
||
if !self._asset_registries.contains_key(collateral_asset_id) {
|
||
self._asset_registries[collateral_asset_id] = Vec::new();
|
||
}
|
||
self._asset_registries[collateral_asset_id].push(registry_id);
|
||
|
||
emit RegistryCreated {
|
||
registry_id: registry_id,
|
||
registry_type: RegistryType::Collateral,
|
||
asset_id: collateral_asset_id,
|
||
registrant: msg.sender,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return registry_id;
|
||
}
|
||
|
||
// ========== 登记审批 ==========
|
||
|
||
/// 批准登记
|
||
///
|
||
/// # 参数
|
||
/// - `registry_id`: 登记ID
|
||
/// - `valid_until`: 有效期(可选)
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn approve_registry(
|
||
registry_id: Hash,
|
||
valid_until: Option<Timestamp>
|
||
) -> bool {
|
||
require(self._registrars.contains(msg.sender), "Not a registrar");
|
||
require(self._records.contains_key(registry_id), "Registry not found");
|
||
|
||
let mut record = self._records[registry_id];
|
||
require(
|
||
record.status == RegistryStatus::Pending,
|
||
"Registry not pending"
|
||
);
|
||
|
||
record.status = RegistryStatus::Approved;
|
||
record.approved_at = Some(block.timestamp);
|
||
record.approver = Some(msg.sender);
|
||
|
||
if let Some(expiry) = valid_until {
|
||
require(expiry > block.timestamp, "Invalid expiry time");
|
||
record.valid_until = Some(expiry);
|
||
}
|
||
|
||
self._records[registry_id] = record;
|
||
|
||
emit RegistryApproved {
|
||
registry_id: registry_id,
|
||
approver: msg.sender,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 拒绝登记
|
||
///
|
||
/// # 参数
|
||
/// - `registry_id`: 登记ID
|
||
/// - `reason`: 拒绝原因
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn reject_registry(registry_id: Hash, reason: String) -> bool {
|
||
require(self._registrars.contains(msg.sender), "Not a registrar");
|
||
require(self._records.contains_key(registry_id), "Registry not found");
|
||
|
||
let mut record = self._records[registry_id];
|
||
require(
|
||
record.status == RegistryStatus::Pending,
|
||
"Registry not pending"
|
||
);
|
||
|
||
record.status = RegistryStatus::Rejected;
|
||
record.notes = reason.clone();
|
||
|
||
self._records[registry_id] = record;
|
||
|
||
emit RegistryRejected {
|
||
registry_id: registry_id,
|
||
approver: msg.sender,
|
||
reason: reason,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 撤销登记
|
||
///
|
||
/// # 参数
|
||
/// - `registry_id`: 登记ID
|
||
/// - `reason`: 撤销原因
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn revoke_registry(registry_id: Hash, reason: String) -> bool {
|
||
require(self._records.contains_key(registry_id), "Registry not found");
|
||
|
||
let mut record = self._records[registry_id];
|
||
|
||
// 只有登记人或管理员可以撤销
|
||
require(
|
||
msg.sender == record.registrant || msg.sender == self._admin,
|
||
"Not authorized"
|
||
);
|
||
|
||
require(
|
||
record.status == RegistryStatus::Approved,
|
||
"Registry not approved"
|
||
);
|
||
|
||
record.status = RegistryStatus::Revoked;
|
||
record.notes = reason.clone();
|
||
|
||
self._records[registry_id] = record;
|
||
|
||
emit RegistryRevoked {
|
||
registry_id: registry_id,
|
||
revoker: msg.sender,
|
||
reason: reason,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return true;
|
||
}
|
||
|
||
// ========== 查询函数 ==========
|
||
|
||
/// 获取登记记录
|
||
///
|
||
/// # 参数
|
||
/// - `registry_id`: 登记ID
|
||
///
|
||
/// # 返回
|
||
/// - `RegistryRecord`: 登记记录
|
||
pub fn get_registry(registry_id: Hash) -> RegistryRecord {
|
||
require(self._records.contains_key(registry_id), "Registry not found");
|
||
return self._records[registry_id];
|
||
}
|
||
|
||
/// 获取资产的所有登记
|
||
///
|
||
/// # 参数
|
||
/// - `asset_id`: 资产ID
|
||
///
|
||
/// # 返回
|
||
/// - `Vec<Hash>`: 登记ID列表
|
||
pub fn get_asset_registries(asset_id: Hash) -> Vec<Hash> {
|
||
return self._asset_registries.get(asset_id).unwrap_or(Vec::new());
|
||
}
|
||
|
||
/// 获取资产的主权登记
|
||
///
|
||
/// # 参数
|
||
/// - `asset_id`: 资产ID
|
||
///
|
||
/// # 返回
|
||
/// - `Vec<SovereigntyRegistry>`: 主权登记列表
|
||
pub fn get_sovereignty_registries(asset_id: Hash) -> Vec<SovereigntyRegistry> {
|
||
return self._sovereignty_registries.get(asset_id).unwrap_or(Vec::new());
|
||
}
|
||
|
||
/// 获取资产的抵押登记
|
||
///
|
||
/// # 参数
|
||
/// - `asset_id`: 资产ID
|
||
///
|
||
/// # 返回
|
||
/// - `Vec<CollateralRegistry>`: 抵押登记列表
|
||
pub fn get_collateral_registries(asset_id: Hash) -> Vec<CollateralRegistry> {
|
||
return self._collateral_registries.get(asset_id).unwrap_or(Vec::new());
|
||
}
|
||
|
||
/// 获取登记人的所有登记
|
||
///
|
||
/// # 参数
|
||
/// - `registrant`: 登记人地址
|
||
///
|
||
/// # 返回
|
||
/// - `Vec<Hash>`: 登记ID列表
|
||
pub fn get_registrant_registries(registrant: Address) -> Vec<Hash> {
|
||
return self._registrant_index.get(registrant).unwrap_or(Vec::new());
|
||
}
|
||
|
||
/// 检查登记是否有效
|
||
///
|
||
/// # 参数
|
||
/// - `registry_id`: 登记ID
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否有效
|
||
pub fn is_registry_valid(registry_id: Hash) -> bool {
|
||
if !self._records.contains_key(registry_id) {
|
||
return false;
|
||
}
|
||
|
||
let record = self._records[registry_id];
|
||
|
||
// 检查状态
|
||
if record.status != RegistryStatus::Approved {
|
||
return false;
|
||
}
|
||
|
||
// 检查是否过期
|
||
if let Some(expiry) = record.valid_until {
|
||
if block.timestamp >= expiry {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 验证文档
|
||
///
|
||
/// # 参数
|
||
/// - `registry_id`: 登记ID
|
||
/// - `document_hash`: 文档哈希
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否存在
|
||
pub fn verify_document(registry_id: Hash, document_hash: Hash) -> bool {
|
||
require(self._records.contains_key(registry_id), "Registry not found");
|
||
|
||
let record = self._records[registry_id];
|
||
|
||
for hash in record.document_hashes {
|
||
if hash == document_hash {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// ========== 内部函数 ==========
|
||
|
||
/// 生成登记ID
|
||
fn _generate_registry_id(
|
||
asset_id: Hash,
|
||
registrant: Address,
|
||
registry_type: RegistryType
|
||
) -> Hash {
|
||
let mut data = Bytes::new();
|
||
data.extend(asset_id.as_bytes());
|
||
data.extend(registrant.as_bytes());
|
||
data.extend(block.timestamp.to_bytes());
|
||
data.extend(tx.hash.as_bytes());
|
||
|
||
return sha3_384_hash(data);
|
||
}
|
||
|
||
// ========== 管理函数 ==========
|
||
|
||
/// 添加登记官员
|
||
///
|
||
/// # 参数
|
||
/// - `registrar`: 登记官员地址
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn add_registrar(registrar: Address) -> bool {
|
||
require(msg.sender == self._admin, "Only admin");
|
||
require(!registrar.is_zero(), "Invalid registrar");
|
||
|
||
self._registrars.insert(registrar);
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 移除登记官员
|
||
///
|
||
/// # 参数
|
||
/// - `registrar`: 登记官员地址
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn remove_registrar(registrar: Address) -> bool {
|
||
require(msg.sender == self._admin, "Only admin");
|
||
|
||
self._registrars.remove(registrar);
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 检查是否为登记官员
|
||
///
|
||
/// # 参数
|
||
/// - `registrar`: 登记官员地址
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否为登记官员
|
||
pub fn is_registrar(registrar: Address) -> bool {
|
||
return self._registrars.contains(registrar);
|
||
}
|
||
}
|