Update Blob Storage Structure (#4104)
* Initial Changes to Blob Storage * Add Arc to SignedBlobSidecar Definition
This commit is contained in:
parent
b40dceaae9
commit
d1e653cfdb
@ -959,35 +959,20 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
Ok(self.get_block(block_root).await?.map(Arc::new))
|
Ok(self.get_block(block_root).await?.map(Arc::new))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_block_and_blobs_checking_early_attester_cache(
|
pub async fn get_blobs_checking_early_attester_cache(
|
||||||
&self,
|
&self,
|
||||||
block_root: &Hash256,
|
block_root: &Hash256,
|
||||||
) -> Result<Option<SignedBeaconBlockAndBlobsSidecar<T::EthSpec>>, Error> {
|
) -> Result<Option<BlobSidecarList<T::EthSpec>>, Error> {
|
||||||
// If there is no data availability boundary, the Eip4844 fork is disabled.
|
// If there is no data availability boundary, the Eip4844 fork is disabled.
|
||||||
if let Some(finalized_data_availability_boundary) =
|
if let Some(finalized_data_availability_boundary) =
|
||||||
self.finalized_data_availability_boundary()
|
self.finalized_data_availability_boundary()
|
||||||
{
|
{
|
||||||
// Only use the attester cache if we can find both the block and blob
|
self.early_attester_cache
|
||||||
if let (Some(block), Some(blobs)) = (
|
.get_blobs(*block_root)
|
||||||
self.early_attester_cache.get_block(*block_root),
|
.map_or_else(
|
||||||
self.early_attester_cache.get_blobs(*block_root),
|
|| self.get_blobs(block_root, finalized_data_availability_boundary),
|
||||||
) {
|
|blobs| Ok(Some(blobs)),
|
||||||
Ok(Some(SignedBeaconBlockAndBlobsSidecar {
|
)
|
||||||
beacon_block: block,
|
|
||||||
blobs_sidecar: blobs,
|
|
||||||
}))
|
|
||||||
// Attempt to get the block and blobs from the database
|
|
||||||
} else if let Some(block) = self.get_block(block_root).await?.map(Arc::new) {
|
|
||||||
let blobs = self
|
|
||||||
.get_blobs(block_root, finalized_data_availability_boundary)?
|
|
||||||
.map(Arc::new);
|
|
||||||
Ok(blobs.map(|blobs| SignedBeaconBlockAndBlobsSidecar {
|
|
||||||
beacon_block: block,
|
|
||||||
blobs_sidecar: blobs,
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -1057,23 +1042,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
.map(Some)
|
.map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(jimmy): temporary method added to unblock API work. This method will be replaced by
|
|
||||||
// the `get_blobs` method below once the new blob sidecar structure (`BlobSidecarList`) is
|
|
||||||
// implemented in that method.
|
|
||||||
#[allow(clippy::type_complexity)] // FIXME: this will be fixed by the `BlobSidecarList` alias in Sean's PR
|
|
||||||
pub fn get_blob_sidecar_list(
|
|
||||||
&self,
|
|
||||||
_block_root: &Hash256,
|
|
||||||
_data_availability_boundary: Epoch,
|
|
||||||
) -> Result<
|
|
||||||
Option<
|
|
||||||
VariableList<Arc<BlobSidecar<T::EthSpec>>, <T::EthSpec as EthSpec>::MaxBlobsPerBlock>,
|
|
||||||
>,
|
|
||||||
Error,
|
|
||||||
> {
|
|
||||||
unimplemented!("update to use the updated `get_blobs` method instead once this PR is merged: https://github.com/sigp/lighthouse/pull/4104")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the blobs at the given root, if any.
|
/// Returns the blobs at the given root, if any.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(None)` if the blobs and associated block are not found.
|
/// Returns `Ok(None)` if the blobs and associated block are not found.
|
||||||
@ -1091,9 +1059,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
&self,
|
&self,
|
||||||
block_root: &Hash256,
|
block_root: &Hash256,
|
||||||
data_availability_boundary: Epoch,
|
data_availability_boundary: Epoch,
|
||||||
) -> Result<Option<BlobsSidecar<T::EthSpec>>, Error> {
|
) -> Result<Option<BlobSidecarList<T::EthSpec>>, Error> {
|
||||||
match self.store.get_blobs(block_root)? {
|
match self.store.get_blobs(block_root)? {
|
||||||
Some(blobs) => Ok(Some(blobs)),
|
Some(blob_sidecar_list) => Ok(Some(blob_sidecar_list)),
|
||||||
None => {
|
None => {
|
||||||
// Check for the corresponding block to understand whether we *should* have blobs.
|
// Check for the corresponding block to understand whether we *should* have blobs.
|
||||||
self.get_blinded_block(block_root)?
|
self.get_blinded_block(block_root)?
|
||||||
@ -1106,7 +1074,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
Err(_) => return Err(Error::NoKzgCommitmentsFieldOnBlock),
|
Err(_) => return Err(Error::NoKzgCommitmentsFieldOnBlock),
|
||||||
};
|
};
|
||||||
if expected_kzg_commitments.is_empty() {
|
if expected_kzg_commitments.is_empty() {
|
||||||
Ok(BlobsSidecar::empty_from_parts(*block_root, block.slot()))
|
// TODO (mark): verify this
|
||||||
|
Ok(BlobSidecarList::empty())
|
||||||
} else if data_availability_boundary <= block.epoch() {
|
} else if data_availability_boundary <= block.epoch() {
|
||||||
// We should have blobs for all blocks younger than the boundary.
|
// We should have blobs for all blocks younger than the boundary.
|
||||||
Err(Error::BlobsUnavailable)
|
Err(Error::BlobsUnavailable)
|
||||||
@ -3052,7 +3021,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
// margin, or younger (of higher epoch number).
|
// margin, or younger (of higher epoch number).
|
||||||
if block_epoch >= import_boundary {
|
if block_epoch >= import_boundary {
|
||||||
if let Some(blobs) = blobs {
|
if let Some(blobs) = blobs {
|
||||||
if !blobs.blobs.is_empty() {
|
if !blobs.is_empty() {
|
||||||
//FIXME(sean) using this for debugging for now
|
//FIXME(sean) using this for debugging for now
|
||||||
info!(
|
info!(
|
||||||
self.log, "Writing blobs to store";
|
self.log, "Writing blobs to store";
|
||||||
@ -4814,7 +4783,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
)
|
)
|
||||||
.map_err(BlockProductionError::KzgError)?;
|
.map_err(BlockProductionError::KzgError)?;
|
||||||
|
|
||||||
let blob_sidecars = VariableList::from(
|
let blob_sidecars = BlobSidecarList::from(
|
||||||
blobs
|
blobs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@ -4827,7 +4796,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
.get(blob_index)
|
.get(blob_index)
|
||||||
.expect("KZG proof should exist for blob");
|
.expect("KZG proof should exist for blob");
|
||||||
|
|
||||||
Ok(BlobSidecar {
|
Ok(Arc::new(BlobSidecar {
|
||||||
block_root: beacon_block_root,
|
block_root: beacon_block_root,
|
||||||
index: blob_index as u64,
|
index: blob_index as u64,
|
||||||
slot,
|
slot,
|
||||||
@ -4836,9 +4805,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
blob,
|
blob,
|
||||||
kzg_commitment: *kzg_commitment,
|
kzg_commitment: *kzg_commitment,
|
||||||
kzg_proof: *kzg_proof,
|
kzg_proof: *kzg_proof,
|
||||||
})
|
}))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<BlobSidecar<T::EthSpec>>, BlockProductionError>>()?,
|
.collect::<Result<Vec<_>, BlockProductionError>>()?,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.blob_cache.put(beacon_block_root, blob_sidecars);
|
self.blob_cache.put(beacon_block_root, blob_sidecars);
|
||||||
|
@ -21,7 +21,7 @@ pub struct CacheItem<E: EthSpec> {
|
|||||||
* Values used to make the block available.
|
* Values used to make the block available.
|
||||||
*/
|
*/
|
||||||
block: Arc<SignedBeaconBlock<E>>,
|
block: Arc<SignedBeaconBlock<E>>,
|
||||||
blobs: Option<Arc<BlobsSidecar<E>>>,
|
blobs: Option<BlobSidecarList<E>>,
|
||||||
proto_block: ProtoBlock,
|
proto_block: ProtoBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ impl<E: EthSpec> EarlyAttesterCache<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the blobs, if `block_root` matches the cached item.
|
/// Returns the blobs, if `block_root` matches the cached item.
|
||||||
pub fn get_blobs(&self, block_root: Hash256) -> Option<Arc<BlobsSidecar<E>>> {
|
pub fn get_blobs(&self, block_root: Hash256) -> Option<BlobSidecarList<E>> {
|
||||||
self.item
|
self.item
|
||||||
.read()
|
.read()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::{state_id::checkpoint_slot_and_execution_optimistic, ExecutionOptimistic};
|
use crate::{state_id::checkpoint_slot_and_execution_optimistic, ExecutionOptimistic};
|
||||||
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes, WhenSlotSkipped};
|
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes, WhenSlotSkipped};
|
||||||
use eth2::types::{BlockId as CoreBlockId, VariableList};
|
use eth2::types::BlockId as CoreBlockId;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{BlobSidecar, EthSpec, Hash256, SignedBeaconBlock, SignedBlindedBeaconBlock, Slot};
|
use types::{BlobSidecarList, Hash256, SignedBeaconBlock, SignedBlindedBeaconBlock, Slot};
|
||||||
|
|
||||||
/// Wraps `eth2::types::BlockId` and provides a simple way to obtain a block or root for a given
|
/// Wraps `eth2::types::BlockId` and provides a simple way to obtain a block or root for a given
|
||||||
/// `BlockId`.
|
/// `BlockId`.
|
||||||
@ -216,16 +216,13 @@ impl BlockId {
|
|||||||
pub async fn blob_sidecar_list<T: BeaconChainTypes>(
|
pub async fn blob_sidecar_list<T: BeaconChainTypes>(
|
||||||
&self,
|
&self,
|
||||||
chain: &BeaconChain<T>,
|
chain: &BeaconChain<T>,
|
||||||
) -> Result<
|
) -> Result<BlobSidecarList<T::EthSpec>, warp::Rejection> {
|
||||||
VariableList<Arc<BlobSidecar<T::EthSpec>>, <T::EthSpec as EthSpec>::MaxBlobsPerBlock>,
|
|
||||||
warp::Rejection,
|
|
||||||
> {
|
|
||||||
let root = self.root(chain)?.0;
|
let root = self.root(chain)?.0;
|
||||||
let Some(data_availability_boundary) = chain.data_availability_boundary() else {
|
let Some(data_availability_boundary) = chain.data_availability_boundary() else {
|
||||||
return Err(warp_utils::reject::custom_not_found("Deneb fork disabled".into()));
|
return Err(warp_utils::reject::custom_not_found("Deneb fork disabled".into()));
|
||||||
};
|
};
|
||||||
match chain.get_blob_sidecar_list(&root, data_availability_boundary) {
|
match chain.get_blobs(&root, data_availability_boundary) {
|
||||||
Ok(Some(blobs)) => Ok(blobs),
|
Ok(Some(blob_sidecar_list)) => Ok(blob_sidecar_list),
|
||||||
Ok(None) => Err(warp_utils::reject::custom_not_found(format!(
|
Ok(None) => Err(warp_utils::reject::custom_not_found(format!(
|
||||||
"No blobs with block root {} found in the store",
|
"No blobs with block root {} found in the store",
|
||||||
root
|
root
|
||||||
|
@ -12,6 +12,7 @@ use lighthouse_network::rpc::*;
|
|||||||
use lighthouse_network::{PeerId, PeerRequestId, ReportSource, Response, SyncInfo};
|
use lighthouse_network::{PeerId, PeerRequestId, ReportSource, Response, SyncInfo};
|
||||||
use slog::{debug, error, warn};
|
use slog::{debug, error, warn};
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
|
use std::collections::{hash_map::Entry, HashMap};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use task_executor::TaskExecutor;
|
use task_executor::TaskExecutor;
|
||||||
use types::blob_sidecar::BlobIdentifier;
|
use types::blob_sidecar::BlobIdentifier;
|
||||||
@ -225,42 +226,34 @@ impl<T: BeaconChainTypes> Worker<T> {
|
|||||||
executor.spawn(
|
executor.spawn(
|
||||||
async move {
|
async move {
|
||||||
let requested_blobs = request.blob_ids.len();
|
let requested_blobs = request.blob_ids.len();
|
||||||
let mut send_block_count = 0;
|
let mut send_blob_count = 0;
|
||||||
let mut send_response = true;
|
let mut send_response = true;
|
||||||
|
|
||||||
|
let mut blob_list_results = HashMap::new();
|
||||||
for BlobIdentifier{ block_root: root, index } in request.blob_ids.into_iter() {
|
for BlobIdentifier{ block_root: root, index } in request.blob_ids.into_iter() {
|
||||||
match self
|
let blob_list_result = match blob_list_results.entry(root) {
|
||||||
.chain
|
Entry::Vacant(entry) => {
|
||||||
.get_block_and_blobs_checking_early_attester_cache(&root)
|
entry.insert(self
|
||||||
.await
|
.chain
|
||||||
{
|
.get_blobs_checking_early_attester_cache(&root)
|
||||||
Ok(Some(block_and_blobs)) => {
|
.await)
|
||||||
//
|
}
|
||||||
// TODO: HORRIBLE NSFW CODE AHEAD
|
Entry::Occupied(entry) => {
|
||||||
//
|
entry.into_mut()
|
||||||
let types::SignedBeaconBlockAndBlobsSidecar {beacon_block, blobs_sidecar} = block_and_blobs;
|
}
|
||||||
let types::BlobsSidecar{ beacon_block_root, beacon_block_slot, blobs: blob_bundle, kzg_aggregated_proof }: types::BlobsSidecar<_> = blobs_sidecar.as_ref().clone();
|
};
|
||||||
// TODO: this should be unreachable after this is addressed seriously,
|
|
||||||
// so for now let's be ok with a panic in the expect.
|
match blob_list_result.as_ref() {
|
||||||
let block = beacon_block.message_eip4844().expect("We fucked up the block blob stuff");
|
Ok(Some(blobs_sidecar_list)) => {
|
||||||
// Intentionally not accessing the list directly
|
for blob_sidecar in blobs_sidecar_list.iter() {
|
||||||
for (known_index, blob) in blob_bundle.into_iter().enumerate() {
|
if blob_sidecar.index == index {
|
||||||
if (known_index as u64) == index {
|
|
||||||
let blob_sidecar = types::BlobSidecar{
|
|
||||||
block_root: beacon_block_root,
|
|
||||||
index,
|
|
||||||
slot: beacon_block_slot,
|
|
||||||
block_parent_root: block.parent_root,
|
|
||||||
proposer_index: block.proposer_index,
|
|
||||||
blob,
|
|
||||||
kzg_commitment: block.body.blob_kzg_commitments[known_index], // TODO: needs to be stored in a more logical way so that this won't panic.
|
|
||||||
kzg_proof: kzg_aggregated_proof // TODO: yeah
|
|
||||||
};
|
|
||||||
self.send_response(
|
self.send_response(
|
||||||
peer_id,
|
peer_id,
|
||||||
Response::BlobsByRoot(Some(Arc::new(blob_sidecar))),
|
Response::BlobsByRoot(Some(blob_sidecar.clone())),
|
||||||
request_id,
|
request_id,
|
||||||
);
|
);
|
||||||
send_block_count += 1;
|
send_blob_count += 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,7 +348,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
|||||||
"Received BlobsByRoot Request";
|
"Received BlobsByRoot Request";
|
||||||
"peer" => %peer_id,
|
"peer" => %peer_id,
|
||||||
"requested" => requested_blobs,
|
"requested" => requested_blobs,
|
||||||
"returned" => send_block_count
|
"returned" => send_blob_count
|
||||||
);
|
);
|
||||||
|
|
||||||
// send stream termination
|
// send stream termination
|
||||||
@ -837,31 +830,12 @@ impl<T: BeaconChainTypes> Worker<T> {
|
|||||||
|
|
||||||
for root in block_roots {
|
for root in block_roots {
|
||||||
match self.chain.get_blobs(&root, data_availability_boundary) {
|
match self.chain.get_blobs(&root, data_availability_boundary) {
|
||||||
Ok(Some(blobs)) => {
|
Ok(Some(blob_sidecar_list)) => {
|
||||||
// TODO: more GROSS code ahead. Reader beware
|
for blob_sidecar in blob_sidecar_list.iter() {
|
||||||
let types::BlobsSidecar {
|
|
||||||
beacon_block_root,
|
|
||||||
beacon_block_slot,
|
|
||||||
blobs: blob_bundle,
|
|
||||||
kzg_aggregated_proof: _,
|
|
||||||
}: types::BlobsSidecar<_> = blobs;
|
|
||||||
|
|
||||||
for (blob_index, blob) in blob_bundle.into_iter().enumerate() {
|
|
||||||
let blob_sidecar = types::BlobSidecar {
|
|
||||||
block_root: beacon_block_root,
|
|
||||||
index: blob_index as u64,
|
|
||||||
slot: beacon_block_slot,
|
|
||||||
block_parent_root: Hash256::zero(),
|
|
||||||
proposer_index: 0,
|
|
||||||
blob,
|
|
||||||
kzg_commitment: types::KzgCommitment::default(),
|
|
||||||
kzg_proof: types::KzgProof::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
blobs_sent += 1;
|
blobs_sent += 1;
|
||||||
self.send_network_message(NetworkMessage::SendResponse {
|
self.send_network_message(NetworkMessage::SendResponse {
|
||||||
peer_id,
|
peer_id,
|
||||||
response: Response::BlobsByRange(Some(Arc::new(blob_sidecar))),
|
response: Response::BlobsByRange(Some(blob_sidecar.clone())),
|
||||||
id: request_id,
|
id: request_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ pub struct HotColdDB<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> {
|
|||||||
/// The hot database also contains all blocks.
|
/// The hot database also contains all blocks.
|
||||||
pub hot_db: Hot,
|
pub hot_db: Hot,
|
||||||
/// LRU cache of deserialized blobs. Updated whenever a blob is loaded.
|
/// LRU cache of deserialized blobs. Updated whenever a blob is loaded.
|
||||||
blob_cache: Mutex<LruCache<Hash256, BlobsSidecar<E>>>,
|
blob_cache: Mutex<LruCache<Hash256, BlobSidecarList<E>>>,
|
||||||
/// LRU cache of deserialized blocks. Updated whenever a block is loaded.
|
/// LRU cache of deserialized blocks. Updated whenever a block is loaded.
|
||||||
block_cache: Mutex<LruCache<Hash256, SignedBeaconBlock<E>>>,
|
block_cache: Mutex<LruCache<Hash256, SignedBeaconBlock<E>>>,
|
||||||
/// Chain spec.
|
/// Chain spec.
|
||||||
@ -568,7 +568,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
blobs_db.key_delete(DBColumn::BeaconBlob.into(), block_root.as_bytes())
|
blobs_db.key_delete(DBColumn::BeaconBlob.into(), block_root.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put_blobs(&self, block_root: &Hash256, blobs: BlobsSidecar<E>) -> Result<(), Error> {
|
pub fn put_blobs(&self, block_root: &Hash256, blobs: BlobSidecarList<E>) -> Result<(), Error> {
|
||||||
let blobs_db = self.blobs_db.as_ref().unwrap_or(&self.cold_db);
|
let blobs_db = self.blobs_db.as_ref().unwrap_or(&self.cold_db);
|
||||||
blobs_db.put_bytes(
|
blobs_db.put_bytes(
|
||||||
DBColumn::BeaconBlob.into(),
|
DBColumn::BeaconBlob.into(),
|
||||||
@ -582,7 +582,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
pub fn blobs_as_kv_store_ops(
|
pub fn blobs_as_kv_store_ops(
|
||||||
&self,
|
&self,
|
||||||
key: &Hash256,
|
key: &Hash256,
|
||||||
blobs: &BlobsSidecar<E>,
|
blobs: BlobSidecarList<E>,
|
||||||
ops: &mut Vec<KeyValueStoreOp>,
|
ops: &mut Vec<KeyValueStoreOp>,
|
||||||
) {
|
) {
|
||||||
let db_key = get_key_for_col(DBColumn::BeaconBlob.into(), key.as_bytes());
|
let db_key = get_key_for_col(DBColumn::BeaconBlob.into(), key.as_bytes());
|
||||||
@ -817,7 +817,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
}
|
}
|
||||||
|
|
||||||
StoreOp::PutBlobs(block_root, blobs) => {
|
StoreOp::PutBlobs(block_root, blobs) => {
|
||||||
self.blobs_as_kv_store_ops(&block_root, &blobs, &mut key_value_batch);
|
self.blobs_as_kv_store_ops(&block_root, blobs, &mut key_value_batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
StoreOp::PutStateSummary(state_root, summary) => {
|
StoreOp::PutStateSummary(state_root, summary) => {
|
||||||
@ -885,8 +885,8 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
StoreOp::PutBlobs(_, _) => true,
|
StoreOp::PutBlobs(_, _) => true,
|
||||||
StoreOp::DeleteBlobs(block_root) => {
|
StoreOp::DeleteBlobs(block_root) => {
|
||||||
match self.get_blobs(block_root) {
|
match self.get_blobs(block_root) {
|
||||||
Ok(Some(blobs_sidecar)) => {
|
Ok(Some(blobs_sidecar_list)) => {
|
||||||
blobs_to_delete.push(blobs_sidecar);
|
blobs_to_delete.push((*block_root, blobs_sidecar_list));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!(
|
error!(
|
||||||
@ -926,7 +926,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
let reverse_op = match op {
|
let reverse_op = match op {
|
||||||
StoreOp::PutBlobs(block_root, _) => StoreOp::DeleteBlobs(*block_root),
|
StoreOp::PutBlobs(block_root, _) => StoreOp::DeleteBlobs(*block_root),
|
||||||
StoreOp::DeleteBlobs(_) => match blobs_to_delete.pop() {
|
StoreOp::DeleteBlobs(_) => match blobs_to_delete.pop() {
|
||||||
Some(blobs) => StoreOp::PutBlobs(blobs.beacon_block_root, Arc::new(blobs)),
|
Some((block_root, blobs)) => StoreOp::PutBlobs(block_root, blobs),
|
||||||
None => return Err(HotColdDBError::Rollback.into()),
|
None => return Err(HotColdDBError::Rollback.into()),
|
||||||
},
|
},
|
||||||
_ => return Err(HotColdDBError::Rollback.into()),
|
_ => return Err(HotColdDBError::Rollback.into()),
|
||||||
@ -972,7 +972,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
for op in blob_cache_ops {
|
for op in blob_cache_ops {
|
||||||
match op {
|
match op {
|
||||||
StoreOp::PutBlobs(block_root, blobs) => {
|
StoreOp::PutBlobs(block_root, blobs) => {
|
||||||
guard_blob.put(block_root, (*blobs).clone());
|
guard_blob.put(block_root, blobs);
|
||||||
}
|
}
|
||||||
|
|
||||||
StoreOp::DeleteBlobs(block_root) => {
|
StoreOp::DeleteBlobs(block_root) => {
|
||||||
@ -1320,12 +1320,12 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch a blobs sidecar from the store.
|
/// Fetch a blobs sidecar from the store.
|
||||||
pub fn get_blobs(&self, block_root: &Hash256) -> Result<Option<BlobsSidecar<E>>, Error> {
|
pub fn get_blobs(&self, block_root: &Hash256) -> Result<Option<BlobSidecarList<E>>, Error> {
|
||||||
let blobs_db = self.blobs_db.as_ref().unwrap_or(&self.cold_db);
|
let blobs_db = self.blobs_db.as_ref().unwrap_or(&self.cold_db);
|
||||||
|
|
||||||
match blobs_db.get_bytes(DBColumn::BeaconBlob.into(), block_root.as_bytes())? {
|
match blobs_db.get_bytes(DBColumn::BeaconBlob.into(), block_root.as_bytes())? {
|
||||||
Some(ref blobs_bytes) => {
|
Some(ref blobs_bytes) => {
|
||||||
let blobs = BlobsSidecar::from_ssz_bytes(blobs_bytes)?;
|
let blobs = BlobSidecarList::from_ssz_bytes(blobs_bytes)?;
|
||||||
// FIXME(sean) I was attempting to use a blob cache here but was getting deadlocks,
|
// FIXME(sean) I was attempting to use a blob cache here but was getting deadlocks,
|
||||||
// may want to attempt to use one again
|
// may want to attempt to use one again
|
||||||
self.blob_cache.lock().put(*block_root, blobs.clone());
|
self.blob_cache.lock().put(*block_root, blobs.clone());
|
||||||
|
@ -159,7 +159,8 @@ pub trait ItemStore<E: EthSpec>: KeyValueStore<E> + Sync + Send + Sized + 'stati
|
|||||||
pub enum StoreOp<'a, E: EthSpec> {
|
pub enum StoreOp<'a, E: EthSpec> {
|
||||||
PutBlock(Hash256, Arc<SignedBeaconBlock<E>>),
|
PutBlock(Hash256, Arc<SignedBeaconBlock<E>>),
|
||||||
PutState(Hash256, &'a BeaconState<E>),
|
PutState(Hash256, &'a BeaconState<E>),
|
||||||
PutBlobs(Hash256, Arc<BlobsSidecar<E>>),
|
// TODO (mark): space can be optimized here by de-duplicating data
|
||||||
|
PutBlobs(Hash256, BlobSidecarList<E>),
|
||||||
PutOrphanedBlobsKey(Hash256),
|
PutOrphanedBlobsKey(Hash256),
|
||||||
PutStateSummary(Hash256, HotStateSummary),
|
PutStateSummary(Hash256, HotStateSummary),
|
||||||
PutStateTemporaryFlag(Hash256),
|
PutStateTemporaryFlag(Hash256),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use ethereum_types::{H160, H256, U128, U256};
|
use ethereum_types::{H160, H256, U128, U256};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn int_to_hash256(int: u64) -> Hash256 {
|
fn int_to_hash256(int: u64) -> Hash256 {
|
||||||
let mut bytes = [0; HASHSIZE];
|
let mut bytes = [0; HASHSIZE];
|
||||||
@ -186,6 +187,24 @@ impl TreeHash for H256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: TreeHash> TreeHash for Arc<T> {
|
||||||
|
fn tree_hash_type() -> TreeHashType {
|
||||||
|
T::tree_hash_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packed_encoding(&self) -> PackedEncoding {
|
||||||
|
self.as_ref().tree_hash_packed_encoding()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_packing_factor() -> usize {
|
||||||
|
T::tree_hash_packing_factor()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tree_hash_root(&self) -> Hash256 {
|
||||||
|
self.as_ref().tree_hash_root()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -6,6 +6,7 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use ssz_types::VariableList;
|
use ssz_types::VariableList;
|
||||||
|
use std::sync::Arc;
|
||||||
use test_random_derive::TestRandom;
|
use test_random_derive::TestRandom;
|
||||||
use tree_hash_derive::TreeHash;
|
use tree_hash_derive::TreeHash;
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ pub struct BlobSidecar<T: EthSpec> {
|
|||||||
pub kzg_proof: KzgProof,
|
pub kzg_proof: KzgProof,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BlobSidecarList<T> = VariableList<BlobSidecar<T>, <T as EthSpec>::MaxBlobsPerBlock>;
|
pub type BlobSidecarList<T> = VariableList<Arc<BlobSidecar<T>>, <T as EthSpec>::MaxBlobsPerBlock>;
|
||||||
|
|
||||||
impl<T: EthSpec> SignedRoot for BlobSidecar<T> {}
|
impl<T: EthSpec> SignedRoot for BlobSidecar<T> {}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ use derivative::Derivative;
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use ssz_types::VariableList;
|
use ssz_types::VariableList;
|
||||||
|
use std::sync::Arc;
|
||||||
use test_random_derive::TestRandom;
|
use test_random_derive::TestRandom;
|
||||||
use tree_hash_derive::TreeHash;
|
use tree_hash_derive::TreeHash;
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
#[arbitrary(bound = "T: EthSpec")]
|
#[arbitrary(bound = "T: EthSpec")]
|
||||||
#[derivative(Hash(bound = "T: EthSpec"))]
|
#[derivative(Hash(bound = "T: EthSpec"))]
|
||||||
pub struct SignedBlobSidecar<T: EthSpec> {
|
pub struct SignedBlobSidecar<T: EthSpec> {
|
||||||
pub message: BlobSidecar<T>,
|
pub message: Arc<BlobSidecar<T>>,
|
||||||
pub signature: Signature,
|
pub signature: Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user