Skip to content

Commit 4c8cc85

Browse files
committed
feat(data_structures): incorporate stakes tracker into ChainState
1 parent f53d78d commit 4c8cc85

File tree

7 files changed

+61
-23
lines changed

7 files changed

+61
-23
lines changed

data_structures/src/capabilities.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use serde::{Deserialize, Serialize};
2+
13
#[repr(u8)]
24
#[derive(Clone, Copy, Debug)]
35
pub enum Capability {
@@ -7,7 +9,7 @@ pub enum Capability {
79
Witnessing = 1,
810
}
911

10-
#[derive(Copy, Clone, Debug, Default, PartialEq)]
12+
#[derive(Copy, Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
1113
pub struct CapabilityMap<T>
1214
where
1315
T: Default,

data_structures/src/chain/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use crate::{
4343
versioning::{ProtocolVersion, Versioned},
4444
ProtobufConvert,
4545
},
46+
staking::prelude::*,
4647
superblock::SuperBlockState,
4748
transaction::{
4849
CommitTransaction, DRTransaction, DRTransactionBody, Memoized, MintTransaction,
@@ -54,6 +55,7 @@ use crate::{
5455
},
5556
utxo_pool::{OldUnspentOutputsPool, OwnUnspentOutputsPool, UnspentOutputsPool},
5657
vrf::{BlockEligibilityClaim, DataRequestEligibilityClaim},
58+
wit::Wit,
5759
};
5860

5961
/// Keeps track of priority being used by transactions included in recent blocks, and provides
@@ -3776,6 +3778,8 @@ pub struct ChainState {
37763778
/// Unspent Outputs Pool
37773779
#[serde(skip)]
37783780
pub unspent_outputs_pool: UnspentOutputsPool,
3781+
/// Tracks stakes for every validator in the network
3782+
pub stakes: Stakes<PublicKeyHash, Wit, Epoch, u64>,
37793783
}
37803784

37813785
impl ChainState {

data_structures/src/staking/aux.rs

+33-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,43 @@
11
use std::{rc::Rc, str::FromStr, sync::RwLock};
22

3-
use super::prelude::*;
3+
use serde::{Deserialize, Serialize};
44

5-
/// Type alias for a reference-counted and read-write-locked instance of `Stake`.
6-
pub type SyncStake<Address, Coins, Epoch, Power> = Rc<RwLock<Stake<Address, Coins, Epoch, Power>>>;
5+
use super::prelude::*;
76

87
/// The resulting type for all the fallible functions in this module.
9-
pub type StakingResult<T, Address, Coins, Epoch> =
10-
Result<T, StakesError<Address, Coins, Epoch>>;
8+
pub type StakingResult<T, Address, Coins, Epoch> = Result<T, StakesError<Address, Coins, Epoch>>;
9+
10+
/// Newtype for a reference-counted and read-write-locked instance of `Stake`.
11+
///
12+
/// This newtype is needed for implementing `PartialEq` manually on the locked data, which cannot be done directly
13+
/// because those are externally owned types.
14+
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
15+
pub struct SyncStake<Address, Coins, Epoch, Power>
16+
where
17+
Address: Default,
18+
Epoch: Default,
19+
{
20+
/// The lock itself.
21+
pub value: Rc<RwLock<Stake<Address, Coins, Epoch, Power>>>,
22+
}
23+
24+
impl<Address, Coins, Epoch, Power> PartialEq for SyncStake<Address, Coins, Epoch, Power>
25+
where
26+
Address: Default,
27+
Epoch: Default + PartialEq,
28+
Coins: PartialEq,
29+
{
30+
fn eq(&self, other: &Self) -> bool {
31+
let self_stake = self.value.read().unwrap();
32+
let other_stake = other.value.read().unwrap();
33+
34+
self_stake.coins.eq(&other_stake.coins) && other_stake.epochs.eq(&other_stake.epochs)
35+
}
36+
}
1137

1238
/// Couples a validator address with a withdrawer address together. This is meant to be used in `Stakes` as the index
1339
/// for the `by_key` index.
14-
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
40+
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
1541
pub struct StakeKey<Address> {
1642
/// A validator address.
1743
pub validator: Address,
@@ -46,7 +72,7 @@ where
4672

4773
/// Couples an amount of coins, a validator address and a withdrawer address together. This is meant to be used in
4874
/// `Stakes` as the index of the `by_coins` index.
49-
#[derive(Eq, Ord, PartialEq, PartialOrd)]
75+
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
5076
pub struct CoinsAndAddresses<Coins, Address> {
5177
/// An amount of coins.
5278
pub coins: Coins,

data_structures/src/staking/stake.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use std::marker::PhantomData;
22

3+
use serde::{Deserialize, Serialize};
4+
35
use super::prelude::*;
46

57
/// A data structure that keeps track of a staker's staked coins and the epochs for different
68
/// capabilities.
7-
#[derive(Copy, Clone, Debug, Default, PartialEq)]
9+
#[derive(Copy, Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
810
pub struct Stake<Address, Coins, Epoch, Power>
911
where
1012
Address: Default,

data_structures/src/staking/stakes.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
use std::collections::btree_map::Entry;
2-
use std::collections::BTreeMap;
1+
use std::collections::{btree_map::Entry, BTreeMap};
32

43
use itertools::Itertools;
4+
use serde::{Deserialize, Serialize};
55

66
use super::prelude::*;
77

88
/// The main data structure that provides the "stakes tracker" functionality.
99
///
1010
/// This structure holds indexes of stake entries. Because the entries themselves are reference
1111
/// counted and write-locked, we can have as many indexes here as we need at a negligible cost.
12-
#[derive(Default)]
12+
#[derive(Clone, Debug, Deserialize, Default, PartialEq, Serialize)]
1313
pub struct Stakes<Address, Coins, Epoch, Power>
1414
where
15-
Address: Default,
15+
Address: Default + Ord,
16+
Coins: Ord,
1617
Epoch: Default,
1718
{
1819
/// A listing of all the stakers, indexed by their address.
@@ -61,10 +62,11 @@ where
6162
let key = key.into();
6263

6364
// Find or create a matching stake entry
64-
let stake_arc = self.by_key.entry(key.clone()).or_default();
65+
let stake = self.by_key.entry(key.clone()).or_default();
6566

6667
// Actually increase the number of coins
67-
stake_arc
68+
stake
69+
.value
6870
.write()?
6971
.add_stake(coins, epoch, self.minimum_stakeable)?;
7072

@@ -75,9 +77,9 @@ where
7577
addresses: key,
7678
};
7779
self.by_coins.remove(&key);
78-
self.by_coins.insert(key, stake_arc.clone());
80+
self.by_coins.insert(key, stake.clone());
7981

80-
Ok(stake_arc.read()?.clone())
82+
Ok(stake.value.read()?.clone())
8183
}
8284

8385
/// Obtain a list of stakers, conveniently ordered by one of several strategies.
@@ -126,6 +128,7 @@ where
126128
.by_key
127129
.get(&key)
128130
.ok_or(StakesError::EntryNotFound { key })?
131+
.value
129132
.read()?
130133
.power(capability, epoch))
131134
}
@@ -141,6 +144,7 @@ where
141144
.iter()
142145
.flat_map(move |(CoinsAndAddresses { addresses, .. }, stake)| {
143146
stake
147+
.value
144148
.read()
145149
.map(move |stake| (addresses.clone(), stake.power(capability, current_epoch)))
146150
})
@@ -161,7 +165,7 @@ where
161165

162166
if let Entry::Occupied(mut by_address_entry) = self.by_key.entry(key.clone()) {
163167
let (initial_coins, final_coins) = {
164-
let mut stake = by_address_entry.get_mut().write()?;
168+
let mut stake = by_address_entry.get_mut().value.write()?;
165169

166170
// Check the former amount of stake
167171
let initial_coins = stake.coins;
@@ -204,6 +208,7 @@ where
204208
.by_key
205209
.get_mut(&key)
206210
.ok_or(StakesError::EntryNotFound { key })?
211+
.value
207212
.write()?;
208213
stake.epochs.update(capability, current_epoch);
209214

node/src/actors/chain_manager/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ use witnet_data_structures::{
7171
data_request::DataRequestPool,
7272
get_environment,
7373
radon_report::{RadonReport, ReportContext},
74-
staking::prelude::*,
7574
superblock::{ARSIdentities, AddSuperBlockVote, SuperBlockConsensus},
7675
transaction::{RevealTransaction, TallyTransaction, Transaction},
7776
types::{
@@ -80,7 +79,6 @@ use witnet_data_structures::{
8079
},
8180
utxo_pool::{Diff, OwnUnspentOutputsPool, UnspentOutputsPool, UtxoWriteBatch},
8281
vrf::VrfCtx,
83-
wit::Wit,
8482
};
8583
use witnet_rad::types::RadonTypes;
8684
use witnet_util::timestamp::seconds_to_human_string;
@@ -249,8 +247,6 @@ pub struct ChainManager {
249247
import: Force<ChainImport<ImportError>>,
250248
/// Signals that a chain snapshot export is due.
251249
export: Force<PathBuf>,
252-
/// Tracks stakes for every validator in the network.
253-
stakes: Stakes<PublicKeyHash, Wit, Epoch, u64>,
254250
}
255251

256252
impl ChainManager {

wallet/src/db/encrypted/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ use std::sync::Arc;
44
use witnet_crypto::cipher;
55

66
use super::*;
7-
use crate::{db::{encrypted::write_batch::EncryptedWriteBatch, GetWith}, types};
7+
use crate::{
8+
db::{encrypted::write_batch::EncryptedWriteBatch, GetWith},
9+
types,
10+
};
811

912
mod engine;
1013
mod prefix;

0 commit comments

Comments
 (0)