Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ op-alloy-rpc-types-engine = { version = "0.18.9", path = "crates/rpc-types-engin
op-alloy-rpc-jsonrpsee = { version = "0.18.9", path = "crates/rpc-jsonrpsee", default-features = false }

# Alloy
alloy-eips = { version = "1.0.15", default-features = false }
alloy-serde = { version = "1.0.15", default-features = false }
alloy-signer = { version = "1.0.15", default-features = false }
alloy-network = { version = "1.0.15", default-features = false }
alloy-provider = { version = "1.0.15", default-features = false }
alloy-transport = { version = "1.0.15", default-features = false }
alloy-consensus = { version = "1.0.15", default-features = false }
alloy-rpc-types-eth = { version = "1.0.15", default-features = false }
alloy-rpc-types-engine = { version = "1.0.15", default-features = false }
alloy-network-primitives = { version = "1.0.15", default-features = false }
alloy-json-rpc = { version = "1.0.15", default-features = false }
alloy-eips = { version = "1.0.22", default-features = false }
alloy-serde = { version = "1.0.22", default-features = false }
alloy-signer = { version = "1.0.22", default-features = false }
alloy-network = { version = "1.0.22", default-features = false }
alloy-provider = { version = "1.0.22", default-features = false }
alloy-transport = { version = "1.0.22", default-features = false }
alloy-consensus = { version = "1.0.22", default-features = false }
alloy-rpc-types-eth = { version = "1.0.22", default-features = false }
alloy-rpc-types-engine = { version = "1.0.22", default-features = false }
alloy-network-primitives = { version = "1.0.22", default-features = false }
alloy-json-rpc = { version = "1.0.22", default-features = false }

# Alloy RLP
alloy-rlp = { version = "0.3", default-features = false }
Expand Down
51 changes: 51 additions & 0 deletions crates/rpc-types-engine/src/payload/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,57 @@ impl OpExecutionPayload {
self.as_v1().timestamp
}

/// Converts [`OpExecutionPayload`] to [`Block`] with raw transactions.
///
/// Caution: This does not set fields that are not part of the payload and only part of the
/// [`OpExecutionPayloadSidecar`]:
/// - parent_beacon_block_root
///
/// See also: [`OpExecutionPayload::into_block_with_sidecar_raw`]
pub fn into_block_raw(self) -> Result<Block<alloy_primitives::Bytes>, PayloadError> {
match self {
Self::V1(payload) => payload.into_block_raw(),
Self::V2(payload) => payload.into_block_raw(),
Self::V3(payload) => payload.into_block_raw(),
Self::V4(payload) => payload.into_block_raw(),
}
}

/// Creates a new unsealed block from the given payload and payload sidecar with raw
/// transactions.
///
/// This sets the `parent_beacon_block_root` and `requests_hash` if present in the sidecar.
/// Also validates that L1 withdrawals are empty.
///
/// See also: [`OpExecutionPayload::try_into_block_with_sidecar`]
pub fn into_block_with_sidecar_raw(
self,
sidecar: &OpExecutionPayloadSidecar,
) -> Result<Block<alloy_primitives::Bytes>, OpPayloadError> {
if let Some(payload) = self.as_v2() {
if !payload.withdrawals.is_empty() {
return Err(OpPayloadError::NonEmptyL1Withdrawals);
}
}

let mut block = self.into_block_raw()?;

if let Some(blobs_hashes) = sidecar.versioned_hashes() {
if !blobs_hashes.is_empty() {
return Err(OpPayloadError::NonEmptyBlobVersionedHashes);
}
}
if let Some(reqs_hash) = sidecar.requests_hash() {
if reqs_hash != EMPTY_REQUESTS_HASH {
return Err(OpPayloadError::NonEmptyELRequests);
}
block.header.requests_hash = Some(EMPTY_REQUESTS_HASH)
}
block.header.parent_beacon_block_root = sidecar.parent_beacon_block_root();

Ok(block)
}

#[allow(rustdoc::broken_intra_doc_links)]
/// Converts [`OpExecutionPayload`] to [`Block`].
///
Expand Down
24 changes: 17 additions & 7 deletions crates/rpc-types-engine/src/payload/v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,28 @@ impl OpExecutionPayloadV4 {
Self { withdrawals_root, payload_inner: payload }
}

/// Converts [`OpExecutionPayloadV4`] to [`Block`] with raw transactions.
///
/// This performs the same conversion as the underlying V3 payload, but inserts the L2
/// withdrawals root and returns raw transaction bytes instead of decoded transactions.
pub fn into_block_raw(self) -> Result<Block<Bytes>, PayloadError> {
let mut base_block = self.payload_inner.into_block_raw()?;

// overwrite l1 withdrawals root with l2 withdrawals root
base_block.header.withdrawals_root = Some(self.withdrawals_root);

Ok(base_block)
}

/// Converts [`OpExecutionPayloadV4`] to [`Block`].
///
/// This performs the same conversion as the underlying V3 payload, but inserts the L2
/// withdrawals root.
///
/// See also [`ExecutionPayloadV3::try_into_block`].
pub fn try_into_block<T: Decodable2718>(self) -> Result<Block<T>, PayloadError> {
self.try_into_block_with(|tx| {
let block = self.into_block_raw()?;
block.try_map_transactions(|tx| {
T::decode_2718_exact(tx.as_ref())
.map_err(alloy_rlp::Error::from)
.map_err(PayloadError::from)
Expand All @@ -60,12 +74,8 @@ impl OpExecutionPayloadV4 {
F: FnMut(Bytes) -> Result<T, E>,
E: Into<PayloadError>,
{
let mut base_block = self.payload_inner.try_into_block_with(f)?;

// overwrite l1 withdrawals root with l2 withdrawals root
base_block.header.withdrawals_root = Some(self.withdrawals_root);

Ok(base_block)
let block = self.into_block_raw()?;
block.try_map_transactions(f).map_err(|e| e.into())
}
}

Expand Down