From 193bcd8d8d204e89e74b25a51b395cbb5e8087e4 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 31 Oct 2024 00:20:59 +0400 Subject: [PATCH 1/3] fix: add more rlp correctness checks (#1595) --- crates/consensus/src/transaction/rlp.rs | 22 ++++++++++++++++++---- crates/eips/src/eip4844/sidecar.rs | 9 ++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/crates/consensus/src/transaction/rlp.rs b/crates/consensus/src/transaction/rlp.rs index 4c3a651f958..b3656696867 100644 --- a/crates/consensus/src/transaction/rlp.rs +++ b/crates/consensus/src/transaction/rlp.rs @@ -109,13 +109,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. @@ -185,7 +191,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) } } From 408770d88b0779c7b000e05b30d959442196c97e Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 31 Oct 2024 12:09:50 +0400 Subject: [PATCH 2/3] fix: RLP for `TxEip4844` (#1596) * fix: rlp for eip4844 * rlp_header_signed --- crates/consensus/src/transaction/eip4844.rs | 37 +++++++++------------ 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/crates/consensus/src/transaction/eip4844.rs b/crates/consensus/src/transaction/eip4844.rs index 9bbfba7d631..52dd343d6ef 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) } @@ -864,6 +859,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); @@ -881,20 +882,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)) } From 273d7849790106bb17f134a56d9725e6e3944f50 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 31 Oct 2024 12:10:12 +0400 Subject: [PATCH 3/3] feat: make more Otterscan types generic over header (#1594) --- crates/rpc-types-trace/src/otterscan.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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, }