-
Notifications
You must be signed in to change notification settings - Fork 334
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-1854: Multi-signatures HD Wallets #69
Conversation
7117525
to
e546261
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Good to clarify the way the structure should be extended in 1852.
ce2299e
to
18406b6
Compare
@crptmppt I just rebased to fix merge conflicts in the README 👍 |
…roles of 1852' wallets
0b02d76
to
c3529f9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
merging as per Editors meeting 21
Abstract
This document describes how to realize multi-parties transactions in Cardano. It is defined as an alternative to CIP-1852 for Cardano HD wallets. This specification does not cover the transport and sharing of partially signed transactions which is / will be covered in another document.
Glossary
Motivation
Overview
Multisig wallets are Cardano wallets capable of providing and tracking keys involved in multi-parties transactions. Such transactions are used to move funds from addresses where (typically) more than one user must sign transactions for its funds to be spent. A simple analogue is a joint bank account where two account holders must approve withdrawals from the account. Cardano has native support for multi-signature schemes: funds at a multi-signature script address are owned by a monetary script, which specifies one or more combinations of cryptographic signatures which must be present to unlock funds at the address (see the Formal Ledger Spec, Figure 4: Multi-signature via Native Scripts). In a similar fashion, Cardano multisig scripts can also be used to capture stake rights on a particular address, shared between different parties.
In the Shelley era, Cardano offers six (partially overlapping) primitives for constructing monetary scripts which are summarized as the following grammar:
Scripts are thereby recursive structures which can contain scripts themselves. For example, a joint account between two parties which specifies that any of the two members can spend from it would be defined in pseudo-code as:
In order to spend from such script, one would have to provide a witness showing ownership of the key associated with either of
key-hash#1
orkey-hash#2
(or possibly, both).Creation of a Multisig Script/Address
The creation of a multisig address will not be covered in this document. Such addresses are described in [Shelley design specification - section 3.2 - Addresses and Credentials][delegation_design.pdf] and are obtained by serializing and hashing a multisig script. This functionality is assumed to be available through existing tooling or piece of software in a variety of ways.
Spending From a Multisig Address
In order to spend from a multisig address, one must provide a special witness in the spending transaction called a "multisig witness". Such witness must be the exact script used as an input for creating the hash part of the multisig address. Then, any additional required verification key signatures specified by the script must be provided as separate verification key witnesses (i.e. signatures of the hashed transaction body for each signing key).
This means that a wallet software has access to the full script to validate and also identify verification key hashes present in transactions, but only does so when funds are being spent from a multisig address! From the Allegra era and beyond, it is also possible to include script pre-image in transaction auxiliary data. Softwares may use this to communicate scripts ahead of time.
Specification
HD Derivation
We consider the following HD derivation paths similarly to CIP-1852:
To associate multi-signature keys to a wallet, we reserve however
purpose=1854'
to distinguish multisig wallets from standard wallets. The coin type remainscoin_type=1815'
to identify Ada as registered in SLIP-0044. The account index (account_ix
) may vary across the whole hardened domain.role=0
is used to identify payment keys, whereasrole=2
identifies stake keys.role=1
is left unused for multisig wallets. Finally, the lastindex
mary across the whole soft domain, but according to the following rules:We can summarize the various paths and their respective domain in the following table:
purpose
coin_type
account_ix
role
index
1854'
1815'
[2^31 .. 2^32-1]
0
or2
[0 .. 2^31-1]
Rationale
Multisig keys are scoped to accounts, which allows wallet's owners to separate their activity easily.
We use a different purpose for mainly two reasons:
It prevents mixing up standard wallets with shared wallets, which would be undesirable and become rapidly a nightmare for software to maintain. In particular, it also makes it possible to share an intermediary account key with co-signers without disclosing any information about non-shared keys in our wallet.
It makes it easier to extend any of the 1852' or 1854' in a similar manner. The addition of a new role can be done in both scheme very consistently.
Using a different purpose also fits well the use-case on hardware wallets who can still rely on a single root seed to manage many types of wallets.
One or many keys can be created from a parent public key via soft-derivation. This allows participant to easily share their multisig keys to participate in a multisig script without having to fetch for their hardware device. The device is still required for signing.
Examples
m/1854’/1815’/0’/0/0
m/1854’/1815’/0’/2/14
m/1854’/1815’/0’/2/42
m/1854’/1815’/0’/0/1337
User-facing encoding
Multi-signatures payment verification and signing keys (
role=0
) with chain code should be presented bech32-encoded usingaddr_shared_xvk
andaddr_shared_xsk
prefixes respectively, as specified in CIP-5. When represented without chain-code,addr_shared_vk
andaddr_shared_sk
should be used instead.Similarly we use
stake_shared_xvk
,stake_shared_xsk
,stake_shared_vk
andstake_shared_sk
for multi-signatures stake verification and signing keys (role=2
).Examples
Multisig Wallets
Templates
To define a multisig wallet, participants must provide:
A script template is a script where key hashes are replaced by a cosigner tag which captures the relation between the cosigners.
There must be a strict one-to-one mapping between the tags used in the template and the cosigner account keys provided. When a new address is needed, the software must instantiate the script by using keys derived from the relevant account. To instantiate a script from a template, a wallet software must abide by the following rules:
(1) and (2) implies that a given instance of a script is associated to one and only one derivation index.
For example, considering the joint-account example from above, an example of payment template can simply be:
and an instantiation of that template for e.g. an index equals to 1 could be:
Keys used in the instantiated template all come from the same derivation index for all cosigners. This allows all wallets to easily find back what indexes other cosigners used to derive a particular key (the same as they use for a particular address).
Sending Transactions
In case the wallet needs a change address internally, it must use the smallest unused indexes known, in ascending order. An index is considered unused if there's no transaction in the ledger with a script using its corresponding key hash. When constructing a transaction, a wallet should use UTxOs associated with script addresses only (hybrid transactions using non-shared UTxOs are forbidden).
Once constructed, a transaction must be signed with all required private keys from the initiator. The initiator must also include all instances of scripts necessary (typically one per input) and then either broadcast the transaction to its cosigners or submits it to the network if valid. The mean by which the transaction is broadcast is out of the scope of this specification.
Upon receiving a partially signed transaction, wallets must for each input:
When valid, the wallet should prompt the user for signing. The transaction can be submitted by any of the cosigners who deems it valid (it could be that only a subset of the cosigners is required to sign). Several cosigners may submit the transaction concurrently without issue, the ledger will ensure that only one transaction eventually get through.
Foreign Script Discovery
Wallets should warn users when discovering known keys in scripts which non-matching templates. Such addresses should not be included as part of the wallet's UTxO and should be treated as anomalies in the wallet. As a matter of facts, everything described in this document is a mere convention between wallets. There's however nothing at the protocol level that enforces that this specification is followed. It is therefore very much possible for advanced users to use their multisig keys in scripts that are different from the template. So long as indexes used are discoverable by the wallet, then such scripts are also discoverable.
However, because such scripts / addresses would not have been created by the wallet, they are considered not being part of the it altogether and would not count towards the wallet's balance. Software should however as much as possible alert users about the existence of such anomalies.
Example
For example, if Alice and Bob wants to share a wallet by requiring a signature from each other on every payment, they can define the following payment script template:
After exchanging their corresponding public keys, both wallets should be initialized and present to Alice and Bob exactly
20
identical addresses, where each address is associated with exactly one derivation index. The first address will use one key from Alice's wallet at pathm/1854’/1815’/0’/0/0
and a key from Bob's at exactly the same path. The next address will use keys at pathm/1854’/1815’/0’/0/1
and so forth.When Alice initiates a transaction from this wallet, she'll construct the transaction body, sign it with her corresponding private key, include an instance of the script as witness and broadcast the transaction to Bob via Telegram. Upon reception, Bob is able to verify that the transaction was indeed signed by Alice using her private key at index #0 (Bob has indeed Alice's parent public key in its possession and is therefore able to derive a child key at index #0 to verify the signature on the transaction). Bob proceeds with the payment by signing the transaction in return and submitting it.
Backwards Compatibility
N/A (no preceding implementation or design).
Reference Implementation
None yet.
Related Work
Copyright
CC-BY-4.0