diff --git a/README.md b/README.md index b331248b..42009d13 100644 --- a/README.md +++ b/README.md @@ -23,4 +23,5 @@ Please check out existing EIPs, such as [EIP-1](eip-0001.md), to understand the | [EIP-0031](eip-0031.md) | Babel Fees | | [EIP-0034](eip-0034.md) | NFT Collection Standard | | [EIP-0039](eip-0039.md) | Monotonic box creation height rule | -| [EIP-0043](eip-0043.md) | Reduced Transaction | \ No newline at end of file +| [EIP-0042](eip-0042.md) | Multi-Signature Wallet | +| [EIP-0043](eip-0043.md) | Reduced Transaction | diff --git a/eip-0042.md b/eip-0042.md new file mode 100644 index 00000000..e7be46b4 --- /dev/null +++ b/eip-0042.md @@ -0,0 +1,176 @@ +# EIP-41: Multi-Signature Wallet + +- Author: lazypinkpatrick, vorujack, mhs_sam +- Status: Completed +- Created: 21-Jan-2023 +- License: MIT +- Forking: not needed + +This EIP defines a standard for multi-signature wallets based on EIP-11, which defines the multi-signature signing process. + +## Introduction + +On top of EIP-11, this EIP implements the following additional operations: + +* Wallet creation and address derivation. +* Transaction signing based on EIP-11. + +## Wallet Creation and Address Derivation + +These parameters define an `K-out-of-N` multi-signature wallet: + +* `N`: number of public keys. +* `K`: minimum signature required. + +Each signer stores the set of extended public keys of all signers and a local copy of their secret. + +An address is derived for each signer using their extended public key over a specified derivation path. The list of derived addresses for all signers is then used to compile a multi-sig contract that looks like this: + +``` +atLeast( + K, + Coll( + PK(Address1), + PK(Address2), + . + . + . + PK(AddressM) + ) +) +``` + +Please note, this contract results in different addresses when the order of signers differs. + +We must guarantee that all signers will have a unique and reproducible multi-signature wallet address. To do so, we use the same derivation path and sort the byte array of public keys in ascending order. + +Then we will manually create the ErgoTree; since using the compiler could cause the resulting address to vary. + +The address derivation algorithm is as follows: + +Sort the list of signers' public keys before being used in the contract. +Create the required ergoTree array as follows: + +- The first byte is header. `00` +- A byte with value `98` indicates **"atLeast"** +- Encoded `K` as: + - A byte with value `04` denotes the integer type, + - followed by the value of `K` encoded as VLQ. +- A constant byte with value `83` indicates **"ConcreteCollection"**, +- The VLQ-encoded value of `N`, +- Constant byte with value `08` indicates element types in collection as **"sigmaProp"** +- For each public key 35 bytes as: + - One byte with value `08` indicates **"sigmaProp"** + - One byte with value `CD` indicates **"proveDlog"** + - followed by 33 bytes representing the public key. + +Therefore, for each derivation path, all wallets are able to generate a unique and similar byte array as an ErgoTree. + +![Ergo Tree Bytes](./eip-0042/bytes.png) + +## Transaction Signing + +An unsigned transaction is generated on one wallet. This transaction may have been generated through ErgoPay or the dApp connector, or it could be an outgoing transaction to another address through the wallet itself. + +After an unsigned transaction is generated, the wallet + +Generates a commitment. +Stores its private part locally. +Shares a commitment as below + +``` +{ + tx:, + boxes:[encoded boxes as base64], + commitment: commitments encoded +} +``` + +The input `boxes:` are only used to display transactions on wallets. + +The general commitment format is as follows. However, this general-purpose commitment can be used for any contract. +``` +{ + "hint": "cmtReal", + "position": "0-0", + "type": "dlog", + "pubkey": { + "op": "205", + "h": "03a73c66970f14fc6450c6ab1a167cb4ba3baa64b20f731e22ec6840c70d27ef1c", + } + "a": "0253db866791af521ba4ab009509b6db89d272d9461636ee65eaa3e316884b21a4" +} +``` + +In a multi-signature wallet, a simplified version of commitment is used. + +``` +commitments: [ + [, ...] + [, ...] +] +``` + +In the multi-signature wallet, a commitment is represented as a list of base64 strings to reduce the commitment size. Also, an empty string is used wherever a commitment is unavailable. + +[//]: # (and we can transform these commitments to standard format:) +This reduced format can be transformed into the standard format: + +``` +{ + "hint": "cmtReal", + "position": "0-", + "type": "dlog", + "pubkey": { + "op": "205", + "h": "" + }, + "a": "" +} +``` + +[//]: # (Because wallets want to pass this code via QRCode, each wallet can split it into chunks) + +To transfer these commitments using QRCode, we can split the data into several chunks: + +``` +{ + MSR: "{\"tx\": ...}", + n: + p: +} +``` + +This data is transferred between multi-signature wallets until one wallet has at least `K` commitments (including its own). + +This wallet creates a partially signed transaction with this encoding: + +``` +{ + partialTx: "", + commitments: + signed: [], + simulated: [], +} +``` + +It can also be transferred using QRCode in several chunks: + +``` +{ + MTX: "{\"partialTx\": ... }", + n: + p: +} +``` + +The first signer creates a list of simulated signers, and other signers use this list. + +Each signer: +Signs the partially signed transaction (if they still need to). +Adds their public key to the list. +Shares the data with the next signer. + +The transaction will be broadcasted whenever the signer determines that the transaction has enough signatures. + + diff --git a/eip-0042/bytes.png b/eip-0042/bytes.png new file mode 100644 index 00000000..a658531a Binary files /dev/null and b/eip-0042/bytes.png differ