Skip to content

Conversation

whankinsiv
Copy link
Collaborator

@whankinsiv whankinsiv commented Oct 9, 2025

This PR enables optional indexing of address-related data required for conformance with the Blockfrost API specification.

Storage lifecycle:

  • The module subscribes to address deltas messages emitted by the UTxO state and applies them to the in-memory volatile layer which tracks live address updates within the rollback window.
  • When the chain advances far enough that an entire previous epoch of deltas can no longer be rolled back, those finalized blocks are pruned from volatile and transferred into a pending queue within the ImmutableAddressStore.
  • A background persistence worker consumes the epoch's pending deltas and atomically writes the updated immutable state to disk. Epochs are processed sequentially, with only one allowed in the queue before blocking the main run loop to prevent unbounded memory growth.

Retrieving live state:

  • The immutable address data is first fetched from Fjall, and any pending immutable entries waiting to be persisted are merged into the result.
  • The getter then iterates through each block in the in-memory volatile layer, applying any deltas relevant to the queried address on top of the immutable snapshot to produce an up-to-date view of the address state.

Data indexed:

pub struct AddressEntry {
    // The live utxo set for an address
    pub utxos: Option<Vec<UtxoDelta>>,      
        
    // All transactions involving the address
    pub transactions: Option<Vec<TxIdentifier>>, 

    // The total sent/received amounts for the address (lovelace + native assets)
    pub totals: Option<Vec<ValueDelta>>,            
}

REST handlers:

  • This PR introduces the REST handler for the /addresses/{address} endpoint.
  • A follow-up PR will add the /addresses/{address}/totals, /addresses/{address}/utxos, and /addresses/{address}/transactions endpoints, all of which rely on the data indexed by this module.

Next steps:

  • Beyond implementing the remaining address-related REST handlers, refactoring the assets_state module to adopt the same storage lifecycle will significantly reduce the RAM footprint for address and transaction indexing.

Signed-off-by: William Hankins <[email protected]>
Signed-off-by: William Hankins <[email protected]>
Signed-off-by: William Hankins <[email protected]>
Signed-off-by: William Hankins <[email protected]>
@whankinsiv whankinsiv marked this pull request as ready for review October 13, 2025 22:28
@lowhung lowhung self-requested a review October 13, 2025 22:55
Copy link
Collaborator

@lowhung lowhung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nicely done Will!

Ok(data)
}

pub fn stake_address_string(&self) -> Result<Option<String>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know these are fairly straightforward methods, but would it be worth adding to/creating tests to cover them?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests for both script and normal addresses to stake_address_string added in a1767e6.


use crate::{handlers_config::HandlersConfig, types::AddressInfoREST};

pub async fn handle_address_single_blockfrost(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More of a nit, but I do appreciate the /path this handle method corresponds to above this as a comment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comments above all address related handlers to indicate which endpoints they cover in 3dfa776.

);
}

match batch.commit() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we limit the batch chunk by chunk, otherwise it ends up batching tons of data which is not that efficient.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to do it this way so that if the program is exited or crashes mid persistence we wont have a corrupted DB. I'm open to any alternative solutions you may have.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants