pub(crate) mod sealed;
pub use sealed::SealedBlock;
pub(crate) mod recovered;
pub use recovered::RecoveredBlock;
pub mod body;
pub mod error;
pub mod header;
use alloc::{fmt, vec::Vec};
use alloy_primitives::{Address, B256};
use alloy_rlp::{Decodable, Encodable};
use crate::{
block::error::BlockRecoveryError, transaction::signed::RecoveryError, BlockBody, BlockHeader,
FullBlockBody, FullBlockHeader, InMemorySize, MaybeSerde, SealedHeader, SignedTransaction,
};
pub trait FullBlock: Block<Header: FullBlockHeader, Body: FullBlockBody> {}
impl<T> FullBlock for T where T: Block<Header: FullBlockHeader, Body: FullBlockBody> {}
pub type BlockTx<B> = <<B as Block>::Body as BlockBody>::Transaction;
pub trait Block:
Send
+ Sync
+ Unpin
+ Clone
+ Default
+ fmt::Debug
+ PartialEq
+ Eq
+ InMemorySize
+ MaybeSerde
+ Encodable
+ Decodable
{
type Header: BlockHeader;
type Body: BlockBody<OmmerHeader = Self::Header>;
fn new(header: Self::Header, body: Self::Body) -> Self;
fn new_sealed(header: SealedHeader<Self::Header>, body: Self::Body) -> SealedBlock<Self> {
SealedBlock::from_sealed_parts(header, body)
}
fn seal_unchecked(self, hash: B256) -> SealedBlock<Self> {
SealedBlock::new_unchecked(self, hash)
}
fn seal(self) -> SealedBlock<Self> {
SealedBlock::new_unhashed(self)
}
fn seal_slow(self) -> SealedBlock<Self> {
SealedBlock::seal_slow(self)
}
fn header(&self) -> &Self::Header;
fn body(&self) -> &Self::Body;
fn split(self) -> (Self::Header, Self::Body);
fn split_ref(&self) -> (&Self::Header, &Self::Body) {
(self.header(), self.body())
}
fn into_header(self) -> Self::Header {
self.split().0
}
fn into_body(self) -> Self::Body {
self.split().1
}
fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize;
fn recover_signers(&self) -> Result<Vec<Address>, RecoveryError>
where
<Self::Body as BlockBody>::Transaction: SignedTransaction,
{
self.body().recover_signers()
}
fn try_into_recovered_unchecked(
self,
senders: Vec<Address>,
) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>>
where
<Self::Body as BlockBody>::Transaction: SignedTransaction,
{
let senders = if self.body().transactions().len() == senders.len() {
senders
} else {
let Ok(senders) = self.body().recover_signers_unchecked() else {
return Err(BlockRecoveryError::new(self))
};
senders
};
Ok(RecoveredBlock::new_unhashed(self, senders))
}
fn into_recovered_with_signers(self, signers: Vec<Address>) -> RecoveredBlock<Self>
where
<Self::Body as BlockBody>::Transaction: SignedTransaction,
{
RecoveredBlock::new_unhashed(self, signers)
}
fn try_into_recovered(self) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>> {
let Ok(signers) = self.body().recover_signers() else {
return Err(BlockRecoveryError::new(self))
};
Ok(RecoveredBlock::new_unhashed(self, signers))
}
fn into_ethereum_block(
self,
) -> alloy_consensus::Block<<Self::Body as BlockBody>::Transaction, Self::Header> {
let (header, body) = self.split();
alloy_consensus::Block::new(header, body.into_ethereum_body())
}
}
impl<T, H> Block for alloy_consensus::Block<T, H>
where
T: SignedTransaction,
H: BlockHeader,
{
type Header = H;
type Body = alloy_consensus::BlockBody<T, H>;
fn new(header: Self::Header, body: Self::Body) -> Self {
Self { header, body }
}
fn header(&self) -> &Self::Header {
&self.header
}
fn body(&self) -> &Self::Body {
&self.body
}
fn split(self) -> (Self::Header, Self::Body) {
(self.header, self.body)
}
fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize {
Self::rlp_length_for(header, body)
}
fn into_ethereum_block(self) -> Self {
self
}
}
#[cfg(any(test, feature = "test-utils"))]
pub trait TestBlock: Block<Header: crate::test_utils::TestHeader> {
fn body_mut(&mut self) -> &mut Self::Body;
fn header_mut(&mut self) -> &mut Self::Header;
fn set_header(&mut self, header: Self::Header);
fn set_parent_hash(&mut self, hash: alloy_primitives::BlockHash) {
crate::header::test_utils::TestHeader::set_parent_hash(self.header_mut(), hash);
}
fn set_block_number(&mut self, number: alloy_primitives::BlockNumber) {
crate::header::test_utils::TestHeader::set_block_number(self.header_mut(), number);
}
fn set_timestamp(&mut self, timestamp: u64) {
crate::header::test_utils::TestHeader::set_timestamp(self.header_mut(), timestamp);
}
fn set_state_root(&mut self, state_root: alloy_primitives::B256) {
crate::header::test_utils::TestHeader::set_state_root(self.header_mut(), state_root);
}
fn set_difficulty(&mut self, difficulty: alloy_primitives::U256) {
crate::header::test_utils::TestHeader::set_difficulty(self.header_mut(), difficulty);
}
}
#[cfg(any(test, feature = "test-utils"))]
impl<T, H> TestBlock for alloy_consensus::Block<T, H>
where
T: SignedTransaction,
H: crate::test_utils::TestHeader,
{
fn body_mut(&mut self) -> &mut Self::Body {
&mut self.body
}
fn header_mut(&mut self) -> &mut Self::Header {
&mut self.header
}
fn set_header(&mut self, header: Self::Header) {
self.header = header
}
}