Skip to content

feat(spice): handle uncertified validator proposals at epoch boundary#15022

Open
darioush wants to merge 6 commits intonear:masterfrom
darioush:spice-vdr2-clean
Open

feat(spice): handle uncertified validator proposals at epoch boundary#15022
darioush wants to merge 6 commits intonear:masterfrom
darioush:spice-vdr2-clean

Conversation

@darioush
Copy link
Contributor

@darioush darioush commented Feb 6, 2026

  • At epoch boundaries in SPICE, staking proposals from uncertified chunks (chunks whose execution results haven't been endorsed yet) were being ignored. This could cause incorrect stake returns - e.g., a validator who re-stakes in an uncertified chunk near the epoch boundary would have their full stake returned as if they hadn't re-staked.
  • Add get_uncertified_validator_proposals to SpiceCoreReader, which collects proposals from uncertified chunks via ChunkExtra (tracking nodes) or DBCol::execution_results (non-tracking nodes).
  • Resolve prev_validator_proposals eagerly in the chunk validator actor's readiness checks, so witnesses whose dependency execution results haven't arrived yet are retried later. (in case a block is certified before its parent)

Added UTs and test-loop for new behavior.

Add get_trusted_chunk_extra and get_uncertified_validator_proposals
to SpiceCoreReader. At epoch boundaries, prev_validator_proposals
returns proposals from chunks not yet certified on-chain, ensuring
late stake changes (e.g. re-stake near epoch end) are not missed.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends SPICE epoch-boundary handling so validator stake proposals from uncertified chunks are still considered, preventing incorrect stake returns when a validator unstakes then re-stakes near an epoch boundary.

Changes:

  • Add SpiceCoreReader support for collecting validator proposals from uncertified chunks and expose prev_validator_proposals for epoch-boundary use.
  • Wire prev_validator_proposals into SPICE chunk execution and witness pre-validation paths.
  • Add regression and unit tests to validate uncertified-proposal discovery and the stake-return scenario; update cspell dictionary.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test-loop-tests/src/tests/stake_nodes.rs Adds a SPICE regression test ensuring re-stake proposals in uncertified chunks prevent stake return at epoch boundary.
cspell.json Adds “unstaker” to the spellcheck dictionary.
chain/client/src/tests/spice_chunk_executor_actor.rs Updates test to provide prev_validator_proposals into SPICE witness pre-validation.
chain/client/src/spice_chunk_validator_actor.rs Fetches prev_validator_proposals per shard and threads it through witness validation context; re-queues pending witnesses when proposals aren’t available.
chain/client/src/chunk_executor_actor.rs Uses core_reader.prev_validator_proposals when building NewChunkData for shard execution.
chain/chain/src/tests/spice_core.rs Adds unit tests for retrieving uncertified validator proposals, including an execution-results fallback case.
chain/chain/src/stateless_validation/spice_chunk_validation.rs Extends spice_pre_validate_chunk_state_witness to accept externally supplied previous validator proposals.
chain/chain/src/spice_core.rs Implements trusted chunk-extra retrieval and uncertified validator proposal collection, plus epoch-boundary prev_validator_proposals.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +139 to +141
/// Proposals are sorted ascending by block height. If multiple uncertified
/// chunks contain proposals for the same account, the most recent one (last
/// in iteration order) should be kept by the caller's fold/insert logic.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After spice, we can move this fold logic to the caller and simplify

let epoch_length: u64 = 10;
let endorsement_delay: u64 = 4;
let unstaker_idx = 0;
let validators_spec = create_validators_spec(4, 1);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

includes a CV to test witness verification path

for witness in ready_witnesses.into_iter().flatten() {
let shard_id = witness.chunk_id().shard_id;
let prev_validator_proposals =
match self.core_reader.prev_validator_proposals(prev_block.hash(), shard_id) {
Copy link
Contributor Author

@darioush darioush Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm checking prev_validator_proposals is ready before the witness handling, for the case that a child block becomes certified before its ancestors.

As an alternative we could have a column that only stores executed_results from block processing.

@codecov
Copy link

codecov bot commented Feb 6, 2026

Codecov Report

❌ Patch coverage is 0% with 130 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.83%. Comparing base (67ba56f) to head (06dff3f).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
chain/client/src/spice_chunk_validator_actor.rs 0.00% 53 Missing ⚠️
chain/chain/src/spice_core.rs 0.00% 47 Missing ⚠️
...src/stateless_validation/spice_chunk_validation.rs 0.00% 25 Missing ⚠️
chain/client/src/chunk_executor_actor.rs 0.00% 5 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master   #15022       +/-   ##
===========================================
+ Coverage    1.30%   68.83%   +67.52%     
===========================================
  Files         726      920      +194     
  Lines      140845   202236    +61391     
  Branches   140845   202236    +61391     
===========================================
+ Hits         1835   139203   +137368     
+ Misses     138957    57040    -81917     
- Partials       53     5993     +5940     
Flag Coverage Δ
pytests-nightly 1.29% <0.00%> (-0.01%) ⬇️
unittests 68.44% <0.00%> (?)
unittests-nightly 68.35% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@darioush darioush requested a review from attila0x2A February 6, 2026 23:02
@darioush darioush marked this pull request as ready for review February 6, 2026 23:02
@darioush darioush requested a review from a team as a code owner February 6, 2026 23:02
@attila0x2A attila0x2A requested review from pugachAG and removed request for attila0x2A February 9, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant