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
31 changes: 30 additions & 1 deletion storage/blockchain/src/ops/alt_block/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub fn add_alt_block(
///
/// This function will look at only the blocks with the given [`AltBlockHeight::chain_id`], no others
/// even if they are technically part of this chain.
pub fn get_alt_block(
pub fn get_alt_block_information(
db: &BlockchainDatabase,
alt_block_height: &AltBlockHeight,
tx_ro: &fjall::Snapshot,
Expand Down Expand Up @@ -134,6 +134,22 @@ pub fn get_alt_block(
})
}

/// Retrieve an alt [`Block`] via its [`AltBlockHeight`].
///
/// This function will look at only the blocks with the given [`AltBlockHeight::chain_id`], no others
/// even if they are technically part of this chain.
pub fn get_alt_block(
db: &BlockchainDatabase,
alt_block_height: &AltBlockHeight,
tx_ro: &fjall::Snapshot,
) -> DbResult<Block> {
let block_blob = tx_ro
.get(&db.alt_block_blobs, bytemuck::bytes_of(alt_block_height))?
.ok_or(BlockchainError::NotFound)?;

Ok(Block::read(&mut block_blob.as_ref()).unwrap())
}

/// Retrieves the hash of the block at the given `block_height` on the alt chain with
/// the given [`ChainId`].
///
Expand Down Expand Up @@ -227,3 +243,16 @@ pub fn get_alt_block_extended_header_from_height(
long_term_weight: block_info.long_term_weight,
})
}

/// Returns the [`AltBlockHeight`] of a block from its hash, only if it is in an alt chain.
pub(crate) fn alt_block_height(
db: &BlockchainDatabase,
tx_ro: &fjall::Snapshot,
hash: &BlockHash,
) -> DbResult<Option<AltBlockHeight>> {
let Some(bytes) = tx_ro.get(&db.alt_block_heights, hash)? else {
return Ok(None);
};

Ok(Some(bytemuck::pod_read_unaligned(bytes.as_ref())))
}
3 changes: 2 additions & 1 deletion storage/blockchain/src/ops/alt_block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ mod block;
mod chain;
mod tx;

pub(crate) use block::alt_block_height;
pub use block::{
add_alt_block, flush_alt_blocks, get_alt_block, get_alt_block_extended_header_from_height,
get_alt_block_hash,
get_alt_block_hash, get_alt_block_information,
};
pub use chain::{get_alt_chain_history_ranges, update_alt_chain_info};
pub use tx::{add_alt_transaction_blob, get_alt_transaction};
2 changes: 1 addition & 1 deletion storage/blockchain/src/ops/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ pub fn block_exists(
pub(crate) fn block_height(
db: &BlockchainDatabase,
tx_ro: &fjall::Snapshot,
hash: &[u8; 32],
hash: &BlockHash,
) -> DbResult<Option<usize>> {
let Some(block_height) = tx_ro.get(&db.block_heights, hash)? else {
return Ok(None);
Expand Down
93 changes: 54 additions & 39 deletions storage/blockchain/src/service/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ use crate::{
error::{BlockchainError, DbResult},
ops::{
alt_block::{
get_alt_block, get_alt_block_extended_header_from_height, get_alt_block_hash,
get_alt_chain_history_ranges,
alt_block_height, get_alt_block, get_alt_block_extended_header_from_height,
get_alt_block_hash, get_alt_block_information, get_alt_chain_history_ranges,
},
block::{
block_exists, block_height, get_block, get_block_by_hash, get_block_complete_entry,
Expand Down Expand Up @@ -290,22 +290,15 @@ fn block_hash_in_range(
fn find_block(db: &BlockchainDatabase, block_hash: BlockHash) -> ResponseResult {
let tx_ro = db.fjall.snapshot();

// Check the main chain first.
if let Some(height) = block_height(db, &tx_ro, &block_hash)? {
return Ok(BlockchainResponse::FindBlock(Some((Chain::Main, height))));
}

match tx_ro.get(&db.alt_block_heights, block_hash)? {
Some(height) => {
let height: AltBlockHeight = bytemuck::pod_read_unaligned(height.as_ref());
// Check the main chain first, then alt chains.
let location = if let Some(height) = block_height(db, &tx_ro, &block_hash)? {
Some((Chain::Main, height))
} else {
alt_block_height(db, &tx_ro, &block_hash)?
.map(|alt| (Chain::Alt(alt.chain_id.into()), alt.height))
};

Ok(BlockchainResponse::FindBlock(Some((
Chain::Alt(height.chain_id.into()),
height.height,
))))
}
None => Ok(BlockchainResponse::FindBlock(None)),
}
Ok(BlockchainResponse::FindBlock(location))
}

/// [`BlockchainReadRequest::FilterUnknownHashes`].
Expand Down Expand Up @@ -704,36 +697,58 @@ fn find_first_unknown(db: &BlockchainDatabase, block_ids: &[BlockHash]) -> Respo
/// [`BlockchainReadRequest::TxsInBlock`]
fn txs_in_block(
db: &BlockchainDatabase,
block_hash: [u8; 32],
block_hash: BlockHash,
missing_txs: Vec<u64>,
) -> ResponseResult {
let tx_ro = db.fjall.snapshot();
let tapes = db.linear_tapes.reader();

let block_height = usize::from_le_bytes(
tx_ro
.get(&db.block_heights, block_hash)?
.ok_or(BlockchainError::NotFound)?
.as_ref()
.try_into()
.unwrap(),
);
// Check the main chain first, fall back to alt blocks if not found.
let (block, txs) = if let Some(block_height) = block_height(db, &tx_ro, &block_hash)? {
let block_info = tapes
.read_entry(&db.block_infos, usize_to_u64(block_height))?
.ok_or(BlockchainError::NotFound)?;

let block_info = tapes
.read_entry(&db.block_infos, usize_to_u64(block_height))?
.ok_or(BlockchainError::NotFound)?;
let block = get_block(&block_height, Some(&block_info), &tapes, db)?;
let first_tx_index = block_info.mining_tx_index + 1;

let block = get_block(&block_height, None, &tapes, db)?;
let first_tx_index = block_info.mining_tx_index + 1;
if block.transactions.len() < missing_txs.len() {
return Ok(BlockchainResponse::TxsInBlock(None));
}

if block.transactions.len() < missing_txs.len() {
return Ok(BlockchainResponse::TxsInBlock(None));
}
let txs = missing_txs
.into_iter()
.map(|index_offset| get_tx_blob_from_id(&(first_tx_index + index_offset), &tapes, db))
.collect::<DbResult<_>>()?;

let txs = missing_txs
.into_iter()
.map(|index_offset| get_tx_blob_from_id(&(first_tx_index + index_offset), &tapes, db))
.collect::<DbResult<_>>()?;
(block, txs)
} else {
let alt_block_height =
alt_block_height(db, &tx_ro, &block_hash)?.ok_or(BlockchainError::NotFound)?;

let block = get_alt_block(db, &alt_block_height, &tx_ro)?;

if block.transactions.len() < missing_txs.len() {
return Ok(BlockchainResponse::TxsInBlock(None));
}

let txs = missing_txs
.into_iter()
.map(|index_offset| {
let tx_hash = block
.transactions
.get(u64_to_usize(index_offset))
.ok_or(BlockchainError::NotFound)?;

tx_ro
.get(&db.alt_transaction_blobs, tx_hash)?
.map(|blob| blob.to_vec())
.ok_or(BlockchainError::NotFound)
})
.collect::<DbResult<_>>()?;

(block, txs)
};

Ok(BlockchainResponse::TxsInBlock(Some(TxsInBlock {
block: block.serialize(),
Expand All @@ -759,7 +774,7 @@ fn alt_blocks_in_chain(db: &BlockchainDatabase, chain_id: ChainId) -> ResponseRe
};

range.clone().map(|height| {
get_alt_block(
get_alt_block_information(
db,
&AltBlockHeight {
chain_id: (*chain_id).into(),
Expand Down
Loading