Skip to content

Commit 0f042c7

Browse files
authored
Merge pull request #187 from input-output-hk/golddydev/impl-pools-historical-spo-endpoints
feat: impl pools historical and spo endpoints
2 parents d7a62bf + 40dc316 commit 0f042c7

File tree

20 files changed

+1190
-381
lines changed

20 files changed

+1190
-381
lines changed

Cargo.lock

Lines changed: 252 additions & 58 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/src/queries/accounts.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::HashMap;
22

3-
use crate::{DRepChoice, KeyHash};
3+
use crate::{DRepChoice, KeyHash, PoolLiveStakeInfo};
44

55
pub const DEFAULT_ACCOUNTS_QUERY_TOPIC: (&str, &str) =
66
("accounts-state-query-topic", "cardano.query.accounts");
@@ -27,6 +27,7 @@ pub enum AccountsStateQuery {
2727
GetOptimalPoolSizing,
2828
GetPoolsLiveStakes { pools_operators: Vec<Vec<u8>> },
2929
GetPoolDelegators { pool_operator: KeyHash },
30+
GetPoolLiveStake { pool_operator: KeyHash },
3031

3132
// Dreps related queries
3233
GetDrepDelegators { drep: DRepChoice },
@@ -55,6 +56,7 @@ pub enum AccountsStateQueryResponse {
5556
OptimalPoolSizing(Option<OptimalPoolSizing>),
5657
PoolsLiveStakes(Vec<u64>),
5758
PoolDelegators(PoolDelegators),
59+
PoolLiveStake(PoolLiveStakeInfo),
5860

5961
// DReps related responses
6062
DrepDelegators(DrepDelegators),

common/src/queries/epochs.rs

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{messages::EpochActivityMessage, protocol_params::ProtocolParams, BlockHash, KeyHash};
1+
use crate::{messages::EpochActivityMessage, protocol_params::ProtocolParams, KeyHash};
22

33
pub const DEFAULT_EPOCHS_QUERY_TOPIC: (&str, &str) =
44
("epochs-state-query-topic", "cardano.query.epochs");
@@ -13,12 +13,7 @@ pub enum EpochsStateQuery {
1313
GetEpochStakeDistributionByPool { epoch_number: u64 },
1414
GetEpochBlockDistribution { epoch_number: u64 },
1515
GetEpochBlockDistributionByPool { epoch_number: u64 },
16-
17-
// Pools related queries
18-
GetBlocksMintedByPools { vrf_key_hashes: Vec<KeyHash> },
19-
GetTotalBlocksMintedByPools { vrf_key_hashes: Vec<KeyHash> },
20-
GetBlocksMintedInfoByPool { vrf_key_hash: KeyHash },
21-
GetBlockHashesByPool { vrf_key_hash: KeyHash },
16+
GetLatestEpochBlocksMintedByPool { vrf_key_hash: KeyHash },
2217
}
2318

2419
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@@ -31,12 +26,7 @@ pub enum EpochsStateQueryResponse {
3126
EpochStakeDistributionByPool(EpochStakeDistributionByPool),
3227
EpochBlockDistribution(EpochBlockDistribution),
3328
EpochBlockDistributionByPool(EpochBlockDistributionByPool),
34-
35-
// Pools related responses
36-
BlocksMintedByPools(BlocksMintedByPools),
37-
TotalBlocksMintedByPools(TotalBlocksMintedByPools),
38-
BlocksMintedInfoByPool(BlocksMintedInfoByPool),
39-
BlockHashesByPool(BlockHashesByPool),
29+
LatestEpochBlocksMintedByPool(u64),
4030

4131
NotFound,
4232
Error(String),
@@ -74,26 +64,3 @@ pub struct EpochBlockDistribution {}
7464

7565
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
7666
pub struct EpochBlockDistributionByPool {}
77-
78-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
79-
pub struct BlocksMintedByPools {
80-
// this is in same order of vrf_key_hashes from EpochsStateQuery::BlocksMintedByPools
81-
pub blocks_minted: Vec<u64>,
82-
}
83-
84-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
85-
pub struct TotalBlocksMintedByPools {
86-
// this is in same order of vrf_key_hashes from EpochsStateQuery::TotalBlocksMinted
87-
pub total_blocks_minted: Vec<u64>,
88-
}
89-
90-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
91-
pub struct BlocksMintedInfoByPool {
92-
pub total_blocks_minted: u64,
93-
pub epoch_blocks_minted: u64,
94-
}
95-
96-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
97-
pub struct BlockHashesByPool {
98-
pub hashes: Vec<BlockHash>,
99-
}

common/src/queries/pools.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
2-
queries::governance::VoteRecord, rational_number::RationalNumber, KeyHash, PoolEpochState,
3-
PoolMetadata, PoolRegistration, PoolRetirement, PoolUpdateEvent, Relay,
2+
queries::governance::VoteRecord, rational_number::RationalNumber, BlockHash, KeyHash,
3+
PoolEpochState, PoolMetadata, PoolRegistration, PoolRetirement, PoolUpdateEvent, Relay,
44
};
55

66
pub const DEFAULT_POOLS_QUERY_TOPIC: (&str, &str) =
@@ -20,26 +20,35 @@ pub enum PoolsStateQuery {
2020
pools_operators: Vec<KeyHash>,
2121
epoch: u64,
2222
},
23+
GetPoolsTotalBlocksMinted {
24+
pools_operators: Vec<KeyHash>,
25+
},
2326
GetPoolInfo {
24-
pool_id: Vec<u8>,
27+
pool_id: KeyHash,
2528
},
2629
GetPoolHistory {
27-
pool_id: Vec<u8>,
30+
pool_id: KeyHash,
2831
},
2932
GetPoolMetadata {
30-
pool_id: Vec<u8>,
33+
pool_id: KeyHash,
3134
},
3235
GetPoolRelays {
33-
pool_id: Vec<u8>,
36+
pool_id: KeyHash,
3437
},
3538
GetPoolDelegators {
36-
pool_id: Vec<u8>,
39+
pool_id: KeyHash,
40+
},
41+
GetPoolTotalBlocksMinted {
42+
pool_id: KeyHash,
43+
},
44+
GetPoolBlockHashes {
45+
pool_id: KeyHash,
3746
},
3847
GetPoolUpdates {
39-
pool_id: Vec<u8>,
48+
pool_id: KeyHash,
4049
},
4150
GetPoolVotes {
42-
pool_id: Vec<u8>,
51+
pool_id: KeyHash,
4352
},
4453
}
4554

@@ -51,11 +60,14 @@ pub enum PoolsStateQueryResponse {
5160
PoolsRetiringList(Vec<PoolRetirement>),
5261
PoolActiveStakeInfo(PoolActiveStakeInfo),
5362
PoolsActiveStakes(Vec<u64>),
54-
PoolInfo(PoolInfo),
63+
PoolsTotalBlocksMinted(Vec<u64>),
64+
PoolInfo(PoolRegistration),
5565
PoolHistory(Vec<PoolEpochState>),
5666
PoolMetadata(PoolMetadata),
5767
PoolRelays(Vec<Relay>),
5868
PoolDelegators(PoolDelegators),
69+
PoolTotalBlocksMinted(u64),
70+
PoolBlockHashes(Vec<BlockHash>),
5971
PoolUpdates(Vec<PoolUpdateEvent>),
6072
PoolVotes(Vec<VoteRecord>),
6173
NotFound,
@@ -73,9 +85,6 @@ pub struct PoolActiveStakeInfo {
7385
pub active_size: RationalNumber,
7486
}
7587

76-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
77-
pub struct PoolInfo {}
78-
7988
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
8089
pub struct PoolDelegators {
8190
pub delegators: Vec<(KeyHash, u64)>,

common/src/stake_addresses.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use std::{
1010

1111
use crate::{
1212
math::update_value_with_delta, messages::DRepDelegationDistribution, DRepChoice,
13-
DRepCredential, DelegatedStake, KeyHash, Lovelace, StakeAddressDelta, StakeCredential,
14-
Withdrawal,
13+
DRepCredential, DelegatedStake, KeyHash, Lovelace, PoolLiveStakeInfo, StakeAddressDelta,
14+
StakeCredential, Withdrawal,
1515
};
1616
use anyhow::Result;
1717
use dashmap::DashMap;
@@ -110,6 +110,34 @@ impl StakeAddressMap {
110110
self.get(stake_key).map(|sas| sas.registered).unwrap_or(false)
111111
}
112112

113+
/// Get Pool's Live Stake Info
114+
pub fn get_pool_live_stake_info(&self, spo: &KeyHash) -> PoolLiveStakeInfo {
115+
let total_live_stakes = AtomicU64::new(0);
116+
let live_stake = AtomicU64::new(0);
117+
let live_delegators = AtomicU64::new(0);
118+
119+
// Par Iter stake addresses values
120+
self.inner.par_iter().for_each(|(_, sas)| {
121+
total_live_stakes.fetch_add(sas.utxo_value, std::sync::atomic::Ordering::Relaxed);
122+
if sas.delegated_spo.as_ref().map(|d_spo| d_spo.eq(spo)).unwrap_or(false) {
123+
live_stake.fetch_add(
124+
sas.utxo_value + sas.rewards,
125+
std::sync::atomic::Ordering::Relaxed,
126+
);
127+
live_delegators.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
128+
}
129+
});
130+
131+
let total_live_stakes = total_live_stakes.load(std::sync::atomic::Ordering::Relaxed);
132+
let live_stake = live_stake.load(std::sync::atomic::Ordering::Relaxed);
133+
let live_delegators = live_delegators.load(std::sync::atomic::Ordering::Relaxed);
134+
PoolLiveStakeInfo {
135+
live_stake,
136+
live_delegators,
137+
total_live_stakes,
138+
}
139+
}
140+
113141
/// Get Pool's Live Stake (same order as spos)
114142
pub fn get_pools_live_stakes(&self, spos: &Vec<KeyHash>) -> Vec<u64> {
115143
let mut live_stakes_map = HashMap::<KeyHash, u64>::new();

common/src/types.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ pub struct PoolRetirement {
638638
}
639639

640640
/// Pool Update Action
641-
#[derive(Debug, Clone, Serialize, Deserialize)]
641+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
642642
pub enum PoolUpdateAction {
643643
Registered,
644644
Deregistered,
@@ -670,6 +670,14 @@ impl PoolUpdateEvent {
670670
}
671671
}
672672

673+
/// Pool Live Stake Info
674+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
675+
pub struct PoolLiveStakeInfo {
676+
pub live_stake: u64,
677+
pub live_delegators: u64,
678+
pub total_live_stakes: u64,
679+
}
680+
673681
/// Pool Epoch History Data
674682
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
675683
pub struct PoolEpochState {

modules/accounts_state/src/accounts_state.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,12 @@ impl AccountsState {
461461
})
462462
}
463463

464+
AccountsStateQuery::GetPoolLiveStake { pool_operator } => {
465+
AccountsStateQueryResponse::PoolLiveStake(
466+
state.get_pool_live_stake_info(pool_operator),
467+
)
468+
}
469+
464470
AccountsStateQuery::GetDrepDelegators { drep } => {
465471
AccountsStateQueryResponse::DrepDelegators(DrepDelegators {
466472
delegators: state.get_drep_delegators(drep),

modules/accounts_state/src/state.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::monetary::calculate_monetary_change;
33
use crate::rewards::{RewardsResult, RewardsState};
44
use crate::snapshot::Snapshot;
55
use acropolis_common::queries::accounts::OptimalPoolSizing;
6+
use acropolis_common::PoolLiveStakeInfo;
67
use acropolis_common::{
78
math::update_value_with_delta,
89
messages::{
@@ -106,6 +107,11 @@ impl State {
106107
Some(OptimalPoolSizing { total_supply, nopt })
107108
}
108109

110+
/// Get Pool Live Stake Info
111+
pub fn get_pool_live_stake_info(&self, pool_operator: &KeyHash) -> PoolLiveStakeInfo {
112+
self.stake_addresses.lock().unwrap().get_pool_live_stake_info(pool_operator)
113+
}
114+
109115
/// Get Pools Live stake
110116
pub fn get_pools_live_stakes(&self, pool_operators: &Vec<KeyHash>) -> Vec<u64> {
111117
self.stake_addresses.lock().unwrap().get_pools_live_stakes(pool_operators)

modules/epochs_state/src/epochs_history.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,19 @@ mod tests {
7373

7474
#[test]
7575
fn epochs_history_is_none_when_store_history_is_false() {
76-
let epochs_history = EpochsHistoryState::new(&StoreConfig::new(false, false));
76+
let epochs_history = EpochsHistoryState::new(&StoreConfig::new(false));
7777
assert!(epochs_history.epochs_history.is_none());
7878
}
7979

8080
#[test]
8181
fn epochs_history_is_some_when_store_history_is_true() {
82-
let epochs_history = EpochsHistoryState::new(&StoreConfig::new(true, false));
82+
let epochs_history = EpochsHistoryState::new(&StoreConfig::new(true));
8383
assert!(epochs_history.epochs_history.is_some());
8484
}
8585

8686
#[test]
8787
fn handle_epoch_activity_saves_history() {
88-
let epochs_history = EpochsHistoryState::new(&StoreConfig::new(true, false));
88+
let epochs_history = EpochsHistoryState::new(&StoreConfig::new(true));
8989
let block = make_block(200);
9090
epochs_history.handle_epoch_activity(
9191
&block,

modules/epochs_state/src/epochs_state.rs

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
use acropolis_common::{
55
messages::{CardanoMessage, Message, StateQuery, StateQueryResponse},
66
queries::epochs::{
7-
BlockHashesByPool, BlocksMintedByPools, BlocksMintedInfoByPool, EpochInfo,
8-
EpochsStateQuery, EpochsStateQueryResponse, LatestEpoch, TotalBlocksMintedByPools,
7+
EpochInfo, EpochsStateQuery, EpochsStateQueryResponse, LatestEpoch,
98
DEFAULT_EPOCHS_QUERY_TOPIC,
109
},
1110
state_history::{StateHistory, StateHistoryStore},
@@ -50,14 +49,13 @@ impl EpochsState {
5049
async fn run(
5150
history: Arc<Mutex<StateHistory<State>>>,
5251
epochs_history: EpochsHistoryState,
53-
store_config: &StoreConfig,
5452
mut headers_subscription: Box<dyn Subscription<Message>>,
5553
mut fees_subscription: Box<dyn Subscription<Message>>,
5654
mut epoch_activity_publisher: EpochActivityPublisher,
5755
) -> Result<()> {
5856
loop {
5957
// Get a mutable state
60-
let mut state = history.lock().await.get_or_init_with(|| State::new(store_config));
58+
let mut state = history.lock().await.get_or_init_with(|| State::new());
6159
let mut current_block: Option<BlockInfo> = None;
6260

6361
// Read both topics in parallel
@@ -113,9 +111,7 @@ impl EpochsState {
113111
// are suppressed upstream
114112
match MultiEraHeader::decode(variant, None, &header_msg.raw) {
115113
Ok(header) => {
116-
if let Some(vrf_vkey) = header.vrf_vkey() {
117-
state.handle_mint(&block_info, Some(vrf_vkey));
118-
}
114+
state.handle_mint(&block_info, header.vrf_vkey());
119115
}
120116

121117
Err(e) => error!("Can't decode header {}: {e}", block_info.slot),
@@ -231,43 +227,12 @@ impl EpochsState {
231227
}
232228
}
233229

234-
EpochsStateQuery::GetBlocksMintedByPools { vrf_key_hashes } => {
235-
EpochsStateQueryResponse::BlocksMintedByPools(BlocksMintedByPools {
236-
blocks_minted: state.get_blocks_minted_by_pools(vrf_key_hashes),
237-
})
238-
}
239-
240-
EpochsStateQuery::GetTotalBlocksMintedByPools { vrf_key_hashes } => {
241-
EpochsStateQueryResponse::TotalBlocksMintedByPools(
242-
TotalBlocksMintedByPools {
243-
total_blocks_minted: state
244-
.get_total_blocks_minted_by_pools(vrf_key_hashes),
245-
},
230+
EpochsStateQuery::GetLatestEpochBlocksMintedByPool { vrf_key_hash } => {
231+
EpochsStateQueryResponse::LatestEpochBlocksMintedByPool(
232+
state.get_latest_epoch_blocks_minted_by_pool(vrf_key_hash),
246233
)
247234
}
248235

249-
EpochsStateQuery::GetBlocksMintedInfoByPool { vrf_key_hash } => {
250-
let (total_blocks_minted, epoch_blocks_minted) =
251-
state.get_blocks_minted_data_by_pool(vrf_key_hash);
252-
EpochsStateQueryResponse::BlocksMintedInfoByPool(BlocksMintedInfoByPool {
253-
total_blocks_minted,
254-
epoch_blocks_minted,
255-
})
256-
}
257-
258-
EpochsStateQuery::GetBlockHashesByPool { vrf_key_hash } => {
259-
if state.is_block_hashes_enabled() {
260-
let hashes = state.get_block_hashes(vrf_key_hash);
261-
EpochsStateQueryResponse::BlockHashesByPool(BlockHashesByPool {
262-
hashes,
263-
})
264-
} else {
265-
EpochsStateQueryResponse::Error(
266-
"Block hashes are not enabled".to_string(),
267-
)
268-
}
269-
}
270-
271236
_ => EpochsStateQueryResponse::Error(format!(
272237
"Unimplemented query variant: {:?}",
273238
query
@@ -284,7 +249,6 @@ impl EpochsState {
284249
Self::run(
285250
history,
286251
epochs_history,
287-
&store_config,
288252
headers_subscription,
289253
fees_subscription,
290254
epoch_activity_publisher,

0 commit comments

Comments
 (0)