use crate::common::{Address as RewardsAddress, Amount};
#[cfg(test)]
use crate::common::U256;
use serde::{Deserialize, Serialize};
pub type PoolHash = [u8; 32];
pub const CANDIDATES_PER_POOL: usize = 16;
pub const MAX_MERKLE_DEPTH: u8 = 8;
pub fn expected_reward_pools(depth: u8) -> usize {
let half_depth = depth.div_ceil(2);
1 << half_depth
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PoolCommitment {
pub pool_hash: PoolHash,
pub candidates: [CandidateNode; CANDIDATES_PER_POOL],
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CandidateNode {
pub rewards_address: RewardsAddress,
pub price: Amount,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct OnChainPaymentInfo {
pub depth: u8,
pub merkle_payment_timestamp: u64,
pub paid_node_addresses: Vec<(RewardsAddress, usize, Amount)>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_expected_reward_pools() {
assert_eq!(expected_reward_pools(1), 2);
assert_eq!(expected_reward_pools(2), 2);
assert_eq!(expected_reward_pools(3), 4);
assert_eq!(expected_reward_pools(4), 4);
assert_eq!(expected_reward_pools(8), 16);
}
#[test]
fn test_candidate_node_price() {
let candidate = CandidateNode {
rewards_address: RewardsAddress::from([0x42; 20]),
price: U256::from(1000u64),
};
assert_eq!(candidate.price, U256::from(1000u64));
assert_eq!(candidate.rewards_address, RewardsAddress::from([0x42; 20]));
}
#[test]
fn test_pool_commitment_structure() {
let candidates: [CandidateNode; CANDIDATES_PER_POOL] =
std::array::from_fn(|i| CandidateNode {
rewards_address: RewardsAddress::from([i as u8; 20]),
price: U256::from((i as u64 + 1) * 100),
});
let pool = PoolCommitment {
pool_hash: [0x42; 32],
candidates,
};
assert_eq!(pool.pool_hash, [0x42; 32]);
assert_eq!(pool.candidates.len(), CANDIDATES_PER_POOL);
assert_eq!(pool.candidates[0].price, U256::from(100u64));
assert_eq!(pool.candidates[15].price, U256::from(1600u64));
}
}