Skip to content

Commit 510ac41

Browse files
committed
Merge bitcoin/bitcoin#25331: Add HashWriter without ser-type and ser-version and use it where possible
faf9acc Use HashWriter where possible (MacroFake) faa5425 Add HashWriter without ser-type and ser-version (MacroFake) Pull request description: This was done in the context of bitcoin/bitcoin#25284 , but I think it also makes sense standalone. The basic idea is that serialization type should not be initialized when it is not needed. Same for the serialization version. So do this here for `HashWriter`. `CHashWriter` remains in places where it is not yet possible. ACKs for top commit: sipa: utACK faf9acc Empact: utACK bitcoin/bitcoin@faf9acc Tree-SHA512: 544cc712436e49f6e608120bcd3ddc5ea72dd236554ce30fb6cfff34a92d7e67b6e6527336ad0f5b6365e2b2884f4c6508aef775953ccd9312f17752729703f2
2 parents 86133df + faf9acc commit 510ac41

File tree

14 files changed

+65
-53
lines changed

14 files changed

+65
-53
lines changed

src/chainparams.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ class SigNetParams : public CChainParams {
352352
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
353353

354354
// message start is defined as the first 4 bytes of the sha256d of the block script
355-
CHashWriter h(SER_DISK, 0);
355+
HashWriter h{};
356356
h << consensus.signet_challenge;
357357
uint256 hash = h.GetHash();
358358
memcpy(pchMessageStart, hash.begin(), 4);

src/crypto/muhash.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ void Num3072::ToBytes(unsigned char (&out)[BYTE_SIZE]) {
298298
Num3072 MuHash3072::ToNum3072(Span<const unsigned char> in) {
299299
unsigned char tmp[Num3072::BYTE_SIZE];
300300

301-
uint256 hashed_in = (CHashWriter(SER_DISK, 0) << in).GetSHA256();
301+
uint256 hashed_in{(HashWriter{} << in).GetSHA256()};
302302
ChaCha20(hashed_in.data(), hashed_in.size()).Keystream(tmp, Num3072::BYTE_SIZE);
303303
Num3072 out{tmp};
304304

@@ -318,7 +318,7 @@ void MuHash3072::Finalize(uint256& out) noexcept
318318
unsigned char data[Num3072::BYTE_SIZE];
319319
m_numerator.ToBytes(data);
320320

321-
out = (CHashWriter(SER_DISK, 0) << data).GetSHA256();
321+
out = (HashWriter{} << data).GetSHA256();
322322
}
323323

324324
MuHash3072& MuHash3072::operator*=(const MuHash3072& mul) noexcept

src/hash.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ uint256 SHA256Uint256(const uint256& input)
8686
return result;
8787
}
8888

89-
CHashWriter TaggedHash(const std::string& tag)
89+
HashWriter TaggedHash(const std::string& tag)
9090
{
91-
CHashWriter writer(SER_GETHASH, 0);
91+
HashWriter writer{};
9292
uint256 taghash;
9393
CSHA256().Write((const unsigned char*)tag.data(), tag.size()).Finalize(taghash.begin());
9494
writer << taghash << taghash;

src/hash.h

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,12 @@ inline uint160 Hash160(const T1& in1)
9696
}
9797

9898
/** A writer stream (for serialization) that computes a 256-bit hash. */
99-
class CHashWriter
99+
class HashWriter
100100
{
101101
private:
102102
CSHA256 ctx;
103103

104-
const int nType;
105-
const int nVersion;
106104
public:
107-
108-
CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
109-
110-
int GetType() const { return nType; }
111-
int GetVersion() const { return nVersion; }
112-
113105
void write(Span<const std::byte> src)
114106
{
115107
ctx.Write(UCharCast(src.data()), src.size());
@@ -144,6 +136,26 @@ class CHashWriter
144136
return ReadLE64(result.begin());
145137
}
146138

139+
template <typename T>
140+
HashWriter& operator<<(const T& obj)
141+
{
142+
::Serialize(*this, obj);
143+
return *this;
144+
}
145+
};
146+
147+
class CHashWriter : public HashWriter
148+
{
149+
private:
150+
const int nType;
151+
const int nVersion;
152+
153+
public:
154+
CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
155+
156+
int GetType() const { return nType; }
157+
int GetVersion() const { return nVersion; }
158+
147159
template<typename T>
148160
CHashWriter& operator<<(const T& obj) {
149161
// Serialize to this stream
@@ -203,12 +215,12 @@ unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vData
203215

204216
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
205217

206-
/** Return a CHashWriter primed for tagged hashes (as specified in BIP 340).
218+
/** Return a HashWriter primed for tagged hashes (as specified in BIP 340).
207219
*
208220
* The returned object will have SHA256(tag) written to it twice (= 64 bytes).
209221
* A tagged hash can be computed by feeding the message into this object, and
210-
* then calling CHashWriter::GetSHA256().
222+
* then calling HashWriter::GetSHA256().
211223
*/
212-
CHashWriter TaggedHash(const std::string& tag);
224+
HashWriter TaggedHash(const std::string& tag);
213225

214226
#endif // BITCOIN_HASH_H

src/kernel/coinstats.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ CDataStream TxOutSer(const COutPoint& outpoint, const Coin& coin) {
6868
//! It is also possible, though very unlikely, that a change in this
6969
//! construction could cause a previously invalid (and potentially malicious)
7070
//! UTXO snapshot to be considered valid.
71-
static void ApplyHash(CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
71+
static void ApplyHash(HashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
7272
{
7373
for (auto it = outputs.begin(); it != outputs.end(); ++it) {
7474
if (it == outputs.begin()) {
@@ -159,7 +159,7 @@ std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsV
159159
bool success = [&]() -> bool {
160160
switch (hash_type) {
161161
case(CoinStatsHashType::HASH_SERIALIZED): {
162-
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
162+
HashWriter ss{};
163163
return ComputeUTXOStats(view, stats, ss, interruption_point);
164164
}
165165
case(CoinStatsHashType::MUHASH): {
@@ -180,15 +180,15 @@ std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsV
180180
}
181181

182182
// The legacy hash serializes the hashBlock
183-
static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
183+
static void PrepareHash(HashWriter& ss, const CCoinsStats& stats)
184184
{
185185
ss << stats.hashBlock;
186186
}
187187
// MuHash does not need the prepare step
188188
static void PrepareHash(MuHash3072& muhash, CCoinsStats& stats) {}
189189
static void PrepareHash(std::nullptr_t, CCoinsStats& stats) {}
190190

191-
static void FinalizeHash(CHashWriter& ss, CCoinsStats& stats)
191+
static void FinalizeHash(HashWriter& ss, CCoinsStats& stats)
192192
{
193193
stats.hashSerialized = ss.GetHash();
194194
}

src/node/blockstorage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const
471471
fileout << blockundo;
472472

473473
// calculate & write checksum
474-
CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
474+
HashWriter hasher{};
475475
hasher << hashBlock;
476476
hasher << blockundo;
477477
fileout << hasher.GetHash();

src/pubkey.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,16 @@ bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span<const unsigned char> si
211211
return secp256k1_schnorrsig_verify(secp256k1_context_verify, sigbytes.data(), msg.begin(), 32, &pubkey);
212212
}
213213

214-
static const CHashWriter HASHER_TAPTWEAK = TaggedHash("TapTweak");
214+
static const HashWriter HASHER_TAPTWEAK{TaggedHash("TapTweak")};
215215

216216
uint256 XOnlyPubKey::ComputeTapTweakHash(const uint256* merkle_root) const
217217
{
218218
if (merkle_root == nullptr) {
219219
// We have no scripts. The actual tweak does not matter, but follow BIP341 here to
220220
// allow for reproducible tweaking.
221-
return (CHashWriter(HASHER_TAPTWEAK) << m_keydata).GetSHA256();
221+
return (HashWriter{HASHER_TAPTWEAK} << m_keydata).GetSHA256();
222222
} else {
223-
return (CHashWriter(HASHER_TAPTWEAK) << m_keydata << *merkle_root).GetSHA256();
223+
return (HashWriter{HASHER_TAPTWEAK} << m_keydata << *merkle_root).GetSHA256();
224224
}
225225
}
226226

src/script/interpreter.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,7 @@ class CTransactionSignatureSerializer
13421342
template <class T>
13431343
uint256 GetPrevoutsSHA256(const T& txTo)
13441344
{
1345-
CHashWriter ss(SER_GETHASH, 0);
1345+
HashWriter ss{};
13461346
for (const auto& txin : txTo.vin) {
13471347
ss << txin.prevout;
13481348
}
@@ -1353,7 +1353,7 @@ uint256 GetPrevoutsSHA256(const T& txTo)
13531353
template <class T>
13541354
uint256 GetSequencesSHA256(const T& txTo)
13551355
{
1356-
CHashWriter ss(SER_GETHASH, 0);
1356+
HashWriter ss{};
13571357
for (const auto& txin : txTo.vin) {
13581358
ss << txin.nSequence;
13591359
}
@@ -1364,7 +1364,7 @@ uint256 GetSequencesSHA256(const T& txTo)
13641364
template <class T>
13651365
uint256 GetOutputsSHA256(const T& txTo)
13661366
{
1367-
CHashWriter ss(SER_GETHASH, 0);
1367+
HashWriter ss{};
13681368
for (const auto& txout : txTo.vout) {
13691369
ss << txout;
13701370
}
@@ -1374,7 +1374,7 @@ uint256 GetOutputsSHA256(const T& txTo)
13741374
/** Compute the (single) SHA256 of the concatenation of all amounts spent by a tx. */
13751375
uint256 GetSpentAmountsSHA256(const std::vector<CTxOut>& outputs_spent)
13761376
{
1377-
CHashWriter ss(SER_GETHASH, 0);
1377+
HashWriter ss{};
13781378
for (const auto& txout : outputs_spent) {
13791379
ss << txout.nValue;
13801380
}
@@ -1384,7 +1384,7 @@ uint256 GetSpentAmountsSHA256(const std::vector<CTxOut>& outputs_spent)
13841384
/** Compute the (single) SHA256 of the concatenation of all scriptPubKeys spent by a tx. */
13851385
uint256 GetSpentScriptsSHA256(const std::vector<CTxOut>& outputs_spent)
13861386
{
1387-
CHashWriter ss(SER_GETHASH, 0);
1387+
HashWriter ss{};
13881388
for (const auto& txout : outputs_spent) {
13891389
ss << txout.scriptPubKey;
13901390
}
@@ -1458,9 +1458,9 @@ template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo,
14581458
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
14591459
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
14601460

1461-
const CHashWriter HASHER_TAPSIGHASH = TaggedHash("TapSighash");
1462-
const CHashWriter HASHER_TAPLEAF = TaggedHash("TapLeaf");
1463-
const CHashWriter HASHER_TAPBRANCH = TaggedHash("TapBranch");
1461+
const HashWriter HASHER_TAPSIGHASH{TaggedHash("TapSighash")};
1462+
const HashWriter HASHER_TAPLEAF{TaggedHash("TapLeaf")};
1463+
const HashWriter HASHER_TAPBRANCH{TaggedHash("TapBranch")};
14641464

14651465
static bool HandleMissingData(MissingDataBehavior mdb)
14661466
{
@@ -1499,7 +1499,7 @@ bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, cons
14991499
return HandleMissingData(mdb);
15001500
}
15011501

1502-
CHashWriter ss = HASHER_TAPSIGHASH;
1502+
HashWriter ss{HASHER_TAPSIGHASH};
15031503

15041504
// Epoch
15051505
static constexpr uint8_t EPOCH = 0;
@@ -1544,7 +1544,7 @@ bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, cons
15441544
if (output_type == SIGHASH_SINGLE) {
15451545
if (in_pos >= tx_to.vout.size()) return false;
15461546
if (!execdata.m_output_hash) {
1547-
CHashWriter sha_single_output(SER_GETHASH, 0);
1547+
HashWriter sha_single_output{};
15481548
sha_single_output << tx_to.vout[in_pos];
15491549
execdata.m_output_hash = sha_single_output.GetSHA256();
15501550
}
@@ -1587,12 +1587,12 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
15871587
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
15881588
hashOutputs = cacheready ? cache->hashOutputs : SHA256Uint256(GetOutputsSHA256(txTo));
15891589
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
1590-
CHashWriter ss(SER_GETHASH, 0);
1590+
HashWriter ss{};
15911591
ss << txTo.vout[nIn];
15921592
hashOutputs = ss.GetHash();
15931593
}
15941594

1595-
CHashWriter ss(SER_GETHASH, 0);
1595+
HashWriter ss{};
15961596
// Version
15971597
ss << txTo.nVersion;
15981598
// Input prevouts/nSequence (none/all, depending on flags)
@@ -1627,7 +1627,7 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
16271627
CTransactionSignatureSerializer<T> txTmp(txTo, scriptCode, nIn, nHashType);
16281628

16291629
// Serialize and hash
1630-
CHashWriter ss(SER_GETHASH, 0);
1630+
HashWriter ss{};
16311631
ss << txTmp << nHashType;
16321632
return ss.GetHash();
16331633
}
@@ -1827,7 +1827,7 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
18271827

18281828
uint256 ComputeTapleafHash(uint8_t leaf_version, const CScript& script)
18291829
{
1830-
return (CHashWriter(HASHER_TAPLEAF) << leaf_version << script).GetSHA256();
1830+
return (HashWriter{HASHER_TAPLEAF} << leaf_version << script).GetSHA256();
18311831
}
18321832

18331833
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash)
@@ -1839,7 +1839,7 @@ uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint25
18391839
const int path_len = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
18401840
uint256 k = tapleaf_hash;
18411841
for (int i = 0; i < path_len; ++i) {
1842-
CHashWriter ss_branch{HASHER_TAPBRANCH};
1842+
HashWriter ss_branch{HASHER_TAPBRANCH};
18431843
Span node{Span{control}.subspan(TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * i, TAPROOT_CONTROL_NODE_SIZE)};
18441844
if (std::lexicographical_compare(k.begin(), k.end(), node.begin(), node.end())) {
18451845
ss_branch << k << node;
@@ -1902,7 +1902,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
19021902
if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) {
19031903
// Drop annex (this is non-standard; see IsWitnessStandard)
19041904
const valtype& annex = SpanPopBack(stack);
1905-
execdata.m_annex_hash = (CHashWriter(SER_GETHASH, 0) << annex).GetSHA256();
1905+
execdata.m_annex_hash = (HashWriter{} << annex).GetSHA256();
19061906
execdata.m_annex_present = true;
19071907
} else {
19081908
execdata.m_annex_present = false;

src/script/interpreter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,9 @@ static constexpr size_t TAPROOT_CONTROL_NODE_SIZE = 32;
233233
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT = 128;
234234
static constexpr size_t TAPROOT_CONTROL_MAX_SIZE = TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT;
235235

236-
extern const CHashWriter HASHER_TAPSIGHASH; //!< Hasher with tag "TapSighash" pre-fed to it.
237-
extern const CHashWriter HASHER_TAPLEAF; //!< Hasher with tag "TapLeaf" pre-fed to it.
238-
extern const CHashWriter HASHER_TAPBRANCH; //!< Hasher with tag "TapBranch" pre-fed to it.
236+
extern const HashWriter HASHER_TAPSIGHASH; //!< Hasher with tag "TapSighash" pre-fed to it.
237+
extern const HashWriter HASHER_TAPLEAF; //!< Hasher with tag "TapLeaf" pre-fed to it.
238+
extern const HashWriter HASHER_TAPBRANCH; //!< Hasher with tag "TapBranch" pre-fed to it.
239239

240240
template <class T>
241241
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);

src/script/sign.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatu
165165
if (leaf_version != TAPROOT_LEAF_TAPSCRIPT) return false;
166166
SigVersion sigversion = SigVersion::TAPSCRIPT;
167167

168-
uint256 leaf_hash = (CHashWriter(HASHER_TAPLEAF) << uint8_t(leaf_version) << script).GetSHA256();
168+
uint256 leaf_hash = (HashWriter{HASHER_TAPLEAF} << uint8_t(leaf_version) << script).GetSHA256();
169169

170170
// <xonly pubkey> OP_CHECKSIG
171171
if (script.size() == 34 && script[33] == OP_CHECKSIG && script[0] == 0x20) {

0 commit comments

Comments
 (0)