Hi all,
Kevin Loaec and I have been working on a new multiparty vault architecture and
I think it reached the point where we’d welcome some feedback.
Intended usage and limitations
==
The aim is to secure the shared storage of coins without relying on a trusted
third party and by disincentivizing theft attempts, while not restricting the
usage of the funds for day-to-day operations.
Revault uses N-of-N multisigs and thus does not protect against intentional
locking of funds (such as refusal to sign, or key erasure). Therefore it
assumes its users (likely companies with already on-going agreements between
shareholders) to be able to solve intentional blockage outside the Bitcoin
network (such as through legal contracts).
The actual architecture
===
We called it revault as it relies on pre-signed and revocable (revaultable)
transactions.
The users pre-sign a transaction chain as the only used way to spend from a
vault output.
They would have signed a set of transactions to either cancel a spend attempt
or lock the funds for some time beforehand. The funds are always better locked
for a long time than stolen.
The transactions
The system is composed of mainly 6 transaction types (with N the number of
stakeholders) :
- The “vault” transaction which pays to a N-of-N, by which funds are received.
- The “emergency” transaction, which spends the vault output and pays to a
[here goes a
high value]-days timelocked N-of-N (with N differents but statics keys, assumed
to be physically stored in hard(/long) to access locations).
- The “unvault” transaction, which spends the vault output and pays to [either
the vault’s N-of-N, or *after X blocks* to a subset of the stakeholders AND a
co-signing server].
- The “unvault emergency” transaction, which spends the unvault output and pays
to the
same script as the first emergency transaction.
- The “cancel” transaction, which spends the unvault output and pays back to a
new vault utxo.
- The “spend” transaction, which spends the unvault output and pays to an
external address (potentially contained in a list of destinations previously
agreed-upon by all the stakeholders).
The process
---
The stakeholders would exchange the signatures of all the revaulting
transactions after the reception of a new vault utxo, and then exchange the
signatures of the unvaulting transaction. Before doing so, the coins are not
available to be spent.
In order to spend a vault, the subset of the stakeholders who manages the funds
(for example, the traders of an investment fund) would make the cosigning
server (which only signs a transaction once) sign the spend transaction.
They would then present it to the other watchers which would ACK the spend (if
paying to an authorized address), and broadcast the "unvault" transaction.
Finally, and after X blocks have passed they would be able to broadcast the
spend transaction.
If a stakeholder's watcher detects an unvaulting transaction without knowing
about its child “spend” transaction, it triggers an automatic “cancel”
transaction (not encumbered by the timelock).
At any point -even in the middle of a spend- any of the stakeholder can trigger
an emergency transaction if anything nasty is happening.
Any network watcher noticing the broadcast of an emergency transaction would
also broadcast all other vaults’ emergency transactions.
This network watching and revaulting power can be replicated (watchtowers) to
further decrease the reliance on a single machine or internet access.
Pre-signed transactions fun
---
In order to avoid our security assumptions to be as weak as betting on the
value of the feerate in the future, stakeholders exchange SINGLE | ANYONECANPAY
signatures for the revaulting transactions and append their own as SIGHASH_ALL
before broadcasting.
They can add another input (and potentially output) in order to bump the fees
before doing so.
We protect ourselves from the bug by leveraging the fact the revaulting (namely
the "emergency", "unvault emergency", and "cancel" transactions) only have
*strictly* one input and one output. The change being part of the spend
transaction.
In addition, revaulting transactions may signal for RBF to cover a feerate
increase after the broadcast. Anyhow, a significant breathing room can be added
to the feerate as these transactions are not intended to be used under normal
circumstances.
Worth mentioning
The original draft of this architecture was first designed by Kevin Loaec who
was hired by NOIA to do so. It was inspired by Bryan Bishop’s single-party
vault architecture
(https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-August/017229.html),
who published a demo implementation of it last week
(https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-April/017755.html,
https://github.com/kanzure/python-vaults).
Kevin