Skip to content

Commit

Permalink
simplifies blockstore Column::index implementations
Browse files Browse the repository at this point in the history
The commits adds a small macro to simplify

    pub trait Column {
        fn index(key: &[u8]) -> Self::Index;
        // ...
    }

implementations.
  • Loading branch information
behzadnouri committed Jan 17, 2025
1 parent 878bcf1 commit d194fb4
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 53 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion ledger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ edition = { workspace = true }
assert_matches = { workspace = true }
bincode = { workspace = true }
bitflags = { workspace = true, features = ["serde"] }
byteorder = { workspace = true }
bzip2 = { workspace = true }
chrono = { workspace = true, features = ["default", "serde"] }
chrono-humanize = { workspace = true }
Expand Down
109 changes: 60 additions & 49 deletions ledger/src/blockstore_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use {
blockstore_options::{AccessType, BlockstoreOptions, LedgerColumnOptions},
},
bincode::{deserialize, Options as BincodeOptions},
byteorder::{BigEndian, ByteOrder},
log::*,
prost::Message,
rocksdb::{
Expand Down Expand Up @@ -103,6 +102,21 @@ const OPTIMISTIC_SLOTS_CF: &str = "optimistic_slots";
/// Column family for merkle roots
const MERKLE_ROOT_META_CF: &str = "merkle_root_meta";

macro_rules! concat_key_bytes {
($key:ident, $($range:expr => $bytes:expr),* $(,)?) => {{
let mut key = [0u8; std::mem::size_of::<Self::$key>()];
debug_assert_eq!(0 $(+$bytes.len())*, key.len());
$(key[$range].copy_from_slice($bytes);)*
key
}};
}

macro_rules! convert_key_bytes {
($k:ident, $($a:literal..$b:literal => $f:expr),* $(,)?) => {{
($($f(<[u8; $b-$a]>::try_from(&$k[$a..$b]).unwrap())),*)
}};
}

#[derive(Error, Debug)]
pub enum BlockstoreError {
#[error("shred for index exists")]
Expand Down Expand Up @@ -837,8 +851,8 @@ impl<T: SlotColumn> Column for T {
}

/// Converts a RocksDB key to its u64 Index.
fn index(key: &[u8]) -> u64 {
BigEndian::read_u64(&key[..8])
fn index(key: &[u8]) -> Self::Index {
convert_key_bytes!(key, 0..8 => Slot::from_be_bytes)
}

fn slot(index: Self::Index) -> Slot {
Expand Down Expand Up @@ -881,15 +895,6 @@ pub trait ColumnIndexDeprecation: Column {
}
}

macro_rules! concat_key_bytes {
($key:ident, $($range:expr => $bytes:expr),* $(,)?) => {{
let mut key = [0u8; std::mem::size_of::<Self::$key>()];
debug_assert_eq!(0 $(+$bytes.len())*, key.len());
$(key[$range].copy_from_slice($bytes);)*
key
}};
}

impl Column for columns::TransactionStatus {
type Index = (Signature, Slot);
type Key = [u8; SIGNATURE_BYTES + std::mem::size_of::<Slot>()];
Expand Down Expand Up @@ -940,19 +945,21 @@ impl ColumnIndexDeprecation for columns::TransactionStatus {
if key.len() != std::mem::size_of::<Self::DeprecatedKey>() {
return Err(IndexError::UnpackError);
}
let primary_index = BigEndian::read_u64(&key[0..8]);
let signature = Signature::try_from(&key[8..72]).unwrap();
let slot = BigEndian::read_u64(&key[72..80]);
Ok((primary_index, signature, slot))
Ok(convert_key_bytes!(key,
0..8 => u64::from_be_bytes, // primary index
8..72 => Signature::from,
72..80 => Slot::from_be_bytes,
))
}

fn try_current_index(key: &[u8]) -> std::result::Result<Self::Index, IndexError> {
if key.len() != Self::CURRENT_INDEX_LEN {
return Err(IndexError::UnpackError);
}
let signature = Signature::try_from(&key[0..64]).unwrap();
let slot = BigEndian::read_u64(&key[64..72]);
Ok((signature, slot))
Ok(convert_key_bytes!(key,
0..64 => Signature::from,
64..72 => Slot::from_be_bytes,
))
}

fn convert_index(deprecated_index: Self::DeprecatedIndex) -> Self::Index {
Expand Down Expand Up @@ -1016,22 +1023,24 @@ impl ColumnIndexDeprecation for columns::AddressSignatures {
if key.len() != std::mem::size_of::<Self::DeprecatedKey>() {
return Err(IndexError::UnpackError);
}
let primary_index = BigEndian::read_u64(&key[0..8]);
let pubkey = Pubkey::try_from(&key[8..40]).unwrap();
let slot = BigEndian::read_u64(&key[40..48]);
let signature = Signature::try_from(&key[48..112]).unwrap();
Ok((primary_index, pubkey, slot, signature))
Ok(convert_key_bytes!(key,
0..8 => u64::from_be_bytes, // primary index
8..40 => Pubkey::from,
40..48 => Slot::from_be_bytes,
48..112 => Signature::from,
))
}

fn try_current_index(key: &[u8]) -> std::result::Result<Self::Index, IndexError> {
if key.len() != Self::CURRENT_INDEX_LEN {
return Err(IndexError::UnpackError);
}
let pubkey = Pubkey::try_from(&key[0..32]).unwrap();
let slot = BigEndian::read_u64(&key[32..40]);
let transaction_index = BigEndian::read_u32(&key[40..44]);
let signature = Signature::try_from(&key[44..108]).unwrap();
Ok((pubkey, slot, transaction_index, signature))
Ok(convert_key_bytes!(key,
0..32 => Pubkey::from,
32..40 => Slot::from_be_bytes,
40..44 => u32::from_be_bytes, // transaction index
44..108 => Signature::from,
))
}

fn convert_index(deprecated_index: Self::DeprecatedIndex) -> Self::Index {
Expand Down Expand Up @@ -1085,9 +1094,10 @@ impl ColumnIndexDeprecation for columns::TransactionMemos {
if key.len() != Self::CURRENT_INDEX_LEN {
return Err(IndexError::UnpackError);
}
let signature = Signature::try_from(&key[0..64]).unwrap();
let slot = BigEndian::read_u64(&key[64..72]);
Ok((signature, slot))
Ok(convert_key_bytes!(key,
0..64 => Signature::from,
64..72 => Slot::from_be_bytes,
))
}

fn convert_index(deprecated_index: Self::DeprecatedIndex) -> Self::Index {
Expand All @@ -1104,8 +1114,8 @@ impl Column for columns::TransactionStatusIndex {
index.to_be_bytes()
}

fn index(key: &[u8]) -> u64 {
BigEndian::read_u64(&key[..8])
fn index(key: &[u8]) -> Self::Index {
convert_key_bytes!(key, 0..8 => u64::from_be_bytes)
}

fn slot(_index: Self::Index) -> Slot {
Expand Down Expand Up @@ -1165,7 +1175,7 @@ impl Column for columns::ProgramCosts {
}

fn index(key: &[u8]) -> Self::Index {
Pubkey::try_from(&key[..32]).unwrap()
convert_key_bytes!(key, 0..32 => Pubkey::from)
}

fn slot(_index: Self::Index) -> Slot {
Expand All @@ -1187,7 +1197,7 @@ impl Column for columns::ShredCode {
<columns::ShredData as Column>::key(index)
}

fn index(key: &[u8]) -> (Slot, u64) {
fn index(key: &[u8]) -> Self::Index {
columns::ShredData::index(key)
}

Expand Down Expand Up @@ -1215,10 +1225,11 @@ impl Column for columns::ShredData {
)
}

fn index(key: &[u8]) -> (Slot, u64) {
let slot = BigEndian::read_u64(&key[..8]);
let index = BigEndian::read_u64(&key[8..16]);
(slot, index)
fn index(key: &[u8]) -> Self::Index {
convert_key_bytes!(key,
0..8 => Slot::from_be_bytes,
8..16 => u64::from_be_bytes, // shred index
)
}

fn slot(index: Self::Index) -> Slot {
Expand Down Expand Up @@ -1323,11 +1334,11 @@ impl Column for columns::ErasureMeta {
)
}

fn index(key: &[u8]) -> (Slot, u64) {
let slot = BigEndian::read_u64(&key[..8]);
let set_index = BigEndian::read_u64(&key[8..]);

(slot, set_index)
fn index(key: &[u8]) -> Self::Index {
convert_key_bytes!(key,
0..8 => Slot::from_be_bytes,
8..16 => u64::from_be_bytes, // FEC set index
)
}

fn slot(index: Self::Index) -> Slot {
Expand Down Expand Up @@ -1366,10 +1377,10 @@ impl Column for columns::MerkleRootMeta {
}

fn index(key: &[u8]) -> Self::Index {
let slot = BigEndian::read_u64(&key[..8]);
let fec_set_index = BigEndian::read_u32(&key[8..]);

(slot, fec_set_index)
convert_key_bytes!(key,
0..8 => Slot::from_be_bytes,
8..12 => u32::from_be_bytes, // FEC set index
)
}

fn slot((slot, _fec_set_index): Self::Index) -> Slot {
Expand Down
1 change: 0 additions & 1 deletion programs/sbf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion svm/examples/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d194fb4

Please sign in to comment.