@@ -170,21 +170,25 @@ specification for the semantics of OP_CHECKTEMPLATEVERIFY.
170
170
Where
171
171
172
172
bool CheckDefaultCheckTemplateVerifyHash(const std::vector<unsigned char>& hash) {
173
+ // note: for anti-DoS, a real implementation *must* cache parts of this computation
174
+ // to avoid quadratic hashing DoS, including
173
175
return GetDefaultCheckTemplateVerifyHash(current_tx, current_input_index) == uint256(hash);
174
176
}
175
177
176
178
The hash is computed as follows:
177
-
179
+ // not DoS safe, for reference/testing!
178
180
uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, uint32_t input_index) {
179
181
return GetDefaultCheckTemplateVerifyHash(tx, GetOutputsSHA256(tx), GetSequenceSHA256(tx), input_index);
180
182
}
183
+ // not DoS safe for reference/testing!
181
184
uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
182
185
const uint32_t input_index) {
183
186
bool skip_scriptSigs = std::find_if(tx.vin.begin(), tx.vin.end(),
184
187
[](const CTxIn& c) { return c.scriptSig != CScript(); }) == tx.vin.end();
185
188
return skip_scriptSigs ? GetDefaultCheckTemplateVerifyHashEmptyScript(tx, outputs_hash, sequences_hash, input_index) :
186
189
GetDefaultCheckTemplateVerifyHashWithScript(tx, outputs_hash, sequences_hash, GetScriptSigsSHA256(tx), input_index);
187
190
}
191
+ // DoS safe, fixed length hash!
188
192
uint256 GetDefaultCheckTemplateVerifyHashWithScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
189
193
const uint256& scriptSig_hash, const uint32_t input_index) {
190
194
auto h = CHashWriter(SER_GETHASH, 0)
@@ -198,6 +202,7 @@ The hash is computed as follows:
198
202
<< input_index;
199
203
return h.GetSHA256();
200
204
}
205
+ // DoS safe, fixed length hash!
201
206
uint256 GetDefaultCheckTemplateVerifyHashEmptyScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
202
207
const uint32_t input_index) {
203
208
auto h = CHashWriter(SER_GETHASH, 0)
@@ -474,6 +479,38 @@ unintentional introduction of the 'half spend' problem.
474
479
475
480
Templates, as restricted as they are, bear some risks.
476
481
482
+ ====Denial of Service and Validation Costs ====
483
+
484
+ CTV is designed to be able to be validated very cheaply without introducing DoS, either by checking a
485
+ precomputed hash or computing a hash of fixed length arguments (some of which may be cached from more
486
+ expensive computations).
487
+
488
+ In particular, CTV requires that clients cache the computation of a hash over all the scriptSigs, sequences,
489
+ and outputs. Before CTV, the hash of the scriptSigs was not required. CTV also requires that the presence of
490
+ any non-empty scriptSig be hashed, but this can be handled as a part of the scriptSigs hash.
491
+
492
+ As such, evaluating a CTV hash during consensus is always O(1) computation when the caches are available.
493
+ These caches usually must be available due to similar issues in CHECKSIG behavior. Computing the caches
494
+ is O(T) (the size of the transaction).
495
+
496
+ An example of a script that could experience an DoS issue without caching is:
497
+
498
+ ```
499
+ <H> CTV CTV CTV... CTV
500
+ ```
501
+
502
+ Such a script would cause the intepreter to compute hashes (supposing N CTV's) over O(N*T) data.
503
+ If the scriptSigs non-nullity is not cached, then the O(T) transaction could be scanned over O(N)
504
+ times as well (although cheaper than hashing, still a DoS). As such, CTV caches hashes and computations
505
+ over all variable length fields in a transaction.
506
+
507
+ For CTV, the Denial-of-Service exposure and validation costs are relatively clear. Implementors must be careful
508
+ to correctly code CTV to make use of existing caches and cache the (new for CTV) computations over scriptSigs.
509
+ Other more flexible covenant proposals may have a more difficult time solving DoS issues as more complex computations may
510
+ be less cacheable and expose issues around quadratic hashing, it is a tradeoff CTV makes in favor of cheap and secure
511
+ validation at the expense of flexibility. For example, if CTV allowed the hashing only select outputs by a bitmask,
512
+ caching of all combinations of outputs would not be possible and would cause a quadratic hashing DoS vulnerability.
513
+
477
514
====Permanently Unspendable Outputs ====
478
515
479
516
The preimage argument passed to CHECKTEMPLATEVERIFY may be unknown or otherwise unsatisfiable.
@@ -565,6 +602,7 @@ Given the simplicity of this approach to implement and analyze, and the benefits
565
602
applications, CHECKTEMPLATEVERIFY's template based approach is proposed in lieu of more complete
566
603
covenants system.
567
604
605
+
568
606
====Future Upgrades ====
569
607
570
608
This section describes updates to OP_CHECKTEMPLATEVERIFY that are possible in
0 commit comments