To provide a custody arrangement in which an owner of bitcoin (Principal) is able to secure bitcoin by working with an Agent. Unlike existing collaborative custody models up to this point, where bitcoin keys WITHIN a multisig threshold are shared between Principals and agents, a joint custody model by default requires a threshold of keys by both the Agent & Principal for movement of funds.
This introduces a concept of "Negative Control" where, by default, funds are not able to be moved unless both the Principal and Agent sign the transaction.
In the event the Principal loses access to all of their keys, a secondary agent is available to work with the Primary Agent such that funds can be recovered after a set period of time.
In the unlikely event the Primary Agent has lost 2 of their 3 keys, a timelock enabled threshold allows only 1 of 3 keys from the Primary Agent to be signed with the secondary agent.
Finally, in the event the Principal no longer wishes to work with the agent, say after a contract expires, the custody defers to a set of recovery keys, which can be held either by the Principal, or their own delegated managers of the recovery keys. As a result, when enough time has passed, the Principal is able to move bitcoin unilaterally without having the Agent sign key material.
There are three timelocks used for this MinT:
-
smallest_epoch_timestamp
- The smallest epoch timestamp timelock enables a "Asset Recovery" period such that only one of the Principal keys is required to sign. -
between_epoch_timestamp
- The epoch timestamp value in between the smallest and largest epoch timestamp enables a "Emergency Recovery Path". In the event the Principal has lost all of their keys, the Primary Agent and Secondary Agent can work together to recover the bitcoin in the Joint Custody vault. -
largest_epoch_timestamp
- The largest epoch timestamp, signifying the expiration of the contract, where the Principal is able to unilaterally withdraw their bitcoin from the joint custody vault.
In total, there are 10 keys in use for the 3 Key Joint Custody Vault, they are as follows:
Key Names | Description | Key Abbreviations | Key Symbol |
---|---|---|---|
Principal Keys 1,2,3 | These keys belong to the owner of the bitcoin. They are used as the default keys the Principal uses to transact bitcoin for the length of the relationship with the agent in the Joint Custody vault. |
|
|
Primary Agent Keys 1,2,3 | These keys belong to the agent, who the Principal has engaged with to fascilitate the securing of bitcoin for a determined set of time. |
|
|
Secondary Agent Key | This key is held by a 3rd party unassoicated with the other keys, in the event the Principal has lost a majority of their keys, can sign transactions with the Primary Agent to move funds after a designated "Recovery Period" has started. | ||
Recovery Keys 1,2,3 | These keys in practice belong to the Principal, they may even be keys related to the Principal Keys with a different derivation path, but can also be delegated key holders. After the initial Joint Custody vault agreement has ended, the recovery keys can unilaterally be used to withdraw money from the vault. |
|
Below are reference diagrams on how the 3 Key Joint Custody operates across time:
Layer is used as an abstraction to segement the different eligible spending conditions, going in an ascending order of timelock values. At the start, only "Layer 1" is accessible for spending funds, over time, other spending conditions become available, but this does not restrict the ability to spend from a proceeding layer.
Layer | Layer Name | Key Set 1 | Condition Between Sets | Key Set 2 | Timelock Condition | Timelock |
---|---|---|---|---|---|---|
1 | Default Spending Path |
|
AND |
|
N/A | None |
2 | Asset Recovery Path |
|
AND |
|
AND | After (smallest_epoch_timestamp ) |
3 | Emergency Recovery Path |
|
AND | N/A | After (between_epoch_timestamp ) |
|
4 | Sovereign Recovery Path |
|
None | None | AND | After (largest_epoch_timestamp ) |
Default Spending Path | 2 of 3 PKs | 2 of 3 PAKs | ||||
---|---|---|---|---|---|---|
PK1 | PK2 | PK3 | PAK1 | PAK2 | PAK3 | |
2 of 3 PKs AND 2 of 3 PAKs |
Spending Scenario | ||||||
---|---|---|---|---|---|---|
Scenario 1 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 2 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 3 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 4 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 5 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 6 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 7 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 8 | ✅ | ✅ | ✅ | ✅ | ||
Scenario 9 | ✅ | ✅ | ✅ | ✅ |
Spending Scenario | PK_1 | PK_2 | PK_3 | PAK_1 | PAK_2 | PAK_3 | BIP-113 greater than smallest_epoch_timestamp |
---|---|---|---|---|---|---|---|
Scenario 10 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 11 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 12 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 13 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 14 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 15 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 16 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 17 | ✅ | ✅ | ✅ | ✅ | |||
Scenario 18 | ✅ | ✅ | ✅ | ✅ |
Emergency Recovery Path | 2 of 3 PAKs | 1 SAK | BIP-113 time greater than `between_epoch_timestamp` |
||
---|---|---|---|---|---|
PAK1 | PAK2 | PAK3 | SAK | ||
2 of 3 PAKs AND SAK AND after BIP-113 time is greater than `between_epoch_timestamp` |
Spending Scenario | PAK_1 | PAK_2 | PAK_3 | SAK | BIP-113 time greater than (between_epoch_timestamp) |
---|---|---|---|---|---|
Scenario 19 | ✅ | ✅ | ✅ | ✅ | |
Scenario 20 | ✅ | ✅ | ✅ | ✅ | |
Scenario 21 | ✅ | ✅ | ✅ | ✅ |
Sovereign Recovery Path | 2 of 3 RKs | Network BIP-113 time greater than `largest_epoch_timestamp` |
||
---|---|---|---|---|
RK1 | RK2 | RK3 | ||
2 of 3 RKs AND after BIP-113 time is greater than `largest_epoch_timestamp` |
Spending Scenario | RK_1 | RK_2 | RK_3 | Timelock (largest_epoch_timestamp) |
---|---|---|---|---|
Scenario 22 | ✅ | ✅ | ✅ | |
Scenario 23 | ✅ | ✅ | ✅ | |
Scenario 24 | ✅ | ✅ | ✅ |
For this example, the smallest_epoch_timestamp
is: 1672531200 (Jan 1 2023, midnight gmt), the between_epoch_timestamp
is: 1673740800 and largest_epoch_timestamp
is: 1675209600 (Feb 1 2023, midnight gmt)
-
MINT-005 Output Descriptor:
wsh(andor(multi(2,$PAK_1$,$PAK_2$,$PAK_3$),or_i(and_v(v:pkh($SAK$),after(
between_epoch_timestamp
)),thresh(2,pk($PK_1$),s:pk($PK_2$),s:pk($PK_3$),snl:after(smallest_epoch_timestamp
))),and_v(v:thresh(2,pkh($RK_1$),a:pkh($RK_2$),a:pkh($RK_3$)),after(larget_epoch_timestamp
)))) -
Source Policy (FOR REFERENCE PURPOSES ONLY):
"or(99@and(thresh(2,pk($PAK_1$),pk($PAK_2$),pk($PAK_3$)),or(99@thresh(2,pk($PK_1$),pk($PK_2$),pk($PK_3$),after(
smallest_epoch_timestamp
)),and(pk($SAK$),after(between_epoch_timestamp
)))),and(thresh(2,pk($RK_1$),pk($RK_2$),pk($RK_3)),after(largest_epoch_timestamp
)))"
Signed by:
Signed by:
Signed by: