Skip to content

Commit 118d22d

Browse files
committed
optimization: cache PresaltedSipHasher in CBlockHeaderAndShortTxIDs
Replaces separate `shorttxidk0`/`shorttxidk1` members with a cached `PresaltedSipHasher`, so `GetShortID()` reuses the precomputed `SipHash` state instead of rebuilding it on every call. `CBlockHeaderAndShortTxIDs` was never intended to be used before `FillShortTxIDSelector()` runs; doing so already relied on indeterminate salt values. The new `Assert(m_hasher)` just makes this invariant explicit and fails fast if the object is used in an uninitialized state.
1 parent 9ca52a4 commit 118d22d

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

src/blockencodings.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,36 @@
1717

1818
#include <unordered_map>
1919

20-
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, const uint64_t nonce) :
21-
nonce(nonce),
22-
shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) {
20+
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, uint64_t nonce)
21+
: nonce(nonce),
22+
shorttxids(block.vtx.size() - 1),
23+
prefilledtxn(1),
24+
header(block)
25+
{
2326
FillShortTxIDSelector();
24-
//TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
27+
// TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
2528
prefilledtxn[0] = {0, block.vtx[0]};
2629
for (size_t i = 1; i < block.vtx.size(); i++) {
2730
const CTransaction& tx = *block.vtx[i];
2831
shorttxids[i - 1] = GetShortID(tx.GetWitnessHash());
2932
}
3033
}
3134

32-
void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const {
35+
void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const
36+
{
3337
DataStream stream{};
3438
stream << header << nonce;
3539
CSHA256 hasher;
3640
hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin());
3741
uint256 shorttxidhash;
3842
hasher.Finalize(shorttxidhash.begin());
39-
shorttxidk0 = shorttxidhash.GetUint64(0);
40-
shorttxidk1 = shorttxidhash.GetUint64(1);
43+
m_hasher.emplace(shorttxidhash.GetUint64(0), shorttxidhash.GetUint64(1));
4144
}
4245

43-
uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const Wtxid& wtxid) const {
46+
uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const Wtxid& wtxid) const
47+
{
4448
static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids calculation assumes 6-byte shorttxids");
45-
PresaltedSipHasher hasher(shorttxidk0, shorttxidk1); // TODO extract
46-
return hasher(wtxid.ToUint256()) & 0xffffffffffffL;
49+
return (*Assert(m_hasher))(wtxid.ToUint256()) & 0xffffffffffffL;
4750
}
4851

4952
/* Reconstructing a compact block is in the hot-path for block relay,

src/blockencodings.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef BITCOIN_BLOCKENCODINGS_H
66
#define BITCOIN_BLOCKENCODINGS_H
77

8+
#include <crypto/siphash.h>
89
#include <primitives/block.h>
910

1011
#include <functional>
@@ -87,8 +88,7 @@ typedef enum ReadStatus_t
8788
} ReadStatus;
8889

8990
class CBlockHeaderAndShortTxIDs {
90-
private:
91-
mutable uint64_t shorttxidk0, shorttxidk1;
91+
mutable std::optional<PresaltedSipHasher> m_hasher;
9292
uint64_t nonce;
9393

9494
void FillShortTxIDSelector() const;
@@ -112,7 +112,7 @@ class CBlockHeaderAndShortTxIDs {
112112
/**
113113
* @param[in] nonce This should be randomly generated, and is used for the siphash secret key
114114
*/
115-
CBlockHeaderAndShortTxIDs(const CBlock& block, const uint64_t nonce);
115+
CBlockHeaderAndShortTxIDs(const CBlock& block, uint64_t nonce);
116116

117117
uint64_t GetShortID(const Wtxid& wtxid) const;
118118

0 commit comments

Comments
 (0)