mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 11:41:51 +00:00
Add Gloas boilerplate (#7728)
Adds the required boilerplate code for the Gloas (Glamsterdam) hard fork. This allows PRs testing Gloas-candidate features to test fork transition. This also includes de-duplication of post-Bellatrix readiness notifiers from #6797 (credit to @dapplion)
This commit is contained in:
@@ -16,7 +16,7 @@ use self::indexed_attestation::IndexedAttestationBase;
|
||||
|
||||
/// A block of the `BeaconChain`.
|
||||
#[superstruct(
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -82,6 +82,8 @@ pub struct BeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E> = FullPayload
|
||||
pub body: BeaconBlockBodyElectra<E, Payload>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "body_fulu"))]
|
||||
pub body: BeaconBlockBodyFulu<E, Payload>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "body_gloas"))]
|
||||
pub body: BeaconBlockBodyGloas<E, Payload>,
|
||||
}
|
||||
|
||||
pub type BlindedBeaconBlock<E> = BeaconBlock<E, BlindedPayload<E>>;
|
||||
@@ -134,8 +136,9 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlock<E, Payload> {
|
||||
/// Usually it's better to prefer `from_ssz_bytes` which will decode the correct variant based
|
||||
/// on the fork slot.
|
||||
pub fn any_from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
|
||||
BeaconBlockFulu::from_ssz_bytes(bytes)
|
||||
.map(BeaconBlock::Fulu)
|
||||
BeaconBlockGloas::from_ssz_bytes(bytes)
|
||||
.map(BeaconBlock::Gloas)
|
||||
.or_else(|_| BeaconBlockFulu::from_ssz_bytes(bytes).map(BeaconBlock::Fulu))
|
||||
.or_else(|_| BeaconBlockElectra::from_ssz_bytes(bytes).map(BeaconBlock::Electra))
|
||||
.or_else(|_| BeaconBlockDeneb::from_ssz_bytes(bytes).map(BeaconBlock::Deneb))
|
||||
.or_else(|_| BeaconBlockCapella::from_ssz_bytes(bytes).map(BeaconBlock::Capella))
|
||||
@@ -235,6 +238,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockRef<'a, E, Payl
|
||||
BeaconBlockRef::Deneb { .. } => ForkName::Deneb,
|
||||
BeaconBlockRef::Electra { .. } => ForkName::Electra,
|
||||
BeaconBlockRef::Fulu { .. } => ForkName::Fulu,
|
||||
BeaconBlockRef::Gloas { .. } => ForkName::Gloas,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,6 +650,37 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockFulu
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockGloas<E, Payload> {
|
||||
/// Returns an empty Gloas block to be used during genesis.
|
||||
fn empty(spec: &ChainSpec) -> Self {
|
||||
BeaconBlockGloas {
|
||||
slot: spec.genesis_slot,
|
||||
proposer_index: 0,
|
||||
parent_root: Hash256::zero(),
|
||||
state_root: Hash256::zero(),
|
||||
body: BeaconBlockBodyGloas {
|
||||
randao_reveal: Signature::empty(),
|
||||
eth1_data: Eth1Data {
|
||||
deposit_root: Hash256::zero(),
|
||||
block_hash: Hash256::zero(),
|
||||
deposit_count: 0,
|
||||
},
|
||||
graffiti: Graffiti::default(),
|
||||
proposer_slashings: VariableList::empty(),
|
||||
attester_slashings: VariableList::empty(),
|
||||
attestations: VariableList::empty(),
|
||||
deposits: VariableList::empty(),
|
||||
voluntary_exits: VariableList::empty(),
|
||||
sync_aggregate: SyncAggregate::empty(),
|
||||
execution_payload: Payload::Gloas::default(),
|
||||
bls_to_execution_changes: VariableList::empty(),
|
||||
blob_kzg_commitments: VariableList::empty(),
|
||||
execution_requests: ExecutionRequests::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can convert pre-Bellatrix blocks without payloads into blocks "with" payloads.
|
||||
impl<E: EthSpec> From<BeaconBlockBase<E, BlindedPayload<E>>>
|
||||
for BeaconBlockBase<E, FullPayload<E>>
|
||||
@@ -728,6 +763,7 @@ impl_from!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |bod
|
||||
impl_from!(BeaconBlockDeneb, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyDeneb<_, _>| body.into());
|
||||
impl_from!(BeaconBlockElectra, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyElectra<_, _>| body.into());
|
||||
impl_from!(BeaconBlockFulu, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyFulu<_, _>| body.into());
|
||||
impl_from!(BeaconBlockGloas, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyGloas<_, _>| body.into());
|
||||
|
||||
// We can clone blocks with payloads to blocks without payloads, without cloning the payload.
|
||||
macro_rules! impl_clone_as_blinded {
|
||||
@@ -762,6 +798,7 @@ impl_clone_as_blinded!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPaylo
|
||||
impl_clone_as_blinded!(BeaconBlockDeneb, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
|
||||
impl_clone_as_blinded!(BeaconBlockElectra, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
|
||||
impl_clone_as_blinded!(BeaconBlockFulu, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
|
||||
impl_clone_as_blinded!(BeaconBlockGloas, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
|
||||
|
||||
// A reference to a full beacon block can be cloned into a blinded beacon block, without cloning the
|
||||
// execution payload.
|
||||
@@ -950,6 +987,26 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrip_gloas_block() {
|
||||
let rng = &mut XorShiftRng::from_seed([42; 16]);
|
||||
let spec = &ForkName::Gloas.make_genesis_spec(MainnetEthSpec::default_spec());
|
||||
|
||||
let inner_block = BeaconBlockGloas {
|
||||
slot: Slot::random_for_test(rng),
|
||||
proposer_index: u64::random_for_test(rng),
|
||||
parent_root: Hash256::random_for_test(rng),
|
||||
state_root: Hash256::random_for_test(rng),
|
||||
body: BeaconBlockBodyGloas::random_for_test(rng),
|
||||
};
|
||||
|
||||
let block = BeaconBlock::Gloas(inner_block.clone());
|
||||
|
||||
test_ssz_tree_hash_pair_with(&block, &inner_block, |bytes| {
|
||||
BeaconBlock::from_ssz_bytes(bytes, spec)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_base_and_altair() {
|
||||
type E = MainnetEthSpec;
|
||||
@@ -971,12 +1028,15 @@ mod tests {
|
||||
let electra_slot = electra_epoch.start_slot(E::slots_per_epoch());
|
||||
let fulu_epoch = electra_epoch + 1;
|
||||
let fulu_slot = fulu_epoch.start_slot(E::slots_per_epoch());
|
||||
let gloas_epoch = fulu_epoch + 1;
|
||||
let gloas_slot = gloas_epoch.start_slot(E::slots_per_epoch());
|
||||
|
||||
spec.altair_fork_epoch = Some(altair_epoch);
|
||||
spec.capella_fork_epoch = Some(capella_epoch);
|
||||
spec.deneb_fork_epoch = Some(deneb_epoch);
|
||||
spec.electra_fork_epoch = Some(electra_epoch);
|
||||
spec.fulu_fork_epoch = Some(fulu_epoch);
|
||||
spec.gloas_fork_epoch = Some(gloas_epoch);
|
||||
|
||||
// BeaconBlockBase
|
||||
{
|
||||
@@ -1101,5 +1161,30 @@ mod tests {
|
||||
good_block
|
||||
);
|
||||
}
|
||||
|
||||
// BeaconBlockGloas
|
||||
{
|
||||
let good_block = BeaconBlock::Gloas(BeaconBlockGloas {
|
||||
slot: gloas_slot,
|
||||
..<_>::random_for_test(rng)
|
||||
});
|
||||
// It's invalid to have a Fulu block with a epoch lower than the fork epoch.
|
||||
let _bad_block = {
|
||||
let mut bad = good_block.clone();
|
||||
*bad.slot_mut() = fulu_slot;
|
||||
bad
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
BeaconBlock::from_ssz_bytes(&good_block.as_ssz_bytes(), &spec)
|
||||
.expect("good gloas block can be decoded"),
|
||||
good_block
|
||||
);
|
||||
|
||||
// TODO(gloas): Uncomment once Gloas has features since without features
|
||||
// and with a Fulu slot it decodes successfully to Fulu.
|
||||
//BeaconBlock::from_ssz_bytes(&bad_block.as_ssz_bytes(), &spec)
|
||||
// .expect_err("bad gloas block cannot be decoded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
|
||||
///
|
||||
/// This *superstruct* abstracts over the hard-fork.
|
||||
#[superstruct(
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -60,7 +60,8 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
|
||||
Capella(metastruct(mappings(beacon_block_body_capella_fields(groups(fields))))),
|
||||
Deneb(metastruct(mappings(beacon_block_body_deneb_fields(groups(fields))))),
|
||||
Electra(metastruct(mappings(beacon_block_body_electra_fields(groups(fields))))),
|
||||
Fulu(metastruct(mappings(beacon_block_body_fulu_fields(groups(fields)))))
|
||||
Fulu(metastruct(mappings(beacon_block_body_fulu_fields(groups(fields))))),
|
||||
Gloas(metastruct(mappings(beacon_block_body_gloas_fields(groups(fields))))),
|
||||
),
|
||||
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
|
||||
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
|
||||
@@ -86,7 +87,7 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
|
||||
)]
|
||||
pub attester_slashings: VariableList<AttesterSlashingBase<E>, E::MaxAttesterSlashings>,
|
||||
#[superstruct(
|
||||
only(Electra, Fulu),
|
||||
only(Electra, Fulu, Gloas),
|
||||
partial_getter(rename = "attester_slashings_electra")
|
||||
)]
|
||||
pub attester_slashings:
|
||||
@@ -96,11 +97,14 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
|
||||
partial_getter(rename = "attestations_base")
|
||||
)]
|
||||
pub attestations: VariableList<AttestationBase<E>, E::MaxAttestations>,
|
||||
#[superstruct(only(Electra, Fulu), partial_getter(rename = "attestations_electra"))]
|
||||
#[superstruct(
|
||||
only(Electra, Fulu, Gloas),
|
||||
partial_getter(rename = "attestations_electra")
|
||||
)]
|
||||
pub attestations: VariableList<AttestationElectra<E>, E::MaxAttestationsElectra>,
|
||||
pub deposits: VariableList<Deposit, E::MaxDeposits>,
|
||||
pub voluntary_exits: VariableList<SignedVoluntaryExit, E::MaxVoluntaryExits>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
pub sync_aggregate: SyncAggregate<E>,
|
||||
// We flatten the execution payload so that serde can use the name of the inner type,
|
||||
// either `execution_payload` for full payloads, or `execution_payload_header` for blinded
|
||||
@@ -123,12 +127,15 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
|
||||
#[serde(flatten)]
|
||||
pub execution_payload: Payload::Fulu,
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
|
||||
#[serde(flatten)]
|
||||
pub execution_payload: Payload::Gloas,
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
pub bls_to_execution_changes:
|
||||
VariableList<SignedBlsToExecutionChange, E::MaxBlsToExecutionChanges>,
|
||||
#[superstruct(only(Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
|
||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas))]
|
||||
pub execution_requests: ExecutionRequests<E>,
|
||||
#[superstruct(only(Base, Altair))]
|
||||
#[metastruct(exclude_from(fields))]
|
||||
@@ -159,6 +166,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
Self::Deneb(body) => Ok(Payload::Ref::from(&body.execution_payload)),
|
||||
Self::Electra(body) => Ok(Payload::Ref::from(&body.execution_payload)),
|
||||
Self::Fulu(body) => Ok(Payload::Ref::from(&body.execution_payload)),
|
||||
Self::Gloas(body) => Ok(Payload::Ref::from(&body.execution_payload)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +201,10 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
beacon_block_body_fulu_fields!(body, |_, field| leaves
|
||||
.push(field.tree_hash_root()));
|
||||
}
|
||||
Self::Gloas(body) => {
|
||||
beacon_block_body_gloas_fields!(body, |_, field| leaves
|
||||
.push(field.tree_hash_root()));
|
||||
}
|
||||
}
|
||||
leaves
|
||||
}
|
||||
@@ -221,7 +233,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
Self::Base(_) | Self::Altair(_) | Self::Bellatrix(_) | Self::Capella(_) => {
|
||||
Err(Error::IncorrectStateVariant)
|
||||
}
|
||||
Self::Deneb(_) | Self::Electra(_) | Self::Fulu(_) => {
|
||||
Self::Deneb(_) | Self::Electra(_) | Self::Fulu(_) | Self::Gloas(_) => {
|
||||
// We compute the branches by generating 2 merkle trees:
|
||||
// 1. Merkle tree for the `blob_kzg_commitments` List object
|
||||
// 2. Merkle tree for the `BeaconBlockBody` container
|
||||
@@ -314,6 +326,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
Self::Deneb(body) => body.attestations.len(),
|
||||
Self::Electra(body) => body.attestations.len(),
|
||||
Self::Fulu(body) => body.attestations.len(),
|
||||
Self::Gloas(body) => body.attestations.len(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +339,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
Self::Deneb(body) => body.attester_slashings.len(),
|
||||
Self::Electra(body) => body.attester_slashings.len(),
|
||||
Self::Fulu(body) => body.attester_slashings.len(),
|
||||
Self::Gloas(body) => body.attester_slashings.len(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,6 +352,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
Self::Deneb(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
|
||||
Self::Electra(body) => Box::new(body.attestations.iter().map(AttestationRef::Electra)),
|
||||
Self::Fulu(body) => Box::new(body.attestations.iter().map(AttestationRef::Electra)),
|
||||
Self::Gloas(body) => Box::new(body.attestations.iter().map(AttestationRef::Electra)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,6 +393,11 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Electra),
|
||||
),
|
||||
Self::Gloas(body) => Box::new(
|
||||
body.attester_slashings
|
||||
.iter()
|
||||
.map(AttesterSlashingRef::Electra),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,6 +426,9 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRefMut<'a,
|
||||
Self::Fulu(body) => {
|
||||
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Electra))
|
||||
}
|
||||
Self::Gloas(body) => {
|
||||
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Electra))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,6 +444,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'_, E, Payl
|
||||
BeaconBlockBodyRef::Deneb { .. } => ForkName::Deneb,
|
||||
BeaconBlockBodyRef::Electra { .. } => ForkName::Electra,
|
||||
BeaconBlockBodyRef::Fulu { .. } => ForkName::Fulu,
|
||||
BeaconBlockBodyRef::Gloas { .. } => ForkName::Gloas,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -781,6 +805,52 @@ impl<E: EthSpec> From<BeaconBlockBodyFulu<E, FullPayload<E>>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BeaconBlockBodyGloas<E, FullPayload<E>>>
|
||||
for (
|
||||
BeaconBlockBodyGloas<E, BlindedPayload<E>>,
|
||||
Option<ExecutionPayloadGloas<E>>,
|
||||
)
|
||||
{
|
||||
fn from(body: BeaconBlockBodyGloas<E, FullPayload<E>>) -> Self {
|
||||
let BeaconBlockBodyGloas {
|
||||
randao_reveal,
|
||||
eth1_data,
|
||||
graffiti,
|
||||
proposer_slashings,
|
||||
attester_slashings,
|
||||
attestations,
|
||||
deposits,
|
||||
voluntary_exits,
|
||||
sync_aggregate,
|
||||
execution_payload: FullPayloadGloas { execution_payload },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
execution_requests,
|
||||
} = body;
|
||||
|
||||
(
|
||||
BeaconBlockBodyGloas {
|
||||
randao_reveal,
|
||||
eth1_data,
|
||||
graffiti,
|
||||
proposer_slashings,
|
||||
attester_slashings,
|
||||
attestations,
|
||||
deposits,
|
||||
voluntary_exits,
|
||||
sync_aggregate,
|
||||
execution_payload: BlindedPayloadGloas {
|
||||
execution_payload_header: From::from(&execution_payload),
|
||||
},
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments: blob_kzg_commitments.clone(),
|
||||
execution_requests,
|
||||
},
|
||||
Some(execution_payload),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// We can clone a full block into a blinded block, without cloning the payload.
|
||||
impl<E: EthSpec> BeaconBlockBodyBase<E, FullPayload<E>> {
|
||||
pub fn clone_as_blinded(&self) -> BeaconBlockBodyBase<E, BlindedPayload<E>> {
|
||||
@@ -974,6 +1044,44 @@ impl<E: EthSpec> BeaconBlockBodyFulu<E, FullPayload<E>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> BeaconBlockBodyGloas<E, FullPayload<E>> {
|
||||
pub fn clone_as_blinded(&self) -> BeaconBlockBodyGloas<E, BlindedPayload<E>> {
|
||||
let BeaconBlockBodyGloas {
|
||||
randao_reveal,
|
||||
eth1_data,
|
||||
graffiti,
|
||||
proposer_slashings,
|
||||
attester_slashings,
|
||||
attestations,
|
||||
deposits,
|
||||
voluntary_exits,
|
||||
sync_aggregate,
|
||||
execution_payload: FullPayloadGloas { execution_payload },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
execution_requests,
|
||||
} = self;
|
||||
|
||||
BeaconBlockBodyGloas {
|
||||
randao_reveal: randao_reveal.clone(),
|
||||
eth1_data: eth1_data.clone(),
|
||||
graffiti: *graffiti,
|
||||
proposer_slashings: proposer_slashings.clone(),
|
||||
attester_slashings: attester_slashings.clone(),
|
||||
attestations: attestations.clone(),
|
||||
deposits: deposits.clone(),
|
||||
voluntary_exits: voluntary_exits.clone(),
|
||||
sync_aggregate: sync_aggregate.clone(),
|
||||
execution_payload: BlindedPayloadGloas {
|
||||
execution_payload_header: execution_payload.into(),
|
||||
},
|
||||
bls_to_execution_changes: bls_to_execution_changes.clone(),
|
||||
blob_kzg_commitments: blob_kzg_commitments.clone(),
|
||||
execution_requests: execution_requests.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
|
||||
for (
|
||||
BeaconBlockBody<E, BlindedPayload<E>>,
|
||||
|
||||
@@ -229,7 +229,7 @@ impl From<BeaconStateHash> for Hash256 {
|
||||
///
|
||||
/// https://github.com/sigp/milhouse/issues/43
|
||||
#[superstruct(
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Derivative,
|
||||
@@ -349,6 +349,20 @@ impl From<BeaconStateHash> for Hash256 {
|
||||
groups(tree_lists)
|
||||
)),
|
||||
num_fields(all()),
|
||||
)),
|
||||
Gloas(metastruct(
|
||||
mappings(
|
||||
map_beacon_state_gloas_fields(),
|
||||
map_beacon_state_gloas_tree_list_fields(mutable, fallible, groups(tree_lists)),
|
||||
map_beacon_state_gloas_tree_list_fields_immutable(groups(tree_lists)),
|
||||
),
|
||||
bimappings(bimap_beacon_state_gloas_tree_list_fields(
|
||||
other_type = "BeaconStateGloas",
|
||||
self_mutable,
|
||||
fallible,
|
||||
groups(tree_lists)
|
||||
)),
|
||||
num_fields(all()),
|
||||
))
|
||||
),
|
||||
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
|
||||
@@ -435,11 +449,11 @@ where
|
||||
|
||||
// Participation (Altair and later)
|
||||
#[compare_fields(as_iter)]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
#[test_random(default)]
|
||||
#[compare_fields(as_iter)]
|
||||
pub previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
#[test_random(default)]
|
||||
pub current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
|
||||
|
||||
@@ -459,15 +473,15 @@ where
|
||||
|
||||
// Inactivity
|
||||
#[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
#[test_random(default)]
|
||||
pub inactivity_scores: List<u64, E::ValidatorRegistryLimit>,
|
||||
|
||||
// Light-client sync committees
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub current_sync_committee: Arc<SyncCommittee<E>>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub next_sync_committee: Arc<SyncCommittee<E>>,
|
||||
|
||||
@@ -502,64 +516,72 @@ where
|
||||
)]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeaderFulu<E>,
|
||||
#[superstruct(
|
||||
only(Gloas),
|
||||
partial_getter(rename = "latest_execution_payload_header_gloas")
|
||||
)]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeaderGloas<E>,
|
||||
|
||||
// Capella
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub next_withdrawal_index: u64,
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub next_withdrawal_validator_index: u64,
|
||||
// Deep history valid from Capella onwards.
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
#[test_random(default)]
|
||||
pub historical_summaries: List<HistoricalSummary, E::HistoricalRootsLimit>,
|
||||
|
||||
// Electra
|
||||
#[superstruct(only(Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub deposit_requests_start_index: u64,
|
||||
#[superstruct(only(Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub deposit_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub exit_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub earliest_exit_epoch: Epoch,
|
||||
#[superstruct(only(Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub consolidation_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub earliest_consolidation_epoch: Epoch,
|
||||
#[compare_fields(as_iter)]
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas))]
|
||||
pub pending_deposits: List<PendingDeposit, E::PendingDepositsLimit>,
|
||||
#[compare_fields(as_iter)]
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas))]
|
||||
pub pending_partial_withdrawals:
|
||||
List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>,
|
||||
#[compare_fields(as_iter)]
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas))]
|
||||
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
|
||||
|
||||
// Fulu
|
||||
#[compare_fields(as_iter)]
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Fulu))]
|
||||
#[superstruct(only(Fulu, Gloas))]
|
||||
pub proposer_lookahead: Vector<u64, E::ProposerLookaheadSlots>,
|
||||
|
||||
// Gloas
|
||||
|
||||
// Caching (not in the spec)
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
@@ -699,6 +721,7 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
BeaconState::Deneb { .. } => ForkName::Deneb,
|
||||
BeaconState::Electra { .. } => ForkName::Electra,
|
||||
BeaconState::Fulu { .. } => ForkName::Fulu,
|
||||
BeaconState::Gloas { .. } => ForkName::Gloas,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1048,6 +1071,9 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
BeaconState::Fulu(state) => Ok(ExecutionPayloadHeaderRef::Fulu(
|
||||
&state.latest_execution_payload_header,
|
||||
)),
|
||||
BeaconState::Gloas(state) => Ok(ExecutionPayloadHeaderRef::Gloas(
|
||||
&state.latest_execution_payload_header,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1071,6 +1097,9 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
BeaconState::Fulu(state) => Ok(ExecutionPayloadHeaderRefMut::Fulu(
|
||||
&mut state.latest_execution_payload_header,
|
||||
)),
|
||||
BeaconState::Gloas(state) => Ok(ExecutionPayloadHeaderRefMut::Gloas(
|
||||
&mut state.latest_execution_payload_header,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1616,6 +1645,16 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
&mut state.exit_cache,
|
||||
&mut state.epoch_cache,
|
||||
)),
|
||||
BeaconState::Gloas(state) => Ok((
|
||||
&mut state.validators,
|
||||
&mut state.balances,
|
||||
&state.previous_epoch_participation,
|
||||
&state.current_epoch_participation,
|
||||
&mut state.inactivity_scores,
|
||||
&mut state.progressive_balances_cache,
|
||||
&mut state.exit_cache,
|
||||
&mut state.epoch_cache,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1797,12 +1836,13 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
| BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_) => self.get_validator_churn_limit(spec)?,
|
||||
BeaconState::Deneb(_) | BeaconState::Electra(_) | BeaconState::Fulu(_) => {
|
||||
std::cmp::min(
|
||||
spec.max_per_epoch_activation_churn_limit,
|
||||
self.get_validator_churn_limit(spec)?,
|
||||
)
|
||||
}
|
||||
BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_)
|
||||
| BeaconState::Fulu(_)
|
||||
| BeaconState::Gloas(_) => std::cmp::min(
|
||||
spec.max_per_epoch_activation_churn_limit,
|
||||
self.get_validator_churn_limit(spec)?,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1922,6 +1962,7 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
BeaconState::Deneb(state) => Ok(&mut state.current_epoch_participation),
|
||||
BeaconState::Electra(state) => Ok(&mut state.current_epoch_participation),
|
||||
BeaconState::Fulu(state) => Ok(&mut state.current_epoch_participation),
|
||||
BeaconState::Gloas(state) => Ok(&mut state.current_epoch_participation),
|
||||
}
|
||||
} else if epoch == previous_epoch {
|
||||
match self {
|
||||
@@ -1932,6 +1973,7 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
BeaconState::Deneb(state) => Ok(&mut state.previous_epoch_participation),
|
||||
BeaconState::Electra(state) => Ok(&mut state.previous_epoch_participation),
|
||||
BeaconState::Fulu(state) => Ok(&mut state.previous_epoch_participation),
|
||||
BeaconState::Gloas(state) => Ok(&mut state.previous_epoch_participation),
|
||||
}
|
||||
} else {
|
||||
Err(BeaconStateError::EpochOutOfBounds)
|
||||
@@ -2196,6 +2238,11 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
any_pending_mutations |= self_field.has_pending_updates();
|
||||
});
|
||||
}
|
||||
Self::Gloas(self_inner) => {
|
||||
map_beacon_state_gloas_tree_list_fields_immutable!(self_inner, |_, self_field| {
|
||||
any_pending_mutations |= self_field.has_pending_updates();
|
||||
});
|
||||
}
|
||||
};
|
||||
any_pending_mutations
|
||||
}
|
||||
@@ -2396,7 +2443,7 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_) => Err(Error::IncorrectStateVariant),
|
||||
BeaconState::Electra(_) | BeaconState::Fulu(_) => {
|
||||
BeaconState::Electra(_) | BeaconState::Fulu(_) | BeaconState::Gloas(_) => {
|
||||
// Consume the balance and update state variables
|
||||
*self.exit_balance_to_consume_mut()? =
|
||||
exit_balance_to_consume.safe_sub(exit_balance)?;
|
||||
@@ -2443,7 +2490,7 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_) => Err(Error::IncorrectStateVariant),
|
||||
BeaconState::Electra(_) | BeaconState::Fulu(_) => {
|
||||
BeaconState::Electra(_) | BeaconState::Fulu(_) | BeaconState::Gloas(_) => {
|
||||
// Consume the balance and update state variables.
|
||||
*self.consolidation_balance_to_consume_mut()? =
|
||||
consolidation_balance_to_consume.safe_sub(consolidation_balance)?;
|
||||
@@ -2514,6 +2561,14 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
);
|
||||
}
|
||||
(Self::Fulu(_), _) => (),
|
||||
(Self::Gloas(self_inner), Self::Gloas(base_inner)) => {
|
||||
bimap_beacon_state_gloas_tree_list_fields!(
|
||||
self_inner,
|
||||
base_inner,
|
||||
|_, self_field, base_field| { self_field.rebase_on(base_field) }
|
||||
);
|
||||
}
|
||||
(Self::Gloas(_), _) => (),
|
||||
}
|
||||
|
||||
// Use sync committees from `base` if they are equal.
|
||||
@@ -2591,6 +2646,7 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
ForkName::Deneb => BeaconStateDeneb::<E>::NUM_FIELDS.next_power_of_two(),
|
||||
ForkName::Electra => BeaconStateElectra::<E>::NUM_FIELDS.next_power_of_two(),
|
||||
ForkName::Fulu => BeaconStateFulu::<E>::NUM_FIELDS.next_power_of_two(),
|
||||
ForkName::Gloas => BeaconStateGloas::<E>::NUM_FIELDS.next_power_of_two(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2642,6 +2698,9 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
Self::Fulu(inner) => {
|
||||
map_beacon_state_fulu_tree_list_fields!(inner, |_, x| { x.apply_updates() })
|
||||
}
|
||||
Self::Gloas(inner) => {
|
||||
map_beacon_state_gloas_tree_list_fields!(inner, |_, x| { x.apply_updates() })
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -2755,6 +2814,11 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
leaves.push(field.tree_hash_root());
|
||||
});
|
||||
}
|
||||
BeaconState::Gloas(state) => {
|
||||
map_beacon_state_gloas_fields!(state, |_, field| {
|
||||
leaves.push(field.tree_hash_root());
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
leaves
|
||||
@@ -2813,6 +2877,7 @@ impl<E: EthSpec> CompareFields for BeaconState<E> {
|
||||
(BeaconState::Deneb(x), BeaconState::Deneb(y)) => x.compare_fields(y),
|
||||
(BeaconState::Electra(x), BeaconState::Electra(y)) => x.compare_fields(y),
|
||||
(BeaconState::Fulu(x), BeaconState::Fulu(y)) => x.compare_fields(y),
|
||||
(BeaconState::Gloas(x), BeaconState::Gloas(y)) => x.compare_fields(y),
|
||||
_ => panic!("compare_fields: mismatched state variants",),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ use crate::beacon_block_body::KzgCommitments;
|
||||
use crate::{
|
||||
ChainSpec, ContextDeserialize, EthSpec, ExecutionPayloadHeaderBellatrix,
|
||||
ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra,
|
||||
ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
|
||||
ExecutionRequests, ForkName, ForkVersionDecode, SignedRoot, Uint256, test_utils::TestRandom,
|
||||
ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderGloas, ExecutionPayloadHeaderRef,
|
||||
ExecutionPayloadHeaderRefMut, ExecutionRequests, ForkName, ForkVersionDecode, SignedRoot,
|
||||
Uint256, test_utils::TestRandom,
|
||||
};
|
||||
use bls::PublicKeyBytes;
|
||||
use bls::Signature;
|
||||
@@ -15,7 +16,7 @@ use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
PartialEq,
|
||||
@@ -48,9 +49,11 @@ pub struct BuilderBid<E: EthSpec> {
|
||||
pub header: ExecutionPayloadHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "header_fulu"))]
|
||||
pub header: ExecutionPayloadHeaderFulu<E>,
|
||||
#[superstruct(only(Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "header_gloas"))]
|
||||
pub header: ExecutionPayloadHeaderGloas<E>,
|
||||
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
|
||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas))]
|
||||
pub execution_requests: ExecutionRequests<E>,
|
||||
#[serde(with = "serde_utils::quoted_u256")]
|
||||
pub value: Uint256,
|
||||
@@ -95,6 +98,7 @@ impl<E: EthSpec> ForkVersionDecode for BuilderBid<E> {
|
||||
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb::from_ssz_bytes(bytes)?),
|
||||
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra::from_ssz_bytes(bytes)?),
|
||||
ForkName::Fulu => BuilderBid::Fulu(BuilderBidFulu::from_ssz_bytes(bytes)?),
|
||||
ForkName::Gloas => BuilderBid::Gloas(BuilderBidGloas::from_ssz_bytes(bytes)?),
|
||||
};
|
||||
Ok(builder_bid)
|
||||
}
|
||||
@@ -150,6 +154,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for BuilderBid<E> {
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Base | ForkName::Altair => {
|
||||
return Err(serde::de::Error::custom(format!(
|
||||
"BuilderBid failed to deserialize: unsupported fork '{}'",
|
||||
|
||||
@@ -208,6 +208,13 @@ pub struct ChainSpec {
|
||||
pub validator_custody_requirement: u64,
|
||||
pub balance_per_additional_custody_group: u64,
|
||||
|
||||
/*
|
||||
* Gloas hard fork params
|
||||
*/
|
||||
pub gloas_fork_version: [u8; 4],
|
||||
/// The Gloas fork epoch is optional, with `None` representing "Gloas never happens".
|
||||
pub gloas_fork_epoch: Option<Epoch>,
|
||||
|
||||
/*
|
||||
* Networking
|
||||
*/
|
||||
@@ -250,6 +257,10 @@ pub struct ChainSpec {
|
||||
pub(crate) blob_schedule: BlobSchedule,
|
||||
min_epochs_for_data_column_sidecars_requests: u64,
|
||||
|
||||
/*
|
||||
* Networking Gloas
|
||||
*/
|
||||
|
||||
/*
|
||||
* Networking Derived
|
||||
*
|
||||
@@ -321,25 +332,26 @@ impl ChainSpec {
|
||||
|
||||
/// Returns the name of the fork which is active at `epoch`.
|
||||
pub fn fork_name_at_epoch(&self, epoch: Epoch) -> ForkName {
|
||||
match self.fulu_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Fulu,
|
||||
_ => match self.electra_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Electra,
|
||||
_ => match self.deneb_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Deneb,
|
||||
_ => match self.capella_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Capella,
|
||||
_ => match self.bellatrix_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Bellatrix,
|
||||
_ => match self.altair_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Altair,
|
||||
_ => ForkName::Base,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
let forks = [
|
||||
(self.gloas_fork_epoch, ForkName::Gloas),
|
||||
(self.fulu_fork_epoch, ForkName::Fulu),
|
||||
(self.electra_fork_epoch, ForkName::Electra),
|
||||
(self.deneb_fork_epoch, ForkName::Deneb),
|
||||
(self.capella_fork_epoch, ForkName::Capella),
|
||||
(self.bellatrix_fork_epoch, ForkName::Bellatrix),
|
||||
(self.altair_fork_epoch, ForkName::Altair),
|
||||
];
|
||||
|
||||
// Find the first fork where `epoch` is >= `fork_epoch`.
|
||||
for (fork_epoch_opt, fork_name) in forks.iter() {
|
||||
if let Some(fork_epoch) = fork_epoch_opt
|
||||
&& epoch >= *fork_epoch
|
||||
{
|
||||
return *fork_name;
|
||||
}
|
||||
}
|
||||
|
||||
ForkName::Base
|
||||
}
|
||||
|
||||
/// Returns the fork version for a named fork.
|
||||
@@ -352,6 +364,7 @@ impl ChainSpec {
|
||||
ForkName::Deneb => self.deneb_fork_version,
|
||||
ForkName::Electra => self.electra_fork_version,
|
||||
ForkName::Fulu => self.fulu_fork_version,
|
||||
ForkName::Gloas => self.gloas_fork_version,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,6 +383,7 @@ impl ChainSpec {
|
||||
ForkName::Deneb => self.deneb_fork_epoch,
|
||||
ForkName::Electra => self.electra_fork_epoch,
|
||||
ForkName::Fulu => self.fulu_fork_epoch,
|
||||
ForkName::Gloas => self.gloas_fork_epoch,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,6 +467,12 @@ impl ChainSpec {
|
||||
.is_some_and(|fulu_fork_epoch| fulu_fork_epoch != self.far_future_epoch)
|
||||
}
|
||||
|
||||
/// Returns true if `GLOAS_FORK_EPOCH` is set and is not set to `FAR_FUTURE_EPOCH`.
|
||||
pub fn is_gloas_scheduled(&self) -> bool {
|
||||
self.gloas_fork_epoch
|
||||
.is_some_and(|gloas_fork_epoch| gloas_fork_epoch != self.far_future_epoch)
|
||||
}
|
||||
|
||||
/// Returns a full `Fork` struct for a given epoch.
|
||||
pub fn fork_at_epoch(&self, epoch: Epoch) -> Fork {
|
||||
let current_fork_name = self.fork_name_at_epoch(epoch);
|
||||
@@ -1050,6 +1070,12 @@ impl ChainSpec {
|
||||
validator_custody_requirement: 8,
|
||||
balance_per_additional_custody_group: 32000000000,
|
||||
|
||||
/*
|
||||
* Gloas hard fork params
|
||||
*/
|
||||
gloas_fork_version: [0x07, 0x00, 0x00, 0x00],
|
||||
gloas_fork_epoch: None,
|
||||
|
||||
/*
|
||||
* Network specific
|
||||
*/
|
||||
@@ -1173,6 +1199,9 @@ impl ChainSpec {
|
||||
// Fulu
|
||||
fulu_fork_version: [0x06, 0x00, 0x00, 0x01],
|
||||
fulu_fork_epoch: None,
|
||||
// Gloas
|
||||
gloas_fork_version: [0x07, 0x00, 0x00, 0x00],
|
||||
gloas_fork_epoch: None,
|
||||
// Other
|
||||
network_id: 2, // lighthouse testnet network id
|
||||
deposit_chain_id: 5,
|
||||
@@ -1387,6 +1416,12 @@ impl ChainSpec {
|
||||
validator_custody_requirement: 8,
|
||||
balance_per_additional_custody_group: 32000000000,
|
||||
|
||||
/*
|
||||
* Gloas hard fork params
|
||||
*/
|
||||
gloas_fork_version: [0x07, 0x00, 0x00, 0x64],
|
||||
gloas_fork_epoch: None,
|
||||
|
||||
/*
|
||||
* Network specific
|
||||
*/
|
||||
@@ -1648,6 +1683,14 @@ pub struct Config {
|
||||
#[serde(deserialize_with = "deserialize_fork_epoch")]
|
||||
pub fulu_fork_epoch: Option<MaybeQuoted<Epoch>>,
|
||||
|
||||
#[serde(default = "default_gloas_fork_version")]
|
||||
#[serde(with = "serde_utils::bytes_4_hex")]
|
||||
gloas_fork_version: [u8; 4],
|
||||
#[serde(default)]
|
||||
#[serde(serialize_with = "serialize_fork_epoch")]
|
||||
#[serde(deserialize_with = "deserialize_fork_epoch")]
|
||||
pub gloas_fork_epoch: Option<MaybeQuoted<Epoch>>,
|
||||
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
seconds_per_slot: u64,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
@@ -1805,6 +1848,11 @@ fn default_fulu_fork_version() -> [u8; 4] {
|
||||
[0xff, 0xff, 0xff, 0xff]
|
||||
}
|
||||
|
||||
fn default_gloas_fork_version() -> [u8; 4] {
|
||||
// This value shouldn't be used.
|
||||
[0xff, 0xff, 0xff, 0xff]
|
||||
}
|
||||
|
||||
/// Placeholder value: 2^256-2^10 (115792089237316195423570985008687907853269984665640564039457584007913129638912).
|
||||
///
|
||||
/// Taken from https://github.com/ethereum/consensus-specs/blob/d5e4828aecafaf1c57ef67a5f23c4ae7b08c5137/configs/mainnet.yaml#L15-L16
|
||||
@@ -2101,6 +2149,11 @@ impl Config {
|
||||
.fulu_fork_epoch
|
||||
.map(|epoch| MaybeQuoted { value: epoch }),
|
||||
|
||||
gloas_fork_version: spec.gloas_fork_version,
|
||||
gloas_fork_epoch: spec
|
||||
.gloas_fork_epoch
|
||||
.map(|epoch| MaybeQuoted { value: epoch }),
|
||||
|
||||
seconds_per_slot: spec.seconds_per_slot,
|
||||
seconds_per_eth1_block: spec.seconds_per_eth1_block,
|
||||
min_validator_withdrawability_delay: spec.min_validator_withdrawability_delay,
|
||||
@@ -2190,6 +2243,8 @@ impl Config {
|
||||
electra_fork_version,
|
||||
fulu_fork_epoch,
|
||||
fulu_fork_version,
|
||||
gloas_fork_version,
|
||||
gloas_fork_epoch,
|
||||
seconds_per_slot,
|
||||
seconds_per_eth1_block,
|
||||
min_validator_withdrawability_delay,
|
||||
@@ -2261,6 +2316,8 @@ impl Config {
|
||||
electra_fork_version,
|
||||
fulu_fork_epoch: fulu_fork_epoch.map(|q| q.value),
|
||||
fulu_fork_version,
|
||||
gloas_fork_version,
|
||||
gloas_fork_epoch: gloas_fork_epoch.map(|q| q.value),
|
||||
seconds_per_slot,
|
||||
seconds_per_eth1_block,
|
||||
min_validator_withdrawability_delay,
|
||||
@@ -2548,6 +2605,8 @@ mod yaml_tests {
|
||||
ELECTRA_FORK_EPOCH: 128
|
||||
FULU_FORK_VERSION: 0x70355025
|
||||
FULU_FORK_EPOCH: 256
|
||||
GLOAS_FORK_VERSION: 0x80355025
|
||||
GLOAS_FORK_EPOCH: 512
|
||||
BLOB_SCHEDULE:
|
||||
- EPOCH: 512
|
||||
MAX_BLOBS_PER_BLOCK: 12
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
AltairPreset, BasePreset, BellatrixPreset, CapellaPreset, ChainSpec, Config, DenebPreset,
|
||||
ElectraPreset, EthSpec, FuluPreset, consts::altair, consts::deneb,
|
||||
ElectraPreset, EthSpec, FuluPreset, GloasPreset, consts::altair, consts::deneb,
|
||||
};
|
||||
use maplit::hashmap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -12,7 +12,7 @@ use superstruct::superstruct;
|
||||
///
|
||||
/// Mostly useful for the API.
|
||||
#[superstruct(
|
||||
variants(Deneb, Electra, Fulu),
|
||||
variants(Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(derive(Serialize, Deserialize, Debug, PartialEq, Clone))
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
@@ -31,12 +31,15 @@ pub struct ConfigAndPreset {
|
||||
pub capella_preset: CapellaPreset,
|
||||
#[serde(flatten)]
|
||||
pub deneb_preset: DenebPreset,
|
||||
#[superstruct(only(Electra, Fulu))]
|
||||
#[superstruct(only(Electra, Fulu, Gloas))]
|
||||
#[serde(flatten)]
|
||||
pub electra_preset: ElectraPreset,
|
||||
#[superstruct(only(Fulu))]
|
||||
#[superstruct(only(Fulu, Gloas))]
|
||||
#[serde(flatten)]
|
||||
pub fulu_preset: FuluPreset,
|
||||
#[superstruct(only(Gloas))]
|
||||
#[serde(flatten)]
|
||||
pub gloas_preset: GloasPreset,
|
||||
/// The `extra_fields` map allows us to gracefully decode fields intended for future hard forks.
|
||||
#[serde(flatten)]
|
||||
pub extra_fields: HashMap<String, Value>,
|
||||
@@ -52,7 +55,24 @@ impl ConfigAndPreset {
|
||||
let deneb_preset = DenebPreset::from_chain_spec::<E>(spec);
|
||||
let extra_fields = get_extra_fields(spec);
|
||||
|
||||
if spec.is_fulu_scheduled() {
|
||||
if spec.is_gloas_scheduled() {
|
||||
let electra_preset = ElectraPreset::from_chain_spec::<E>(spec);
|
||||
let fulu_preset = FuluPreset::from_chain_spec::<E>(spec);
|
||||
let gloas_preset = GloasPreset::from_chain_spec::<E>(spec);
|
||||
|
||||
ConfigAndPreset::Gloas(ConfigAndPresetGloas {
|
||||
config,
|
||||
base_preset,
|
||||
altair_preset,
|
||||
bellatrix_preset,
|
||||
capella_preset,
|
||||
deneb_preset,
|
||||
electra_preset,
|
||||
fulu_preset,
|
||||
gloas_preset,
|
||||
extra_fields,
|
||||
})
|
||||
} else if spec.is_fulu_scheduled() {
|
||||
let electra_preset = ElectraPreset::from_chain_spec::<E>(spec);
|
||||
let fulu_preset = FuluPreset::from_chain_spec::<E>(spec);
|
||||
|
||||
@@ -139,8 +159,8 @@ mod test {
|
||||
.open(tmp_file.as_ref())
|
||||
.expect("error opening file");
|
||||
let mut mainnet_spec = ChainSpec::mainnet();
|
||||
// setting fulu_fork_epoch because we are roundtripping a fulu config
|
||||
mainnet_spec.fulu_fork_epoch = Some(Epoch::new(42));
|
||||
// setting gloas_fork_epoch because we are roundtripping a gloas config
|
||||
mainnet_spec.gloas_fork_epoch = Some(Epoch::new(42));
|
||||
let mut yamlconfig = ConfigAndPreset::from_chain_spec::<MainnetEthSpec>(&mainnet_spec);
|
||||
let (k1, v1) = ("SAMPLE_HARDFORK_KEY1", "123456789");
|
||||
let (k2, v2) = ("SAMPLE_HARDFORK_KEY2", "987654321");
|
||||
@@ -158,8 +178,8 @@ mod test {
|
||||
.write(false)
|
||||
.open(tmp_file.as_ref())
|
||||
.expect("error while opening the file");
|
||||
let from: ConfigAndPresetFulu =
|
||||
let from: ConfigAndPresetGloas =
|
||||
serde_yaml::from_reader(reader).expect("error while deserializing");
|
||||
assert_eq!(ConfigAndPreset::Fulu(from), yamlconfig);
|
||||
assert_eq!(ConfigAndPreset::Gloas(from), yamlconfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ pub type Transactions<E> = VariableList<
|
||||
pub type Withdrawals<E> = VariableList<Withdrawal, <E as EthSpec>::MaxWithdrawalsPerPayload>;
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Default,
|
||||
@@ -88,12 +88,12 @@ pub struct ExecutionPayload<E: EthSpec> {
|
||||
pub block_hash: ExecutionBlockHash,
|
||||
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")]
|
||||
pub transactions: Transactions<E>,
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
pub withdrawals: Withdrawals<E>,
|
||||
#[superstruct(only(Deneb, Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub blob_gas_used: u64,
|
||||
#[superstruct(only(Deneb, Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub excess_blob_gas: u64,
|
||||
}
|
||||
@@ -122,6 +122,7 @@ impl<E: EthSpec> ForkVersionDecode for ExecutionPayload<E> {
|
||||
ForkName::Deneb => ExecutionPayloadDeneb::from_ssz_bytes(bytes).map(Self::Deneb),
|
||||
ForkName::Electra => ExecutionPayloadElectra::from_ssz_bytes(bytes).map(Self::Electra),
|
||||
ForkName::Fulu => ExecutionPayloadFulu::from_ssz_bytes(bytes).map(Self::Fulu),
|
||||
ForkName::Gloas => ExecutionPayloadGloas::from_ssz_bytes(bytes).map(Self::Gloas),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +170,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayload<E>
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -181,6 +185,7 @@ impl<E: EthSpec> ExecutionPayload<E> {
|
||||
ExecutionPayload::Deneb(_) => ForkName::Deneb,
|
||||
ExecutionPayload::Electra(_) => ForkName::Electra,
|
||||
ExecutionPayload::Fulu(_) => ForkName::Fulu,
|
||||
ExecutionPayload::Gloas(_) => ForkName::Gloas,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Default,
|
||||
@@ -84,12 +84,12 @@ pub struct ExecutionPayloadHeader<E: EthSpec> {
|
||||
pub block_hash: ExecutionBlockHash,
|
||||
#[superstruct(getter(copy))]
|
||||
pub transactions_root: Hash256,
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
pub withdrawals_root: Hash256,
|
||||
#[superstruct(only(Deneb, Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub blob_gas_used: u64,
|
||||
#[superstruct(only(Deneb, Electra, Fulu), partial_getter(copy))]
|
||||
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub excess_blob_gas: u64,
|
||||
}
|
||||
@@ -115,6 +115,7 @@ impl<E: EthSpec> ExecutionPayloadHeader<E> {
|
||||
ExecutionPayloadHeaderElectra::from_ssz_bytes(bytes).map(Self::Electra)
|
||||
}
|
||||
ForkName::Fulu => ExecutionPayloadHeaderFulu::from_ssz_bytes(bytes).map(Self::Fulu),
|
||||
ForkName::Gloas => ExecutionPayloadHeaderGloas::from_ssz_bytes(bytes).map(Self::Gloas),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +137,7 @@ impl<E: EthSpec> ExecutionPayloadHeader<E> {
|
||||
ExecutionPayloadHeader::Deneb(_) => ForkName::Deneb,
|
||||
ExecutionPayloadHeader::Electra(_) => ForkName::Electra,
|
||||
ExecutionPayloadHeader::Fulu(_) => ForkName::Fulu,
|
||||
ExecutionPayloadHeader::Gloas(_) => ForkName::Gloas,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,6 +245,30 @@ impl<E: EthSpec> ExecutionPayloadHeaderElectra<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ExecutionPayloadHeaderFulu<E> {
|
||||
pub fn upgrade_to_gloas(&self) -> ExecutionPayloadHeaderGloas<E> {
|
||||
ExecutionPayloadHeaderGloas {
|
||||
parent_hash: self.parent_hash,
|
||||
fee_recipient: self.fee_recipient,
|
||||
state_root: self.state_root,
|
||||
receipts_root: self.receipts_root,
|
||||
logs_bloom: self.logs_bloom.clone(),
|
||||
prev_randao: self.prev_randao,
|
||||
block_number: self.block_number,
|
||||
gas_limit: self.gas_limit,
|
||||
gas_used: self.gas_used,
|
||||
timestamp: self.timestamp,
|
||||
extra_data: self.extra_data.clone(),
|
||||
base_fee_per_gas: self.base_fee_per_gas,
|
||||
block_hash: self.block_hash,
|
||||
transactions_root: self.transactions_root,
|
||||
withdrawals_root: self.withdrawals_root,
|
||||
blob_gas_used: self.blob_gas_used,
|
||||
excess_blob_gas: self.excess_blob_gas,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<&'a ExecutionPayloadBellatrix<E>> for ExecutionPayloadHeaderBellatrix<E> {
|
||||
fn from(payload: &'a ExecutionPayloadBellatrix<E>) -> Self {
|
||||
Self {
|
||||
@@ -358,6 +384,30 @@ impl<'a, E: EthSpec> From<&'a ExecutionPayloadFulu<E>> for ExecutionPayloadHeade
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<&'a ExecutionPayloadGloas<E>> for ExecutionPayloadHeaderGloas<E> {
|
||||
fn from(payload: &'a ExecutionPayloadGloas<E>) -> Self {
|
||||
Self {
|
||||
parent_hash: payload.parent_hash,
|
||||
fee_recipient: payload.fee_recipient,
|
||||
state_root: payload.state_root,
|
||||
receipts_root: payload.receipts_root,
|
||||
logs_bloom: payload.logs_bloom.clone(),
|
||||
prev_randao: payload.prev_randao,
|
||||
block_number: payload.block_number,
|
||||
gas_limit: payload.gas_limit,
|
||||
gas_used: payload.gas_used,
|
||||
timestamp: payload.timestamp,
|
||||
extra_data: payload.extra_data.clone(),
|
||||
base_fee_per_gas: payload.base_fee_per_gas,
|
||||
block_hash: payload.block_hash,
|
||||
transactions_root: payload.transactions.tree_hash_root(),
|
||||
withdrawals_root: payload.withdrawals.tree_hash_root(),
|
||||
blob_gas_used: payload.blob_gas_used,
|
||||
excess_blob_gas: payload.excess_blob_gas,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These impls are required to work around an inelegance in `to_execution_payload_header`.
|
||||
// They only clone headers so they should be relatively cheap.
|
||||
impl<'a, E: EthSpec> From<&'a Self> for ExecutionPayloadHeaderBellatrix<E> {
|
||||
@@ -390,6 +440,12 @@ impl<'a, E: EthSpec> From<&'a Self> for ExecutionPayloadHeaderFulu<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<&'a Self> for ExecutionPayloadHeaderGloas<E> {
|
||||
fn from(payload: &'a Self) -> Self {
|
||||
payload.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<ExecutionPayloadRef<'a, E>> for ExecutionPayloadHeader<E> {
|
||||
fn from(payload: ExecutionPayloadRef<'a, E>) -> Self {
|
||||
map_execution_payload_ref_into_execution_payload_header!(
|
||||
@@ -451,6 +507,9 @@ impl<E: EthSpec> ExecutionPayloadHeaderRefMut<'_, E> {
|
||||
ExecutionPayloadHeaderRefMut::Fulu(mut_ref) => {
|
||||
*mut_ref = header.try_into()?;
|
||||
}
|
||||
ExecutionPayloadHeaderRefMut::Gloas(mut_ref) => {
|
||||
*mut_ref = header.try_into()?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -478,6 +537,16 @@ impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for ExecutionPayloadHeaderFu
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for ExecutionPayloadHeaderGloas<E> {
|
||||
type Error = BeaconStateError;
|
||||
fn try_from(header: ExecutionPayloadHeader<E>) -> Result<Self, Self::Error> {
|
||||
match header {
|
||||
ExecutionPayloadHeader::Gloas(execution_payload_header) => Ok(execution_payload_header),
|
||||
_ => Err(BeaconStateError::IncorrectStateVariant),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadHeader<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -511,6 +580,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadHead
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ pub enum ForkName {
|
||||
Deneb,
|
||||
Electra,
|
||||
Fulu,
|
||||
Gloas,
|
||||
}
|
||||
|
||||
impl ForkName {
|
||||
@@ -30,6 +31,7 @@ impl ForkName {
|
||||
ForkName::Deneb,
|
||||
ForkName::Electra,
|
||||
ForkName::Fulu,
|
||||
ForkName::Gloas,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -64,6 +66,7 @@ impl ForkName {
|
||||
spec.deneb_fork_epoch = None;
|
||||
spec.electra_fork_epoch = None;
|
||||
spec.fulu_fork_epoch = None;
|
||||
spec.gloas_fork_epoch = None;
|
||||
spec
|
||||
}
|
||||
ForkName::Altair => {
|
||||
@@ -73,6 +76,7 @@ impl ForkName {
|
||||
spec.deneb_fork_epoch = None;
|
||||
spec.electra_fork_epoch = None;
|
||||
spec.fulu_fork_epoch = None;
|
||||
spec.gloas_fork_epoch = None;
|
||||
spec
|
||||
}
|
||||
ForkName::Bellatrix => {
|
||||
@@ -82,6 +86,7 @@ impl ForkName {
|
||||
spec.deneb_fork_epoch = None;
|
||||
spec.electra_fork_epoch = None;
|
||||
spec.fulu_fork_epoch = None;
|
||||
spec.gloas_fork_epoch = None;
|
||||
spec
|
||||
}
|
||||
ForkName::Capella => {
|
||||
@@ -91,6 +96,7 @@ impl ForkName {
|
||||
spec.deneb_fork_epoch = None;
|
||||
spec.electra_fork_epoch = None;
|
||||
spec.fulu_fork_epoch = None;
|
||||
spec.gloas_fork_epoch = None;
|
||||
spec
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
@@ -100,6 +106,7 @@ impl ForkName {
|
||||
spec.deneb_fork_epoch = Some(Epoch::new(0));
|
||||
spec.electra_fork_epoch = None;
|
||||
spec.fulu_fork_epoch = None;
|
||||
spec.gloas_fork_epoch = None;
|
||||
spec
|
||||
}
|
||||
ForkName::Electra => {
|
||||
@@ -109,6 +116,7 @@ impl ForkName {
|
||||
spec.deneb_fork_epoch = Some(Epoch::new(0));
|
||||
spec.electra_fork_epoch = Some(Epoch::new(0));
|
||||
spec.fulu_fork_epoch = None;
|
||||
spec.gloas_fork_epoch = None;
|
||||
spec
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
@@ -118,6 +126,17 @@ impl ForkName {
|
||||
spec.deneb_fork_epoch = Some(Epoch::new(0));
|
||||
spec.electra_fork_epoch = Some(Epoch::new(0));
|
||||
spec.fulu_fork_epoch = Some(Epoch::new(0));
|
||||
spec.gloas_fork_epoch = None;
|
||||
spec
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||
spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||
spec.capella_fork_epoch = Some(Epoch::new(0));
|
||||
spec.deneb_fork_epoch = Some(Epoch::new(0));
|
||||
spec.electra_fork_epoch = Some(Epoch::new(0));
|
||||
spec.fulu_fork_epoch = Some(Epoch::new(0));
|
||||
spec.gloas_fork_epoch = Some(Epoch::new(0));
|
||||
spec
|
||||
}
|
||||
}
|
||||
@@ -135,6 +154,7 @@ impl ForkName {
|
||||
ForkName::Deneb => Some(ForkName::Capella),
|
||||
ForkName::Electra => Some(ForkName::Deneb),
|
||||
ForkName::Fulu => Some(ForkName::Electra),
|
||||
ForkName::Gloas => Some(ForkName::Fulu),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +169,8 @@ impl ForkName {
|
||||
ForkName::Capella => Some(ForkName::Deneb),
|
||||
ForkName::Deneb => Some(ForkName::Electra),
|
||||
ForkName::Electra => Some(ForkName::Fulu),
|
||||
ForkName::Fulu => None,
|
||||
ForkName::Fulu => Some(ForkName::Gloas),
|
||||
ForkName::Gloas => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +197,10 @@ impl ForkName {
|
||||
pub fn fulu_enabled(self) -> bool {
|
||||
self >= ForkName::Fulu
|
||||
}
|
||||
|
||||
pub fn gloas_enabled(self) -> bool {
|
||||
self >= ForkName::Gloas
|
||||
}
|
||||
}
|
||||
|
||||
/// Map a fork name into a fork-versioned superstruct type like `BeaconBlock`.
|
||||
@@ -231,6 +256,10 @@ macro_rules! map_fork_name_with {
|
||||
let (value, extra_data) = $body;
|
||||
($t::Fulu(value), extra_data)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
let (value, extra_data) = $body;
|
||||
($t::Gloas(value), extra_data)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -247,6 +276,7 @@ impl FromStr for ForkName {
|
||||
"deneb" => ForkName::Deneb,
|
||||
"electra" => ForkName::Electra,
|
||||
"fulu" => ForkName::Fulu,
|
||||
"gloas" => ForkName::Gloas,
|
||||
_ => return Err(format!("unknown fork name: {}", fork_name)),
|
||||
})
|
||||
}
|
||||
@@ -262,6 +292,7 @@ impl Display for ForkName {
|
||||
ForkName::Deneb => "deneb".fmt(f),
|
||||
ForkName::Electra => "electra".fmt(f),
|
||||
ForkName::Fulu => "fulu".fmt(f),
|
||||
ForkName::Gloas => "gloas".fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,13 +128,13 @@ pub use crate::attester_slashing::{
|
||||
};
|
||||
pub use crate::beacon_block::{
|
||||
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockCapella,
|
||||
BeaconBlockDeneb, BeaconBlockElectra, BeaconBlockFulu, BeaconBlockRef, BeaconBlockRefMut,
|
||||
BlindedBeaconBlock, BlockImportSource, EmptyBlock,
|
||||
BeaconBlockDeneb, BeaconBlockElectra, BeaconBlockFulu, BeaconBlockGloas, BeaconBlockRef,
|
||||
BeaconBlockRefMut, BlindedBeaconBlock, BlockImportSource, EmptyBlock,
|
||||
};
|
||||
pub use crate::beacon_block_body::{
|
||||
BeaconBlockBody, BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyBellatrix,
|
||||
BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconBlockBodyFulu,
|
||||
BeaconBlockBodyRef, BeaconBlockBodyRefMut,
|
||||
BeaconBlockBodyGloas, BeaconBlockBodyRef, BeaconBlockBodyRefMut,
|
||||
};
|
||||
pub use crate::beacon_block_header::BeaconBlockHeader;
|
||||
pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee};
|
||||
@@ -148,6 +148,7 @@ pub use crate::chain_spec::{ChainSpec, Config, Domain};
|
||||
pub use crate::checkpoint::Checkpoint;
|
||||
pub use crate::config_and_preset::{
|
||||
ConfigAndPreset, ConfigAndPresetDeneb, ConfigAndPresetElectra, ConfigAndPresetFulu,
|
||||
ConfigAndPresetGloas,
|
||||
};
|
||||
pub use crate::consolidation_request::ConsolidationRequest;
|
||||
pub use crate::contribution_and_proof::ContributionAndProof;
|
||||
@@ -168,13 +169,13 @@ pub use crate::execution_block_hash::ExecutionBlockHash;
|
||||
pub use crate::execution_block_header::{EncodableExecutionBlockHeader, ExecutionBlockHeader};
|
||||
pub use crate::execution_payload::{
|
||||
ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
|
||||
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadRef, Transaction, Transactions,
|
||||
Withdrawals,
|
||||
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionPayloadRef,
|
||||
Transaction, Transactions, Withdrawals,
|
||||
};
|
||||
pub use crate::execution_payload_header::{
|
||||
ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
|
||||
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,
|
||||
ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
|
||||
ExecutionPayloadHeaderGloas, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
|
||||
};
|
||||
pub use crate::execution_requests::{ExecutionRequests, RequestType};
|
||||
pub use crate::fork::Fork;
|
||||
@@ -189,32 +190,35 @@ pub use crate::indexed_attestation::{
|
||||
pub use crate::light_client_bootstrap::{
|
||||
LightClientBootstrap, LightClientBootstrapAltair, LightClientBootstrapCapella,
|
||||
LightClientBootstrapDeneb, LightClientBootstrapElectra, LightClientBootstrapFulu,
|
||||
LightClientBootstrapGloas,
|
||||
};
|
||||
pub use crate::light_client_finality_update::{
|
||||
LightClientFinalityUpdate, LightClientFinalityUpdateAltair, LightClientFinalityUpdateCapella,
|
||||
LightClientFinalityUpdateDeneb, LightClientFinalityUpdateElectra,
|
||||
LightClientFinalityUpdateFulu,
|
||||
LightClientFinalityUpdateFulu, LightClientFinalityUpdateGloas,
|
||||
};
|
||||
pub use crate::light_client_header::{
|
||||
LightClientHeader, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderElectra, LightClientHeaderFulu,
|
||||
LightClientHeaderElectra, LightClientHeaderFulu, LightClientHeaderGloas,
|
||||
};
|
||||
pub use crate::light_client_optimistic_update::{
|
||||
LightClientOptimisticUpdate, LightClientOptimisticUpdateAltair,
|
||||
LightClientOptimisticUpdateCapella, LightClientOptimisticUpdateDeneb,
|
||||
LightClientOptimisticUpdateElectra, LightClientOptimisticUpdateFulu,
|
||||
LightClientOptimisticUpdateGloas,
|
||||
};
|
||||
pub use crate::light_client_update::{
|
||||
Error as LightClientUpdateError, LightClientUpdate, LightClientUpdateAltair,
|
||||
LightClientUpdateCapella, LightClientUpdateDeneb, LightClientUpdateElectra,
|
||||
LightClientUpdateFulu, MerkleProof,
|
||||
LightClientUpdateFulu, LightClientUpdateGloas, MerkleProof,
|
||||
};
|
||||
pub use crate::participation_flags::ParticipationFlags;
|
||||
pub use crate::payload::{
|
||||
AbstractExecPayload, BlindedPayload, BlindedPayloadBellatrix, BlindedPayloadCapella,
|
||||
BlindedPayloadDeneb, BlindedPayloadElectra, BlindedPayloadFulu, BlindedPayloadRef, BlockType,
|
||||
ExecPayload, FullPayload, FullPayloadBellatrix, FullPayloadCapella, FullPayloadDeneb,
|
||||
FullPayloadElectra, FullPayloadFulu, FullPayloadRef, OwnedExecPayload,
|
||||
BlindedPayloadDeneb, BlindedPayloadElectra, BlindedPayloadFulu, BlindedPayloadGloas,
|
||||
BlindedPayloadRef, BlockType, ExecPayload, FullPayload, FullPayloadBellatrix,
|
||||
FullPayloadCapella, FullPayloadDeneb, FullPayloadElectra, FullPayloadFulu, FullPayloadGloas,
|
||||
FullPayloadRef, OwnedExecPayload,
|
||||
};
|
||||
pub use crate::pending_attestation::PendingAttestation;
|
||||
pub use crate::pending_consolidation::PendingConsolidation;
|
||||
@@ -222,7 +226,7 @@ pub use crate::pending_deposit::PendingDeposit;
|
||||
pub use crate::pending_partial_withdrawal::PendingPartialWithdrawal;
|
||||
pub use crate::preset::{
|
||||
AltairPreset, BasePreset, BellatrixPreset, CapellaPreset, DenebPreset, ElectraPreset,
|
||||
FuluPreset,
|
||||
FuluPreset, GloasPreset,
|
||||
};
|
||||
pub use crate::proposer_preparation_data::ProposerPreparationData;
|
||||
pub use crate::proposer_slashing::ProposerSlashing;
|
||||
@@ -237,7 +241,7 @@ pub use crate::signed_aggregate_and_proof::{
|
||||
pub use crate::signed_beacon_block::{
|
||||
SignedBeaconBlock, SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockBellatrix,
|
||||
SignedBeaconBlockCapella, SignedBeaconBlockDeneb, SignedBeaconBlockElectra,
|
||||
SignedBeaconBlockFulu, SignedBeaconBlockHash, SignedBlindedBeaconBlock,
|
||||
SignedBeaconBlockFulu, SignedBeaconBlockGloas, SignedBeaconBlockHash, SignedBlindedBeaconBlock,
|
||||
ssz_tagged_signed_beacon_block, ssz_tagged_signed_beacon_block_arc,
|
||||
};
|
||||
pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader;
|
||||
|
||||
@@ -2,8 +2,8 @@ use crate::context_deserialize;
|
||||
use crate::{
|
||||
BeaconState, ChainSpec, ContextDeserialize, EthSpec, FixedVector, ForkName, Hash256,
|
||||
LightClientHeader, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderElectra, LightClientHeaderFulu, SignedBlindedBeaconBlock, Slot, SyncCommittee,
|
||||
light_client_update::*, test_utils::TestRandom,
|
||||
LightClientHeaderElectra, LightClientHeaderFulu, LightClientHeaderGloas,
|
||||
SignedBlindedBeaconBlock, Slot, SyncCommittee, light_client_update::*, test_utils::TestRandom,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -17,7 +17,7 @@ use tree_hash_derive::TreeHash;
|
||||
/// A LightClientBootstrap is the initializer we send over to light_client nodes
|
||||
/// that are trying to generate their basic storage when booting up.
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu),
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -62,6 +62,8 @@ pub struct LightClientBootstrap<E: EthSpec> {
|
||||
pub header: LightClientHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "header_fulu"))]
|
||||
pub header: LightClientHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "header_gloas"))]
|
||||
pub header: LightClientHeaderGloas<E>,
|
||||
/// The `SyncCommittee` used in the requested period.
|
||||
pub current_sync_committee: Arc<SyncCommittee<E>>,
|
||||
/// Merkle proof for sync committee
|
||||
@@ -71,7 +73,7 @@ pub struct LightClientBootstrap<E: EthSpec> {
|
||||
)]
|
||||
pub current_sync_committee_branch: FixedVector<Hash256, CurrentSyncCommitteeProofLen>,
|
||||
#[superstruct(
|
||||
only(Electra, Fulu),
|
||||
only(Electra, Fulu, Gloas),
|
||||
partial_getter(rename = "current_sync_committee_branch_electra")
|
||||
)]
|
||||
pub current_sync_committee_branch: FixedVector<Hash256, CurrentSyncCommitteeProofLenElectra>,
|
||||
@@ -88,6 +90,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
Self::Deneb(_) => func(ForkName::Deneb),
|
||||
Self::Electra(_) => func(ForkName::Electra),
|
||||
Self::Fulu(_) => func(ForkName::Fulu),
|
||||
Self::Gloas(_) => func(ForkName::Gloas),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +110,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
ForkName::Deneb => Self::Deneb(LightClientBootstrapDeneb::from_ssz_bytes(bytes)?),
|
||||
ForkName::Electra => Self::Electra(LightClientBootstrapElectra::from_ssz_bytes(bytes)?),
|
||||
ForkName::Fulu => Self::Fulu(LightClientBootstrapFulu::from_ssz_bytes(bytes)?),
|
||||
ForkName::Gloas => Self::Gloas(LightClientBootstrapGloas::from_ssz_bytes(bytes)?),
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientBootstrap decoding for {fork_name} not implemented"
|
||||
@@ -128,6 +132,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
ForkName::Deneb => <LightClientBootstrapDeneb<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Electra => <LightClientBootstrapElectra<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Fulu => <LightClientBootstrapFulu<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Gloas => <LightClientBootstrapGloas<E> as Encode>::ssz_fixed_len(),
|
||||
};
|
||||
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
@@ -168,6 +173,11 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
current_sync_committee,
|
||||
current_sync_committee_branch: current_sync_committee_branch.into(),
|
||||
}),
|
||||
ForkName::Gloas => Self::Gloas(LightClientBootstrapGloas {
|
||||
header: LightClientHeaderGloas::block_to_light_client_header(block)?,
|
||||
current_sync_committee,
|
||||
current_sync_committee_branch: current_sync_committee_branch.into(),
|
||||
}),
|
||||
};
|
||||
|
||||
Ok(light_client_bootstrap)
|
||||
@@ -213,6 +223,11 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
current_sync_committee,
|
||||
current_sync_committee_branch: current_sync_committee_branch.into(),
|
||||
}),
|
||||
ForkName::Gloas => Self::Gloas(LightClientBootstrapGloas {
|
||||
header: LightClientHeaderGloas::block_to_light_client_header(block)?,
|
||||
current_sync_committee,
|
||||
current_sync_committee_branch: current_sync_committee_branch.into(),
|
||||
}),
|
||||
};
|
||||
|
||||
Ok(light_client_bootstrap)
|
||||
@@ -252,6 +267,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientBootstrap
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -288,4 +306,10 @@ mod tests {
|
||||
use crate::{LightClientBootstrapFulu, MainnetEthSpec};
|
||||
ssz_tests!(LightClientBootstrapFulu<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod gloas {
|
||||
use crate::{LightClientBootstrapGloas, MainnetEthSpec};
|
||||
ssz_tests!(LightClientBootstrapGloas<MainnetEthSpec>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ use crate::context_deserialize;
|
||||
use crate::{
|
||||
ContextDeserialize, ForkName, LightClientHeaderAltair, LightClientHeaderCapella,
|
||||
LightClientHeaderDeneb, LightClientHeaderElectra, LightClientHeaderFulu,
|
||||
SignedBlindedBeaconBlock, light_client_update::*, test_utils::TestRandom,
|
||||
LightClientHeaderGloas, SignedBlindedBeaconBlock, light_client_update::*,
|
||||
test_utils::TestRandom,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -16,7 +17,7 @@ use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu),
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -61,6 +62,8 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
|
||||
pub attested_header: LightClientHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "attested_header_fulu"))]
|
||||
pub attested_header: LightClientHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "attested_header_gloas"))]
|
||||
pub attested_header: LightClientHeaderGloas<E>,
|
||||
/// The last `BeaconBlockHeader` from the last attested finalized block (end of epoch).
|
||||
#[superstruct(only(Altair), partial_getter(rename = "finalized_header_altair"))]
|
||||
pub finalized_header: LightClientHeaderAltair<E>,
|
||||
@@ -72,6 +75,8 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
|
||||
pub finalized_header: LightClientHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "finalized_header_fulu"))]
|
||||
pub finalized_header: LightClientHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "finalized_header_gloas"))]
|
||||
pub finalized_header: LightClientHeaderGloas<E>,
|
||||
/// Merkle proof attesting finalized header.
|
||||
#[superstruct(
|
||||
only(Altair, Capella, Deneb),
|
||||
@@ -79,7 +84,7 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
|
||||
)]
|
||||
pub finality_branch: FixedVector<Hash256, FinalizedRootProofLen>,
|
||||
#[superstruct(
|
||||
only(Electra, Fulu),
|
||||
only(Electra, Fulu, Gloas),
|
||||
partial_getter(rename = "finality_branch_electra")
|
||||
)]
|
||||
pub finality_branch: FixedVector<Hash256, FinalizedRootProofLenElectra>,
|
||||
@@ -160,6 +165,17 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Gloas => Self::Gloas(LightClientFinalityUpdateGloas {
|
||||
attested_header: LightClientHeaderGloas::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
finalized_header: LightClientHeaderGloas::block_to_light_client_header(
|
||||
finalized_block,
|
||||
)?,
|
||||
finality_branch: finality_branch.into(),
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
|
||||
ForkName::Base => return Err(Error::AltairForkNotActive),
|
||||
};
|
||||
@@ -177,6 +193,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
Self::Deneb(_) => func(ForkName::Deneb),
|
||||
Self::Electra(_) => func(ForkName::Electra),
|
||||
Self::Fulu(_) => func(ForkName::Fulu),
|
||||
Self::Gloas(_) => func(ForkName::Gloas),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +231,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
Self::Electra(LightClientFinalityUpdateElectra::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Fulu => Self::Fulu(LightClientFinalityUpdateFulu::from_ssz_bytes(bytes)?),
|
||||
ForkName::Gloas => Self::Gloas(LightClientFinalityUpdateGloas::from_ssz_bytes(bytes)?),
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientFinalityUpdate decoding for {fork_name} not implemented"
|
||||
@@ -235,6 +253,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
ForkName::Deneb => <LightClientFinalityUpdateDeneb<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Electra => <LightClientFinalityUpdateElectra<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Fulu => <LightClientFinalityUpdateFulu<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Gloas => <LightClientFinalityUpdateGloas<E> as Encode>::ssz_fixed_len(),
|
||||
};
|
||||
// `2 *` because there are two headers in the update
|
||||
fixed_size + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
@@ -287,6 +306,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientFinalityU
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -323,4 +345,10 @@ mod tests {
|
||||
use crate::{LightClientFinalityUpdateFulu, MainnetEthSpec};
|
||||
ssz_tests!(LightClientFinalityUpdateFulu<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod gloas {
|
||||
use crate::{LightClientFinalityUpdateGloas, MainnetEthSpec};
|
||||
ssz_tests!(LightClientFinalityUpdateGloas<MainnetEthSpec>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::{BeaconBlockHeader, ExecutionPayloadHeader};
|
||||
use crate::{ContextDeserialize, ForkName};
|
||||
use crate::{
|
||||
EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
||||
ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu, FixedVector, Hash256,
|
||||
SignedBlindedBeaconBlock, test_utils::TestRandom,
|
||||
ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderGloas,
|
||||
FixedVector, Hash256, SignedBlindedBeaconBlock, test_utils::TestRandom,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -18,7 +18,7 @@ use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu),
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -68,8 +68,10 @@ pub struct LightClientHeader<E: EthSpec> {
|
||||
pub execution: ExecutionPayloadHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_header_fulu"))]
|
||||
pub execution: ExecutionPayloadHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_header_gloas"))]
|
||||
pub execution: ExecutionPayloadHeaderGloas<E>,
|
||||
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu))]
|
||||
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
|
||||
pub execution_branch: FixedVector<Hash256, ExecutionPayloadProofLen>,
|
||||
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
@@ -104,6 +106,9 @@ impl<E: EthSpec> LightClientHeader<E> {
|
||||
ForkName::Fulu => {
|
||||
LightClientHeader::Fulu(LightClientHeaderFulu::block_to_light_client_header(block)?)
|
||||
}
|
||||
ForkName::Gloas => LightClientHeader::Gloas(
|
||||
LightClientHeaderGloas::block_to_light_client_header(block)?,
|
||||
),
|
||||
};
|
||||
Ok(header)
|
||||
}
|
||||
@@ -125,6 +130,9 @@ impl<E: EthSpec> LightClientHeader<E> {
|
||||
ForkName::Fulu => {
|
||||
LightClientHeader::Fulu(LightClientHeaderFulu::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
LightClientHeader::Gloas(LightClientHeaderGloas::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientHeader decoding for {fork_name} not implemented"
|
||||
@@ -340,6 +348,48 @@ impl<E: EthSpec> Default for LightClientHeaderFulu<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> LightClientHeaderGloas<E> {
|
||||
pub fn block_to_light_client_header(
|
||||
block: &SignedBlindedBeaconBlock<E>,
|
||||
) -> Result<Self, Error> {
|
||||
let payload = block
|
||||
.message()
|
||||
.execution_payload()?
|
||||
.execution_payload_gloas()?;
|
||||
|
||||
let header = ExecutionPayloadHeaderGloas::from(payload);
|
||||
let beacon_block_body = BeaconBlockBody::from(
|
||||
block
|
||||
.message()
|
||||
.body_gloas()
|
||||
.map_err(|_| Error::BeaconBlockBodyError)?
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
let execution_branch = beacon_block_body
|
||||
.to_ref()
|
||||
.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
|
||||
Ok(LightClientHeaderGloas {
|
||||
beacon: block.message().block_header(),
|
||||
execution: header,
|
||||
execution_branch: FixedVector::new(execution_branch)?,
|
||||
_phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Default for LightClientHeaderGloas<E> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
beacon: BeaconBlockHeader::empty(),
|
||||
execution: ExecutionPayloadHeaderGloas::default(),
|
||||
execution_branch: FixedVector::default(),
|
||||
_phantom_data: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientHeader<E> {
|
||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -373,6 +423,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientHeader<E>
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -403,4 +456,16 @@ mod tests {
|
||||
use crate::{LightClientHeaderElectra, MainnetEthSpec};
|
||||
ssz_tests!(LightClientHeaderElectra<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod fulu {
|
||||
use crate::{LightClientHeaderFulu, MainnetEthSpec};
|
||||
ssz_tests!(LightClientHeaderFulu<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod gloas {
|
||||
use crate::{LightClientHeaderGloas, MainnetEthSpec};
|
||||
ssz_tests!(LightClientHeaderGloas<MainnetEthSpec>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ use crate::context_deserialize;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
ChainSpec, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderElectra, LightClientHeaderFulu, SignedBlindedBeaconBlock,
|
||||
light_client_update::*,
|
||||
LightClientHeaderElectra, LightClientHeaderFulu, LightClientHeaderGloas,
|
||||
SignedBlindedBeaconBlock, light_client_update::*,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -19,7 +19,7 @@ use tree_hash_derive::TreeHash;
|
||||
/// A LightClientOptimisticUpdate is the update we send on each slot,
|
||||
/// it is based off the current unfinalized epoch is verified only against BLS signature.
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu),
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -64,6 +64,8 @@ pub struct LightClientOptimisticUpdate<E: EthSpec> {
|
||||
pub attested_header: LightClientHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "attested_header_fulu"))]
|
||||
pub attested_header: LightClientHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "attested_header_gloas"))]
|
||||
pub attested_header: LightClientHeaderGloas<E>,
|
||||
/// current sync aggregate
|
||||
pub sync_aggregate: SyncAggregate<E>,
|
||||
/// Slot of the sync aggregated signature
|
||||
@@ -119,6 +121,13 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Gloas => Self::Gloas(LightClientOptimisticUpdateGloas {
|
||||
attested_header: LightClientHeaderGloas::block_to_light_client_header(
|
||||
attested_block,
|
||||
)?,
|
||||
sync_aggregate,
|
||||
signature_slot,
|
||||
}),
|
||||
ForkName::Base => return Err(Error::AltairForkNotActive),
|
||||
};
|
||||
|
||||
@@ -135,6 +144,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
Self::Deneb(_) => func(ForkName::Deneb),
|
||||
Self::Electra(_) => func(ForkName::Electra),
|
||||
Self::Fulu(_) => func(ForkName::Fulu),
|
||||
Self::Gloas(_) => func(ForkName::Gloas),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +184,9 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
Self::Electra(LightClientOptimisticUpdateElectra::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Fulu => Self::Fulu(LightClientOptimisticUpdateFulu::from_ssz_bytes(bytes)?),
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(LightClientOptimisticUpdateGloas::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientOptimisticUpdate decoding for {fork_name} not implemented"
|
||||
@@ -195,6 +208,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
ForkName::Deneb => <LightClientOptimisticUpdateDeneb<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Electra => <LightClientOptimisticUpdateElectra<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Fulu => <LightClientOptimisticUpdateFulu<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Gloas => <LightClientOptimisticUpdateGloas<E> as Encode>::ssz_fixed_len(),
|
||||
};
|
||||
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
@@ -246,6 +260,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientOptimisti
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -282,4 +299,10 @@ mod tests {
|
||||
use crate::{LightClientOptimisticUpdateFulu, MainnetEthSpec};
|
||||
ssz_tests!(LightClientOptimisticUpdateFulu<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod gloas {
|
||||
use crate::{LightClientOptimisticUpdateGloas, MainnetEthSpec};
|
||||
ssz_tests!(LightClientOptimisticUpdateGloas<MainnetEthSpec>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::light_client_header::LightClientHeaderElectra;
|
||||
use crate::{
|
||||
ChainSpec, ContextDeserialize, Epoch, ForkName, LightClientHeaderAltair,
|
||||
LightClientHeaderCapella, LightClientHeaderDeneb, LightClientHeaderFulu,
|
||||
SignedBlindedBeaconBlock, beacon_state, test_utils::TestRandom,
|
||||
LightClientHeaderGloas, SignedBlindedBeaconBlock, beacon_state, test_utils::TestRandom,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use safe_arith::ArithError;
|
||||
@@ -100,7 +100,7 @@ impl From<milhouse::Error> for Error {
|
||||
/// or to sync up to the last committee period, we need to have one ready for each ALTAIR period
|
||||
/// we go over, note: there is no need to keep all of the updates from [ALTAIR_PERIOD, CURRENT_PERIOD].
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu),
|
||||
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -145,6 +145,8 @@ pub struct LightClientUpdate<E: EthSpec> {
|
||||
pub attested_header: LightClientHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "attested_header_fulu"))]
|
||||
pub attested_header: LightClientHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "attested_header_gloas"))]
|
||||
pub attested_header: LightClientHeaderGloas<E>,
|
||||
/// The `SyncCommittee` used in the next period.
|
||||
pub next_sync_committee: Arc<SyncCommittee<E>>,
|
||||
// Merkle proof for next sync committee
|
||||
@@ -154,7 +156,7 @@ pub struct LightClientUpdate<E: EthSpec> {
|
||||
)]
|
||||
pub next_sync_committee_branch: NextSyncCommitteeBranch,
|
||||
#[superstruct(
|
||||
only(Electra, Fulu),
|
||||
only(Electra, Fulu, Gloas),
|
||||
partial_getter(rename = "next_sync_committee_branch_electra")
|
||||
)]
|
||||
pub next_sync_committee_branch: NextSyncCommitteeBranchElectra,
|
||||
@@ -169,6 +171,8 @@ pub struct LightClientUpdate<E: EthSpec> {
|
||||
pub finalized_header: LightClientHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "finalized_header_fulu"))]
|
||||
pub finalized_header: LightClientHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "finalized_header_gloas"))]
|
||||
pub finalized_header: LightClientHeaderGloas<E>,
|
||||
/// Merkle proof attesting finalized header.
|
||||
#[superstruct(
|
||||
only(Altair, Capella, Deneb),
|
||||
@@ -176,7 +180,7 @@ pub struct LightClientUpdate<E: EthSpec> {
|
||||
)]
|
||||
pub finality_branch: FinalityBranch,
|
||||
#[superstruct(
|
||||
only(Electra, Fulu),
|
||||
only(Electra, Fulu, Gloas),
|
||||
partial_getter(rename = "finality_branch_electra")
|
||||
)]
|
||||
pub finality_branch: FinalityBranchElectra,
|
||||
@@ -216,6 +220,9 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientUpdate<E>
|
||||
ForkName::Fulu => {
|
||||
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
ForkName::Gloas => {
|
||||
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -356,6 +363,30 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
sync_aggregate: sync_aggregate.clone(),
|
||||
signature_slot: block_slot,
|
||||
})
|
||||
}
|
||||
fork_name @ ForkName::Gloas => {
|
||||
let attested_header =
|
||||
LightClientHeaderGloas::block_to_light_client_header(attested_block)?;
|
||||
|
||||
let finalized_header = if let Some(finalized_block) = finalized_block {
|
||||
if finalized_block.fork_name_unchecked() == fork_name {
|
||||
LightClientHeaderGloas::block_to_light_client_header(finalized_block)?
|
||||
} else {
|
||||
LightClientHeaderGloas::default()
|
||||
}
|
||||
} else {
|
||||
LightClientHeaderGloas::default()
|
||||
};
|
||||
|
||||
Self::Gloas(LightClientUpdateGloas {
|
||||
attested_header,
|
||||
next_sync_committee,
|
||||
next_sync_committee_branch: next_sync_committee_branch.into(),
|
||||
finalized_header,
|
||||
finality_branch: finality_branch.into(),
|
||||
sync_aggregate: sync_aggregate.clone(),
|
||||
signature_slot: block_slot,
|
||||
})
|
||||
} // To add a new fork, just append the new fork variant on the latest fork. Forks that
|
||||
// have a distinct execution header will need a new LightClientUpdate variant only
|
||||
// if you need to test or support lightclient usages
|
||||
@@ -373,6 +404,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
ForkName::Deneb => Self::Deneb(LightClientUpdateDeneb::from_ssz_bytes(bytes)?),
|
||||
ForkName::Electra => Self::Electra(LightClientUpdateElectra::from_ssz_bytes(bytes)?),
|
||||
ForkName::Fulu => Self::Fulu(LightClientUpdateFulu::from_ssz_bytes(bytes)?),
|
||||
ForkName::Gloas => Self::Gloas(LightClientUpdateGloas::from_ssz_bytes(bytes)?),
|
||||
ForkName::Base => {
|
||||
return Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"LightClientUpdate decoding for {fork_name} not implemented"
|
||||
@@ -390,6 +422,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
LightClientUpdate::Deneb(update) => update.attested_header.beacon.slot,
|
||||
LightClientUpdate::Electra(update) => update.attested_header.beacon.slot,
|
||||
LightClientUpdate::Fulu(update) => update.attested_header.beacon.slot,
|
||||
LightClientUpdate::Gloas(update) => update.attested_header.beacon.slot,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,6 +433,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
LightClientUpdate::Deneb(update) => update.finalized_header.beacon.slot,
|
||||
LightClientUpdate::Electra(update) => update.finalized_header.beacon.slot,
|
||||
LightClientUpdate::Fulu(update) => update.finalized_header.beacon.slot,
|
||||
LightClientUpdate::Gloas(update) => update.finalized_header.beacon.slot,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,6 +554,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
ForkName::Deneb => <LightClientUpdateDeneb<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Electra => <LightClientUpdateElectra<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Fulu => <LightClientUpdateFulu<E> as Encode>::ssz_fixed_len(),
|
||||
ForkName::Gloas => <LightClientUpdateGloas<E> as Encode>::ssz_fixed_len(),
|
||||
};
|
||||
fixed_len + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
|
||||
}
|
||||
@@ -534,6 +569,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
Self::Deneb(_) => func(ForkName::Deneb),
|
||||
Self::Electra(_) => func(ForkName::Electra),
|
||||
Self::Fulu(_) => func(ForkName::Fulu),
|
||||
Self::Gloas(_) => func(ForkName::Gloas),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -596,6 +632,13 @@ mod tests {
|
||||
ssz_tests!(LightClientUpdateFulu<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod gloas {
|
||||
use super::*;
|
||||
use crate::MainnetEthSpec;
|
||||
ssz_tests!(LightClientUpdateGloas<MainnetEthSpec>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finalized_root_params() {
|
||||
assert!(2usize.pow(FINALIZED_ROOT_PROOF_LEN as u32) <= FINALIZED_ROOT_INDEX);
|
||||
|
||||
@@ -105,6 +105,7 @@ pub trait AbstractExecPayload<E: EthSpec>:
|
||||
+ TryInto<Self::Deneb>
|
||||
+ TryInto<Self::Electra>
|
||||
+ TryInto<Self::Fulu>
|
||||
+ TryInto<Self::Gloas>
|
||||
+ Sync
|
||||
{
|
||||
type Ref<'a>: ExecPayload<E>
|
||||
@@ -113,7 +114,8 @@ pub trait AbstractExecPayload<E: EthSpec>:
|
||||
+ From<&'a Self::Capella>
|
||||
+ From<&'a Self::Deneb>
|
||||
+ From<&'a Self::Electra>
|
||||
+ From<&'a Self::Fulu>;
|
||||
+ From<&'a Self::Fulu>
|
||||
+ From<&'a Self::Gloas>;
|
||||
|
||||
type Bellatrix: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
@@ -140,10 +142,15 @@ pub trait AbstractExecPayload<E: EthSpec>:
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadFulu<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderFulu<E>>
|
||||
+ Sync;
|
||||
type Gloas: OwnedExecPayload<E>
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadGloas<E>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderGloas<E>>
|
||||
+ Sync;
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -198,6 +205,8 @@ pub struct FullPayload<E: EthSpec> {
|
||||
pub execution_payload: ExecutionPayloadElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
|
||||
pub execution_payload: ExecutionPayloadFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
|
||||
pub execution_payload: ExecutionPayloadGloas<E>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<FullPayload<E>> for ExecutionPayload<E> {
|
||||
@@ -309,6 +318,7 @@ impl<E: EthSpec> ExecPayload<E> for FullPayload<E> {
|
||||
FullPayload::Deneb(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
|
||||
FullPayload::Electra(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
|
||||
FullPayload::Fulu(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
|
||||
FullPayload::Gloas(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,6 +330,7 @@ impl<E: EthSpec> ExecPayload<E> for FullPayload<E> {
|
||||
FullPayload::Deneb(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
FullPayload::Electra(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
FullPayload::Fulu(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
FullPayload::Gloas(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,6 +362,7 @@ impl<E: EthSpec> FullPayload<E> {
|
||||
ForkName::Deneb => Ok(FullPayloadDeneb::default().into()),
|
||||
ForkName::Electra => Ok(FullPayloadElectra::default().into()),
|
||||
ForkName::Fulu => Ok(FullPayloadFulu::default().into()),
|
||||
ForkName::Gloas => Ok(FullPayloadGloas::default().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -451,6 +463,9 @@ impl<E: EthSpec> ExecPayload<E> for FullPayloadRef<'_, E> {
|
||||
Ok(inner.execution_payload.withdrawals.tree_hash_root())
|
||||
}
|
||||
FullPayloadRef::Fulu(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
|
||||
FullPayloadRef::Gloas(inner) => {
|
||||
Ok(inner.execution_payload.withdrawals.tree_hash_root())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,6 +477,7 @@ impl<E: EthSpec> ExecPayload<E> for FullPayloadRef<'_, E> {
|
||||
FullPayloadRef::Deneb(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
FullPayloadRef::Electra(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
FullPayloadRef::Fulu(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
FullPayloadRef::Gloas(inner) => Ok(inner.execution_payload.blob_gas_used),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,6 +501,7 @@ impl<E: EthSpec> AbstractExecPayload<E> for FullPayload<E> {
|
||||
type Deneb = FullPayloadDeneb<E>;
|
||||
type Electra = FullPayloadElectra<E>;
|
||||
type Fulu = FullPayloadFulu<E>;
|
||||
type Gloas = FullPayloadGloas<E>;
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<ExecutionPayload<E>> for FullPayload<E> {
|
||||
@@ -503,7 +520,7 @@ impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for FullPayload<E> {
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -557,6 +574,8 @@ pub struct BlindedPayload<E: EthSpec> {
|
||||
pub execution_payload_header: ExecutionPayloadHeaderElectra<E>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
|
||||
pub execution_payload_header: ExecutionPayloadHeaderFulu<E>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
|
||||
pub execution_payload_header: ExecutionPayloadHeaderGloas<E>,
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec> From<BlindedPayloadRef<'a, E>> for BlindedPayload<E> {
|
||||
@@ -646,6 +665,7 @@ impl<E: EthSpec> ExecPayload<E> for BlindedPayload<E> {
|
||||
BlindedPayload::Deneb(inner) => Ok(inner.execution_payload_header.withdrawals_root),
|
||||
BlindedPayload::Electra(inner) => Ok(inner.execution_payload_header.withdrawals_root),
|
||||
BlindedPayload::Fulu(inner) => Ok(inner.execution_payload_header.withdrawals_root),
|
||||
BlindedPayload::Gloas(inner) => Ok(inner.execution_payload_header.withdrawals_root),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,6 +677,7 @@ impl<E: EthSpec> ExecPayload<E> for BlindedPayload<E> {
|
||||
BlindedPayload::Deneb(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
BlindedPayload::Electra(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
BlindedPayload::Fulu(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
BlindedPayload::Gloas(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,6 +777,7 @@ impl<'b, E: EthSpec> ExecPayload<E> for BlindedPayloadRef<'b, E> {
|
||||
Ok(inner.execution_payload_header.withdrawals_root)
|
||||
}
|
||||
BlindedPayloadRef::Fulu(inner) => Ok(inner.execution_payload_header.withdrawals_root),
|
||||
BlindedPayloadRef::Gloas(inner) => Ok(inner.execution_payload_header.withdrawals_root),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,6 +789,7 @@ impl<'b, E: EthSpec> ExecPayload<E> for BlindedPayloadRef<'b, E> {
|
||||
BlindedPayloadRef::Deneb(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
BlindedPayloadRef::Electra(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
BlindedPayloadRef::Fulu(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
BlindedPayloadRef::Gloas(inner) => Ok(inner.execution_payload_header.blob_gas_used),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1077,6 +1100,13 @@ impl_exec_payload_for_fork!(
|
||||
ExecutionPayloadFulu,
|
||||
Fulu
|
||||
);
|
||||
impl_exec_payload_for_fork!(
|
||||
BlindedPayloadGloas,
|
||||
FullPayloadGloas,
|
||||
ExecutionPayloadHeaderGloas,
|
||||
ExecutionPayloadGloas,
|
||||
Gloas
|
||||
);
|
||||
|
||||
impl<E: EthSpec> AbstractExecPayload<E> for BlindedPayload<E> {
|
||||
type Ref<'a> = BlindedPayloadRef<'a, E>;
|
||||
@@ -1085,6 +1115,7 @@ impl<E: EthSpec> AbstractExecPayload<E> for BlindedPayload<E> {
|
||||
type Deneb = BlindedPayloadDeneb<E>;
|
||||
type Electra = BlindedPayloadElectra<E>;
|
||||
type Fulu = BlindedPayloadFulu<E>;
|
||||
type Gloas = BlindedPayloadGloas<E>;
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<ExecutionPayload<E>> for BlindedPayload<E> {
|
||||
@@ -1126,6 +1157,11 @@ impl<E: EthSpec> From<ExecutionPayloadHeader<E>> for BlindedPayload<E> {
|
||||
execution_payload_header,
|
||||
})
|
||||
}
|
||||
ExecutionPayloadHeader::Gloas(execution_payload_header) => {
|
||||
Self::Gloas(BlindedPayloadGloas {
|
||||
execution_payload_header,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1148,6 +1184,9 @@ impl<E: EthSpec> From<BlindedPayload<E>> for ExecutionPayloadHeader<E> {
|
||||
BlindedPayload::Fulu(blinded_payload) => {
|
||||
ExecutionPayloadHeader::Fulu(blinded_payload.execution_payload_header)
|
||||
}
|
||||
BlindedPayload::Gloas(blinded_payload) => {
|
||||
ExecutionPayloadHeader::Gloas(blinded_payload.execution_payload_header)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +316,16 @@ impl FuluPreset {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
pub struct GloasPreset {}
|
||||
|
||||
impl GloasPreset {
|
||||
pub fn from_chain_spec<E: EthSpec>(_spec: &ChainSpec) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@@ -363,6 +373,9 @@ mod test {
|
||||
|
||||
let fulu: FuluPreset = preset_from_file(&preset_name, "fulu.yaml");
|
||||
assert_eq!(fulu, FuluPreset::from_chain_spec::<E>(&spec));
|
||||
|
||||
let gloas: GloasPreset = preset_from_file(&preset_name, "gloas.yaml");
|
||||
assert_eq!(gloas, GloasPreset::from_chain_spec::<E>(&spec));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -41,7 +41,7 @@ impl From<SignedBeaconBlockHash> for Hash256 {
|
||||
|
||||
/// A `BeaconBlock` and a signature from its proposer.
|
||||
#[superstruct(
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu),
|
||||
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -92,6 +92,8 @@ pub struct SignedBeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E> = FullP
|
||||
pub message: BeaconBlockElectra<E, Payload>,
|
||||
#[superstruct(only(Fulu), partial_getter(rename = "message_fulu"))]
|
||||
pub message: BeaconBlockFulu<E, Payload>,
|
||||
#[superstruct(only(Gloas), partial_getter(rename = "message_gloas"))]
|
||||
pub message: BeaconBlockGloas<E, Payload>,
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
@@ -178,6 +180,9 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload>
|
||||
BeaconBlock::Fulu(message) => {
|
||||
SignedBeaconBlock::Fulu(SignedBeaconBlockFulu { message, signature })
|
||||
}
|
||||
BeaconBlock::Gloas(message) => {
|
||||
SignedBeaconBlock::Gloas(SignedBeaconBlockGloas { message, signature })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,6 +648,64 @@ impl<E: EthSpec> SignedBeaconBlockFulu<E, BlindedPayload<E>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> SignedBeaconBlockGloas<E, BlindedPayload<E>> {
|
||||
pub fn into_full_block(
|
||||
self,
|
||||
execution_payload: ExecutionPayloadGloas<E>,
|
||||
) -> SignedBeaconBlockGloas<E, FullPayload<E>> {
|
||||
let SignedBeaconBlockGloas {
|
||||
message:
|
||||
BeaconBlockGloas {
|
||||
slot,
|
||||
proposer_index,
|
||||
parent_root,
|
||||
state_root,
|
||||
body:
|
||||
BeaconBlockBodyGloas {
|
||||
randao_reveal,
|
||||
eth1_data,
|
||||
graffiti,
|
||||
proposer_slashings,
|
||||
attester_slashings,
|
||||
attestations,
|
||||
deposits,
|
||||
voluntary_exits,
|
||||
sync_aggregate,
|
||||
execution_payload: BlindedPayloadGloas { .. },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
execution_requests,
|
||||
},
|
||||
},
|
||||
signature,
|
||||
} = self;
|
||||
SignedBeaconBlockGloas {
|
||||
message: BeaconBlockGloas {
|
||||
slot,
|
||||
proposer_index,
|
||||
parent_root,
|
||||
state_root,
|
||||
body: BeaconBlockBodyGloas {
|
||||
randao_reveal,
|
||||
eth1_data,
|
||||
graffiti,
|
||||
proposer_slashings,
|
||||
attester_slashings,
|
||||
attestations,
|
||||
deposits,
|
||||
voluntary_exits,
|
||||
sync_aggregate,
|
||||
execution_payload: FullPayloadGloas { execution_payload },
|
||||
bls_to_execution_changes,
|
||||
blob_kzg_commitments,
|
||||
execution_requests,
|
||||
},
|
||||
},
|
||||
signature,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
|
||||
pub fn try_into_full_block(
|
||||
self,
|
||||
@@ -666,6 +729,9 @@ impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
|
||||
(SignedBeaconBlock::Fulu(block), Some(ExecutionPayload::Fulu(payload))) => {
|
||||
SignedBeaconBlock::Fulu(block.into_full_block(payload))
|
||||
}
|
||||
(SignedBeaconBlock::Gloas(block), Some(ExecutionPayload::Gloas(payload))) => {
|
||||
SignedBeaconBlock::Gloas(block.into_full_block(payload))
|
||||
}
|
||||
// avoid wildcard matching forks so that compiler will
|
||||
// direct us here when a new fork has been added
|
||||
(SignedBeaconBlock::Bellatrix(_), _) => return None,
|
||||
@@ -673,6 +739,7 @@ impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
|
||||
(SignedBeaconBlock::Deneb(_), _) => return None,
|
||||
(SignedBeaconBlock::Electra(_), _) => return None,
|
||||
(SignedBeaconBlock::Fulu(_), _) => return None,
|
||||
(SignedBeaconBlock::Gloas(_), _) => return None,
|
||||
};
|
||||
Some(full_block)
|
||||
}
|
||||
@@ -818,6 +885,9 @@ pub mod ssz_tagged_signed_beacon_block {
|
||||
ForkName::Fulu => Ok(SignedBeaconBlock::Fulu(
|
||||
SignedBeaconBlockFulu::from_ssz_bytes(body)?,
|
||||
)),
|
||||
ForkName::Gloas => Ok(SignedBeaconBlock::Gloas(
|
||||
SignedBeaconBlockGloas::from_ssz_bytes(body)?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -897,6 +967,7 @@ mod test {
|
||||
chain_spec.deneb_fork_epoch = Some(Epoch::new(4));
|
||||
chain_spec.electra_fork_epoch = Some(Epoch::new(5));
|
||||
chain_spec.fulu_fork_epoch = Some(Epoch::new(6));
|
||||
chain_spec.gloas_fork_epoch = Some(Epoch::new(7));
|
||||
|
||||
// check that we have all forks covered
|
||||
assert!(chain_spec.fork_epoch(ForkName::latest()).is_some());
|
||||
@@ -934,7 +1005,11 @@ mod test {
|
||||
BeaconBlock::Electra(BeaconBlockElectra::empty(spec)),
|
||||
sig.clone(),
|
||||
),
|
||||
SignedBeaconBlock::from_block(BeaconBlock::Fulu(BeaconBlockFulu::empty(spec)), sig),
|
||||
SignedBeaconBlock::from_block(
|
||||
BeaconBlock::Fulu(BeaconBlockFulu::empty(spec)),
|
||||
sig.clone(),
|
||||
),
|
||||
SignedBeaconBlock::from_block(BeaconBlock::Gloas(BeaconBlockGloas::empty(spec)), sig),
|
||||
];
|
||||
|
||||
for block in blocks {
|
||||
|
||||
Reference in New Issue
Block a user