188 lines
5.5 KiB
Rust
188 lines
5.5 KiB
Rust
//! Partition Manager
|
|
|
|
use crate::error::{Acc1410Error, Result};
|
|
use crate::types::{ExtendedGNACS, Partition, PartitionInfo, PartitionType};
|
|
use sha3::{Digest, Sha3_256};
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Debug)]
|
|
pub struct PartitionManager {
|
|
partitions: HashMap<String, Partition>,
|
|
account_partitions: HashMap<String, Vec<String>>,
|
|
}
|
|
|
|
impl PartitionManager {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
partitions: HashMap::new(),
|
|
account_partitions: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn create_partition(
|
|
&mut self,
|
|
name: String,
|
|
extended_gnacs: ExtendedGNACS,
|
|
partition_type: PartitionType,
|
|
) -> Result<[u8; 32]> {
|
|
let mut hasher = Sha3_256::new();
|
|
hasher.update(name.as_bytes());
|
|
hasher.update(&extended_gnacs.encode());
|
|
let hash_result = hasher.finalize();
|
|
let mut partition_id = [0u8; 32];
|
|
partition_id.copy_from_slice(&hash_result);
|
|
|
|
let partition_id_hex = hex::encode(partition_id);
|
|
|
|
if self.partitions.contains_key(&partition_id_hex) {
|
|
return Err(Acc1410Error::PartitionAlreadyExists(partition_id_hex));
|
|
}
|
|
|
|
let partition = Partition::new(
|
|
partition_id,
|
|
extended_gnacs,
|
|
name,
|
|
partition_type,
|
|
Self::current_timestamp(),
|
|
);
|
|
|
|
self.partitions.insert(partition_id_hex, partition);
|
|
Ok(partition_id)
|
|
}
|
|
|
|
pub fn close_partition(&mut self, partition_id: &[u8; 32]) -> Result<()> {
|
|
let partition_id_hex = hex::encode(partition_id);
|
|
let partition = self
|
|
.partitions
|
|
.get_mut(&partition_id_hex)
|
|
.ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex.clone()))?;
|
|
partition.info.is_active = false;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn get_partition_info(&self, partition_id: &[u8; 32]) -> Result<PartitionInfo> {
|
|
let partition_id_hex = hex::encode(partition_id);
|
|
let partition = self
|
|
.partitions
|
|
.get(&partition_id_hex)
|
|
.ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex))?;
|
|
Ok(partition.info.clone())
|
|
}
|
|
|
|
pub fn balance_of_by_partition(
|
|
&self,
|
|
partition_id: &[u8; 32],
|
|
account: &str,
|
|
) -> Result<u64> {
|
|
let partition_id_hex = hex::encode(partition_id);
|
|
let partition = self
|
|
.partitions
|
|
.get(&partition_id_hex)
|
|
.ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex))?;
|
|
Ok(partition.balance_of(account))
|
|
}
|
|
|
|
pub fn partitions_of(&self, account: &str) -> Vec<[u8; 32]> {
|
|
self.account_partitions
|
|
.get(account)
|
|
.map(|partition_ids| {
|
|
partition_ids
|
|
.iter()
|
|
.filter_map(|id_hex| {
|
|
let bytes = hex::decode(id_hex).ok()?;
|
|
if bytes.len() == 32 {
|
|
let mut arr = [0u8; 32];
|
|
arr.copy_from_slice(&bytes);
|
|
Some(arr)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.collect()
|
|
})
|
|
.unwrap_or_default()
|
|
}
|
|
|
|
pub fn add_balance(
|
|
&mut self,
|
|
partition_id: &[u8; 32],
|
|
account: &str,
|
|
amount: u64,
|
|
) -> Result<()> {
|
|
let partition_id_hex = hex::encode(partition_id);
|
|
let partition = self
|
|
.partitions
|
|
.get_mut(&partition_id_hex)
|
|
.ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex.clone()))?;
|
|
|
|
if !partition.info.is_active {
|
|
return Err(Acc1410Error::PartitionClosed(partition_id_hex));
|
|
}
|
|
|
|
partition.add_balance(account, amount);
|
|
self.account_partitions
|
|
.entry(account.to_string())
|
|
.or_insert_with(Vec::new)
|
|
.push(partition_id_hex);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn sub_balance(
|
|
&mut self,
|
|
partition_id: &[u8; 32],
|
|
account: &str,
|
|
amount: u64,
|
|
) -> Result<()> {
|
|
let partition_id_hex = hex::encode(partition_id);
|
|
let partition = self
|
|
.partitions
|
|
.get_mut(&partition_id_hex)
|
|
.ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex.clone()))?;
|
|
|
|
if !partition.info.is_active {
|
|
return Err(Acc1410Error::PartitionClosed(partition_id_hex));
|
|
}
|
|
|
|
let available = partition.balance_of(account);
|
|
if available < amount {
|
|
return Err(Acc1410Error::InsufficientBalance {
|
|
account: account.to_string(),
|
|
required: amount,
|
|
available,
|
|
});
|
|
}
|
|
|
|
partition.sub_balance(account, amount);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn get_all_partition_ids(&self) -> Vec<[u8; 32]> {
|
|
self.partitions
|
|
.keys()
|
|
.filter_map(|id_hex| {
|
|
let bytes = hex::decode(id_hex).ok()?;
|
|
if bytes.len() == 32 {
|
|
let mut arr = [0u8; 32];
|
|
arr.copy_from_slice(&bytes);
|
|
Some(arr)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn current_timestamp() -> u64 {
|
|
std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_secs()
|
|
}
|
|
}
|
|
|
|
impl Default for PartitionManager {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|