Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
19 changes: 18 additions & 1 deletion crates/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ use ethrex_common::types::{
};
use ethrex_common::types::{ELASTICITY_MULTIPLIER, P2PTransaction};
use ethrex_common::types::{Fork, MempoolTransaction};
use ethrex_common::types::{MAX_BLOB_TX_SIZE, MAX_TX_SIZE};
use ethrex_common::utils::keccak;
use ethrex_common::{Address, H256, TrieLogger, U256};
pub use ethrex_common::{
Expand Down Expand Up @@ -2432,7 +2433,23 @@ impl Blockchain {
.ok_or(MempoolError::NoBlockHeaderError)?;
let config = self.storage.get_chain_config();

// NOTE: We could add a tx size limit here, but it's not in the actual spec
// Wire size cap: peer-policy default, not consensus. Matches geth
// `txMaxSize` (legacypool / blobpool), reth `DEFAULT_MAX_TX_INPUT_BYTES`,
// nethermind `MaxTxSize` / `MaxBlobTxSize`. For EIP-4844 the canonical
// encoding of `Transaction` excludes the sidecar (which lives in the
// adjacent `BlobsBundle`), so this caps the core tx only.
let encoded_len = tx.encode_canonical_to_vec().len();
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to find another way to compute this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let size_limit = if matches!(tx, Transaction::EIP4844Transaction(_)) {
MAX_BLOB_TX_SIZE
} else {
MAX_TX_SIZE
};
if encoded_len > size_limit {
return Err(MempoolError::TxSizeExceeded {
actual: encoded_len,
limit: size_limit,
});
}

// Check init code size
// [EIP-7954] - Amsterdam increases the limit
Expand Down
2 changes: 2 additions & 0 deletions crates/blockchain/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ pub enum MempoolError {
TxMaxInitCodeSizeError,
#[error("Transaction max data size exceeded")]
TxMaxDataSizeError,
#[error("Transaction encoded size ({actual} bytes) exceeds the {limit}-byte limit")]
TxSizeExceeded { actual: usize, limit: usize },
#[error("Transaction gas limit exceeded")]
TxGasLimitExceededError,
#[error(
Expand Down
10 changes: 10 additions & 0 deletions crates/common/types/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,13 @@ pub const FIELD_ELEMENTS_PER_EXT_BLOB: usize = 2 * FIELD_ELEMENTS_PER_BLOB;
pub const FIELD_ELEMENTS_PER_CELL: usize = 64;
pub const BYTES_PER_CELL: usize = FIELD_ELEMENTS_PER_CELL * BYTES_PER_FIELD_ELEMENT;
pub const CELLS_PER_EXT_BLOB: usize = FIELD_ELEMENTS_PER_EXT_BLOB / FIELD_ELEMENTS_PER_CELL;

// Mempool admission size caps — peer-policy defaults, not consensus.
// Matches geth `txMaxSize` (legacypool) and `txMaxSize` (blobpool), reth
// `DEFAULT_MAX_TX_INPUT_BYTES`, nethermind `MaxTxSize` / `MaxBlobTxSize`.
/// Maximum RLP-encoded wire size for a non-blob transaction (128 KiB).
pub const MAX_TX_SIZE: usize = 131_072;
/// Maximum RLP-encoded core size for an EIP-4844 blob transaction (1 MiB),
/// excluding the blob sidecar. Sidecar size is bounded separately by the
/// per-blob byte count and the fork's max blob count.
pub const MAX_BLOB_TX_SIZE: usize = 1_048_576;
27 changes: 27 additions & 0 deletions crates/common/types/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3764,4 +3764,31 @@ mod tests {
"blob-gas term missing from cost_without_base_fee() for EIP-4844"
);
}

#[test]
fn test_encoded_size_exceeds_max_tx_size() {
// Confirms the wire-size signal used by the mempool admission cap:
// an EIP-1559 tx with > 128 KiB of `data` encodes to > MAX_TX_SIZE bytes.
use crate::types::MAX_TX_SIZE;

let payload = vec![0u8; MAX_TX_SIZE + 1];
let tx = Transaction::EIP1559Transaction(EIP1559Transaction {
data: Bytes::from(payload),
..Default::default()
});

assert!(
tx.encode_canonical_to_vec().len() > MAX_TX_SIZE,
"tx with > 128 KiB calldata must encode larger than MAX_TX_SIZE"
);
Comment thread
MegaRedHand marked this conversation as resolved.
Outdated
}

#[test]
fn test_encoded_size_below_max_tx_size() {
// A small tx encodes well below the cap.
use crate::types::MAX_TX_SIZE;

let tx = Transaction::EIP1559Transaction(EIP1559Transaction::default());
assert!(tx.encode_canonical_to_vec().len() <= MAX_TX_SIZE);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No test for the MAX_BLOB_TX_SIZE cap

Both new tests exercise MAX_TX_SIZE via EIP-1559 transactions, but there is no corresponding test that constructs an EIP4844Transaction with an encoded size just over MAX_BLOB_TX_SIZE (1 MiB) and verifies the signal fires. The blob tx branch in validate_transaction is the riskier path (1 MiB limit vs 128 KiB), so a parallel "exceeds / below" pair for blob txs would meaningfully close the coverage gap.

Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/common/types/transaction.rs
Line: 3786-3793

Comment:
**No test for the `MAX_BLOB_TX_SIZE` cap**

Both new tests exercise `MAX_TX_SIZE` via EIP-1559 transactions, but there is no corresponding test that constructs an `EIP4844Transaction` with an encoded size just over `MAX_BLOB_TX_SIZE` (1 MiB) and verifies the signal fires. The blob tx branch in `validate_transaction` is the riskier path (1 MiB limit vs 128 KiB), so a parallel "exceeds / below" pair for blob txs would meaningfully close the coverage gap.

How can I resolve this? If you propose a fix, please make it concise.

}
Loading