Opened as an alternative to #18071 to be more similar to #17977.
I’m fine with either, deferring to others.
cc jnewbery Sjors
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
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);
= 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);
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.
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)
utACK 8986838d3a4d52ce912e2ce385ec87a4a3d34cad.
One request for additional comments inline.
Several proposals (Taproot, MuHash, CTV) require access to the single
hash.
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)
0 uint256 result = GetSHA256();
The whole function could even be written like this (but I think I slightly prefer the version above to this one):
0 uint256 sha256 = GetSHA256();
1 ctx.Reset().Write(sha256.begin(), CSHA256::OUTPUT_SIZE);
2 return GetSHA256();
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
CSHA256
is 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 :)