Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions CIP-XXXX/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
CIP: XXXX
Title: Default SPO vote
Category: Ledger
Authors:
- Teodora Danciu <teodora.danciu@iohk.io>
- Alexey Kuleshevich <alexey.kuleshevich@iohk.io>
Implementors: N/A
Status: Proposed
Discussions:
- https://github.com/cardano-foundation/CIPs/pull/1108
- https://github.com/IntersectMBO/cardano-ledger/issues/4645
Created: 2025-10-28
License: CC-BY-4.0
---

## Abstract

We propose introducing an explicit mechanism for SPOs to define their default governance vote as part of their pool's registration parameters.
This would replace the current indirect approach, which relies on delegating the pool’s reward account to predefined DReps AlwaysNoConfidence and AlwaysAbstain.

## Motivation: why is this CIP necessary?

The current approach was always intended as a temporary workaround. While it solved the immediate problem (as discussed in [cardano-ledger#4645](https://github.com/IntersectMBO/cardano-ledger/issues/4645)), it introduces several issues:
* It is not transparent or easily inspectable what a pool’s default vote actually is, making it difficult to understand how undelegated or non-voting stake will behave in governance actions.
* It couples operational reward accounts with governance semantics, constraining how SPOs can use their reward accounts.
* It can distort governance outcomes, as SPOs who do not configure their reward accounts may unintentionally default to voting No, potentially skewing proposal results.

By contrast, providing SPOs with a clear, explicit default vote parameter allows them to opt in or out of governance participation transparently, mitigating the coupling between financial and governance mechanisms and reducing long-term bias in voting behaviour.

## Specification

### Current behaviour

The "default vote" determines how *not voting* counts toward the ratification of a proposal.
For SPOs, this is currently implemented as folllows:
* `HardForkInitiation` proposals: default is `No`
* `NoConfidence` proposals:
- if the pool's reward account is delegated to `AlwaysNoConfidence`, the default is `Yes`
- otherwise, `No`
* `UpdateCommittee` and `ParameterUpdate` (for security-group parameters) proposals:
- if the pool reward account is delegated to `AlwaysAbstain`, the default is `Abstain`
- otherwise, `No`

### Proposed changes

Add a new non-optional field to the pool parameters that specifies the SPO's default vote, with 3 possible values:
* `DefaultNoConfidence`: `Yes` on `NoConfidence`, `No` on all other actions (matches delegation to `AlwaysNoConfidence`)
* `DefaultAbstain`: `Abstain` on all actions (matches delegation to `AlwaysAbstain`)
* `NoDefault`: `No` on all actions (matches no delegation to a default DRep)

<br>

Currently the pool parameters are specified in cddl like this:

```cddl
pool_params =
( operator : pool_keyhash
, vrf_keyhash : vrf_keyhash
, pledge : coin
, cost : coin
, margin : unit_interval
, reward_account : reward_account
, pool_owners : set<addr_keyhash>
, relays : [* relay]
, pool_metadata : pool_metadata/ nil
)
```

The proposed definition is:
```cddl
pool_params =
( operator : pool_keyhash
, vrf_keyhash : vrf_keyhash
, pledge : coin
, cost : coin
, margin : unit_interval
, reward_account : reward_account
, pool_owners : set<addr_keyhash>
, relays : [* relay]
, pool_metadata : pool_metadata/ nil
, default_vote : stakepool_default_vote
)

stakepool_default_vote = default_vote_abstain / default_vote_no_confidence / no_default_vote
Copy link
Collaborator

Choose a reason for hiding this comment

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

@Crypto2099's comment from CIP Editors meeting # 123

  • Since we are making this change, does it make sense to offer a default "yes" vote?

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally I would be opposed to having a default "yes" option to closely mimic our default "no" voting for all governance actions as it applies to dReps and the CC already. I think allowing SPOs to effectively choose default "yes" as an option could cause issues with inactive/myopic SPOs that causes some GAs to pass that otherwise shouldn't.

IF we were to allow default "yes", then I think it should come with some sort of expiration date that requires an SPO to re-affirm this default choice every so often. However I think that added complexity is not worth the benefit and would rather just leave default "yes" out altogether.

Copy link
Contributor

@gitmachtl gitmachtl Nov 25, 2025

Choose a reason for hiding this comment

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

I am on the same page as @Cerkoryn , whats the point of a default "yes" vote? Do an "always abstain" if you don't care. A default "yes" vote sounds like a "do whatever you guys want i support it" option.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Didn't see this discussion at the time I posted #1108 (review) but in any case we should consider this an active review item.

Copy link
Contributor

Choose a reason for hiding this comment

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

See my take on this suggestion: #1108 (comment)

TLDR: it is a bad idea and I am very much against it.

This was also the comment on Discord from Johnny Kelly on Discord about this idea:

So long as the Default Options available are only Auto-Abstain, or No-confidence Delegation.
An Auto Yes Vote Option could be very irresponsible...

Copy link
Collaborator

Choose a reason for hiding this comment

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

There is no fundamental difference from a "default" yes, no, or abstain vote or an explicit vote cast on chain except for the person who wants to agree with any action except for those they explicitly want to cast a "No" or "Abstain" vote on. What questions have been posed to SPOs in the year+ of governance for which they've been responsible that would have been endangered by a default "yes" option?

The CC has no "default" vote option so must always cast an explicit vote for those actions which their vote is required for. For an ecosystem that values personal liberty and freedom of choice and permissionless behavior it's rather strange that three strangers in a quiet back room get to decide which options I'm allowed to choose for myself and which ones are "too dangerous" for me to be trusted with.

You don't get to have it both ways, are we governed by the people, for the people, for the good of the blockchain, or by what whomever happens to be the Ledger team lead at the time thinks is a "good and responsible" decision?

Copy link
Contributor

Choose a reason for hiding this comment

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

@Crypto2099 That is the beauty of the CIP process. I can suggest whatever the hell I want in my CIP. You don't like it, write your own and stop pushing your opinion on CIP authors.
I am sure you know by now, that online it is usually the loudest person that wins. And you are one of the loudest people I know. So, stop blaming me on using some sort of powers that you think I have and look in the mirror before blaming someone.

default_vote_abstain = 0
default_vote_no_confidence = 1
no_default_vote = 2
```

This change requires a hard fork, since it modifies transaction serialization.

### Migration of currently configured default votes

At the hard-fork boundary, the pool parameters of each existing pool will be updated to reflect the implicit preference currently expressed through its reward account delegation.
For each pool, we'll set the new `defaultVote` parameter to:
* `DefaultAbstain`, if the reward account is delegated to `AlwaysAbstain`
* `DefaultNoConfidence`, if the reward account is delegated to `AlwaysNoConfidence`
* `NoDefault`, if the reward account is not delegated to a defaul DRep

## Rationale: how does this CIP achieve its goals?

This CIP replaces a temporary workaround with a simple, explicit field in the pool parameters.
The new field makes each pool's default vote transparent and self-contained.

Limiting the field to three fixed values: `DefaultNoConfidence`, `DefaultAbstain`, and `NoDefault` preserves current behaviours while keeping the change minimal, easy to implement, and compatible with existing ledger logic.

The proposal also addresses the concern that large pools might unintentionally vote `No`, skewing governance results.

Backward compatibility is maintained by migrating each pool’s current implicit default to the corresponding explicit value at the hard fork boundary.

## Path to Active

### Acceptance Criteria

- [ ] Transaction serializers and deserializers in [cardano-ledger](https://github.com/IntersectMBO/cardano-ledger) are implemented such that they follow the cddl specification described above, and reflected in the cddl specs
- [ ] The migration of the existing default vote preferences is implemented in ledger
- [ ] The feature is integrated into [cardano-node](https://github.com/IntersectMBO/cardano-node) with necessary adjustments made to [ouroboros-consensus](https://github.com/IntersectMBO/ouroboros-consensus) and released as part of the Dijkstra era hard fork

### Implementation Plan

- [ ] Add support for a new pool parameter without changing serialization in existing eras
- [ ] Implement and test migration logic to populate the new parameter at the hard-fork boundary.

## Copyright

This CIP is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode).