Skip to content

Commit

Permalink
docs(CIP): Add RBAC transaction signing with CIP-30 CIP
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenj committed May 8, 2024
1 parent b14311d commit 73c03eb
Show file tree
Hide file tree
Showing 3 changed files with 1,212 additions and 0 deletions.
139 changes: 139 additions & 0 deletions CIP-XXXX/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
CIP: /?
Title: Preparing and Signing x509 Metadata
Category: MetaData
Status: Proposed
Authors:
- Steven Johnson<steven.johnson@iohk.io>
Implementors: []
Discussions:
- https://github.com/cardano-foundation/cips/pulls/?
Created: 2023-10-24
License: CC-BY-4.0
---

<!-- markdownlint-disable MD025-->
# Role Based Access Control Registration

## Abstract

This document defines how a dApp will use the wallet connect interfaces of CIP-30 to produce and sign
x509 registration transactions.

## Motivation: why is this CIP necessary?

The x509 certificate metadata CIPs are complex, and it is required to clearly document how they
can be produced using standard tooling.

The primary motivation is that the registration can be produced with existing interfaces.

Wallets MAY OPTIONALLY detect this registration format and display it in a more meaningful way to users.
But that is not required.

The aim is to have broad interoperability with ALL wallets that already implement CIP-30.

## Specification

### Components of an individual transaction

![Cardano Transaction Anatomy](./images/cardano-transaction.svg)

### Creation and Signing procedure

![Creation/Signing procedure](../x509-envelope-metadata/images/metadata-envelope-process.svg)

### Wallet interaction

CIP 30 defines two main functions.

1. signData
2. signTransaction

We deliberately do NOT use signData.
The reason is signData has limitations, primarily it can ONLY sign data with a single key.

it is also incapable of creating data that can not be replayed across transactions, which is a requirement.

Accordingly, the entire transaction is produced using `signTransaction`.

Following the procedure described above, the prepared transaction and complete metadata
(which has been pre-signed with the role 0 keys of the user) are sent to the wallet to be signed.

The Transaction MUST include where appropriate extra keys in `required signers` in the transaction to properly
link the off-chain role keys with on-chain keys.

The wallet DOES NOT need to know that the metadata has this requirement, it simply sees the keys it needs to witness
the transaction with, and prompts the user to sign.

#### Enhanced UX

The Role registration metadata is general in form.

A Wallet MAY elect to detect that it is signing a role registration and
present the data in a form which is easier for the user to reason through.

It may also be aware of key supported dApps and provide even further information.
It can also perform both universal and dApp specific validity checks against the registration to ensure
it is properly structured by the dApp.

However, the Wallet should simply WARN the user if it detects a problem, and not prevent the user from
signing the transaction.

Once the wallet has signed the transaction, the dApp will have a fully signed role registration transaction and metadata.
It will be impossible for the dApp or anyone else to separate the metadata from the transaction and retain its validity.
It is impossible to replay the metadata on a new transaction and it retain validity.

With the complete transaction properly signed, it can then be posted on-chain.

### Posting the transaction

Once the transaction has been properly constructed and signed, anyone with a copy of it can post it on-chain.

it is recommended that dApps post the transaction to their own backend logic, which handles posting the data on-chain
vs posting the data on-chain through the wallet.

The reason for this, is this affords the dApp backend the opportunity to
validate the registration data in its entirety before posting it on-chain.

It is preferable to inform a user their registration is invalid or has problems
BEFORE they spend the ADA required to post the transaction,
and the only authoritive way this can be achieved is through the dApp.

having validated the registration would be valid if posted on-chain, it is then posted by the dapp on-chain.

Once the dApp sees the registration appear in the ledger,
it is now confirmed that not only was the registration valid, but that the transaction itself was valid,
properly spent valid UTXOs, etc.

The dApp may cache registration data it received from users,
but it should never act on it until it has been seen validly posted on-chain.

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

This CIP defines wallet interactions and how CIP-30 is used to create and
post transactions that conform to the x509 metadata specification.

## Path to Active

To-do.

### Acceptance Criteria

To-do.

### Implementation Plan

To-do.

## References

To-do.

## Copyright

This CIP is licensed under [CC-BY-4.0]

Code samples and reference material are licensed under [Apache 2.0]

[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode
[Apache 2.0]: https://www.apache.org/licenses/LICENSE-2.0.html
150 changes: 150 additions & 0 deletions CIP-XXXX/images/cardano-transaction.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
vars: {
d2-config: {
layout-engine: elk

# Terminal theme code
theme-id: 300
}
}

direction: right
grid-columns: 1

title: |md
# Cardano Transactions - Babbage ERA
| {
shape: text
# near: top-left
style: {
font-size: 30
}
}

processing: "Block to Individual Transaction Processing" {
direction: right

style: {
border-radius: 20
}

cardano block transactions: "Cardano Block (Babbage ERA)" {
shape: sql_table
link: "https://github.com/IntersectMBO/cardano-ledger/blob/6d860294304749a767d99db92fab42f7c18d9af4/eras/babbage/impl/cddl-files/babbage.cddl#L3-L6"
header: "[ header_body, body_signature ]"
transaction bodies: "[ * transaction_body ]"
transaction witness sets: "[ *transaction_witness_set ]"
invalid transactions: "[* transaction_index ]"
auxiliary data set: "{ *transaction_index => auxiliary_data }"
}

individual_transaction: "Cardano Transaction" {
shape: sql_table
link: "https://github.com/IntersectMBO/cardano-ledger/blob/6d860294304749a767d99db92fab42f7c18d9af4/eras/babbage/impl/cddl-files/babbage.cddl#L13-L18"
body: "transaction body"
witnesses: "transaction witness set"
valid: "bool"
auxiliary_data: "Option<auxiliary_data>"
}

collator: "collation logic: for i in 0..len(transaction_bodies)" {
shape: sql_table
style: {
stroke: PapayaWhip
font-color: cyan
}
1: "transaction_bodies[i]" {
shape: text
style: {
font: mono
}
}
2: "transaction_witness_sets[i]" {
shape: text
style: {
font: mono
}
}
3: "i not in invalid_transactions" {
shape: text
style: {
font: mono
}
}
4: "auxiliary_data_set[i] else None" {
shape: text
style: {
font: mono
}
}
}

cardano block transactions.transaction bodies -> collator.1
cardano block transactions.transaction witness sets -> collator.2
cardano block transactions.auxiliary data set -> collator.4
cardano block transactions.invalid transactions -> collator.3

collator.1 -> individual_transaction.body
collator.2 -> individual_transaction.witnesses
collator.3 -> individual_transaction.valid
collator.4 -> individual_transaction.auxiliary_data
}

transaction_data: "Transaction Data Details" {
shape: page

transaction_body: "transaction body" {
shape: sql_table
link: "https://github.com/IntersectMBO/cardano-ledger/blob/6d860294304749a767d99db92fab42f7c18d9af4/eras/babbage/impl/cddl-files/babbage.cddl#L53-L71"
"0 = transaction inputs": "[ * [transaction hash, index] ]"
"1 = transaction outputs": "[ * transaction_output ]"
"2 = transaction fee": "coin (lovelace uint64)"
"? 3 = Time to live \[TTL\]": "uint64"
"? 4 = certificates": "[* certificate]"
"? 5 = reward withdrawals": "{ * reward_account => coin (lovelace uint64) }"
"? 6 = protocol parameter update": "[ proposed_protocol_parameter_updates, epoch ]"
"? 7 = auxiliary_data_hash": "32 byte hash"
"? 8 = validity interval start": "uint64"
"? 9 = mint": "{ * policy_id => { * asset_name => a } }"
"? 11 = script_data_hash": "32 byte hash"
"? 13 = collateral inputs": "[ * [transaction hash, index] ]"
"? 14 = required_signers": "[ * address key hash (blake2b-224) of signing public key ]"
"? 15 = network_id": "0 or 1"
"? 16 = collateral return": transaction_output (collateral return)
"? 17 = total collateral": "coin (lovelace uint64)"
"? 18 = reference inputs": set<transaction_input>
}

transaction_witness_set: "transaction witness set" {
shape: sql_table
link: "https://github.com/IntersectMBO/cardano-ledger/blob/6d860294304749a767d99db92fab42f7c18d9af4/eras/babbage/impl/cddl-files/babbage.cddl#L295C1-L303"
"? 0": "[* vkeywitness ]"
"? 1": "[* native_script]"
"? 2": "[* bootstrap_witness]"
"? 3": "[* plutus_v1_script]"
"? 4": "[* plutus_data]"
"? 5": "[* redeemer]"
"? 6": "[* plutus_v2_script]"
}

vkeywitness: {
shape: sql_table
link: "https://github.com/IntersectMBO/cardano-ledger/blob/6d860294304749a767d99db92fab42f7c18d9af4/eras/babbage/impl/cddl-files/babbage.cddl#L370"
"vkey": "ED25519-Bip32 Public Key [32 Bytes]"
"signature": "ED25519-Bip32 Signature of Transaction [64 bytes]"
}

transaction_witness_set."? 0" -> vkeywitness

auxiliary_data: "auxiliary data" {
shape: sql_table
link: "https://github.com/IntersectMBO/cardano-ledger/blob/6d860294304749a767d99db92fab42f7c18d9af4/eras/babbage/impl/cddl-files/babbage.cddl#L359C1-L368"
"{ * uint => transaction_metadatum }": Optional
"[ * native_script ]": Optional
"[ * plutus_v1_script ]": Optional
"[ * plutus_v2_script ]": Optional
}
}

processing.individual_transaction.body -> transaction_data.transaction_body: "body"
processing.individual_transaction.witnesses -> transaction_data.transaction_witness_set: "witnesses"
processing.individual_transaction.auxiliary_data -> transaction_data.auxiliary_data: "auxiliary_data (optional)"

0 comments on commit 73c03eb

Please sign in to comment.