1
0
Fork 0
mirror of https://github.com/bitcoin/bips.git synced 2025-02-24 07:28:03 +01:00

Merge pull request #1272 from JeremyRubin/patch-4

[BIP-119] Add notes and warnings about DoS during validation of CTV.
This commit is contained in:
Luke Dashjr 2022-01-15 23:27:16 +00:00 committed by GitHub
commit abc9e84e73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -193,14 +193,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(),
@ -208,6 +213,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)
@ -221,6 +227,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)
@ -512,6 +519,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.
@ -603,6 +642,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