summaryrefslogtreecommitdiff
path: root/bip-0119.mediawiki
diff options
context:
space:
mode:
Diffstat (limited to 'bip-0119.mediawiki')
-rw-r--r--bip-0119.mediawiki174
1 files changed, 131 insertions, 43 deletions
diff --git a/bip-0119.mediawiki b/bip-0119.mediawiki
index e59987f..7f5159c 100644
--- a/bip-0119.mediawiki
+++ b/bip-0119.mediawiki
@@ -39,9 +39,12 @@ The recommended standardness rules additionally:
==Motivation==
-Covenants are restrictions on how a coin may be spent beyond key ownership. Covenants can be useful
-to construct smart contracts. As covenants are complex to implement and risk of introducing
-fungibility discriminants they have not been seriously considered for inclusion in Bitcoin.
+Covenants are restrictions on how a coin may be spent beyond key ownership. This is a general
+definition based on the legal definition which even simple scripts using CSV would satisfy.
+Covenants in Bitcoin transactions usually refer to restrictions on where coins can be transferred.
+Covenants can be useful to construct smart contracts. As covenants are complex to implement
+and risk of introducing fungibility discriminants they have not been seriously considered for
+inclusion in Bitcoin.
This BIP introduces a simple covenant called a *template* which enables a limited set of highly
valuable use cases without significant risk.
@@ -73,9 +76,9 @@ is provided in this BIP's subdirectory.
There are numerous payment channel related uses.
-====Channel Factories====
+====Batched Channel Creation====
-Using CHECKTEMPLATEVERIFY for Channel Factories is similar to the use for Congestion Control,
+Using CHECKTEMPLATEVERIFY for Batched Channel Creation is similar to the use for Congestion Control,
except the leaf node transactions are channels instead of plain payments. The channel can be between
the sender and recipient or a target of recipient's choice. Using an CHECKTEMPLATEVERIFY, the
recipient may give the sender an address which makes a tree of channels unbeknownst to them.
@@ -111,27 +114,50 @@ sensitivity of the lightning protocol on contested channel close.
===Wallet Vaults===
-When greater security is required for cold storage solutions, there can be
-default script paths that move funds from one target to another target.
-For example, a cold wallet can be set up where one customer support desk can,
+This section will detail two variants of wallet vault that can be built using
+CTV. Wallet vaults are a useful tool when greater security is required for
+cold storage solutions, providing default transactional paths that move funds
+from one's cold storage to a hot wallet.
+
+One type of cold wallet can be set up such that a customer support desk can,
without further authorization, move a portion of the funds (using multiple
pre-set amounts) into a lukewarm wallet operated by an isolated support desk.
The support desk can then issue some funds to a hot wallet, and send the
remainder back to cold storage with a similar withdrawal mechanism in place.
This is all possible without CHECKTEMPLATEVERIFY, but CHECKTEMPLATEVERIFY
-eliminates the need for coordination and online signers, as well as reducing the
-ability for a support desk to improperly move funds.
-Furthermore, all such designs can be combined with relative time locks to give
-time for compliance and risk desks to intervene.
+eliminates the need for coordination and online signers, as well as reducing
+the ability for a support desk to improperly move funds. Furthermore, all such
+designs can be combined with relative time locks to give time for compliance
+and risk desks to intervene. This is a 'Coins at Rest' or 'Optically Isolated'
+vault, and is shown below.
<img src="bip-0119/vaults.svg" align="middle"></img>
-===CoinJoin===
-
-CHECKTEMPLATEVERIFY makes it much easier to set up trustless CoinJoins than previously because
-participants agree on a single output which pays all participants, which will be lower fee than
-before. Further each participant doesn't need to know the totality of the outputs committed to by
-that output, they only have to verify their own sub-tree will pay them.
+An alternative design for vaults is also highly effective and simpler to
+implement in Sapio, a smart contract programming language. In this design, the
+user commits to a single UTXO that contains a program for an annuity of
+withdrawals from cold storage to a hot wallet. At any time, the remaining
+balance for the annuity can be cancelled and funds locked entirely in cold
+storage. The withdrawals to the hot wallet can be 'cancelled' before a maturity
+date to ensure the action was authorized. These sort of vaults strongly benefit
+from non-interactivity because the withdrawal program can be set up with cold
+keys that are permanently offline, except in case of emergency. The image below
+shows an instance of this type of wallet vault created with Sapio in Sapio
+Studio. These types of wallet vault can also be chained together by taking
+advantage of CTV's scriptSig commitment. This type of vault is a 'Coins in Motion'
+variant where the coins move along the control path.
+
+<img src="bip-0119/vaultanim.gif" align="middle"></img>
+
+===CoinJoin / Payment Pools / Join Pools ===
+
+CHECKTEMPLATEVERIFY makes it much easier to set up trustless CoinJoins than
+previously because participants agree on a single output which pays all
+participants, which will be lower fee than before. Further each participant
+doesn't need to know the totality of the outputs committed to by that output,
+they only have to verify their own sub-tree will pay them. These trees can
+then, using a top-level Schnorr key, be interactively updated on a rolling basis
+forming a "Payment Pool".
==Detailed Specification==
@@ -170,14 +196,19 @@ specification for the semantics of OP_CHECKTEMPLATEVERIFY.
Where
bool CheckDefaultCheckTemplateVerifyHash(const std::vector<unsigned char>& hash) {
+ // note: for anti-DoS, a real implementation *must* cache parts of this computation
+ // to avoid quadratic hashing DoS all variable length computations must be precomputed
+ // including hashes of the scriptsigs, sequences, and outputs. See the section
+ // "Denial of Service and Validation Costs" below.
return GetDefaultCheckTemplateVerifyHash(current_tx, current_input_index) == uint256(hash);
}
The hash is computed as follows:
-
+ // not DoS safe, for reference/testing!
uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, uint32_t input_index) {
return GetDefaultCheckTemplateVerifyHash(tx, GetOutputsSHA256(tx), GetSequenceSHA256(tx), input_index);
}
+ // not DoS safe for reference/testing!
uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint32_t input_index) {
bool skip_scriptSigs = std::find_if(tx.vin.begin(), tx.vin.end(),
@@ -185,6 +216,7 @@ The hash is computed as follows:
return skip_scriptSigs ? GetDefaultCheckTemplateVerifyHashEmptyScript(tx, outputs_hash, sequences_hash, input_index) :
GetDefaultCheckTemplateVerifyHashWithScript(tx, outputs_hash, sequences_hash, GetScriptSigsSHA256(tx), input_index);
}
+ // DoS safe, fixed length hash!
uint256 GetDefaultCheckTemplateVerifyHashWithScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint256& scriptSig_hash, const uint32_t input_index) {
auto h = CHashWriter(SER_GETHASH, 0)
@@ -198,6 +230,7 @@ The hash is computed as follows:
<< input_index;
return h.GetSHA256();
}
+ // DoS safe, fixed length hash!
uint256 GetDefaultCheckTemplateVerifyHashEmptyScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint32_t input_index) {
auto h = CHashWriter(SER_GETHASH, 0)
@@ -223,7 +256,11 @@ A PayToBareDefaultCheckTemplateVerifyHash output matches the following template:
==Deployment==
-Deployment should be done via BIP 9 VersionBits deployed through Speedy Trial.
+Deployment could be done via BIP 9 VersionBits deployed through Speedy Trial.
+The Bitcoin Core reference implementation includes the below parameters,
+configured to match Speedy Trial, as that is the current activation mechanism
+implemented in Bitcoin Core. Should another method become favored by the wider
+Bitcoin comminity, that might be used instead.
The start time and bit in the implementation are currently set to bit 5 and
NEVER_ACTIVE/NO_TIMEOUT, but this is subject to change while the BIP is a draft.
@@ -237,19 +274,26 @@ For the avoidance of unclarity, the parameters to be determined are:
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY].min_activation_height = 0;
Until BIP-119 reaches ACTIVE state and the
-SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH flag is set, the network should
-execute a NOP4 as SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS for policy and a NOP for
-consensus.
+SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH flag is enforced, node implementations should (are recommended to)
+execute a NOP4 as SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS (to deny entry to the mempool) for policy and must evaluate as
+a NOP for consensus (during block validation).
In order to facilitate using CHECKTEMPLATEVERIFY, the common case of a
PayToBareDefaultCheckTemplateVerifyHash
-with no scriptSig data shall be made standard to permit relaying. Future template types may be
-standardized later as policy changes.
+with no scriptSig data may (is recommended to) be made standard to permit relaying. Future template types may be
+standardized later as policy changes at the preference of the implementor.
==Reference Implementation==
-A reference implementation and tests are available here:
-https://github.com/JeremyRubin/bitcoin/tree/checktemplateverify.
+A reference implementation and tests are available here in the PR to Bitcoin Core https://github.com/bitcoin/bitcoin/pull/21702.
+
+It is not ideal to link to a PR, as it may be rebased and changed, but it is the best place to find
+the current implementation and review comments of others.
+A recent commit hash in that PR including tests and vectors can be found here https://github.com/jeremyrubin/bitcoin/commit/3109df5616796282786706738994a5b97b8a5a38.
+Once the PR is merged, this BIP should be updated to point to the specific code released.
+
+Test vectors are available in [/bip-0119/vectors the bip-0119/vectors
+directory] for checking compatibility with the refrence implementation and BIP.
==Rationale==
@@ -262,8 +306,11 @@ Below we'll discuss the rules one-by-one:
The set of data committed to is a superset of data which can impact the TXID of the transaction,
other than the inputs. This ensures that for a given known input, the TXIDs can also be known ahead
-of time. Otherwise, CHECKTEMPLATEVERIFY would not be usable for Channel Factory type constructions
-as the redemption TXID could be malleated and pre-signed transactions invalidated.
+of time. Otherwise, CHECKTEMPLATEVERIFY would not be usable for Batched Channel Creation constructions
+as the redemption TXID could be malleated and pre-signed transactions invalidated, unless the channels
+are built using an Eltoo-like protocol. Note that there may be other types of pre-signed contracts that
+may or may not be able to use Eltoo-like constructs, therefore making TXIDs predictable makes CTV more
+composable with arbitrary sub-protocols.
=====Committing to the version and locktime=====
@@ -326,13 +373,15 @@ spent. In general, using CHECKTEMPLATEVERIFY with more than one input is difficu
and exposes subtle issues, so multiple inputs should not be used except in
specific applications.
-In principal, committing to the Sequences Hash (below) implicitly commits to the number of inputs,
+In principle, committing to the Sequences Hash (below) implicitly commits to the number of inputs,
making this field strictly redundant. However, separately committing to this number makes it easier
to construct DefaultCheckTemplateVerifyHash from script.
-We treat the number of inputs as a `uint32_t` because signature checking code expects nIn to be an
-`unsigned int`, even though in principal a transaction can encode more than a `uint32_t`'s worth of
-inputs.
+We treat the number of inputs as a `uint32_t` because Bitcoin's consensus decoding logic limits vectors
+to `MAX_SIZE=33554432` and that is larger than `uint16_t` and smaller than `uint32_t`. 32 bits is also
+friendly for manipulation using Bitcoin's current math opcodes, should `OP_CAT` be added. Note that
+the max inputs in a block is further restricted by the block size to around 25,000, which would fit
+into a `uint16_t`, but that is an uneccessary abstraction leak.
=====Committing to the Sequences Hash=====
@@ -348,12 +397,14 @@ script.
=====Committing to the Number of Outputs=====
-In principal, committing to the Outputs Hash (below) implicitly commits to the number of outputs,
+In principle, committing to the Outputs Hash (below) implicitly commits to the number of outputs,
making this field strictly redundant. However, separately committing to this number makes it easier
to construct DefaultCheckTemplateVerifyHash from script.
-We treat the number of outputs as a `uint32_t` because a `COutpoint` index is a `uint32_t`, even
-though in principal a transaction could encode more outputs.
+We treat the number of outputs as a `uint32_t` because a `COutpoint` index is a `uint32_t`.
+Further, Bitcoin's consensus decoding logic limits vectors to `MAX_SIZE=33554432` and that is
+larger than `uint16_t` and smaller than `uint32_t`. 32 bits is also friendly for manipulation using
+Bitcoin's current math opcodes, should `OP_CAT` be added.
=====Committing to the outputs hash=====
@@ -474,6 +525,38 @@ unintentional introduction of the 'half spend' problem.
Templates, as restricted as they are, bear some risks.
+====Denial of Service and Validation Costs====
+
+CTV is designed to be able to be validated very cheaply without introducing DoS, either by checking a
+precomputed hash or computing a hash of fixed length arguments (some of which may be cached from more
+expensive computations).
+
+In particular, CTV requires that clients cache the computation of a hash over all the scriptSigs, sequences,
+and outputs. Before CTV, the hash of the scriptSigs was not required. CTV also requires that the presence of
+any non-empty scriptSig be hashed, but this can be handled as a part of the scriptSigs hash.
+
+As such, evaluating a CTV hash during consensus is always O(1) computation when the caches are available.
+These caches usually must be available due to similar issues in CHECKSIG behavior. Computing the caches
+is O(T) (the size of the transaction).
+
+An example of a script that could experience an DoS issue without caching is:
+
+```
+<H> CTV CTV CTV... CTV
+```
+
+Such a script would cause the intepreter to compute hashes (supposing N CTV's) over O(N*T) data.
+If the scriptSigs non-nullity is not cached, then the O(T) transaction could be scanned over O(N)
+times as well (although cheaper than hashing, still a DoS). As such, CTV caches hashes and computations
+over all variable length fields in a transaction.
+
+For CTV, the Denial-of-Service exposure and validation costs are relatively clear. Implementors must be careful
+to correctly code CTV to make use of existing caches and cache the (new for CTV) computations over scriptSigs.
+Other more flexible covenant proposals may have a more difficult time solving DoS issues as more complex computations may
+be less cacheable and expose issues around quadratic hashing, it is a tradeoff CTV makes in favor of cheap and secure
+validation at the expense of flexibility. For example, if CTV allowed the hashing only select outputs by a bitmask,
+caching of all combinations of outputs would not be possible and would cause a quadratic hashing DoS vulnerability.
+
====Permanently Unspendable Outputs====
The preimage argument passed to CHECKTEMPLATEVERIFY may be unknown or otherwise unsatisfiable.
@@ -509,12 +592,13 @@ reuse-unsafe.
Because CHECKTEMPLATEVERIFY commits to the input index currently being spent, reused-keys are
guaranteed to execute in separate transactions which reduces the risk of "half-spend" type issues.
-====NOP-Default and Standardness Rules====
+====NOP-Default and Recommended Standardness Rules====
-If the argument length is not exactly 32, CHECKTEMPLATEVERIFY treats it as a NOP.
-Many OP_NOP upgrades prefer to fail in such circumstances. In particular, for
-CHECKTEMPLATEVERIFY, making an invalid argument a NOP permits future soft-forks to upgrade the
-semantics or loosed restrictions around the value being previously pushed only.
+If the argument length is not exactly 32, CHECKTEMPLATEVERIFY treats it as a NOP during
+consensus validation. Implementations are recommended to fail in such circumstances during non-consensus
+relaying and mempool validation. In particular, making an invalid-length argument a failure aids future
+soft-forks upgrades to be able to rely on the tighter standard restrictions to safely loosen
+the restrictions for standardness while tightening them for consensus with the upgrade's rules.
The standardness rules may lead an unscrupulous script developer to accidentally rely on the
stricter standardness rules to be enforced during consensus. Should that developer submit a
@@ -565,6 +649,7 @@ Given the simplicity of this approach to implement and analyze, and the benefits
applications, CHECKTEMPLATEVERIFY's template based approach is proposed in lieu of more complete
covenants system.
+
====Future Upgrades====
This section describes updates to OP_CHECKTEMPLATEVERIFY that are possible in
@@ -629,8 +714,9 @@ for an OP_NOP are a soft fork, so existing software will be fully functional wit
for mining and block validation. Similar soft forks for OP_CHECKSEQUENCEVERIFY and OP_CHECKLOCKTIMEVERIFY
(see BIP-0065 and BIP-0112) have similarly changed OP_NOP semantics without introducing compatibility issues.
-In contrast to previous forks, OP_CHECKTEMPLATEVERIFY will not make scripts
-valid for policy until the new rule is active.
+In contrast to previous forks, OP_CHECKTEMPLATEVERIFY's reference implementation does not allow transactions with spending
+scripts using it to be accepted to the mempool or relayed under standard policy until the new rule is active. Other implementations
+are recommended to follow this rule as well, but not required.
Older wallet software will be able to accept spends from OP_CHECKTEMPLATEVERIFY outputs, but will
require an upgrade in order to treat PayToBareDefaultCheckTemplateVerifyHash chains with a confirmed ancestor as
@@ -642,6 +728,8 @@ for older node versions that can be patched but not upgraded to a newer major re
== References ==
*[https://utxos.org utxos.org informational site]
+*[https://learn.sapio-lang.org Sapio Bitcoin smart contract language]
+*[https://rubin.io/advent21 27 Blog Posts on building smart contracts with Sapio and CTV, including examples described here.]
*[https://www.youtube.com/watch?v=YxsjdIl0034&t=2451 Scaling Bitcoin Presentation]
*[https://bitcoinops.org/en/newsletters/2019/05/29/ Optech Newsletter Covering OP_CHECKOUTPUTSHASHVERIFY]
*[https://cyber.stanford.edu/sites/g/files/sbiybj9936/f/jeremyrubin.pdf Structuring Multi Transaction Contracts in Bitcoin]