mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-31 10:41:08 +00:00
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:
parent
9ca52a4cbe
commit
118d22ddb4
@ -17,11 +17,14 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, const uint64_t nonce) :
|
||||
nonce(nonce),
|
||||
shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) {
|
||||
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, uint64_t nonce)
|
||||
: nonce(nonce),
|
||||
shorttxids(block.vtx.size() - 1),
|
||||
prefilledtxn(1),
|
||||
header(block)
|
||||
{
|
||||
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]};
|
||||
for (size_t i = 1; i < block.vtx.size(); 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{};
|
||||
stream << header << nonce;
|
||||
CSHA256 hasher;
|
||||
hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin());
|
||||
uint256 shorttxidhash;
|
||||
hasher.Finalize(shorttxidhash.begin());
|
||||
shorttxidk0 = shorttxidhash.GetUint64(0);
|
||||
shorttxidk1 = shorttxidhash.GetUint64(1);
|
||||
m_hasher.emplace(shorttxidhash.GetUint64(0), 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");
|
||||
PresaltedSipHasher hasher(shorttxidk0, shorttxidk1); // TODO extract
|
||||
return hasher(wtxid.ToUint256()) & 0xffffffffffffL;
|
||||
return (*Assert(m_hasher))(wtxid.ToUint256()) & 0xffffffffffffL;
|
||||
}
|
||||
|
||||
/* Reconstructing a compact block is in the hot-path for block relay,
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#ifndef BITCOIN_BLOCKENCODINGS_H
|
||||
#define BITCOIN_BLOCKENCODINGS_H
|
||||
|
||||
#include <crypto/siphash.h>
|
||||
#include <primitives/block.h>
|
||||
|
||||
#include <functional>
|
||||
@ -87,8 +88,7 @@ typedef enum ReadStatus_t
|
||||
} ReadStatus;
|
||||
|
||||
class CBlockHeaderAndShortTxIDs {
|
||||
private:
|
||||
mutable uint64_t shorttxidk0, shorttxidk1;
|
||||
mutable std::optional<PresaltedSipHasher> m_hasher;
|
||||
uint64_t nonce;
|
||||
|
||||
void FillShortTxIDSelector() const;
|
||||
@ -112,7 +112,7 @@ public:
|
||||
/**
|
||||
* @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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user