From 6f8b9c95f0825bd41998a9b2b252494d66f974af Mon Sep 17 00:00:00 2001 From: behzad nouri Date: Sun, 12 Jan 2025 18:46:06 -0600 Subject: [PATCH] reworks blockstore ColumnIndexDeprecation trait Similar to https://github.com/anza-xyz/agave/pull/4416 in order to add more type-safety and avoid unnecessary heap allocations: https://github.com/anza-xyz/agave/blob/8a0c9b461/ledger/src/blockstore_db.rs#L932 https://github.com/anza-xyz/agave/blob/8a0c9b461/ledger/src/blockstore_db.rs#L1005 https://github.com/anza-xyz/agave/blob/8a0c9b461/ledger/src/blockstore_db.rs#L1075 the commit removes const DEPRECATED_INDEX_LEN: usize; from ColumnIndexDeprecation trait and instead adds: type DeprecatedKey: AsRef<[u8]>; --- ledger/src/blockstore_db.rs | 72 +++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/ledger/src/blockstore_db.rs b/ledger/src/blockstore_db.rs index dc0b5f078bceb3..10e9f189bfd6ad 100644 --- a/ledger/src/blockstore_db.rs +++ b/ledger/src/blockstore_db.rs @@ -857,11 +857,11 @@ pub enum IndexError { /// Helper trait to transition primary indexes out from the columns that are using them. pub trait ColumnIndexDeprecation: Column { - const DEPRECATED_INDEX_LEN: usize; const CURRENT_INDEX_LEN: usize; type DeprecatedIndex; + type DeprecatedKey: AsRef<[u8]>; - fn deprecated_key(index: Self::DeprecatedIndex) -> Vec; + fn deprecated_key(index: Self::DeprecatedIndex) -> Self::DeprecatedKey; fn try_deprecated_index(key: &[u8]) -> std::result::Result; fn try_current_index(key: &[u8]) -> std::result::Result; @@ -881,15 +881,27 @@ pub trait ColumnIndexDeprecation: Column { } } -macro_rules! concat_key_bytes { - ($($range:expr => $bytes:expr),* $(,)?) => {{ - let mut key = [0u8; std::mem::size_of::()]; +macro_rules! concat_bytes { + ($key:ty, $($range:expr => $bytes:expr),* $(,)?) => {{ + let mut key = [0u8; std::mem::size_of::<$key>()]; debug_assert_eq!(0 $(+$bytes.len())*, key.len()); $(key[$range].copy_from_slice($bytes);)* key }}; } +macro_rules! concat_key_bytes { + ($($range:expr => $bytes:expr),* $(,)?) => { + concat_bytes!(Self::Key, $($range => $bytes),*) + }; +} + +macro_rules! concat_deprecated_key_bytes { + ($($range:expr => $bytes:expr),* $(,)?) => { + concat_bytes!(Self::DeprecatedKey, $($range => $bytes),*) + }; +} + impl Column for columns::TransactionStatus { type Index = (Signature, Slot); type Key = [u8; SIGNATURE_BYTES + std::mem::size_of::()]; @@ -924,20 +936,20 @@ impl ProtobufColumn for columns::TransactionStatus { } impl ColumnIndexDeprecation for columns::TransactionStatus { - const DEPRECATED_INDEX_LEN: usize = 80; const CURRENT_INDEX_LEN: usize = 72; type DeprecatedIndex = (u64, Signature, Slot); + type DeprecatedKey = [u8; 80]; - fn deprecated_key((index, signature, slot): Self::DeprecatedIndex) -> Vec { - let mut key = vec![0; Self::DEPRECATED_INDEX_LEN]; - BigEndian::write_u64(&mut key[0..8], index); - key[8..72].copy_from_slice(&signature.as_ref()[0..64]); - BigEndian::write_u64(&mut key[72..80], slot); - key + fn deprecated_key((index, signature, slot): Self::DeprecatedIndex) -> Self::DeprecatedKey { + concat_deprecated_key_bytes!( + ..8 => &index.to_be_bytes(), + 8..72 => signature.as_ref(), + 72.. => &slot.to_be_bytes(), + ) } fn try_deprecated_index(key: &[u8]) -> std::result::Result { - if key.len() != Self::DEPRECATED_INDEX_LEN { + if key.len() != std::mem::size_of::() { return Err(IndexError::UnpackError); } let primary_index = BigEndian::read_u64(&key[0..8]); @@ -997,21 +1009,23 @@ impl ColumnName for columns::AddressSignatures { } impl ColumnIndexDeprecation for columns::AddressSignatures { - const DEPRECATED_INDEX_LEN: usize = 112; const CURRENT_INDEX_LEN: usize = 108; type DeprecatedIndex = (u64, Pubkey, Slot, Signature); - - fn deprecated_key((primary_index, pubkey, slot, signature): Self::DeprecatedIndex) -> Vec { - let mut key = vec![0; Self::DEPRECATED_INDEX_LEN]; - BigEndian::write_u64(&mut key[0..8], primary_index); - key[8..40].clone_from_slice(&pubkey.as_ref()[0..32]); - BigEndian::write_u64(&mut key[40..48], slot); - key[48..112].clone_from_slice(&signature.as_ref()[0..64]); - key + type DeprecatedKey = [u8; 112]; + + fn deprecated_key( + (primary_index, pubkey, slot, signature): Self::DeprecatedIndex, + ) -> Self::DeprecatedKey { + concat_deprecated_key_bytes!( + ..8 => &primary_index.to_be_bytes(), + 8..40 => pubkey.as_ref(), + 40..48 => &slot.to_be_bytes(), + 48..112 => signature.as_ref(), + ) } fn try_deprecated_index(key: &[u8]) -> std::result::Result { - if key.len() != Self::DEPRECATED_INDEX_LEN { + if key.len() != std::mem::size_of::() { return Err(IndexError::UnpackError); } let primary_index = BigEndian::read_u64(&key[0..8]); @@ -1067,14 +1081,12 @@ impl ColumnName for columns::TransactionMemos { } impl ColumnIndexDeprecation for columns::TransactionMemos { - const DEPRECATED_INDEX_LEN: usize = 64; const CURRENT_INDEX_LEN: usize = 72; type DeprecatedIndex = Signature; + type DeprecatedKey = [u8; 64]; - fn deprecated_key(signature: Self::DeprecatedIndex) -> Vec { - let mut key = vec![0; Self::DEPRECATED_INDEX_LEN]; - key[0..64].copy_from_slice(&signature.as_ref()[0..64]); - key + fn deprecated_key(signature: Self::DeprecatedIndex) -> Self::DeprecatedKey { + <[u8; SIGNATURE_BYTES]>::from(signature) } fn try_deprecated_index(key: &[u8]) -> std::result::Result { @@ -1885,13 +1897,13 @@ where &self, iterator_mode: IteratorMode, ) -> Result)> + '_> { - let start_key; + let start_key: ::DeprecatedKey; let iterator_mode = match iterator_mode { IteratorMode::Start => RocksIteratorMode::Start, IteratorMode::End => RocksIteratorMode::End, IteratorMode::From(start_from, direction) => { start_key = C::deprecated_key(start_from); - RocksIteratorMode::From(&start_key, direction) + RocksIteratorMode::From(start_key.as_ref(), direction) } };