pchain_world_state/network/
pool.rs

1/*
2    Copyright © 2023, ParallelChain Lab 
3    Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
4*/
5
6//! Definition of Key Format of Pool in Storage of Network Account
7
8use std::{
9    ops::Deref, 
10    convert::{TryInto, TryFrom}
11};
12use pchain_types::{ serialization::{Serializable, Deserializable}, cryptography::PublicAddress};
13
14use super::{
15    stake::{Stake, StakeValue}, 
16    network_account::{NetworkAccountStorage, KeySpaced}, 
17    index_map::{IndexMap, IndexMapOperationError}, 
18    index_heap::IndexHeap
19};
20
21/// Pool is the place that stake owners can stake to.
22#[derive(Debug, Clone, PartialEq, Eq, borsh::BorshSerialize, borsh::BorshDeserialize)]
23pub struct Pool {
24    /// Address of the pool's operator
25    pub operator: PublicAddress,
26    /// Commission rate (in unit of percentage) is the portion that 
27    /// the owners of its delegated stakes should pay from the reward in an epoch transaction.
28    pub commission_rate: u8,
29    /// Pool's power that determines the eligibility to be one of the validator
30    pub power: u64,
31    /// Operator's own stake
32    pub operator_stake: Option<Stake>
33}
34
35impl Serializable for Pool {}
36impl Deserializable for Pool {}
37
38/// PoolDict defines key formatting for dictionary-like read-write operations to Pool state in a Network Account.
39pub struct PoolDict<'a, S, const M: u16>
40    where S: NetworkAccountStorage
41{
42    pub(in crate::network) prefix_key: Vec<u8>,
43    pub(in crate::network) world_state: &'a mut S
44}
45
46impl<'a, S, const M: u16> PoolDict<'a, S, M> 
47    where S: NetworkAccountStorage
48{
49    pub fn exists(&self) -> bool {
50        let key = [self.prefix_key.as_slice(), &pool_data::OPERATOR].concat();
51        self.world_state.contains(&key)
52    }
53
54    pub fn operator(&self) -> Option<PublicAddress> {
55        let bytes = self.world_state.get(&[self.prefix_key.as_slice(), &pool_data::OPERATOR].concat())?;
56        match bytes.try_into() {
57            Ok(address) => Some(address),
58            Err(_) => None
59        }
60    }
61
62    pub fn set_operator(&mut self, operator: PublicAddress) {
63        self.world_state.set(&[self.prefix_key.as_slice(), &pool_data::OPERATOR].concat(), operator.to_vec());
64    }
65
66    pub fn power(&self) -> Option<u64> {
67        let bytes = self.world_state.get(&[self.prefix_key.as_slice(), &pool_data::POWER].concat())?;
68        match bytes.try_into() {
69            Ok(value) => Some(u64::from_le_bytes(value)),
70            Err(_) => None
71        }
72    }
73
74    pub fn set_power(&mut self, power: u64) {
75        self.world_state.set(&[self.prefix_key.as_slice(), &pool_data::POWER].concat(), power.to_le_bytes().to_vec());
76    }
77
78    pub fn commission_rate(&self) -> Option<u8> {
79        let bytes = self.world_state.get(&[self.prefix_key.as_slice(), &pool_data::COMMISSION_RATE].concat())?;
80        match bytes.try_into() {
81            Ok(value) => Some(u8::from_le_bytes(value)),
82            Err(_) => None
83        }
84    }
85
86    pub fn set_commission_rate(&mut self, commission_rate: u8) {
87        self.world_state.set(&[self.prefix_key.as_slice(), &pool_data::COMMISSION_RATE].concat(), commission_rate.to_le_bytes().to_vec());
88    }
89
90    pub fn operator_stake(&self) -> Option<Option<Stake>> {
91        self.world_state.get(&[self.prefix_key.as_slice(), &pool_data::OPERATOR_STAKE].concat()).map(|bytes|{
92            Option::<Stake>::deserialize(&bytes).unwrap()
93        })
94    }
95
96    pub fn set_operator_stake(&mut self, stake: Option<Stake>) {
97        self.world_state.set(&[self.prefix_key.as_slice(), &pool_data::OPERATOR_STAKE].concat(), Option::<Stake>::serialize(&stake));
98    }
99
100    pub fn delegated_stakes(&mut self) -> IndexHeap<S, StakeValue> {
101        IndexHeap::<S, StakeValue>::new(
102            [self.prefix_key.as_slice(), &pool_data::DELEGATED_STAKES].concat(),
103            self.world_state, 
104            M as u32,
105        )
106    }
107
108    pub fn delete(&'a mut self) {
109        for k in vec![
110            [self.prefix_key.as_slice(), &pool_data::OPERATOR].concat(),
111            [self.prefix_key.as_slice(), &pool_data::POWER].concat(),
112            [self.prefix_key.as_slice(), &pool_data::COMMISSION_RATE].concat(),
113            [self.prefix_key.as_slice(), &pool_data::OPERATOR_STAKE].concat(),
114        ] {
115            self.world_state.delete(k.as_slice());
116        }
117
118        self.delegated_stakes().clear();
119    }
120}
121
122impl<'a, S, const M: u16> TryFrom<PoolDict<'a, S, M>> for Pool 
123    where S: NetworkAccountStorage
124{
125    type Error = ();
126    fn try_from(pool: PoolDict<'a, S, M>) -> Result<Self, Self::Error> {
127        Ok(Pool { 
128            operator: pool.operator().ok_or(())?, 
129            commission_rate: pool.commission_rate().ok_or(())?, 
130            power: pool.power().ok_or(())?, 
131            operator_stake: pool.operator_stake().ok_or(())? 
132        })
133    }
134}
135
136
137/// ValidatorPool defines the pool value to be stored in state of a Network Account. 
138/// Different from [PoolDict], fields are stored as a single value in the Key-Value storage, 
139/// rather than assigning keyspaces to each fields as a dictionary.
140pub struct ValidatorPool<'a, S, const N: u16, const M: u16> where S: NetworkAccountStorage
141{
142    inner: IndexMap<'a, S, PoolAddress>
143}
144
145
146impl<'a, S, const N: u16, const M: u16> ValidatorPool<'a, S, N, M> where S: NetworkAccountStorage
147{
148    /// A single byte prefix key to partition the Pool values (as a nested IndexMap) and IndexMap ValidatorPool itself.
149    /// ### Cautions
150    /// The value 3u8 is chosen because the value 0u8, 1u8 and 2u8 are already chosen in IndexMap.
151    pub(in crate::network) const PREFIX_NESTED_MAP: [u8; 1] = [3u8];
152
153    pub(in crate::network) fn new(world_state: &'a mut S, prefix_key: Vec<u8>) -> Self {
154        Self {
155            inner: IndexMap::<S, PoolAddress>::new(
156                prefix_key,
157                world_state, 
158                N as u32,
159            )
160        }
161    }
162
163    pub fn length(&self) -> u32 {
164        self.inner.length()
165    }
166
167    pub fn pool(&mut self, operator: PublicAddress) -> Option<PoolDict<S, M>> {
168        self.inner.get_by(PoolAddress(operator).key())?;
169        
170        Some(PoolDict {
171            prefix_key: [self.inner.domain.as_slice(), &Self::PREFIX_NESTED_MAP, operator.as_slice()].concat(),
172            world_state: self.inner.store
173        })
174    }
175
176    pub fn pool_at(&mut self, index: u32) -> Option<PoolDict<S, M>> {
177        let pool_address = self.inner.get(index)?;
178        self.pool(pool_address.into())
179    }
180
181    /// Push pool value to Index Map with reset of delegated stakes.
182    pub fn push(&'a mut self, pool: Pool, delegated_stakes: Vec<StakeValue>) -> Result<(), IndexMapOperationError> {
183        // push pool address to the list first
184        self.inner.push(PoolAddress(pool.operator))?;
185
186        // set pool value
187        let mut pool_dict = self.pool(pool.operator).unwrap();
188        pool_dict.set_operator(pool.operator);
189        pool_dict.set_power(pool.power);
190        pool_dict.set_commission_rate(pool.commission_rate);
191        pool_dict.set_operator_stake(pool.operator_stake);
192
193        // set delegated stakes
194        let _ = pool_dict.delegated_stakes().reset(delegated_stakes);
195        Ok(())
196    }
197
198    /// Clear pool and it's delegated stakes.
199    pub fn clear(&'a mut self) {
200        let pool_length = self.length();
201        for i in 0..pool_length {
202            let mut pool = self.pool_at(i).unwrap();
203            pool.delegated_stakes().clear();
204            pool.delete();
205        }
206        self.inner.set_length(0);
207    }
208
209    pub fn get(&self, index: u32) -> Option<PoolAddress> {
210        self.inner.get(index)
211    }
212
213}
214
215mod pool_data {
216    pub const OPERATOR: [u8; 1] = [0x0];
217    pub const POWER: [u8; 1] = [0x1];
218    pub const COMMISSION_RATE: [u8; 1] = [0x2];
219    pub const OPERATOR_STAKE: [u8; 1] = [0x3];
220    pub const DELEGATED_STAKES: [u8; 1] = [0x4];
221}
222
223/// PoolAddress is the value store inside the IndexMap for Validator Set (Previous and Current). 
224/// Different with [PoolKey], power is not needed because PVP and VP does not need to implement a binary heap.
225#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
226pub struct PoolAddress(pub PublicAddress);
227
228impl KeySpaced for PoolAddress {
229    fn key(&self) -> &[u8] {
230        &self.0
231    }
232}
233
234impl From<PoolAddress> for Vec<u8>{
235    fn from(value: PoolAddress) -> Vec<u8> {
236        value.0.to_vec()
237    }
238}
239
240impl From<Vec<u8>> for PoolAddress {
241    fn from(value: Vec<u8>) -> Self {
242        Self(value.try_into().unwrap())
243    }
244}
245
246impl From<PoolAddress> for PublicAddress {
247    fn from(value: PoolAddress) -> Self {
248        value.0
249    }
250}
251
252impl Deref for PoolAddress {
253    type Target = PublicAddress;
254    fn deref(&self) -> &Self::Target {
255        &self.0
256    }
257}
258
259#[derive(Clone)]
260/// PoolKey is a small description of a pool. It affects the order of its representing pool in the Index Heap which is the state format of next validator set.
261pub struct PoolKey {
262    pub operator: PublicAddress,
263    pub power: u64
264}
265
266impl PoolKey {
267    pub fn new(operator: PublicAddress, power: u64) -> Self {
268        Self { operator, power }
269    }
270}
271
272impl KeySpaced for PoolKey {
273    fn key(&self) -> &[u8] {
274        self.operator.as_slice()
275    }
276}
277
278impl Eq for PoolKey {}
279
280impl PartialEq for PoolKey {
281    fn eq(&self, other: &Self) -> bool {
282        match self.power.eq(&other.power) {
283            true => self.operator.eq(&other.operator),
284            false => false,
285        }
286    }
287}
288
289impl PartialOrd for PoolKey {
290    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
291        match self.power.partial_cmp(&other.power) {
292            Some(std::cmp::Ordering::Equal) => self.operator.partial_cmp(&other.operator),
293            Some(compare) => Some(compare),
294            None => None
295        }
296    }
297}
298
299impl Ord for PoolKey {
300    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
301        match self.power.cmp(&other.power) {
302            std::cmp::Ordering::Equal => self.operator.cmp(&other.operator),
303            compare => compare
304        }
305    }
306}
307
308impl From<PoolKey> for Vec<u8> {
309    fn from(pool_key: PoolKey) -> Self {
310        <(Vec<u8>, u64)>::serialize(&(pool_key.operator.to_vec(), pool_key.power))
311    }
312}
313
314impl From<Vec<u8>> for PoolKey {
315    fn from(bytes: Vec<u8>) -> Self {
316        let (operator, power) = <(Vec<u8>, u64)>::deserialize(&bytes).unwrap();
317        Self { operator: operator.try_into().unwrap(), power }
318    }
319}