mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
fix: only accept rpc enveloped format for transactions in payload (#4928)
This commit is contained in:
@ -10,8 +10,8 @@ use reth_rpc_types::engine::{
|
|||||||
PayloadId,
|
PayloadId,
|
||||||
};
|
};
|
||||||
use reth_rpc_types_compat::engine::payload::{
|
use reth_rpc_types_compat::engine::payload::{
|
||||||
convert_block_to_payload_field_v2, convert_standalonewithdraw_to_withdrawal,
|
block_to_payload_v3, convert_block_to_payload_field_v2,
|
||||||
try_block_to_payload_v1, try_block_to_payload_v3,
|
convert_standalone_withdraw_to_withdrawal, try_block_to_payload_v1,
|
||||||
};
|
};
|
||||||
use revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, SpecId};
|
use revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, SpecId};
|
||||||
/// Contains the built payload.
|
/// Contains the built payload.
|
||||||
@ -100,7 +100,7 @@ impl From<BuiltPayload> for ExecutionPayloadEnvelopeV3 {
|
|||||||
let BuiltPayload { block, fees, sidecars, .. } = value;
|
let BuiltPayload { block, fees, sidecars, .. } = value;
|
||||||
|
|
||||||
ExecutionPayloadEnvelopeV3 {
|
ExecutionPayloadEnvelopeV3 {
|
||||||
execution_payload: try_block_to_payload_v3(block),
|
execution_payload: block_to_payload_v3(block),
|
||||||
block_value: fees,
|
block_value: fees,
|
||||||
// From the engine API spec:
|
// From the engine API spec:
|
||||||
//
|
//
|
||||||
@ -148,7 +148,7 @@ impl PayloadBuilderAttributes {
|
|||||||
|withdrawals: Vec<reth_rpc_types::engine::payload::Withdrawal>| {
|
|withdrawals: Vec<reth_rpc_types::engine::payload::Withdrawal>| {
|
||||||
withdrawals
|
withdrawals
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(convert_standalonewithdraw_to_withdrawal) // Removed the parentheses here
|
.map(convert_standalone_withdraw_to_withdrawal) // Removed the parentheses here
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -876,7 +876,7 @@ impl TransactionSigned {
|
|||||||
///
|
///
|
||||||
/// For legacy transactions, it encodes the RLP of the transaction into the buffer: `rlp(tx)`
|
/// For legacy transactions, it encodes the RLP of the transaction into the buffer: `rlp(tx)`
|
||||||
/// For EIP-2718 typed it encodes the type of the transaction followed by the rlp of the
|
/// For EIP-2718 typed it encodes the type of the transaction followed by the rlp of the
|
||||||
/// transaction: `type` + `rlp(tx)`
|
/// transaction: `type || rlp(tx)`
|
||||||
pub fn encode_enveloped(&self, out: &mut dyn bytes::BufMut) {
|
pub fn encode_enveloped(&self, out: &mut dyn bytes::BufMut) {
|
||||||
self.encode_inner(out, false)
|
self.encode_inner(out, false)
|
||||||
}
|
}
|
||||||
@ -927,6 +927,9 @@ impl TransactionSigned {
|
|||||||
/// Decodes legacy transaction from the data buffer into a tuple.
|
/// Decodes legacy transaction from the data buffer into a tuple.
|
||||||
///
|
///
|
||||||
/// This expects `rlp(legacy_tx)`
|
/// This expects `rlp(legacy_tx)`
|
||||||
|
///
|
||||||
|
/// Refer to the docs for [Self::decode_rlp_legacy_transaction] for details on the exact
|
||||||
|
/// format expected.
|
||||||
// TODO: make buf advancement semantics consistent with `decode_enveloped_typed_transaction`,
|
// TODO: make buf advancement semantics consistent with `decode_enveloped_typed_transaction`,
|
||||||
// so decoding methods do not need to manually advance the buffer
|
// so decoding methods do not need to manually advance the buffer
|
||||||
pub(crate) fn decode_rlp_legacy_transaction_tuple(
|
pub(crate) fn decode_rlp_legacy_transaction_tuple(
|
||||||
@ -956,6 +959,12 @@ impl TransactionSigned {
|
|||||||
|
|
||||||
/// Decodes legacy transaction from the data buffer.
|
/// Decodes legacy transaction from the data buffer.
|
||||||
///
|
///
|
||||||
|
/// This should be used _only_ be used in general transaction decoding methods, which have
|
||||||
|
/// already ensured that the input is a legacy transaction with the following format:
|
||||||
|
/// `rlp(legacy_tx)`
|
||||||
|
///
|
||||||
|
/// Legacy transactions are encoded as lists, so the input should start with a RLP list header.
|
||||||
|
///
|
||||||
/// This expects `rlp(legacy_tx)`
|
/// This expects `rlp(legacy_tx)`
|
||||||
// TODO: make buf advancement semantics consistent with `decode_enveloped_typed_transaction`,
|
// TODO: make buf advancement semantics consistent with `decode_enveloped_typed_transaction`,
|
||||||
// so decoding methods do not need to manually advance the buffer
|
// so decoding methods do not need to manually advance the buffer
|
||||||
@ -969,7 +978,14 @@ impl TransactionSigned {
|
|||||||
|
|
||||||
/// Decodes en enveloped EIP-2718 typed transaction.
|
/// Decodes en enveloped EIP-2718 typed transaction.
|
||||||
///
|
///
|
||||||
/// CAUTION: this expects that `data` is `[id, rlp(tx)]`
|
/// This should be used _only_ be used internally in general transaction decoding methods,
|
||||||
|
/// which have already ensured that the input is a typed transaction with the following format:
|
||||||
|
/// `tx_type || rlp(tx)`
|
||||||
|
///
|
||||||
|
/// Note that this format does not start with any RLP header, and instead starts with a single
|
||||||
|
/// byte indicating the transaction type.
|
||||||
|
///
|
||||||
|
/// CAUTION: this expects that `data` is `tx_type || rlp(tx)`
|
||||||
pub fn decode_enveloped_typed_transaction(
|
pub fn decode_enveloped_typed_transaction(
|
||||||
data: &mut &[u8],
|
data: &mut &[u8],
|
||||||
) -> alloy_rlp::Result<TransactionSigned> {
|
) -> alloy_rlp::Result<TransactionSigned> {
|
||||||
@ -1003,12 +1019,23 @@ impl TransactionSigned {
|
|||||||
Ok(signed)
|
Ok(signed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes the "raw" format of transaction (e.g. `eth_sendRawTransaction`).
|
/// Decodes the "raw" format of transaction (similar to `eth_sendRawTransaction`).
|
||||||
///
|
///
|
||||||
/// The raw transaction is either a legacy transaction or EIP-2718 typed transaction
|
/// This should be used for any RPC method that accepts a raw transaction, **excluding** raw
|
||||||
/// For legacy transactions, the format is encoded as: `rlp(tx)`
|
/// EIP-4844 transactions in `eth_sendRawTransaction`. Currently, this includes:
|
||||||
/// For EIP-2718 typed transaction, the format is encoded as the type of the transaction
|
/// * `eth_sendRawTransaction` for non-EIP-4844 transactions.
|
||||||
/// followed by the rlp of the transaction: `type` + `rlp(tx)`
|
/// * All versions of `engine_newPayload`, in the `transactions` field.
|
||||||
|
///
|
||||||
|
/// A raw transaction is either a legacy transaction or EIP-2718 typed transaction.
|
||||||
|
///
|
||||||
|
/// For legacy transactions, the format is encoded as: `rlp(tx)`. This format will start with a
|
||||||
|
/// RLP list header.
|
||||||
|
///
|
||||||
|
/// For EIP-2718 typed transactions, the format is encoded as the type of the transaction
|
||||||
|
/// followed by the rlp of the transaction: `type || rlp(tx)`.
|
||||||
|
///
|
||||||
|
/// To decode EIP-4844 transactions in `eth_sendRawTransaction`, use
|
||||||
|
/// [PooledTransactionsElement::decode_enveloped].
|
||||||
pub fn decode_enveloped(tx: Bytes) -> alloy_rlp::Result<Self> {
|
pub fn decode_enveloped(tx: Bytes) -> alloy_rlp::Result<Self> {
|
||||||
let mut data = tx.as_ref();
|
let mut data = tx.as_ref();
|
||||||
|
|
||||||
@ -1045,7 +1072,24 @@ impl Encodable for TransactionSigned {
|
|||||||
/// This `Decodable` implementation only supports decoding rlp encoded transactions as it's used by
|
/// This `Decodable` implementation only supports decoding rlp encoded transactions as it's used by
|
||||||
/// p2p.
|
/// p2p.
|
||||||
///
|
///
|
||||||
/// CAUTION: this expects that the given buf contains rlp
|
/// The p2p encoding format always includes an RLP header, although the type RLP header depends on
|
||||||
|
/// whether or not the transaction is a legacy transaction.
|
||||||
|
///
|
||||||
|
/// If the transaction is a legacy transaction, it is just encoded as a RLP list: `rlp(tx)`.
|
||||||
|
///
|
||||||
|
/// If the transaction is a typed transaction, it is encoded as a RLP string:
|
||||||
|
/// `rlp(type || rlp(tx))`
|
||||||
|
///
|
||||||
|
/// This cannot be used for decoding EIP-4844 transactions in p2p, since the EIP-4844 variant of
|
||||||
|
/// [TransactionSigned] does not include the blob sidecar. For a general purpose decoding method
|
||||||
|
/// suitable for decoding transactions from p2p, see [PooledTransactionsElement].
|
||||||
|
///
|
||||||
|
/// CAUTION: Due to a quirk in [Header::decode], this method will succeed even if a typed
|
||||||
|
/// transaction is encoded in the RPC format, and does not start with a RLP header. This is because
|
||||||
|
/// [Header::decode] does not advance the buffer, and returns a length-1 string header if the first
|
||||||
|
/// byte is less than `0xf7`. This causes this decode implementation to pass unaltered buffer to
|
||||||
|
/// [TransactionSigned::decode_enveloped_typed_transaction], which expects the RPC format. Despite
|
||||||
|
/// this quirk, this should **not** be used for RPC methods that accept raw transactions.
|
||||||
impl Decodable for TransactionSigned {
|
impl Decodable for TransactionSigned {
|
||||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||||
// decode header
|
// decode header
|
||||||
|
|||||||
@ -109,12 +109,28 @@ impl PooledTransactionsElement {
|
|||||||
|
|
||||||
/// Decodes the "raw" format of transaction (e.g. `eth_sendRawTransaction`).
|
/// Decodes the "raw" format of transaction (e.g. `eth_sendRawTransaction`).
|
||||||
///
|
///
|
||||||
/// The raw transaction is either a legacy transaction or EIP-2718 typed transaction
|
/// This should be used for `eth_sendRawTransaction`, for any transaction type. Blob
|
||||||
/// For legacy transactions, the format is encoded as: `rlp(tx)`
|
/// transactions **must** include the blob sidecar as part of the raw encoding.
|
||||||
/// For EIP-2718 typed transaction, the format is encoded as the type of the transaction
|
|
||||||
/// followed by the rlp of the transaction: `type` + `rlp(tx)`
|
|
||||||
///
|
///
|
||||||
/// For encoded EIP-4844 transactions, the blob sidecar _must_ be included.
|
/// This method can not be used for decoding the `transactions` field of `engine_newPayload`,
|
||||||
|
/// because EIP-4844 transactions for that method do not include the blob sidecar. The blobs
|
||||||
|
/// are supplied in an argument separate from the payload.
|
||||||
|
///
|
||||||
|
/// A raw transaction is either a legacy transaction or EIP-2718 typed transaction, with a
|
||||||
|
/// special case for EIP-4844 transactions.
|
||||||
|
///
|
||||||
|
/// For legacy transactions, the format is encoded as: `rlp(tx)`. This format will start with a
|
||||||
|
/// RLP list header.
|
||||||
|
///
|
||||||
|
/// For EIP-2718 typed transactions, the format is encoded as the type of the transaction
|
||||||
|
/// followed by the rlp of the transaction: `type || rlp(tx)`.
|
||||||
|
///
|
||||||
|
/// For EIP-4844 transactions, the format includes a blob sidecar (the blobs, commitments, and
|
||||||
|
/// proofs) after the transaction:
|
||||||
|
/// `type || rlp([tx_payload_body, blobs, commitments, proofs])`
|
||||||
|
///
|
||||||
|
/// Where `tx_payload_body` is encoded as a RLP list:
|
||||||
|
/// `[chain_id, nonce, max_priority_fee_per_gas, ..., y_parity, r, s]`
|
||||||
pub fn decode_enveloped(tx: Bytes) -> alloy_rlp::Result<Self> {
|
pub fn decode_enveloped(tx: Bytes) -> alloy_rlp::Result<Self> {
|
||||||
let mut data = tx.as_ref();
|
let mut data = tx.as_ref();
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ use reth_rpc_types::engine::{
|
|||||||
ExecutionPayload, ExecutionPayloadBodyV1, ExecutionPayloadV1, PayloadError,
|
ExecutionPayload, ExecutionPayloadBodyV1, ExecutionPayloadV1, PayloadError,
|
||||||
};
|
};
|
||||||
use reth_rpc_types_compat::engine::payload::{
|
use reth_rpc_types_compat::engine::payload::{
|
||||||
convert_standalonewithdraw_to_withdrawal, convert_to_payload_body_v1, try_block_to_payload,
|
convert_standalone_withdraw_to_withdrawal, convert_to_payload_body_v1, try_block_to_payload,
|
||||||
try_block_to_payload_v1, try_into_sealed_block, try_payload_v1_to_block,
|
try_block_to_payload_v1, try_into_sealed_block, try_payload_v1_to_block,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ fn payload_body_roundtrip() {
|
|||||||
let withdraw = payload_body.withdrawals.map(|withdrawals| {
|
let withdraw = payload_body.withdrawals.map(|withdrawals| {
|
||||||
withdrawals
|
withdrawals
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(convert_standalonewithdraw_to_withdrawal)
|
.map(convert_standalone_withdraw_to_withdrawal)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
});
|
});
|
||||||
assert_eq!(block.withdrawals, withdraw);
|
assert_eq!(block.withdrawals, withdraw);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//! Standalone functions for engine specific rpc type conversions
|
//! Standalone functions for engine specific rpc type conversions
|
||||||
pub mod payload;
|
pub mod payload;
|
||||||
pub use payload::{
|
pub use payload::{
|
||||||
convert_standalonewithdraw_to_withdrawal, convert_withdrawal_to_standalonewithdraw,
|
convert_standalone_withdraw_to_withdrawal, convert_withdrawal_to_standalone_withdraw,
|
||||||
try_block_to_payload_v1, try_into_sealed_block, try_payload_v1_to_block,
|
try_block_to_payload_v1, try_into_sealed_block, try_payload_v1_to_block,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
//! Standalone Conversion Functions for Handling Different Versions of Execution Payloads in
|
//! Standalone Conversion Functions for Handling Different Versions of Execution Payloads in
|
||||||
//! Ethereum's Engine
|
//! Ethereum's Engine
|
||||||
use alloy_rlp::Decodable;
|
|
||||||
use reth_primitives::{
|
use reth_primitives::{
|
||||||
constants::{MAXIMUM_EXTRA_DATA_SIZE, MIN_PROTOCOL_BASE_FEE_U256},
|
constants::{MAXIMUM_EXTRA_DATA_SIZE, MIN_PROTOCOL_BASE_FEE_U256},
|
||||||
proofs::{self, EMPTY_LIST_HASH},
|
proofs::{self, EMPTY_LIST_HASH},
|
||||||
@ -23,8 +22,8 @@ pub fn try_payload_v1_to_block(payload: ExecutionPayloadV1) -> Result<Block, Pay
|
|||||||
|
|
||||||
let transactions = payload
|
let transactions = payload
|
||||||
.transactions
|
.transactions
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|tx| TransactionSigned::decode(&mut tx.as_ref()))
|
.map(TransactionSigned::decode_enveloped)
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
let transactions_root = proofs::calculate_transaction_root(&transactions);
|
let transactions_root = proofs::calculate_transaction_root(&transactions);
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ pub fn try_payload_v2_to_block(payload: ExecutionPayloadV2) -> Result<Block, Pay
|
|||||||
let withdrawals: Vec<_> = payload
|
let withdrawals: Vec<_> = payload
|
||||||
.withdrawals
|
.withdrawals
|
||||||
.iter()
|
.iter()
|
||||||
.map(|w| convert_standalonewithdraw_to_withdrawal(w.clone()))
|
.map(|w| convert_standalone_withdraw_to_withdrawal(w.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
let withdrawals_root = proofs::calculate_withdrawals_root(&withdrawals);
|
let withdrawals_root = proofs::calculate_withdrawals_root(&withdrawals);
|
||||||
base_sealed_block.withdrawals = Some(withdrawals);
|
base_sealed_block.withdrawals = Some(withdrawals);
|
||||||
@ -92,7 +91,7 @@ pub fn try_payload_v3_to_block(payload: ExecutionPayloadV3) -> Result<Block, Pay
|
|||||||
pub fn try_block_to_payload(value: SealedBlock) -> ExecutionPayload {
|
pub fn try_block_to_payload(value: SealedBlock) -> ExecutionPayload {
|
||||||
if value.header.parent_beacon_block_root.is_some() {
|
if value.header.parent_beacon_block_root.is_some() {
|
||||||
// block with parent beacon block root: V3
|
// block with parent beacon block root: V3
|
||||||
ExecutionPayload::V3(try_block_to_payload_v3(value))
|
ExecutionPayload::V3(block_to_payload_v3(value))
|
||||||
} else if value.withdrawals.is_some() {
|
} else if value.withdrawals.is_some() {
|
||||||
// block with withdrawals: V2
|
// block with withdrawals: V2
|
||||||
ExecutionPayload::V2(try_block_to_payload_v2(value))
|
ExecutionPayload::V2(try_block_to_payload_v2(value))
|
||||||
@ -147,7 +146,7 @@ pub fn try_block_to_payload_v2(value: SealedBlock) -> ExecutionPayloadV2 {
|
|||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(convert_withdrawal_to_standalonewithdraw)
|
.map(convert_withdrawal_to_standalone_withdraw)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
ExecutionPayloadV2 {
|
ExecutionPayloadV2 {
|
||||||
@ -172,7 +171,7 @@ pub fn try_block_to_payload_v2(value: SealedBlock) -> ExecutionPayloadV2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts [SealedBlock] to [ExecutionPayloadV3]
|
/// Converts [SealedBlock] to [ExecutionPayloadV3]
|
||||||
pub fn try_block_to_payload_v3(value: SealedBlock) -> ExecutionPayloadV3 {
|
pub fn block_to_payload_v3(value: SealedBlock) -> ExecutionPayloadV3 {
|
||||||
let transactions = value
|
let transactions = value
|
||||||
.body
|
.body
|
||||||
.iter()
|
.iter()
|
||||||
@ -188,7 +187,7 @@ pub fn try_block_to_payload_v3(value: SealedBlock) -> ExecutionPayloadV3 {
|
|||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(convert_withdrawal_to_standalonewithdraw)
|
.map(convert_withdrawal_to_standalone_withdraw)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
ExecutionPayloadV3 {
|
ExecutionPayloadV3 {
|
||||||
@ -249,7 +248,7 @@ pub fn convert_payload_input_v2_to_payload(value: ExecutionPayloadInputV2) -> Ex
|
|||||||
/// Converts [SealedBlock] to [ExecutionPayloadInputV2]
|
/// Converts [SealedBlock] to [ExecutionPayloadInputV2]
|
||||||
pub fn convert_block_to_payload_input_v2(value: SealedBlock) -> ExecutionPayloadInputV2 {
|
pub fn convert_block_to_payload_input_v2(value: SealedBlock) -> ExecutionPayloadInputV2 {
|
||||||
let withdraw = value.withdrawals.clone().map(|withdrawals| {
|
let withdraw = value.withdrawals.clone().map(|withdrawals| {
|
||||||
withdrawals.into_iter().map(convert_withdrawal_to_standalonewithdraw).collect::<Vec<_>>()
|
withdrawals.into_iter().map(convert_withdrawal_to_standalone_withdraw).collect::<Vec<_>>()
|
||||||
});
|
});
|
||||||
ExecutionPayloadInputV2 {
|
ExecutionPayloadInputV2 {
|
||||||
withdrawals: withdraw,
|
withdrawals: withdraw,
|
||||||
@ -321,7 +320,7 @@ pub fn validate_block_hash(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts [Withdrawal] to [reth_rpc_types::engine::payload::Withdrawal]
|
/// Converts [Withdrawal] to [reth_rpc_types::engine::payload::Withdrawal]
|
||||||
pub fn convert_withdrawal_to_standalonewithdraw(
|
pub fn convert_withdrawal_to_standalone_withdraw(
|
||||||
withdrawal: Withdrawal,
|
withdrawal: Withdrawal,
|
||||||
) -> reth_rpc_types::engine::payload::Withdrawal {
|
) -> reth_rpc_types::engine::payload::Withdrawal {
|
||||||
reth_rpc_types::engine::payload::Withdrawal {
|
reth_rpc_types::engine::payload::Withdrawal {
|
||||||
@ -333,7 +332,7 @@ pub fn convert_withdrawal_to_standalonewithdraw(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts [reth_rpc_types::engine::payload::Withdrawal] to [Withdrawal]
|
/// Converts [reth_rpc_types::engine::payload::Withdrawal] to [Withdrawal]
|
||||||
pub fn convert_standalonewithdraw_to_withdrawal(
|
pub fn convert_standalone_withdraw_to_withdrawal(
|
||||||
standalone: reth_rpc_types::engine::payload::Withdrawal,
|
standalone: reth_rpc_types::engine::payload::Withdrawal,
|
||||||
) -> Withdrawal {
|
) -> Withdrawal {
|
||||||
Withdrawal {
|
Withdrawal {
|
||||||
@ -355,8 +354,92 @@ pub fn convert_to_payload_body_v1(value: Block) -> ExecutionPayloadBodyV1 {
|
|||||||
value.withdrawals.map(|withdrawals| {
|
value.withdrawals.map(|withdrawals| {
|
||||||
withdrawals
|
withdrawals
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(convert_withdrawal_to_standalonewithdraw)
|
.map(convert_withdrawal_to_standalone_withdraw)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
});
|
});
|
||||||
ExecutionPayloadBodyV1 { transactions: transactions.collect(), withdrawals: withdraw }
|
ExecutionPayloadBodyV1 { transactions: transactions.collect(), withdrawals: withdraw }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use reth_primitives::{hex, Bytes, U256, U64};
|
||||||
|
use reth_rpc_types::{engine::ExecutionPayloadV3, ExecutionPayloadV1, ExecutionPayloadV2};
|
||||||
|
|
||||||
|
use super::{block_to_payload_v3, try_payload_v3_to_block};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_payload_to_block() {
|
||||||
|
let first_transaction_raw = Bytes::from_static(&hex!("02f9017a8501a1f0ff438211cc85012a05f2008512a05f2000830249f094d5409474fd5a725eab2ac9a8b26ca6fb51af37ef80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000001bdd2ed4b616c800000000000000000000000000001e9ee781dd4b97bdef92e5d1785f73a1f931daa20000000000000000000000007a40026a3b9a41754a95eec8c92c6b99886f440c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009ae80eb647dd09968488fa1d7e412bf8558a0b7a0000000000000000000000000f9815537d361cb02befd9918c95c97d4d8a4a2bc001a0ba8f1928bb0efc3fcd01524a2039a9a2588fa567cd9a7cc18217e05c615e9d69a0544bfd11425ac7748e76b3795b57a5563e2b0eff47b5428744c62ff19ccfc305")[..]);
|
||||||
|
let second_transaction_raw = Bytes::from_static(&hex!("03f901388501a1f0ff430c843b9aca00843b9aca0082520894e7249813d8ccf6fa95a2203f46a64166073d58878080c005f8c6a00195f6dff17753fc89b60eac6477026a805116962c9e412de8015c0484e661c1a001aae314061d4f5bbf158f15d9417a238f9589783f58762cd39d05966b3ba2fba0013f5be9b12e7da06f0dd11a7bdc4e0db8ef33832acc23b183bd0a2c1408a757a0019d9ac55ea1a615d92965e04d960cb3be7bff121a381424f1f22865bd582e09a001def04412e76df26fefe7b0ed5e10580918ae4f355b074c0cfe5d0259157869a0011c11a415db57e43db07aef0de9280b591d65ca0cce36c7002507f8191e5d4a80a0c89b59970b119187d97ad70539f1624bbede92648e2dc007890f9658a88756c5a06fb2e3d4ce2c438c0856c2de34948b7032b1aadc4642a9666228ea8cdc7786b7")[..]);
|
||||||
|
|
||||||
|
let new_payload = ExecutionPayloadV3 {
|
||||||
|
payload_inner: ExecutionPayloadV2 {
|
||||||
|
payload_inner: ExecutionPayloadV1 {
|
||||||
|
base_fee_per_gas: U256::from(7u64),
|
||||||
|
block_number: U64::from(0xa946u64),
|
||||||
|
block_hash: hex!("a5ddd3f286f429458a39cafc13ffe89295a7efa8eb363cf89a1a4887dbcf272b").into(),
|
||||||
|
logs_bloom: hex!("00200004000000000000000080000000000200000000000000000000000000000000200000000000000000000000000000000000800000000200000000000000000000000000000000000008000000200000000000000000000001000000000000000000000000000000800000000000000000000100000000000030000000000000000040000000000000000000000000000000000800080080404000000000000008000000000008200000000000200000000000000000000000000000000000000002000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000100000000000000000000").into(),
|
||||||
|
extra_data: hex!("d883010d03846765746888676f312e32312e31856c696e7578").into(),
|
||||||
|
gas_limit: U64::from(0x1c9c380),
|
||||||
|
gas_used: U64::from(0x1f4a9),
|
||||||
|
timestamp: U64::from(0x651f35b8),
|
||||||
|
fee_recipient: hex!("f97e180c050e5ab072211ad2c213eb5aee4df134").into(),
|
||||||
|
parent_hash: hex!("d829192799c73ef28a7332313b3c03af1f2d5da2c36f8ecfafe7a83a3bfb8d1e").into(),
|
||||||
|
prev_randao: hex!("753888cc4adfbeb9e24e01c84233f9d204f4a9e1273f0e29b43c4c148b2b8b7e").into(),
|
||||||
|
receipts_root: hex!("4cbc48e87389399a0ea0b382b1c46962c4b8e398014bf0cc610f9c672bee3155").into(),
|
||||||
|
state_root: hex!("017d7fa2b5adb480f5e05b2c95cb4186e12062eed893fc8822798eed134329d1").into(),
|
||||||
|
transactions: vec![first_transaction_raw, second_transaction_raw],
|
||||||
|
},
|
||||||
|
withdrawals: vec![],
|
||||||
|
},
|
||||||
|
blob_gas_used: U64::from(0xc0000),
|
||||||
|
excess_blob_gas: U64::from(0x580000),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut block = try_payload_v3_to_block(new_payload.clone()).unwrap();
|
||||||
|
|
||||||
|
// this newPayload came with a parent beacon block root, we need to manually insert it
|
||||||
|
// before hashing
|
||||||
|
let parent_beacon_block_root =
|
||||||
|
hex!("531cd53b8e68deef0ea65edfa3cda927a846c307b0907657af34bc3f313b5871");
|
||||||
|
block.header.parent_beacon_block_root = Some(parent_beacon_block_root.into());
|
||||||
|
|
||||||
|
let converted_payload = block_to_payload_v3(block.seal_slow());
|
||||||
|
|
||||||
|
// ensure the payloads are the same
|
||||||
|
assert_eq!(new_payload, converted_payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn payload_to_block_rejects_network_encoded_tx() {
|
||||||
|
let first_transaction_raw = Bytes::from_static(&hex!("b9017e02f9017a8501a1f0ff438211cc85012a05f2008512a05f2000830249f094d5409474fd5a725eab2ac9a8b26ca6fb51af37ef80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000001bdd2ed4b616c800000000000000000000000000001e9ee781dd4b97bdef92e5d1785f73a1f931daa20000000000000000000000007a40026a3b9a41754a95eec8c92c6b99886f440c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009ae80eb647dd09968488fa1d7e412bf8558a0b7a0000000000000000000000000f9815537d361cb02befd9918c95c97d4d8a4a2bc001a0ba8f1928bb0efc3fcd01524a2039a9a2588fa567cd9a7cc18217e05c615e9d69a0544bfd11425ac7748e76b3795b57a5563e2b0eff47b5428744c62ff19ccfc305")[..]);
|
||||||
|
let second_transaction_raw = Bytes::from_static(&hex!("b9013c03f901388501a1f0ff430c843b9aca00843b9aca0082520894e7249813d8ccf6fa95a2203f46a64166073d58878080c005f8c6a00195f6dff17753fc89b60eac6477026a805116962c9e412de8015c0484e661c1a001aae314061d4f5bbf158f15d9417a238f9589783f58762cd39d05966b3ba2fba0013f5be9b12e7da06f0dd11a7bdc4e0db8ef33832acc23b183bd0a2c1408a757a0019d9ac55ea1a615d92965e04d960cb3be7bff121a381424f1f22865bd582e09a001def04412e76df26fefe7b0ed5e10580918ae4f355b074c0cfe5d0259157869a0011c11a415db57e43db07aef0de9280b591d65ca0cce36c7002507f8191e5d4a80a0c89b59970b119187d97ad70539f1624bbede92648e2dc007890f9658a88756c5a06fb2e3d4ce2c438c0856c2de34948b7032b1aadc4642a9666228ea8cdc7786b7")[..]);
|
||||||
|
|
||||||
|
let new_payload = ExecutionPayloadV3 {
|
||||||
|
payload_inner: ExecutionPayloadV2 {
|
||||||
|
payload_inner: ExecutionPayloadV1 {
|
||||||
|
base_fee_per_gas: U256::from(7u64),
|
||||||
|
block_number: U64::from(0xa946u64),
|
||||||
|
block_hash: hex!("a5ddd3f286f429458a39cafc13ffe89295a7efa8eb363cf89a1a4887dbcf272b").into(),
|
||||||
|
logs_bloom: hex!("00200004000000000000000080000000000200000000000000000000000000000000200000000000000000000000000000000000800000000200000000000000000000000000000000000008000000200000000000000000000001000000000000000000000000000000800000000000000000000100000000000030000000000000000040000000000000000000000000000000000800080080404000000000000008000000000008200000000000200000000000000000000000000000000000000002000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000100000000000000000000").into(),
|
||||||
|
extra_data: hex!("d883010d03846765746888676f312e32312e31856c696e7578").into(),
|
||||||
|
gas_limit: U64::from(0x1c9c380),
|
||||||
|
gas_used: U64::from(0x1f4a9),
|
||||||
|
timestamp: U64::from(0x651f35b8),
|
||||||
|
fee_recipient: hex!("f97e180c050e5ab072211ad2c213eb5aee4df134").into(),
|
||||||
|
parent_hash: hex!("d829192799c73ef28a7332313b3c03af1f2d5da2c36f8ecfafe7a83a3bfb8d1e").into(),
|
||||||
|
prev_randao: hex!("753888cc4adfbeb9e24e01c84233f9d204f4a9e1273f0e29b43c4c148b2b8b7e").into(),
|
||||||
|
receipts_root: hex!("4cbc48e87389399a0ea0b382b1c46962c4b8e398014bf0cc610f9c672bee3155").into(),
|
||||||
|
state_root: hex!("017d7fa2b5adb480f5e05b2c95cb4186e12062eed893fc8822798eed134329d1").into(),
|
||||||
|
transactions: vec![first_transaction_raw, second_transaction_raw],
|
||||||
|
},
|
||||||
|
withdrawals: vec![],
|
||||||
|
},
|
||||||
|
blob_gas_used: U64::from(0xc0000),
|
||||||
|
excess_blob_gas: U64::from(0x580000),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _block = try_payload_v3_to_block(new_payload.clone())
|
||||||
|
.expect_err("execution payload conversion requires typed txs without a rlp header");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user