Skip to main content

reth_payload_validator/
amsterdam.rs

1//! Amsterdam rules for new payloads.
2
3use alloy_consensus::BlockHeader;
4use alloy_rpc_types_engine::PayloadError;
5use reth_primitives_traits::{Block, SealedBlock};
6
7/// Checks that Amsterdam header fields are present if Amsterdam is active and absent otherwise.
8#[inline]
9pub fn ensure_well_formed_fields<T: Block>(
10    block: &SealedBlock<T>,
11    is_amsterdam_active: bool,
12) -> Result<(), PayloadError> {
13    if is_amsterdam_active {
14        if block.block_access_list_hash().is_none() {
15            return Err(PayloadError::PostAmsterdamBlockWithoutBlockAccessList)
16        }
17        if block.slot_number().is_none() {
18            return Err(PayloadError::PostAmsterdamBlockWithoutSlotNumber)
19        }
20    } else {
21        if block.block_access_list_hash().is_some() {
22            return Err(PayloadError::PreAmsterdamBlockWithBlockAccessList)
23        }
24        if block.slot_number().is_some() {
25            return Err(PayloadError::PreAmsterdamBlockWithSlotNumber)
26        }
27    }
28
29    Ok(())
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35    use alloy_consensus::{Block as AlloyBlock, Header, TxEnvelope};
36
37    fn block(
38        has_block_access_list: bool,
39        has_slot_number: bool,
40    ) -> SealedBlock<AlloyBlock<TxEnvelope>> {
41        let header = Header {
42            block_access_list_hash: has_block_access_list.then_some(Default::default()),
43            slot_number: has_slot_number.then_some(0),
44            ..Default::default()
45        };
46        AlloyBlock { header, body: Default::default() }.seal_slow()
47    }
48
49    #[test]
50    fn validates_amsterdam_fields() {
51        assert!(ensure_well_formed_fields(&block(true, true), true).is_ok());
52        assert!(ensure_well_formed_fields(&block(false, false), false).is_ok());
53
54        assert!(matches!(
55            ensure_well_formed_fields(&block(false, true), true),
56            Err(PayloadError::PostAmsterdamBlockWithoutBlockAccessList)
57        ));
58        assert!(matches!(
59            ensure_well_formed_fields(&block(true, false), true),
60            Err(PayloadError::PostAmsterdamBlockWithoutSlotNumber)
61        ));
62        assert!(matches!(
63            ensure_well_formed_fields(&block(true, false), false),
64            Err(PayloadError::PreAmsterdamBlockWithBlockAccessList)
65        ));
66        assert!(matches!(
67            ensure_well_formed_fields(&block(false, true), false),
68            Err(PayloadError::PreAmsterdamBlockWithSlotNumber)
69        ));
70    }
71}