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.
This commit is contained in:
2 files changed
+16
-13
No files matched your search
+13
-10
@@ -17,11 +17,14 @@
|
|||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, const uint64_t nonce) :
|
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, uint64_t nonce)
|
||||||
nonce(nonce),
|
: nonce(nonce),
|
||||||
shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) {
|
shorttxids(block.vtx.size() - 1),
|
||||||
|
prefilledtxn(1),
|
||||||
|
header(block)
|
||||||
|
{
|
||||||
FillShortTxIDSelector();
|
FillShortTxIDSelector();
|
||||||
//TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
|
// TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
|
||||||
prefilledtxn[0] = {0, block.vtx[0]};
|
prefilledtxn[0] = {0, block.vtx[0]};
|
||||||
for (size_t i = 1; i < block.vtx.size(); i++) {
|
for (size_t i = 1; i < block.vtx.size(); i++) {
|
||||||
const CTransaction& tx = *block.vtx[i];
|
const CTransaction& tx = *block.vtx[i];
|
||||||
@@ -29,21 +32,21 @@ CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const {
|
void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const
|
||||||
|
{
|
||||||
DataStream stream{};
|
DataStream stream{};
|
||||||
stream << header << nonce;
|
stream << header << nonce;
|
||||||
CSHA256 hasher;
|
CSHA256 hasher;
|
||||||
hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin());
|
hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin());
|
||||||
uint256 shorttxidhash;
|
uint256 shorttxidhash;
|
||||||
hasher.Finalize(shorttxidhash.begin());
|
hasher.Finalize(shorttxidhash.begin());
|
||||||
shorttxidk0 = shorttxidhash.GetUint64(0);
|
m_hasher.emplace(shorttxidhash.GetUint64(0), shorttxidhash.GetUint64(1));
|
||||||
shorttxidk1 = shorttxidhash.GetUint64(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const Wtxid& wtxid) const {
|
uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const Wtxid& wtxid) const
|
||||||
|
{
|
||||||
static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids calculation assumes 6-byte shorttxids");
|
static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids calculation assumes 6-byte shorttxids");
|
||||||
PresaltedSipHasher hasher(shorttxidk0, shorttxidk1); // TODO extract
|
return (*Assert(m_hasher))(wtxid.ToUint256()) & 0xffffffffffffL;
|
||||||
return hasher(wtxid.ToUint256()) & 0xffffffffffffL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reconstructing a compact block is in the hot-path for block relay,
|
/* Reconstructing a compact block is in the hot-path for block relay,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#ifndef BITCOIN_BLOCKENCODINGS_H
|
#ifndef BITCOIN_BLOCKENCODINGS_H
|
||||||
#define BITCOIN_BLOCKENCODINGS_H
|
#define BITCOIN_BLOCKENCODINGS_H
|
||||||
|
|
||||||
|
#include <crypto/siphash.h>
|
||||||
#include <primitives/block.h>
|
#include <primitives/block.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -87,8 +88,7 @@ typedef enum ReadStatus_t
|
|||||||
} ReadStatus;
|
} ReadStatus;
|
||||||
|
|
||||||
class CBlockHeaderAndShortTxIDs {
|
class CBlockHeaderAndShortTxIDs {
|
||||||
private:
|
mutable std::optional<PresaltedSipHasher> m_hasher;
|
||||||
mutable uint64_t shorttxidk0, shorttxidk1;
|
|
||||||
uint64_t nonce;
|
uint64_t nonce;
|
||||||
|
|
||||||
void FillShortTxIDSelector() const;
|
void FillShortTxIDSelector() const;
|
||||||
@@ -112,7 +112,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @param[in] nonce This should be randomly generated, and is used for the siphash secret key
|
* @param[in] nonce This should be randomly generated, and is used for the siphash secret key
|
||||||
*/
|
*/
|
||||||
CBlockHeaderAndShortTxIDs(const CBlock& block, const uint64_t nonce);
|
CBlockHeaderAndShortTxIDs(const CBlock& block, uint64_t nonce);
|
||||||
|
|
||||||
uint64_t GetShortID(const Wtxid& wtxid) const;
|
uint64_t GetShortID(const Wtxid& wtxid) const;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user