Skip to content

feat: add governance voting messages and fields to the Cardano transaction proto definition.#193

Open
Emmanuel-Tyty wants to merge 5 commits intoutxorpc:mainfrom
Emmanuel-Tyty:feat/add-govrnance-voting-fields
Open

feat: add governance voting messages and fields to the Cardano transaction proto definition.#193
Emmanuel-Tyty wants to merge 5 commits intoutxorpc:mainfrom
Emmanuel-Tyty:feat/add-govrnance-voting-fields

Conversation

@Emmanuel-Tyty
Copy link

@Emmanuel-Tyty Emmanuel-Tyty commented Feb 20, 2026

Updates cardano.proto to support CIP-1694 governance by adding votes and proposals to the
Tx message. This prevents data loss when parsing Conway transactions via UTxO RPC endpoints.

@Mercurial
Copy link
Contributor

Hey @Emmanuel-Tyty, nice work on this — governance votes are definitely needed in the spec. Did a review cross-referencing against the Conway CDDL and ledger source. A few things to flag:

Vote enum ordering doesn't match the CDDL

The Conway CDDL defines vote = 0 .. 2 where:

  • 0 = No
  • 1 = Yes
  • 2 = Abstain

The PR has:

enum Vote {
  VOTE_UNSPECIFIED = 0;
  VOTE_YES = 1;
  VOTE_NO = 2;
  VOTE_ABSTAIN = 3;
}

The UNSPECIFIED = 0 is standard protobuf convention so the shift is expected, but the ordering swaps Yes and No relative to the CDDL (No=0, Yes=1 on-chain vs Yes=1, No=2 in proto). This could be a source of mapping bugs for implementors. Consider reordering to match the CDDL:

enum Vote {
  VOTE_UNSPECIFIED = 0;
  VOTE_NO = 1;
  VOTE_YES = 2;
  VOTE_ABSTAIN = 3;
}

SPO voter credential

The ledger explicitly disallows script credentials for StakePoolVoter (tag 5 fails with "Script objects are not allowed for StakePool votes"). The Voter message uses StakeCredential which includes a script_hash variant — this works at the wire level since it's still 28 bytes, but might be worth a comment on the credential field noting that for SPOs only addr_key_hash is valid (and it represents a pool key hash, not a stake key hash).

Everything else looks good

  • VoterRole correctly collapses the 5 CBOR tags into 3 roles (CC can be key or script via StakeCredential, same for DRep)
  • VoterVotes is a clean proto flattening of the CDDL's nested map {+ voter => {+ gov_action_id => voting_procedure}}
  • VotingProcedure fields (gov_action_id, vote, anchor) are correct
  • Field number 15 on Tx is the next available
  • Both v1alpha and v1beta are updated consistently

@Mercurial
Copy link
Contributor

One more thing — this PR also raises a broader question worth discussing: how closely should the u5c proto definitions follow the Cardano CDDL?

There's a natural tension between:

  • Mirroring the CDDL closely — makes it easier for implementors to map on-chain data, reduces translation bugs, and serves as a more predictable spec for anyone already familiar with the ledger
  • Idiomatic protobuf — things like UNSPECIFIED = 0 defaults, more descriptive enums, flattening nested maps, using StakeCredential as a reusable type even when the CDDL uses distinct credential kinds

This PR leans toward idiomatic protobuf (which is reasonable), but the Vote enum ordering mismatch is an example of where that divergence can bite. It might be worth establishing a convention for the project — e.g., enum values should follow CDDL ordering (shifted by 1 for the protobuf UNSPECIFIED default), or at minimum document the mapping explicitly in comments.

cc @scarmuega — would be good to align on this as more governance and Conway-era types get added.

@Emmanuel-Tyty
Copy link
Author

Hey @Emmanuel-Tyty, nice work on this — governance votes are definitely needed in the spec. Did a review cross-referencing against the Conway CDDL and ledger source. A few things to flag:

Vote enum ordering doesn't match the CDDL

The Conway CDDL defines vote = 0 .. 2 where:

  • 0 = No
  • 1 = Yes
  • 2 = Abstain

The PR has:

enum Vote {
  VOTE_UNSPECIFIED = 0;
  VOTE_YES = 1;
  VOTE_NO = 2;
  VOTE_ABSTAIN = 3;
}

The UNSPECIFIED = 0 is standard protobuf convention so the shift is expected, but the ordering swaps Yes and No relative to the CDDL (No=0, Yes=1 on-chain vs Yes=1, No=2 in proto). This could be a source of mapping bugs for implementors. Consider reordering to match the CDDL:

enum Vote {
  VOTE_UNSPECIFIED = 0;
  VOTE_NO = 1;
  VOTE_YES = 2;
  VOTE_ABSTAIN = 3;
}

SPO voter credential

The ledger explicitly disallows script credentials for StakePoolVoter (tag 5 fails with "Script objects are not allowed for StakePool votes"). The Voter message uses StakeCredential which includes a script_hash variant — this works at the wire level since it's still 28 bytes, but might be worth a comment on the credential field noting that for SPOs only addr_key_hash is valid (and it represents a pool key hash, not a stake key hash).

Everything else looks good

  • VoterRole correctly collapses the 5 CBOR tags into 3 roles (CC can be key or script via StakeCredential, same for DRep)
  • VoterVotes is a clean proto flattening of the CDDL's nested map {+ voter => {+ gov_action_id => voting_procedure}}
  • VotingProcedure fields (gov_action_id, vote, anchor) are correct
  • Field number 15 on Tx is the next available
  • Both v1alpha and v1beta are updated consistently

Suggested changes make sense, i will update this.

Emmanuel-Tyty and others added 4 commits March 2, 2026 18:19
Co-authored-by: Mateusz Galazyn <228866+carbolymer@users.noreply.github.com>
Co-authored-by: Mateusz Galazyn <228866+carbolymer@users.noreply.github.com>
Copy link
Contributor

@carbolymer carbolymer left a comment

Choose a reason for hiding this comment

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

LGTM

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.

3 participants