-
Notifications
You must be signed in to change notification settings - Fork 971
fix: repair Gloas block replay crash with IncorrectStateVariant #8876
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -780,6 +780,42 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold> | |
| .map(|payload| payload.is_some()) | ||
| } | ||
|
|
||
| /// Store a Gloas (EIP-7732) execution payload envelope in the hot database. | ||
| /// | ||
| /// The key is the execution `block_hash` committed to by the builder in the corresponding | ||
| /// `signed_execution_payload_bid`. This allows efficient lookup during block replay using | ||
| /// only the information present in each block's bid header. | ||
| pub fn put_execution_payload_envelope( | ||
| &self, | ||
| exec_block_hash: &ExecutionBlockHash, | ||
| envelope: &SignedExecutionPayloadEnvelope<E>, | ||
| ops: &mut Vec<KeyValueStoreOp>, | ||
| ) { | ||
| ops.push(KeyValueStoreOp::PutKeyValue( | ||
| DBColumn::ExecPayloadEnvelope, | ||
| exec_block_hash.as_ssz_bytes(), | ||
| envelope.as_ssz_bytes(), | ||
| )); | ||
| } | ||
|
|
||
| /// Load a Gloas (EIP-7732) execution payload envelope by the execution block hash. | ||
| /// | ||
| /// Returns `None` when no envelope has been stored for the given hash (e.g. the builder did | ||
| /// not deliver the payload for that slot, or envelope storage is not yet implemented for the | ||
| /// current database schema). | ||
| pub fn get_execution_payload_envelope( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we already have a function |
||
| &self, | ||
| exec_block_hash: &ExecutionBlockHash, | ||
| ) -> Result<Option<SignedExecutionPayloadEnvelope<E>>, Error> { | ||
| let key = exec_block_hash.as_ssz_bytes(); | ||
| match self.hot_db.get_bytes(DBColumn::ExecPayloadEnvelope, &key)? { | ||
| Some(bytes) => Ok(Some(SignedExecutionPayloadEnvelope::from_ssz_bytes( | ||
| &bytes, | ||
| )?)), | ||
| None => Ok(None), | ||
| } | ||
| } | ||
|
|
||
| /// Get the sync committee branch for the given block root | ||
| /// Note: we only persist sync committee branches for checkpoint slots | ||
| pub fn get_sync_committee_branch( | ||
|
|
@@ -2476,6 +2512,28 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold> | |
| block_replayer = block_replayer.pre_slot_hook(pre_slot_hook); | ||
| } | ||
|
|
||
| // For Gloas (EIP-7732) replay: attempt to load the execution payload envelope for each | ||
| // block from the hot DB, keyed by the execution block hash that the builder committed to. | ||
| // If any block is a Gloas block, we build the envelope map and wire it into BlockReplayer | ||
| // so the look-ahead logic can apply envelopes between consecutive blocks. | ||
| let any_gloas = blocks | ||
| .iter() | ||
| .any(|b| b.fork_name(&self.spec).is_ok_and(|f| f.gloas_enabled())); | ||
| if any_gloas { | ||
| let mut envelopes = HashMap::new(); | ||
| for block in &blocks { | ||
| if let Ok(ForkName::Gloas) = block.fork_name(&self.spec) | ||
| && let BeaconBlockBodyRef::Gloas(body) = block.message().body() | ||
| { | ||
| let bid_hash = body.signed_execution_payload_bid.message.block_hash; | ||
| if let Some(envelope) = self.get_execution_payload_envelope(&bid_hash)? { | ||
| envelopes.insert(bid_hash, envelope.message); | ||
| } | ||
| } | ||
| } | ||
| block_replayer = block_replayer.payload_envelopes(envelopes); | ||
| } | ||
|
|
||
| block_replayer | ||
| .apply_blocks(blocks, Some(target_slot)) | ||
| .map(|block_replayer| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -310,6 +310,12 @@ pub enum DBColumn { | |
| /// Execution payloads for blocks more recent than the finalized checkpoint. | ||
| #[strum(serialize = "exp")] | ||
| ExecPayload, | ||
| /// Execution payload envelopes for Gloas (EIP-7732) blocks in the hot database. | ||
| /// | ||
| /// - Key: 32-byte execution `block_hash` from the block's `signed_execution_payload_bid`. | ||
| /// - Value: SSZ-encoded `SignedExecutionPayloadEnvelope`. | ||
| #[strum(serialize = "ppe")] | ||
| ExecPayloadEnvelope, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have a |
||
| /// For persisting in-memory state to the database. | ||
| #[strum(serialize = "bch")] | ||
| BeaconChain, | ||
|
|
@@ -413,6 +419,7 @@ impl DBColumn { | |
| | Self::BeaconColdStateSummary | ||
| | Self::BeaconStateTemporary | ||
| | Self::ExecPayload | ||
| | Self::ExecPayloadEnvelope | ||
| | Self::BeaconChain | ||
| | Self::OpPool | ||
| | Self::Eth1Cache | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we already have a function
payload_envelope_as_kv_store_opsthat does this