block wrapper refactor initial commit

This commit is contained in:
realbigsean
2023-01-20 11:50:16 -05:00
parent e046657b4f
commit 3cb8fb7973
9 changed files with 335 additions and 328 deletions

View File

@@ -35,8 +35,10 @@ impl From<SignedBeaconBlockHash> for Hash256 {
}
}
#[derive(Debug)]
pub enum BlobReconstructionError {
BlobsMissing,
UnavailableBlobs,
InconsistentFork,
}
/// A `BeaconBlock` and a signature from its proposer.
@@ -244,25 +246,24 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload>
/// Reconstructs an empty `BlobsSidecar`, using the given block root if provided, else calculates it.
/// If this block has kzg commitments, an error will be returned. If this block is from prior to the
/// Eip4844 fork, `None` will be returned.
/// Eip4844 fork, this will error.
pub fn reconstruct_empty_blobs(
&self,
block_root_opt: Option<Hash256>,
) -> Result<Option<BlobsSidecar<E>>, BlobReconstructionError> {
self.message()
) -> Result<BlobsSidecar<E>, BlobReconstructionError> {
let kzg_commitments = self
.message()
.body()
.blob_kzg_commitments()
.map(|kzg_commitments| {
if kzg_commitments.len() > 0 {
Err(BlobReconstructionError::BlobsMissing)
} else {
Ok(Some(BlobsSidecar::empty_from_parts(
block_root_opt.unwrap_or(self.canonical_root()),
self.slot(),
)))
}
})
.unwrap_or(Ok(None))
.map_err(|_| BlobReconstructionError::InconsistentFork)?;
if kzg_commitments.is_empty() {
Ok(BlobsSidecar::empty_from_parts(
block_root_opt.unwrap_or(self.canonical_root()),
self.slot(),
))
} else {
Err(BlobReconstructionError::UnavailableBlobs)
}
}
}

View File

@@ -1,4 +1,3 @@
use crate::signed_beacon_block::BlobReconstructionError;
use crate::{BlobsSidecar, EthSpec, Hash256, SignedBeaconBlock, SignedBeaconBlockEip4844, Slot};
use derivative::Derivative;
use serde_derive::{Deserialize, Serialize};
@@ -33,128 +32,3 @@ impl<T: EthSpec> SignedBeaconBlockAndBlobsSidecar<T> {
})
}
}
/// A wrapper over a [`SignedBeaconBlock`] or a [`SignedBeaconBlockAndBlobsSidecar`]. This newtype
/// wraps the `BlockWrapperInner` to ensure blobs cannot be accessed via an enum match. This would
/// circumvent empty blob reconstruction when accessing blobs.
#[derive(Clone, Debug, Derivative)]
#[derivative(PartialEq, Hash(bound = "T: EthSpec"))]
pub struct BlockWrapper<T: EthSpec>(BlockWrapperInner<T>);
/// A wrapper over a [`SignedBeaconBlock`] or a [`SignedBeaconBlockAndBlobsSidecar`].
#[derive(Clone, Debug, Derivative)]
#[derivative(PartialEq, Hash(bound = "T: EthSpec"))]
pub enum BlockWrapperInner<T: EthSpec> {
Block(Arc<SignedBeaconBlock<T>>),
BlockAndBlob(SignedBeaconBlockAndBlobsSidecar<T>),
}
impl<T: EthSpec> BlockWrapper<T> {
pub fn new(block: Arc<SignedBeaconBlock<T>>) -> Self {
Self(BlockWrapperInner::Block(block))
}
pub fn new_with_blobs(
beacon_block: Arc<SignedBeaconBlock<T>>,
blobs_sidecar: Arc<BlobsSidecar<T>>,
) -> Self {
Self(BlockWrapperInner::BlockAndBlob(
SignedBeaconBlockAndBlobsSidecar {
beacon_block,
blobs_sidecar,
},
))
}
pub fn slot(&self) -> Slot {
match &self.0 {
BlockWrapperInner::Block(block) => block.slot(),
BlockWrapperInner::BlockAndBlob(block_sidecar_pair) => {
block_sidecar_pair.beacon_block.slot()
}
}
}
pub fn block(&self) -> &SignedBeaconBlock<T> {
match &self.0 {
BlockWrapperInner::Block(block) => &block,
BlockWrapperInner::BlockAndBlob(block_sidecar_pair) => &block_sidecar_pair.beacon_block,
}
}
pub fn block_cloned(&self) -> Arc<SignedBeaconBlock<T>> {
match &self.0 {
BlockWrapperInner::Block(block) => block.clone(),
BlockWrapperInner::BlockAndBlob(block_sidecar_pair) => {
block_sidecar_pair.beacon_block.clone()
}
}
}
pub fn blobs(
&self,
block_root: Option<Hash256>,
) -> Result<Option<Arc<BlobsSidecar<T>>>, BlobReconstructionError> {
match &self.0 {
BlockWrapperInner::Block(block) => block
.reconstruct_empty_blobs(block_root)
.map(|blob_opt| blob_opt.map(Arc::new)),
BlockWrapperInner::BlockAndBlob(block_sidecar_pair) => {
Ok(Some(block_sidecar_pair.blobs_sidecar.clone()))
}
}
}
pub fn message(&self) -> crate::BeaconBlockRef<T> {
match &self.0 {
BlockWrapperInner::Block(block) => block.message(),
BlockWrapperInner::BlockAndBlob(block_sidecar_pair) => {
block_sidecar_pair.beacon_block.message()
}
}
}
pub fn parent_root(&self) -> Hash256 {
self.block().parent_root()
}
pub fn deconstruct(
self,
block_root: Option<Hash256>,
) -> (
Arc<SignedBeaconBlock<T>>,
Result<Option<Arc<BlobsSidecar<T>>>, BlobReconstructionError>,
) {
match self.0 {
BlockWrapperInner::Block(block) => {
let blobs = block
.reconstruct_empty_blobs(block_root)
.map(|blob_opt| blob_opt.map(Arc::new));
(block, blobs)
}
BlockWrapperInner::BlockAndBlob(block_sidecar_pair) => {
let SignedBeaconBlockAndBlobsSidecar {
beacon_block,
blobs_sidecar,
} = block_sidecar_pair;
(beacon_block, Ok(Some(blobs_sidecar)))
}
}
}
}
impl<T: EthSpec> From<SignedBeaconBlock<T>> for BlockWrapper<T> {
fn from(block: SignedBeaconBlock<T>) -> Self {
BlockWrapper(BlockWrapperInner::Block(Arc::new(block)))
}
}
impl<T: EthSpec> From<Arc<SignedBeaconBlock<T>>> for BlockWrapper<T> {
fn from(block: Arc<SignedBeaconBlock<T>>) -> Self {
BlockWrapper(BlockWrapperInner::Block(block))
}
}
impl<T: EthSpec> From<SignedBeaconBlockAndBlobsSidecar<T>> for BlockWrapper<T> {
fn from(block: SignedBeaconBlockAndBlobsSidecar<T>) -> Self {
BlockWrapper(BlockWrapperInner::BlockAndBlob(block))
}
}