Add macro to simplify into_full_block implementations (#9294)

Use a macro to remove the repetitive fork variant boilerplate in `signed_beacon_block.rs` when implementing `into_full_block` for the various `SignedBeaconBlock` variants


Co-Authored-By: Mac L <mjladson@pm.me>
This commit is contained in:
Mac L
2026-05-25 05:29:34 +04:00
committed by GitHub
parent b9a68ad2c6
commit 89ee020330
2 changed files with 76 additions and 276 deletions

View File

@@ -44,6 +44,7 @@ merkle_proof = { workspace = true }
metastruct = "0.1.0"
milhouse = { workspace = true }
parking_lot = { workspace = true }
paste = { workspace = true }
rand = { workspace = true }
rand_xorshift = { workspace = true }
rayon = { workspace = true }
@@ -67,7 +68,6 @@ yaml_serde = { workspace = true }
[dev-dependencies]
beacon_chain = { workspace = true }
criterion = { workspace = true }
paste = { workspace = true }
state_processing = { workspace = true }
tokio = { workspace = true }
types = { path = ".", features = ["arbitrary"] }

View File

@@ -433,285 +433,85 @@ impl<E: EthSpec> From<SignedBeaconBlockAltair<E, BlindedPayload<E>>>
}
// Post-Bellatrix blocks can be "unblinded" by adding the full payload.
// NOTE: It might be nice to come up with a `superstruct` pattern to abstract over this before
// the first fork after Bellatrix.
impl<E: EthSpec> SignedBeaconBlockBellatrix<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadBellatrix<E>,
) -> SignedBeaconBlockBellatrix<E, FullPayload<E>> {
let SignedBeaconBlockBellatrix {
message:
BeaconBlockBellatrix {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyBellatrix {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadBellatrix { .. },
macro_rules! impl_into_full_block {
($fork:ident, [ $($extra_field:ident),* $(,)? ]) => {
paste::paste! {
impl<E: EthSpec> [<SignedBeaconBlock $fork>]<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: [<ExecutionPayload $fork>]<E>,
) -> [<SignedBeaconBlock $fork>]<E, FullPayload<E>> {
let [<SignedBeaconBlock $fork>] {
message:
[<BeaconBlock $fork>] {
slot,
proposer_index,
parent_root,
state_root,
body:
[<BeaconBlockBody $fork>] {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: [<BlindedPayload $fork>] { .. },
$($extra_field,)*
},
},
signature,
} = self;
[<SignedBeaconBlock $fork>] {
message: [<BeaconBlock $fork>] {
slot,
proposer_index,
parent_root,
state_root,
body: [<BeaconBlockBody $fork>] {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: [<FullPayload $fork>] { execution_payload },
$($extra_field,)*
},
},
},
signature,
} = self;
SignedBeaconBlockBellatrix {
message: BeaconBlockBellatrix {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyBellatrix {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadBellatrix { execution_payload },
},
},
signature,
signature,
}
}
}
}
}
};
}
impl<E: EthSpec> SignedBeaconBlockCapella<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadCapella<E>,
) -> SignedBeaconBlockCapella<E, FullPayload<E>> {
let SignedBeaconBlockCapella {
message:
BeaconBlockCapella {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadCapella { .. },
bls_to_execution_changes,
},
},
signature,
} = self;
SignedBeaconBlockCapella {
message: BeaconBlockCapella {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadCapella { execution_payload },
bls_to_execution_changes,
},
},
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlockDeneb<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadDeneb<E>,
) -> SignedBeaconBlockDeneb<E, FullPayload<E>> {
let SignedBeaconBlockDeneb {
message:
BeaconBlockDeneb {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyDeneb {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadDeneb { .. },
bls_to_execution_changes,
blob_kzg_commitments,
},
},
signature,
} = self;
SignedBeaconBlockDeneb {
message: BeaconBlockDeneb {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyDeneb {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadDeneb { execution_payload },
bls_to_execution_changes,
blob_kzg_commitments,
},
},
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlockElectra<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadElectra<E>,
) -> SignedBeaconBlockElectra<E, FullPayload<E>> {
let SignedBeaconBlockElectra {
message:
BeaconBlockElectra {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyElectra {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadElectra { .. },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
} = self;
SignedBeaconBlockElectra {
message: BeaconBlockElectra {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyElectra {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadElectra { execution_payload },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlockFulu<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadFulu<E>,
) -> SignedBeaconBlockFulu<E, FullPayload<E>> {
let SignedBeaconBlockFulu {
message:
BeaconBlockFulu {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyFulu {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadFulu { .. },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
} = self;
SignedBeaconBlockFulu {
message: BeaconBlockFulu {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyFulu {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadFulu { execution_payload },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
}
}
}
impl_into_full_block!(Bellatrix, []);
impl_into_full_block!(Capella, [bls_to_execution_changes]);
impl_into_full_block!(Deneb, [bls_to_execution_changes, blob_kzg_commitments]);
impl_into_full_block!(
Electra,
[
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests
]
);
impl_into_full_block!(
Fulu,
[
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests
]
);
// We can convert gloas blocks without payloads into blocks "with" payloads.
// TODO(EIP-7732) Look into whether we can remove this in the future since no blinded blocks post-gloas