Skip to content

BEEFY session keys and worker - #2084

Open
LGLO wants to merge 10 commits into
mainfrom
lglo/beefy-on-main
Open

BEEFY session keys and worker#2084
LGLO wants to merge 10 commits into
mainfrom
lglo/beefy-on-main

Conversation

@LGLO

@LGLO LGLO commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Overview

  • Adds BEEFY

🗹 TODO before merging

  • Ready

📌 Submission Checklist

  • All commits are signed off (git commit -s) for the DCO
  • Changes are backward-compatible (or flagged if breaking)
  • Pull request description explains why the change is needed
  • Self-reviewed the diff
  • I have included a change file, or skipped for this reason:
  • If the changes introduce a new feature, I have bumped the node minor version
  • Update documentation (if relevant)
  • Updated AGENTS.md if build commands, architecture, or workflows changed
  • No new todos introduced

🧪 Testing Evidence

Please describe any additional testing aside from CI:

  • Additional tests are provided (if possible)

🔱 Fork Strategy

  • Node Runtime Update
  • Node Client Update
  • Other:
  • N/A

Links

MicroProofs and others added 5 commits September 2, 2026 10:07
Signed-off-by: microproofs <kwhitemsg@gmail.com>
Signed-off-by: microproofs <kwhitemsg@gmail.com>
…rsion

Signed-off-by: microproofs <kwhitemsg@gmail.com>
Fix committee_membership.
Fix genesis block building.
Read beefy key from its own seed.

Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>
Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>
@LGLO
LGLO requested a review from a team as a code owner September 2, 2026 11:50
Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9596e72509

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread runtime/src/migrations.rs
Comment on lines +288 to +289
1,
2,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Handle predecessor states already migrated to version 2

When upgrading a chain that has already run the immediate predecessor, this migration is skipped: that runtime wires pallet_session_validator_management::migrations::v2::V1ToV2Migration, which writes storage version 2 while the committee and session entries still use the two-key LegacySessionKeys encoding. Because this VersionedMigration only executes at version 1, the new runtime subsequently decodes those bytes as three-key session data without translating them, causing committee reads to fail and preventing the next session rotation from installing the expected authorities. Use a distinct key-shape storage version or explicitly support both predecessor versions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The predecessor of the release this code is intended for does not contain V1ToV2Migration.

Comment thread metadata/Cargo.toml Outdated
Comment thread README.md

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1adb3eb930

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread runtime/src/lib.rs Outdated
@datadog-official

This comment has been minimized.

Copy link
Copy Markdown

Hi @LGLO — we’re working on Ura Finance and have been testing a trust-minimized Midnight → Cardano reverse-bridge path.

We reached a very specific protocol boundary and wanted to check whether #2084 is the upstream piece we should align with rather than inventing anything parallel.

What we have established on the application side:

  • our represented ADA is a user-owned shielded custom Zswap asset (swap.pixel.ada.v1)
  • native Zswap spend/nullifier semantics can consume it without an Ura/operator approval path
  • amount/color binding and double-spend rejection are available at the ledger layer
  • a withdrawal intent can be composed atomically with that spend in the ledger-v8 transaction model

Where our current Preprod research stops is the cross-chain proof boundary. GRANDPA finality is available, but we could not derive a complete, independently verifiable chain from a pinned trust root through authority-set evolution + finalized header + withdrawal transaction/state inclusion without trusting an RPC/indexer.

We then found the existing Midnight bridge-proof lineage (#222, #233, #235) and the current relay/ code: BEEFY signed commitments, current/next authority-set data, AuthoritiesProof, RelayChainProof, mmr_generateProof, and Cardano/Plutus encoding. That looks extremely close to the canonical interface we need.

Could you clarify four things?

  1. Is BEEFY session keys and worker #2084 the current public path for enabling BEEFY in the newer node line / eventual public-network deployment?
  2. Is the RelayChainProof + authority-proof + Plutus encoding lineage intended to be part of the Midnight → Cardano / Stage-2 bridge verification path?
  3. Once BEEFY is active, is mmr_generateProof expected to provide usable proofs for finalized blocks, and what is the intended cryptographic link from an application transaction/state commitment into the MMR/finalized commitment?
  4. What is the supported way for an external verifier to advance BEEFY/GRANDPA authority state from a pinned genesis or trusted checkpoint without trusting an RPC response for the current validator set?

We are reproducing the canonical BEEFY/MMR/RelayChainProof stack locally against the #2084 line now. We’re happy to contribute an external verifier harness, adversarial/negative vectors, RPC conformance tests, and Cardano-side verification work once the intended proof interface is confirmed.

Our design constraint is deliberate: RPC/indexer/relayer may transport proof bytes, but none should become a validity authority. We’d rather stop than add an Ura signer/oracle/federation workaround.

If there is a Stage-2 bridge technical owner/spec we should coordinate with, a pointer would be very helpful. @b-yap @justinfrevert, tagging because your earlier authority-proof/Cardano-encoding work appears directly relevant.

Copy link
Copy Markdown

Follow-up with concrete reproduction results from the exact #2084 pin (1adb3eb930c983b689b9466795f55ef40867040d), no source patches:

RELAY_BUILD=YES
NODE_BUILD=YES
CHAIN_PRODUCING_BLOCKS=YES
GRANDPA_FINALIZING=YES
BEEFY_WORKER_RUNNING=YES
BEEFY_JUSTIFICATION_OBSERVED=YES
BEEFY_BLOCK_NUMBER=17
VALIDATOR_SET_ID=0 -> 1
AUTHORITY_PROOF=YES
RELAYCHAIN_PROOF=YES
PLUTUS_ENCODING=YES
MMR_PROOF=YES
MMR_VERIFY=YES
AUTHORITY_TRANSITION_CHAIN=COMPLETE
GENERIC_STATE_INCLUSION_CHAIN=YES
OFFLINE_VERIFIER=YES
NEGATIVE_MATRIX=YES
DETERMINISTIC=YES

So Midnight's canonical BEEFY/MMR/authority-proof/RelayChainProof stack reproduces locally end-to-end for us. We also verified a full authority-set transition and independent MMR verification. No Ura crypto or authority was added.

The remaining public-network delta from our Preprod tests is now narrow:

FIRST_PREPROD_DELTA=BEEFY_WORKER_AND_RPC_NOT_READY_ON_PUBLIC_PREPROD
MINIMUM_UPSTREAM_UNBLOCK=Enable BEEFY worker + session keys + justifications on Preprod, then expose usable MMR leaf proofs

This changes our question from “is the architecture missing?” to “what is the intended deployment/interface path for the already-existing canonical proof stack?”

We are deliberately keeping the reverse bridge blocked rather than falling back to an indexer/oracle/signer.

If helpful, we can share the reproduction matrix and contribute an external verifier/conformance suite around:

  • authority-set transition verification
  • signed BEEFY commitments
  • MMR proof verification
  • malformed/stale authority-set negatives
  • Cardano/Plutus proof decoding

The one remaining application-specific step on our side is to bind our atomic Zswap withdrawal commitment into the authenticated state-inclusion path; we are not asking Midnight to solve that application logic for us.

Would appreciate guidance on whether #2084 + the existing relay/ proof lineage is the intended Stage-2 / Midnight->Cardano public-network path, and what network milestone or interface we should target for a W0R2 Preprod verification.

LGLO added 2 commits September 3, 2026 08:54
Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>
Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 09e6998023

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread runtime/src/lib.rs
let grandpa = keys.find(GRANDPA)?;
let grandpa = ed25519::Public::from_raw(grandpa.try_into().ok()?);
Some(Self { aura: aura.into(), grandpa: grandpa.into() })
let beefy = keys.find(BEEFY).or_else(|| keys.find(CROSS_CHAIN))?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve legacy candidates without embedded BEEFY keys

For V0/db-sync and local-mock inputs, CandidateKeys contains only AURA and GRANDPA; the usable ECDSA identity is stored separately in RegistrationData.cross_chain_pub_key or PermissionedCandidateData.sidechain_public_key (for example, primitives/mainchain-follower/src/data_source/candidates_data_source/mod.rs:272 and partner-chains/toolkit/data-sources/mock/src/candidate.rs:115). Consequently this ? rejects every such candidate, authority selection returns None, and the pallet repeatedly retains the queued committee instead of applying registrations or permissioned-candidate changes. Fresh evidence in this revision is that the new CROSS_CHAIN lookup still searches the key list where those sources do not place the identity; derive the fallback from the candidate's separate ECDSA identity or add it to CandidateKeys before validation.

AGENTS.md reference: AGENTS.md:L69-L69

Useful? React with 👍 / 👎.

Comment thread README.md
| AURA seed | `AURA_SEED_FILE=/path/to/seed` | - | Path to AURA consensus seed file |
| GRANDPA seed | `GRANDPA_SEED_FILE=/path/to/seed` | - | Path to GRANDPA finality seed file |
| Cross-chain seed | `CROSS_CHAIN_SEED_FILE=/path/to/seed` | - | Path to cross-chain seed file |
| BEEFY seed | `BEEFY_SEED_FILE=/path/to/seed` | - | Path to BEEFY seed file (ECDSA, like cross-chain) |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add the BEEFY seed to the single-node command

The single-node example immediately below this new option still supplies only AURA, GRANDPA, and cross-chain seeds and does not use --alice; node/src/command.rs inserts a beef keystore entry only when BEEFY_SEED_FILE is set. Because the dev authority's registered BEEFY public key has no matching secret under the BEEFY key type, this advertised one-validator setup produces blocks but cannot produce BEEFY signatures. Fresh evidence is that the multi-node examples were updated with the new variable while the single-node command at line 308 remains unchanged.

AGENTS.md reference: AGENTS.md:L69-L69

Useful? React with 👍 / 👎.

Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>
@Klapeyron

Copy link
Copy Markdown
Contributor

Thanks for the detailed note @alba-press — this PR is about enabling BEEFY in our node line, so I’ll briefly describe what we’re actually doing.

Work done as part of the item is one of the preliminary items of the bigger midnightntwrk/midnight-improvement-proposals#262 that is already in progress of refinement (please do not consider above document as final). As part of #2084, we plan to make BEEFY operational in a way that it will be able to provide signed commitments and follow canonical chain finalized by GRANDPA. The exact shape of the commitments and what will be in MMR proofs is still discussed, I've hope more details we will have closer to the next quarter. In current state of code (main) BEEFY is partially integrated, so there exists pieces either in runtime or the node that are capable of driving the consensus, but they are not voting due there is no active beefy session key integrated yet

Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c85113521d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread runtime/src/lib.rs
pub grandpa: Grandpa,
// todo: add the beefy
// pub beefy: Beefy,
pub beefy: Beefy,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bump the runtime spec version for the BEEFY change

The parent and this runtime both advertise spec_version: 003_000_000, even though this changes the encoded SessionKeys shape and adds a storage migration. When this Wasm is applied to an existing 3.0.0 chain, util/toolkit/src/commands/runtime_upgrade.rs only recognizes spec > pre_spec_version, so the standard upgrade command eventually reports UpgradeNotEnacted; version-based metadata and runtime selection also cannot distinguish the old two-key runtime from this three-key runtime. Assign a new runtime/package/metadata version before shipping.

AGENTS.md reference: AGENTS.md:L69-L69

Useful? React with 👍 / 👎.

AURA_SEED_FILE: "/seeds/aura.seed"
CROSS_CHAIN_SEED_FILE: "/seeds/cross_chain.seed"
GRANDPA_SEED_FILE: "/seeds/grandpa.seed"
BEEFY_SEED_FILE: "/seeds/beefy.seed"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Seed BEEFY in generated compose overrides

This provisions the checked-in local environment, but the from-genesis and fork/mock paths generate validator overrides through genesisComposeOverride.ts and mockComposeOverride.ts, and both still create only AURA, GRANDPA, and cross-chain seed files/environment variables. Validators launched through those workflows therefore have no beef keystore entry for their advertised BEEFY key, so BEEFY finality cannot advance; both generators and their tests should set BEEFY_SEED_FILE, reusing the cross-chain seed where appropriate.

AGENTS.md reference: AGENTS.md:L69-L69

Useful? React with 👍 / 👎.

@alba-press alba-press left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Update from our side: we have now closed the full local verification chain against this PR's exact head c85113521de5a6e1f3aa1029bb49036285caddac.

On a fresh local chain with the corrected BEEFY authority history we reproduced:

user-owned shielded custom Zswap value
→ canonical user spend/nullifier
→ receiveShielded withdrawal receipt + user change
→ public withdrawal-intent binding
→ TxApplied
→ extrinsics_root + System::Events/state_root
→ MMR inclusion
→ BEEFY signed commitment
→ AuthoritiesProof
→ independent offline verifier = VALID

Concrete specimen: withdrawal at block 346, later BEEFY commitment at block 363 (validator_set_id=1 after a real session 0→1 transition), mmr_verifyProofStateless passed against the mh root, BEEFY signatures and AuthoritiesProof verified. No Ura signer/oracle/indexer/RPC verdict is used as validity authority.

So for us the remaining boundary is now specifically public Preprod activation/exposure, not local proof architecture. Our direct Preprod probes still see the BEEFY endpoint as not ready / no usable BEEFY justification path.

Could you help us pin the exact current activation blockers/order so we do not guess? In particular:

  1. Is merge/deployment of #2084 itself still the first required step for Preprod?
  2. Is #1953 (combined v1→v2 + BEEFY SessionKeys migration) still required in addition to #2084 for the existing Preprod state, or has #2084 superseded/absorbed that migration path?
  3. Is #2078 / #1895 (all-or-nothing session-key registration on committee rotation) considered a prerequisite for enabling BEEFY on public networks, or only related hardening?
  4. For Preprod activation, is the intended initial RPC surface beefy_getFinalizedHead + justifications + mmr_generateProof, or is the MMR-root-only / deduplicated committee format from MIP #262 expected to land first?
  5. Is there any operator-side prerequisite (candidate beef re-registration / keystore provisioning) that must happen before the runtime can safely activate BEEFY on Preprod?

We can provide the complete external conformance fixture and negative matrix from the local run if useful. The goal is to identify the real deployment blocker(s), not infer them from open PRs.

@LGLO

LGLO commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

@alba-press
Ad 1 - yes this PR, #2084, is a pre-requisite. Even if merged now, it would not be deployed on Preview soon, because we there are other releases in the pipeline. Actually, Shielded isn't really in charge here. I'm not someone who decides, but I can share my own personal expectations regarding deployment of this feature and it is around November.
Ad 2: #1953 is a PR to a long living branch, that will be merged October earliest and is expected to start hitting public networks in December at best, for this reason I've moved the changes closer to main branch. In other words I hope that we merge this PR and discard #1953
Ad 3: it is hardening, for now we control what keys are on Cardano, but when decentralization is enabled, then we could face malicious candidates who share keys and make a mess
Ad 4: I'm sorry, I don't know answer for this one
Ad 5: Only validator nodes are signing blocks. We expect node operators to insert proper (matching public keys on Cardano) BEEFY keys. It is like with AURA or GRANDPA - if keys are wrong or missing, then node is not only not useful, but can be considered malicious.

I would call @MicroProofs to help with verifying my answers.

Copy link
Copy Markdown

Thanks @LGLO, this clears up most of the sequencing.

@MicroProofs, could you help validate the remaining proof-side question for us?

For a client verifying Midnight finality externally after #2084 is deployed, should we expect the usable path to be BEEFY justification, signed MMR root, mmr_generateProof for the target leaf, then external verification?

Or does MIP #262 introduce a different committee/MMR proof format that clients should target instead?

We are trying to determine whether the existing public BEEFY/MMR RPC path is the correct integration target once enabled, or whether we should wait for the MIP #262 light-client format before building against it.

Thanks. This is the remaining dependency for our Preprod withdrawal verifier.

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.

4 participants