From def39bd6e189fdecf9cc5805a5f0d5fc8b1ce4fe Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 9 Oct 2025 19:00:27 +0200 Subject: [PATCH 1/7] refactor: store block hashes by epoch on spo state --- modules/spo_state/src/state.rs | 69 +++++++++++++++++++++++++--------- processes/omnibus/omnibus.toml | 2 +- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/modules/spo_state/src/state.rs b/modules/spo_state/src/state.rs index 976faf15..d109197a 100644 --- a/modules/spo_state/src/state.rs +++ b/modules/spo_state/src/state.rs @@ -15,7 +15,7 @@ use acropolis_common::{ TxHash, Voter, VotingProcedures, }; use anyhow::Result; -use imbl::{HashMap, Vector}; +use imbl::{HashMap, OrdMap, Vector}; use std::sync::{Arc, Mutex}; use tracing::{debug, error, info}; @@ -42,7 +42,7 @@ pub struct State { total_blocks_minted: HashMap, /// block hashes keyed pool id - block_hashes: Option>>, + block_hashes: Option>>>, /// historical spo state /// keyed by pool operator id @@ -219,9 +219,33 @@ impl State { delegators_map.map(|map| map.into_iter().collect()) } - /// Get Pool Blocks - pub fn get_pool_block_hashes(&self, pool_id: &KeyHash) -> Option> { - self.block_hashes.as_ref()?.get(pool_id).map(|blocks| blocks.clone().into_iter().collect()) + /// Get Pool Block Hashes + /// Return Err when block_hashes not enabled + pub fn get_pool_block_hashes(&self, pool_id: &KeyHash) -> Result> { + let Some(block_hashes) = self.block_hashes.as_ref() else { + return Err(anyhow::anyhow!("Block hashes are not enabled")); + }; + Ok(block_hashes + .get(pool_id) + .map(|epochs| epochs.values().flatten().cloned().collect()) + .unwrap_or_default()) + } + + /// Get Pool Block Hashes per Epoch + /// Return Err when block_hashes not enabled + pub fn get_pool_block_hashes_per_epoch( + &self, + pool_id: &KeyHash, + epoch: u64, + ) -> Result> { + let Some(block_hashes) = self.block_hashes.as_ref() else { + return Err(anyhow::anyhow!("Block hashes are not enabled")); + }; + Ok(block_hashes + .get(pool_id) + .map(|epochs| epochs.get(&epoch).map(|blocks| blocks.iter().cloned().collect())) + .flatten() + .unwrap_or_default()) } /// Get Pool Updates @@ -268,20 +292,24 @@ impl State { } // Handle block's minting. - // Returns None if block_hashes is not enabled - // Return Some(false) if pool_id for vrf_vkey is not found - pub fn handle_mint(&mut self, block_info: &BlockInfo, vrf_vkey: &[u8]) -> Option { + // Returns false if vrf_vkey_hash is not mapped to any pool_id + pub fn handle_mint(&mut self, block_info: &BlockInfo, vrf_vkey: &[u8]) -> bool { let vrf_key_hash = keyhash(vrf_vkey); let Some(pool_id) = self.vrf_key_hash_to_pool_id_map.get(&vrf_key_hash).cloned() else { - return Some(false); + return false; }; *(self.total_blocks_minted.entry(pool_id.clone()).or_insert(0)) += 1; // if block_hashes are enabled if let Some(block_hashes) = self.block_hashes.as_mut() { - block_hashes.entry(pool_id).or_insert_with(Vector::new).push_back(block_info.hash); + block_hashes + .entry(pool_id) + .or_insert_with(OrdMap::new) + .entry(block_info.epoch) + .or_insert_with(Vector::new) + .push_back(block_info.hash); }; - Some(true) + true } fn handle_new_epoch(&mut self, block: &BlockInfo) -> Arc { @@ -1045,25 +1073,25 @@ mod tests { assert!(state.handle_tx_certs(&block, &msg).is_ok()); block = new_block(2); - assert_eq!(Some(true), state.handle_mint(&block, &vec![0])); + assert_eq!(true, state.handle_mint(&block, &vec![0])); assert_eq!(1, state.get_total_blocks_minted_by_pool(&vec![1])); block = new_block(3); - assert_eq!(Some(true), state.handle_mint(&block, &vec![0])); + assert_eq!(true, state.handle_mint(&block, &vec![0])); assert_eq!(2, state.get_total_blocks_minted_by_pools(&vec![vec![1]])[0]); } #[test] - fn get_block_hashes_returns_none_when_state_is_new() { + fn get_block_hashes_returns_err_when_block_hashes_not_enabled() { let state = State::default(); - assert!(state.get_pool_block_hashes(&vec![0]).is_none()); + assert!(state.get_pool_block_hashes(&vec![0]).is_err()); } #[test] fn handle_mint_returns_false_if_pool_not_found() { let mut state = State::new(&save_block_hashes_store_config()); let block = new_block(0); - assert_eq!(Some(false), state.handle_mint(&block, &vec![0])); + assert_eq!(false, state.handle_mint(&block, &vec![0])); } #[test] @@ -1093,9 +1121,16 @@ mod tests { )); assert!(state.handle_tx_certs(&block, &msg).is_ok()); block = new_block(2); - assert_eq!(Some(true), state.handle_mint(&block, &vec![0])); + assert_eq!(true, state.handle_mint(&block, &vec![0])); let block_hashes = state.get_pool_block_hashes(&vec![1]).unwrap(); assert_eq!(block_hashes.len(), 1); assert_eq!(block_hashes[0], block.hash); + + let block_hashes = state.get_pool_block_hashes_per_epoch(&vec![1], 2).unwrap(); + assert_eq!(block_hashes.len(), 1); + assert_eq!(block_hashes[0], block.hash); + + let block_hashes = state.get_pool_block_hashes_per_epoch(&vec![1], 3).unwrap(); + assert_eq!(block_hashes.len(), 0); } } diff --git a/processes/omnibus/omnibus.toml b/processes/omnibus/omnibus.toml index 12b9954c..c96960ef 100644 --- a/processes/omnibus/omnibus.toml +++ b/processes/omnibus/omnibus.toml @@ -44,7 +44,7 @@ store-updates = false store-delegators = false # Enables /pools/{pool_id}/votes endpoint store-votes = false -# Store block hashes, enables /pools/{pool_id}/blocks endpoints +# Store block hashes, enables /pools/{pool_id}/blocks, /epochs/{number}/blocks/{pool_id} store-block-hashes = false # Store stake_addresses store-stake-addresses = false From 04ff185cf960dc04ace266e92a94fe05cfaad750 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 9 Oct 2025 19:13:23 +0200 Subject: [PATCH 2/7] chore: save first and last blocks' height --- modules/epochs_state/src/state.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/epochs_state/src/state.rs b/modules/epochs_state/src/state.rs index a443eb8e..2878211d 100644 --- a/modules/epochs_state/src/state.rs +++ b/modules/epochs_state/src/state.rs @@ -29,10 +29,16 @@ pub struct State { // UNIX timestamp first_block_time: u64, + // first block height + first_block_height: u64, + // last block time // UNIX timestamp last_block_time: u64, + // last block height + last_block_height: u64, + // Map of counts by VRF key hashes blocks_minted: HashMap, @@ -63,7 +69,9 @@ impl State { epoch: 0, epoch_start_time: genesis.byron_timestamp, first_block_time: genesis.byron_timestamp, + first_block_height: 0, last_block_time: 0, + last_block_height: 0, blocks_minted: HashMap::new(), epoch_blocks: 0, epoch_txs: 0, @@ -178,6 +186,7 @@ impl State { // This will update last block time pub fn handle_mint(&mut self, block_info: &BlockInfo, vrf_vkey: Option<&[u8]>) { self.last_block_time = block_info.timestamp; + self.last_block_height = block_info.number; self.epoch_blocks += 1; if let Some(vrf_vkey) = vrf_vkey { @@ -215,7 +224,9 @@ impl State { self.epoch = block_info.epoch; self.epoch_start_time = block_info.timestamp; self.first_block_time = block_info.timestamp; + self.first_block_height = block_info.number; self.last_block_time = block_info.timestamp; + self.last_block_height = block_info.number; self.blocks_minted.clear(); self.epoch_blocks = 0; self.epoch_txs = 0; @@ -422,7 +433,9 @@ mod tests { assert!(state.blocks_minted.is_empty()); assert_eq!(state.epoch_start_time, block.timestamp); assert_eq!(state.first_block_time, block.timestamp); + assert_eq!(state.first_block_height, block.number); assert_eq!(state.last_block_time, block.timestamp); + assert_eq!(state.last_block_height, block.number); let blocks_minted = state.get_latest_epoch_blocks_minted_by_pool(&keyhash(b"vrf_1")); assert_eq!(blocks_minted, 0); From 1133913e8691c9f490d2b9514f9a77281f7f673a Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 9 Oct 2025 20:14:01 +0200 Subject: [PATCH 3/7] feat: save first, last blocks heights. implement epochs/{number}/blocks/{pool_id} --- common/src/messages.rs | 6 ++ common/src/queries/epochs.rs | 10 --- common/src/queries/pools.rs | 5 ++ modules/epochs_state/src/epochs_history.rs | 2 + modules/epochs_state/src/state.rs | 2 + .../rest_blockfrost/src/handlers/epochs.rs | 70 +++++++++++++++++-- modules/spo_state/src/spo_state.rs | 14 ++-- modules/spo_state/src/state.rs | 8 +-- modules/spo_state/src/test_utils.rs | 2 + 9 files changed, 97 insertions(+), 22 deletions(-) diff --git a/common/src/messages.rs b/common/src/messages.rs index 5f8cdbf2..0b6a1268 100644 --- a/common/src/messages.rs +++ b/common/src/messages.rs @@ -156,9 +156,15 @@ pub struct EpochActivityMessage { /// First block time pub first_block_time: u64, + /// First block height + pub first_block_height: u64, + /// Last block time pub last_block_time: u64, + /// Last block height + pub last_block_height: u64, + /// Total blocks in this epoch pub total_blocks: usize, diff --git a/common/src/queries/epochs.rs b/common/src/queries/epochs.rs index 4218d39c..75b02484 100644 --- a/common/src/queries/epochs.rs +++ b/common/src/queries/epochs.rs @@ -11,8 +11,6 @@ pub enum EpochsStateQuery { GetPreviousEpochs { epoch_number: u64 }, GetEpochStakeDistribution { epoch_number: u64 }, GetEpochStakeDistributionByPool { epoch_number: u64 }, - GetEpochBlockDistribution { epoch_number: u64 }, - GetEpochBlockDistributionByPool { epoch_number: u64 }, GetLatestEpochBlocksMintedByPool { vrf_key_hash: KeyHash }, } @@ -24,8 +22,6 @@ pub enum EpochsStateQueryResponse { PreviousEpochs(PreviousEpochs), EpochStakeDistribution(EpochStakeDistribution), EpochStakeDistributionByPool(EpochStakeDistributionByPool), - EpochBlockDistribution(EpochBlockDistribution), - EpochBlockDistributionByPool(EpochBlockDistributionByPool), LatestEpochBlocksMintedByPool(u64), NotFound, @@ -58,9 +54,3 @@ pub struct EpochStakeDistribution {} #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct EpochStakeDistributionByPool {} - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct EpochBlockDistribution {} - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct EpochBlockDistributionByPool {} diff --git a/common/src/queries/pools.rs b/common/src/queries/pools.rs index 6608cf45..825bb842 100644 --- a/common/src/queries/pools.rs +++ b/common/src/queries/pools.rs @@ -44,6 +44,10 @@ pub enum PoolsStateQuery { GetPoolBlockHashes { pool_id: KeyHash, }, + GetPoolBlockHashesByEpoch { + pool_id: KeyHash, + epoch: u64, + }, GetPoolUpdates { pool_id: KeyHash, }, @@ -68,6 +72,7 @@ pub enum PoolsStateQueryResponse { PoolDelegators(PoolDelegators), PoolTotalBlocksMinted(u64), PoolBlockHashes(Vec), + PoolBlockHashesByEpoch(Vec), PoolUpdates(Vec), PoolVotes(Vec), NotFound, diff --git a/modules/epochs_state/src/epochs_history.rs b/modules/epochs_state/src/epochs_history.rs index 35f19e15..478f11b7 100644 --- a/modules/epochs_state/src/epochs_history.rs +++ b/modules/epochs_state/src/epochs_history.rs @@ -94,7 +94,9 @@ mod tests { epoch_start_time: 0, epoch_end_time: 0, first_block_time: 0, + first_block_height: 0, last_block_time: 0, + last_block_height: 0, total_blocks: 1, total_txs: 1, total_outputs: 100, diff --git a/modules/epochs_state/src/state.rs b/modules/epochs_state/src/state.rs index 2878211d..7e2d3120 100644 --- a/modules/epochs_state/src/state.rs +++ b/modules/epochs_state/src/state.rs @@ -242,7 +242,9 @@ impl State { epoch_start_time: self.epoch_start_time, epoch_end_time: self.epoch_start_time + EPOCH_LENGTH, first_block_time: self.first_block_time, + first_block_height: self.first_block_height, last_block_time: self.last_block_time, + last_block_height: self.last_block_height, // NOTE: // total_blocks will be missing one // This is only because we now ignore EBBs diff --git a/modules/rest_blockfrost/src/handlers/epochs.rs b/modules/rest_blockfrost/src/handlers/epochs.rs index 3fe85659..d5830d8f 100644 --- a/modules/rest_blockfrost/src/handlers/epochs.rs +++ b/modules/rest_blockfrost/src/handlers/epochs.rs @@ -8,9 +8,11 @@ use acropolis_common::{ accounts::{AccountsStateQuery, AccountsStateQueryResponse}, epochs::{EpochsStateQuery, EpochsStateQueryResponse}, parameters::{ParametersStateQuery, ParametersStateQueryResponse}, + pools::{PoolsStateQuery, PoolsStateQueryResponse}, spdd::{SPDDStateQuery, SPDDStateQueryResponse}, utils::query_state, }, + serialization::Bech32WithHrp, }; use anyhow::{anyhow, Result}; use caryatid_sdk::Context; @@ -295,9 +297,69 @@ pub async fn handle_epoch_total_blocks_blockfrost( } pub async fn handle_epoch_pool_blocks_blockfrost( - _context: Arc>, - _params: Vec, - _handlers_config: Arc, + context: Arc>, + params: Vec, + handlers_config: Arc, ) -> Result { - Ok(RESTResponse::with_text(501, "Not implemented")) + if params.len() != 2 { + return Ok(RESTResponse::with_text( + 400, + "Expected two parameters: an epoch number and a pool ID", + )); + } + let epoch_number_param = ¶ms[0]; + let pool_id_param = ¶ms[1]; + + let epoch_number = match epoch_number_param.parse::() { + Ok(num) => num, + Err(_) => { + return Ok(RESTResponse::with_text( + 400, + "Invalid epoch number parameter", + )); + } + }; + + let Ok(spo) = Vec::::from_bech32_with_hrp(pool_id_param, "pool") else { + return Ok(RESTResponse::with_text( + 400, + &format!("Invalid Bech32 stake pool ID: {pool_id_param}"), + )); + }; + + // query Pool's BlockHashes by epoch from spo-state + let msg = Arc::new(Message::StateQuery(StateQuery::Pools( + PoolsStateQuery::GetPoolBlockHashesByEpoch { + pool_id: spo.clone(), + epoch: epoch_number, + }, + ))); + + let block_hashes = query_state( + &context, + &handlers_config.pools_query_topic, + msg, + |message| match message { + Message::StateQueryResponse(StateQueryResponse::Pools( + PoolsStateQueryResponse::PoolBlockHashesByEpoch(block_hashes), + )) => Ok(block_hashes), + Message::StateQueryResponse(StateQueryResponse::Pools( + PoolsStateQueryResponse::Error(e), + )) => Err(anyhow::anyhow!( + "Internal server error while retrieving pool block hashes by epoch: {e}" + )), + _ => Err(anyhow::anyhow!("Unexpected message type")), + }, + ) + .await?; + + let block_hashes_rest = block_hashes.into_iter().map(|b| hex::encode(b)).collect::>(); + + match serde_json::to_string(&block_hashes_rest) { + Ok(json) => Ok(RESTResponse::with_json(200, &json)), + Err(e) => Ok(RESTResponse::with_text( + 500, + &format!("Internal server error while retrieving pool block hashes by epoch: {e}"), + )), + } } diff --git a/modules/spo_state/src/spo_state.rs b/modules/spo_state/src/spo_state.rs index 757f3c30..315fe708 100644 --- a/modules/spo_state/src/spo_state.rs +++ b/modules/spo_state/src/spo_state.rs @@ -635,10 +635,16 @@ impl SPOState { } PoolsStateQuery::GetPoolBlockHashes { pool_id } => { - if state.is_block_hashes_enabled() { - PoolsStateQueryResponse::PoolBlockHashes(state.get_pool_block_hashes(pool_id).unwrap_or_default()) - } else { - PoolsStateQueryResponse::Error("Block hashes are not enabled".into()) + match state.get_pool_block_hashes(pool_id) { + Ok(block_hashes) => PoolsStateQueryResponse::PoolBlockHashes(block_hashes), + Err(_) => PoolsStateQueryResponse::Error("Block hashes are not enabled".into()), + } + } + + PoolsStateQuery::GetPoolBlockHashesByEpoch { pool_id, epoch } => { + match state.get_pool_block_hashes_by_epoch(pool_id, *epoch) { + Ok(block_hashes) => PoolsStateQueryResponse::PoolBlockHashesByEpoch(block_hashes), + Err(_) => PoolsStateQueryResponse::Error("Block hashes are not enabled".into()), } } diff --git a/modules/spo_state/src/state.rs b/modules/spo_state/src/state.rs index d109197a..0d5e1372 100644 --- a/modules/spo_state/src/state.rs +++ b/modules/spo_state/src/state.rs @@ -231,9 +231,9 @@ impl State { .unwrap_or_default()) } - /// Get Pool Block Hashes per Epoch + /// Get Pool Block Hashes by Epoch /// Return Err when block_hashes not enabled - pub fn get_pool_block_hashes_per_epoch( + pub fn get_pool_block_hashes_by_epoch( &self, pool_id: &KeyHash, epoch: u64, @@ -1126,11 +1126,11 @@ mod tests { assert_eq!(block_hashes.len(), 1); assert_eq!(block_hashes[0], block.hash); - let block_hashes = state.get_pool_block_hashes_per_epoch(&vec![1], 2).unwrap(); + let block_hashes = state.get_pool_block_hashes_by_epoch(&vec![1], 2).unwrap(); assert_eq!(block_hashes.len(), 1); assert_eq!(block_hashes[0], block.hash); - let block_hashes = state.get_pool_block_hashes_per_epoch(&vec![1], 3).unwrap(); + let block_hashes = state.get_pool_block_hashes_by_epoch(&vec![1], 3).unwrap(); assert_eq!(block_hashes.len(), 0); } } diff --git a/modules/spo_state/src/test_utils.rs b/modules/spo_state/src/test_utils.rs index 920eb2c1..030381f8 100644 --- a/modules/spo_state/src/test_utils.rs +++ b/modules/spo_state/src/test_utils.rs @@ -92,7 +92,9 @@ pub fn new_epoch_activity_message(epoch: u64) -> EpochActivityMessage { epoch_start_time: 0, epoch_end_time: 0, first_block_time: 0, + first_block_height: 0, last_block_time: 0, + last_block_height: 0, total_blocks: 0, total_txs: 0, total_outputs: 0, From 526262d2731a5745fda67c37593cccfba3a22c9e Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 13 Oct 2025 09:53:02 +0200 Subject: [PATCH 4/7] refactor: store block height instead of block hashes for memory usage --- common/src/messages.rs | 10 ++- common/src/queries/pools.rs | 14 ++-- .../rest_blockfrost/src/handlers/epochs.rs | 16 ++-- modules/rest_blockfrost/src/handlers/pools.rs | 15 ++-- modules/spo_state/src/spo_state.rs | 16 ++-- modules/spo_state/src/state.rs | 84 +++++++++---------- modules/spo_state/src/store_config.rs | 12 ++- modules/spo_state/src/test_utils.rs | 10 +-- processes/omnibus/omnibus.toml | 4 +- 9 files changed, 93 insertions(+), 88 deletions(-) diff --git a/common/src/messages.rs b/common/src/messages.rs index 0b6a1268..09f98164 100644 --- a/common/src/messages.rs +++ b/common/src/messages.rs @@ -148,21 +148,23 @@ pub struct EpochActivityMessage { pub epoch: u64, /// Epoch start time + /// UNIX timestamp pub epoch_start_time: u64, /// Epoch end time + /// UNIX timestamp pub epoch_end_time: u64, - /// First block time + /// When first block of this epoch was created pub first_block_time: u64, - /// First block height + /// Block height of first block of this epoch pub first_block_height: u64, - /// Last block time + /// When last block of this epoch was created pub last_block_time: u64, - /// Last block height + /// Block height of last block of this epoch pub last_block_height: u64, /// Total blocks in this epoch diff --git a/common/src/queries/pools.rs b/common/src/queries/pools.rs index 825bb842..0cf53e78 100644 --- a/common/src/queries/pools.rs +++ b/common/src/queries/pools.rs @@ -1,6 +1,6 @@ use crate::{ - queries::governance::VoteRecord, rational_number::RationalNumber, BlockHash, KeyHash, - PoolEpochState, PoolMetadata, PoolRegistration, PoolRetirement, PoolUpdateEvent, Relay, + queries::governance::VoteRecord, rational_number::RationalNumber, KeyHash, PoolEpochState, + PoolMetadata, PoolRegistration, PoolRetirement, PoolUpdateEvent, Relay, }; pub const DEFAULT_POOLS_QUERY_TOPIC: (&str, &str) = @@ -41,10 +41,10 @@ pub enum PoolsStateQuery { GetPoolTotalBlocksMinted { pool_id: KeyHash, }, - GetPoolBlockHashes { + GetBlocksByPool { pool_id: KeyHash, }, - GetPoolBlockHashesByEpoch { + GetBlocksByPoolAndEpoch { pool_id: KeyHash, epoch: u64, }, @@ -71,8 +71,10 @@ pub enum PoolsStateQueryResponse { PoolRelays(Vec), PoolDelegators(PoolDelegators), PoolTotalBlocksMinted(u64), - PoolBlockHashes(Vec), - PoolBlockHashesByEpoch(Vec), + // Vector of Block Heights + BlocksByPool(Vec), + // Vector of Block Heights + BlocksByPoolAndEpoch(Vec), PoolUpdates(Vec), PoolVotes(Vec), NotFound, diff --git a/modules/rest_blockfrost/src/handlers/epochs.rs b/modules/rest_blockfrost/src/handlers/epochs.rs index d5830d8f..6f561dcb 100644 --- a/modules/rest_blockfrost/src/handlers/epochs.rs +++ b/modules/rest_blockfrost/src/handlers/epochs.rs @@ -327,22 +327,22 @@ pub async fn handle_epoch_pool_blocks_blockfrost( )); }; - // query Pool's BlockHashes by epoch from spo-state + // query Pool's Blocks by epoch from spo-state let msg = Arc::new(Message::StateQuery(StateQuery::Pools( - PoolsStateQuery::GetPoolBlockHashesByEpoch { + PoolsStateQuery::GetBlocksByPoolAndEpoch { pool_id: spo.clone(), epoch: epoch_number, }, ))); - let block_hashes = query_state( + let blocks = query_state( &context, &handlers_config.pools_query_topic, msg, |message| match message { Message::StateQueryResponse(StateQueryResponse::Pools( - PoolsStateQueryResponse::PoolBlockHashesByEpoch(block_hashes), - )) => Ok(block_hashes), + PoolsStateQueryResponse::BlocksByPoolAndEpoch(blocks), + )) => Ok(blocks), Message::StateQueryResponse(StateQueryResponse::Pools( PoolsStateQueryResponse::Error(e), )) => Err(anyhow::anyhow!( @@ -353,9 +353,11 @@ pub async fn handle_epoch_pool_blocks_blockfrost( ) .await?; - let block_hashes_rest = block_hashes.into_iter().map(|b| hex::encode(b)).collect::>(); + // NOTE: + // Need to query chain_store + // to get block_hash for each block height - match serde_json::to_string(&block_hashes_rest) { + match serde_json::to_string_pretty(&blocks) { Ok(json) => Ok(RESTResponse::with_json(200, &json)), Err(e) => Ok(RESTResponse::with_text( 500, diff --git a/modules/rest_blockfrost/src/handlers/pools.rs b/modules/rest_blockfrost/src/handlers/pools.rs index 4c28f897..d5bf5771 100644 --- a/modules/rest_blockfrost/src/handlers/pools.rs +++ b/modules/rest_blockfrost/src/handlers/pools.rs @@ -1062,9 +1062,9 @@ pub async fn handle_pool_blocks_blockfrost( )); }; - // Get block hashes by pool_id from spo_state + // Get blocks by pool_id from spo_state let pool_blocks_msg = Arc::new(Message::StateQuery(StateQuery::Pools( - PoolsStateQuery::GetPoolBlockHashes { + PoolsStateQuery::GetBlocksByPool { pool_id: spo.clone(), }, ))); @@ -1075,18 +1075,21 @@ pub async fn handle_pool_blocks_blockfrost( pool_blocks_msg, |message| match message { Message::StateQueryResponse(StateQueryResponse::Pools( - PoolsStateQueryResponse::PoolBlockHashes(pool_blocks), + PoolsStateQueryResponse::BlocksByPool(pool_blocks), )) => Ok(pool_blocks), Message::StateQueryResponse(StateQueryResponse::Pools( PoolsStateQueryResponse::Error(_), - )) => Err(anyhow::anyhow!("Block hashes are not enabled")), + )) => Err(anyhow::anyhow!("Blocks are not enabled")), _ => Err(anyhow::anyhow!("Unexpected message type")), }, ) .await?; - let pool_blocks_rest = pool_blocks.into_iter().map(|b| hex::encode(b)).collect::>(); - match serde_json::to_string(&pool_blocks_rest) { + // NOTE: + // Need to query chain_store + // to get block_hash for each block height + + match serde_json::to_string_pretty(&pool_blocks) { Ok(json) => Ok(RESTResponse::with_json(200, &json)), Err(e) => Ok(RESTResponse::with_text( 500, diff --git a/modules/spo_state/src/spo_state.rs b/modules/spo_state/src/spo_state.rs index 315fe708..396663a5 100644 --- a/modules/spo_state/src/spo_state.rs +++ b/modules/spo_state/src/spo_state.rs @@ -634,17 +634,17 @@ impl SPOState { PoolsStateQueryResponse::PoolTotalBlocksMinted(state.get_total_blocks_minted_by_pool(&pool_id)) } - PoolsStateQuery::GetPoolBlockHashes { pool_id } => { - match state.get_pool_block_hashes(pool_id) { - Ok(block_hashes) => PoolsStateQueryResponse::PoolBlockHashes(block_hashes), - Err(_) => PoolsStateQueryResponse::Error("Block hashes are not enabled".into()), + PoolsStateQuery::GetBlocksByPool { pool_id } => { + match state.get_blocks_by_pool(pool_id) { + Ok(blocks) => PoolsStateQueryResponse::BlocksByPool(blocks), + Err(_) => PoolsStateQueryResponse::Error("Blocks are not enabled".into()), } } - PoolsStateQuery::GetPoolBlockHashesByEpoch { pool_id, epoch } => { - match state.get_pool_block_hashes_by_epoch(pool_id, *epoch) { - Ok(block_hashes) => PoolsStateQueryResponse::PoolBlockHashesByEpoch(block_hashes), - Err(_) => PoolsStateQueryResponse::Error("Block hashes are not enabled".into()), + PoolsStateQuery::GetBlocksByPoolAndEpoch { pool_id, epoch } => { + match state.get_blocks_by_pool_and_epoch(pool_id, *epoch) { + Ok(blocks) => PoolsStateQueryResponse::BlocksByPoolAndEpoch(blocks), + Err(_) => PoolsStateQueryResponse::Error("Blocks are not enabled".into()), } } diff --git a/modules/spo_state/src/state.rs b/modules/spo_state/src/state.rs index 0d5e1372..72609bef 100644 --- a/modules/spo_state/src/state.rs +++ b/modules/spo_state/src/state.rs @@ -10,9 +10,9 @@ use acropolis_common::{ params::TECHNICAL_PARAMETER_POOL_RETIRE_MAX_EPOCH, queries::governance::VoteRecord, stake_addresses::StakeAddressMap, - BlockHash, BlockInfo, KeyHash, PoolMetadata, PoolRegistration, PoolRegistrationWithPos, - PoolRetirement, PoolRetirementWithPos, PoolUpdateEvent, Relay, StakeCredential, TxCertificate, - TxHash, Voter, VotingProcedures, + BlockInfo, KeyHash, PoolMetadata, PoolRegistration, PoolRegistrationWithPos, PoolRetirement, + PoolRetirementWithPos, PoolUpdateEvent, Relay, StakeCredential, TxCertificate, TxHash, Voter, + VotingProcedures, }; use anyhow::Result; use imbl::{HashMap, OrdMap, Vector}; @@ -41,8 +41,9 @@ pub struct State { // Keyed by pool_id total_blocks_minted: HashMap, - /// block hashes keyed pool id - block_hashes: Option>>>, + /// block heights (numbers) keyed pool id and epoch + /// > + blocks: Option>>>, /// historical spo state /// keyed by pool operator id @@ -67,7 +68,7 @@ impl State { } else { None }, - block_hashes: if config.store_block_hashes { + blocks: if config.store_blocks { Some(HashMap::new()) } else { None @@ -96,8 +97,8 @@ impl State { self.store_config.store_votes } - pub fn is_block_hashes_enabled(&self) -> bool { - self.store_config.store_block_hashes + pub fn is_blocks_enabled(&self) -> bool { + self.store_config.store_blocks } pub fn is_stake_address_enabled(&self) -> bool { @@ -124,7 +125,7 @@ impl From for State { vrf_key_hash_to_pool_id_map, total_blocks_minted: HashMap::new(), historical_spos: None, - block_hashes: None, + blocks: None, stake_addresses: None, } } @@ -219,29 +220,26 @@ impl State { delegators_map.map(|map| map.into_iter().collect()) } - /// Get Pool Block Hashes - /// Return Err when block_hashes not enabled - pub fn get_pool_block_hashes(&self, pool_id: &KeyHash) -> Result> { - let Some(block_hashes) = self.block_hashes.as_ref() else { - return Err(anyhow::anyhow!("Block hashes are not enabled")); + /// Get Blocks by Pool + /// Return Vector of block heights + /// Return Err when store_blocks not enabled + pub fn get_blocks_by_pool(&self, pool_id: &KeyHash) -> Result> { + let Some(blocks) = self.blocks.as_ref() else { + return Err(anyhow::anyhow!("Blocks are not enabled")); }; - Ok(block_hashes + Ok(blocks .get(pool_id) .map(|epochs| epochs.values().flatten().cloned().collect()) .unwrap_or_default()) } - /// Get Pool Block Hashes by Epoch - /// Return Err when block_hashes not enabled - pub fn get_pool_block_hashes_by_epoch( - &self, - pool_id: &KeyHash, - epoch: u64, - ) -> Result> { - let Some(block_hashes) = self.block_hashes.as_ref() else { - return Err(anyhow::anyhow!("Block hashes are not enabled")); + /// Get Blocks by Pool and Epoch + /// Return Err when store_blocks not enabled + pub fn get_blocks_by_pool_and_epoch(&self, pool_id: &KeyHash, epoch: u64) -> Result> { + let Some(blocks) = self.blocks.as_ref() else { + return Err(anyhow::anyhow!("Blocks are not enabled")); }; - Ok(block_hashes + Ok(blocks .get(pool_id) .map(|epochs| epochs.get(&epoch).map(|blocks| blocks.iter().cloned().collect())) .flatten() @@ -300,14 +298,14 @@ impl State { }; *(self.total_blocks_minted.entry(pool_id.clone()).or_insert(0)) += 1; - // if block_hashes are enabled - if let Some(block_hashes) = self.block_hashes.as_mut() { - block_hashes + // if store_blocks is enabled + if let Some(blocks) = self.blocks.as_mut() { + blocks .entry(pool_id) .or_insert_with(OrdMap::new) .entry(block_info.epoch) .or_insert_with(Vector::new) - .push_back(block_info.hash); + .push_back(block_info.number); }; true } @@ -1047,7 +1045,7 @@ mod tests { #[test] fn get_total_blocks_minted_returns_after_handle_mint() { - let mut state = State::new(&save_block_hashes_store_config()); + let mut state = State::new(&save_blocks_store_config()); let mut block = new_block(0); let mut msg = new_certs_msg(); msg.certificates.push(TxCertificate::PoolRegistrationWithPos( @@ -1082,21 +1080,21 @@ mod tests { } #[test] - fn get_block_hashes_returns_err_when_block_hashes_not_enabled() { + fn get_blocks_returns_err_when_blocks_not_enabled() { let state = State::default(); - assert!(state.get_pool_block_hashes(&vec![0]).is_err()); + assert!(state.get_blocks_by_pool(&vec![0]).is_err()); } #[test] fn handle_mint_returns_false_if_pool_not_found() { - let mut state = State::new(&save_block_hashes_store_config()); + let mut state = State::new(&save_blocks_store_config()); let block = new_block(0); assert_eq!(false, state.handle_mint(&block, &vec![0])); } #[test] - fn get_block_hashes_return_data_after_handle_mint() { - let mut state = State::new(&save_block_hashes_store_config()); + fn get_blocks_return_data_after_handle_mint() { + let mut state = State::new(&save_blocks_store_config()); let mut block = new_block(0); let mut msg = new_certs_msg(); msg.certificates.push(TxCertificate::PoolRegistrationWithPos( @@ -1122,15 +1120,15 @@ mod tests { assert!(state.handle_tx_certs(&block, &msg).is_ok()); block = new_block(2); assert_eq!(true, state.handle_mint(&block, &vec![0])); - let block_hashes = state.get_pool_block_hashes(&vec![1]).unwrap(); - assert_eq!(block_hashes.len(), 1); - assert_eq!(block_hashes[0], block.hash); + let blocks = state.get_blocks_by_pool(&vec![1]).unwrap(); + assert_eq!(blocks.len(), 1); + assert_eq!(blocks[0], block.number); - let block_hashes = state.get_pool_block_hashes_by_epoch(&vec![1], 2).unwrap(); - assert_eq!(block_hashes.len(), 1); - assert_eq!(block_hashes[0], block.hash); + let blocks = state.get_blocks_by_pool_and_epoch(&vec![1], 2).unwrap(); + assert_eq!(blocks.len(), 1); + assert_eq!(blocks[0], block.number); - let block_hashes = state.get_pool_block_hashes_by_epoch(&vec![1], 3).unwrap(); - assert_eq!(block_hashes.len(), 0); + let blocks = state.get_blocks_by_pool_and_epoch(&vec![1], 3).unwrap(); + assert_eq!(blocks.len(), 0); } } diff --git a/modules/spo_state/src/store_config.rs b/modules/spo_state/src/store_config.rs index 97a294a5..3b3372fc 100644 --- a/modules/spo_state/src/store_config.rs +++ b/modules/spo_state/src/store_config.rs @@ -9,7 +9,7 @@ const DEFAULT_STORE_REGISTRATION: (&str, bool) = ("store-registration", false); const DEFAULT_STORE_UPDATES: (&str, bool) = ("store-updates", false); const DEFAULT_STORE_DELEGATORS: (&str, bool) = ("store-delegators", false); const DEFAULT_STORE_VOTES: (&str, bool) = ("store-votes", false); -const DEFAULT_STORE_BLOCK_HASHES: (&str, bool) = ("store-block-hashes", false); +const DEFAULT_STORE_BLOCKS: (&str, bool) = ("store-blocks", false); const DEFAULT_STORE_STAKE_ADDRESSES: (&str, bool) = ("store-stake-addresses", false); #[derive(Default, Debug, Clone, Serialize)] @@ -20,7 +20,7 @@ pub struct StoreConfig { pub store_updates: bool, pub store_delegators: bool, pub store_votes: bool, - pub store_block_hashes: bool, + pub store_blocks: bool, pub store_stake_addresses: bool, } @@ -32,7 +32,7 @@ impl StoreConfig { store_updates: bool, store_delegators: bool, store_votes: bool, - store_block_hashes: bool, + store_blocks: bool, store_stake_addresses: bool, ) -> Self { Self { @@ -42,7 +42,7 @@ impl StoreConfig { store_updates, store_delegators, store_votes, - store_block_hashes, + store_blocks, store_stake_addresses, } } @@ -71,9 +71,7 @@ impl From> for StoreConfig { .get_bool(DEFAULT_STORE_DELEGATORS.0) .unwrap_or(DEFAULT_STORE_DELEGATORS.1), store_votes: config.get_bool(DEFAULT_STORE_VOTES.0).unwrap_or(DEFAULT_STORE_VOTES.1), - store_block_hashes: config - .get_bool(DEFAULT_STORE_BLOCK_HASHES.0) - .unwrap_or(DEFAULT_STORE_BLOCK_HASHES.1), + store_blocks: config.get_bool(DEFAULT_STORE_BLOCKS.0).unwrap_or(DEFAULT_STORE_BLOCKS.1), store_stake_addresses: config .get_bool(DEFAULT_STORE_STAKE_ADDRESSES.0) .unwrap_or(DEFAULT_STORE_STAKE_ADDRESSES.1), diff --git a/modules/spo_state/src/test_utils.rs b/modules/spo_state/src/test_utils.rs index 030381f8..ce257135 100644 --- a/modules/spo_state/src/test_utils.rs +++ b/modules/spo_state/src/test_utils.rs @@ -15,7 +15,7 @@ pub fn default_store_config() -> StoreConfig { store_updates: false, store_delegators: false, store_votes: false, - store_block_hashes: false, + store_blocks: false, store_stake_addresses: false, } } @@ -28,7 +28,7 @@ pub fn save_history_store_config() -> StoreConfig { store_updates: false, store_delegators: false, store_votes: false, - store_block_hashes: false, + store_blocks: false, store_stake_addresses: false, } } @@ -41,12 +41,12 @@ pub fn save_retired_pools_store_config() -> StoreConfig { store_updates: false, store_delegators: false, store_votes: false, - store_block_hashes: false, + store_blocks: false, store_stake_addresses: false, } } -pub fn save_block_hashes_store_config() -> StoreConfig { +pub fn save_blocks_store_config() -> StoreConfig { StoreConfig { store_epochs_history: false, store_retired_pools: false, @@ -54,7 +54,7 @@ pub fn save_block_hashes_store_config() -> StoreConfig { store_updates: false, store_delegators: false, store_votes: false, - store_block_hashes: true, + store_blocks: true, store_stake_addresses: false, } } diff --git a/processes/omnibus/omnibus.toml b/processes/omnibus/omnibus.toml index c96960ef..e66f566e 100644 --- a/processes/omnibus/omnibus.toml +++ b/processes/omnibus/omnibus.toml @@ -44,8 +44,8 @@ store-updates = false store-delegators = false # Enables /pools/{pool_id}/votes endpoint store-votes = false -# Store block hashes, enables /pools/{pool_id}/blocks, /epochs/{number}/blocks/{pool_id} -store-block-hashes = false +# Store blocks, enables /pools/{pool_id}/blocks, /epochs/{number}/blocks/{pool_id} +store-blocks = false # Store stake_addresses store-stake-addresses = false From c889ab73a6900206810eeb645f32a91b7805be24 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 13 Oct 2025 10:17:09 +0200 Subject: [PATCH 5/7] refactor: move blocks to historical state in spo state --- modules/spo_state/src/historical_spo_state.rs | 24 +++++++- modules/spo_state/src/spo_state.rs | 17 +++--- modules/spo_state/src/state.rs | 60 +++++++------------ 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/modules/spo_state/src/historical_spo_state.rs b/modules/spo_state/src/historical_spo_state.rs index 609684d9..51c63ddc 100644 --- a/modules/spo_state/src/historical_spo_state.rs +++ b/modules/spo_state/src/historical_spo_state.rs @@ -1,7 +1,7 @@ use acropolis_common::{ queries::governance::VoteRecord, KeyHash, PoolRegistration, PoolUpdateEvent, }; -use imbl::HashSet; +use imbl::{HashSet, OrdMap, Vector}; use serde::{Deserialize, Serialize}; use crate::store_config::StoreConfig; @@ -17,6 +17,10 @@ pub struct HistoricalSPOState { pub delegators: Option>, // SPO's votes pub votes: Option>, + + // blocks + // + pub blocks: Option>>, } impl HistoricalSPOState { @@ -27,6 +31,7 @@ impl HistoricalSPOState { updates: store_config.store_updates.then(Vec::new), delegators: store_config.store_delegators.then(HashSet::new), votes: store_config.store_votes.then(Vec::new), + blocks: store_config.store_blocks.then(OrdMap::new), } } @@ -55,4 +60,21 @@ impl HistoricalSPOState { pub fn remove_delegator(&mut self, delegator: &KeyHash) -> Option { self.delegators.as_mut().and_then(|delegators| Some(delegators.remove(delegator).is_some())) } + + pub fn get_all_blocks(&self) -> Option> { + self.blocks.as_ref().map(|blocks| blocks.values().flatten().cloned().collect()) + } + + pub fn get_blocks_by_epoch(&self, epoch: u64) -> Option> { + self.blocks + .as_ref() + .and_then(|blocks| blocks.get(&epoch).map(|blocks| blocks.iter().cloned().collect())) + } + + pub fn add_block(&mut self, epoch: u64, block_number: u64) -> Option<()> { + self.blocks.as_mut().and_then(|blocks| { + blocks.entry(epoch).or_insert_with(Vector::new).push_back(block_number); + Some(()) + }) + } } diff --git a/modules/spo_state/src/spo_state.rs b/modules/spo_state/src/spo_state.rs index 396663a5..70de4850 100644 --- a/modules/spo_state/src/spo_state.rs +++ b/modules/spo_state/src/spo_state.rs @@ -635,17 +635,18 @@ impl SPOState { } PoolsStateQuery::GetBlocksByPool { pool_id } => { - match state.get_blocks_by_pool(pool_id) { - Ok(blocks) => PoolsStateQueryResponse::BlocksByPool(blocks), - Err(_) => PoolsStateQueryResponse::Error("Blocks are not enabled".into()), - } + state + .is_historical_blocks_enabled() + .then(|| PoolsStateQueryResponse::BlocksByPool(state.get_blocks_by_pool(pool_id).unwrap_or_default())) + .unwrap_or(PoolsStateQueryResponse::Error("Blocks are not enabled".into())) } PoolsStateQuery::GetBlocksByPoolAndEpoch { pool_id, epoch } => { - match state.get_blocks_by_pool_and_epoch(pool_id, *epoch) { - Ok(blocks) => PoolsStateQueryResponse::BlocksByPoolAndEpoch(blocks), - Err(_) => PoolsStateQueryResponse::Error("Blocks are not enabled".into()), - } + state + .is_historical_blocks_enabled() + .then(|| PoolsStateQueryResponse::BlocksByPoolAndEpoch(state.get_blocks_by_pool_and_epoch(pool_id, *epoch) + .unwrap_or_default())) + .unwrap_or(PoolsStateQueryResponse::Error("Blocks are not enabled".into())) } PoolsStateQuery::GetPoolUpdates { pool_id } => { diff --git a/modules/spo_state/src/state.rs b/modules/spo_state/src/state.rs index 72609bef..4b1a18ff 100644 --- a/modules/spo_state/src/state.rs +++ b/modules/spo_state/src/state.rs @@ -15,7 +15,7 @@ use acropolis_common::{ VotingProcedures, }; use anyhow::Result; -use imbl::{HashMap, OrdMap, Vector}; +use imbl::HashMap; use std::sync::{Arc, Mutex}; use tracing::{debug, error, info}; @@ -41,10 +41,6 @@ pub struct State { // Keyed by pool_id total_blocks_minted: HashMap, - /// block heights (numbers) keyed pool id and epoch - /// > - blocks: Option>>>, - /// historical spo state /// keyed by pool operator id historical_spos: Option>, @@ -68,11 +64,6 @@ impl State { } else { None }, - blocks: if config.store_blocks { - Some(HashMap::new()) - } else { - None - }, stake_addresses: if config.store_stake_addresses { Some(Arc::new(Mutex::new(StakeAddressMap::new()))) } else { @@ -97,7 +88,7 @@ impl State { self.store_config.store_votes } - pub fn is_blocks_enabled(&self) -> bool { + pub fn is_historical_blocks_enabled(&self) -> bool { self.store_config.store_blocks } @@ -125,7 +116,6 @@ impl From for State { vrf_key_hash_to_pool_id_map, total_blocks_minted: HashMap::new(), historical_spos: None, - blocks: None, stake_addresses: None, } } @@ -222,28 +212,21 @@ impl State { /// Get Blocks by Pool /// Return Vector of block heights - /// Return Err when store_blocks not enabled - pub fn get_blocks_by_pool(&self, pool_id: &KeyHash) -> Result> { - let Some(blocks) = self.blocks.as_ref() else { - return Err(anyhow::anyhow!("Blocks are not enabled")); + /// Return None when store_blocks not enabled + pub fn get_blocks_by_pool(&self, pool_id: &KeyHash) -> Option> { + let Some(historical_spos) = self.historical_spos.as_ref() else { + return None; }; - Ok(blocks - .get(pool_id) - .map(|epochs| epochs.values().flatten().cloned().collect()) - .unwrap_or_default()) + historical_spos.get(pool_id).and_then(|s| s.get_all_blocks()) } /// Get Blocks by Pool and Epoch - /// Return Err when store_blocks not enabled - pub fn get_blocks_by_pool_and_epoch(&self, pool_id: &KeyHash, epoch: u64) -> Result> { - let Some(blocks) = self.blocks.as_ref() else { - return Err(anyhow::anyhow!("Blocks are not enabled")); + /// Return None when store_blocks not enabled + pub fn get_blocks_by_pool_and_epoch(&self, pool_id: &KeyHash, epoch: u64) -> Option> { + let Some(historical_spos) = self.historical_spos.as_ref() else { + return None; }; - Ok(blocks - .get(pool_id) - .map(|epochs| epochs.get(&epoch).map(|blocks| blocks.iter().cloned().collect())) - .flatten() - .unwrap_or_default()) + historical_spos.get(pool_id).and_then(|s| s.get_blocks_by_epoch(epoch)) } /// Get Pool Updates @@ -299,14 +282,13 @@ impl State { *(self.total_blocks_minted.entry(pool_id.clone()).or_insert(0)) += 1; // if store_blocks is enabled - if let Some(blocks) = self.blocks.as_mut() { - blocks - .entry(pool_id) - .or_insert_with(OrdMap::new) - .entry(block_info.epoch) - .or_insert_with(Vector::new) - .push_back(block_info.number); - }; + if self.is_historical_blocks_enabled() { + if let Some(historical_spos) = self.historical_spos.as_mut() { + if let Some(historical_spo) = historical_spos.get_mut(&pool_id) { + historical_spo.add_block(block_info.epoch, block_info.number); + } + } + } true } @@ -1080,9 +1062,9 @@ mod tests { } #[test] - fn get_blocks_returns_err_when_blocks_not_enabled() { + fn get_blocks_returns_none_when_blocks_not_enabled() { let state = State::default(); - assert!(state.get_blocks_by_pool(&vec![0]).is_err()); + assert!(state.get_blocks_by_pool(&vec![0]).is_none()); } #[test] From c3eccf68ce52217d88e228b29585df3decef8fec Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 13 Oct 2025 10:21:24 +0200 Subject: [PATCH 6/7] fix: test cases --- modules/spo_state/src/state.rs | 3 +-- modules/spo_state/src/store_config.rs | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/spo_state/src/state.rs b/modules/spo_state/src/state.rs index 4b1a18ff..931ad608 100644 --- a/modules/spo_state/src/state.rs +++ b/modules/spo_state/src/state.rs @@ -1110,7 +1110,6 @@ mod tests { assert_eq!(blocks.len(), 1); assert_eq!(blocks[0], block.number); - let blocks = state.get_blocks_by_pool_and_epoch(&vec![1], 3).unwrap(); - assert_eq!(blocks.len(), 0); + assert!(state.get_blocks_by_pool_and_epoch(&vec![1], 3).is_none()); } } diff --git a/modules/spo_state/src/store_config.rs b/modules/spo_state/src/store_config.rs index 3b3372fc..a89c15d6 100644 --- a/modules/spo_state/src/store_config.rs +++ b/modules/spo_state/src/store_config.rs @@ -48,7 +48,11 @@ impl StoreConfig { } pub fn store_historical_state(&self) -> bool { - self.store_registration || self.store_updates || self.store_delegators || self.store_votes + self.store_registration + || self.store_updates + || self.store_delegators + || self.store_votes + || self.store_blocks } } From e60501eb3a23ed34946eb76aa2992006d139f060 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 13 Oct 2025 10:34:25 +0200 Subject: [PATCH 7/7] fix: test --- modules/epochs_state/src/epochs_history.rs | 4 ++++ processes/omnibus/omnibus.toml | 1 + 2 files changed, 5 insertions(+) diff --git a/modules/epochs_state/src/epochs_history.rs b/modules/epochs_state/src/epochs_history.rs index 22875633..ee2d67bf 100644 --- a/modules/epochs_state/src/epochs_history.rs +++ b/modules/epochs_state/src/epochs_history.rs @@ -149,7 +149,9 @@ mod tests { epoch_start_time: 0, epoch_end_time: 0, first_block_time: 0, + first_block_height: 0, last_block_time: 0, + last_block_height: 0, total_blocks: 1, total_txs: 1, total_outputs: 100, @@ -167,7 +169,9 @@ mod tests { epoch_start_time: 0, epoch_end_time: 0, first_block_time: 0, + first_block_height: 0, last_block_time: 0, + last_block_height: 0, total_blocks: 1, total_txs: 1, total_outputs: 100, diff --git a/processes/omnibus/omnibus.toml b/processes/omnibus/omnibus.toml index e66f566e..c44f9449 100644 --- a/processes/omnibus/omnibus.toml +++ b/processes/omnibus/omnibus.toml @@ -51,6 +51,7 @@ store-stake-addresses = false [module.spdd-state] # Enables active_stakes in /epochs/latest | {number} endpoints +# Enables /epochs/{number}/{next | previous} store-spdd = false [module.drep-state]