Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIP-0126? | Multi-Stake Delegation from a Single Account #628

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
146 changes: 146 additions & 0 deletions CIP-XXXX/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
CIP: ????
rphair marked this conversation as resolved.
Show resolved Hide resolved
Title: Multi-Stake Delegation from a Single Account
Category: Wallets
Status: Proposed
Authors:
- Angel Castillo <angel.castillo@iohk.io>
- Fernando Moreno <fernando.moreno@iohk.io>
- Martynas Kazlauskas <martynas.kazlauskas@iohk.io>
- Mircea Hasegan <mircea.hasegan@iohk.io>
- Rhys Bartels-Waller <rhys.bartelswaller@iohk.io>
Implementors:
- Angel Castillo <angel.castillo@iohk.io>
- Mircea Hasegan <mircea.hasegan@iohk.io>
Discussions:
- https://github.com/cardano-foundation/CIPs/pull/628
Created: 2023-11-30
License: CC-BY-4.0
---

## Abstract

This document presents an alternative approach for Cardano sequential wallets to support multiple stake keys by deriving them from a single account. Building
upon the foundations of [CIP-1852](https://github.com/cardano-foundation/CIPs/tree/master/CIP-1852) and [CIP-0011](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0011), this proposal introduces a simple method for managing multiple delegations within a single account.

## Terminology
rphair marked this conversation as resolved.
Show resolved Hide resolved

Before delving into the specifics of the proposal, it's important to define two key terms that will be used throughout this document:

- **First Payment Key:** This refers to the external (role 0) payment key derived at index 0.

- **First Stake Key:** Similarly, this is the stake key (role 2) derived at index 0.

Throughout this proposal, the terms "first payment key" and "first stake key" will be used to refer to these specific keys.

## Motivation: why is this CIP necessary?
The current philosophy of Cardano wallets, centering around a single stake key per wallet, has served well during the initial adoption phase. However, as the Cardano ecosystem expands and matures, the need for more flexible delegation options becomes evident. This proposal introduces a method for the derivation of multiple stake keys from a single account, combining the original simplicity with flexibility.

### Empowering Smaller Actors
In the current system, moderate stakeholders often find themselves constrained, unable to optimize returns due to limited delegation capabilities. This proposal empowers them to delegate across a diverse set of pools, offering a way to hedge against pool underperformance and sudden changes. It allows for a comprehensive view of their balance within a single account, thus combining convenience with enhanced delegation options. Additionally, Cardano projects are often funded via Initial Stake Pool Offering (ISPO). When multiple ISPOs happen at the same time, users might want to participate in more than one. Multi-delegation enables doing this from a single account.

### Addressing the Challenges for Large Stakeholders
Large stakeholders currently face the challenge of distributing their stake without causing pool over-saturation, which affects potential rewards. The current remedy, which involves segmenting funds into multiple distinct accounts, does not provide a good UX, requiring users to constantly switch across multiple accounts for core operations, or requiring wallet developers to add an abstraction layer on top of user accounts to overcome this issue.

### Efficient Fund Tracking with Optional Privacy
By linking all stake keys to the first payment key, this proposal introduces a transparent and simple mechanism for multi-delegation, greatly simplifying the fund tracking process. This association not only simplifies the delegation and deregistration processes but also facilitates easier tracking of funds and delegations. Besides, this method does not preclude the use of the multi-account approach for users desiring enhanced privacy. Stakeholders can still derive multiple accounts, each potentially capable of multi-delegation, granting them granular control while retaining the option for increased privacy.

### Foundation for Advanced Wallet Features and Enhanced User Experience
One of the underlying rationales of this proposal is to provide a robust foundation for more advanced wallet features. The dynamic nature of this approach offers wallets the opportunity to innovate. For example allowing users to support multiple dReps from a single account, or implementing sophisticated heuristics to maintain stake distribution to different pools. .
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
One of the underlying rationales of this proposal is to provide a robust foundation for more advanced wallet features. The dynamic nature of this approach offers wallets the opportunity to innovate. For example allowing users to support multiple dReps from a single account, or implementing sophisticated heuristics to maintain stake distribution to different pools. .
One of the underlying rationales of this proposal is to provide a robust foundation for more advanced wallet features. The dynamic nature of this approach offers wallets the opportunity to innovate. For example allowing users to support multiple DReps from a single account, or implementing sophisticated heuristics to maintain stake distribution to different pools. .

Capitalization.

But also, how could this be expanded for DRep delegation? this is not clear to me.

Copy link
Author

Choose a reason for hiding this comment

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

thanks for the feedback @Ryun1, as you mentioned in your comment, DRep vote delegation and Stake delegation use the same key, so the two systems are intertwined at the protocol level, the only important consideration this CIP adds regarding DReps is that users will use more than one stake key and can have funds distributes among those stake keys, this will mean that users must also delegate their vote to the DReps for each key, for example:

Alice have a portfolio delegating to three pools, A, B and C with the following distribution 10%, 50%, 40%. She can chose to either delegate all three stake keys to the same DRep (effectively delegating 100% of her voting power to him) or delegate her different stake keys to different DReps, for example if she want to distribute her voting power between two DReps, she could delegate the same stake key used for pool A and B to DRep1 and the remaining stake key to DRep2 delegating to each each (approximately) 50% of her voting power, alternatively she could delegate to three different DReps. This is how the system works at the protocol level, the difference here is that wallets that implement this CIP will have the additionally flexibility to allow Alice to delegate to more than one DRep if she has more than one stake key.

As for how this would work with future types of delegations is hard to say since it will depend on the mechanics of those, but this CIP is not proposing/altering any feature at the protocol level, having multiple stake keys is already supported by the protocol, so I would assume there will be no conflict with any future use of stake keys unless there is a breaking protocol change in that regard.


## Specification

### Overview

Under this proposal, the constraints of [CIP-0011 ](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0011)regarding the sole derivation index for the stake key are removed. While we introduce the ability to derive stake keys beyond the first , there is no strict requirement to do so in a sequential manner, although it is recommended for logical organization. A pivotal change in this approach is that all derived stake keys must be associated with the first payment key. This consistent association to the first payment key serves as the foundation for the efficient discovery of these stake keys by wallet software and services.

### Multi-Delegating
- **Stake Key Derivation:** Begin by deriving the required number of stake keys needed for multi-delegation. While this derivation does not have to be sequential, it is recommended for clarity and orderly management. Ensure that the gap between any two consecutive active stake addresses does not exceed 20, in line with the [BIP-44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) address gap limit.

- **Key Registration:** Once derived, register these stake keys. This registration process remains consistent with current procedures, with the added context that all these new stake keys will be associated with a common payment key.

- **Fund Distribution:** Distribute the funds across addresses formed by pairing the first payment key with each of the newly created stake keys. This creates an association between all stake delegations. The details of how funds are distributed are specified by the user when creating the multi delegation transaction.

Wallet software can then easily discover all stake keys and associated delegations either by sequential discovery or identifying addresses containing the first payment credential.
rphair marked this conversation as resolved.
Show resolved Hide resolved

### Updating the Multi-Delegation
The dynamic nature of multi-delegation facilitates not just participation but also continuous optimization of delegations.

#### Adding Pools
To delegate to additional pools, the first step would involve deriving the necessary number of new stake keys. Then, make a transaction that: registers the new stake keys, delegates and distributes funds among addresses that pair the new stake keys with the first payment key.

#### Removing Pools
To remove a pool, the wallet first identifies all addresses associated with the stake key designated for removal. Then, make a transaction that
Transfer all funds from these addresses
withdraw all rewards from their associated reward accounts to one of the accounts that are still in delegation. If no other delegating accounts are left, revert the funds to addresses associated with the first payment key.
. Deregister stake keys

**Note that all rewards calculated but not distributed will be lost.**

#### Interoperability
Live delegation portfolio might drift overtime due to:
- Receiving funds to a single address
- Building transactions with software that doesn’t support multi-stake delegation (e.g. via dapp connector)

In order to maintain a record of user’s delegation portfolio preferences , all actions pertaining to stake delegation, including funds transfers, stake key registration, and deregistration, must be executed within a single atomic transaction when performing an update. This transaction should also include the delegation portfolio metadata, using the reserved metadata label 6862 (hexadecimal 0x1ace), as outlined in [CIP-0017](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0017) preferably without any of the optional fields.

Choose a reason for hiding this comment

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

Maybe make even more explicit that wallet apps must ensure that the chosen pools match between the CIP-17 JSON specification and the pools actually delegated to. … and that other wallet apps managing the same account are free to correct it if one misbehaves.

Should a new delegation certificate be included for all stakes and pools even if there is no change in that part of the multi-delegation? Advantage would be that this ensures that all stake keys have to sign the transaction partly attenuating @yHSJ's point on “Franken” addresses above. Disadvantage would be that it bloats the transaction and makes it more expensive unnecessarily.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe make even more explicit that wallet apps must ensure that the chosen pools match between the CIP-17 JSON specification and the pools actually delegated to. … and that other wallet apps managing the same account are free to correct it if one misbehaves.

I like this idea

… partly attenuating …

Since it doesn’t fully attenuate I’d vote in favour of not enforcing unnecessary certificates.

#628 (comment)


Example:

``` Json
{
"pools": [
{
"ticker": "DARK",
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that putting stake keys here instead of pool ids/tickers would be better, because:

  • there wouldn't be a need to update the metadata if delegation changes, but not the weight
  • wallet implementations will have to perform one series of lookups less: instead of caring about pools, they will be only concerned with stake keys
  • removing a delegation in favor of another would be as easy as re-delegating stake for one stake key - again, no metadata update

Copy link
Contributor

Choose a reason for hiding this comment

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

As a separate note, there is probably no need in supporting tickers at all: reverse lookups only introduce complexity for the implementors to deal with

Copy link
Collaborator

@rphair rphair Dec 1, 2023

Choose a reason for hiding this comment

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

latter #628 (comment) appears resolved here: #628 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

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

@rphair no it does not: that discussion was about tickers vs pool IDs, but I propose using stake addresses instead of pool identifiers.

Copy link
Contributor

@klntsky klntsky Dec 4, 2023

Choose a reason for hiding this comment

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

dApps that will actually make use of this standard may not care about delegations at all. So why force them to perform additional lookups to figure out which of the stake addresses correspond to which pools?

Copy link
Collaborator

@rphair rphair Dec 5, 2023

Choose a reason for hiding this comment

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

thanks @klntsky I was only referring to your 2nd #628 (comment) in my own #628 (comment); apologies for the ambiguity & I've corrected that now. BTW I would support the suggestion to use stake addresses vs. pool IDs.

Copy link
Author

@AngelCastilloB AngelCastilloB Dec 5, 2023

Choose a reason for hiding this comment

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

Regarding changing the pool ids for stake keys, this is an interesting idea, but I am not convinced yet this is better. First, wallets need this mapping anyways since in order for wallet software to determine to which pools the users is delegating to, it needs to first find the stake keys of the user and then find to which pools the keys are delegated to. The users also interact with the delegation from the point of view of pools not stake keys, as in, users select pools and percentages and this information would need to be converted to key hashes in order to create the metadata as you are suggesting. This also have the opposite effect on external actors, anyone that wants to parse this metadata to determine the user portfolio will now have to do an extra lookup to find which pools these stake keys are delegating to, as it is right now no extra lookup are required for external actors, and the wallet software already can (and need to anyway in both cases) map from stake key to pool id.

there wouldn't be a need to update the metadata if delegation changes, but not the weight

There wouldn't be the need for updating the metadata in the case where pools are swapped but no number of pools or percentages changes, agree.

wallet implementations will have to perform one series of lookup less: instead of caring about pools, they will be only concerned with stake keys

The lookup cant be avoided, users delegate to pools and this would need to be converted to stake keys anyways to issue certificates. The mapping Stake Key -> Pool cant be avoided by the wallet.

removing a delegation in favor of another would be as easy as re-delegating stake for one stake key - again, no metadata update

This is the same as point 1.

Copy link
Contributor

Choose a reason for hiding this comment

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

The users also interact with the delegation from the point of view of pools not stake keys, as in, users select pools and percentages and this information would need to be converted to key hashes in order to create the metadata as you are suggesting

You are only considering wallet's and user's point of view. But what about dApps that just want to generate change such that the distribution is preserved. These dApps may as well be other wallets that do not fully support this feature (i.e. in the UI), but try to respect the distribution.

I think it's obvious that one can always go from poolIDs to stake addresses and in the opposite direction. Stake addresses just have strictly more use cases without an extra lookup

"weight": 42
},
{
"id": "5f3833027fe8c8d63bc5e75960d9a22df52e41bdf62af5b689663c50",
"weight": 14
},
{
"id": "a16abb03d87b86f30bb743aad2e2504b126286fe744d3d2f6a0b4aec",
"weight": 37
},
{
"id": "9f9bdee3e053e3102815b778db5ef8d55393f7ae83b36f906f4c3a47",
"weight": 25
}
]
}
```

rphair marked this conversation as resolved.
Show resolved Hide resolved
The inclusion of the delegation portfolio object as transaction metadata serves to reflect any updates to the user's delegation preferences on-chain. This ensures that external applications retrieving this information are always presented with the most current data, without the need to parse through multiple transactions.

External applications can retrieve the most up-to-date delegation portfolio for a given wallet by scanning the blockchain for the latest transaction with the metadata label 6862 originating from the user's wallet. This transaction will contain the metadata with the current delegation portfolio, thereby affirming the wallet owner's latest delegation preferences.

Choose a reason for hiding this comment

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

Scanning historical transactions for a specific metadatum label is rather inefficient. For wallet apps, that's a minor problem since they will typically want to present the whole transaction history to the user anyway and they only deal with one or a small set of wallets. But for dApps that are confronted with ever new wallets every moment, it might well be prohibitive.

Copy link
Author

Choose a reason for hiding this comment

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

Agree here, but what could be the alternative? Also for external applications that need this information, they could build any off-chain solution to make this efficient.

Copy link
Collaborator

Choose a reason for hiding this comment

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

To be honest, if this standard were to be adopted the only way I would support it as a dApp developer is if the wallet itself either:

  1. Figured out its changing strategy for me
  2. At least provided the connected wallet's changing strategy

Copy link
Contributor

Choose a reason for hiding this comment

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

for the latest transaction with the metadata label 6862 originating from the user's wallet

There's no such thing as user's wallet. There are utxos at addresses that are being consumed. Consider this: I construct an atomic swap transaction and put metadata that redefines the portfolio. I send it to the swap counterparty and they sign it. Who of us now has the delegation preferences updated?

Or even simpler, I am a malicious NFT minting dApp that wants to steal user's delegation. I put a metadata hash but do not disclose it to the user (which is normally expected)...

It is important to note that currently metadata posting never imposes any financial consequences for the users. But with this proposal adopted, it will.

This should not be accepted without a clear algorithm how to go from a chain of transactions to a mapping of payment_address -> delegation_map

Copy link
Author

@AngelCastilloB AngelCastilloB Dec 5, 2023

Choose a reason for hiding this comment

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

Thanks for the feedback @klntsky, only updating the metadata doesn't affect the users delegation, the delegation can only be altered by submitting certificates and the right signatures in the transaction, so a malicious dApp cant steal user delegation by only updating the metadata of the transaction. The portfolio metadata is only intended to be consumed by off chain clients for context, I.E to determined the users preferences vs theirs actual stake distribution

Copy link
Contributor

Choose a reason for hiding this comment

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

@AngelCastilloB

delegation can only be altered by submitting certificates and the right signatures in the transaction

They do not specify the amount, so that any ADA that is on a stake pubkey is automatically delegated.

Which means a wallet or a dApp that consumes this info will find the wrongly updated metadata and prompt the user to either perform a rebalance, or will silently generate a change distribution such that ADA is moved to a SP the user didn't want to prefer more.

Right now as I understand there is no well-defined connection between user's "identity" and metadata, and what is this "identity" is also undecided.

Copy link
Author

Choose a reason for hiding this comment

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

Ah I see your point now @klntsky, so yes it would be possible for a malicious dApp to move the percentages, but it wouldn't be possible to make the user delegate to a different pool.

So I guess the attack vector you are suggesting here would be for an adversarial pool to create a dApp that when it detects an user that is multi-delegating and one of the pools is multi-delegating to is in his control, it would then change the percentages to make it more favorable for him.

I think we have a few options here:

  • Add a signature to the metadata
  • Place the metadata in an script output the user controls

Copy link
Contributor

Choose a reason for hiding this comment

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

Add a signature to the metadata

Yep. That would also make it unambiguous who is the issuer of the metadata in case of multiple user inputs. Moreover, to support this edge case, user address or pubkeyhash can be used as a key in the map.

Place the metadata in an script output the user controls

There is no way to prevent consuming an UTxO from another wallet



### Change Balancing Algorithm

Balancing change is a crucial feature designed to maintain a user’s stake distribution, using the portfolio preferences attached to the delegation transaction. As transactions occur over time, the distribution of funds across different pools will deviate from the initial portfolio percentages as the change would otherwise be concentrated onto a single address, and therefore be delegated to a single pool. This drift can be corrected while constructing transactions for a user who has defined a multi-delegation intent by reading the preferences from the delegation transaction metadata and distributing the change to best adhere

When implementing this feature, it is essential to maintain the integrity of the change outputs as produced by the input selection algorithm. The design of these algorithms, such as the Random Improve input selection, is aimed at optimizing the overall health of the wallet's UTXO (Unspent Transaction Output) set. This optimization includes avoiding the creation of dust and ensuring that the size of outputs aligns with the user's spending habits over time.

Choose a reason for hiding this comment

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

Is Random Improve really a good coin selection algorithm for this? Is it – in an unmodified form – even a good coin selection algorithm for wallets with native tokens?

Shouldn't it at least be modified to select UTxOs from all stakes as proportional as possible and not leave that to the randomness of the algorithm?

Copy link
Author

Choose a reason for hiding this comment

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

Random Improve was just provided as an example. The point here would be that implementing multi-delegation shouldn't require changing the current input selection algorithm to accommodate it, the wallet could be using an input selection strategy that optimize for a given use case, ideally we dont want to disrupt that, as forcing the wallet to come up with a new input selection algorithm that satisfies his use case and multi delegation could be too problematic. Also during our internal tests, just directing the change output was sufficient to advert drift in the long run


Therefore, the following key principle will guide the balancing change process for wallets that are multi-delegating:

Every multi delegation transaction (creation or update) must include the delegation portfolio metadata specifying the percentage of funds they wish to delegate to each pool. This portfolio serves as a guideline for how funds should be distributed across different stake keys.
When following transactions are built, input selection is performed as usual. The resulting change from the transaction is then evaluated for rebalancing. The structure and size of change outputs determined by the input selection algorithm are preserved.

Choose a reason for hiding this comment

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

When initially starting multi-delegation, Lace seems to try to ensure that UTxOs of all sizes are equally available on all of the stakes. Might be worth mentioning here?

Copy link

Choose a reason for hiding this comment

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

I think this is an implementation detail. Wallets may choose to leave the distribution of UTxOs up to the user, for example.

The change outputs will be distributed as-is across multiple addresses associated with different stake keys, without altering the outputs values. Priority is given to stake keys that are most divergent from the set preferences, thereby gradually realigning the actual distribution with the user's delegation strategy.

Choose a reason for hiding this comment

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

Why not changing the output values? If it is a transaction created in the soverignty of the wallet app, it can choose the output sizes freely and can probably better redistribute if it does.

Nit-pick: If the stake is divergent in the direction of too much stake, priority should specifically not be given to this stake. Could maybe be worded a bit clearer.

Copy link
Author

@AngelCastilloB AngelCastilloB Dec 1, 2023

Choose a reason for hiding this comment

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

Early we made the design choice to not require changes on the input selection. These change outputs are produced by selection algorithms that are design to prevent dust and in theory optimize the UTxO set of the wallet. If the wallet is already using any given strategy for UTxO selection (and change production), implementing this CIP shouldn't force the wallet to alter that if possible. In our tests, only redistributing the change outputs produced as they are was enough to subvert dirft given enough time

Choose a reason for hiding this comment

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

The problem of NFTs and other native tokens should at leas be mentioned.

Is it maybe feasible to demand that native tokens are not moved between stakes in the process that they stay on the same stake address unless the user explicitly moves them to another stake?

Copy link
Author

@AngelCastilloB AngelCastilloB Dec 1, 2023

Choose a reason for hiding this comment

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

could you elaborate more on the problem of NFTs and other native tokens?

Adding this extra requirement of allowing users to fix tokens to specific stake address would make the input selection harder, and many edge cases would need to be considered.

In short this will requiere wallets to modify their input selection algorithm. We want to avoid having as a requirement to support this having to alter the input selection algorithm, doing this properly is not trivial, some wallets may be relying on libraries that do the input selection and could not have control over this. So having as a requirement modifying/coming up with a new input selection algorithm being use by wallets seems too harsh. The approach followed by this CIP (simply redirecting change outputs) is compatible with any input selection, is easy to implement and ultimately achieve the end goal of avoiding drift


#### Benefits and Implementation Considerations

Consistent Delegation Strategy: Ensures that the user's delegation strategy is consistently maintained, even as funds are spent and rewards are received.

UTXO Set Optimization: Maintains the health and efficiency of the UTXO set as intended by the input selection algorithm.

Reduced Manual Adjustments: Minimizes the need for users to manually rebalance their stake across different pools, saving time and effort.

## Reference Implementation
rphair marked this conversation as resolved.
Show resolved Hide resolved

An already working implementation can be found in Lace wallet and the Cardano-js-sdk:

- Lace: https://github.com/input-output-hk/lace
- Cardano JS SDK: https://github.com/input-output-hk/cardano-js-sdk/blob/master/packages/e2e/src/tools/multi-delegation-data-gen/index.ts

rphair marked this conversation as resolved.
Show resolved Hide resolved
## Copyright

CC-BY-4.0
rphair marked this conversation as resolved.
Show resolved Hide resolved