diff options
-rw-r--r-- | README.mediawiki | 23 | ||||
-rw-r--r-- | bip-0002.mediawiki | 7 | ||||
-rw-r--r-- | bip-0010.mediawiki | 4 | ||||
-rw-r--r-- | bip-0012.mediawiki | 4 | ||||
-rw-r--r-- | bip-0021.mediawiki | 2 | ||||
-rw-r--r-- | bip-0038.mediawiki | 2 | ||||
-rw-r--r-- | bip-0039.mediawiki | 3 | ||||
-rw-r--r-- | bip-0043.mediawiki | 2 | ||||
-rw-r--r-- | bip-0044.mediawiki | 2 | ||||
-rw-r--r-- | bip-0049.mediawiki | 2 | ||||
-rw-r--r-- | bip-0084.mediawiki | 2 | ||||
-rw-r--r-- | bip-0327.mediawiki | 8 | ||||
-rw-r--r-- | bip-0345.mediawiki | 688 | ||||
-rw-r--r-- | bip-0345/opvault.drawio.png | bin | 0 -> 92563 bytes | |||
-rw-r--r-- | bip-0345/vaults-Basic.png | bin | 0 -> 18595 bytes | |||
-rw-r--r-- | bip-0345/vaults.drawio | 1113 | ||||
-rw-r--r-- | bip-0345/withdrawal-comparison.drawio.png | bin | 0 -> 20720 bytes | |||
-rw-r--r-- | bip-0380.mediawiki | 14 | ||||
-rw-r--r-- | bip-0381.mediawiki | 2 | ||||
-rw-r--r-- | bip-0382.mediawiki | 2 | ||||
-rw-r--r-- | bip-0384.mediawiki | 2 |
21 files changed, 1845 insertions, 37 deletions
diff --git a/README.mediawiki b/README.mediawiki index 6dbd798..2355dba 100644 --- a/README.mediawiki +++ b/README.mediawiki @@ -1,4 +1,4 @@ -People wishing to submit BIPs, first should propose their idea or document to the [https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev bitcoin-dev@lists.linuxfoundation.org] mailing list (do <em>not</em> assign a number - read <a href="bip-0002.mediawiki">BIP 2</a> for the full process). After discussion, please open a PR. After copy-editing and acceptance, it will be published here. +People wishing to submit BIPs, first should propose their idea or document to the [https://groups.google.com/g/bitcoindev bitcoindev@googlegroups.com] mailing list (do <em>not</em> assign a number - read <a href="bip-0002.mediawiki">BIP 2</a> for the full process). After discussion, please open a PR. After copy-editing and acceptance, it will be published here. We are fairly liberal with approving BIPs, and try not to be too involved in decision making on behalf of the community. The exception is in very rare cases of dispute resolution when a decision is contentious and cannot be agreed upon. In those cases, the conservative option will always be preferred. @@ -235,7 +235,7 @@ Those proposing changes should consider that ultimately consent may rest with th | Applications | Purpose Field for Deterministic Wallets | Marek Palatinus, Pavol Rusnak -| Informational +| Standard | Final |- style="background-color: #ffffcf" | [[bip-0044.mediawiki|44]] @@ -243,7 +243,7 @@ Those proposing changes should consider that ultimately consent may rest with th | Multi-Account Hierarchy for Deterministic Wallets | Marek Palatinus, Pavol Rusnak | Standard -| Proposed +| Final |- style="background-color: #ffffcf" | [[bip-0045.mediawiki|45]] | Applications @@ -270,7 +270,7 @@ Those proposing changes should consider that ultimately consent may rest with th | Applications | Derivation scheme for P2WPKH-nested-in-P2SH based accounts | Daniel Weigl -| Informational +| Standard | Final |- style="background-color: #cfffcf" | [[bip-0050.mediawiki|50]] @@ -434,12 +434,12 @@ Those proposing changes should consider that ultimately consent may rest with th | Eric Lombrozo | Standard | Rejected -|- +|- style="background-color: #cfffcf" | [[bip-0084.mediawiki|84]] | Applications | Derivation scheme for P2WPKH based accounts | Pavol Rusnak -| Informational +| Standard | Final |- | [[bip-0085.mediawiki|85]] @@ -487,7 +487,7 @@ Those proposing changes should consider that ultimately consent may rest with th | [[bip-0093.mediawiki|93]] | Applications | codex32: Checksummed SSSS-aware BIP32 seeds -| Leon Olsson Curr, Pearlwort Sneed +| Leon Olsson Curr, Pearlwort Sneed, Andrew Poelstra | Informational | Draft |- @@ -627,7 +627,7 @@ Those proposing changes should consider that ultimately consent may rest with th | [[bip-0119.mediawiki|119]] | Consensus (soft fork) | CHECKTEMPLATEVERIFY -| Jeremy Rubin +| Jeremy Rubin, James O'Beirne | Standard | Draft |- style="background-color: #ffcfcf" @@ -1072,6 +1072,13 @@ Those proposing changes should consider that ultimately consent may rest with th | Standard | Final |- +| [[bip-0345.mediawiki|345]] +| Consensus (soft fork) +| OP_VAULT +| James O'Beirne, Greg Sanders, Anthony Towns +| Standard +| Draft +|- style="background-color: #cfffcf" | [[bip-0350.mediawiki|350]] | Applications | Bech32m format for v1+ witness addresses diff --git a/bip-0002.mediawiki b/bip-0002.mediawiki index c6eb950..71d3812 100644 --- a/bip-0002.mediawiki +++ b/bip-0002.mediawiki @@ -32,13 +32,13 @@ The BIP process begins with a new idea for Bitcoin. Each potential BIP must have Small enhancements or patches to a particular piece of software often don't require standardisation between multiple projects; these don't need a BIP and should be injected into the relevant project-specific development workflow with a patch submission to the applicable issue tracker. Additionally, many ideas have been brought forward for changing Bitcoin that have been rejected for various reasons. The first step should be to search past discussions to see if an idea has been considered before, and if so, what issues arose in its progression. -After investigating past work, the best way to proceed is by posting about the new idea to the [https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev Bitcoin development mailing list]. +After investigating past work, the best way to proceed is by posting about the new idea to the [https://groups.google.com/g/bitcoindev Bitcoin development mailing list]. Vetting an idea publicly before going as far as writing a BIP is meant to save both the potential author and the wider community time. Asking the Bitcoin community first if an idea is original helps prevent too much time being spent on something that is guaranteed to be rejected based on prior discussions (searching the internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Just because an idea sounds good to the author does not mean it will work for most people in most areas where Bitcoin is used. -Once the champion has asked the Bitcoin community as to whether an idea has any chance of acceptance, a draft BIP should be presented to the [https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev Bitcoin development mailing list]. +Once the champion has asked the Bitcoin community as to whether an idea has any chance of acceptance, a draft BIP should be presented to the [https://groups.google.com/g/bitcoindev Bitcoin development mailing list]. This gives the author a chance to flesh out the draft BIP to make it properly formatted, of high quality, and to address additional concerns about the proposal. Following a discussion, the proposal should be submitted to the [https://github.com/bitcoin/bips BIPs git repository] as a pull request. This draft must be written in BIP style as described below, and named with an alias such as "bip-johndoe-infinitebitcoins" until an editor has assigned it a BIP number (authors MUST NOT self-assign BIP numbers). @@ -102,7 +102,7 @@ The BIP editors are intended to fulfill administrative and editorial responsibil ===Specification=== -BIPs should be written in mediawiki format. +BIPs should be written in mediawiki or markdown format. Each BIP should have the following parts: @@ -409,7 +409,6 @@ Why is Public Domain no longer acceptable for new BIPs? * Non-image auxiliary files are permitted in the bip-XXXX subdirectory. * Email addresses are now required for authors. * The Post-History header may be provided as a link instead of a simple date. -* Markdown format is no longer permitted for BIPs. * The Resolution header has been dropped, as it is not applicable to a decentralised system where no authority exists to make final decisions. ==See Also== diff --git a/bip-0010.mediawiki b/bip-0010.mediawiki index 42071f3..289e3b0 100644 --- a/bip-0010.mediawiki +++ b/bip-0010.mediawiki @@ -93,10 +93,10 @@ The following is an example TxDP from Armory, produced while running on the test In this transaction, there are two inputs, one of 150 BTC and the other of 12 BTC. This transaction combines 162 BTC to create two outputs, one of 160 BTC, one 1.9995 BTC, and a tx fee of 0.0005. In this TxDP, both inputs have been signed, and thus could broadcast immediately. -The style of communication is taken directly from PGP/GPG, which uses blocks of ASCII like this to communicate encrypted messages and signatures. This serialization is compact, and will be interpretted the same in all character encodings. It can be copied inline into an email, or saved in a text file. The advantage over the analogous PGP encoding is that there are some human readable elements to it, for users that wish to examine the TxDP packet manually, instead of requiring a program to parse the core elements of the TxDP. +The style of communication is taken directly from PGP/GPG, which uses blocks of ASCII like this to communicate encrypted messages and signatures. This serialization is compact, and will be interpreted the same in all character encodings. It can be copied inline into an email, or saved in a text file. The advantage over the analogous PGP encoding is that there are some human readable elements to it, for users that wish to examine the TxDP packet manually, instead of requiring a program to parse the core elements of the TxDP. A party receiving this TxDP can simply add their signature to the appropriate _TXINPUT_ line. If that is the last signature required, they can broadcast it themselves. Any software that implements this standard should be able to combine multiple TxDPs into a single TxDP. However, even without the programmatic support, a user could manually combine them by copying the appropriate _TXSIGS_ lines between serializations, though it is not the recommended method for combining TxDPs. == Reference Implementation == -This proposal was implemented and tested in the older versions of ''Armory'' Bitcoin software for use in offline-wallet transaction signing (as a 1-of-1 transaction). Implementation can be found in https://github.com/etotheipi/BitcoinArmory/blob/v0.91-beta/armoryengine/Transaction.py under the class PyTxDistProposal. However, as of verion 0.92 released in July 2014, Armory no longer uses this proposal for offline wallet transaction signing and has moved on to a new format. +This proposal was implemented and tested in the older versions of ''Armory'' Bitcoin software for use in offline-wallet transaction signing (as a 1-of-1 transaction). Implementation can be found in https://github.com/etotheipi/BitcoinArmory/blob/v0.91-beta/armoryengine/Transaction.py under the class PyTxDistProposal. However, as of version 0.92 released in July 2014, Armory no longer uses this proposal for offline wallet transaction signing and has moved on to a new format. diff --git a/bip-0012.mediawiki b/bip-0012.mediawiki index 70069d6..bd3d88c 100644 --- a/bip-0012.mediawiki +++ b/bip-0012.mediawiki @@ -43,11 +43,11 @@ OP_EVAL allows the receiver of bitcoins to specify how they can be spent when th If ''serialized script'' is a large or complicated multi-signature script, then the burden of paying for it (in increased transaction fees due to more signature operations or transaction size) is shifted from the sender to the receiver. -The main objection to OP_EVAL is that it adds complexity, and complexity is the enemy of security. Also, evaluating data as code has a long record of being a source of security vulnerabilties. +The main objection to OP_EVAL is that it adds complexity, and complexity is the enemy of security. Also, evaluating data as code has a long record of being a source of security vulnerabilities. That same argument can be applied to the existing Bitcoin 'scripting' system; scriptPubKeys are transmit as data across the network and are then interpreted by every bitcoin implementation. OP_EVAL just moves the data that will be interpreted. It is debatable whether or not the entire idea of putting a little interpreted expression evaluation language at the core of Bitcoin was brilliant or stupid, but the existence of OP_EVAL does not make the expression language less secure. -There is a 1-confirmation attack on old clients that interepret OP_EVAL as a no-op, but it is expensive and difficult in practice. The attack is: +There is a 1-confirmation attack on old clients that interpret OP_EVAL as a no-op, but it is expensive and difficult in practice. The attack is: # Attacker creates an OP_EVAL transaction that is valid as seen by old clients, but invalid for new clients. # Attacker also creates a standard transaction that spends the OP_EVAL transaction, and pays the victim. diff --git a/bip-0021.mediawiki b/bip-0021.mediawiki index 0fba9bc..cdc37ba 100644 --- a/bip-0021.mediawiki +++ b/bip-0021.mediawiki @@ -37,7 +37,7 @@ Elements of the query component may contain characters outside the valid range. === ABNF grammar === -(See also [[#Simpler syntax|a simpler representation of syntax]]) +(See also [[#simpler-syntax|a simpler representation of syntax]]) bitcoinurn = "bitcoin:" bitcoinaddress [ "?" bitcoinparams ] bitcoinaddress = *base58 diff --git a/bip-0038.mediawiki b/bip-0038.mediawiki index 511b55a..7f99b1a 100644 --- a/bip-0038.mediawiki +++ b/bip-0038.mediawiki @@ -170,7 +170,7 @@ To recalculate the address: # Derive ''passfactor'' using scrypt with ''ownerentropy'' and the user's passphrase and use it to recompute ''passpoint'' # Derive decryption key for ''pointb'' using scrypt with ''passpoint'', ''addresshash'', and ''ownerentropy'' # Decrypt ''encryptedpointb'' to yield ''pointb'' -# ECMultiply ''pointb'' by ''passfactor''. Use the resulting EC point as a public key and hash it into ''address'' using either compressed or uncompressed public key methodology as specifid in ''flagbyte''. +# ECMultiply ''pointb'' by ''passfactor''. Use the resulting EC point as a public key and hash it into ''address'' using either compressed or uncompressed public key methodology as specified in ''flagbyte''. =====Decryption===== # Collect encrypted private key and passphrase from user. diff --git a/bip-0039.mediawiki b/bip-0039.mediawiki index 5170edd..1c4845e 100644 --- a/bip-0039.mediawiki +++ b/bip-0039.mediawiki @@ -171,6 +171,9 @@ JavaScript: * https://github.com/dashhive/DashPhrase.js * https://github.com/hujiulong/web-bip39 +TypeScript: +* https://github.com/bitauth/libauth + Java: * https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/crypto/MnemonicCode.java diff --git a/bip-0043.mediawiki b/bip-0043.mediawiki index 32e02b1..f07c94a 100644 --- a/bip-0043.mediawiki +++ b/bip-0043.mediawiki @@ -7,7 +7,7 @@ Comments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0043 Status: Final - Type: Informational + Type: Standards Track Created: 2014-04-24 </pre> diff --git a/bip-0044.mediawiki b/bip-0044.mediawiki index 4ddd56b..5db540c 100644 --- a/bip-0044.mediawiki +++ b/bip-0044.mediawiki @@ -6,7 +6,7 @@ Pavol Rusnak <stick@satoshilabs.com> Comments-Summary: Mixed review (one person) Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0044 - Status: Proposed + Status: Final Type: Standards Track Created: 2014-04-24 </pre> diff --git a/bip-0049.mediawiki b/bip-0049.mediawiki index 7d8d2c7..a13b437 100644 --- a/bip-0049.mediawiki +++ b/bip-0049.mediawiki @@ -6,7 +6,7 @@ Comments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0049 Status: Final - Type: Informational + Type: Standards Track Created: 2016-05-19 License: PD </pre> diff --git a/bip-0084.mediawiki b/bip-0084.mediawiki index 7f20217..e1e458c 100644 --- a/bip-0084.mediawiki +++ b/bip-0084.mediawiki @@ -6,7 +6,7 @@ Comments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0084 Status: Final - Type: Informational + Type: Standards Track Created: 2017-12-28 License: CC0-1.0 </pre> diff --git a/bip-0327.mediawiki b/bip-0327.mediawiki index 07b40f5..b5600ab 100644 --- a/bip-0327.mediawiki +++ b/bip-0327.mediawiki @@ -123,7 +123,7 @@ This is by design: All algorithms in this proposal handle multiple signers who ( and applications are not required to check for duplicate individual public keys. In fact, applications are recommended to omit checks for duplicate individual public keys in order to simplify error handling. Moreover, it is often impossible to tell at key aggregation which signer is to blame for the duplicate, i.e., which signer came up with an individual public key honestly and which disruptive signer copied it. -In contrast, MuSig2 is designed to identify disruptive signers at signing time (see [[#identifiying-disruptive-signers|Identifiying Disruptive Signers]]). +In contrast, MuSig2 is designed to identify disruptive signers at signing time (see [[#identifying-disruptive-signers|Identifying Disruptive Signers]]). While the algorithms in this proposal are able to handle duplicate individual public keys, there are scenarios where applications may choose to abort when encountering duplicates. For example, we can imagine a scenario where a single entity creates a MuSig2 setup with multiple signing devices. @@ -211,7 +211,7 @@ The bit can be obtained with ''GetPlainPubkey(keyagg_ctx)[0] & 1''. The following specification of the algorithms has been written with a focus on clarity. As a result, the specified algorithms are not always optimal in terms of computation and space. -In particular, some values are recomputed but can be cached in actual implementations (see [[#signing-flow|Signing Flow]]). +In particular, some values are recomputed but can be cached in actual implementations (see [[#general-signing-flow|General Signing Flow]]). === Notation === @@ -367,7 +367,7 @@ Algorithm ''ApplyTweak(keyagg_ctx, tweak, is_xonly_t)'': Algorithm ''NonceGen(sk, pk, aggpk, m, extra_in)'': * Inputs: ** The secret signing key ''sk'': a 32-byte array (optional argument) -** The individual public key ''pk'': a 33-byte array (see [[#modifications-to-nonce-generation|Modifications to Nonce Generation]] for the reason that this argument is mandatory) +** The individual public key ''pk'': a 33-byte array (see [[#signing-with-tweaked-individual-keys|Signing with Tweaked Individual Keys]] for the reason that this argument is mandatory) ** The x-only aggregate public key ''aggpk'': a 32-byte array (optional argument) ** The message ''m'': a byte array (optional argument)<ref name="mlen">In theory, the allowed message size is restricted because SHA256 accepts byte strings only up to size of 2^61-1 bytes (and because of the 8-byte length encoding).</ref> ** The auxiliary input ''extra_in'': a byte array with ''0 ≤ len(extra_in) ≤ 2<sup>32</sup>-1'' (optional argument) @@ -465,7 +465,7 @@ Algorithm ''Sign(secnonce, sk, session_ctx)'': * Fail if ''pk ≠ secnonce[64:97]'' * Let ''a = GetSessionKeyAggCoeff(session_ctx, P)''; fail if that fails<ref>Failing ''Sign'' when ''GetSessionKeyAggCoeff(session_ctx, P)'' fails is not necessary for unforgeability. It merely indicates to the caller that the scheme is not being used correctly.</ref> * Let ''g = 1'' if ''has_even_y(Q)'', otherwise let ''g = -1 mod n'' -* <div id="Sign negation"></div>Let ''d = g⋅gacc⋅d' mod n'' (See [[negation-of-the-secret-key-when-signing|Negation Of The Secret Key When Signing]]) +* <div id="Sign negation"></div>Let ''d = g⋅gacc⋅d' mod n'' (See [[#negation-of-the-secret-key-when-signing|Negation Of The Secret Key When Signing]]) * Let ''s = (k<sub>1</sub> + b⋅k<sub>2</sub> + e⋅a⋅d) mod n'' * Let ''psig = bytes(32, s)'' * Let ''pubnonce = cbytes(k<sub>1</sub>'⋅G) || cbytes(k<sub>2</sub>'⋅G)'' diff --git a/bip-0345.mediawiki b/bip-0345.mediawiki new file mode 100644 index 0000000..a6ead31 --- /dev/null +++ b/bip-0345.mediawiki @@ -0,0 +1,688 @@ +<pre> + BIP: 345 + Layer: Consensus (soft fork) + Title: OP_VAULT + Author: James O'Beirne <vaults@au92.org> + Greg Sanders <gsanders87@gmail.com> + Anthony Towns <aj@erisian.com.au> + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0345 + Status: Draft + Type: Standards Track + Created: 2023-02-03 + License: BSD-3-Clause + Post-History: 2023-01-09: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html [bitcoin-dev] OP_VAULT announcment + 2023-03-01: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-March/021510.html [bitcoin-dev] BIP for OP_VAULT +</pre> + + +== Introduction == + +This BIP proposes two new tapscript opcodes that add consensus support for a specialized +covenant: <code>OP_VAULT</code> and <code>OP_VAULT_RECOVER</code>. These opcodes, in conjunction with +<code>OP_CHECKTEMPLATEVERIFY</code> +([https://github.com/bitcoin/bips/blob/master/bip-0119.mediawiki BIP-0119]), +allow users to enforce a delay period before designated coins may be spent to +an arbitrary destination, with the exception of a prespecified "recovery" path. +At any time prior to final withdrawal, the coins can be spent to the +recovery path. + +=== Copyright === + +This document is licensed under the 3-clause BSD license. + + +=== Motivation === + +The hazard of custodying Bitcoin is well-known. Users of Bitcoin must go to +significant effort to secure their private keys, and hope that once provisioned +their custody system does not yield to any number of evolving and +persistent threats. Users have little means to intervene once a compromise is +detected. This proposal introduces a mechanism that significantly +mitigates the worst-case outcome of key compromise: coin loss. + +Introducing a way to intervene during unexpected spends allows users to +incorporate highly secure key storage methods or unusual fallback strategies +that are only exercised in the worst case, and which may otherwise be +operationally prohibitive. The goal of this proposal is to make this strategy +usable for custodians of any size with minimal complication. + +==== Example uses ==== + +A common configuration for an individual custodying Bitcoin is "single +signature and passphrase" using a hardware wallet. A user with such a +configuration might be concerned about the risk associated with relying on a +single manufacturer for key management, as well as physical access to the +hardware. + +This individual can use <code>OP_VAULT</code> to make use of a highly secure +key as the unlikely recovery path, while using their existing signing procedure +as the withdrawal trigger key with a configured spend delay of e.g. 1 day. + +The recovery path key can be of a highly secure nature that might otherwise +make it impractical for daily use. For example, the key could be generated in +some analog fashion, or on an old computer that is then destroyed, with the +private key replicated only in paper form. Or the key could be a 2-of-3 +multisig using devices from different manufacturers. Perhaps the key is +geographically or socially distributed. + +Since it can be any Bitcoin script policy, the recovery key can include a +number of spending conditions, e.g. a time-delayed fallback to an "easier" +recovery method, in case the highly secure key winds up being ''too'' highly +secure. + +The user can run software on their mobile device that monitors the blockchain +for spends of the vault outpoints. If the vaulted coins move in an unexpected +way, the user can immediately sweep them to the recovery path, but spending the +coins on a daily basis works in the same way it did prior to vaulting (aside +from the spend delay). + +Institutional custodians of Bitcoin may use vaults in similar fashion. + +===== Provable timelocks ===== + +This proposal provides a mitigation to the +[https://web.archive.org/web/20230210123933/https://xkcd.com/538/ "$5 wrench attack."] By +setting the spend delay to, say, a week, and using as the recovery path a +script that enforces a longer relative timelock, the owner of the vault can +prove that he is unable to access its value immediately. To the author's +knowledge, this is the only way to configure this defense without rolling +timelocked coins for perpetuity or relying on a trusted third party. + +== Goals == + +[[File:bip-0345/vaults-Basic.png|frame|center]] + +Vaults in Bitcoin have been discussed formally since 2016 +([http://fc16.ifca.ai/bitcoin/papers/MES16.pdf MES16]) and informally since [https://web.archive.org/web/20160220215151/https://bitcointalk.org/index.php?topic=511881.0 2014]. The value of +having a configurable delay period with recovery capability in light of an +unexpected spend has been widely recognized. + +The only way to implement vaults given the existing consensus rules, aside from +[https://github.com/revault emulating vaults with large multisig +configurations], is to use presigned transactions created with a one-time-use +key. This approach was first demonstrated +[https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-April/017755.html in 2020]. + +Unfortunately, this approach has a number of practical shortcomings: +* generating and securely deleting ephemeral keys, which are used to emulate the vault covenant, is required, +* amounts and withdrawal patterns must be precommitted to, +* there is a necessity to precommit to an address that the funds must pass through on their way to the final withdrawal target, which is likely only known at unvault time, +* the particular fee management technique or wallet must be decided upon vault creation, +* coin loss follows if a vault address is reused, +* the transaction data that represents the "bearer asset" of the vault must be stored for perpetuity, otherwise value is lost, and +* the vault creation ceremony must be performed each time a new balance is to be deposited. + +The deployment of a "precomputed" covenant mechanism like +[https://github.com/bitcoin/bips/blob/master/bip-0119.mediawiki OP_CHECKTEMPLATEVERIFY] or +[https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki SIGHASH_ANYPREVOUT] +would both remove the necessity to use an ephemeral key, since the +covenant is enforced on-chain, and lessen the burden of sensitive data storage, +since the necessary transactions can be generated from a set of compact +parameters. This approach was demonstrated [https://github.com/jamesob/simple-ctv-vault in +2022]. + +However, the limitations of precomputation still apply: amounts, +destinations, and fee management are all fixed. Funds must flow through a fixed +intermediary to their final destination. Batch operations, which may be vital +for successful recovery during fee spikes or short spend delay, are not possible. + +[[File:bip-0345/withdrawal-comparison.drawio.png|frame|center]] + +Having a "general" covenant mechanism that can encode arbitrary transactional +state machines would allow us to solve these issues, but at the cost of complex +and large scripts that would probably be duplicated many times over in the +blockchain. The particular design and deployment timeline of such a general +framework is also uncertain. This approach was demonstrated +[https://blog.blockstream.com/en-covenants-in-elements-alpha/ in 2016]. + +This proposal intends to address the problems outlined above by +providing a delay period/recovery path use with minimal transactional and +operational overhead using a specialized covenant. + +The design goals of the proposal are: + +* '''efficient reuse of an existing vault configuration.'''<ref>'''Why does this support address reuse?''' The proposal doesn't rely on or encourage address reuse, but certain uses are unsafe if address reuse cannot be handled - for example, if a custodian gives its users a vault address to deposit to, it cannot enforce that those users make a single deposit for each address.</ref> A single vault configuration, whether the same literal <code>scriptPubKey</code> or not, should be able to “receive” multiple deposits. + +* '''batched operations''' for recovery and withdrawal to allow managing multiple vault coins efficiently. + +* '''unbounded partial withdrawals''', which allows users to withdraw partial vault balances without having to perform the setup ceremony for a new vault. + +* '''dynamic unvault targets''', which allow the proposed withdrawal target for a vault to be specified at withdrawal time rather than when the vault is first created. This would remove the need for a prespecified, intermediate wallet that only exists to route unvaulted funds to their desired destination. + +* '''dynamic fee management''' that, like dynamic targets, defers the specification of fee rates and source to unvault time rather than vault creation time. + +These goals are accompanied by basic safety considerations (e.g. not being +vulnerable to mempool pinning) and a desire for concision, both in terms of the number +of outputs created as well as script sizes. + +This proposal is designed to be compatible with any future sighash modes (e.g. <code>SIGHASH_GROUP</code>) or fee management strategies (e.g. [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-September/018168.html transaction sponsors]) that may be introduced. Use of these opcodes will benefit from, but do not strictly rely on, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-September/020937.html v3 transaction relay] and [https://github.com/instagibbs/bips/blob/ephemeral_anchor/bip-ephemeralanchors.mediawiki ephemeral anchors]. + +== Design == + +In typical usage, a vault is created by encumbering coins under a +taptree [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki (BIP-341)] +containing at least two leaves: one with an <code>OP_VAULT</code>-containing script that +facilitates the expected withdrawal process, and another leaf with +<code>OP_VAULT_RECOVER</code> which ensures the coins can be recovered +at any time prior to withdrawal finalization. + +The rules of <code>OP_VAULT</code> ensure the timelocked, interruptible +withdrawal by allowing a spending transaction to replace the +<code>OP_VAULT</code> tapleaf with a prespecified script template, allowing for +some parameters to be set at spend (trigger) time. All other leaves in the +taptree must be unchanged in the destination output, which preserves the recovery path as well as any +other spending conditions originally included in the vault. This is similar to +the <code>TAPLEAF_UPDATE_VERIFY</code> design that was proposed +[https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-September/019419.html in 2021]. + +These tapleaf replacement rules, described more precisely below, ensure a +timelocked withdrawal, where the timelock is fixed by the original +<code>OP_VAULT</code> parameters, to a fixed set of outputs (via +<code>OP_CHECKTEMPLATEVERIFY</code><ref>'''Why is <code>OP_CHECKTEMPLATEVERIFY</code> (BIP-119) relied upon for this proposal?''' During the withdrawal process, the proposed final destination for value being withdrawn must be committed to. <code>OP_CTV</code> is the simplest, safest way to commit the spend of some coins to a particular set of outputs. An earlier version of this proposal attempted to use a simpler, but similar method, of locking the spend of coins to a set of outputs, but this method introduced txid malleability.<br />Note that if some other method of locking spends to a particular set of outputs should be deployed, that method can be used in the <code>OP_VAULT</code> <code><leaf-update-script-body></code> with no changes.</ref>) which is chosen when the withdrawal +process is triggered. + +While <code>OP_CHECKTEMPLATEVERIFY</code> is used in this proposal as the +preferred method to bind the proposed withdrawal to a particular set of final +outputs, <code>OP_VAULT</code> is composable with other (and future) opcodes to +facilitate other kinds of withdrawal processes. + +[[File:bip-0345/opvault.drawio.png|frame|center]] + + +=== Transaction types === + +The vault has a number of stages, some of them optional: + +* '''vault transaction''': encumbers some coins into a Taproot structure that includes at least one <code>OP_VAULT</code> leaf and one <code>OP_VAULT_RECOVER</code> leaf. + +* '''trigger transaction''': spends one or more <code>OP_VAULT</code>-tapleaf inputs into an output which is encumbered by a timelocked withdrawal to a fixed set of outputs, chosen at trigger time. This publicly broadcasts the intent to withdraw to some specific set of outputs.<br /><br />The trigger transaction may have an additional output which allocates some of the vault balance into a partial "revault," which simply encumbers the revaulted portion of the value into the same <code>scriptPubKey</code> as the <code>OP_VAULT</code>-containing input(s) being spent. + +* '''withdrawal transaction''': spends the timelocked, destination-locked trigger inputs into a compatible set of final withdrawal outputs (per, e.g., a <code>CHECKTEMPLATEVERIFY</code> hash), after the trigger inputs have matured per the spend delay. Timelocked CTV transactions are the motivating usage of OP_VAULT, but any script template can be specified during the creation of the vault. + +* '''recovery transaction''': spends one or more vault inputs via <code>OP_VAULT_RECOVER</code> tapleaf to the prespecified recovery path, which can be done at any point before the withdrawal transaction confirms. Each input can optionally require a witness satisfying a specified ''recovery authorization'' script, an optional script prefixing the <code>OP_VAULT_RECOVER</code> fragment. The use of recovery authorization has certain trade-offs discussed later. + + +=== Fee management === + +A primary consideration of this proposal is how fee management is handled. +Providing dynamic fee management is critical to the operation of a vault, since + +* precalculated fees are prone to making transactions unconfirmable in high fee environments, and +* a fee wallet that is prespecified might be compromised or lost before use. + +But dynamic fee management can introduce +[https://bitcoinops.org/en/topics/transaction-pinning/ pinning vectors]. Care +has been taken to avoid unnecessarily introducing these vectors when using the new +destination-based spending policies that this proposal introduces. + +Originally, this proposal had a hard dependency on reformed transaction +nVersion=3 policies, including ephemeral anchors, but it has since been revised +to simply benefit from these changes in policy as well as other potential fee +management mechanisms. + + +== Specification == + +The tapscript opcodes <code>OP_SUCCESS187</code> (<code>0xbb</code>) and +<code>OP_SUCCESS188</code> (<code>0xbc</code>) are constrained with new rules +to implement <code>OP_VAULT</code> and <code>OP_VAULT_RECOVER</code>, +respectively. + +=== <code>OP_VAULT</code> evaluation === + +When evaluating <code>OP_VAULT</code> (<code>OP_SUCCESS187</code>, +<code>0xbb</code>), the expected format of the stack, shown top to bottom, is: + +<source> +<leaf-update-script-body> +<push-count> +[ <push-count> leaf-update script data items ... ] +<trigger-vout-idx> +<revault-vout-idx> +<revault-amount> +</source> + +where + +* <code><leaf-update-script-body></code> is a minimally-encoded data push of a serialized script. <ref>In conjunction with the leaf-update data items, it dictates the tapleaf script in the output taptree that will replace the one currently executing.</ref> +** Otherwise, script execution MUST fail and terminate immediately. + +* <code><push-count></code> is an up to 4-byte minimally encoded <code>CScriptNum</code> indicating how many leaf-update script items should be popped off the stack. <ref>'''Why only prefix with data pushes?''' Prefixing the <code>leaf-update-script-body</code> with opcodes opens up the door to prefix OP_SUCCESSX opcodes, to name a single issue only, side-stepping the validation that was meant to be run by the committed script.</ref> +** If this value does not decode to a valid CScriptNum, script execution MUST fail and terminate immediately. +** If this value is less than 0, script execution MUST fail and terminate immediately. +** If there are fewer than 3 items following the <code><push-count></code> items on the stack, script execution MUST fail and terminate immediately. In other words, after popping <code><leaf-update-script-body></code>, there must be at least <code>3 + <push-count></code> items remaining on the stack. + +* The following <code><push-count></code> stack items are popped off the stack and prefixed as minimally-encoded push-data arguments to the <code><leaf-update-script-body></code> to construct the expected tapleaf replacement script. + +* <code><trigger-vout-idx></code> is an up to 4-byte minimally encoded <code>CScriptNum</code> indicating the index of the output which, in conjunction with an optional revault output, carries forward the value of this input, and has an identical taptree aside from the currently executing leaf. +** If this value does not decode to a valid CScriptNum, script execution MUST fail and terminate immediately. +** If this value is less than 0 or is greater than or equal to the number of outputs, script execution MUST fail and terminate immediately. + +* <code><revault-vout-idx></code> is an up to 4-byte minimally encoded <code>CScriptNum</code> optionally indicating the index of an output which, in conjunction with the trigger output, carries forward the value of this input, and has an identical scriptPubKey to the current input. +** If this value does not decode to a valid CScriptNum, script execution MUST fail and terminate immediately. +** If this value is greater than or equal to the number of outputs, script execution MUST fail and terminate immediately. +** If this value is negative and not equal to -1, script execution MUST fail and terminate immediately.<ref>'''Why is -1 the only allowable negative value for revault-vout-idx?''' A negative revault index indicates that no revault output exists; if this value were allowed to be any negative number, the witness could be malleated (and bloated) while a transaction is waiting for confirmation.</ref> + +* <code><revault-amount></code> is an up to 7-byte minimally encoded CScriptNum indicating the number of satoshis being revaulted. +** If this value does not decode to a valid CScriptNum, script execution MUST fail and terminate immediately. +** If this value is not greater than or equal to 0, script execution MUST fail and terminate immediately. +** If this value is non-zero but <code><revault-vout-idx></code> is negative, script execution MUST fail and terminate immediately. +** If this value is zero but <code><revault-vout-idx></code> is not -1, script execution MUST fail and terminate immediately. + +After the stack is parsed, the following validation checks are performed: + +* Decrement the per-script sigops budget (see [https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki#user-content-Resource_limits BIP-0342]) by 60<ref>'''Why is the sigops cost for OP_VAULT set to 60?''' To determine the validity of a trigger output, OP_VAULT must perform an EC multiplication and hashing proportional to the length of the control block in order to generate the output's expected TapTweak. This has been measured to have a cost in the worst case (max length control block) of roughly twice a Schnorr verification. Because the hashing cost could be mitigated by caching midstate, the cost is 60 and not 100.</ref>; if the budget is brought below zero, script execution MUST fail and terminate immediately. +* Let the output designated by <code><trigger-vout-idx></code> be called ''triggerOut''. +* If the scriptPubKey of ''triggerOut'' is not a version 1 witness program, script execution MUST fail and terminate immediately. +* Let the script constructed by taking the <code><leaf-update-script-body></code> and prefixing it with minimally-encoded data pushes of the <code><push-count></code> leaf-update script data items be called the ''leaf-update-script''. +* If the scriptPubKey of ''triggerOut'' does not match that of a taptree that is identical to that of the currently evaluated input, but with the leaf script substituted for ''leaf-update-script'', script execution MUST fail and terminate immediately. +** Note: the parity bit of the resulting taproot output is allowed to vary, so both values for the new output must be checked. +* Let the output designated by <code><revault-vout-idx></code> (if the index value is non-negative) be called ''revaultOut''. +* If the scriptPubKey of ''revaultOut'' is not equal to the scriptPubKey of the input being spent, script execution MUST fail and terminate immediately. +* Implementation recommendation: if the sum of the amounts of ''triggerOut'' and ''revaultOut'' (if any) are not greater than or equal to the value of this input, script execution SHOULD fail and terminate immediately. This ensures that (at a minimum) the vaulted value for this input is carried through. +** Amount checks are ultimately done with deferred checks, but this check can help short-circuit obviously invalid spends. +* Queue a deferred check<ref>'''What is a deferred check and why does this proposal require them for correct script evaluation?''' A deferred check is a validation check that is executed only after all input scripts have been validated, and is based on aggregate information collected during each input's EvalScript run.<br /><br />Currently, the validity of each input is (usually) checked concurrently across all inputs in a transaction. Because this proposal allows batching the spend of multiple vault inputs into a single recovery or withdrawal output, we need a mechanism to ensure that all expected values per output can be summed and then checked. This necessitates the introduction of an "aggregating" set of checks which can only be executed after each input's script is evaluated. Note that similar functionality would be required for batch input validation or cross-input signature aggregation.</ref> that ensures the satoshis for this input's <code>nValue</code> minus <code><revault-amount></code> are included within the output <code>nValue</code> found at <code><trigger-vout-idx></code>. +* Queue a deferred check that ensures <code><revault-amount></code> satoshis, if non-zero, are included within the output's <code>nValue</code> found at <code><revault-vout-idx></code>. +** These deferred checks could be characterized in terms of the pseudocode below (in ''Deferred checks'') as<br /><code>TriggerCheck(input_amount, <revault-amount>, <trigger-vout-idx>, <revault-vout-idx>)</code>. + +If none of the conditions fail, a single true value (<code>0x01</code>) is left on the stack. + +=== <code>OP_VAULT_RECOVER</code> evaluation === + +When evaluating <code>OP_VAULT_RECOVER</code> (<code>OP_SUCCESS188</code>, +<code>0xbb</code>), the expected format of the stack, shown top to bottom, is: + +<source> +<recovery-sPK-hash> +<recovery-vout-idx> +</source> + +where + +* <code><recovery-sPK-hash></code> is a 32-byte data push. +** If this is not 32 bytes in length, script execution MUST fail and terminate immediately. +* <code><recovery-vout-idx></code> is an up to 4-byte minimally encoded <code>CScriptNum</code> indicating the index of the recovery output. +** If this value does not decode to a valid CScriptNum, script execution MUST fail and terminate immediately. +** If this value is less than 0 or is greater than or equal to the number of outputs, script execution MUST fail and terminate immediately. + +After the stack is parsed, the following validation checks are performed: + +* Let the output at index <code><recovery-vout-idx></code> be called ''recoveryOut''. +* If the scriptPubKey of ''recoveryOut'' does not have a tagged hash equal to <code><recovery-sPK-hash></code> (<code>tagged_hash("VaultRecoverySPK", recoveryOut.scriptPubKey) == recovery-sPK-hash</code>, where <code>tagged_hash()</code> is from the [https://github.com/bitcoin/bips/blob/master/bip-0340/reference.py BIP-0340 reference code]), script execution MUST fail and terminate immediately. +** Implementation recommendation: if ''recoveryOut'' does not have an <code>nValue</code> greater than or equal to this input's amount, the script SHOULD fail and terminate immediately. +* Queue a deferred check that ensures the <code>nValue</code> of ''recoveryOut'' contains the entire <code>nValue</code> of this input.<ref>'''How do recovery transactions pay for fees?''' If the recovery is unauthorized, fees are attached either via CPFP with an ephemeral anchor or as inputs which are solely spent to fees (i.e. no change output). If the recovery is authorized, fees can be attached in any manner, e.g. unrelated inputs and outputs or CPFP via anchor.</ref> +** This deferred check could be characterized in terms of the pseudocode below as <code>RecoveryCheck(<recovery-vout-idx>, input_amount)</code>. + +If none of the conditions fail, a single true value (<code>0x01</code>) is left on the stack. + +=== Deferred check evaluation === + +Once all inputs for a transaction are validated per the rules above, any +deferred checks queued MUST be evaluated. + +The Python pseudocode for this is as follows: + +<source lang="python"> +class TriggerCheck: + """Queued by evaluation of OP_VAULT (withdrawal trigger).""" + input_amount: int + revault_amount: int + trigger_vout_idx: int + revault_vout_idx: int + + +class RecoveryCheck: + """Queued by evaluation of OP_VAULT_RECOVER.""" + input_amount: int + vout_idx: int + + +def validate_deferred_checks(checks: [DeferredCheck], tx: Transaction) -> bool: + """ + Ensure that all value from vault inputs being triggered or recovered is preserved + in suitable output nValues. + """ + # Map to hold expected output values. + out_map: Dict[int, int] = defaultdict(lambda: 0) + + for c in checks: + if isinstance(c, TriggerCheck): + out_map[c.trigger_vout_idx] += (c.input_amount - c.revault_amount) + + if c.revault_amount > 0: + out_map[c.revault_vout_idx] += c.revault_amount + + elif isinstance(c, RecoveryCheck): + out_map[c.vout_idx] += c.input_amount + + for (vout_idx, amount_sats) in out_map.items(): + # Trigger/recovery value can be greater than the constituent vault input + # amounts. + if tx.vout[vout_idx].nValue < amount_sats: + return False + + return True +</source> + +If the above procedure, or an equivalent, returns false, script execution MUST fail and terminate +immediately. + +This ensures that all compatible vault inputs can be batched into shared +corresponding trigger or recovery outputs while preserving their entire input value. + + +== Policy changes == + +In order to prevent possible pinning attacks, recovery transactions must be replaceable. + +* When validating an <code>OP_VAULT_RECOVER</code> input being spent, the script MUST fail (by policy, not consensus) and terminate immediately if both<ref>'''Why are recovery transactions required to be replaceable?''' In the case of unauthorized recoveries, an attacker may attempt to pin recovery transactions by broadcasting a "rebundled" version with a low fee rate. Vault owners must be able to overcome this with replacement. In the case of authorized recovery, if an attacker steals the recovery authorization key, the attacker may try to pin the recovery transaction during theft. Requiring replaceability ensures that the owner can always raise the fee rate of the recovery transaction, even if they are RBF rule #3 griefed in the process.</ref> +*# the input is not marked as opt-in replaceable by having an nSequence number less than <code>0xffffffff - 1</code>, per [https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki BIP-0125], and +*# the version of the recovery transaction has an nVersion other than 3. + +If the script containing <code>OP_VAULT_RECOVER</code> is 34 bytes or less<ref>34 bytes is the length of a recovery script that consists solely of <code><recovery-sPK-hash> OP_VAULT_RECOVER</code>.</ref>, let +it be called "unauthorized," because there is no script guarding the recovery +process. In order to prevent pinning attacks in the case of unauthorized +recovery - since the spend of the input (and the structure of the +transaction) is not authorized by a signed signature message - the output structure of +unauthorized recovery transaction is limited. + +* If the recovery is unauthorized, the recovery transaction MUST (by policy) abide by the following constraints: +** If the spending transaction has more than two outputs, the script MUST fail and terminate immediately. +** If the spending transaction has two outputs, and the output which is not ''recoveryOut'' is not an [https://github.com/instagibbs/bips/blob/ephemeral_anchor/bip-ephemeralanchors.mediawiki ephemeral anchor], the script MUST fail and terminate immediately.<ref>'''Why can unauthorized recoveries only process a single recovery path?''' Because there is no signature required for unauthorized recoveries, if additional outputs were allowed, someone observing a recovery in the mempool would be able to rebundle and broadcast the recovery with a lower fee rate.</ref> + +== Implementation == + +A sample implementation is available on bitcoin-inquisition [https://github.com/jamesob/bitcoin/tree/2023-01-opvault-inq here], with an associated [https://github.com/bitcoin-inquisition/bitcoin/pull/21 pull request]. + + +== Applications == + +The specification above, perhaps surprisingly, does not specifically cover how a relative timelocked withdrawal process with a fixed target is implemented. The tapleaf update semantics specified in <code>OP_VAULT</code> as well as the output-based authorization enabled by <code>OP_VAULT_RECOVER</code> can be used to implement a vault, but they are incomplete without two other pieces: + +* a way to enforce relative timelocks, like <code>OP_CHECKSEQUENCEVERIFY</code>, and +* a way to enforce that proposed withdrawals are ultimately being spent to a precise set of outputs, like <code>OP_CHECKTEMPLATEVERIFY</code>. + +These two pieces are combined with the tapleaf update capabilities of +<code>OP_VAULT</code> to create a vault, described below. + +=== Creating a vault === + +In order to vault coins, they can be spent into a witness v1 <code>scriptPubKey</code> +that contains a taptree of the form + +<source> +tr(<internal-pubkey>, + leaves = { + recover: + <recovery-sPK-hash> OP_VAULT_RECOVER, + + trigger: + <trigger-auth-pubkey> OP_CHECKSIGVERIFY (i) + <spend-delay> 2 $leaf-update-script-body OP_VAULT, (ii) + + ... [ possibly other leaves ] + } +) +</source> +where +* <code>$leaf-update-script-body</code> is, for example, <code>OP_CHECKSEQUENCEVERIFY OP_DROP OP_CHECKTEMPLATEVERIFY</code>. +** This is one example of a trigger script, but ''any'' script fragment can be used, allowing the creation of different types of vaults. For example, you could use <code>OP_CHECKSEQUENCEVERIFY OP_DROP OP_CHECKSIG</code> to do a time-delayed transfer of the coins to another key. This also future-proofs <code>OP_VAULT</code> for future scripting capabilities. +* The script fragment in <code>(i)</code> is called the "trigger authorization," because it gates triggering the withdrawal. This can be done in whatever manner the wallet designer would like. +* The script fragment in <code>(ii)</code> is the incomplete <code>OP_VAULT</code> invocation - it will be completed once the rest of the parameters (the CTV target hash, trigger vout index, and revault vout index) are provided by the trigger transaction witness. + +Typically, the internal key for the vault taproot output will be specified so +that it is controlled by the same descriptor as the recovery path, which +facilitates another (though probably unused) means of recovering the vault +output to the recovery path. This has the potential advantage of recovering the +coin without ever revealing it was a vault. + +Otherwise, the internal key can be chosen to be an unspendable NUMS point to +force execution of the taptree contents. + +=== Triggering a withdrawal === + +To make use of the vault, and spend it towards some output, we construct a spend +of the above <code>tr()</code> output that simply replaces the "trigger" leaf with the +full leaf-update script (in this case, a timelocked CTV script): + +<source> +Witness stack: + +- <revault-amount> +- <revault-vout-idx> (-1 if none) +- <trigger-vout-idx> +- <target-CTV-hash> +- <trigger-auth-pubkey-signature> +- [ "trigger" leaf script contents ] +- [ taproot control block prompting a script-path spend to "trigger" leaf ] + +Output scripts: + +[ + tr(<internal-pubkey>, + leaves = { + recover: + <recovery-sPK-hash> OP_VAULT_RECOVER, <-- unchanged + + trigger: + <target-CTV-hash> <spend-delay> + OP_CHECKSEQUENCEVERIFY OP_DROP OP_CHECKTEMPLATEVERIFY <-- changed per the + leaf-update + rules of OP_VAULT + ... [ possibly other leaves ] + } + ), + + [ optional revault output with the + same sPK as the original vault output ], +] +</source> + +<code>OP_VAULT</code> has allowed the taptree to be transformed so that the trigger leaf +becomes a timelocked CTV script, which is what actually facilitates the announced +withdrawal. The withdrawal is interruptible by the recovery path because the +"recover" leaf is preserved exactly from the original taptree. + +Note that the CTV hash is specified at spend time using the witness stack, and +"locked in" via the <code>OP_VAULT</code> spend rules which assert its existence in the output. + +The vault funds can be recovered at any time prior to the spend of the +timelocked CTV script by way of a script-path spend using the "recover" leaf. + + +=== Recovery authorization === + +When configuring a vault, the user must decide if they want to have the +recovery process gated by a script fragment prefixing the +<code>OP_VAULT_RECOVER</code> instruction in the "recover" leaf. Its use +entails trade-offs. + +==== Unauthorized recovery ==== + +Unauthorized recovery simplifies vault use in that recovery never requires additional information aside from the location of the vault outpoints and the recovery path - the "authorization" is simply the reveal of the recovery path, i.e. the preimage of <code><recovery-sPK-hash></code>. + +But because this reveal is the only authorization necessary to spend the vault coins to recovery, the user must expect to recover all such vaults at once, since an observer can replay this recovery (provided they know the outpoints). + +Additionally, unauthorized recovery across multiple distinct recovery paths +cannot be done in the same transaction, and fee control is more constrained: +because the output structure is limited for unauthorized recovery, fee +management relies either on inputs which are completely spent to fees or the +use of the optional ephemeral anchor and package relay. + +These limitations are to avoid pinning attacks. + +==== Authorized recovery ==== + +With authorized recovery, the user must keep track of an additional piece of information: how to solve the recovery authorization script fragment when recovery is required. + +If this key is lost, the user will be unable to initiate the recovery process for their coins. If an attacker obtains the recovery key, they may grief the user during the recovery process by constructing a low fee rate recovery transaction and broadcasting it (though they will not be able to pin because of the replaceability requirement on recovery transactions). + +However, authorized recovery configurations have significant benefits. Batched recoveries are possible for vaults with otherwise incompatible recovery parameters. Fee management is much more flexible, since authorized recovery transactions are "free form" and unrelated inputs and outputs can be added, potentially to handle fees. + +==== Recommendation: use a simple, offline recovery authorization key seed ==== + +The benefits of batching and fee management that authorized recovery provides are significant. If the recovery authorization key falls into the hands of an attacker, the outcome is not catastrophic, whereas if the user loses their recovery authorization key as well as their trigger key, the result is likely coin loss. Consequently, the author's recommendation is to use a simple seed for the recovery authorization key that can be written down offline and replicated. + +Note that the recovery authorization key '''is not''' the recovery path key, and +this is '''much different''' than any recommendation on how to generate the +recovery path key itself. + +=== Address reuse and recovery === + +When creating a vault, four factors affect the resulting P2TR address: +# The internal pubkey (likely belonging to the recovery wallet) +# The recovery leaf +# The trigger leaf +# Any other leaves that exist in the taptree + +The end user has the option of varying certain contents along descriptors in +order to avoid reusing vault addresses without affecting key management, e.g. +the trigger authorization pubkeys. + +Note that when using unauthorized recovery, the reveal of the +recovery scriptPubKey will allow any observer to initiate the recovery process +for any vault with matching recovery params, provided they are able to locate +the vault outpoints. As a result, it is recommended to expect that +'''all outputs sharing an identical unauthorized <code><recovery-sPK-hash></code> should be recovered together'''. + +This situation can be avoided with a comparable key management model by varying +the generation of each vault's recovery scriptPubKey along a single descriptor, +but note that this will prevent recovering multiple separate vaults into a single +recovery output. + +Varying the internal pubkey will prevent batching the trigger of multiple vault +inputs into a single trigger output; consequently it is recommended that users +instead vary some component of the trigger leaf script if address reuse is +undesirable. Users could vary the trigger pubkey along a descriptor, keeping +the recovery path and internal-pubkey the same, which both avoids reusing +addresses and allows batched trigger and recovery operations. + +==== Recommendation: generate new recovery addresses for new trigger keys ==== + +If using unauthorized recovery, it is recommended that you do not share recovery scriptPubKeys +across separate trigger keys. If one trigger key is compromised, that will necessitate the (unauthorized) +recovery of all vaults with that trigger key, which will reveal the recovery path preimage. This +means that an observer might be able to initiate recovery for vaults controlled by an uncompromised +trigger key. + +==== Fee management ==== + +Fees can be managed in a variety of ways, but it's worth noting that both +trigger and recovery transactions must preserve the total value of vault +inputs, so vaulted values cannot be repurposed to pay for fees. This does not +apply to the withdrawal transaction, which can allocate value arbitrarily. + +In the case of vaults that use recovery authorization, all transactions can +"bring their own fees" in the form of unrelated inputs and outputs. These +transactions are also free to specify ephemeral anchors, once the related relay +policies are deployed. This means that vaults using recovery authorization have +no dependence on the deploy of v3 relay policy. + +For vaults using unauthorized recovery, the recovery +transaction relies on the use of either fully-spent fee inputs or an ephemeral +anchor output. This means that vaults which do not use recovery authorization +are essentially dependent on v3 transaction relay policy being deployed. + +=== Batching === + +==== During trigger ==== + +<code>OP_VAULT</code> outputs with the same taptree, aside from slightly +different trigger leaves, can be batched together in the same withdrawal +process. Two "trigger" leaves are compatible if they have the same +<code>OP_VAULT</code> arguments. + +Note that this allows the trigger authorization -- the script prefixing the +<code>OP_VAULT</code> invocation -- to differ while still allowing batching. + +Trigger transactions can act on multiple incompatible <code>OP_VAULT</code> +input sets, provided each set has a suitable associated ''triggerOut'' +output. + +Since <code>SIGHASH_DEFAULT</code> can be used to sign the trigger +authorization, unrelated inputs and outputs can be included, possibly to +facilitate fee management or the batch withdrawal of incompatible vaults. + +==== During withdrawal ==== + +During final withdrawal, multiple trigger outputs can be used towards the same +withdrawal transaction provided that they share identical +<code><target-CTV-hash></code> parameters. This facilitates batched +withdrawals. + +==== During recovery ==== + +<code>OP_VAULT_RECOVER</code> outputs with the same <code><recovery-sPK-hash></code> +can be recovered into the same output. + +Recovery-incompatible vaults which have authorized recovery can be recovered in +the same transaction, so long as each set (grouped by +<code><recovery-sPK-hash></code>) has an associated ''recoveryOut''. This allows +unrelated recoveries to share common fee management. + +=== Watchtowers === + +The value of vaults is contingent upon having monitoring in place that will +alert the owner when unexpected spends are taking place. This can be done in a +variety of ways, with varying degrees of automation and trust in the +watchtower. + +In the maximum-trust case, the watchtower can be fully aware of all vaulted +coins and has the means to initiate the recovery process if spends are not +pre-reported to the watchtower. + +In the minimum-trust case, the user can supply a probabilistic filter of which +coins they wish to monitor; the watchtower would then alert the user if any +coins matching the filter move, and the user would be responsible for ignoring +false positives and handling recovery initiation. + +=== Output descriptors === + +Output descriptors for vault-related outputs will be covered in a subsequent BIP. + +== Deployment == + +Activation mechanism is to be determined. + +This BIP should be deployed concurrently with BIP-0119 to enable full use of vaults. + +== Backwards compatibility == + +<code>OP_VAULT</code> and <code>OP_VAULT_RECOVER</code> replace, respectively, +the witness v1-only opcodes OP_SUCCESS187 and OP_SUCCESS188 with stricter +verification semantics. Consequently, scripts using those opcodes which +previously were valid will cease to be valid with this change. + +Stricter verification semantics for an OP_SUCCESSx opcode are a soft fork, so +existing software will be fully functional without upgrade except for mining +and block validation. + +Backwards compatibility considerations are very comparable to previous +deployments for OP_CHECKSEQUENCEVERIFY and OP_CHECKLOCKTIMEVERIFY (see +[https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP-0065] and +[https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki BIP-0112]). + + +== Rationale == + +<references /> + +== References == + +* [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-February/012470.html [bitcoin-dev] Bitcoin Vaults (2016)] +* [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015793.html [bitcoin-dev] Simple lock/unlock mechanism (2018)] +* [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-April/017755.html [bitcoin-dev] On-chain vaults prototype (2020)] +* [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-September/019419.html [bitcoin-dev] TAPLEAF_UPDATE_VERIFY covenant opcode (2021)] +* [https://arxiv.org/abs/2005.11776 Custody Protocols Using Bitcoin Vaults (2020)] +* [https://jameso.be/vaults.pdf Vaults and Covenants (2023)] + +== Acknowledgements == + +The author would like to thank + +* AJ Towns and Greg Sanders for discussion, numerous suggestions that improved the proposal, and advice. +* Jeremy Rubin for inspiration, advice, and mentorship. +* BL for discussion and insight. +* John Moffett for early feedback and a test case demonstrating a recursive script evaluation attack. +* Johan Halseth for providing conceptual review and pointing out a pinning attack. +* Pieter Wuille for implementation advice. diff --git a/bip-0345/opvault.drawio.png b/bip-0345/opvault.drawio.png Binary files differnew file mode 100644 index 0000000..702189d --- /dev/null +++ b/bip-0345/opvault.drawio.png diff --git a/bip-0345/vaults-Basic.png b/bip-0345/vaults-Basic.png Binary files differnew file mode 100644 index 0000000..591b633 --- /dev/null +++ b/bip-0345/vaults-Basic.png diff --git a/bip-0345/vaults.drawio b/bip-0345/vaults.drawio new file mode 100644 index 0000000..6f7fd4e --- /dev/null +++ b/bip-0345/vaults.drawio @@ -0,0 +1,1113 @@ +<mxfile host="app.diagrams.net" modified="2023-03-23T20:50:16.927Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36" etag="MVPrlQq-FqlMbts0SwvB" version="21.1.0" type="device" pages="8"> + <diagram id="qHG0FeF2aWp-aiau7VVg" name="Basic flow"> + <mxGraphModel dx="2162" dy="1316" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="b8DSxFJpJzC5LI19bmsF-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="b8DSxFJpJzC5LI19bmsF-1" target="b8DSxFJpJzC5LI19bmsF-3" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-8" value="<div>Sign with trigger key</div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="b8DSxFJpJzC5LI19bmsF-5" vertex="1" connectable="0"> + <mxGeometry x="-0.3102" y="-1" relative="1" as="geometry"> + <mxPoint x="1" y="6" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-6" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeColor=default;dashed=1;" parent="1" source="b8DSxFJpJzC5LI19bmsF-1" target="b8DSxFJpJzC5LI19bmsF-2" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-7" value="Reveal recovery <br>scriptPubKey<br>and (if applicable)<br>satisfy recovery <br>auth. script" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="b8DSxFJpJzC5LI19bmsF-6" vertex="1" connectable="0"> + <mxGeometry x="-0.17" y="2" relative="1" as="geometry"> + <mxPoint x="52" y="57" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-1" value="<div><span style="background-color: initial;"><b>Vault transaction</b></span></div><div><span style="background-color: initial;"><br></span></div><div><i style="background-color: initial;">&lt;recovery-params&gt;</i><br></div><div>&lt;<i>spend-delay</i>&gt;</div><div>&lt;<i>trigger-sPK-hash</i>&gt;<br></div><div><b style="border-color: var(--border-color);">OP_VAULT</b><br></div>" style="rounded=1;whiteSpace=wrap;html=1;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="1" vertex="1"> + <mxGeometry x="190" y="250" width="140" height="100" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-2" value="<b>Recovery transaction<br></b><br>[outputs controlled <br>by recovery keys]" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="443" y="420" width="130" height="70" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-9" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;dashed=1;strokeColor=default;endArrow=none;endFill=0;rounded=1;" parent="1" source="b8DSxFJpJzC5LI19bmsF-3" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="400" y="300" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="iAfIXZV-x1gRYHwice2W-8" value="Recover from trigger,<br style="font-size: 11px;">before withdrawal<br style="font-size: 11px;">confirms" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=11;" parent="b8DSxFJpJzC5LI19bmsF-9" vertex="1" connectable="0"> + <mxGeometry x="0.4001" y="-1" relative="1" as="geometry"> + <mxPoint x="-13" y="19" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=default;" parent="1" source="b8DSxFJpJzC5LI19bmsF-3" target="b8DSxFJpJzC5LI19bmsF-10" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-12" value="<div>Wait <i>spend-delay</i> blocks <b>&amp;&amp;</b><br></div><div>outputs match target hash<br></div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="b8DSxFJpJzC5LI19bmsF-11" vertex="1" connectable="0"> + <mxGeometry x="-0.302" y="2" relative="1" as="geometry"> + <mxPoint x="1" y="4" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="oT6HpDHtKCBb9ui_6_kA-1" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.001;exitY=0.406;exitDx=0;exitDy=0;entryX=0.001;entryY=0.595;entryDx=0;entryDy=0;dashed=1;endArrow=classic;endFill=1;entryPerimeter=0;exitPerimeter=0;" parent="1" source="b8DSxFJpJzC5LI19bmsF-3" target="b8DSxFJpJzC5LI19bmsF-1" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="90" y="441" /> + <mxPoint x="90" y="310" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="oT6HpDHtKCBb9ui_6_kA-2" value="Optional <br>partial-balance<br>revault" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="oT6HpDHtKCBb9ui_6_kA-1" vertex="1" connectable="0"> + <mxGeometry x="0.1091" y="1" relative="1" as="geometry"> + <mxPoint y="13" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-3" value="<div><b><span style="background-color: initial;">Trigger transaction</span><br></b></div><div><i style="background-color: initial;"><br></i></div><div><i style="background-color: initial;">&lt;recovery-params&gt;</i><br></div><div>&lt;<i>spend-delay</i>&gt;</div><div>&lt;<i>target-outputs-hash</i>&gt;<br></div><div><b style="border-color: var(--border-color);">OP_UNVAULT</b><br></div>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="190" y="400" width="140" height="100" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-10" value="<b>Withdrawal transaction<br></b><br>[dynamically chosen target outputs]" style="rounded=1;whiteSpace=wrap;html=1;align=center;" parent="1" vertex="1"> + <mxGeometry x="190" y="567" width="140" height="73" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;" parent="1" source="b8DSxFJpJzC5LI19bmsF-13" target="b8DSxFJpJzC5LI19bmsF-1" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="b8DSxFJpJzC5LI19bmsF-13" value="" style="points=[[0.145,0.145,0],[0.5,0,0],[0.855,0.145,0],[1,0.5,0],[0.855,0.855,0],[0.5,1,0],[0.145,0.855,0],[0,0.5,0]];shape=mxgraph.bpmn.event;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;align=center;perimeter=ellipsePerimeter;outlineConnect=0;aspect=fixed;outline=standard;symbol=general;rounded=1;" parent="1" vertex="1"> + <mxGeometry x="245" y="200" width="30" height="30" as="geometry" /> + </mxCell> + <mxCell id="BqwL7Yf8YW1r5e_O7xE0-1" value="" style="shadow=0;dashed=0;html=1;strokeColor=none;fillColor=#4495D1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.veeam.time;" parent="1" vertex="1"> + <mxGeometry x="158" y="512" width="30" height="30" as="geometry" /> + </mxCell> + <mxCell id="BqwL7Yf8YW1r5e_O7xE0-2" value="" style="sketch=0;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;fillColor=#505050;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;outlineConnect=0;align=center;shape=mxgraph.office.security.key_permissions;" parent="1" vertex="1"> + <mxGeometry x="183" y="358" width="15" height="33" as="geometry" /> + </mxCell> + <mxCell id="oT6HpDHtKCBb9ui_6_kA-7" value="" style="endArrow=none;html=1;rounded=1;entryX=1;entryY=0.25;entryDx=0;entryDy=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" parent="1" source="b8DSxFJpJzC5LI19bmsF-1" target="b8DSxFJpJzC5LI19bmsF-1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="190" y="280" as="sourcePoint" /> + <mxPoint x="240" y="230" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="oT6HpDHtKCBb9ui_6_kA-8" value="" style="endArrow=none;html=1;rounded=1;entryX=1;entryY=0.25;entryDx=0;entryDy=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="190" y="427" as="sourcePoint" /> + <mxPoint x="330" y="427" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="oT6HpDHtKCBb9ui_6_kA-9" value="" style="endArrow=none;html=1;rounded=1;entryX=1;entryY=0.25;entryDx=0;entryDy=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="190" y="596" as="sourcePoint" /> + <mxPoint x="330" y="596" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="oT6HpDHtKCBb9ui_6_kA-10" value="" style="endArrow=none;html=1;rounded=1;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="443" y="446" as="sourcePoint" /> + <mxPoint x="573" y="446" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="LweIh1WkpCqs_c0vHIex-1" value="" style="endArrow=none;html=1;rounded=1;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="393" y="236" as="sourcePoint" /> + <mxPoint x="413" y="236" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="LweIh1WkpCqs_c0vHIex-2" value="Withdrawal path" style="text;strokeColor=none;align=left;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="415" y="221" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="LweIh1WkpCqs_c0vHIex-3" value="" style="endArrow=none;html=1;rounded=1;dashed=1;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="393" y="252" as="sourcePoint" /> + <mxPoint x="413" y="252" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="LweIh1WkpCqs_c0vHIex-4" value="Optional path" style="text;strokeColor=none;align=left;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="416" y="237" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="iAfIXZV-x1gRYHwice2W-2" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=default;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="359" y="449.76" as="sourcePoint" /> + <mxPoint x="369" y="449.76" as="targetPoint" /> + <Array as="points"> + <mxPoint x="359" y="449.76" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="iAfIXZV-x1gRYHwice2W-4" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=default;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="399" y="299.76" as="sourcePoint" /> + <mxPoint x="409" y="299.76" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="iAfIXZV-x1gRYHwice2W-5" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=default;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="150" y="440" as="sourcePoint" /> + <mxPoint x="140" y="440" as="targetPoint" /> + </mxGeometry> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="hQFg2SRqlWPJF2oUK6n1" name="Batch sweep"> + <mxGraphModel dx="1430" dy="1768" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="DGUraX8pYsX29eg1CZX8-1" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="636" y="415" width="138" height="160" as="geometry" /> + </mxCell> + <mxCell id="DGUraX8pYsX29eg1CZX8-2" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="DGUraX8pYsX29eg1CZX8-1" target="DGUraX8pYsX29eg1CZX8-1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="660" y="519.5" as="sourcePoint" /> + <mxPoint x="710" y="469.5" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="DGUraX8pYsX29eg1CZX8-3" value="<b style="background-color: initial;"><br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;" parent="1" vertex="1"> + <mxGeometry x="722" y="440" width="100" height="80" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-11" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="380" y="300" width="138" height="122" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-12" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="IMLKYxiTQTyD-2dyPs5i-11" target="IMLKYxiTQTyD-2dyPs5i-11" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="398" y="352" as="sourcePoint" /> + <mxPoint x="448" y="302" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-13" value="<b style="background-color: initial;"><br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;" parent="1" vertex="1"> + <mxGeometry x="460" y="313" width="100" height="83" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-16" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="400" y="499" width="115" height="138" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-17" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="435" y="637" as="sourcePoint" /> + <mxPoint x="435" y="499" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-18" value="<b style="background-color: initial;"><br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;" parent="1" vertex="1"> + <mxGeometry x="457" y="516" width="100" height="101" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-27" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="165" y="420" width="138" height="140" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-28" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="201" y="560" as="sourcePoint" /> + <mxPoint x="201" y="420" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-29" value="<b style="background-color: initial;"><br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;" parent="1" vertex="1"> + <mxGeometry x="230" y="437" width="100" height="101" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-30" value="<p style="line-height: 40%;"><b>scriptPubKey</b></p><p style="border-color: var(--border-color); line-height: 4.8px;"><i style="border-color: var(--border-color);"><b style="border-color: var(--border-color);"><font style="border-color: var(--border-color);" color="#0066cc">recov-hash&nbsp;</font><font style="border-color: var(--border-color);" color="#00060d">...</font></b>&nbsp;</i></p><p style="border-color: var(--border-color); line-height: 4.8px;">&nbsp; OP_VAULT</p><p style="line-height: 40%;"><b style="background-color: initial;">amount</b></p><p style="line-height: 40%;"><span style="background-color: initial;">a3</span></p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="1" vertex="1"> + <mxGeometry x="461" y="513.5" width="100" height="110" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-31" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="134" y="270" width="88" height="122" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-32" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="157" y="392" as="sourcePoint" /> + <mxPoint x="157" y="270" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-33" value="<b style="background-color: initial;"><br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;" parent="1" vertex="1"> + <mxGeometry x="180" y="282" width="100" height="101" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-34" value="<p style="line-height: 40%;"><b>scriptPubKey</b></p><p style="line-height: 40%;"><span style="background-color: initial;"><i><b style=""><font color="#0066cc">recov-hash </font><font color="#00060d">...</font></b>&nbsp;</i></span></p><p style="line-height: 40%;"><span style="background-color: initial;">&nbsp; OP_VAULT</span></p><p style="line-height: 120%;"><b>amount</b><br>a1</p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="1" vertex="1"> + <mxGeometry x="183" y="271" width="100" height="120" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" parent="1" source="IMLKYxiTQTyD-2dyPs5i-38" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="280" y="333" as="targetPoint" /> + <Array as="points"> + <mxPoint x="340" y="333" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-38" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="340" y="319" width="90" height="60" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-39" value="<p style="line-height: 40%;"><b>witness</b></p><p style="line-height: 40%;">[<i>trigger-key&nbsp;</i></p><p style="line-height: 40%;">&nbsp; signature]</p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="1" vertex="1"> + <mxGeometry x="353" y="310" width="90" height="80" as="geometry" /> + </mxCell> + <mxCell id="IMagvj_H5wSyhYbexlPS-2" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" target="IMLKYxiTQTyD-2dyPs5i-18" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="600" y="538" as="sourcePoint" /> + </mxGeometry> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-54" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" target="IMLKYxiTQTyD-2dyPs5i-13" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="600" y="448.5" as="sourcePoint" /> + <Array as="points"> + <mxPoint x="580" y="449" /> + <mxPoint x="580" y="355" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="IMagvj_H5wSyhYbexlPS-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.367;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitPerimeter=0;" parent="1" source="IMLKYxiTQTyD-2dyPs5i-43" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="600" y="491.5" as="sourcePoint" /> + <mxPoint x="330" y="486.5" as="targetPoint" /> + <Array as="points"> + <mxPoint x="600" y="487" /> + <mxPoint x="465" y="487" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-43" value="Script-path reveal" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="600" y="473" width="90" height="35" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-20" value="<p style="line-height: 40%;"><b>scriptPubKey</b></p><p style="border-color: var(--border-color); line-height: 4.8px;"><i style="border-color: var(--border-color);"><b style="border-color: var(--border-color);"><font style="border-color: var(--border-color);" color="#0066cc">recov-hash&nbsp;</font><font style="border-color: var(--border-color);" color="#00060d">...</font></b>&nbsp;</i></p><p style="border-color: var(--border-color); line-height: 4.8px;"><span style="border-color: var(--border-color); background-color: initial;">&nbsp; OP_VAULT</span></p><p style="line-height: 120%;"><b>amount</b><br>a2</p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="1" vertex="1"> + <mxGeometry x="233" y="430" width="100" height="120" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-53" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="465" y="307.5" width="120" height="95" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-15" value="<p style="line-height: 10%;"><b>scriptPubKey</b></p><p style="border-color: var(--border-color); line-height: 4.8px;"><i style="border-color: var(--border-color);"><b style="border-color: var(--border-color);"><font style="border-color: var(--border-color);" color="#0066cc">recov-hash&nbsp;</font><font style="border-color: var(--border-color);" color="#00060d">...</font></b>&nbsp;</i></p><p style="border-color: var(--border-color); line-height: 4.8px;"><span style="border-color: var(--border-color); background-color: initial;">&nbsp; OP_UNVAULT</span></p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="IMLKYxiTQTyD-2dyPs5i-53" vertex="1"> + <mxGeometry width="110" height="70" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-26" value="<p style="line-height: 10%;"><b>amount</b></p><p style="line-height: 10%;">a1</p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="IMLKYxiTQTyD-2dyPs5i-53" vertex="1"> + <mxGeometry y="45" width="70" height="50" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-60" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="730" y="438" width="100" height="82" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-58" value="<p style="line-height: 20%;"><b>scriptPubKey</b></p><p style="line-height: 20%;"><i>[recovery-spk]</i></p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="IMLKYxiTQTyD-2dyPs5i-60" vertex="1"> + <mxGeometry width="100" height="50" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-59" value="<p style="line-height: 10%;"><b>amount</b></p><p style="line-height: 10%;">a1 + a2 + a3</p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="IMLKYxiTQTyD-2dyPs5i-60" vertex="1"> + <mxGeometry y="32" width="90" height="50" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-61" value="<i>Ephemeral anchor</i>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;" parent="1" vertex="1"> + <mxGeometry x="723.5" y="527" width="97" height="35" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-62" value="Recovered to interrupt unvault" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontSize=17;" parent="1" vertex="1"> + <mxGeometry x="277" y="268.5" width="250" height="30" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-63" value="Recovered while still vaulted" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontSize=17;" parent="1" vertex="1"> + <mxGeometry x="139" y="571" width="240" height="30" as="geometry" /> + </mxCell> + <mxCell id="IMLKYxiTQTyD-2dyPs5i-64" value="Batch recovery" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontSize=17;" parent="1" vertex="1"> + <mxGeometry x="635" y="380.5" width="140" height="30" as="geometry" /> + </mxCell> + <mxCell id="IMagvj_H5wSyhYbexlPS-9" value="output" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="723" y="273" width="90" height="21" as="geometry" /> + </mxCell> + <mxCell id="IMagvj_H5wSyhYbexlPS-10" value="optional output" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;" parent="1" vertex="1"> + <mxGeometry x="723" y="302" width="90" height="21" as="geometry" /> + </mxCell> + <mxCell id="IMagvj_H5wSyhYbexlPS-11" value="input" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="723" y="332" width="90" height="22" as="geometry" /> + </mxCell> + <mxCell id="prdVbKwsFvf7KEGo0tpI-2" value="Script-path reveal" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="600" y="515" width="90" height="35" as="geometry" /> + </mxCell> + <mxCell id="T7j29g-1OFRtJtuNoE9x-1" value="Script-path reveal" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="600" y="434" width="90" height="35" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="x3-0X1WiPTrt-eOLsWqB" name="Recovery comparison"> + <mxGraphModel dx="1236" dy="1768" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-1" target="QagaKE3Mm4n1A5BtnNWS-2" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-1" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="120" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-2" target="QagaKE3Mm4n1A5BtnNWS-5" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-2" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="200" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-4" value="<div>Presigned</div><div>vault<br></div>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="180" y="200" width="80" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-5" target="QagaKE3Mm4n1A5BtnNWS-8" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-5" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="280" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-7" value="Unvault" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="265" y="205" width="70" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-8" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="360" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-10" value="To recovery" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="335" y="205" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-12" target="QagaKE3Mm4n1A5BtnNWS-14" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-12" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="120" y="299" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-14" target="QagaKE3Mm4n1A5BtnNWS-16" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-14" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="200" y="299" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-16" target="QagaKE3Mm4n1A5BtnNWS-17" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-16" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="280" y="299" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-17" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="360" y="299" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-21" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="240" y="260" width="40" height="60" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-18" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-21" vertex="1"> + <mxGeometry width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-19" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-21" vertex="1"> + <mxGeometry y="10" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-20" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-21" vertex="1"> + <mxGeometry y="20" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-22" value="<b>Precomputed vaults</b>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="210" y="168" width="140" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-24" target="QagaKE3Mm4n1A5BtnNWS-26" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-24" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="480" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-26" target="QagaKE3Mm4n1A5BtnNWS-29" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-26" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="560" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-27" value="<div>OP_VAULT</div>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="540" y="205" width="80" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-29" target="QagaKE3Mm4n1A5BtnNWS-31" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-29" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="640" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-30" value="OP_UNVAULT" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="615" y="205" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-31" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="720" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-32" value="To recovery" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="695" y="205" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-34" target="QagaKE3Mm4n1A5BtnNWS-36" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-34" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="480" y="299" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-36" target="QagaKE3Mm4n1A5BtnNWS-38" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-36" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="560" y="299" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-38" target="QagaKE3Mm4n1A5BtnNWS-31" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="720" y="342" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-38" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="640" y="299" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-40" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="600" y="260" width="40" height="60" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-41" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-40" vertex="1"> + <mxGeometry width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-42" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-40" vertex="1"> + <mxGeometry y="10" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-43" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-40" vertex="1"> + <mxGeometry y="20" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-44" value="<b>OP_VAULT</b>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="600" y="168" width="80" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-46" target="QagaKE3Mm4n1A5BtnNWS-48" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-46" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="120" y="449" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-48" target="QagaKE3Mm4n1A5BtnNWS-51" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-48" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="200" y="449" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-49" value="<div>Presigned</div><div>vault<br></div>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="180" y="409" width="80" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-51" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="280" y="449" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-52" value="To recovery" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="255" y="414" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-56" target="QagaKE3Mm4n1A5BtnNWS-58" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-56" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="120" y="503" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-58" target="QagaKE3Mm4n1A5BtnNWS-60" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-58" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="200" y="503" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-60" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="280" y="503" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-62" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="238" y="467" width="40" height="60" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-63" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-62" vertex="1"> + <mxGeometry width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-64" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-62" vertex="1"> + <mxGeometry y="10" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-65" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-62" vertex="1"> + <mxGeometry y="20" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-66" value="<b>Precomputed vaults</b>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="210" y="377" width="140" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-68" target="QagaKE3Mm4n1A5BtnNWS-70" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-68" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="480" y="449" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-70" target="QagaKE3Mm4n1A5BtnNWS-73" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-70" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="560" y="449" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-71" value="<div>OP_VAULT</div>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="540" y="412" width="80" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-73" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="640" y="449" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-76" value="To recovery" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="615" y="412" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-77" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-78" target="QagaKE3Mm4n1A5BtnNWS-80" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-78" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="480" y="503" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="QagaKE3Mm4n1A5BtnNWS-80" target="QagaKE3Mm4n1A5BtnNWS-73" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="640" y="551" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-80" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="560" y="503" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-83" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="517" y="468" width="40" height="60" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-84" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-83" vertex="1"> + <mxGeometry width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-85" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-83" vertex="1"> + <mxGeometry y="10" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-86" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="QagaKE3Mm4n1A5BtnNWS-83" vertex="1"> + <mxGeometry y="20" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="QagaKE3Mm4n1A5BtnNWS-87" value="<b>OP_VAULT</b>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="600" y="377" width="80" height="30" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="51t3zBxVp8Nxi1LOdNUq" name="Withdrawal comparison"> + <mxGraphModel dx="1430" dy="1768" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="ezkKjIhg79-38QoQ9XiY-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-2" target="ezkKjIhg79-38QoQ9XiY-4" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-2" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="120" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-4" target="ezkKjIhg79-38QoQ9XiY-7" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-4" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="190" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-5" value="<div>Presigned</div><div>vault<br></div>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="167" y="198" width="80" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-7" target="ezkKjIhg79-38QoQ9XiY-9" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-7" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="260" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-8" value="Unvault" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="243" y="202" width="70" height="30" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-78" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-9" target="ezkKjIhg79-38QoQ9XiY-77" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-9" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="335" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-10" value="<div>"Warm" <br></div><div>wallet<br></div>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="322" y="199" width="60" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-12" target="ezkKjIhg79-38QoQ9XiY-14" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-12" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="120" y="322" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-14" target="ezkKjIhg79-38QoQ9XiY-16" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-14" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="190" y="322" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-16" target="ezkKjIhg79-38QoQ9XiY-17" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-16" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="260" y="322" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-90" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontFamily=Helvetica;" parent="1" source="ezkKjIhg79-38QoQ9XiY-17" target="ezkKjIhg79-38QoQ9XiY-80" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-17" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="335" y="322" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-18" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="220" y="270" width="40" height="60" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-19" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="ezkKjIhg79-38QoQ9XiY-18" vertex="1"> + <mxGeometry width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-20" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="ezkKjIhg79-38QoQ9XiY-18" vertex="1"> + <mxGeometry y="10" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-21" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="ezkKjIhg79-38QoQ9XiY-18" vertex="1"> + <mxGeometry y="20" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-22" value="<b>Precomputed vaults</b>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1"> + <mxGeometry x="210" y="158" width="140" height="30" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-24" target="ezkKjIhg79-38QoQ9XiY-26" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-24" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="519" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-26" target="ezkKjIhg79-38QoQ9XiY-29" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-26" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="599" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-27" value="<div>OP_VAULT</div>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="579" y="203" width="80" height="30" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-29" target="ezkKjIhg79-38QoQ9XiY-31" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-89" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=0;fontFamily=Helvetica;" parent="1" target="ezkKjIhg79-38QoQ9XiY-83" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="740" y="260" as="sourcePoint" /> + </mxGeometry> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-29" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="690" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-31" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="769" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="ezkKjIhg79-38QoQ9XiY-34" target="ezkKjIhg79-38QoQ9XiY-36" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-34" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="519" y="322" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="ezkKjIhg79-38QoQ9XiY-36" target="ezkKjIhg79-38QoQ9XiY-29" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="660" y="260" as="targetPoint" /> + <Array as="points"> + <mxPoint x="660" y="342" /> + <mxPoint x="660" y="260" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-36" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="599" y="322" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-39" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="559" y="270" width="40" height="60" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-40" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="ezkKjIhg79-38QoQ9XiY-39" vertex="1"> + <mxGeometry width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-41" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="ezkKjIhg79-38QoQ9XiY-39" vertex="1"> + <mxGeometry y="10" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-42" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="ezkKjIhg79-38QoQ9XiY-39" vertex="1"> + <mxGeometry y="20" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-43" value="<b>OP_VAULT</b>" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="639" y="158" width="80" height="30" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-77" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="414" y="240" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-80" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="414" y="322" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-83" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="769" y="290" width="40" height="40" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-84" value="Targets" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Helvetica;" parent="1" vertex="1"> + <mxGeometry x="401" y="202" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="ezkKjIhg79-38QoQ9XiY-85" value="Targets" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Helvetica;" parent="1" vertex="1"> + <mxGeometry x="758" y="203" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="hU3LCPZSUflRbzsWwJJh-1" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1"> + <mxGeometry x="462" y="170" width="20" height="20" as="geometry" /> + </mxCell> + <mxCell id="hU3LCPZSUflRbzsWwJJh-2" value="=&nbsp; UTXO" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;" parent="1" vertex="1"> + <mxGeometry x="482" y="166" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="zbme-GfWksCJWwraIK2J-1" value=""Trigger"" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;fontFamily=Helvetica;" vertex="1" parent="1"> + <mxGeometry x="673" y="203" width="70" height="30" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="M-0T8bRLORY_nlIivCLq" name="Alt-vaults"> + <mxGraphModel dx="1236" dy="1160" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-1" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="-zpKa_FQ8lR9X4kw_iqW-5" target="-zpKa_FQ8lR9X4kw_iqW-9" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-2" value="<div>Sign with unvault key</div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="-zpKa_FQ8lR9X4kw_iqW-1" vertex="1" connectable="0"> + <mxGeometry x="-0.3102" y="-1" relative="1" as="geometry"> + <mxPoint x="1" y="6" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeColor=default;dashed=1;" parent="1" source="-zpKa_FQ8lR9X4kw_iqW-5" target="-zpKa_FQ8lR9X4kw_iqW-6" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-4" value="Reveal cold address" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="-zpKa_FQ8lR9X4kw_iqW-3" vertex="1" connectable="0"> + <mxGeometry x="-0.17" y="2" relative="1" as="geometry"> + <mxPoint x="6" y="-8" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-5" value="<div><b>OP_VAULT</b></div><div>&lt;<i>cold-addr-hash</i>&gt;</div><div>&lt;<i>spend-delay</i>&gt;</div><div>&lt;<i>unvault-pk</i>&gt;<br></div>" style="rounded=1;whiteSpace=wrap;html=1;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="1" vertex="1"> + <mxGeometry x="190" y="270" width="140" height="80" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-6" value="[recovery path]" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="460" y="285" width="120" height="50" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=default;" parent="1" source="-zpKa_FQ8lR9X4kw_iqW-9" target="-zpKa_FQ8lR9X4kw_iqW-10" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-8" value="<div>Wait <i>spend-delay</i> blocks <b>&amp;&amp;</b><br></div><div>outputs match target hash<br></div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="-zpKa_FQ8lR9X4kw_iqW-7" vertex="1" connectable="0"> + <mxGeometry x="-0.302" y="2" relative="1" as="geometry"> + <mxPoint y="5" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-9" value="<div><b>OP_UNVAULT</b></div><div>&lt;<i>cold-addr-hash</i>&gt;</div><div>&lt;<i>spend-delay</i>&gt;</div><div>&lt;<i>target-outputs-hash</i>&gt;<br></div>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="190" y="400" width="140" height="80" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-10" value="[arbitrary unvault target]" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="520" y="360" width="140" height="40" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;" parent="1" source="-zpKa_FQ8lR9X4kw_iqW-12" target="-zpKa_FQ8lR9X4kw_iqW-5" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-12" value="" style="points=[[0.145,0.145,0],[0.5,0,0],[0.855,0.145,0],[1,0.5,0],[0.855,0.855,0],[0.5,1,0],[0.145,0.855,0],[0,0.5,0]];shape=mxgraph.bpmn.event;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;align=center;perimeter=ellipsePerimeter;outlineConnect=0;aspect=fixed;outline=standard;symbol=general;rounded=1;" parent="1" vertex="1"> + <mxGeometry x="245" y="220" width="30" height="30" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-13" value="" style="shadow=0;dashed=0;html=1;strokeColor=none;fillColor=#4495D1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.veeam.time;" parent="1" vertex="1"> + <mxGeometry x="505" y="425" width="30" height="30" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-14" value="" style="sketch=0;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;fillColor=#505050;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;outlineConnect=0;align=center;shape=mxgraph.office.security.key_permissions;" parent="1" vertex="1"> + <mxGeometry x="170" y="360" width="15" height="33" as="geometry" /> + </mxCell> + <mxCell id="-zpKa_FQ8lR9X4kw_iqW-15" value="" style="endArrow=none;dashed=1;html=1;rounded=0;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="330" y="420" as="sourcePoint" /> + <mxPoint x="390" y="310" as="targetPoint" /> + <Array as="points"> + <mxPoint x="390" y="420" /> + </Array> + </mxGeometry> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="9IyR_zxcH8IqVGAvo76N" name="Basic"> + <mxGraphModel dx="1236" dy="1768" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="uh7-YCnJg2CyufrYdqnU-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" source="uh7-YCnJg2CyufrYdqnU-1" target="uh7-YCnJg2CyufrYdqnU-2" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="uh7-YCnJg2CyufrYdqnU-7" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" source="uh7-YCnJg2CyufrYdqnU-1" target="uh7-YCnJg2CyufrYdqnU-4" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="uh7-YCnJg2CyufrYdqnU-1" value="<div>User spends UTXO(s)<br></div><div>into vault<br></div>" style="rounded=1;whiteSpace=wrap;html=1;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" vertex="1"> + <mxGeometry x="90" y="310" width="140" height="60" as="geometry" /> + </mxCell> + <mxCell id="uh7-YCnJg2CyufrYdqnU-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" source="uh7-YCnJg2CyufrYdqnU-2" target="uh7-YCnJg2CyufrYdqnU-3" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="KdfuowOYJgZ3zCW8n2jm-2" value="<div>After some</div><div>delay<br></div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=1;points=[];movable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="uh7-YCnJg2CyufrYdqnU-6" vertex="1" connectable="0"> + <mxGeometry x="-0.2" y="-1" relative="1" as="geometry"> + <mxPoint x="15" y="-1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="uh7-YCnJg2CyufrYdqnU-10" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" source="uh7-YCnJg2CyufrYdqnU-2" target="uh7-YCnJg2CyufrYdqnU-4" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="uh7-YCnJg2CyufrYdqnU-2" value="<div>Unvault attempt<br></div><div>is triggered</div>" style="rounded=1;whiteSpace=wrap;html=1;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" vertex="1"> + <mxGeometry x="260" y="310" width="140" height="60" as="geometry" /> + </mxCell> + <mxCell id="uh7-YCnJg2CyufrYdqnU-3" value="<div>Withdrawal is finalized<br></div>" style="rounded=1;whiteSpace=wrap;html=1;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" vertex="1"> + <mxGeometry x="500" y="310" width="140" height="60" as="geometry" /> + </mxCell> + <mxCell id="uh7-YCnJg2CyufrYdqnU-4" value="<div>Vaulted coins <br></div><div>swept to prespecified</div><div>recovery path<br></div>" style="rounded=1;whiteSpace=wrap;html=1;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" vertex="1"> + <mxGeometry x="340" y="230" width="140" height="60" as="geometry" /> + </mxCell> + <mxCell id="KdfuowOYJgZ3zCW8n2jm-1" value="" style="shadow=0;dashed=0;html=1;strokeColor=none;fillColor=#4495D1;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.veeam.time;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" vertex="1"> + <mxGeometry x="446" y="360" width="20" height="20" as="geometry" /> + </mxCell> + <mxCell id="4beDPwlwmHm2dIG_X1VO-2" value="" style="endArrow=none;html=1;rounded=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="520" y="259" as="sourcePoint" /> + <mxPoint x="540" y="259" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="4beDPwlwmHm2dIG_X1VO-3" value="Expected path" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" vertex="1"> + <mxGeometry x="542" y="244" width="90" height="30" as="geometry" /> + </mxCell> + <mxCell id="4beDPwlwmHm2dIG_X1VO-4" value="" style="endArrow=none;html=1;rounded=1;dashed=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="520" y="275" as="sourcePoint" /> + <mxPoint x="540" y="275" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="4beDPwlwmHm2dIG_X1VO-5" value="Recovery path" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="1" vertex="1"> + <mxGeometry x="543" y="260" width="90" height="30" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="jRtaY6zHFwBRHzIYjIhC" name="Page-7"> + <mxGraphModel dx="2162" dy="1316" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-56" value="" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;strokeColor=#4D4D4D;fontFamily=Courier New;fontSize=20;" parent="1" vertex="1"> + <mxGeometry x="308" y="660" width="232" height="100" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-50" value="" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;strokeColor=#4D4D4D;fontFamily=Courier New;fontSize=20;" parent="1" vertex="1"> + <mxGeometry x="57" y="380" width="413" height="230" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-48" value="" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;strokeColor=#4D4D4D;fontFamily=Courier New;fontSize=20;" parent="1" vertex="1"> + <mxGeometry x="590" y="380" width="230" height="221" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-46" value="" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#4D4D4D;fontFamily=Courier New;fontSize=8;dashed=1;" parent="1" vertex="1"> + <mxGeometry x="182" y="102.5" width="509" height="183.5" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-19" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="445" y="169.5" width="120" height="100" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-2" value="&nbsp;[trigger auth]&nbsp;<i>&lt;spend-delay&gt;</i> 2 "OP_CSV OP_DROP OP_CTV" <b>OP_VAULT&nbsp;</b>" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#336600;" parent="1" vertex="1"> + <mxGeometry x="199" y="187.5" width="471" height="30" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-20" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="288" y="488" width="120" height="100" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-21" value="&nbsp;<i> <font color="#994c00">&lt;CTV-hash&gt;</font>&nbsp;&lt;spend-delay&gt;</i>&nbsp;OP_CSV OP_DROP OP_CTV&nbsp;" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#B01E1E;" parent="1" vertex="1"> + <mxGeometry x="80" y="508" width="380" height="30" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-22" value="[recovery auth]<i> &lt;recovery-sPK-hash&gt;</i> <b>OP_VAULT_RECOVER&nbsp;<br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#007FFF;" parent="1" vertex="1"> + <mxGeometry x="80" y="545" width="380" height="30" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-18" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.394;entryY=0.97;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Courier New;fontSize=22;" parent="1" source="Y65zMmu6unbP29DxbX5J-24" target="Y65zMmu6unbP29DxbX5J-25" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-24" value="<i>&lt;internal-pubkey&gt;</i>" style="rounded=1;whiteSpace=wrap;html=1;align=center;" parent="1" vertex="1"> + <mxGeometry x="139" y="483" width="120" height="16.5" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-25" value="TR" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="239" y="444.5" width="100" height="28.5" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-17" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontFamily=Courier New;fontSize=22;" parent="1" source="Y65zMmu6unbP29DxbX5J-26" target="Y65zMmu6unbP29DxbX5J-25" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-26" value="Tapleaves" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" parent="1" vertex="1"> + <mxGeometry x="290" y="481" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-27" value="<i>withdrawal</i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" parent="1" vertex="1"> + <mxGeometry x="80" y="499" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-28" value="<i>recover<br></i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" parent="1" vertex="1"> + <mxGeometry x="75" y="536" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-29" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=1;fontFamily=Courier New;fontSize=9;endWidth=7.5;endSize=4.325;strokeColor=#336600;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="310" y="300" as="sourcePoint" /> + <mxPoint x="263" y="366" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-30" value="script-path spend of <i style="font-size: 11px;"><font color="#336600" style="font-size: 11px;">trigger</font></i>&nbsp;leaf,<br style="font-size: 11px;">supplying <font color="#cc6600" style="font-size: 11px;">CTV hash </font>in witness,<br style="font-size: 11px;">satisfying trigger auth" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;" parent="1" vertex="1"> + <mxGeometry x="97" y="305" width="167" height="43" as="geometry" /> + </mxCell> + <mxCell id="Y65zMmu6unbP29DxbX5J-33" value="script-path spend of <i style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">recover</font></i>&nbsp;leaf, satisfying recovery authorization <br style="font-size: 11px;">script, if specified" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;" parent="1" vertex="1"> + <mxGeometry x="640" y="295.5" width="140" height="64" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-12" value="OP_VAULT allows templated replacement of its leaf during spend (green to red) - otherwise taptree unchanged" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=10;fontStyle=0" parent="1" vertex="1"> + <mxGeometry x="251" y="398" width="202" height="30" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-13" value="" style="endArrow=classic;html=1;rounded=1;fontFamily=Courier New;fontSize=22;strokeColor=#007FFF;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="570" y="300" as="sourcePoint" /> + <mxPoint x="642" y="360" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-21" value="&nbsp;[recovery auth] <i>&lt;recovery-sPK-hash&gt;</i> <b>OP_VAULT_RECOVER&nbsp;<br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#007FFF;" parent="1" vertex="1"> + <mxGeometry x="199" y="226.5" width="471" height="30" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-22" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.394;entryY=0.97;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Courier New;fontSize=22;" parent="1" source="nh3bwgDFfLlpKYWmzqJt-23" target="nh3bwgDFfLlpKYWmzqJt-24" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-23" value="<i>&lt;internal-pubkey&gt;</i>" style="rounded=1;whiteSpace=wrap;html=1;align=center;" parent="1" vertex="1"> + <mxGeometry x="289" y="164.5" width="120" height="16.5" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-24" value="TR" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1"> + <mxGeometry x="389" y="126" width="100" height="28.5" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-26" value="Tapleaves" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" parent="1" vertex="1"> + <mxGeometry x="444" y="162.5" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-27" value="<i>trigger</i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" parent="1" vertex="1"> + <mxGeometry x="188" y="180.5" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-28" value="<i>recover<br></i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" parent="1" vertex="1"> + <mxGeometry x="191" y="217.5" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-29" value="1" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=8;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="444" y="139.5" width="12" height="10" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-30" value="2" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=8;fontFamily=Courier New;" parent="1" vertex="1"> + <mxGeometry x="270" y="449" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-37" value="<p style="border-color: var(--border-color); line-height: 2.4px;"><i style="border-color: var(--border-color);"><font style="border-color: var(--border-color);" color="#cc6600">[transaction</font></i><i style="background-color: initial; border-color: var(--border-color);"><font style="border-color: var(--border-color);" color="#cc6600">&nbsp;satisfying&nbsp;</font></i></p><p style="border-color: var(--border-color); line-height: 2.4px;"><i style="border-color: var(--border-color);"><font style="border-color: var(--border-color);" color="#cc6600">&nbsp; CTV hash]</font></i></p>" style="rounded=1;whiteSpace=wrap;html=1;align=center;" parent="1" vertex="1"> + <mxGeometry x="339" y="695" width="171" height="50" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-43" value="" style="endArrow=classic;html=1;rounded=1;fontFamily=Courier New;fontSize=22;strokeColor=#CC0000;fontColor=#CC0000;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="266" y="620" as="sourcePoint" /> + <mxPoint x="300" y="660" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-44" value="timelocked CTV spend to predefined destination" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;" parent="1" vertex="1"> + <mxGeometry x="150" y="654" width="120" height="40" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-47" value="1. initial vault" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=2;fontColor=#808080;" parent="1" vertex="1"> + <mxGeometry x="199.5" y="104.5" width="131" height="28" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-49" value="recovery" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=2;fontColor=#808080;" parent="1" vertex="1"> + <mxGeometry x="688" y="378" width="131" height="28" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-51" value="2. trigger" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=2;fontColor=#808080;" parent="1" vertex="1"> + <mxGeometry x="50" y="380.5" width="131" height="28" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-52" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;fontFamily=Courier New;fontSize=20;" parent="1" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="565.0000000000002" y="340" as="sourcePoint" /> + <mxPoint x="565.0000000000002" y="340" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-53" value="" style="group" parent="1" vertex="1" connectable="0"> + <mxGeometry x="610" y="418.5" width="210" height="160" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-1" value="" style="rounded=1;whiteSpace=wrap;html=1;" parent="nh3bwgDFfLlpKYWmzqJt-53" vertex="1"> + <mxGeometry x="22.105263157894736" width="127.10526315789473" height="160" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-3" value="<b style="background-color: initial;"><br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;" parent="nh3bwgDFfLlpKYWmzqJt-53" vertex="1"> + <mxGeometry x="101.31578947368422" y="14" width="92.10526315789473" height="80" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-5" value="" style="group;fontSize=9;" parent="nh3bwgDFfLlpKYWmzqJt-53" vertex="1" connectable="0"> + <mxGeometry x="105.6842105263158" y="14" width="101.31578947368422" height="82" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-6" value="<p style="line-height: 20%; font-size: 11px;"><b style=""><font style="font-size: 11px;">scriptPubKey</font></b></p><p style="line-height: 20%; font-size: 11px;"><i style=""><font style="font-size: 11px;">[recovery-spk]</font></i></p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="nh3bwgDFfLlpKYWmzqJt-5" vertex="1"> + <mxGeometry x="-2" width="100" height="50" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-7" value="<p style="line-height: 10%; font-size: 11px;"><b style=""><font style="font-size: 11px;">amount</font></b></p><p style="line-height: 10%; font-size: 11px;"><font style="font-size: 11px;"><i>[full vault amount]</i></font></p>" style="text;html=1;resizable=0;autosize=1;align=left;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;dashed=1;" parent="nh3bwgDFfLlpKYWmzqJt-5" vertex="1"> + <mxGeometry x="-2" y="32" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-8" value="<i><font style="font-size: 11px;">Ephemeral anchor</font></i>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;" parent="nh3bwgDFfLlpKYWmzqJt-53" vertex="1"> + <mxGeometry x="102.69736842105263" y="107" width="89.34210526315789" height="35" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-11" value="Script-path reveal" style="rounded=0;whiteSpace=wrap;html=1;fontSize=10;" parent="nh3bwgDFfLlpKYWmzqJt-53" vertex="1"> + <mxGeometry y="30" width="64.47368421052632" height="35" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-2" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="nh3bwgDFfLlpKYWmzqJt-53" source="nh3bwgDFfLlpKYWmzqJt-1" target="nh3bwgDFfLlpKYWmzqJt-1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="540.6578947368422" y="505" as="sourcePoint" /> + <mxPoint x="586.7105263157895" y="455" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-57" value="3. withdrawal" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=2;fontColor=#808080;" parent="1" vertex="1"> + <mxGeometry x="395" y="660" width="131" height="28" as="geometry" /> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-61" value="" style="endArrow=classic;html=1;rounded=1;strokeColor=#000000;fontFamily=Courier New;fontSize=11;fontColor=#808080;exitX=0.098;exitY=-0.004;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.663;entryY=0.984;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="nh3bwgDFfLlpKYWmzqJt-19" target="nh3bwgDFfLlpKYWmzqJt-24" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="446.5" y="176" as="sourcePoint" /> + <mxPoint x="496.5" y="126" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nh3bwgDFfLlpKYWmzqJt-62" value="" style="endArrow=classic;html=1;rounded=1;fontFamily=Courier New;fontSize=22;strokeColor=#007FFF;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="490" y="440" as="sourcePoint" /> + <mxPoint x="570" y="440" as="targetPoint" /> + </mxGeometry> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="gvPKSLqK7s9hnQgXeOr3" name="Page-8"> + <mxGraphModel dx="547" dy="897" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="IdHh1SD0108lOCAqlYyb-2" value="" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;strokeColor=#4D4D4D;fontFamily=Courier New;fontSize=20;" vertex="1" parent="1"> + <mxGeometry x="223" y="387" width="427" height="230" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-4" value="" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#4D4D4D;fontFamily=Courier New;fontSize=8;dashed=1;" vertex="1" parent="1"> + <mxGeometry x="182" y="102.5" width="509" height="183.5" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-48" value="" style="endArrow=classic;html=1;rounded=1;strokeColor=#000000;fontFamily=Courier New;fontSize=11;fontColor=#808080;entryX=0.544;entryY=1.002;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.1;exitY=0.583;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="IdHh1SD0108lOCAqlYyb-26" target="IdHh1SD0108lOCAqlYyb-25"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="450" y="178" as="sourcePoint" /> + <mxPoint x="496.5" y="126" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-5" value="" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="445" y="169.5" width="120" height="100" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-6" value="&nbsp;[trigger auth]&nbsp;<i>&lt;spend-delay&gt;</i> 2 "OP_CSV OP_DROP OP_CTV" <b>OP_VAULT&nbsp;</b>" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#336600;" vertex="1" parent="1"> + <mxGeometry x="199" y="187.5" width="471" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-7" value="" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="454" y="495" width="120" height="100" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-8" value="&nbsp;<i> <font color="#994c00">&lt;CTV-hash&gt;</font>&nbsp;&lt;spend-delay&gt;</i>&nbsp;OP_CSV OP_DROP OP_CTV&nbsp;" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#B01E1E;" vertex="1" parent="1"> + <mxGeometry x="240" y="515" width="386" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-9" value="[recovery auth]<i> &lt;recovery-sPK-hash&gt;</i> <b>OP_VAULT_RECOVER&nbsp;<br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#007FFF;" vertex="1" parent="1"> + <mxGeometry x="240" y="552" width="386" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-10" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.394;entryY=0.97;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Courier New;fontSize=22;" edge="1" parent="1" source="IdHh1SD0108lOCAqlYyb-11" target="IdHh1SD0108lOCAqlYyb-12"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-11" value="<i>&lt;internal-pubkey&gt;</i>" style="rounded=1;whiteSpace=wrap;html=1;align=center;" vertex="1" parent="1"> + <mxGeometry x="305" y="490" width="120" height="16.5" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-12" value="TR" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="405" y="451.5" width="100" height="28.5" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-13" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontFamily=Courier New;fontSize=22;" edge="1" parent="1" source="IdHh1SD0108lOCAqlYyb-14" target="IdHh1SD0108lOCAqlYyb-12"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-14" value="Tapleaves" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" vertex="1" parent="1"> + <mxGeometry x="456" y="488" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-15" value="<i>withdrawal</i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" vertex="1" parent="1"> + <mxGeometry x="239" y="506" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-16" value="<i>recover<br></i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" vertex="1" parent="1"> + <mxGeometry x="235" y="543" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-17" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=1;fontFamily=Courier New;fontSize=9;endWidth=7.5;endSize=4.325;strokeColor=#336600;" edge="1" parent="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="438" y="301" as="sourcePoint" /> + <mxPoint x="438" y="371" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-18" value="script-path spend of <i style="font-size: 11px;"><font color="#336600" style="font-size: 11px;">trigger</font></i>&nbsp;leaf,<br style="font-size: 11px;">supplying <font color="#cc6600" style="font-size: 11px;">CTV hash </font>in witness,<br style="font-size: 11px;">satisfying trigger auth" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;" vertex="1" parent="1"> + <mxGeometry x="248" y="310" width="167" height="43" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-20" value="OP_VAULT allows templated replacement of its leaf during spend (green to red) - otherwise taptree unchanged" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=10;fontStyle=0" vertex="1" parent="1"> + <mxGeometry x="417" y="405" width="202" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-22" value="&nbsp;[recovery auth] <i>&lt;recovery-sPK-hash&gt;</i> <b>OP_VAULT_RECOVER&nbsp;<br></b>" style="rounded=1;whiteSpace=wrap;html=1;align=right;fontFamily=Courier New;verticalAlign=bottom;strokeColor=#007FFF;" vertex="1" parent="1"> + <mxGeometry x="199" y="226.5" width="471" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-23" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.394;entryY=0.97;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Courier New;fontSize=22;" edge="1" parent="1" source="IdHh1SD0108lOCAqlYyb-24" target="IdHh1SD0108lOCAqlYyb-25"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-24" value="<i>&lt;internal-pubkey&gt;</i>" style="rounded=1;whiteSpace=wrap;html=1;align=center;" vertex="1" parent="1"> + <mxGeometry x="289" y="164.5" width="120" height="16.5" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-25" value="TR" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="389" y="126" width="100" height="28.5" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-26" value="Tapleaves" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" vertex="1" parent="1"> + <mxGeometry x="444" y="162.5" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-27" value="<i>trigger</i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" vertex="1" parent="1"> + <mxGeometry x="188" y="180.5" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-28" value="<i>recover<br></i>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=9;" vertex="1" parent="1"> + <mxGeometry x="191" y="217.5" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-29" value="1" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=8;fontFamily=Courier New;" vertex="1" parent="1"> + <mxGeometry x="444" y="139.5" width="12" height="10" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-30" value="2" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=8;fontFamily=Courier New;" vertex="1" parent="1"> + <mxGeometry x="436" y="456" width="60" height="30" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-34" value="1. initial vault" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=2;fontColor=#808080;" vertex="1" parent="1"> + <mxGeometry x="199.5" y="104.5" width="131" height="28" as="geometry" /> + </mxCell> + <mxCell id="IdHh1SD0108lOCAqlYyb-36" value="2. trigger" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=2;fontColor=#808080;" vertex="1" parent="1"> + <mxGeometry x="216" y="389.5" width="131" height="28" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> +</mxfile> diff --git a/bip-0345/withdrawal-comparison.drawio.png b/bip-0345/withdrawal-comparison.drawio.png Binary files differnew file mode 100644 index 0000000..8a76d20 --- /dev/null +++ b/bip-0345/withdrawal-comparison.drawio.png diff --git a/bip-0380.mediawiki b/bip-0380.mediawiki index 4e73b5f..27b7908 100644 --- a/bip-0380.mediawiki +++ b/bip-0380.mediawiki @@ -26,7 +26,7 @@ This BIP is licensed under the BSD 2-clause license. Bitcoin wallets traditionally have stored a set of keys which are later serialized and mutated to produce the output scripts that the wallet watches and the addresses it provides to users. Typically backups have consisted of solely the private keys, nowadays primarily in the form of BIP 39 mnemonics. -However this backup solution is insuffient, especially since the introduction of Segregated Witness which added new output types. +However this backup solution is insufficient, especially since the introduction of Segregated Witness which added new output types. Given just the private keys, it is not possible for restored wallets to know which kinds of output scripts and addresses to produce. This has lead to incompatibilities between wallets when restoring a backup or exporting data for a watch only wallet. @@ -238,19 +238,19 @@ Valid expressions: * Extended private key with hardened derivation and children: <tt>xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/3h/4h/5h/*h</tt> * Extended private key with key origin, hardened derivation and children: <tt>[deadbeef/0h/1h/2]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/3h/4h/5h/*h</tt> -Invalid expressiosn: +Invalid expression: * Children indicator in key origin: <tt>[deadbeef/0h/0h/0h/*]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> * Trailing slash in key origin: <tt>[deadbeef/0h/0h/0h/]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> * Too short fingerprint: <tt>[deadbef/0h/0h/0h]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> * Too long fingerprint: <tt>[deadbeeef/0h/0h/0h]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> -* Invalid hardened indicators: <tt>[deadbeeef/0f/0f/0f]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> -* Invalid hardened indicators: <tt>[deadbeeef/0H/0H/0H]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> -* Invalid hardened indicators: <tt>[deadbeeef/-0/-0/-0]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> +* Invalid hardened indicators: <tt>[deadbeef/0f/0f/0f]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> +* Invalid hardened indicators: <tt>[deadbeef/0H/0H/0H]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> +* Invalid hardened indicators: <tt>[deadbeef/-0/-0/-0]0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600</tt> * Private key with derivation: <tt>L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1/0</tt> * Private key with derivation children: <tt>L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1/*</tt> -* Derivation index out of range: <tt>xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648</tt> -* Invalid derivation index: <tt>xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1aa</tt> +* Derivation index out of range: <tt>xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648</tt> +* Invalid derivation index: <tt>xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa</tt> * Multiple key origins: <tt>[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0</tt> * Missing key origin start: <tt>aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0</tt> * Non hex fingerprint: <tt>[gaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0</tt> diff --git a/bip-0381.mediawiki b/bip-0381.mediawiki index 4b94278..bfda2c8 100644 --- a/bip-0381.mediawiki +++ b/bip-0381.mediawiki @@ -100,8 +100,6 @@ Valid descriptors followed by the scripts they produce. Descriptors involving de ** <tt>a9141a31ad23bf49c247dd531a623c2ef57da3c400c587</tt> * <tt>pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)</tt> ** <tt>76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac</tt> -* <tt>pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)</tt> -** <tt>76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac</tt> * <tt>pkh([bd16bee5/2147483647h]xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)</tt> ** <tt>76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac</tt> * <tt>pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)</tt> diff --git a/bip-0382.mediawiki b/bip-0382.mediawiki index 942f62c..bb1951d 100644 --- a/bip-0382.mediawiki +++ b/bip-0382.mediawiki @@ -73,7 +73,7 @@ Valid descriptors followed by the scripts they produce. Descriptors involving de ** <tt>a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87</tt> ** <tt>a914bed59fc0024fae941d6e20a3b44a109ae740129287</tt> ** <tt>a9148483aa1116eb9c05c482a72bada4b1db24af654387</tt> -* <tt>sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))</tt> +* <tt>sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*h))</tt> ** <tt>a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87</tt> ** <tt>a914bed59fc0024fae941d6e20a3b44a109ae740129287</tt> ** <tt>a9148483aa1116eb9c05c482a72bada4b1db24af654387</tt> diff --git a/bip-0384.mediawiki b/bip-0384.mediawiki index 02d6f76..ba12b55 100644 --- a/bip-0384.mediawiki +++ b/bip-0384.mediawiki @@ -55,7 +55,7 @@ Valid descriptors followed by the scripts they produce. Descriptors involving de *** <tt>2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac</tt> *** <tt>76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac</tt> *** <tt>0014f90e3178ca25f2c808dc76624032d352fdbdfaf2</tt> -*** <tt>a91473e39884cb71ae4e5ac9739e9225026c99763e6687</tt> +*** <tt>a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087</tt> ** Child 1 *** <tt>21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac</tt> *** <tt>76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac</tt> |