diff options
author | Bryan Bishop <kanzure@gmail.com> | 2019-08-07 08:48:06 -0500 |
---|---|---|
committer | bitcoindev <bitcoindev@gnusha.org> | 2019-08-07 13:50:13 +0000 |
commit | 459a43cb38425b24e606afe761180987b640c543 (patch) | |
tree | 2151c9583d9240f23a831b208c6c82a43b2b0a01 | |
parent | 2f58b7726aca710d266b7f1f0bb1c58a798f91eb (diff) | |
download | pi-bitcoindev-459a43cb38425b24e606afe761180987b640c543.tar.gz pi-bitcoindev-459a43cb38425b24e606afe761180987b640c543.zip |
[bitcoin-dev] Bitcoin vaults with anti-theft recovery/clawback mechanisms
-rw-r--r-- | 18/faab9bf320f157a2d938d0a89e511cf729a297 | 543 |
1 files changed, 543 insertions, 0 deletions
diff --git a/18/faab9bf320f157a2d938d0a89e511cf729a297 b/18/faab9bf320f157a2d938d0a89e511cf729a297 new file mode 100644 index 000000000..2f58e1e68 --- /dev/null +++ b/18/faab9bf320f157a2d938d0a89e511cf729a297 @@ -0,0 +1,543 @@ +Return-Path: <kanzure@gmail.com> +Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org + [172.17.192.35]) + by mail.linuxfoundation.org (Postfix) with ESMTPS id 13A32D4B + for <bitcoin-dev@lists.linuxfoundation.org>; + Wed, 7 Aug 2019 13:50:13 +0000 (UTC) +X-Greylist: whitelisted by SQLgrey-1.7.6 +Received: from mail-vs1-f48.google.com (mail-vs1-f48.google.com + [209.85.217.48]) + by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 272E77D2 + for <bitcoin-dev@lists.linuxfoundation.org>; + Wed, 7 Aug 2019 13:50:11 +0000 (UTC) +Received: by mail-vs1-f48.google.com with SMTP id k9so60673936vso.5 + for <bitcoin-dev@lists.linuxfoundation.org>; + Wed, 07 Aug 2019 06:50:11 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; + h=mime-version:from:date:message-id:subject:to; + bh=Yv885FP/0NT69WBrbIRFQQhVdM5+gbLsjmn2tdPlcgA=; + b=gZYYIX4tlLidpDV/E+KnZzoyULaVpfVhDbWiNO+Uk9i3L0FT6NqFJYh83ffZKMN7S5 + wB8IRcLeOlTtRO5bNMV2ZmDAXzxJ9Fo3TLx25aTvcS0wyNvfRws629IkqnxA2mFi6Wsb + Iio3BwFAlJXww8zpq9izSZsez3e0Bz0Fm1/5LuG2qMFBFUbUO2KEnzSdmd0rkEXPu1Yz + YzYwvNva1G3z8gUUDw69qwotJRyYs0MDRje+c/gHxqbnhSgs6Zc1/kI6c+C6MxYDeZO2 + 0gybmsd51tWv475gjvqfy7V4kOwxGPjnsroDbnHkKY2ATIIDL/XxI90hj1CARezbyiXw + pqNg== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:mime-version:from:date:message-id:subject:to; + bh=Yv885FP/0NT69WBrbIRFQQhVdM5+gbLsjmn2tdPlcgA=; + b=kK2q0vi0XtYRO3wLMZDMvnw4Ms5wEo/bh3uj8/mm8n9QntmPCNw9ub7BnqTKWRJqYf + lmC4VcDVFgfllYSq8kNCnxkrJH4l8I6/KeNh3kSmgOmAvNqEfG5Rd5z0jBM7Rhe0SGg7 + x5zmQAxebHynzwx6fDSHiViPDhEPLIkC1qHQ8tP8jm+UfTBYiyIm/rNZVu5C0eHLY2EX + Y2OR6YxiupzEIuWMBtOG3Ni89bFFr7VE4tSryih6mr/WTLawD4mkFRGKGMm/InJV68b2 + 6I5mLZ0AaIEVUH5+SaltSlJ67IVsH6YRQhQY6Ys0Udj3/5a9HhjcO4v8A8mehu92xWXU + PiAA== +X-Gm-Message-State: APjAAAU/+hhRZUqqGdIzMZFA7ZL1Is7xCEVSiiCyXO76wKaCyAYKrkto + zuUwZXUF2ZtPi2g0KVN9ph4L9eIx+aPX8RZAwdyDXZJH +X-Google-Smtp-Source: APXvYqw2F38t/qvkqgYGg8klb2A/991hqLl4bUK8sEGZvJyMCKDHQLR3Qqixp8zX2P/fsP4wlkmSMk+49Lj/O+JFlRs= +X-Received: by 2002:a67:ee01:: with SMTP id f1mr6134634vsp.3.1565185809617; + Wed, 07 Aug 2019 06:50:09 -0700 (PDT) +MIME-Version: 1.0 +From: Bryan Bishop <kanzure@gmail.com> +Date: Wed, 7 Aug 2019 08:48:06 -0500 +Message-ID: <CABaSBawe_oF_zoso2RQBX+7OWDoCwC7T2MeKSX9fYRUQaY_xmg@mail.gmail.com> +To: Bitcoin Dev <bitcoin-dev@lists.linuxfoundation.org>, + Bryan Bishop <kanzure@gmail.com> +Content-Type: text/plain; charset="UTF-8" +X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, + DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, + RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 +X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on + smtp1.linux-foundation.org +X-Mailman-Approved-At: Wed, 07 Aug 2019 13:52:30 +0000 +Subject: [bitcoin-dev] Bitcoin vaults with anti-theft recovery/clawback + mechanisms +X-BeenThere: bitcoin-dev@lists.linuxfoundation.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: Bitcoin Protocol Discussion <bitcoin-dev.lists.linuxfoundation.org> +List-Unsubscribe: <https://lists.linuxfoundation.org/mailman/options/bitcoin-dev>, + <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=unsubscribe> +List-Archive: <http://lists.linuxfoundation.org/pipermail/bitcoin-dev/> +List-Post: <mailto:bitcoin-dev@lists.linuxfoundation.org> +List-Help: <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=help> +List-Subscribe: <https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev>, + <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=subscribe> +X-List-Received-Date: Wed, 07 Aug 2019 13:50:13 -0000 + +Hi, + +I have a proposal for implementing bitcoin vaults in a way that does not +require any soft-forks or other software upgrades, although it could benefit +from SIGHASH_NOINPUT which I'll describe later. + +I call them pre-signed vaults. + +Vault definition +================ + +Here, a vault is defined as a transaction setup scheme that binds both the user +and the attacker to always using a public observation and delay period before a +weakly-secured hot key is allowed to arbitrarily spend coins. This is the same +definition previously used[1]. During the delay period, there is an opportunity +to initiate recovery/clawback which can either trigger deeper cold storage +parameters or at least reset the delay period to start over again for the same +keys. + +One of the important components of this is the delete-the-key pre-signed +transaction concept, where only a single transaction is (pre)signed before +deleting the key. This is basically an emulation of a covenant and enforces a +certain outcome. + +Background and motivation +========================= + +I was looking at Eyal and Sirer's 2016 vaults paper [1], and I saw this +headscratcher: + +> Vault transactions use a delay mechanism. We note that vault transactions +> cannot be implemented with existing timing mechanisms such as +> CHECKLOCKTIMEVERIFY opcode or transaction locktime. + +This was probably written before the introduction of OP_CHECKSEQUENCEVERIFY. +Still, a viable construction would have more steps than just using OP_CSV. They +were probably not thinking about what those steps might be, because in the +context of the paper they were proposing a bitcoin vault implemented using +recursive consensus-enforced covenants via a new opcode, which obviously cannot +be deployed without an upgrade fork. Covenants have been discussed for years, +but require new opcodes or other consensus-enforcement changes. + +Relative locktimes are useful here because there is no knowledge as to when the +transactions might be broadcasted in the future. The delays need to be relative +to after the transaction is included in the blockchain, not to setup +initialization time. + +Also, from [2]: + +> We show that a [vault transaction] mechanism is currently not possible in all +> cryptocurrencies [...] Bitcoin's scripting language requires support for +> covenants. + +I haven't seen any previous proposal for how to implement recursive bitcoin +vaults without a fork and without a covenant. After asking around, I am pretty +sure this is somewhat novel. The closest I guess is [3]. + +Vaults are particularly interesting as a bitcoin cold storage security +mechanism because they enable a publicly observable delay period during which +time a user could be alerted by a watchtower that a thief might be in the +process of stealing their coins, and then the user may take some actions to +place the coins back into the vault before the relative timelock expires. There +seems to be no way to get this notification or observation period without a +vault construction. It might have been assumed it required a covenant. + +Having a vault construction might go a long way to discourage would-be +attackers, on principle that the attacker might be incapable of recovering +their cost-of-attack because the recovery mechanism can lock up the coins +indefinitely. Griefing or denial-of-service would still be possible, of course, +but with multisig there might be some ways to put a halt to that as well. I am +working under the assumption that the attacker knows that the user is a vault +user. + +Vaults +====== + +The idea is to have a sequence of pre-generated pre-signed transactions that +are generated in a certain way. The basic components are a vaulting transaction +that locks coins into a vault, a delayed-spend transaction which is the only +way to spend from a vault, and a re-vaulting transaction which can +recover/clawback coins from the delayed-spend transaction. The security of this +scheme is enforced by pre-signing transactions and deleting private keys, or +with the help of SIGHASH_NOINPUT then there's another scheme where private keys +are provably never known. This enforces that there's only a specific set of +possible outcomes at every step of the vault. + +Some examples of what the set of broadcasted transactions might look like in +regular usage: + + coins -> VT -> DST -> exit via hot wallet key + coins -> VT -> DST -> RVT + coins -> VT -> DST -> RVT -> DST -> ... + coins -> VT -> ... -> RVT998 -> nuclear abort + +where: + VT = vault transaction + DST = delayed-spend transaction + RVT = re-vaulting transaction + +The delayed-spending transaction would have a single output with a script like: +( + 30 days AND hot wallet key + OR 10 days AND re-vaulting public key + OR 1 day AND 4-of-7 multisig + OR 0 days and super-secure nuclear abort ragequit key +) + +Another diagram: + + VT_100 -> DST -> (optionally) RVT -> coins are now in VT_99 + VT_99 -> DST -> (optionally) RVT -> coins are now in VT_98 + ... + VT_1 -> burn-all-coins nuclear abort ragequit (final) + +Definitions +=========== + +Transactions and components: + +* Commitment/funding vault setup transaction. Signed after setting up the +transaction tree, and it is broadcasted whenever funds are to be placed into +the vault. + +* Delayed-spend transaction. Signed during the vault transaction tree setup, +and it is broadcasted when the user wants to withdraw coins from cold storage +or otherwise manipulate the coins. The output script template used by the +delayed-spend transaction was defined earlier. + +* Hot wallet key: Somewhat insecure key. This can also be multisig using +multiple hot keys. + +* Re-vaulting key: It is important to note that the private key either never +existed (SIGHASH_NOINPUT + P2WPK for the re-vaulting transaction) or the +private key was deleted after pre-signing the re-vaulting transaction. + +* 4-of-7 multisig: This is a group of differently-motivated individuals who are +responsible for signing transactions. This multisig group is not necessry to +describe the technique, I just think it's a useful feature for a vault to +include. + +* Nuclear abort key: Also unnecessary. This is a key for which only a single +signed transaction will ever exist, and that single transaction will spend to a +proof-of-burn key like 0x00. This key must be extremely secure, and if there +is any doubt about the ability to keep such a key secured, then it is better to +not include this in the protocol. Alternatively, maybe include it as an option +50 layers down in the revaulting sequence. + +* Nuclear-abort pre-signed transaction. This is signed during transaction tree +setup, before constructing the delayed-spend transaction. It is broadcasted +only if the user wants to provably relinquish coins forever without giving the +attacker any coins. + +* Re-vaulting transaction. This is where the magic happens. The re-vaulting +transaction is signed during transaction tree setup, before constructing the +delayed-spend transaction for the parent vault. The re-vaulting transaction is +broadcasted when someone wants to prevent a coin withdrawal during the public +observation delay period. The re-vaulting transaction spends the delayed-spend +transaction outputs. It has a single output with a script created by running +the entire vault setup function again. Hence, when the re-vaulting transaction +is confirmed, all of the coins go back into a new identically-configured vault +instead of being relinquished through the delayed-spend transaction timeout for +hot wallet key signing. + +* Special case: final transaction. This is the very first pre-signed +transaction during setup, and the transaction spends the coins using any +provable burn technique. This is broadcasted only at the end of the game, as an +ultimate abort and forfeiture of coins without giving in to an adversary. It's +similar to the nuclear-abort ragequit transaction but it sits at the same place +that a delayed-spend transaction would, at the very end of the rainbow or +yellow brick road. + +Example log during vault setup +============================== + +When running the recursive vault setup function, the created artifacts (in +order) will look like: + +1) choose one of: + (first iteration) pre-signed burn-all-coins nuclear abort ragequit (final) + (all others) a new vault setup transaction spendable only by its + delayed-spend transaction + +2) pre-signed re-vaulting transaction sending to vault setup or final +transaction, with a unique private key + +3) pre-signed delayed-spend transaction, with a unique private key + +4) vault transaction spendable only by the delayed-spend public key + +Pseudocode +========== + +In pseudocode (where PTX is a pre-signed transaction function with +private key deletion): + + VT(counter, *args, **kwargs) = + if counter == 0: + DST = PTX("burn-all-coins") + else: + next_vault = VT(counter-1, *args, **kwargs) + revaulting = PTX("only spendable by next_vault public key") + DST = PTX("DST policy including revaulting and other conditions") + vault = PTX("spendable only by this DST") + return vault + +Pre-signed transactions +======================= + +What has been known for a while is that a covenant can be somewhat emulated +using a pre-signed transaction where the user then deletes the private key, +enforcing that the user's chosen policy must be enforced since there is only +one existing option and there will only ever be one option. + +Such a scheme has been previously described for simple one-time and chained +vaults [3]. I have learned that the author has an implementation that is in +preparation, for a non-recursive version. + +Note that a series of pre-signed transactions can be considered to be an +emulation of a covenant. Imagine a linear chain of pre-signed transactions +where each hop has a relative locktime before being able to broadcast the next +transaction. To recover the coins at the end of the rainbow, one would need to +broadcast each sequential transaction in order and wait for the relative +timelocks to expire each time. Here, covenants provide something like an undo +for bitcoin, but only between pre-determined addresses and scripts. + +Fees for pre-signed transactions +================================ + +There's a few different techniques to talk about: + +1) SIGHASH_SINGLE|SIGHASH_ANYONECANPAY to let someone add inputs and outputs. +This can get pretty complex though. + +2) Add a zero-value OP_TRUE output and let anyone spend the zero-value output +and attach a child-pays-for-parent (CPFP) transaction to pay for everything. + +3) Pre-sign a variety of different possible fee rates. Unfortunately this +involves an explosive blow-up in the amount of transaction data to generate. It +might actually be a reasonable blow-up amount, only resulting in a few hundred +megabytes of additional data. But given the other options, this is unnecessary. + +Delete the key (for pre-signed transactions) +============================================ + +The delete-the-key trick is simple. The idea is to pre-sign at least one +transaction and then delete the private key, thus locking in that course of +action. + +Unfortunately, delete-the-key doesn't really work for multisig scenarios +because nobody would trust that anyone else in the scheme has actually deleted +the secret. If they haven't deleted the secret, then they have full unilateral +control to sign anything in that branch of the transaction tree. The only time +that delete-the-key might be appropriate would be where the user who deletes +the key and controls the key during the setup process is also the sole +beneficiary of the entire setup with the multisig participants. + +Alternative fee rates are easier to deal with using delete-the-key, compared to +a technique where the private key never existed which can only be used to sign +one fee rate per public key, requiring an entirely new vault subtree for each +alternative fee rate. With delete-the-key, the alternative fee rates are signed +with the private key before the private key is deleted. + +Multisig gated by ECDSA pubkey recovery for provably-unknown keys +================================================================= + +A group can participate in a multisig scheme with provably-unknown ECDSA keys. +Instead of deleting the key, the idea is to agree on a blockheight and then +select the blockhash (or some function of the chosen blockhash like +H(H(H(blockhash)))) as the signature. Next, the group agrees on a transaction +and they recover the public key from the signature using ECDSA pubkey recovery. +A pre-signed transaction is created, which will trigger the start of the public +observation period described earlier and also start the clock for the bip112 +relative timelock on its output. In the output script, an OR branch +is added that enables the use of a re-vaulting key which could also be its own +separate multisig construction. + +This is incompatible with P2WPKH because the P2WPKH spending scriptSig needs to +have the pubkey (to check the hash of the pubkey against the pubkeyhash in the +scriptPubKey), which in turn makes it incompatible with ECDSA pubkey recovery +which requires a hash of the message. However, with P2WPK and SIGHASH_NOINPUT +instead of P2WPKH it could conceivably work. SIGHASH_NOINPUT is required because +otherwise the input includes a txid which references the public key. With P2WPK, +the scriptSig only needs a signature and not a public key. Note that what would +be required is a version of SIGHASH_NOINPUT that does not commit to the public +key, and I think a few of the NOINPUT proposals are committing to the public +key. + +Alternatively, there may be some constructions using the 2-party ECDSA +techniques or m-n party ECDSA techniques. + +Deploying exceedingly large scripts +=================================== + +A brief interlude to share a somewhat obvious construction. I haven't seen this +written down yet. + +Suppose there is a bitcoin script that someone is interested in using, but it +far exceeds the size limits and sigop limits. To fix this, they would split up +the script into usable chunks, and then use the delete-the-key mechanism (or +the other one) to create an OR branch that is signable by a single key for +which only a single signature is known. That new pre-signed transaction would +spend to a script that has the output with the remainder of the script of +interest. Re-vaulting or clawback clauses can be added to that output as well, +but spending back to the original root script will only work by generating new +scripts and keys (since the final hash isn't known until the whole tree is +constructed, it's a dependency loop). + +Recursively-enforced multi-party multisig bitcoin vaults +======================================================== + +Ideally, to enforce a covenant with impossible fairy dust magic, we would ask +for a bitcoin transaction that could be self-referential because the +only-one-signature-ever trick requires that the signed message be known before +producing the signature, and the signature has to be known before the public +key can be known, and the public key would have to be included in the +self-referential message/transaction hash value. So, that's a dependency loop +and it doesn't work. It would be interesting to explore a variation of this +idea with masking, such that a value X can be replaced by a hash over the whole +script with the X value, even though the real script will have the hash. +Someone else can figure that one out for me :-). + +Instead of the self-referential values attempting to reference the same +script that is in the process of being constructed, an alternative is to use +the same script template but populate it with different parameters. The script +template gets reused over and over again, all the way down the tree, until the +final transaction which could be >100 years into the future once done adding up +all the relative locktimes. In fact, to create and populate this terrifying +recursive script tree, the final transaction needs to be created first, and +then it is given as input to the script template function and that output is +then given to the script template function itself-- and so on. At each stage, +there are additional pre-signed transactions and values to remember. + +This can be written as: + + final_transaction = TX(spend to 0x0000 to burn the coins) + initial_transaction = F(F(...F(final_transaction)) + + (This is missing parameters to indicate to the function what the spending + keys requirements are to be.) + +See earlier explanation for more details. + +Each call to the template populating function produces values that each must be +preserved for a very long time. It is less safe to store all of the pre-signed +transactions together at the same time, but more convenient. With less +redundancy, there is an increased chance of losing data over time, which could +render the coins completely frozen. This doesn't particularly worry me because +forgetting a key has that property already, and this could be likened to +hundreds of megabytes of extra key data or something. Unlike the much smaller +covenant-based (opcode-based covenant) vault construction, the multiple layers +here can be separately stored and protected, which might be able to protect +against an adversary that has stolen some of the re-vaulting keys but not all +of them. + +Optimizations can be made to store parameters for generating the remainder of +the tree, such as using deterministic key derivation, such that megabytes of +data wouldn't need to be long-term stored. Only the initial parameters would +need to be stored. + +Financial privacy for custody +============================= + +One of the concerns raised in [2] is that if all coins at an exchange are +stored together in the same vault, then attackers would be able to learn about +access control policies by observing scripts and keys. Some privacy can be +recovered by using segregated vaults, at the cost of additional setup +complexity and keeping more data in long-term storage. + +However, note that I think vaults are also useful for personal cold storage +solutions. + +Fail-deadly mechanism +===================== + +An early nuclear abort option can be added to these scripts. This idea was +explored in [2]. This would be a very cold very secret key that would abort the +re-vaulting procedure and send all coins to a (provably) nonsense key. This +allows a vault user to destroy the coins instead of continuously monitoring the +bitcoin blockchain for the rest of his life. The attacker can't recover their +cost of attack if they never get the coins, and this eliminates an entire class +of potential attackers who are directly interested only in financial gain. The +disadvantage is that if the attacker finds the secret key for the fail-deadly +mechanism and uses it, then all of the coins are gone forever. + +Multisig variations +=================== + +The re-vaulting key could be the same key at each layer, or only sometimes the +same key, or always a unique key stored separately in another secure location. + +Additionally, these re-vaulting keys could be subjected to multisig schemes, as +well as Shamir secret sharing schemes or other secret sharing schemes. + +The idea of adding the 4-of-7 multisig component is to avoid griefing +situations, at the cost of the additional security requirements for the 4-of-7 +multisig group. + +Key rotation for vaults +======================= + +Keeping the same hot wallet key for 100 years is not advisable. Rotate the keys +by setting up a new vault construction and initiating a withdrawal transaction +from the old vault to the new vault. + +Single-use seals +================ + +This proposal may have inadvertedly demonstrated a practical way to implement +Peter Todd's single-use seals concept [4]. I am hesitant to say so, though, +because I think he would ask for a more sophisticated way to verify seal +closure. + +Paid defection +============== + +It might be advisable to add small rewards for evidence of defection amongst +multiparty multisig setups. Besides amounts spendable by individual keys from a +multisig setup, it may be possible to use a zero-knowledge contingent payment +for a zero-knowledge statement like: I have a signature s over some message m +which validates for pubkey pk where pk is a member of the multisig group. Then +the zkcp transaction would pay for knowledge of defectors. The zkcp procedure +would require interaction with the defector, while the direct pubkey method +would not. This is similar to companies paying employees to quit when they +value the payment over the value of continued employment. + +Handling change +=============== + +It is important to note that this vault setup is one-time and once-only. There +must only ever be one deposit into one vault. Also, spending some coins would +require sending the change amount back into a new vault. Alternatively, +upfront work can be done to set a regular withdrawal stipend or assumption +about how many coins are left, such that the transaction tree can be +pre-generated for those possibilities, hence cutting down on future vault +reinitializations. It would also be possible to commit upfront to only ever +working in some minimum increment number of bitcoin or something. + +It is very important to only fund the vault once, and only with the amount that +was configured when setting up the vault. + +References +========== + +[1] https://fc16.ifca.ai/bitcoin/papers/MES16.pdf + +[2] http://www0.cs.ucl.ac.uk/staff/P.McCorry/preventing-cryptocurrency-exchange.pdf + +[3] http://web.archive.org/web/20180503151920/https://blog.sldx.com/re-imagining-cold-storage-with-timelocks-1f293bfe421f?gi=da99a4a00f67 + +[4] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-December/015350.html +or https://diyhpl.us/wiki/transcripts/building-on-bitcoin/2018/single-use-seals/ +or https://petertodd.org/2016/closed-seal-sets-and-truth-lists-for-privacy + +Acknowledgements +================ + +* Jeremy Rubin for pointing out something embarrassingly broken in an earlier +draft. + +* Bob McElrath for telling me to use SIGHASH_NOINPUT which I proceeded to +promptly forget about. + +* Andrew Poelstra for the OP_TRUE trick. + +* Joe Rayhawk for paid defection. + +* Tadge Dryja for pointing out a few differences between SIGHASH_NOINPUT +proposals. + + + +Thank you, + +- Bryan +http://heybryan.org/ + |