Opened as an alternative to #18071 to be more similar to #17977.
I'm fine with either, deferring to others.
cc jnewbery Sjors
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--174a7506f384e20aa4161008e828411d-->
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
I have mild preference for other PR but
utACK https://github.com/bitcoin/bitcoin/pull/19601/commits/2f450929c8fa29a56afe0a05cc482cea71c23ada
1296 | @@ -1297,9 +1297,12 @@ void PrecomputedTransactionData::Init(const T& txTo) 1297 | 1298 | // Cache is calculated only for transactions with witness 1299 | if (txTo.HasWitness()) { 1300 | - hashPrevouts = GetPrevoutHash(txTo); 1301 | - hashSequence = GetSequenceHash(txTo); 1302 | - hashOutputs = GetOutputsHash(txTo); 1303 | + hashPrevouts = GetPrevoutsSHA256(txTo);
Why this weird double assignment? = SHA256Uint256(GetPrevoutsSHA256(txTo)) is shorter and more clear IMO.
This PR was made before #17977 (review) was added (or before I saw it at least).
I specifically made it so it would be easy on rebase to switch the first assignment and argument to SHA256Uint256 to m_hash_prevouts for taproot, but now since that logic is all different it's not clear that this is an easier rebase. In any case, this part of the patch was designed so that master is correct, but was intended to be blown out by #17977.
212 | @@ -200,6 +213,9 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL 213 | return ss.GetHash(); 214 | } 215 | 216 | +/** Single-SHA256 a 32-byte input (represented as uint256). */ 217 | +uint256 SHA256Uint256(const uint256& input);
Perhaps add NODISCARD here to guard against the issue you pointed out in the other PR.
Concept ACK
I prefer this PR over the alternative (#1807)1: this one is simpler and thus more likely to be used correctly by callers.
Adding NODISCARD to SHA256Uint256 would be nice as observed by sipa.
rebased and added NODISCARD.
1258 | @@ -1259,33 +1259,33 @@ class CTransactionSignatureSerializer 1259 | }; 1260 | 1261 | template <class T> 1262 | -uint256 GetPrevoutHash(const T& txTo) 1263 | +uint256 GetPrevoutsSHA256(const T& txTo)
#17977 adds doxygen comments for this functions (https://github.com/bitcoin/bitcoin/pull/17977/files#diff-be2905e2f5218ecdbe4e55637dac75f3R1352). Mind doing the same here?
done
utACK 8986838d3a4d52ce912e2ce385ec87a4a3d34cad.
One request for additional comments inline.
Several proposals (Taproot, MuHash, CTV) require access to the single
hash.
Code review ACK 9ab4cafabda227ccee5b241d7690fc67f9a27221
Nit: Could add unit tests for the newly introduced functions?
121 | + * Invalidates this object. 122 | + */ 123 | uint256 GetHash() { 124 | uint256 result; 125 | - ctx.Finalize(result); 126 | + ctx.Finalize(result.begin());
nit to consider if you retouch: this should work as well and might be a bit more concise (removing the first line in the function as well)
uint256 result = GetSHA256();
The whole function could even be written like this (but I think I slightly prefer the version above to this one):
uint256 sha256 = GetSHA256();
ctx.Reset().Write(sha256.begin(), CSHA256::OUTPUT_SIZE);
return GetSHA256();
resolving as a fixlater -- at some point, the SHA256 crypto interfaces are going to span-ified, and at that point this code will be touched up anyways :)
tested ACK 9ab4cafabda227ccee5b241d7690fc67f9a27221
On tests: I think it's ok as is in this case because CSHA256 is tested extensively and the GetHash() function is used in several test cases as a utility. If the GetSHA256() would be used inside GetHash() it would be covered through those as well.
On tests: I think it's ok as is in this case because
CSHA256is tested extensively and theGetHash()function is used in several test cases as a utility. If theGetSHA256()would be used insideGetHash()it would be covered through those as well.
AFAICT SHA256Uint256 is used in src/script/interpreter.cpp but not tested directly, or indirectly via a call from another tested function.
I don't think we should settle with "OK testing" for consensus critical code -- we want excellent testing :)
We should be hitting the PrecomputedTransactionData init all across the tests, and then validation would fail in numerous places if those have an error.
In fact I'd go as far as to say if this code isn't already widely tested, we have bigger problems (because it would mean we have no tests covering our PrecomputedTransactionData).
It's also an absolutely trivial function. Testing is important, but there is no point in wasting effort on more than a covering test for a single-line wrapper around otherwise very well-tested code.
Tested ACK 9ab4caf
@sipa @instagibbs mind re-reviewing this? It's a fairly basic change and it'd be nice to get it merged to simplify #19055 and #17977