-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(data_structures): adapt stakes tracker to latest specs
fix #2398
- Loading branch information
1 parent
f9790bc
commit 4d19e09
Showing
11 changed files
with
773 additions
and
487 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#[macro_use] | ||
extern crate bencher; | ||
use bencher::Bencher; | ||
use rand::Rng; | ||
use witnet_data_structures::staking::prelude::*; | ||
|
||
fn populate(b: &mut Bencher) { | ||
let mut stakes = Stakes::<String, u64, u64, u64>::default(); | ||
let mut i = 1; | ||
|
||
b.iter(|| { | ||
let address = format!("{i}"); | ||
let coins = i; | ||
let epoch = i; | ||
stakes.add_stake(address, coins, epoch).unwrap(); | ||
|
||
i += 1; | ||
}); | ||
} | ||
|
||
fn rank(b: &mut Bencher) { | ||
let mut stakes = Stakes::<String, u64, u64, u64>::default(); | ||
let mut i = 1; | ||
|
||
let stakers = 100_000; | ||
let rf = 10; | ||
|
||
let mut rng = rand::thread_rng(); | ||
|
||
loop { | ||
let coins = i; | ||
let epoch = i; | ||
let address = format!("{}", rng.gen::<u64>()); | ||
|
||
stakes.add_stake(address, coins, epoch).unwrap(); | ||
|
||
i += 1; | ||
|
||
if i == stakers { | ||
break; | ||
} | ||
} | ||
|
||
b.iter(|| { | ||
let rank = stakes.rank(Capability::Mining, i); | ||
let mut top = rank.take(usize::try_from(stakers / rf).unwrap()); | ||
let _first = top.next(); | ||
let _last = top.last(); | ||
|
||
i += 1; | ||
}) | ||
} | ||
|
||
fn query_power(b: &mut Bencher) { | ||
let mut stakes = Stakes::<String, u64, u64, u64>::default(); | ||
let mut i = 1; | ||
|
||
let stakers = 100_000; | ||
|
||
loop { | ||
let coins = i; | ||
let epoch = i; | ||
let address = format!("{i}"); | ||
|
||
stakes.add_stake(address, coins, epoch).unwrap(); | ||
|
||
i += 1; | ||
|
||
if i == stakers { | ||
break; | ||
} | ||
} | ||
|
||
i = 1; | ||
|
||
b.iter(|| { | ||
let address = format!("{i}"); | ||
let _power = stakes.query_power(&address, Capability::Mining, i); | ||
|
||
i += 1; | ||
}) | ||
} | ||
|
||
benchmark_main!(benches); | ||
benchmark_group!(benches, populate, rank, query_power); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#[repr(u8)] | ||
#[derive(Clone, Copy, Debug)] | ||
pub enum Capability { | ||
/// The base block mining and superblock voting capability | ||
Mining = 0, | ||
/// The universal HTTP GET / HTTP POST / WIP-0019 RNG capability | ||
Witnessing = 1, | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, Default, PartialEq)] | ||
pub struct CapabilityMap<T> | ||
where | ||
T: Default, | ||
{ | ||
pub mining: T, | ||
pub witnessing: T, | ||
} | ||
|
||
impl<T> CapabilityMap<T> | ||
where | ||
T: Copy + Default, | ||
{ | ||
#[inline] | ||
pub fn get(&self, capability: Capability) -> T { | ||
match capability { | ||
Capability::Mining => self.mining, | ||
Capability::Witnessing => self.witnessing, | ||
} | ||
} | ||
|
||
#[inline] | ||
pub fn update(&mut self, capability: Capability, value: T) { | ||
match capability { | ||
Capability::Mining => self.mining = value, | ||
Capability::Witnessing => self.witnessing = value, | ||
} | ||
} | ||
|
||
#[inline] | ||
pub fn update_all(&mut self, value: T) { | ||
self.mining = value; | ||
self.witnessing = value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use std::rc::Rc; | ||
use std::sync::RwLock; | ||
|
||
use super::prelude::*; | ||
|
||
/// Type alias for a reference-counted and read-write-locked instance of `Stake`. | ||
pub type SyncStake<Address, Coins, Epoch, Power> = Rc<RwLock<Stake<Address, Coins, Epoch, Power>>>; | ||
|
||
/// The resulting type for all the fallible functions in this module. | ||
pub type Result<T, Address, Coins, Epoch> = | ||
std::result::Result<T, StakesError<Address, Coins, Epoch>>; | ||
|
||
/// Couples an amount of coins and an address together. This is to be used in `Stakes` as the index | ||
/// of the `by_coins` index.. | ||
#[derive(Eq, Ord, PartialEq, PartialOrd)] | ||
pub struct CoinsAndAddress<Coins, Address> { | ||
/// An amount of coins. | ||
pub coins: Coins, | ||
/// The address of a staker. | ||
pub address: Address, | ||
} | ||
|
||
/// Allows telling the `census` method in `Stakes` to source addresses from its internal `by_coins` | ||
/// following different strategies. | ||
#[repr(u8)] | ||
#[derive(Clone, Copy, Debug)] | ||
pub enum CensusStrategy { | ||
/// Retrieve all addresses, ordered by decreasing power. | ||
All = 0, | ||
/// Retrieve every Nth address, ordered by decreasing power. | ||
StepBy(usize) = 1, | ||
/// Retrieve the most powerful N addresses, ordered by decreasing power. | ||
Take(usize) = 2, | ||
/// Retrieve a total of N addresses, evenly distributed from the index, ordered by decreasing | ||
/// power. | ||
Evenly(usize) = 3, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/// A minimum stakeable amount needs to exist to prevent spamming of the tracker. | ||
pub const MINIMUM_STAKEABLE_AMOUNT_WITS: u64 = 100; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
use std::sync::PoisonError; | ||
|
||
/// All errors related to the staking functionality. | ||
#[derive(Debug, PartialEq)] | ||
pub enum StakesError<Address, Coins, Epoch> { | ||
/// The amount of coins being staked or the amount that remains after unstaking is below the | ||
/// minimum stakeable amount. | ||
AmountIsBelowMinimum { | ||
/// The number of coins being staked or remaining after staking. | ||
amount: Coins, | ||
/// The minimum stakeable amount. | ||
minimum: Coins, | ||
}, | ||
/// Tried to query `Stakes` for information that belongs to the past. | ||
EpochInThePast { | ||
/// The Epoch being referred. | ||
epoch: Epoch, | ||
/// The latest Epoch. | ||
latest: Epoch, | ||
}, | ||
/// An operation thrown an Epoch value that overflows. | ||
EpochOverflow { | ||
/// The computed Epoch value. | ||
computed: u64, | ||
/// The maximum Epoch. | ||
maximum: Epoch, | ||
}, | ||
/// Tried to query `Stakes` for the address of a staker that is not registered in `Stakes`. | ||
IdentityNotFound { | ||
/// The unknown address. | ||
identity: Address, | ||
}, | ||
/// Tried to obtain a lock on a write-locked piece of data that is already locked. | ||
PoisonedLock, | ||
} | ||
|
||
impl<T, Address, Coins, Epoch> From<PoisonError<T>> for StakesError<Address, Coins, Epoch> { | ||
fn from(_value: PoisonError<T>) -> Self { | ||
StakesError::PoisonedLock | ||
} | ||
} |
Oops, something went wrong.