Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## v0.15.0 (TBD)

- [BREAKING] Changed `GetBlockByNumber` to accept a `GetBlockByNumberRequest` (with optional `include_proof` flag) and returns a `GetBlockByNumberResponse` containing the block and an optional block proof ([#1864](https://github.com/0xMiden/node/pull/1864)).

## v0.14.0 (TBD)

### Enhancements
Expand Down
4 changes: 2 additions & 2 deletions crates/rpc/src/server/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,8 @@ impl api_server::Api for RpcService {

async fn get_block_by_number(
&self,
request: Request<proto::blockchain::BlockNumber>,
) -> Result<Response<proto::blockchain::MaybeBlock>, Status> {
request: Request<proto::blockchain::GetBlockByNumberRequest>,
) -> Result<Response<proto::blockchain::GetBlockByNumberResponse>, Status> {
let request = request.into_inner();

debug!(target: COMPONENT, ?request);
Expand Down
17 changes: 17 additions & 0 deletions crates/store/src/blocks.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
//! File-based storage for raw block data and block proofs.
//!
//! Block data is stored under `{store_dir}/{epoch:04x}/block_{block_num:08x}.dat`, and proof data
//! for proven blocks is stored under `{store_dir}/{epoch:04x}/proof_{block_num:08x}.dat`.
//!
//! The epoch is derived from the 16 most significant bits of the block number (i.e.,
//! `block_num >> 16`), and both the epoch and block number are formatted as zero-padded
//! hexadecimal strings.

use std::io::ErrorKind;
use std::ops::Not;
use std::path::PathBuf;
Expand Down Expand Up @@ -96,6 +105,14 @@ impl BlockStore {
fs_err::write(block_path, data)
}

pub async fn load_proof(&self, block_num: BlockNumber) -> std::io::Result<Option<Vec<u8>>> {
match tokio::fs::read(self.proof_path(block_num)).await {
Ok(data) => Ok(Some(data)),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(err) => Err(err),
}
}

// PROOF STORAGE
// --------------------------------------------------------------------------------------------

Expand Down
21 changes: 13 additions & 8 deletions crates/store/src/server/rpc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,19 +237,24 @@ impl rpc_server::Rpc for StoreApi {

async fn get_block_by_number(
&self,
request: Request<proto::blockchain::BlockNumber>,
) -> Result<Response<proto::blockchain::MaybeBlock>, Status> {
request: Request<proto::blockchain::GetBlockByNumberRequest>,
) -> Result<Response<proto::blockchain::GetBlockByNumberResponse>, Status> {
let request = request.into_inner();

debug!(target: COMPONENT, ?request);

let block = self
.state
.load_block(request.block_num.into())
.await
.map_err(GetBlockByNumberError::from)?;
// Load block from state.
let block_num = BlockNumber::from(request.block_num);
let block = self.state.load_block(block_num).await.map_err(GetBlockByNumberError::from)?;

// Load proof from state.
let proof = if request.include_proof.unwrap_or_default() {
self.state.load_proof(block_num).await.map_err(GetBlockByNumberError::from)?
} else {
None
};

Ok(Response::new(proto::blockchain::MaybeBlock { block }))
Ok(Response::new(proto::blockchain::GetBlockByNumberResponse { block, proof }))
}

async fn get_account(
Expand Down
11 changes: 11 additions & 0 deletions crates/store/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,17 @@ impl State {
self.block_store.load_block(block_num).await.map_err(Into::into)
}

/// Loads a block proof from the block store. Returns `Ok(None)` if the proof is not found.
pub async fn load_proof(
&self,
block_num: BlockNumber,
) -> Result<Option<Vec<u8>>, DatabaseError> {
if block_num > self.latest_block_num().await {
return Ok(None);
}
self.block_store.load_proof(block_num).await.map_err(Into::into)
}

/// Returns the latest block number.
pub async fn latest_block_num(&self) -> BlockNumber {
self.inner.read().await.latest_block_num()
Expand Down
4 changes: 2 additions & 2 deletions proto/proto/internal/store.proto
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ service Rpc {
// Returns the latest details the specified account.
rpc GetAccount(rpc.AccountRequest) returns (rpc.AccountResponse) {}

// Returns raw block data for the specified block number.
rpc GetBlockByNumber(blockchain.BlockNumber) returns (blockchain.MaybeBlock) {}
// Returns raw block data for the specified block number, optionally including the block proof.
rpc GetBlockByNumber(blockchain.GetBlockByNumberRequest) returns (blockchain.GetBlockByNumberResponse) {}

// Retrieves block header by given block number. Optionally, it also returns the MMR path
// and current chain length to authenticate the block's inclusion.
Expand Down
4 changes: 2 additions & 2 deletions proto/proto/rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ service Api {
// Returns the latest details of the specified account.
rpc GetAccount(AccountRequest) returns (AccountResponse) {}

// Returns raw block data for the specified block number.
rpc GetBlockByNumber(blockchain.BlockNumber) returns (blockchain.MaybeBlock) {}
// Returns raw block data for the specified block number, optionally including the block proof.
rpc GetBlockByNumber(blockchain.GetBlockByNumberRequest) returns (blockchain.GetBlockByNumberResponse) {}

// Retrieves block header by given block number. Optionally, it also returns the MMR path
// and current chain length to authenticate the block's inclusion.
Expand Down
18 changes: 18 additions & 0 deletions proto/proto/types/blockchain.proto
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ message MaybeBlock {
optional bytes block = 1;
}

// Request for retrieving a block by its number, optionally including the block proof.
message GetBlockByNumberRequest {
// The block number of the target block.
fixed32 block_num = 1;
// Whether to include the block proof in the response.
optional bool include_proof = 2;
}

// Response containing the block data and optionally its proof.
message GetBlockByNumberResponse {
// The requested block data encoded using [miden_serde_utils::Serializable] implementation for
// [miden_protocol::block::Block].
optional bytes block = 1;
// The block proof encoded using [miden_serde_utils::Serializable] implementation for
// [miden_protocol::block::BlockProof], if requested and available.
optional bytes proof = 2;
}

// Represents a block number.
message BlockNumber {
// The block number of the target block.
Expand Down
Loading