Skip to content

fix(cardano): stop dropping StakeVoteDeleg drep leg and drep anchors#1128

Merged
scarmuega merged 1 commit into
mainfrom
fix/governance-cert-handling
Jul 25, 2026
Merged

fix(cardano): stop dropping StakeVoteDeleg drep leg and drep anchors#1128
scarmuega merged 1 commit into
mainfrom
fix/governance-cert-handling

Conversation

@scarmuega

@scarmuega scarmuega commented Jul 25, 2026

Copy link
Copy Markdown
Member

Summary

Two Conway cert-handling gaps in delegation/DRep tracking, both on the block-roll path:

1. StakeVoteDeleg's DRep leg was silently dropped

cert_as_vote_delegation (pallas_extras.rs) matched VoteDeleg, VoteRegDeleg and StakeVoteRegDeleg but not StakeVoteDeleg, so a combined stake+vote delegation cert updated the account's pool delegation (its pool leg is handled by cert_as_stake_delegation) while the DRep delegation was never recorded. This is a live correctness bug: any account that delegated to a DRep via that cert shows no vote delegation. Fixed by adding the missing arm, emitting the existing VoteDelegation delta.

2. DRep anchors were discarded

DRepState had no anchor field: the anchor carried by RegDRepCert was stashed in the DRepRegistration delta but never written to the entity, and UpdateDRepCert only refreshed activity, discarding its anchor entirely.

  • DRepState gains anchor: Option<Anchor> at CBOR index 7 — a backward-compatible addition: pre-existing rows decode with None, no migration.
  • A new DRepAnchorUpdate delta (appended to CardanoDelta, preserving the frozen bincode variant order) writes it, emitted for both RegDRepCert and UpdateDRepCert. A separate delta rather than extending DRepRegistration because existing delta shapes are frozen for WAL decode compatibility (same reason as the EpochWrapUp → V2/V3 lineage).
  • Semantics match the ledger's CERT rules: both certs replace drepAnchor wholesale (anchor := anchor), so a cert without an anchor clears the stored one. The activity/expiry refresh side of UpdateDRepCert remains covered by the existing DRepActivity delta.

This is the first step of making Conway governance tracking real (DRep delegation at the transaction level); vote/proposal capture and ratification come separately.

Testing

  • New proptests: drep_anchor_update_roundtrip (apply→undo reversibility) and drep_anchor_update_serde_roundtrip (undo survives the WAL wire format); any_drep_state extended with the anchor field.
  • cargo clippy --workspace --all-targets --all-features: clean.
  • cargo test --workspace --all-features: all green.
  • cargo fmt --check: clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for storing and updating DRep anchors.
    • DRep registration and anchor update certificates now appear in state changes.
    • Anchors can be cleared when no longer provided.
  • Bug Fixes

    • Improved handling of Conway-era vote delegation certificates.
    • Existing persisted DRep records remain compatible when no anchor is present.
  • Tests

    • Added coverage for anchor updates, serialization, undo operations, and state round trips.

Two Conway cert-handling gaps in delegation/drep tracking:

- cert_as_vote_delegation did not match StakeVoteDeleg, so the drep leg
  of that cert was silently dropped and the delegator's vote delegation
  never recorded (the pool leg was already handled by
  cert_as_stake_delegation).

- The anchor carried by RegDRepCert and UpdateDRepCert was discarded:
  DRepState had no anchor field and UpdateDRepCert only refreshed
  activity. DRepState now persists the anchor at a new backward-
  compatible CBOR index (old rows decode with None), written by a new
  DRepAnchorUpdate delta appended to CardanoDelta. A separate delta is
  used because the on-disk shapes of existing deltas are frozen for WAL
  compatibility.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

DRep anchor support

Layer / File(s) Summary
Anchor state and delta contract
crates/cardano/src/model/dreps.rs
DRepState stores an optional anchor, and DRepAnchorUpdate supports applying, undoing, serialization, and property-based roundtrip testing.
Cardano delta wiring
crates/cardano/src/model/mod.rs
CardanoDelta exposes and routes DRepAnchorUpdate operations.
Certificate anchor emission
crates/cardano/src/roll/dreps.rs, crates/cardano/src/pallas_extras.rs
DRep registration and update certificates emit anchor deltas, while stake vote delegation matching follows the current certificate fields.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ConwayCert
  participant visit_cert
  participant DRepAnchorUpdate
  participant DRepState
  ConwayCert->>visit_cert: provide DRep anchor
  visit_cert->>DRepAnchorUpdate: emit anchor update
  DRepAnchorUpdate->>DRepState: apply anchor
Loading

Possibly related PRs

  • txpipe/dolos#703: Extends the DRep delta system and certificate processing for related DRep changes.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main fixes: preserving StakeVoteDeleg drep data and DRep anchors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/governance-cert-handling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
crates/cardano/src/model/dreps.rs (1)

467-482: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add a legacy CBOR decoding regression test.

The new tests cover delta undo and bincode serialization, but not loading a pre-change DRepState row without field 7. Add a fixture for the legacy seven-field representation and assert that anchor decodes as None.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/cardano/src/model/dreps.rs` around lines 467 - 482, Add a regression
test near drep_anchor_update_serde_roundtrip that decodes a legacy seven-field
DRepState CBOR fixture lacking field 7, then assert the resulting anchor is
None. Reuse the existing CBOR decoding helpers and DRepState representation
conventions, ensuring the test verifies compatibility with pre-change rows.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/cardano/src/model/dreps.rs`:
- Around line 467-482: Add a regression test near
drep_anchor_update_serde_roundtrip that decodes a legacy seven-field DRepState
CBOR fixture lacking field 7, then assert the resulting anchor is None. Reuse
the existing CBOR decoding helpers and DRepState representation conventions,
ensuring the test verifies compatibility with pre-change rows.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 19e8112c-8502-4f80-966b-066d71a17ed1

📥 Commits

Reviewing files that changed from the base of the PR and between c797e97 and f0ea292.

📒 Files selected for processing (4)
  • crates/cardano/src/model/dreps.rs
  • crates/cardano/src/model/mod.rs
  • crates/cardano/src/pallas_extras.rs
  • crates/cardano/src/roll/dreps.rs

@scarmuega
scarmuega merged commit 3b165c4 into main Jul 25, 2026
14 checks passed
@scarmuega
scarmuega deleted the fix/governance-cert-handling branch July 25, 2026 13:31
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