use super::*;
#[async_trait]
impl IndexedBlockExt for DbV1 {
async fn get_chain_block(
&self,
height: Height,
) -> Result<Option<IndexedBlock>, FinalisedStateError> {
self.get_chain_block(height).await
}
}
impl DbV1 {
async fn get_chain_block(
&self,
height: Height,
) -> Result<Option<IndexedBlock>, FinalisedStateError> {
let validated_height = match self
.resolve_validated_hash_or_height(HashOrHeight::Height(height.into()))
.await
{
Ok(height) => height,
Err(FinalisedStateError::DataUnavailable(_)) => return Ok(None),
Err(other) => return Err(other),
};
let height_bytes = validated_height.to_bytes()?;
tokio::task::block_in_place(|| {
let txn = self.env.begin_ro_txn()?;
let raw = match txn.get(self.headers, &height_bytes) {
Ok(val) => val,
Err(lmdb::Error::NotFound) => {
return Err(FinalisedStateError::DataUnavailable(
"block data missing from db".into(),
));
}
Err(e) => return Err(FinalisedStateError::LmdbError(e)),
};
let header: BlockHeaderData = *StoredEntryVar::from_bytes(raw)
.map_err(|e| FinalisedStateError::Custom(format!("header decode error: {e}")))?
.inner();
let raw = match txn.get(self.txids, &height_bytes) {
Ok(val) => val,
Err(lmdb::Error::NotFound) => {
return Err(FinalisedStateError::DataUnavailable(
"block data missing from db".into(),
));
}
Err(e) => return Err(FinalisedStateError::LmdbError(e)),
};
let txids_list = StoredEntryVar::<TxidList>::from_bytes(raw)
.map_err(|e| FinalisedStateError::Custom(format!("txids decode error: {e}")))?
.inner()
.clone();
let txids = txids_list.txids();
let raw = match txn.get(self.transparent, &height_bytes) {
Ok(val) => val,
Err(lmdb::Error::NotFound) => {
return Err(FinalisedStateError::DataUnavailable(
"block data missing from db".into(),
));
}
Err(e) => return Err(FinalisedStateError::LmdbError(e)),
};
let transparent_list = StoredEntryVar::<TransparentTxList>::from_bytes(raw)
.map_err(|e| FinalisedStateError::Custom(format!("transparent decode error: {e}")))?
.inner()
.clone();
let transparent = transparent_list.tx();
let raw = match txn.get(self.sapling, &height_bytes) {
Ok(val) => val,
Err(lmdb::Error::NotFound) => {
return Err(FinalisedStateError::DataUnavailable(
"block data missing from db".into(),
));
}
Err(e) => return Err(FinalisedStateError::LmdbError(e)),
};
let sapling_list = StoredEntryVar::<SaplingTxList>::from_bytes(raw)
.map_err(|e| FinalisedStateError::Custom(format!("sapling decode error: {e}")))?
.inner()
.clone();
let sapling = sapling_list.tx();
let raw = match txn.get(self.orchard, &height_bytes) {
Ok(val) => val,
Err(lmdb::Error::NotFound) => {
return Err(FinalisedStateError::DataUnavailable(
"block data missing from db".into(),
));
}
Err(e) => return Err(FinalisedStateError::LmdbError(e)),
};
let orchard_list = StoredEntryVar::<OrchardTxList>::from_bytes(raw)
.map_err(|e| FinalisedStateError::Custom(format!("orchard decode error: {e}")))?
.inner()
.clone();
let orchard = orchard_list.tx();
let len = txids.len();
if transparent.len() != len || sapling.len() != len || orchard.len() != len {
return Err(FinalisedStateError::Custom(
"mismatched tx list lengths in block data".to_string(),
));
}
let txs: Vec<CompactTxData> = (0..len)
.map(|i| {
let txid = txids[i];
let transparent_tx = transparent[i]
.clone()
.unwrap_or_else(|| TransparentCompactTx::new(vec![], vec![]));
let sapling_tx = sapling[i]
.clone()
.unwrap_or_else(|| SaplingCompactTx::new(None, vec![], vec![]));
let orchard_tx = orchard[i]
.clone()
.unwrap_or_else(|| OrchardCompactTx::new(None, vec![]));
CompactTxData::new(i as u64, txid, transparent_tx, sapling_tx, orchard_tx)
})
.collect();
let raw = match txn.get(self.commitment_tree_data, &height_bytes) {
Ok(val) => val,
Err(lmdb::Error::NotFound) => {
return Err(FinalisedStateError::DataUnavailable(
"block data missing from db".into(),
));
}
Err(e) => return Err(FinalisedStateError::LmdbError(e)),
};
let commitment_tree_data: CommitmentTreeData = *StoredEntryFixed::from_bytes(raw)
.map_err(|e| {
FinalisedStateError::Custom(format!("commitment_tree decode error: {e}"))
})?
.inner();
Ok(Some(IndexedBlock::new(
header.context,
*header.data(),
txs,
commitment_tree_data,
)))
})
}
}