Skip to content

Commit

Permalink
Add BIP 45 for "Structure for Deterministic P2SH Multisignature Wallets"
Browse files Browse the repository at this point in the history
  • Loading branch information
maraoz committed Oct 21, 2014
1 parent 1eb781c commit bd0da6f
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ Those proposing changes should consider that ultimately consent may rest with th
| Standard
| Draft
|-
| [[bip-0045.mediawiki|45]]
| Structure for Deterministic P2SH Multisignature Wallets
| Manuel Araoz
| Standard
| Draft
|-
| [[bip-0050.mediawiki|50]]
| March 2013 Chain Fork Post-Mortem
| Gavin Andresen
Expand Down
256 changes: 256 additions & 0 deletions bip-0045.mediawiki
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
<pre>
BIP: BIP-0045
Title: Structure for Deterministic P2SH Multisignature Wallets
Authors: Manuel Araoz <manu@bitpay.com>
Ryan X. Charles <ryan@bitpay.com>
Matias Alejo Garcia <matias@bitpay.com>
Status: Draft
Type: Standards Track
Created: 2014-04-25
</pre>

==Abstract==

This BIP defines a structure for hierarchical deterministic P2SH multi-party
multi-signature wallets (HDPM wallets from now on) based on the algorithm
described in BIP-0032 (BIP32 from now on) and purpose scheme described in
BIP-0043 (BIP43 from now on).
This BIP is a particular application of BIP43.

==Motivation==

The structure proposed in this document allows for standard ways to create,
use, import, and store HDPM wallets. It allows to handle multiple parties sharing
an m-of-n wallet, on the following assumptions:
* n parties share an m-of-n wallet.
* Each party generates their master private keys independently.
* Multisig P2SH is used for all addresses.
* BIP32 is used to derive public keys, then create a multisig script, and the corresponding P2SH address for that script.
* Address generation should not require communication between parties. (Thus, all parties must be able to generate all public keys)
* Transaction creation and signing requires communication between parties.
This BIP will allow interoperability between various HDPM wallet implementations.

==Specification==

We define the following levels in BIP32 path:

<code>
m / purpose' / cosigner_index / change / address_index
</code>

Apostrophe in the path indicates that BIP32 hardened derivation is used.

Each level has special meaning described in the chapters below.

===Purpose===

Purpose is a constant set to 45, following the BIP43 recommendation.
It indicates that the subtree of this node is used according to this specification.

<code>
m / purpose' / *
</code>

Hardened derivation is used at this level.


===Cosigner Index===

The index of the party creating a P2SH multisig address. The indices can
be determined independently by lexicographically sorting the purpose public
keys of each cosigner. Each cosigner creates addresses on it's own branch,
even though they have independent extended master public key, as explained
in the "Address generation" section.

Note that the master public key is not shared amongst the cosigners. Only the
hardened purpose extended public key is shared, and this is what is used to
derive child extended public keys.

Software should only use indices corresponding to each of the N cosigners
sequentially. For example, for a 2-of-3 HDPM wallet, having the following
purpose public keys:
<pre>
03a473275a750a20b7b71ebeadfec83130c014da4b53f1c4743fcf342af6589a38
039863fb5f07b667d9b1ca68773c6e6cdbcac0088ffba9af46f6f6acd153d44463
03f76588e06c0d688617ef365d1e58a7f1aa84daa3801380b1e7f12acc9a69cd13
</pre>

it should use `m / purpose ' / 0 / *` for
`039863fb5f07b667d9b1ca68773c6e6cdbcac0088ffba9af46f6f6acd153d44463`,
`m / purpose ' / 1 / *` for
`03a473275a750a20b7b71ebeadfec83130c014da4b53f1c4743fcf342af6589a38`,
and `m / purpose ' / 2 / *` for
`03f76588e06c0d688617ef365d1e58a7f1aa84daa3801380b1e7f12acc9a69cd13`,
as dictated by their lexicographical order.


Software needs to discover all used indexes when importing the seed from
an external source. Such algorithm is described in "Address discovery" chapter.

Non-hardened derivation is used at this level.

===Change===

Constant 0 is used for external chain and constant 1 for internal chain (also
known as change addresses). External chain is used for addresses that are meant
to be visible outside of the wallet (e.g. for receiving payments). Internal
chain is used for addresses which are not meant to be visible outside of the
wallet and is used for return transaction change.

For example, if cosigner 2 wants to generate a change address, he would use
`m / purpose ' / 2 / 1 / *`, and `m / purpose ' / 2 / 0 / *` for a receive
address.

Non-hardened derivation is used at this level.

===Address Index===

Addresses are numbered from index 0 in sequentially increasing manner.
This number is used as child index in BIP32 derivation.

Non-hardened derivation is used at this level.

===HDPM Wallet High-level Description===
Each party generates their own extended master keypair and shares the
extended purpose' public key with the others, which is stored encrypted.
Each party can generate any of the other's derived public keys, but only
his own private keys.

===Address Generation Procedure===
When generating an address, each party can independently generate the N needed
public keys. They do this by deriving the public key in each of the different
trees, but using the same path. They can then generate the multisig script (by
lexicographically sorting the public keys) and the corresponding p2sh address.
In this way, each path corresponds to an address, but the public keys for that
address come from different trees.

====Receive address case====
Each cosigner generates addresses only on his own branch. One of the n
cosigners wants to receive a payment, and the others are offline. He
knows the last used index in his own branch, because only he generates
addresses there. Thus, he can generate the public keys for all of the
others using the next index, and calculate the needed script for the address.

Example: Cosigner #2 wants to receive a payment to the shared wallet. His last
used index on his own branch is 4. Then, the path for the next receive
address is `m/$purpose/2/1/5`. He uses this same path in all of the cosigners

This comment has been minimized.

Copy link
@dskloet

dskloet Apr 11, 2015

Isn't 2/1/5 actually a change address?

trees to generate a public key for each one, and from that he gets the new
p2sh address.
====Change address case====
Again, each cosigner generates addresses only on his own branch. One of the
n cosigners wants to create an outgoing payment, for which he'll need a change
address. He generates a new address using the same procedure as above, but
using a separate index to track the used change addresses.

Example: Cosigner #5 wants to send a payment from the shared wallet, for which
he'll need a change address. His last used change index on his own branch is
11. Then, the path for the next change address is `m/$purpose/5/0/12`. He uses

This comment has been minimized.

Copy link
@dskloet

dskloet Apr 11, 2015

Isn't 5/0/12 actually a receive address?

This comment has been minimized.

Copy link
@maraoz

maraoz Apr 13, 2015

Author Contributor

Yes. We changed the order of receive/change and didn't change the examples. I'll fix it

This comment has been minimized.

Copy link
@dskloet

dskloet Apr 20, 2015

Did you forget?

This comment has been minimized.

Copy link
@maraoz

maraoz Apr 20, 2015

Author Contributor

Nope, here is the PR: #149 please review :)

this same path in all of the cosigners trees to generate a public key for each
one, and from that he gets the new p2sh address.


===Transaction creation and signing===
When creating a transaction, first one of the parties creates a Transaction
Proposal. This is a transaction that spends some output stored in any of the
p2sh multisig addresses (corresponding to any of the copayers' branches).
This proposal is sent to the other parties, who decide if they want to sign.
If they approve the proposal, they can generate their needed private key for
that specific address (using the same path that generated the public key in
that address, but deriving the private key instead), and sign it. Once the
proposal reaches m signatures, any cosigner can broadcast it to the network,
becoming final. The specifics of how this proposal is structured, and the
protocol to accept or reject it, belong to another BIP, in my opinion.

===Address discovery===

This comment has been minimized.

Copy link
@dskloet

dskloet Apr 11, 2015

The text below looks like it was copied and not properly adjusted. It talks about accounts but the text above doesn't talk about accounts anywhere. Also, since each cosigner can create addresses independently, each chain should be explored regardless of whether any of the other chains has a transaction history. So this part is meaningless:

+This algorithm is correct, because software should disallow creation of new
+accounts if previous one has no transaction history as described in chapter
+"Account" above.


When the master seed is imported from an external source the software should
start to discover the accounts in the following manner:

# derive the first account's node (index = 0)
# derive the external chain node of this account
# scan addresses of the external chain; respect the gap limit described below
# if no transactions are found on the external chain stop discovery
# if there are some transactions, increase the account index and go to step 1
This algorithm is correct, because software should disallow creation of new
accounts if previous one has no transaction history as described in chapter
"Account" above.

Please note that the algorithm works with the transaction history, not account
balances, so you can have account with total 0 coins and the algorithm will
still continue with discovery.

===Address gap limit===

Address gap limit is currently set to 20. If the software hits 20 unused
addresses in a row, it expects there are no used addresses beyond this point
and stops searching the address chain.

Wallet software should warn when user is trying to exceed the gap limit on
an external chain by generating a new address.


===Rationale===

This stucture provides a general way of doing HDPM wallets between m-of-n
parties. Here are some explanations about the design decisions made.

The reason for using separate branches for each cosigner is we don't want
two of them generating the same address and receiving simultaneous payments
to it. The ideal case is that each address receives at most one payment,
requested by the corresponding cosigner.

==Examples==

{|
!cosigner_index
!change
!address_index
!path
|-
|first
|receive
|first
| m / 45' / 0 / 0 / 0
|-
|first
|receive
|second
| m / 45' / 0 / 0 / 1
|-
|first
|receive
|fifth
| m / 45' / 0 / 0 / 4
|-
|first
|change
|first
| m / 45' / 0 / 1 / 0
|-
|first
|change
|second
| m / 45' / 0 / 1 / 1
|-
|second
|receive
|first
| m / 45' / 1 / 0 / 0
|-
|third
|change
|tenth
| m / 45' / 2 / 1 / 9
|}

==Compatible walets==

* [[https://copay.io|Copay wallet]] ([[https://github.com/bitpay/copay|source]])
==Reference==

* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
* [[bip-0043.mediawiki|BIP43 - Purpose Field for Deterministic Wallets]]
* [[https://www.mail-archive.com/bitcoin-development@lists.sourceforge.net/msg05156.html|Original mailing list discussion]]

0 comments on commit bd0da6f

Please sign in to comment.