diff --git a/crates/astria-conductor/src/celestia/block_verifier.rs b/crates/astria-conductor/src/celestia/block_verifier.rs index 7b580b954e..f8fb5ced55 100644 --- a/crates/astria-conductor/src/celestia/block_verifier.rs +++ b/crates/astria-conductor/src/celestia/block_verifier.rs @@ -224,7 +224,10 @@ mod tests { generated::astria::sequencerblock::v1::SequencerBlockHeader as RawSequencerBlockHeader, primitive::v1::RollupId, sequencerblock::v1::{ - block::SequencerBlockHeader, + block::{ + self, + SequencerBlockHeader, + }, celestia::UncheckedSubmittedMetadata, }, }; @@ -237,7 +240,6 @@ mod tests { block::Commit, validator, validator::Info as Validator, - Hash, }, tendermint_proto, tendermint_rpc::endpoint::validators, @@ -345,7 +347,7 @@ mod tests { let header = SequencerBlockHeader::try_from_raw(header).unwrap(); let sequencer_blob = UncheckedSubmittedMetadata { - block_hash: [0u8; 32], + block_hash: block::Hash::new([0u8; 32]), header, rollup_ids: vec![], rollup_transactions_proof, @@ -390,7 +392,7 @@ mod tests { let header = SequencerBlockHeader::try_from_raw(header).unwrap(); let sequencer_blob = UncheckedSubmittedMetadata { - block_hash: [0u8; 32], + block_hash: block::Hash::new([0u8; 32]), header, rollup_ids: vec![rollup_id], rollup_transactions_proof, @@ -510,12 +512,12 @@ mod tests { round: 0u16.into(), block_id: tendermint::block::Id { hash: "74BD4E7F7EF902A84D55589F2AA60B332F1C2F34DDE7652C80BFEB8E7471B1DA" - .parse::() + .parse::() .unwrap(), part_set_header: tendermint::block::parts::Header::new( 1, "7632FFB5D84C3A64279BC9EA86992418ED23832C66E0C3504B7025A9AF42C8C4" - .parse::() + .parse::() .unwrap(), ) .unwrap(), diff --git a/crates/astria-conductor/src/celestia/mod.rs b/crates/astria-conductor/src/celestia/mod.rs index 85146dc645..0c7bc9043c 100644 --- a/crates/astria-conductor/src/celestia/mod.rs +++ b/crates/astria-conductor/src/celestia/mod.rs @@ -6,7 +6,10 @@ use std::{ use astria_core::{ primitive::v1::RollupId, - sequencerblock::v1::block::SequencerBlockHeader, + sequencerblock::v1::block::{ + self, + SequencerBlockHeader, + }, }; use astria_eyre::eyre::{ self, @@ -103,12 +106,16 @@ use crate::{ #[derive(Clone, Debug)] pub(crate) struct ReconstructedBlock { pub(crate) celestia_height: u64, - pub(crate) block_hash: [u8; 32], + pub(crate) block_hash: block::Hash, pub(crate) header: SequencerBlockHeader, pub(crate) transactions: Vec, } impl ReconstructedBlock { + pub(crate) fn block_hash(&self) -> &block::Hash { + &self.block_hash + } + pub(crate) fn sequencer_height(&self) -> SequencerHeight { self.header.height() } @@ -458,7 +465,7 @@ impl RunningReader { error = %eyre::Report::new(e), source_celestia_height = celestia_height, sequencer_height, - block_hash = %base64(&block_hash), + block_hash = %block_hash, "failed pushing reconstructed block into sequential cache; dropping it", ); } diff --git a/crates/astria-conductor/src/celestia/reconstruct.rs b/crates/astria-conductor/src/celestia/reconstruct.rs index 3ee84f93be..9dc5a7d7ea 100644 --- a/crates/astria-conductor/src/celestia/reconstruct.rs +++ b/crates/astria-conductor/src/celestia/reconstruct.rs @@ -3,12 +3,12 @@ use std::collections::HashMap; use astria_core::{ primitive::v1::RollupId, sequencerblock::v1::{ + block, celestia::UncheckedSubmittedMetadata, SubmittedMetadata, SubmittedRollupData, }, }; -use telemetry::display::base64; use tracing::{ info, warn, @@ -72,7 +72,7 @@ pub(super) fn reconstruct_blocks_from_verified_blobs( "no sequencer header blob matching the rollup blob's block hash found" }; info!( - block_hash = %base64(&rollup.sequencer_block_hash()), + block_hash = %rollup.sequencer_block_hash(), reason, "dropping rollup blob", ); @@ -83,7 +83,7 @@ pub(super) fn reconstruct_blocks_from_verified_blobs( for header_blob in header_blobs.into_values() { if header_blob.contains_rollup_id(rollup_id) { warn!( - block_hash = %base64(header_blob.block_hash()), + block_hash = %header_blob.block_hash(), "sequencer header blob contains the target rollup ID, but no matching rollup blob was found; dropping it", ); } else { @@ -99,7 +99,7 @@ pub(super) fn reconstruct_blocks_from_verified_blobs( } fn remove_header_blob_matching_rollup_blob( - headers: &mut HashMap<[u8; 32], SubmittedMetadata>, + headers: &mut HashMap, rollup: &SubmittedRollupData, ) -> Option { // chaining methods and returning () to use the ? operator and to not bind the value diff --git a/crates/astria-conductor/src/celestia/reporting.rs b/crates/astria-conductor/src/celestia/reporting.rs index cd16454b6f..284bc4ac6c 100644 --- a/crates/astria-conductor/src/celestia/reporting.rs +++ b/crates/astria-conductor/src/celestia/reporting.rs @@ -53,7 +53,8 @@ impl<'a> Serialize for ReportReconstructedBlock<'a> { ]; let mut state = serializer.serialize_struct("ReconstructedBlockInfo", FIELDS.len())?; state.serialize_field(FIELDS[0], &self.0.celestia_height)?; - state.serialize_field(FIELDS[1], &base64(&self.0.block_hash))?; + // TODO: use the block hash's Display impl for this + state.serialize_field(FIELDS[1], &base64(&*self.0.block_hash))?; state.serialize_field(FIELDS[2], &self.0.transactions.len())?; state.serialize_field(FIELDS[3], &self.0.celestia_height)?; state.end() diff --git a/crates/astria-conductor/src/celestia/verify.rs b/crates/astria-conductor/src/celestia/verify.rs index 3ac09fa9d1..44570088ad 100644 --- a/crates/astria-conductor/src/celestia/verify.rs +++ b/crates/astria-conductor/src/celestia/verify.rs @@ -5,6 +5,7 @@ use std::{ }; use astria_core::sequencerblock::v1::{ + block, SubmittedMetadata, SubmittedRollupData, }; @@ -25,7 +26,6 @@ use sequencer_client::{ Client as _, HttpClient as SequencerClient, }; -use telemetry::display::base64; use tokio_util::task::JoinMap; use tower::{ util::BoxService, @@ -58,7 +58,7 @@ use crate::executor::{ pub(super) struct VerifiedBlobs { celestia_height: u64, - header_blobs: HashMap<[u8; 32], SubmittedMetadata>, + header_blobs: HashMap, rollup_blobs: Vec, } @@ -75,7 +75,7 @@ impl VerifiedBlobs { self, ) -> ( u64, - HashMap<[u8; 32], SubmittedMetadata>, + HashMap, Vec, ) { (self.celestia_height, self.header_blobs, self.rollup_blobs) @@ -88,7 +88,7 @@ impl VerifiedBlobs { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct VerificationTaskKey { index: usize, - block_hash: [u8; 32], + block_hash: block::Hash, sequencer_height: SequencerHeight, } @@ -142,7 +142,7 @@ pub(super) async fn verify_metadata( .get(dropped_entry.block_hash()) .expect("must exist; just inserted an item under the same key"); info!( - block_hash = %base64(&dropped_entry.block_hash()), + block_hash = %dropped_entry.block_hash(), dropped_blob.sequencer_height = dropped_entry.height().value(), accepted_blob.sequencer_height = accepted_entry.height().value(), "two Sequencer header blobs were well formed and validated against \ @@ -154,7 +154,7 @@ pub(super) async fn verify_metadata( Ok(None) => {} Err(error) => { info!( - block_hash = %base64(&key.block_hash), + block_hash = %key.block_hash, sequencer_height = %key.sequencer_height, %error, "verification of sequencer blob was cancelled abruptly; dropping it" @@ -552,10 +552,13 @@ fn ensure_chain_ids_match(in_commit: &str, in_header: &str) -> eyre::Result<()> Ok(()) } -fn ensure_block_hashes_match(in_commit: &[u8], in_header: &[u8]) -> eyre::Result<()> { +fn ensure_block_hashes_match(in_commit: &[u8], in_header: &block::Hash) -> eyre::Result<()> { use base64::prelude::*; + // NOTE: we still re-encode the block hash using base64 instead of its display impl + // to ensure that the formatting of the two byte slices doesn't accidentally go + // out of whack should the display impl change. ensure!( - in_commit == in_header, + in_commit == in_header.as_ref(), "expected block hash `{}` (from commit), but found `{}` in retrieved metadata", BASE64_STANDARD.encode(in_commit), BASE64_STANDARD.encode(in_header), diff --git a/crates/astria-conductor/src/executor/mod.rs b/crates/astria-conductor/src/executor/mod.rs index 8c3155ca8b..ea515ada8c 100644 --- a/crates/astria-conductor/src/executor/mod.rs +++ b/crates/astria-conductor/src/executor/mod.rs @@ -7,6 +7,7 @@ use astria_core::{ }, primitive::v1::RollupId, sequencerblock::v1::block::{ + self, FilteredSequencerBlock, FilteredSequencerBlockParts, }, @@ -285,7 +286,7 @@ impl Executor { { debug_span!("conductor::Executor::run_until_stopped").in_scope(||debug!( block.height = %block.sequencer_height(), - block.hash = %telemetry::display::base64(&block.block_hash), + block.hash = %block.block_hash(), "received block from celestia reader", )); if let Err(error) = self.execute_firm(block).await { @@ -298,7 +299,7 @@ impl Executor { { debug_span!("conductor::Executor::run_until_stopped").in_scope(||debug!( block.height = %block.height(), - block.hash = %telemetry::display::base64(&block.block_hash()), + block.hash = %block.block_hash(), "received block from sequencer reader", )); if let Err(error) = self.execute_soft(block).await { @@ -388,7 +389,7 @@ impl Executor { } #[instrument(skip_all, fields( - block.hash = %telemetry::display::base64(&block.block_hash()), + block.hash = %block.block_hash(), block.height = block.height().value(), err, ))] @@ -452,7 +453,7 @@ impl Executor { } #[instrument(skip_all, fields( - block.hash = %telemetry::display::base64(&block.block_hash), + block.hash = %block.block_hash(), block.height = block.sequencer_height().value(), err, ))] @@ -532,7 +533,7 @@ impl Executor { /// This function is called via [`Executor::execute_firm`] or [`Executor::execute_soft`], /// and should not be called directly. #[instrument(skip_all, fields( - block.hash = %telemetry::display::base64(&block.hash), + block.hash = %block.hash, block.height = block.height.value(), block.num_of_transactions = block.transactions.len(), rollup.parent_hash = %telemetry::display::base64(&parent_hash), @@ -690,7 +691,7 @@ enum Update { #[derive(Debug)] struct ExecutableBlock { - hash: [u8; 32], + hash: block::Hash, height: SequencerHeight, timestamp: pbjson_types::Timestamp, transactions: Vec, diff --git a/crates/astria-conductor/tests/blackbox/helpers/mod.rs b/crates/astria-conductor/tests/blackbox/helpers/mod.rs index 8890bc3f20..c14ffff018 100644 --- a/crates/astria-conductor/tests/blackbox/helpers/mod.rs +++ b/crates/astria-conductor/tests/blackbox/helpers/mod.rs @@ -642,7 +642,7 @@ pub fn make_commit(height: u32) -> tendermint::block::Commit { height: height.into(), round: 0u16.into(), block_id: Some(tendermint::block::Id { - hash: tendermint::Hash::Sha256(block_hash), + hash: tendermint::Hash::Sha256(block_hash.get()), part_set_header: tendermint::block::parts::Header::default(), }), timestamp: Some(timestamp), @@ -657,7 +657,7 @@ pub fn make_commit(height: u32) -> tendermint::block::Commit { height: height.into(), round: 0u16.into(), block_id: tendermint::block::Id { - hash: tendermint::Hash::Sha256(block_hash), + hash: tendermint::Hash::Sha256(block_hash.get()), part_set_header: tendermint::block::parts::Header::default(), }, signatures: vec![tendermint::block::CommitSig::BlockIdFlagCommit { diff --git a/crates/astria-core/CHANGELOG.md b/crates/astria-core/CHANGELOG.md index b24c5b2855..d80e1e5370 100644 --- a/crates/astria-core/CHANGELOG.md +++ b/crates/astria-core/CHANGELOG.md @@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 to `astria_core::generated::astria` [#1825](https://github.com/astriaorg/astria/pull/1825). - Update `idna` dependency to resolve cargo audit warning [#1869](https://github.com/astriaorg/astria/pull/1869). +- Replaced all instances of `[u8; 32]` by newtype + `astria_core::sequencerblock::v1::block::Hash` where appropriate [#1884](https://github.com/astriaorg/astria/pull/1884). ### Removed diff --git a/crates/astria-core/src/sequencerblock/v1/block.rs b/crates/astria-core/src/sequencerblock/v1/block.rs index d4fc7e7b25..6b52a596e7 100644 --- a/crates/astria-core/src/sequencerblock/v1/block.rs +++ b/crates/astria-core/src/sequencerblock/v1/block.rs @@ -1,5 +1,7 @@ use std::{ collections::HashMap, + fmt::Display, + ops::Deref, vec::IntoIter, }; @@ -580,13 +582,107 @@ enum SequencerBlockHeaderErrorKind { /// Exists to provide convenient access to fields of a [`SequencerBlock`]. #[derive(Clone, Debug, PartialEq)] pub struct SequencerBlockParts { - pub block_hash: [u8; 32], + pub block_hash: Hash, pub header: SequencerBlockHeader, pub rollup_transactions: IndexMap, pub rollup_transactions_proof: merkle::Proof, pub rollup_ids_proof: merkle::Proof, } +/// A newtype wrapper around `[u8; 32]` to represent the hash of a [`SequencerBlock`]. +/// +/// [`Hash`] is the cometbft constructed hash of block. +/// +/// There are two main purposes of this type: +/// +/// 1. avoid confusion with other hashes of the form `[u8; 32]` common in Astria, like rollup +/// (ethereum) 32 byte hashes. +/// 2. to provide a hex formatted display impl, which is the convention for block hashes. +/// +/// Note that hex based `Display` impl of [`Hash`] does not follow the pbjson +/// convention to display protobuf `bytes` using base64 encoding. To get the +/// display formatting faithful to pbjson convetion use the alternative formatting selector, +/// `{block_hash:#}` instead. +/// +/// # Examples +/// +/// ``` +/// use astria_core::sequencerblock::v1::block; +/// +/// let block_hash = block::Hash::new([42; 32]); +/// assert_eq!( +/// "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a", +/// format!("{block_hash}"), +/// ); +/// assert_eq!( +/// "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio=", +/// format!("{block_hash:#}"), +/// ); +/// ``` +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Hash([u8; 32]); + +impl Hash { + pub fn new(inner: [u8; 32]) -> Self { + Self(inner) + } + + pub fn get(&self) -> [u8; 32] { + self.0 + } +} + +impl AsRef<[u8]> for Hash { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl Deref for Hash { + type Target = [u8; 32]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Debug, thiserror::Error)] +#[error("block hash requires 32 bytes, but slice contained `{actual}`")] +pub struct HashFromSliceError { + actual: usize, + source: std::array::TryFromSliceError, +} + +impl<'a> TryFrom<&'a [u8]> for Hash { + type Error = HashFromSliceError; + + fn try_from(value: &'a [u8]) -> Result { + let inner = value.try_into().map_err(|source| Self::Error { + actual: value.len(), + source, + })?; + Ok(Self(inner)) + } +} + +impl Display for Hash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use base64::{ + display::Base64Display, + engine::general_purpose::STANDARD, + }; + + if f.alternate() { + Base64Display::new(&self.0, &STANDARD).fmt(f)?; + } else { + for byte in self.0 { + write!(f, "{byte:02x}")?; + } + } + Ok(()) + } +} + /// `SequencerBlock` is constructed from a tendermint/cometbft block by /// converting its opaque `data` bytes into sequencer specific types. #[derive(Clone, Debug, PartialEq)] @@ -597,7 +693,7 @@ pub struct SequencerBlockParts { pub struct SequencerBlock { /// The result of hashing the cometbft header. Guaranteed to not be `None` as compared to /// the cometbft/tendermint-rs return type. - block_hash: [u8; 32], + block_hash: Hash, /// the block header, which contains the cometbft header and additional sequencer-specific /// commitments. header: SequencerBlockHeader, @@ -622,7 +718,7 @@ impl SequencerBlock { /// /// This is done by hashing the `CometBFT` header stored in this block. #[must_use] - pub fn block_hash(&self) -> &[u8; 32] { + pub fn block_hash(&self) -> &Hash { &self.block_hash } @@ -687,7 +783,7 @@ impl SequencerBlock { rollup_ids_proof, } = self; raw::SequencerBlock { - block_hash: Bytes::copy_from_slice(&block_hash), + block_hash: Bytes::copy_from_slice(block_hash.as_ref()), header: Some(header.into_raw()), rollup_transactions: rollup_transactions .into_values() @@ -863,7 +959,7 @@ impl SequencerBlock { ); Ok(Self { - block_hash, + block_hash: Hash(block_hash), header: SequencerBlockHeader { chain_id, height, @@ -1032,7 +1128,7 @@ where /// Exists to provide convenient access to fields of a [`FilteredSequencerBlock`]. #[derive(Debug, Clone, PartialEq)] pub struct FilteredSequencerBlockParts { - pub block_hash: [u8; 32], + pub block_hash: Hash, pub header: SequencerBlockHeader, // filtered set of rollup transactions pub rollup_transactions: IndexMap, @@ -1050,7 +1146,7 @@ pub struct FilteredSequencerBlockParts { reason = "we want consistent and specific naming" )] pub struct FilteredSequencerBlock { - block_hash: [u8; 32], + block_hash: Hash, header: SequencerBlockHeader, // filtered set of rollup transactions rollup_transactions: IndexMap, @@ -1064,7 +1160,7 @@ pub struct FilteredSequencerBlock { impl FilteredSequencerBlock { #[must_use] - pub fn block_hash(&self) -> &[u8; 32] { + pub fn block_hash(&self) -> &Hash { &self.block_hash } @@ -1114,7 +1210,7 @@ impl FilteredSequencerBlock { .. } = self; raw::FilteredSequencerBlock { - block_hash: Bytes::copy_from_slice(&block_hash), + block_hash: Bytes::copy_from_slice(&*block_hash), header: Some(header.into_raw()), rollup_transactions: rollup_transactions .into_values() diff --git a/crates/astria-core/src/sequencerblock/v1/celestia.rs b/crates/astria-core/src/sequencerblock/v1/celestia.rs index 1fb359d0a4..b7d9eb9139 100644 --- a/crates/astria-core/src/sequencerblock/v1/celestia.rs +++ b/crates/astria-core/src/sequencerblock/v1/celestia.rs @@ -6,6 +6,7 @@ use sha2::{ use super::{ block::{ + self, RollupTransactionsParts, SequencerBlock, SequencerBlockHeader, @@ -134,7 +135,7 @@ enum SubmittedRollupDataErrorKind { /// they can be converted directly into one another. This can change in the future. pub struct UncheckedSubmittedRollupData { /// The hash of the sequencer block. Must be 32 bytes. - pub sequencer_block_hash: [u8; 32], + pub sequencer_block_hash: block::Hash, /// The 32 bytes identifying the rollup this blob belongs to. Matches /// `astria.sequencerblock.v1.RollupTransactions.rollup_id` pub rollup_id: RollupId, @@ -154,7 +155,7 @@ impl UncheckedSubmittedRollupData { #[derive(Clone, Debug)] pub struct SubmittedRollupData { /// The hash of the sequencer block. Must be 32 bytes. - sequencer_block_hash: [u8; 32], + sequencer_block_hash: block::Hash, /// The 32 bytes identifying the rollup this blob belongs to. Matches /// `astria.sequencerblock.v1.RollupTransactions.rollup_id` rollup_id: RollupId, @@ -181,7 +182,7 @@ impl SubmittedRollupData { } #[must_use] - pub fn sequencer_block_hash(&self) -> &[u8; 32] { + pub fn sequencer_block_hash(&self) -> &block::Hash { &self.sequencer_block_hash } @@ -235,7 +236,7 @@ impl SubmittedRollupData { proof, } = self; raw::SubmittedRollupData { - sequencer_block_hash: Bytes::copy_from_slice(&sequencer_block_hash), + sequencer_block_hash: Bytes::copy_from_slice(&*sequencer_block_hash), rollup_id: Some(rollup_id.to_raw()), transactions, proof: Some(proof.into_raw()), @@ -382,7 +383,7 @@ enum SubmittedMetadataErrorKind { /// access the sequencer block's internal types. #[derive(Clone, Debug)] pub struct UncheckedSubmittedMetadata { - pub block_hash: [u8; 32], + pub block_hash: block::Hash, /// The original `CometBFT` header that is the input to this blob's original sequencer block. /// Corresponds to `astria.SequencerBlock.header`. pub header: SequencerBlockHeader, @@ -474,7 +475,7 @@ impl UncheckedSubmittedMetadata { #[derive(Clone, Debug)] pub struct SubmittedMetadata { /// The block hash obtained from hashing `.header`. - block_hash: [u8; 32], + block_hash: block::Hash, /// The sequencer block header. header: SequencerBlockHeader, /// The rollup IDs for which `SubmittedRollupData`s were submitted to celestia. @@ -507,7 +508,7 @@ impl<'a> Iterator for RollupIdIter<'a> { impl SubmittedMetadata { /// Returns the block hash of the tendermint header stored in this blob. #[must_use] - pub fn block_hash(&self) -> &[u8; 32] { + pub fn block_hash(&self) -> &block::Hash { &self.block_hash } @@ -617,7 +618,7 @@ impl SubmittedMetadata { .. } = self; raw::SubmittedMetadata { - block_hash: Bytes::copy_from_slice(&block_hash), + block_hash: Bytes::copy_from_slice(&*block_hash), header: Some(header.into_raw()), rollup_ids: rollup_ids.into_iter().map(RollupId::into_raw).collect(), rollup_transactions_proof: Some(rollup_transactions_proof.into_raw()), diff --git a/crates/astria-sequencer/src/grpc/sequencer.rs b/crates/astria-sequencer/src/grpc/sequencer.rs index dbe25337c2..7643465576 100644 --- a/crates/astria-sequencer/src/grpc/sequencer.rs +++ b/crates/astria-sequencer/src/grpc/sequencer.rs @@ -160,7 +160,7 @@ impl SequencerService for SequencerServer { let all_rollup_ids = all_rollup_ids.into_iter().map(RollupId::into_raw).collect(); let block = RawFilteredSequencerBlock { - block_hash: Bytes::copy_from_slice(&block_hash), + block_hash: Bytes::copy_from_slice(&*block_hash), header: Some(header.into_raw()), rollup_transactions, rollup_transactions_proof: Some(rollup_transactions_proof.into_raw()), diff --git a/crates/astria-sequencer/src/grpc/state_ext.rs b/crates/astria-sequencer/src/grpc/state_ext.rs index fc377d48c1..61097b6301 100644 --- a/crates/astria-sequencer/src/grpc/state_ext.rs +++ b/crates/astria-sequencer/src/grpc/state_ext.rs @@ -1,6 +1,7 @@ use astria_core::{ primitive::v1::RollupId, sequencerblock::v1::block::{ + self, RollupTransactions, SequencerBlock, SequencerBlockHeader, @@ -31,7 +32,7 @@ use crate::storage::StoredValue; #[async_trait] pub(crate) trait StateReadExt: StateRead { #[instrument(skip_all)] - async fn get_block_hash_by_height(&self, height: u64) -> Result<[u8; 32]> { + async fn get_block_hash_by_height(&self, height: u64) -> Result { let Some(bytes) = self .nonverifiable_get_raw(keys::block_hash_by_height(height).as_bytes()) .await @@ -41,14 +42,14 @@ pub(crate) trait StateReadExt: StateRead { bail!("block hash not found for given height"); }; StoredValue::deserialize(&bytes) - .and_then(|value| storage::BlockHash::try_from(value).map(<[u8; 32]>::from)) + .and_then(|value| storage::BlockHash::try_from(value).map(block::Hash::from)) .wrap_err("invalid block hash bytes") } #[instrument(skip_all)] async fn get_sequencer_block_header_by_hash( &self, - hash: &[u8; 32], + hash: &block::Hash, ) -> Result { let Some(bytes) = self .nonverifiable_get_raw(keys::sequencer_block_header_by_hash(hash).as_bytes()) @@ -66,7 +67,7 @@ pub(crate) trait StateReadExt: StateRead { } #[instrument(skip_all)] - async fn get_rollup_ids_by_block_hash(&self, hash: &[u8; 32]) -> Result> { + async fn get_rollup_ids_by_block_hash(&self, hash: &block::Hash) -> Result> { let Some(bytes) = self .nonverifiable_get_raw(keys::rollup_ids_by_hash(hash).as_bytes()) .await @@ -183,7 +184,7 @@ pub(crate) trait StateWriteExt: StateWrite { #[instrument(skip_all)] async fn get_sequencer_block_by_hash( state: &S, - hash: &[u8; 32], + hash: &block::Hash, ) -> Result { let header = state .get_sequencer_block_header_by_hash(hash) @@ -228,7 +229,7 @@ async fn get_sequencer_block_by_hash( fn put_block_hash( state: &mut S, block_height: tendermint::block::Height, - block_hash: [u8; 32], + block_hash: block::Hash, ) -> Result<()> { let bytes = StoredValue::from(storage::BlockHash::from(&block_hash)) .serialize() diff --git a/crates/astria-sequencer/src/grpc/storage/values/block_hash.rs b/crates/astria-sequencer/src/grpc/storage/values/block_hash.rs index 4c772091ca..4921c6f33e 100644 --- a/crates/astria-sequencer/src/grpc/storage/values/block_hash.rs +++ b/crates/astria-sequencer/src/grpc/storage/values/block_hash.rs @@ -28,15 +28,15 @@ impl<'a> Debug for BlockHash<'a> { } } -impl<'a> From<&'a [u8; 32]> for BlockHash<'a> { - fn from(block_hash: &'a [u8; 32]) -> Self { +impl<'a> From<&'a astria_core::sequencerblock::v1::block::Hash> for BlockHash<'a> { + fn from(block_hash: &'a astria_core::sequencerblock::v1::block::Hash) -> Self { BlockHash(Cow::Borrowed(block_hash)) } } -impl<'a> From> for [u8; 32] { +impl<'a> From> for astria_core::sequencerblock::v1::block::Hash { fn from(block_hash: BlockHash<'a>) -> Self { - block_hash.0.into_owned() + Self::new(block_hash.0.into_owned()) } }