Skip to content

Commit

Permalink
feat: adds rpcs: block_info, block_digest
Browse files Browse the repository at this point in the history
block_info   --> returns information about a block
block_digest --> returns a digest for a block selector

introduces BlockSelector enum, for identifying block by
 height | digest | genesis | tip

removes block_tip RPC, as block_info() includes that functionality
when called with selector == BlockSelector::Tip
  • Loading branch information
dan-da committed Apr 18, 2024
1 parent 678ede6 commit b433e0d
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 12 deletions.
29 changes: 29 additions & 0 deletions src/models/state/archival_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ impl ArchivalState {
}
}

pub fn genesis_block(&self) -> &Block {
&self.genesis_block
}

/// Write a newly found block to database and to disk.
pub async fn write_block(
&mut self,
Expand Down Expand Up @@ -494,6 +498,31 @@ impl ArchivalState {
.unwrap_or_else(Vec::new)
}

/// Return the digest of canonical block at a specific height, or None
pub async fn block_height_to_canonical_block_digest(
&self,
block_height: BlockHeight,
tip_digest: Digest,
) -> Option<Digest> {
let digests = self.block_height_to_block_digests(block_height).await;

// note: there should only ever be 1 block at a given height that
// is in the canonical chain.
//
// note: we could do this with an async stream using equivalent of
// Iterator::find() but the for loop is easier to understand.
// see: https://stackoverflow.com/questions/74901029/rust-async-find-use-await-within-predicate
for digest in digests.into_iter() {
if self
.block_belongs_to_canonical_chain(digest, tip_digest)
.await
{
return Some(digest);
}
}
None
}

pub async fn get_children_block_headers(
&self,
parent_block_digest: Digest,
Expand Down
66 changes: 54 additions & 12 deletions src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::models::peer::PeerInfo;
use crate::models::peer::PeerStanding;
use crate::models::state::wallet::address::generation_address;
use crate::models::state::wallet::wallet_status::WalletStatus;
use crate::models::state::{GlobalStateLock, UtxoReceiverData};
use crate::models::state::{GlobalState, GlobalStateLock, UtxoReceiverData};

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct DashBoardOverviewDataFromClient {
Expand Down Expand Up @@ -61,6 +61,31 @@ pub struct BlockInfo {
fee: NeptuneCoins,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum BlockSelector {
Digest(Digest), // Identifies block by Digest (hash)
Height(BlockHeight), // Identifies block by Height (count from genesis)
Genesis, // Indicates the genesis block
Tip, // Indicates the latest canonical block
}

impl BlockSelector {
async fn as_digest(&self, state: &GlobalState) -> Option<Digest> {
match self {
BlockSelector::Digest(d) => Some(*d),
BlockSelector::Height(h) => {
state
.chain
.archival_state()
.block_height_to_canonical_block_digest(*h, state.chain.light_state().hash())
.await
}
BlockSelector::Tip => Some(state.chain.light_state().hash()),
BlockSelector::Genesis => Some(state.chain.archival_state().genesis_block().hash()),
}
}
}

#[tarpc::service]
pub trait RPC {
/******** READ DATA ********/
Expand Down Expand Up @@ -94,15 +119,18 @@ pub trait RPC {
/// Returns the digest of the latest block
async fn tip_digest() -> Digest;

/// Returns information about the latest block
async fn tip_info() -> BlockInfo;

/// Returns the digest of the latest n blocks
async fn latest_tip_digests(n: usize) -> Vec<Digest>;

/// Return the block header of the tip digest
async fn tip_header() -> BlockHeader;

/// Returns information about the specified block
async fn block_info(block_selector: BlockSelector) -> Option<BlockInfo>;

/// Return the digest for the specified block selector (genesis, tip, or height)
async fn block_digest(block_selector: BlockSelector) -> Option<Digest>;

/// Return the block header for the specified block
async fn header(hash: Digest) -> Option<BlockHeader>;

Expand Down Expand Up @@ -235,22 +263,36 @@ impl RPC for NeptuneRPCServer {
self.state.lock_guard().await.chain.light_state().hash()
}

async fn tip_info(self, _: context::Context) -> BlockInfo {
async fn block_digest(
self,
_: context::Context,
block_selector: BlockSelector,
) -> Option<Digest> {
let state = self.state.lock_guard().await;
let light_state = state.chain.light_state();

let header = light_state.header();
let body = light_state.body();
block_selector.as_digest(&state).await
}

BlockInfo {
digest: state.chain.light_state().hash(),
async fn block_info(
self,
_: context::Context,
block_selector: BlockSelector,
) -> Option<BlockInfo> {
let state = self.state.lock_guard().await;
let digest = block_selector.as_digest(&state).await?;
let archival_state = state.chain.archival_state();

let block = archival_state.get_block(digest).await.unwrap()?;
let header = block.header();
let body = block.body();
Some(BlockInfo {
digest: block.hash(),
height: header.height,
timestamp: header.timestamp,
difficulty: header.difficulty,
num_inputs: body.transaction.kernel.inputs.len(),
num_outputs: body.transaction.kernel.outputs.len(),
fee: body.transaction.kernel.fee,
}
})
}

async fn latest_tip_digests(self, _context: tarpc::context::Context, n: usize) -> Vec<Digest> {
Expand Down

0 comments on commit b433e0d

Please sign in to comment.