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-0062? | Cardano dApp-Wallet Web Bridge Catalyst Extension #296

Closed
Closed
Changes from 8 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
81c7596
Jurmungandr api submitVote, connect to Node
ehanoc Jul 14, 2022
e360eb5
Jurmungandr unnecessary connectToNode
ehanoc Jul 14, 2022
ad82668
Removing requirement for single voting key for mnemonic. Rewording de…
ehanoc Jul 14, 2022
5cfa051
Support batching of votes in api.submitVotes. Refactor multiple steps…
ehanoc Jul 25, 2022
25fff85
Typo, 32 bytes not 64 for ed25519 pub key
ehanoc Jul 26, 2022
da74c10
remove reward address, nonce and staking key from delegation object. …
ehanoc Jul 28, 2022
3c7db95
Add getVotingKeys, rotateVotingKey, getCurrentVotingKey api methods t…
ehanoc Aug 8, 2022
8e9d58f
Removing unnecessary keypath type
ehanoc Aug 8, 2022
20feaf3
Align naming of variables and update setup-by-step guide
ehanoc Aug 10, 2022
66d8cf1
clean changes ready for merge
stevenj Sep 12, 2022
da063a4
Remove unnecessary rotateVotingKeys and getVotingKeys
ehanoc Sep 13, 2022
a12b8a6
Add sample data for delegation certificates and related keys
ehanoc Sep 15, 2022
5dc31ab
GetVotingKey endpoint
ehanoc Sep 27, 2022
dd1a2e8
votePlanId as Hex encoded. Add votePublic boolean
ehanoc Nov 3, 2022
b6a6b52
Add missing rationale. Small improvements, formatting, typos add prop…
ehanoc Nov 30, 2022
532f493
Fix description refering to old method name
ehanoc Nov 30, 2022
239d943
md formatting
stevenj Dec 12, 2022
48acc62
fix typo
stevenj Dec 12, 2022
864ef72
correct the proposal structure
stevenj Dec 12, 2022
52a2d3c
add example settings string for the project catalyst vote v0 format
stevenj Dec 13, 2022
fe0247d
Update CIP-0062/README.md
ehanoc Dec 19, 2022
9a98ee6
Replaced .getVotingKey with .getVotingCredentials
Ryun1 Jan 6, 2023
7336a91
Removed Bech32 encoding for public keys
Ryun1 Jan 8, 2023
f19d350
Merge pull request #7 from Ryun1/cip-governance-wallet-connector-cred…
ehanoc Jan 9, 2023
bbfce74
Update CIP-0062/README.md
ehanoc Jan 19, 2023
d5d50c7
Merge branch 'cip-governance-wallet-connector' into cip-governance-wa…
ehanoc Jan 19, 2023
591bb10
Merge pull request #6 from stevenj/cip-governance-wallet-connector
ehanoc Jan 19, 2023
d931f42
Update CIP-0062/README.md
ehanoc Jan 19, 2023
d8b140b
Refactor to match new CIP-01 requirements
Ryun1 Jan 20, 2023
9a07508
Fixed Copyright link
Ryun1 Jan 20, 2023
9bba6d6
Merge pull request #8 from Ryun1/cip-governance-wallet-connector-cip-…
ehanoc Jan 23, 2023
04edd0c
Addressed weekly meetings comments
Ryun1 Jan 27, 2023
3db6476
Merge pull request #9 from Ryun1/cip-62-update-01-27
ehanoc Feb 10, 2023
46d6c98
Rescope to Catalyst
Ryun1 Feb 17, 2023
a00b591
Changed title to match CIP-30's naming
Ryun1 Mar 7, 2023
0201fd5
Merge pull request #14 from Ryun1/cip-62-scope-catalyst
ehanoc Mar 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
217 changes: 217 additions & 0 deletions CIP-0062/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
---
CIP: 62
Title: Cardano dApp-Connector Governance extension
Authors: Bruno Martins <bruno.martins@iohk.io>
Status: Draft
Type: Standards
Created: 2021-06-11
License: CC-BY-4.0
---

# **Abstract**

This document describe the interface between webpage / web-based stack and cardano wallets. This specificies that API of the javascript object that need to be injected into the web applications in order to support all the Governance features.

These definitions extend [CIP-30 (Cardano dApp-Wallet Web Bridge)](https://cips.cardano.org/cips/cip30/) to provide specific support for vote delegation.

# **Motivation**
The goal for this CIP is to extend the dApp-Wallet web bridge to enable the construction of transactions containing metadata that conforms to
[CIP-36 (Catalyst/Voltaire Registration Transaction Metadata Format - Updated)](https://cips.cardano.org/cips/cip36/),
enabling new functionality including vote delegation to either private or public representatives (dReps),
splitting or combining of private votes,
the use of different voting keys or delegations
for different purposes (Catalyst etc).

# **Specification**

## `Types`

### **GovernanceKey**

```
type GovernanceKey = {
votingKey: string,
weight: number
}

```

`votingKey`: Ed25519 pubkey 32 bytes HEX string

`weight`: Used to calculate the actual voting power using the rules described
in
[CIP-36](https://cips.cardano.org/cips/cip36/).


### **Purpose**

```
type enum Purpose = {
CATALYST = 0,
OTHER = 1
}
ehanoc marked this conversation as resolved.
Show resolved Hide resolved

```

`Purpose`: Defines the purpose of the delegations. This is used to limit the scope of the delegations. For example, a purpose might be a subset of Catalyst proposals, a council election, or even some private purpose (agreed by convention).

## **Namespace**

### **cardano.{walletName}.governance.enable(): Promise\<API>**
The `cardano.{walletName}.governance.enable()` method is used to enable the governance API. It should request permission from the wallet to enable the API. If permission is granted, the rest of the API will be available. The wallet should maintain a specific whitelist of allowed clients for this API. This whitelist can be used to avoid asking for permission every time.

This api being an extension of [CIP-30 (Cardano dApp-Wallet Web Bridge)](https://cips.cardano.org/cips/cip30/), expects that `cardano.{walletName}.enable()` to be enabled and added to CIP-30 whitelist implicitly.

When both this API and **CIP-30** is being enabled, is up to the wallet to decide the number of prompts requesting permissions to be displayed to the user.
Copy link
Contributor

@refi93 refi93 Sep 14, 2022

Choose a reason for hiding this comment

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

This api being an extension of CIP-30 (Cardano dApp-Wallet Web Bridge), expects that cardano.{walletName}.enable() to be enabled and added to CIP-30 whitelist implicitly.

Doesn't this sentence imply that the dapp has to always enable first the CIP-30 API and only then request the governance one? On the other hand this sentence

When both this API and CIP-30 is being enabled, is up to the wallet to decide the number of prompts requesting permissions to be displayed to the user.

seems to contradict that, hinting that it may not always be the case that CIP-30 is being enabled before CIP-62. Is my understanding that CIP-30 always has to be enabled before CIP-62 correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's correct @refi93 . I've updated this section, could you have a re-read?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm checking https://github.com/cardano-foundation/CIPs/pull/296/files#diff-d3ac75d45e4e621f6ad95567378e0dc2b671f44d3c32425dda9ca08210e18876R265-R272 but I didn't notice a difference, am I checking perhaps the wrong commit/branch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doesn't this sentence imply that the dapp has to always enable first the CIP-30 API and only then request the governance one? On the other hand this sentence

Yes, it ties to explain that CIP-30 should be enabled as well, if not so already.

Maybe Is there a reason why it shouldn't?

Is my understanding that CIP-30 always has to be enabled before CIP-62 correct?

Yes, that was the idea.

Would it be more clear if i were to remove the section that states:

When both this API and CIP-30 is being enabled, is up to the wallet to decide the number of prompts requesting permissions to be displayed to the user.


# **`Jormungandr API`**
ehanoc marked this conversation as resolved.
Show resolved Hide resolved

## **api.submitVotes**(votes: Vote[], spendingCounter: number): Promise\<hash32>
ehanoc marked this conversation as resolved.
Show resolved Hide resolved
ehanoc marked this conversation as resolved.
Show resolved Hide resolved
ehanoc marked this conversation as resolved.
Show resolved Hide resolved

### `spendingCounter`:
The spending counter is used to prevent double voting. The current spending counter for the account should be provided and the implementation should increment it for each vote before submission and attach it to the vote according to [Jormungandr Voting] (https://input-output-hk.github.io/jormungandr/jcli/vote.html#voting). This needs to be in sequential order.

ehanoc marked this conversation as resolved.
Show resolved Hide resolved
### **`votes`**:

```
interface Vote {
proposal: Proposal,
choice: number,
expiration: BlockDate
}
```
#### `expiration`:
chain epoch \& slot for when the vote will expire. The type used is:

```
interface BlockDate {
epoch: number
slot: number
}
```

Ryun1 marked this conversation as resolved.
Show resolved Hide resolved
#### `choice`:
The choice **index** we want to vote for. An `UnkownChoiceError` should be thrown is the value is not within the `proposal` option set.

#### **`proposal`** :
proposal information. Include the range of options we can use to vote. This defines the allowed values in `choice`.

```
interface Proposal {
Copy link
Contributor

@refi93 refi93 Sep 14, 2022

Choose a reason for hiding this comment

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

will there be an API where the wallet could fetch the proposal metadata to show something more user friendly in the confirmation prompt to the user than a list of numbers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see; this would definitely be easier to implement on the client side.

About some sort of Map<string,string> // <planId, proposalTitle> ?

votePlanId: number
voteOptions: number[]
}
```

##### `votePlanId`:
the vote plan id. This is used to identify the vote plan. This should be the same as anchored on chain.

##### `voteOptions`:
The vote options. This is the set of options we can vote for.

### **Returns**

`hash32` - This is the hash of the transaction that will be submitted to the node.

#### **Errors**
`InvalidArgumentError` - Generic error for errors in the formatting of the arguments.

`UnknownChoiceError` - If the `choice` is not within the `proposal` option set.

`InvalidBlockDateError` - If the `validUntil` is not a valid block date.

`InvalidVotePlanError` - If the `votePlanId` is not a valid vote plan.

`InvalidVoteOptionError` - If the `index` is not a valid vote option.

# **`Delegation API`**

## **api.getVotingKeys**(): Promise<cbor<PublicKey\>[]>
Should return a list of all the voting keys for the current wallet.

ehanoc marked this conversation as resolved.
Show resolved Hide resolved
### **Returns**
An array with the cbor hex encoded public keys.

## **api.rotateVotingKey**(): Promise<cbor<PublicKey\>>
This call should explicitly rotate the current in-use voting key. Given the current `address_index` in the derivation path defined in [CIP-36](https://cips.cardano.org/cips/cip36/), it should be incremented by 1.
ehanoc marked this conversation as resolved.
Show resolved Hide resolved

The key should be derived from the following path.

```
m / 1694' / 1815' / account' / role' / address_index'
```
ehanoc marked this conversation as resolved.
Show resolved Hide resolved

`1694` (year Voltaire was born) Sets a dedicated `purpose` in the derivation path for the voting profile.

`address_index` - index of the key to use.

### **Returns**
cbor hex encoded representation of the public key


## **api.getCurrentVotingKey**(): Promise\<cbor<PublicKey\>>

Should return the current in-use voting public-key. The wallet should maintain a reference to the current `adress_index` counter and return the public key for that index.
ehanoc marked this conversation as resolved.
Show resolved Hide resolved

### **Returns**
cbor hex encoded representation of the public key.

## **api.submitDelegation(delegation: Delegation): Promise\<SignedDelegationMetadata>**

This endpoint should construct the cbor encoded delegation certificate according to the specs in [CIP-36 Example](https://github.com/Zeegomo/CIPs/blob/472181b9c69feeedae0b5b2db8b42d0cf4eb1a11/CIP-0036/README.md#example).

It should then sign the certificate with the staking key as described in the same example as above.

The implementation of this endpoint can make use of the already existing [CIP-30](https://cips.cardano.org/cips/cip30/) `api.signData` and `api.submitTx` to perform the broadcasting of the transaction containing the metadata.

Upon submission of the transaction containing the delegation cert as part of metadata, the wallet should store the delegation in its local storage and return an object that contains the delegation cert, the signature and the txhash of the transaction that the certificate was submitted with.

## **`Delegation`**

```
export interface Delegation {
voting_delegation: GovernanceKey[],
purpose: Purpose
}
```

Defines the structure to be crafted and signed for delegation of voting & their respectively voting power. Embeds the stake key and reward address from the wallet, and constructs a suitable nonce.

***`voting_delegation`***: List of keys and their voting weight to delegate voting power to.

This should be a call that implicitly cbor encodes the `delegation` object and uses the already existing [CIP-30](https://cips.cardano.org/cips/cip30/) `api.submitTx` to submit the transaction. The resulting transaction hash should be returned.

This should be trigger a request to the wallet to approve the transaction.

### **Returns**

```
interface SignedDelegationMetadata {
certificate: DelegatedCertificate,
signature: string, // signature on the CIP-36 delegation certificate
txHash: string // of the transaction that submitted the delegation
}
```

#### **DelegatedCertificate**
```
interface DelegatedCertificate {
delegations: GovernanceKey[] // key delegations,
stakingPub: string // staking public key
rewardAddress: string // reward address
nonce: number //nonce used in the transaction
purpose: Purpose
}
```

Errors: `APIError`, `TxSendError`

## **Delegation Cert process**
Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect a similar breakdown for the Voting process, it would make the motivation behind the available calls clearer to the reader

Copy link
Collaborator

Choose a reason for hiding this comment

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

Will do.


1. **`Get Voting Key`** - use the method **api.getVotingKey** to return a ed25519 32 bytes public key (x value of the point on the curve).

2. **`Collect Voting Keys`** - Collect the keys to delegate voting power to.

3. **`Craft delegation cert`** - Use **api.buildDelegation** to construct the object containing the key array set to delegate voting power to. Each value will express the `weight` of the voting powers given.

4. **`Submit delegation`** - Submit the metadata transaction to the chain using **api.submitDelegation** which implicitly sign and/or can use the already existing **api.submitTx**, available from [CIP-30](https://cips.cardano.org/cips/cip30/)
ehanoc marked this conversation as resolved.
Show resolved Hide resolved