Skip to content

Fix GRANDPA set ID handling - #2971

Merged
UnArbosFive merged 1 commit into
release-v446from
fix/grandpa-setid
Aug 13, 2026
Merged

Fix GRANDPA set ID handling#2971
UnArbosFive merged 1 commit into
release-v446from
fix/grandpa-setid

Conversation

@UnArbosFive

@UnArbosFive UnArbosFive commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • advance Grandpa::CurrentSetId with a checked next ID after a successful admin-scheduled authority change
  • require admin-scheduled GRANDPA changes to activate at the end of the current block, keeping the authority set and set ID atomic in persisted state
  • apply Finney's historical initial set-ID correction once at warp-sync start instead of once per proof fragment
  • preserve testnet checkpoint behavior and update runtime versioning, weight accounting, benchmarks, regression coverage, Python SDK metadata bindings, and generated source-link catalogs

Root cause

The admin scheduling path called Grandpa::schedule_change directly and therefore bypassed the set-ID bookkeeping normally performed by pallet-grandpa's session integration. This runtime does not use pallet-session, so a successful scheduling path must perform that bookkeeping explicitly. Because advancing the ID before a delayed authority change activates would persist a mismatched ID/authority pair, the admin path now accepts only immediate changes. It also checks the next set ID before writing the pending change, so overflow cannot panic or leave state half-applied.

Separately, the pinned SDK's legacy initial-set-ID mechanism adds its offset inside the proof-fragment loop. Finney needs the historical offset only at the beginning of verification; applying it to every fragment over-counts later authority-set transitions.

Impact

Admin-scheduled authority rotations now keep GRANDPA's authorities and set ID aligned in every persisted state. Finney warp-sync verification applies the historical correction once, then carries the proof's set ID forward normally across subsequent transitions.

Validation

  • CARGO_NET_OFFLINE=true cargo test -p pallet-admin-utils --locked
  • CARGO_NET_OFFLINE=true cargo check -p pallet-admin-utils --features runtime-benchmarks --locked
  • SKIP_WASM_BUILD=1 CARGO_NET_OFFLINE=true cargo test -p node-subtensor grandpa_warp_sync --locked -- --nocapture
  • SKIP_WASM_BUILD=1 CARGO_NET_OFFLINE=true cargo test -p node-subtensor-runtime --lib --locked
  • SKIP_WASM_BUILD=1 CARGO_NET_OFFLINE=true cargo clippy -p pallet-admin-utils -p node-subtensor-runtime -p node-subtensor --tests --no-deps --locked
  • uv run ruff check . && uv run ruff format --check . && uv run ty check --exit-zero-on-warning bittensor (from sdk/python)
  • uv run python -m codegen.check --coverage && uv run python -m codegen.check --names && uv run python -m codegen.check --namespaces (from sdk/python)
  • uv run pytest (from sdk/python; 1089 passed and 1 skipped in-sandbox, with all 6 local-socket bridge tests passing outside the socket-restricted sandbox)
  • uv run python ../../website/apps/bittensor-website/scripts/generate.py --check (from sdk/python)
  • cargo fmt --all -- --check
  • git diff --check

Dependency

This PR is intentionally stacked on #3078 and should merge after it.

@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
subtensor Ready Ready Preview Aug 13, 2026 7:53pm

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread runtime/src/lib.rs Outdated
Comment on lines +1001 to +1004
Grandpa::schedule_change(next_authorities, in_blocks, forced)?;
// This runtime does not use pallet-session, so mirror the bookkeeping performed by
// pallet-grandpa's session handler after it successfully schedules an authority change.
pallet_grandpa::CurrentSetId::<Runtime>::mutate(|set_id| *set_id += 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[HIGH] Delay set-ID advancement until the authority change takes effect

schedule_change accepts an arbitrary in_blocks, but this advances CurrentSetId immediately while Grandpa::grandpa_authorities() remains the old set until the scheduled block. During that window, a restarting node reads the new set ID through GrandpaApi::current_set_id() alongside the old authorities and can initialize GRANDPA with an invalid (set_id, authorities) pair, impairing finality. The session-handler pattern cited here is safe only when scheduling at the session transition; it cannot be copied unchanged to this delayed admin API. Advance the ID when the change is enacted, or constrain this path to an immediate change and reject nonzero delays. Add a restart/runtime-API regression test for the pending-change window.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🛡️ AI Review — Skeptic (security review)

VERDICT: SAFE

VERY HIGH scrutiny: account has zero public repos and was under 90 days old when the PR opened, mitigated by repository-admin status, matching author/committer, substantial merged history, and no Gittensor association; fix/grandpa-setid → release-v446.

The diff is scoped to checked GRANDPA set-ID bookkeeping, zero-delay authority rotations, a Finney-specific warp-sync correction, associated tests and weights, and generated documentation. No dependencies or AI-review trust-boundary files change.

Findings

No findings.

Conclusion

Static analysis found no security vulnerability or malicious behavior. The changes preserve authority/set-ID consistency and apply Finney’s historical offset only at warp-sync initialization.


🔍 AI Review — Auditor (domain review)

VERDICT: 👍

Gittensor association UNKNOWN; repository admin with substantial recent contributions, though the account is under 90 days old.

The implementation matches the substantive PR description. Checked set-ID advancement occurs only after successful scheduling, the zero-delay constraint keeps authority and set-ID updates atomic at the block boundary, and regression coverage includes delayed changes, pending changes, overflow, and multi-fragment Finney warp sync. The custom release-v446 base has no applicable spec-version check; no runtime confirmation or auto-fix was needed.

Findings

No findings.

Conclusion

No domain-correctness issues were found. The PR is ready from the Auditor perspective.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

@github-actions github-actions Bot mentioned this pull request Jul 23, 2026
@UnArbosFive
UnArbosFive changed the base branch from fix/testnet-grandpa-warp-sync-v2 to fix/alpha-accounting-446 August 13, 2026 02:36
@github-actions

Copy link
Copy Markdown
Contributor

eco-tests changed — indexer review required

This PR modifies files under eco-tests/. and may affect downstream indexing.
cc @evgeny-s — please review manually

Changed files
  • eco-tests/Cargo.toml
  • eco-tests/src/mock.rs
  • eco-tests/src/tests_mentat_indexer.rs

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread runtime/src/lib.rs Outdated
Comment on lines +1024 to +1027
Grandpa::schedule_change(next_authorities, in_blocks, forced)?;
// This runtime does not use pallet-session, so mirror the bookkeeping performed by
// pallet-grandpa's session handler after it successfully schedules an authority change.
pallet_grandpa::CurrentSetId::<Runtime>::mutate(|set_id| *set_id += 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[HIGH] Handle set-ID overflow before scheduling the change

SetId is a u64, so *set_id += 1 can panic when overflow checks are enabled or wrap to zero otherwise. Either outcome violates the monotonic GRANDPA set-ID invariant. Compute the checked successor before schedule_change; this also ensures an overflow error cannot occur after PendingChange has already been written.

Suggested change
Grandpa::schedule_change(next_authorities, in_blocks, forced)?;
// This runtime does not use pallet-session, so mirror the bookkeeping performed by
// pallet-grandpa's session handler after it successfully schedules an authority change.
pallet_grandpa::CurrentSetId::<Runtime>::mutate(|set_id| *set_id += 1);
let next_set_id = Grandpa::current_set_id()
.checked_add(1)
.ok_or(sp_runtime::ArithmeticError::Overflow)?;
Grandpa::schedule_change(next_authorities, in_blocks, forced)?;
// This runtime does not use pallet-session, so mirror the bookkeeping performed by
// pallet-grandpa's session handler after it successfully schedules an authority change.
pallet_grandpa::CurrentSetId::<Runtime>::put(next_set_id);

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👎

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread runtime/src/lib.rs
Comment on lines +1024 to +1028
Grandpa::schedule_change(next_authorities, in_blocks, forced)?;
// This runtime does not use pallet-session, so mirror the bookkeeping performed by
// pallet-grandpa's session handler after it successfully schedules an authority change.
pallet_grandpa::CurrentSetId::<Runtime>::mutate(|set_id| *set_id += 1);
Ok(())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[HIGH] Handle set-ID overflow before scheduling the change

CurrentSetId is a u64, so *set_id += 1 can panic in the runtime at exhaustion. It also runs after schedule_change, making a fallible increment at that point unsafe because the pending authority change has already been written. Compute the checked next ID first, schedule only after that succeeds, then persist the ID.

Suggested change
Grandpa::schedule_change(next_authorities, in_blocks, forced)?;
// This runtime does not use pallet-session, so mirror the bookkeeping performed by
// pallet-grandpa's session handler after it successfully schedules an authority change.
pallet_grandpa::CurrentSetId::<Runtime>::mutate(|set_id| *set_id += 1);
Ok(())
let next_set_id = Grandpa::current_set_id()
.checked_add(1)
.ok_or(sp_runtime::ArithmeticError::Overflow)?;
Grandpa::schedule_change(next_authorities, in_blocks, forced)?;
// This runtime does not use pallet-session, so mirror the bookkeeping performed by
// pallet-grandpa's session handler after it successfully schedules an authority change.
pallet_grandpa::CurrentSetId::<Runtime>::put(next_set_id);
Ok(())

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👎

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@UnArbosFive
UnArbosFive marked this pull request as ready for review August 13, 2026 10:06
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@UnArbosFive
UnArbosFive marked this pull request as draft August 13, 2026 14:01
@UnArbosFive
UnArbosFive changed the base branch from fix/alpha-accounting-446 to release-v446 August 13, 2026 19:43
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@UnArbosFive
UnArbosFive marked this pull request as ready for review August 13, 2026 20:02
@UnArbosFive
UnArbosFive merged commit 94dd956 into release-v446 Aug 13, 2026
104 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@UnArbosFive UnArbosFive mentioned this pull request Aug 13, 2026
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.

2 participants