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" metastruct = "0.1.0"
milhouse = { workspace = true } milhouse = { workspace = true }
parking_lot = { workspace = true } parking_lot = { workspace = true }
paste = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
rand_xorshift = { workspace = true } rand_xorshift = { workspace = true }
rayon = { workspace = true } rayon = { workspace = true }
@@ -67,7 +68,6 @@ yaml_serde = { workspace = true }
[dev-dependencies] [dev-dependencies]
beacon_chain = { workspace = true } beacon_chain = { workspace = true }
criterion = { workspace = true } criterion = { workspace = true }
paste = { workspace = true }
state_processing = { workspace = true } state_processing = { workspace = true }
tokio = { workspace = true } tokio = { workspace = true }
types = { path = ".", features = ["arbitrary"] } 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. // 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 macro_rules! impl_into_full_block {
// the first fork after Bellatrix. ($fork:ident, [ $($extra_field:ident),* $(,)? ]) => {
impl<E: EthSpec> SignedBeaconBlockBellatrix<E, BlindedPayload<E>> { paste::paste! {
pub fn into_full_block( impl<E: EthSpec> [<SignedBeaconBlock $fork>]<E, BlindedPayload<E>> {
self, pub fn into_full_block(
execution_payload: ExecutionPayloadBellatrix<E>, self,
) -> SignedBeaconBlockBellatrix<E, FullPayload<E>> { execution_payload: [<ExecutionPayload $fork>]<E>,
let SignedBeaconBlockBellatrix { ) -> [<SignedBeaconBlock $fork>]<E, FullPayload<E>> {
message: let [<SignedBeaconBlock $fork>] {
BeaconBlockBellatrix { message:
slot, [<BeaconBlock $fork>] {
proposer_index, slot,
parent_root, proposer_index,
state_root, parent_root,
body: state_root,
BeaconBlockBodyBellatrix { body:
randao_reveal, [<BeaconBlockBody $fork>] {
eth1_data, randao_reveal,
graffiti, eth1_data,
proposer_slashings, graffiti,
attester_slashings, proposer_slashings,
attestations, attester_slashings,
deposits, attestations,
voluntary_exits, deposits,
sync_aggregate, voluntary_exits,
execution_payload: BlindedPayloadBellatrix { .. }, 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,
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,
} }
} };
} }
impl<E: EthSpec> SignedBeaconBlockCapella<E, BlindedPayload<E>> { impl_into_full_block!(Bellatrix, []);
pub fn into_full_block( impl_into_full_block!(Capella, [bls_to_execution_changes]);
self, impl_into_full_block!(Deneb, [bls_to_execution_changes, blob_kzg_commitments]);
execution_payload: ExecutionPayloadCapella<E>, impl_into_full_block!(
) -> SignedBeaconBlockCapella<E, FullPayload<E>> { Electra,
let SignedBeaconBlockCapella { [
message: bls_to_execution_changes,
BeaconBlockCapella { blob_kzg_commitments,
slot, execution_requests
proposer_index, ]
parent_root, );
state_root, impl_into_full_block!(
body: Fulu,
BeaconBlockBodyCapella { [
randao_reveal, bls_to_execution_changes,
eth1_data, blob_kzg_commitments,
graffiti, execution_requests
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,
}
}
}
// We can convert gloas blocks without payloads into blocks "with" payloads. // 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 // TODO(EIP-7732) Look into whether we can remove this in the future since no blinded blocks post-gloas