-
Notifications
You must be signed in to change notification settings - Fork 324
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CIP-36? | Update CIP-15 to support multi-delegation (#188)
* Update CIP-15 to support multi-delegation Co-authored-by: Kevin Hammond <[email protected]> * make cddl schema backwards compatible * add new test vector * Revert "add new test vector" This reverts commit d0d5402. * Revert "make cddl schema backwards compatible" This reverts commit 7a3df9b. * Revert "Update CIP-15 to support multi-delegation" This reverts commit 3f32fc1. * Add new test vector * Add backwards compatible schema.cddl * Add Catalyst support multi-delegation Create alternative to CIP-15 to support multi-delegation * Add Mark Stopka to the author list, remove Sebastien Guillemot, Rinor Hoxha and Mikhail Zabaluev. * Add section about voting key derivation path. * Change status to 'Proposed'. * encode limit for weight in cddl * Address future addition of different stake credentials * add clarification about registrations with different voting purpose values * Fix leftover changes * fix legacy test vector * Update delegations example in README Co-authored-by: Kevin Hammond <[email protected]> Co-authored-by: KtorZ <[email protected]> Co-authored-by: Mark Stopka <[email protected]>
- Loading branch information
1 parent
d37738a
commit 1cc035d
Showing
3 changed files
with
326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
--- | ||
CIP: 36 | ||
Title: Catalyst/Voltaire Registration Transaction Metadata Format (Updated) | ||
Authors: Giacomo Pasini <[email protected]>, Kevin Hammond <[email protected]>, Mark Stopka <[email protected]> | ||
Comments-URI: https://forum.cardano.org/t/cip-catalyst-registration-metadata-format/44038 | ||
Status: Proposed | ||
Type: Standards | ||
Created: 2021-12-06 | ||
License: CC-BY-4.0 | ||
--- | ||
|
||
## Abstract | ||
|
||
Cardano uses a sidechain for its treasury system. One needs to "register" to participate on this sidechain by submitting a registration transaction on the mainnet chain. This CIP details the registration transaction format. | ||
This is a revised version of the original CIP-15. | ||
|
||
## Motivation | ||
|
||
Cardano uses a sidechain for its treasury system ("Catalyst") and for other voting purposes. One of the desirable properties of this sidechain is that even if its safety is compromised, it doesn't cause loss of funds on the main Cardano chain. To achieve this, instead of using your wallet's recovery phrase on the sidechain, we need to use a brand new "voting key". | ||
|
||
However, since 1 ADA = 1 vote, a user needs to associate their mainnet ADA to their new voting key. This can be achieved through a registration transaction. | ||
|
||
In addition, to encourage participation by a broader range of ADA holders, it should be possible to delegate one's rights to vote to (possibly multiple) representatives and/or expert voters. Such delegations will still be able to receive Catalyst rewards. | ||
|
||
We therefore need a registration transaction that serves three purposes: | ||
|
||
1. Registers a "voting key" to be included in the sidechain and/or delegates to existing "voting key"s | ||
2. Associates mainnet ADA to this voting key(s) | ||
3. Declares an address to receive Catalyst rewards | ||
|
||
|
||
Note: This schema does not attempt to differentiate delegations from direct registrations, as the two options have exactly the same format. It also does not distinguish between delegations that are made as "private" arrangements (proxy votes) | ||
from those that are made by delegating to representatives who promote themselves publicly. | ||
Distinguishing these possibilities is left to upper layers or future revisions of this standard, if required. | ||
In this document, we will use the term 'delegations' to refer to all these possibilities. | ||
|
||
## Specification | ||
|
||
### Registration metadata format | ||
|
||
A registration transaction is a regular Cardano transaction with a specific transaction metadata associated with it. | ||
|
||
Notably, there should be five entries inside the metadata map: | ||
- A non-empty array of delegations, as described below; | ||
- A stake address for the network that this transaction is submitted to (to point to the Ada that is being delegated); | ||
- A Shelley address discriminated for the same network this transaction is submitted to to receive rewards. | ||
- A nonce that identifies that most recent delegation | ||
- A non-negative integer that indicates the purpose of the vote. This is an optional field to allow for compatibility with CIP-15. For now, we define 0 as the value to use for Catalyst, and leave others for future use. A new registration should not invalidate a previous one with a different voting purpose value. | ||
|
||
### Delegation format | ||
|
||
A delegation assigns (a portion of) the ADA controlled by one or more UTxOs on mainnet to the voting key in the sidechain as voting power. The UTxOs can be identified via the stake address at some designated point in time. | ||
|
||
Each delegation therefore contains: | ||
- a voting key: simply an ED25519 public key. This is the spending credential in the sidechain that will receive voting power from this delegation. For direct voting it's necessary to have the corresponding private key to cast votes in the sidechain. How this key is created is up to the wallet. | ||
- the weight that is associated with this key: this is a 4-byte unsigned integer (CBOR major type 0, The weight may range from 0 to 2^32-1) that represents the relative weight of this delegation over the total weight of all delegations in the same registration transaction. | ||
|
||
### Voting key derivation path | ||
|
||
To avoid linking voting keys directly with Cardano spending keys, the voting key derivation path must start with a specific segment: | ||
|
||
`m / 1694' / 1815' / account' / chain / address_index` | ||
|
||
### Associating voting power with a voting key | ||
|
||
This method has been used since Fund 2. | ||
For future fund iterations, a new method making use of time-lock scripts may | ||
be introduced as described [below][future-development]. | ||
|
||
Recall: Cardano uses the UTXO model so to completely associate a wallet's balance with a voting key (i.e. including enterprise addresses), we would need to associate every payment key to a voting key individually. Although there are attempts at this (see [CIP-0008]), the resulting data structure is a little excessive for on-chain metadata (which we want to keep small) | ||
|
||
Given the above, we choose to associate staking credentials with voting keys. At the moment, the only supported staking credential is a staking key. Since most Cardano wallets only use base addresses for Shelley wallet types, in most cases this should perfectly match the user's wallet. | ||
|
||
The voting power that is associated with each delegated voting key is derived from the user's total voting power | ||
as follows. | ||
|
||
1. The total weight is calculated as a sum of all the weights; | ||
2. The user's total voting power is calculated as a whole number of ADA (rounded down); | ||
3. The voting power associated with each voting key in the delegation array is calculated as the weighted fraction of the | ||
total voting power (rounded down); | ||
4. Any remaining voting power is assigned to the last voting key in the delegation array. | ||
|
||
This ensures that the voter's total voting power is never accidentally reduced through poor choices of weights, | ||
and that all voting powers are exact ADA. | ||
|
||
### Example | ||
|
||
Voting registration example: | ||
``` | ||
61284: { | ||
// delegations - CBOR byte array | ||
1: [["0xa6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d1663", 1], ["0x00588e8e1d18cba576a4d35758069fe94e53f638b6faf7c07b8abd2bc5c5cdee", 3]], | ||
// stake_pub - CBOR byte array | ||
2: "0xad4b948699193634a39dd56f779a2951a24779ad52aa7916f6912b8ec4702cee", | ||
// reward_address - CBOR byte array | ||
3: "0x00588e8e1d18cba576a4d35758069fe94e53f638b6faf7c07b8abd2bc5c5cdee47b60edc7772855324c85033c638364214cbfc6627889f81c4", | ||
// nonce | ||
4: 5479467 | ||
// voting_purpose: 0 = Catalyst | ||
5: 0 | ||
} | ||
``` | ||
The entries under keys 1, 2, 3, 4 and 5 represent the Catalyst delegation array, | ||
the staking credential on the Cardano network, the address to receive rewards, | ||
a nonce, and a voting purpose, respectively. A registration with these metadata will be | ||
considered valid if the following conditions hold: | ||
|
||
- The nonce is an unsigned integer (of CBOR major type 0) that should be | ||
monotonically rising across all transactions with the same staking key. | ||
The advised way to construct a nonce is to use the current slot number. | ||
This is a simple way to keep the nonce increasing without having to access | ||
the previous transaction data. | ||
- The reward address is a Shelley address discriminated for the same network | ||
this transaction is submitted to. | ||
- The delegation array is not empty | ||
- The weights in the delegation array are not all zero | ||
|
||
|
||
Delegation to the voting key `0xa6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d1663` will have relative weight 1 and delegation to the voting key `0x00588e8e1d18cba576a4d35758069fe94e53f638b6faf7c07b8abd2bc5c5cdee` relative weight 3 (for a total weight of 4). | ||
Such a registration will assign 1/4 and 3/4 of the value in ADA to those keys respectively, with any remainder assigned to the second key. | ||
|
||
The registration witness depends on the type of stake credential used. | ||
To produce the witness field in case of a staking public key, the CBOR representation of a map containing | ||
a single entry with key 61284 and the registration metadata map in the | ||
format above is formed, designated here as `sign_data`. | ||
This data is signed with the staking key as follows: first, the | ||
blake2b-256 hash of `sign_data` is obtained. This hash is then signed | ||
using the Ed25519 signature algorithm. The witness metadata entry is | ||
added to the transaction under key 61285 as a CBOR map with a single entry | ||
that consists of the integer key 1 and signature as obtained above as the byte array value. | ||
|
||
Witness example: | ||
``` | ||
61285: { | ||
// witness - ED25119 signature CBOR byte array | ||
1: "0x8b508822ac89bacb1f9c3a3ef0dc62fd72a0bd3849e2381b17272b68a8f52ea8240dcc855f2264db29a8512bfcd522ab69b982cb011e5f43d0154e72f505f007" | ||
} | ||
``` | ||
|
||
### Metadata schema | ||
|
||
See the [schema file](./schema.cddl) | ||
|
||
# Test vector | ||
|
||
See [test vector file](./test-vector.md) | ||
|
||
### Future development | ||
|
||
[future-development]: #future-development | ||
|
||
A future change of the Catalyst system may make use of a time-lock script to commit ADA on the mainnet for the duration of a voting period. The voter registration metadata in this method will not need an association | ||
with a staking credential. Therefore, the `staking_credential` map entry | ||
and the `registration_witness` payload with key 61285 will no longer | ||
be required. | ||
|
||
## Changelog | ||
|
||
Fund 3 added the `reward_address` inside the `key_registration` field. | ||
|
||
Fund 4: | ||
- added the `nonce` field to prevent replay attacks; | ||
- changed the signature algorithm from one that signed `sign_data` directly | ||
to signing the Blake2b hash of `sign_data` to accommodate memory-constrained hardware wallet devices. | ||
|
||
It was planned that since Fund 4, `registration_signature` and the `staking_pub_key` entry inside the `key_registration` field will be deprecated. | ||
This has been deferred to a future revision of the protocol. | ||
|
||
Fund 8: | ||
- renamed the `voting_key` field to `delegations` and add support for splitting voting power across multiple vote keys. | ||
- added the `voting_purpose` field to limit the scope of the delegations. | ||
- rename the `staking_pub_key` field to `stake_credential` and `registration_signature` to `registration_witness` to allow for future credentials additions. | ||
|
||
## Copyright | ||
|
||
This CIP is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode) | ||
|
||
[CIP-0008]: https://github.com/cardano-foundation/CIPs/tree/master/CIP-0008 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
registration_cbor = { | ||
61284: key_registration, | ||
61285: registration_witness | ||
} | ||
|
||
$voting_pub_key /= bytes .size 32 | ||
$reward_address /= bytes | ||
$nonce /= uint | ||
$proportion /= uint .size 4 | ||
$voting_purpose /= uint | ||
legacy_key_registration = $voting_pub_key | ||
delegation = ($voting_pub_key, $proportion) | ||
|
||
; May support other stake credentials in the future. | ||
; Such additional credentials should be tagged at the CDDL/CBOR level | ||
; so that parsing is not ambiguous and future proof. | ||
; However, to avoid breaking changes, the simple key credential is | ||
; left untagged. | ||
$stake_credential /= $staking_pub_key | ||
$stake_witness /= $ed25519_signature | ||
; A stake key credential, not tagged for backward compatibility | ||
$staking_pub_key /= bytes .size 32 | ||
; Witness for a stake key credential, not tagged for backward compatibility | ||
$ed25519_signature /= bytes .size 64 | ||
|
||
|
||
key_registration = { | ||
1 : [+delegation] / legacy_key_registration, | ||
2 : $stake_credential, | ||
3 : $reward_address, | ||
4 : $nonce, | ||
? 5 : $voting_purpose .default 0 | ||
} | ||
|
||
|
||
registration_witness = { | ||
1 : $stake_witness | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# Test vector for CIP15 | ||
|
||
### Inputs | ||
|
||
Payment **public** key hex | ||
``` | ||
3273a5316e4de228863bd7cf8dac90d57149e1a595f3dd131073b84e35546676 | ||
``` | ||
|
||
Staking **private** key hex | ||
``` | ||
f5beaeff7932a4164d270afde7716067582412e8977e67986cd9b456fc082e3a | ||
``` | ||
|
||
Catalyst **private** key hex | ||
``` | ||
4820f7ce221e177c8eae2b2ee5c1f1581a0d88ca5c14329d8f2389e77a465655c27662621bfb99cb9445bf8114cc2a630afd2dd53bc88c08c5f2aed8e9c7cb89 | ||
``` | ||
|
||
### Intermediate steps | ||
|
||
Reward address generated from staking key | ||
``` | ||
bech32 | ||
stake_test1uzhr5zn6akj2affzua8ylcm8t872spuf5cf6tzjrvnmwemcehgcjm | ||
hex-encoded | ||
e0ae3a0a7aeda4aea522e74e4fe36759fca80789a613a58a4364f6ecef | ||
``` | ||
|
||
Data to sign (human readable format) | ||
|
||
Legacy version (full delegation to one key only): | ||
```javascript | ||
'61284': { | ||
'1': '0x0036ef3e1f0d3f5989e2d155ea54bdb2a72c4c456ccb959af4c94868f473f5a0', | ||
'2': '0x86870efc99c453a873a16492ce87738ec79a0ebd064379a62e2c9cf4e119219e', | ||
'3': '0xe0ae3a0a7aeda4aea522e74e4fe36759fca80789a613a58a4364f6ecef', | ||
'4': 1234, | ||
}, | ||
``` | ||
|
||
New version: | ||
```javascript | ||
'61284': { | ||
'1': [['0xa6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d1663', 1], ['0x00588e8e1d18cba576a4d35758069fe94e53f638b6faf7c07b8abd2bc5c5cdee', 3]], | ||
'2': '0x86870efc99c453a873a16492ce87738ec79a0ebd064379a62e2c9cf4e119219e', | ||
'3': '0xe0ae3a0a7aeda4aea522e74e4fe36759fca80789a613a58a4364f6ecef', | ||
'4': 1234, | ||
'5': 0 | ||
}, | ||
``` | ||
|
||
|
||
Metadata (CBOR encoding) | ||
|
||
Legacy: | ||
``` | ||
a119ef64a4015820a6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d166302582086870efc99c453a873a16492ce87738ec79a0ebd064379a62e2c9cf4e119219e03581de0ae3a0a7aeda4aea522e74e4fe36759fca80789a613a58a4364f6ecef041904d2 | ||
``` | ||
|
||
New: | ||
``` | ||
a119ef64a50182825820a6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d16630182582000588e8e1d18cba576a4d35758069fe94e53f638b6faf7c07b8abd2bc5c5cdee0302582086870efc99c453a873a16492ce87738ec79a0ebd064379a62e2c9cf4e119219e03581de0ae3a0a7aeda4aea522e74e4fe36759fca80789a613a58a4364f6ecef041904d20500 | ||
``` | ||
|
||
Blake2b-256 hash of metadata | ||
|
||
Legacy: | ||
``` | ||
872bcb4a9e2b110a06fd5de04be5924b6c659c28a1665ecc75def13ebca6dfd8 | ||
``` | ||
|
||
New: | ||
``` | ||
5bc0681f173efd76e1989037a3694b8a7abea22053f5940cbb5cfcdf721007d7 | ||
``` | ||
|
||
### Output | ||
|
||
Legacy: | ||
```javascript | ||
{ | ||
'61284': { | ||
'1': '0x0036ef3e1f0d3f5989e2d155ea54bdb2a72c4c456ccb959af4c94868f473f5a0', | ||
'2': '0x1c5d88aa573da97e5a4667e0f7c4a9c6a3d848934c3b0a5b9296b401540f2aef', | ||
'3': '0xe0ae3a0a7aeda4aea522e74e4fe36759fca80789a613a58a4364f6ecef', | ||
'4': 1234, | ||
}, | ||
'61285': { | ||
'1': '0xcf8e34db193edc930faf64626a0a759dd9ce654874d4b6f255dc2aa8f52313b6dbb9aa1b162b43ed8946668edca920dd34f5a51a14130814fdc86adb6218b501' | ||
} | ||
} | ||
``` | ||
|
||
New: | ||
```javascript | ||
{ | ||
'61284': { | ||
'1': [['0xa6a3c0447aeb9cc54cf6422ba32b294e5e1c3ef6d782f2acff4a70694c4d1663', 1], ['0x00588e8e1d18cba576a4d35758069fe94e53f638b6faf7c07b8abd2bc5c5cdee', 3]], | ||
'2': '0x1c5d88aa573da97e5a4667e0f7c4a9c6a3d848934c3b0a5b9296b401540f2aef', | ||
'3': '0xe0ae3a0a7aeda4aea522e74e4fe36759fca80789a613a58a4364f6ecef', | ||
'4': 1234, | ||
'5': 0 | ||
}, | ||
'61285': { | ||
'1': '0x3aaa2e6b43c0a96e880a7d70df84dffb2a1a17b19d7a99a6ed27b91d499b32027c43acfbf6dff097af7634b2ee38c8039af259b0b6a64316f02b4ffee28a0608' | ||
} | ||
} | ||
``` |