use serde::{Deserialize, Serialize};
use thiserror::Error;
pub const ADDRESS_SIZE: usize = 12;
pub const HASH_SIZE: usize = 32;
pub const SLOT_SIZE: usize = 64;
pub const PULSE_INTERVAL_MS: u64 = 1500;
pub const DEFAULT_LADDER_HEIGHT: usize = 100_000;
pub const COIN_DECIMALS: u32 = 8; pub const COIN: u64 = 10_u64.pow(COIN_DECIMALS); pub const MAX_SUPPLY: u64 = 19_000_000 * COIN; pub const HALVING_PULSES: u64 = 84_000_000;
pub const GENESIS_REWARD: u64 = MAX_SUPPLY / 2 / HALVING_PULSES;
pub type Address = [u8; ADDRESS_SIZE];
pub type Hash = [u8; HASH_SIZE];
pub type NanoYD = u64;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub struct Slot {
pub pulse_id: u32,
pub user_address: Address,
pub ladder_id: u32,
pub step_number: u32,
pub balance: NanoYD,
pub last_hash: Hash,
}
impl Slot {
pub fn new(user_address: Address, ladder_id: u32, step_number: u32, last_hash: Hash) -> Self {
Self {
pulse_id: 0,
user_address,
ladder_id,
step_number,
balance: 0,
last_hash,
}
}
pub fn to_bytes(&self) -> [u8; SLOT_SIZE] {
let mut bytes = [0u8; SLOT_SIZE];
bytes[0..4].copy_from_slice(&self.pulse_id.to_le_bytes());
bytes[4..16].copy_from_slice(&self.user_address);
bytes[16..20].copy_from_slice(&self.ladder_id.to_le_bytes());
bytes[20..24].copy_from_slice(&self.step_number.to_le_bytes());
bytes[24..32].copy_from_slice(&self.balance.to_le_bytes());
bytes[32..64].copy_from_slice(&self.last_hash);
bytes
}
pub fn from_bytes(bytes: &[u8; SLOT_SIZE]) -> Self {
let pulse_id = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
let mut user_address = [0u8; ADDRESS_SIZE];
user_address.copy_from_slice(&bytes[4..16]);
let ladder_id = u32::from_le_bytes(bytes[16..20].try_into().unwrap());
let step_number = u32::from_le_bytes(bytes[20..24].try_into().unwrap());
let balance = u64::from_le_bytes(bytes[24..32].try_into().unwrap());
let mut last_hash = [0u8; HASH_SIZE];
last_hash.copy_from_slice(&bytes[32..64]);
Self {
pulse_id,
user_address,
ladder_id,
step_number,
balance,
last_hash,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SlotKey {
pub user_address: Address,
pub ladder_id: u32,
pub last_hash: Hash,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Transaction {
pub timestamp: u32,
pub from: Address,
pub to: Address,
pub amount: NanoYD,
pub proof: Hash,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotepadEntry {
pub pulse_id: u32,
pub timestamp: u64, pub root_hash: Hash, pub pulse_hash: u32, }
#[derive(Error, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum YedadError {
#[error("Invalid proof")]
InvalidProof,
#[error("Insufficient balance")]
InsufficientBalance,
#[error("Account not found")]
AccountNotFound,
#[error("Ladder exhausted")]
LadderExhausted,
#[error("Arithmetic overflow")]
ArithmeticOverflow,
#[error("Already exists")]
AlreadyExists,
#[error("IO error: {0}")]
Io(String),
}
pub fn address_to_string(address: &Address) -> String {
hex::encode(address)
}
pub fn string_to_address(s: &str) -> Result<Address, hex::FromHexError> {
let bytes = hex::decode(s)?;
let mut addr = [0u8; ADDRESS_SIZE];
addr.copy_from_slice(&bytes);
Ok(addr)
}