Add Gloas data column support (#8682)

Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>

Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com>
This commit is contained in:
Eitan Seri-Levi
2026-01-27 20:52:12 -08:00
committed by GitHub
parent 0f57fc9d8e
commit 9bec8df37a
44 changed files with 1507 additions and 680 deletions

View File

@@ -114,7 +114,7 @@ impl<E: EthSpec> BlockCache<E> {
pub fn put_data_column(&mut self, block_root: Hash256, data_column: Arc<DataColumnSidecar<E>>) {
self.data_column_cache
.get_or_insert_mut(block_root, Default::default)
.insert(data_column.index, data_column);
.insert(*data_column.index(), data_column);
}
pub fn put_data_column_custody_info(
&mut self,
@@ -969,7 +969,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
) {
ops.push(KeyValueStoreOp::PutKeyValue(
DBColumn::BeaconDataColumn,
get_data_column_key(block_root, &data_column.index),
get_data_column_key(block_root, data_column.index()),
data_column.as_ssz_bytes(),
));
}
@@ -1002,7 +1002,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
for data_column in data_columns {
self.blobs_db.put_bytes(
DBColumn::BeaconDataColumn,
&get_data_column_key(block_root, &data_column.index),
&get_data_column_key(block_root, data_column.index()),
&data_column.as_ssz_bytes(),
)?;
self.block_cache
@@ -1021,7 +1021,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
for data_column in data_columns {
ops.push(KeyValueStoreOp::PutKeyValue(
DBColumn::BeaconDataColumn,
get_data_column_key(block_root, &data_column.index),
get_data_column_key(block_root, data_column.index()),
data_column.as_ssz_bytes(),
));
}
@@ -1301,7 +1301,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
));
}
StoreOp::DeleteDataColumns(block_root, column_indices) => {
StoreOp::DeleteDataColumns(block_root, column_indices, _) => {
for index in column_indices {
let key = get_data_column_key(&block_root, &index);
key_value_batch
@@ -1415,10 +1415,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
}
true
}
StoreOp::DeleteDataColumns(block_root, indices) => {
StoreOp::DeleteDataColumns(block_root, indices, fork_name) => {
match indices
.iter()
.map(|index| self.get_data_column(block_root, index))
.map(|index| self.get_data_column(block_root, index, *fork_name))
.collect::<Result<Vec<_>, _>>()
{
Ok(data_column_sidecar_list_opt) => {
@@ -1471,14 +1471,24 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
let reverse_op = match op {
StoreOp::PutBlobs(block_root, _) => StoreOp::DeleteBlobs(*block_root),
StoreOp::PutDataColumns(block_root, data_columns) => {
let indices = data_columns.iter().map(|c| c.index).collect();
StoreOp::DeleteDataColumns(*block_root, indices)
let indices = data_columns.iter().map(|c| *c.index()).collect();
match data_columns.first() {
Some(column) => {
let slot = column.slot();
let fork_name = self.spec.fork_name_at_slot::<E>(slot);
StoreOp::DeleteDataColumns(*block_root, indices, fork_name)
}
// It shouldn't be possible to reach this case. We're reverting
// a `PutDataColumn` operation that attempted to write columns to the store.
None => return Err(HotColdDBError::Rollback.into()),
}
}
StoreOp::DeleteBlobs(_) => match blobs_to_delete.pop() {
Some((block_root, blobs)) => StoreOp::PutBlobs(block_root, blobs),
None => return Err(HotColdDBError::Rollback.into()),
},
StoreOp::DeleteDataColumns(_, _) => match data_columns_to_delete.pop() {
StoreOp::DeleteDataColumns(_, _, _) => match data_columns_to_delete.pop() {
Some((block_root, data_columns)) => {
StoreOp::PutDataColumns(block_root, data_columns)
}
@@ -1530,7 +1540,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
StoreOp::DeleteBlobs(_) => (),
StoreOp::DeleteDataColumns(_, _) => (),
StoreOp::DeleteDataColumns(_, _, _) => (),
StoreOp::DeleteExecutionPayload(_) => (),
@@ -2506,12 +2516,16 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
pub fn get_data_columns(
&self,
block_root: &Hash256,
fork_name: ForkName,
) -> Result<Option<DataColumnSidecarList<E>>, Error> {
let column_indices = self.get_data_column_keys(*block_root)?;
let columns: DataColumnSidecarList<E> = column_indices
.into_iter()
.filter_map(|col_index| self.get_data_column(block_root, &col_index).transpose())
.filter_map(|col_index| {
self.get_data_column(block_root, &col_index, fork_name)
.transpose()
})
.collect::<Result<_, _>>()?;
Ok((!columns.is_empty()).then_some(columns))
@@ -2585,6 +2599,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
&self,
block_root: &Hash256,
column_index: &ColumnIndex,
fork_name: ForkName,
) -> Result<Option<Arc<DataColumnSidecar<E>>>, Error> {
// Check the cache.
if let Some(data_column) = self
@@ -2601,7 +2616,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
&get_data_column_key(block_root, column_index),
)? {
Some(ref data_column_bytes) => {
let data_column = Arc::new(DataColumnSidecar::from_ssz_bytes(data_column_bytes)?);
let data_column = Arc::new(DataColumnSidecar::from_ssz_bytes_for_fork(
data_column_bytes,
fork_name,
)?);
self.block_cache.as_ref().inspect(|cache| {
cache
.lock()

View File

@@ -237,7 +237,7 @@ pub enum StoreOp<'a, E: EthSpec> {
PutStateSummary(Hash256, HotStateSummary),
DeleteBlock(Hash256),
DeleteBlobs(Hash256),
DeleteDataColumns(Hash256, Vec<ColumnIndex>),
DeleteDataColumns(Hash256, Vec<ColumnIndex>, ForkName),
DeleteState(Hash256, Option<Slot>),
DeleteExecutionPayload(Hash256),
DeleteSyncCommitteeBranch(Hash256),