diff --git a/crates/consensus/src/transaction/eip4844.rs b/crates/consensus/src/transaction/eip4844.rs index 063f9c8b5df..5a3dfe0b4a4 100644 --- a/crates/consensus/src/transaction/eip4844.rs +++ b/crates/consensus/src/transaction/eip4844.rs @@ -3,7 +3,7 @@ use crate::{SignableTransaction, Signed, Transaction, TxType}; use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip4844::DATA_GAS_PER_BLOB, eip7702::SignedAuthorization}; use alloy_primitives::{Address, Bytes, ChainId, Signature, TxKind, B256, U256}; -use alloy_rlp::{Buf, BufMut, Decodable, Encodable, Header}; +use alloy_rlp::{BufMut, Decodable, Encodable, Header}; use core::mem; #[doc(inline)] @@ -290,22 +290,17 @@ impl RlpEcdsaTx for TxEip4844Variant { } fn rlp_decode(buf: &mut &[u8]) -> alloy_rlp::Result { - let needle = &mut &**buf; - let header = Header::decode(needle)?; + let header = Header::decode(buf)?; if !header.list { return Err(alloy_rlp::Error::UnexpectedString); } - let remaining_len = needle.len(); - if header.payload_length > remaining_len { - return Err(alloy_rlp::Error::InputTooShort); - } + let remaining = buf.len(); + + let res = Self::rlp_decode_fields(buf)?; - let chunk = &mut &buf[..header.length_with_payload()]; - let res = Self::rlp_decode_fields(chunk)?; - if !chunk.is_empty() { + if buf.len() + header.payload_length != remaining { return Err(alloy_rlp::Error::UnexpectedLength); } - buf.advance(header.length_with_payload()); Ok(res) } @@ -850,6 +845,12 @@ impl RlpEcdsaTx for TxEip4844WithSidecar { self.sidecar.rlp_encode_fields(out); } + fn rlp_header_signed(&self, signature: &Signature) -> Header { + let payload_length = self.tx.rlp_encoded_length_with_signature(signature) + + self.sidecar.rlp_encoded_fields_length(); + Header { list: true, payload_length } + } + fn rlp_encode_signed(&self, signature: &Signature, out: &mut dyn BufMut) { self.rlp_header_signed(signature).encode(out); self.tx.rlp_encode_signed(signature, out); @@ -867,20 +868,14 @@ impl RlpEcdsaTx for TxEip4844WithSidecar { if !header.list { return Err(alloy_rlp::Error::UnexpectedString); } - let remaining_len = buf.len(); - if header.payload_length > remaining_len { - return Err(alloy_rlp::Error::InputTooShort); - } + let remaining = buf.len(); - let chunk = &mut &buf[..remaining_len]; - let (tx, signature) = TxEip4844::rlp_decode_with_signature(chunk)?; - let sidecar = BlobTransactionSidecar::rlp_decode_fields(chunk)?; + let (tx, signature) = TxEip4844::rlp_decode_with_signature(buf)?; + let sidecar = BlobTransactionSidecar::rlp_decode_fields(buf)?; - // Decoding did not consume the entire payload specified by the header - if !chunk.is_empty() { + if buf.len() + header.payload_length != remaining { return Err(alloy_rlp::Error::UnexpectedLength); } - buf.advance(header.payload_length); Ok((Self { tx, sidecar }, signature)) } diff --git a/crates/consensus/src/transaction/rlp.rs b/crates/consensus/src/transaction/rlp.rs index 37eba755c82..444bf8a46a7 100644 --- a/crates/consensus/src/transaction/rlp.rs +++ b/crates/consensus/src/transaction/rlp.rs @@ -110,13 +110,19 @@ pub trait RlpEcdsaTx: SignableTransaction + Sized { if !header.list { return Err(alloy_rlp::Error::UnexpectedString); } - let remaining_len = buf.len(); + let remaining = buf.len(); - if header.payload_length > remaining_len { + if header.payload_length > remaining { return Err(alloy_rlp::Error::InputTooShort); } - Self::rlp_decode_fields(buf) + let this = Self::rlp_decode_fields(buf)?; + + if buf.len() + header.payload_length != remaining { + return Err(alloy_rlp::Error::UnexpectedLength); + } + + Ok(this) } /// Decodes the transaction from RLP bytes, including the signature. @@ -180,7 +186,15 @@ pub trait RlpEcdsaTx: SignableTransaction + Sized { if header.list { return Err(alloy_rlp::Error::UnexpectedList.into()); } - Self::eip2718_decode_with_type(buf, ty) + + let remaining = buf.len(); + let res = Self::eip2718_decode_with_type(buf, ty)?; + + if buf.len() + header.payload_length != remaining { + return Err(alloy_rlp::Error::UnexpectedLength.into()); + } + + Ok(res) } /// Decodes the transaction from network bytes, expecting the default type diff --git a/crates/eips/src/eip4844/sidecar.rs b/crates/eips/src/eip4844/sidecar.rs index 62d778810e3..2204c077f80 100644 --- a/crates/eips/src/eip4844/sidecar.rs +++ b/crates/eips/src/eip4844/sidecar.rs @@ -363,7 +363,14 @@ impl BlobTransactionSidecar { if buf.len() < header.payload_length { return Err(alloy_rlp::Error::InputTooShort); } - Self::rlp_decode_fields(buf) + let remaining = buf.len(); + let this = Self::rlp_decode_fields(buf)?; + + if buf.len() + header.payload_length != remaining { + return Err(alloy_rlp::Error::UnexpectedLength); + } + + Ok(this) } } diff --git a/crates/rpc-types-trace/src/otterscan.rs b/crates/rpc-types-trace/src/otterscan.rs index b1b2eba40a1..11938afae01 100644 --- a/crates/rpc-types-trace/src/otterscan.rs +++ b/crates/rpc-types-trace/src/otterscan.rs @@ -105,17 +105,17 @@ pub struct InternalIssuance { /// Custom `Block` struct that includes transaction count for Otterscan responses #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct OtsBlock { +pub struct OtsBlock { /// The block information. #[serde(flatten)] - pub block: Block, + pub block: Block, /// The number of transactions in the block. #[doc(alias = "tx_count")] pub transaction_count: usize, } -impl From> for OtsBlock { - fn from(block: Block) -> Self { +impl From> for OtsBlock { + fn from(block: Block) -> Self { Self { transaction_count: block.transactions.len(), block } } } @@ -215,9 +215,9 @@ pub struct OtsReceipt { /// Custom struct for otterscan `getBlockTransactions` RPC response #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct OtsBlockTransactions { +pub struct OtsBlockTransactions { /// The full block information with transaction count. - pub fullblock: OtsBlock, + pub fullblock: OtsBlock, /// The list of transaction receipts. pub receipts: Vec, }