diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 275297133f..3a8672ddd8 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -1558,7 +1558,11 @@ impl ExecutionPendingBlock { let distance = block.slot().as_u64().saturating_sub(state.slot().as_u64()); for _ in 0..distance { - let state_root = if parent.beacon_block.slot() == state.slot() { + // TODO(gloas): could do a similar optimisation here for Full blocks if we have access + // to the parent envelope and its `state_root`. + let state_root = if parent.beacon_block.slot() == state.slot() + && state.payload_status() == StatePayloadStatus::Pending + { // If it happens that `pre_state` has *not* already been advanced forward a single // slot, then there is no need to compute the state root for this // `per_slot_processing` call since that state root is already stored in the parent @@ -1997,24 +2001,26 @@ fn load_parent>( // Post-Gloas we must also fetch a state with the correct payload status. If the current // block builds upon the payload of its parent block, then we know the parent block is FULL // and we need to load the full state. - let payload_status = if block.as_block().fork_name_unchecked().gloas_enabled() { - let parent_bid_block_hash = parent_block.payload_bid_block_hash()?; - if block.as_block().is_parent_block_full(parent_bid_block_hash) { - StatePayloadStatus::Full + let (payload_status, parent_state_root) = + if block.as_block().fork_name_unchecked().gloas_enabled() { + let parent_bid_block_hash = parent_block.payload_bid_block_hash()?; + if block.as_block().is_parent_block_full(parent_bid_block_hash) { + // TODO(gloas): loading the envelope here is not very efficient + let envelope = chain.store.get_payload_envelope(&root)?.ok_or_else(|| { + BeaconChainError::DBInconsistent(format!( + "Missing envelope for parent block {root:?}", + )) + })?; + (StatePayloadStatus::Full, envelope.message.state_root) + } else { + (StatePayloadStatus::Pending, parent_block.state_root()) + } } else { - StatePayloadStatus::Pending - } - } else { - StatePayloadStatus::Pending - }; + (StatePayloadStatus::Pending, parent_block.state_root()) + }; let (parent_state_root, state) = chain .store - .get_advanced_hot_state( - root, - payload_status, - block.slot(), - parent_block.state_root(), - )? + .get_advanced_hot_state(root, payload_status, block.slot(), parent_state_root)? .ok_or_else(|| { BeaconChainError::DBInconsistent( format!("Missing state for parent block {root:?}",), diff --git a/beacon_node/beacon_chain/tests/store_tests.rs b/beacon_node/beacon_chain/tests/store_tests.rs index 770d3ababd..8e10f0e85f 100644 --- a/beacon_node/beacon_chain/tests/store_tests.rs +++ b/beacon_node/beacon_chain/tests/store_tests.rs @@ -5477,9 +5477,11 @@ async fn test_gloas_block_and_envelope_storage() { // Process the envelope. let envelope = envelope.expect("Gloas block should have envelope"); let mut full_state = pending_state.clone(); + let envelope_state_root = envelope.message.state_root; let full_state_root = harness .process_envelope(block_root, envelope, &mut full_state) .await; + assert_eq!(full_state_root, envelope_state_root); full_state_roots.push(full_state_root); block_roots.push(block_root); diff --git a/consensus/state_processing/src/state_advance.rs b/consensus/state_processing/src/state_advance.rs index 11a956bc2a..b1d8770d4f 100644 --- a/consensus/state_processing/src/state_advance.rs +++ b/consensus/state_processing/src/state_advance.rs @@ -77,6 +77,11 @@ pub fn partial_state_advance( // (all-zeros) state root. let mut initial_state_root = Some(if state.slot() > state.latest_block_header().slot { state_root_opt.unwrap_or_else(Hash256::zero) + } else if state.slot() == state.latest_block_header().slot + && !state.latest_block_header().state_root.is_zero() + { + // Post-Gloas Full block case. + state.latest_block_header().state_root } else { state_root_opt.ok_or(Error::StateRootNotProvided)? });