pot_o_extensions/
pool_strategy.rs1use pot_o_core::TribeResult;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11pub enum PoolType {
12 Solo,
13 Proportional,
14 PPLNS,
15 Custom,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct MinerShare {
20 pub miner_pubkey: String,
21 pub share_pct: f64,
22 pub reward_amount: u64,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct MinerInfo {
27 pub pubkey: String,
28 pub stake: u64,
29 pub proofs_submitted: u64,
30 pub reputation: f64,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct ProofRecord {
35 pub miner_pubkey: String,
36 pub challenge_id: String,
37 pub reward: u64,
38 pub timestamp: chrono::DateTime<chrono::Utc>,
39}
40
41#[derive(Debug, Clone, Default, Serialize, Deserialize)]
42pub struct PoolInfo {
43 pub pool_type: String,
44 pub total_miners: usize,
45 pub total_stake: u64,
46 pub minimum_stake: u64,
47}
48
49pub trait PoolStrategy: Send + Sync {
55 fn pool_type(&self) -> PoolType;
56 fn calculate_shares(&self, proofs: &[ProofRecord], reward: u64)
57 -> TribeResult<Vec<MinerShare>>;
58 fn minimum_stake(&self) -> u64;
59 fn accept_miner(&self, miner: &MinerInfo) -> TribeResult<bool>;
60 fn pool_info(&self, miners: usize, total_stake: u64) -> PoolInfo;
61}
62
63pub struct SoloStrategy;
68
69impl PoolStrategy for SoloStrategy {
70 fn pool_type(&self) -> PoolType {
71 PoolType::Solo
72 }
73
74 fn calculate_shares(
75 &self,
76 proofs: &[ProofRecord],
77 reward: u64,
78 ) -> TribeResult<Vec<MinerShare>> {
79 Ok(proofs
81 .last()
82 .map(|p| {
83 vec![MinerShare {
84 miner_pubkey: p.miner_pubkey.clone(),
85 share_pct: 100.0,
86 reward_amount: reward,
87 }]
88 })
89 .unwrap_or_default())
90 }
91
92 fn minimum_stake(&self) -> u64 {
93 0 }
95
96 fn accept_miner(&self, _miner: &MinerInfo) -> TribeResult<bool> {
97 Ok(true)
98 }
99
100 fn pool_info(&self, miners: usize, total_stake: u64) -> PoolInfo {
101 PoolInfo {
102 pool_type: "solo".into(),
103 total_miners: miners,
104 total_stake,
105 minimum_stake: 0,
106 }
107 }
108}
109
110pub struct ProportionalPool {
115 pub min_stake: u64,
116}
117
118impl PoolStrategy for ProportionalPool {
119 fn pool_type(&self) -> PoolType {
120 PoolType::Proportional
121 }
122
123 fn calculate_shares(
124 &self,
125 _proofs: &[ProofRecord],
126 _reward: u64,
127 ) -> TribeResult<Vec<MinerShare>> {
128 todo!("Proportional reward distribution not yet implemented")
129 }
130
131 fn minimum_stake(&self) -> u64 {
132 self.min_stake
133 }
134
135 fn accept_miner(&self, miner: &MinerInfo) -> TribeResult<bool> {
136 Ok(miner.stake >= self.min_stake)
137 }
138
139 fn pool_info(&self, miners: usize, total_stake: u64) -> PoolInfo {
140 PoolInfo {
141 pool_type: "proportional".into(),
142 total_miners: miners,
143 total_stake,
144 minimum_stake: self.min_stake,
145 }
146 }
147}
148
149pub struct PPLNSPool {
154 pub window_size: usize,
155 pub min_stake: u64,
156}
157
158impl PoolStrategy for PPLNSPool {
159 fn pool_type(&self) -> PoolType {
160 PoolType::PPLNS
161 }
162
163 fn calculate_shares(
164 &self,
165 _proofs: &[ProofRecord],
166 _reward: u64,
167 ) -> TribeResult<Vec<MinerShare>> {
168 todo!("PPLNS reward distribution not yet implemented")
169 }
170
171 fn minimum_stake(&self) -> u64 {
172 self.min_stake
173 }
174
175 fn accept_miner(&self, miner: &MinerInfo) -> TribeResult<bool> {
176 Ok(miner.stake >= self.min_stake)
177 }
178
179 fn pool_info(&self, miners: usize, total_stake: u64) -> PoolInfo {
180 PoolInfo {
181 pool_type: "pplns".into(),
182 total_miners: miners,
183 total_stake,
184 minimum_stake: self.min_stake,
185 }
186 }
187}