diff --git a/.github/workflows/ci_l1.yaml b/.github/workflows/ci_l1.yaml index 264f40824b..feeee92baa 100644 --- a/.github/workflows/ci_l1.yaml +++ b/.github/workflows/ci_l1.yaml @@ -75,7 +75,7 @@ jobs: - name: Run tests run: | make test - + docker_build: # "Build Docker" is a required check, don't change the name name: Build Docker @@ -163,7 +163,7 @@ jobs: test_pattern: engine-(auth|exchange-capabilities)/ - name: "Cancun Engine tests" simulation: ethereum/engine - test_pattern: "engine-cancun/Blob Transactions On Block 1|Blob Transaction Ordering, Single|Blob Transaction Ordering, Multiple Accounts|Replace Blob Transactions|Parallel Blob Transactions|ForkchoiceUpdated|GetPayload|NewPayloadV3 After Cancun|NewPayloadV3 Before Cancun|NewPayloadV3 Versioned Hashes|Incorrect BlobGasUsed|Bad Hash|ParentHash equals BlockHash|RPC:|in ForkchoiceState|Unknown|Invalid PayloadAttributes|Unique|Re-Execute Payload|In-Order Consecutive Payload|Multiple New Payloads|Valid NewPayload->|NewPayload with|Payload Build after|Build Payload with|Invalid Missing Ancestor ReOrg, StateRoot|Re-Org Back to|Re-org to Previously|Safe Re-Org to Side Chain|Transaction Re-Org, Re-Org Back In|Re-Org Back into Canonical Chain, Depth=5|Suggested Fee Recipient Test|PrevRandao Opcode|Invalid NewPayload, [^R][^e]|Fork ID: Genesis=0, Cancun=0|Fork ID: Genesis=0, Cancun=1|Fork ID: Genesis=0, Cancun=2 |Fork ID: Genesis=0, Cancun=2, BlocksBeforePeering=1|Fork ID: Genesis=0, Cancun=2, Shanghai=[^2]|Fork ID Genesis=1, Cancun=2, Shanghai=2" + test_pattern: "engine-cancun/Blob Transactions On Block 1|Blob Transaction Ordering, Single|Blob Transaction Ordering, Multiple Accounts|Replace Blob Transactions|Parallel Blob Transactions|ForkchoiceUpdated|GetPayload|NewPayloadV3 After Cancun|NewPayloadV3 Before Cancun|NewPayloadV3 Versioned Hashes|Incorrect BlobGasUsed|Bad Hash|ParentHash equals BlockHash|RPC:|in ForkchoiceState|Unknown|Invalid PayloadAttributes|Unique|Re-Execute Payload|In-Order Consecutive Payload|Multiple New Payloads|Valid NewPayload->|NewPayload with|Payload Build after|Build Payload with|Invalid Missing Ancestor ReOrg, StateRoot|Re-Org Back to|Re-org to Previously|Safe Re-Org to Side Chain|Transaction Re-Org, Re-Org Back In|Re-Org Back into Canonical Chain, Depth=5|Suggested Fee Recipient Test|PrevRandao Opcode|Invalid NewPayload|Fork ID: Genesis=0, Cancun=0|Fork ID: Genesis=0, Cancun=1|Fork ID: Genesis=0, Cancun=2 |Fork ID: Genesis=0, Cancun=2, BlocksBeforePeering=1|Fork ID: Genesis=0, Cancun=2, Shanghai=[^2]|Fork ID Genesis=1, Cancun=2, Shanghai=2" steps: - name: Download artifacts uses: actions/download-artifact@v4 @@ -198,7 +198,7 @@ jobs: name: Integration Test runs-on: ubuntu-latest needs: [run-assertoor, run-hive] - # Make sure this job runs even if the previous jobs failed or were skipped + # Make sure this job runs even if the previous jobs failed or were skipped if: ${{ always() && needs.run-assertoor.result != 'skipped' && needs.run-hive.result != 'skipped' }} steps: - name: Check if any job failed diff --git a/crates/blockchain/blockchain.rs b/crates/blockchain/blockchain.rs index 27f0f968a6..451d2a949a 100644 --- a/crates/blockchain/blockchain.rs +++ b/crates/blockchain/blockchain.rs @@ -8,8 +8,9 @@ mod smoke_test; use constants::{GAS_PER_BLOB, MAX_BLOB_GAS_PER_BLOCK, MAX_BLOB_NUMBER_PER_BLOCK}; use error::{ChainError, InvalidBlockError}; use ethrex_core::types::{ - validate_block_header, validate_cancun_header_fields, validate_no_cancun_header_fields, Block, - BlockHash, BlockHeader, BlockNumber, EIP4844Transaction, Receipt, Transaction, + compute_receipts_root, validate_block_header, validate_cancun_header_fields, + validate_no_cancun_header_fields, Block, BlockHash, BlockHeader, BlockNumber, + EIP4844Transaction, Receipt, Transaction, }; use ethrex_core::H256; @@ -58,6 +59,9 @@ pub fn add_block(block: &Block, storage: &Store) -> Result<(), ChainError> { // Check state root matches the one in block header after execution validate_state_root(&block.header, new_state_root)?; + // Check receipts root matches the one in block header after execution + validate_receipts_root(&block.header, &receipts)?; + store_block(storage, block.clone())?; store_receipts(storage, receipts, block_hash)?; @@ -101,6 +105,9 @@ pub fn add_block(block: &Block, storage: &Store) -> Result<(), ChainError> { // Check state root matches the one in block header after execution validate_state_root(&block.header, new_state_root)?; + // Check receipts root matches the one in block header after execution + validate_receipts_root(&block.header, &receipts)?; + store_block(storage, block.clone())?; store_receipts(storage, receipts, block_hash)?; @@ -137,6 +144,21 @@ pub fn validate_state_root( } } +pub fn validate_receipts_root( + block_header: &BlockHeader, + receipts: &[Receipt], +) -> Result<(), ChainError> { + let receipts_root = compute_receipts_root(receipts); + + if receipts_root == block_header.receipts_root { + Ok(()) + } else { + Err(ChainError::InvalidBlock( + InvalidBlockError::ReceiptsRootMismatch, + )) + } +} + // Returns the hash of the head of the canonical chain (the latest valid hash). pub fn latest_canonical_block_hash(storage: &Store) -> Result { if let Some(latest_block_number) = storage.get_latest_block_number()? { diff --git a/crates/blockchain/error.rs b/crates/blockchain/error.rs index 8a16ab224c..05ef4ce457 100644 --- a/crates/blockchain/error.rs +++ b/crates/blockchain/error.rs @@ -22,6 +22,8 @@ pub enum ChainError { pub enum InvalidBlockError { #[error("World State Root does not match the one in the header after executing")] StateRootMismatch, + #[error("Receipts Root does not match the one in the header after executing")] + ReceiptsRootMismatch, #[error("Invalid Header, validation failed pre-execution: {0}")] InvalidHeader(#[from] InvalidBlockHeaderError), #[error("Exceeded MAX_BLOB_GAS_PER_BLOCK")]