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

Add Vote Delegation Operation to Rosetta (Installment 1) #288

Open
Kartiiyer12 opened this issue Feb 19, 2025 · 7 comments · May be fixed by #307
Open

Add Vote Delegation Operation to Rosetta (Installment 1) #288

Kartiiyer12 opened this issue Feb 19, 2025 · 7 comments · May be fixed by #307
Assignees
Labels
enhancement New feature or request high

Comments

@Kartiiyer12
Copy link
Collaborator

Why

As we are in the conway era now, the rosetta-java should also start supporting the governance features as a part of the operations.
This is needed -

  • For Exchange SPOs who can can vote using rosetta for GA (hard fork initiation atleast)
  • VoteDelegation to a DRep (for staking withdrawal)
  • Exchange ingest all blocks/transactions/operations for historical records, so they need an accurate history of all operations. As some actions like DRepRegistration require a deposit, which we need to be able to account for to accurately calculate the transaction fees.

What

  1. Operations to added for transaction building to cover governance operations like -
  • DRepRegistration
  • DRepDeregistration
  • VoteDelegation
  • Voting as SPO, DRep
  1. The /block/transaction endpoint when queried for the DRep registration/vote delegation/voting transaction should show proper operation as it currently show for stake registration and stake delegation.
{
                "operation_identifier": {
                    "index": 1
                },
                "type": "stakeKeyRegistration",
                "status": "success",
                "account": {
                    "address": "stake1uxzn54wypm23d0v4d54fftgkv6d8le2pg4mylrhw53gzu4s2trsrj"
                },
                "metadata": {
                    "depositAmount": {
                        "value": "2000000",
                        "currency": {
                            "symbol": "ADA",
                            "decimals": 6
                        }
                    }
                }
            },
            {
                "operation_identifier": {
                    "index": 2
                },
                "type": "stakeDelegation",
                "status": "success",
                "account": {
                    "address": "stake1uxzn54wypm23d0v4d54fftgkv6d8le2pg4mylrhw53gzu4s2trsrj"
                },
                "metadata": {
                    "pool_key_hash": "57147265c639309d365ef7c419698cbc9c1d3337d58c1c6a373a4130"
                }
            },
@Kartiiyer12 Kartiiyer12 added enhancement New feature or request high labels Feb 19, 2025
@Kartiiyer12
Copy link
Collaborator Author

Kartiiyer12 commented Feb 20, 2025

Instalment 1 feature -

  • voteDelegation operation for txn building, the option for stake address to delegate to a Drep (Must have).

Instalment 2 feature -

  • /block/transaction endpoint identify the operations such as DRep Registration, DRep Registration and vote delelgation (Must have)
  • Voting for SPOs on GA (should have)

Instalment 3 feature -

  • DrepRegistraion and DRep Deregristaion operaton for txn building. (Could have)
  • DrepRegistraion and DRep Deregristaion operaton for txn building. (Must have)
  • Voting for DReps (Must have)
  • /block/transaction endpoint identify other GA such as proposal submission (could have)

@matiwinnetou matiwinnetou self-assigned this Feb 21, 2025
@linconvidal linconvidal changed the title Add governance features for Rosetta Add Vote Delegation Operation to Rosetta (Installment 1) Mar 1, 2025
@linconvidal
Copy link
Member

linconvidal commented Mar 1, 2025

I took the original GitHub issue and streamlined it to clearly focus on installment 1 only, making the task easier for everyone to understand. I simplified the scope to include just what’s strictly needed first (the vote_deleg_cert operation), and also explicitly called out what’s out-of-scope to help us avoid any confusion about future installments. Lastly, I included handy technical references at the end, so they’re easy to find when someone starts implementing.

Let me know if this aligns with what you had in mind!


Background

With the Conway era activated, Cardano has introduced governance operations enabling stake credentials to delegate their voting power to Delegate Representatives (DReps). Rosetta, which provides standardized blockchain integration for exchanges and wallets, currently lacks support for these governance-related operations. Implementing vote delegation is the first essential step toward comprehensive governance support. To ensure incremental delivery, we are splitting new governance certificate support into multiple installments (as already noted in the GitHub issue).

Objective

Introduce minimal support for the vote_deleg_cert ledger certificate using Rosetta’s construction and data APIs, allowing stake credentials to delegate votes to a DRep.

Scope of Work

  • Define and implement a new Rosetta operation type named dRepVoteDelegation (CBOR tag 9).
  • Add dRepVoteDelegation to the list of operation types returned by /network/options
  • Extend transaction construction endpoints (/construction/preprocess and /construction/payloads) to support building transactions containing the voteDelegation operation.
  • Ensure /block/transaction endpoint correctly parses and identifies the voteDelegation operation in historical transaction records.
  • No additional endpoints or brand-new request/response types are strictly required.

Technical Requirements

  • Operation should include metadata to specify:
    • Stake credential (staking_credential)
    • DRep identifier (drep_key_hash)
  • Allow special cases for DRep identifier:
    • Regular DRep (key hash or script hash)
    • Special "no confidence" or "auto abstain" identifiers, represented explicitly within metadata.

Example: dRepVoteDelegation Operation

Below is one example operation for a single-certificate transaction, assuming the stake key is already registered:

{
  "operation_identifier": { "index": 1 },
  "type": "dRepVoteDelegation",
  "status": "",   // empty if this is a pre-construction operation
  "account": {
    "address": "stake_test1uq3f99..."
    // The stake address that wants to delegate their *vote* to some DRep
  },
  "metadata": {
    "staking_credential": {
      "hex_bytes": "4CF7C1CCEE5015A8DD8E563224EB4F7A07B8...97B",
      "curve_type": "edwards25519"
    },
    "drep_id": "4A1BC3...DEF0",  // Optional: present for standard DReps (e.g., key_hash or script_hash)
    "drep_type": "key_hash"      // Mandatory: valid values include "key_hash", "script_hash", "abstain", "no_confidence"
  }
}

Notice we can reuse the same approach as the older stakeDelegation operation. The difference is simply the operation.type (which signals to our api code that it must produce a vote_deleg_cert certificate on chain) and the presence of relevant fields in metadata.

All dRep types

Regular DRep (key hash)

"metadata": {
  "staking_credential": { ... },
  "drep_id": "4A1BC3...DEF0",
  "drep_type": "key_hash"
}

Regular DRep (script hash)

"metadata": {
  "staking_credential": { ... },
  "drep_id": "6B8A9321...AC4F",
  "drep_type": "script_hash"
}

Abstain

"metadata": {
  "staking_credential": { ... },
  "drep_type": "abstain"
}

No Confidence

"metadata": {
  "staking_credential": { ... },
  "drep_type": "no_confidence"
}

Out of Scope (for future installments)

  • Other governance certificates (e.g., drep_reg_certdrep_dereg_cert).
  • Migration of existing stake certificates to new governance certificate formats.

Note: The ledger still accepts the older stake certs, but the plan is that eventually these older ones are deprecated. For Rosetta, you can keep the existing “stakeKeyRegistration” or “stakeDelegation” operation types for Babbage‐era compatibility, but gradually switch them (internally) to produce the new “reg_cert (7)” or “stake_reg_deleg_cert (11)” once that’s stable.

Acceptance Criteria

  • Transactions delegating votes can be constructed and submitted successfully through Rosetta endpoints.
  • Historical transactions involving vote delegation are accurately parsed and reflected via Rosetta's /block/transaction endpoint.
  • Special delegation cases (no confidence/auto abstain) are explicitly supported and documented.
  • The dRepVoteDelegation operation type is correctly returned in the /network/options response.

Reference & useful links

@matiwinnetou
Copy link
Collaborator

matiwinnetou commented Mar 4, 2025

Thank You @linconvidal, within metadata, there is metadata, isn't that it can be either:

  • drep_key_hash
  • drep_script_hash
    ?

Also it seems there is a legacy dRep Id and more up to date one. I need to dig into details of CIP-129 in this regard but at the moment all we need to make sure is that input API is not different and the contract would not change, which I am assuming it doesn't because it is just probably a different "string.

In the example above, you also didn't show how we could do no_confidence vote and add some drep_delegation_type parameter. We need to add this to the specification

@linconvidal
Copy link
Member

Hey! After discussing this with @matiwinnetou earlier today, we concluded that it would be better to introduce a separate field to specify the DRep type. By using two fields, we avoid conflating different identifier formats into a single string, and we also make validation logic more straightforward, because we can branch on drep_id_type first and then parse drep_id accordingly.

Here’s what I have in mind:

  • If drep_id_type is "key_hash" or "script_hash", then drep_id must be a blake2b-224 hash (i.e., a typical “real” DRep).
  • If drep_id_type is "predefined", then drep_id can be either "abstain" or "no_confidence" (or any other special string we might introduce later).

Example Usage

  • Regular DRep (key hash)

    "metadata": {
      "staking_credential": { ... },
      "drep_id": "4A1BC3...DEF0",
      "drep_id_type": "key_hash"
    }
  • Regular DRep (script hash)

    "metadata": {
      "staking_credential": { ... },
      "drep_id": "6B8A9321...AC4F",
      "drep_id_type": "script_hash"
    }
  • Abstain

    "metadata": {
      "staking_credential": { ... },
      "drep_id": "abstain",
      "drep_id_type": "predefined"
    }
  • No Confidence

    "metadata": {
      "staking_credential": { ... },
      "drep_id": "no_confidence",
      "drep_id_type": "predefined"
    }

What do you think @Kartiiyer12 @matiwinnetou? I’ve also updated my previous comment to reflect these changes, if this approach sounds good to everyone!

@matiwinnetou
Copy link
Collaborator

Almost, I suggest a bit differently:

No Confidence

"metadata": {
  "staking_credential": { ... },
  "drep_type": "no_confidence"
}

and

"metadata": {
  "staking_credential": { ... },
  "drep_id": "6B8A9321...AC4F",
  "drep_type": "script_hash"
}

drep_type is always mandatory, drep_id is optional.

the rest very should be analogous

@linconvidal
Copy link
Member

@matiwinnetou Nice, seems cleaner!

@matiwinnetou
Copy link
Collaborator

matiwinnetou commented Mar 7, 2025

upon reflection and playing around I propose a slightly different structure, more nested.

"metadata": {
  "staking_credential": { ... },
  "drep": {
      "id": "6B8A9321...AC4F",
      "type": "script_hash"
   }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request high
Projects
None yet
3 participants