hasher.h raw

   1  // Copyright (c) 2019-2022 The Limenka developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #ifndef LIMENKA_UTIL_HASHER_H
   6  #define LIMENKA_UTIL_HASHER_H
   7  
   8  #include <crypto/common.h>
   9  #include <crypto/siphash.h>
  10  #include <primitives/transaction.h>
  11  #include <span.h>
  12  #include <uint256.h>
  13  
  14  #include <cstdint>
  15  #include <cstring>
  16  
  17  class SaltedTxidHasher
  18  {
  19  private:
  20      /** Salt */
  21      const uint64_t k0, k1;
  22  
  23  public:
  24      SaltedTxidHasher();
  25  
  26      size_t operator()(const uint256& txid) const {
  27          return SipHashUint256(k0, k1, txid);
  28      }
  29  };
  30  
  31  class SaltedOutpointHasher
  32  {
  33  private:
  34      /** Salt */
  35      const uint64_t k0, k1;
  36  
  37  public:
  38      SaltedOutpointHasher(bool deterministic = false);
  39  
  40      /**
  41       * Having the hash noexcept allows libstdc++'s unordered_map to recalculate
  42       * the hash during rehash, so it does not have to cache the value. This
  43       * reduces node's memory by sizeof(size_t). The required recalculation has
  44       * a slight performance penalty (around 1.6%), but this is compensated by
  45       * memory savings of about 9% which allow for a larger dbcache setting.
  46       *
  47       * @see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/unordered_associative.html
  48       */
  49      size_t operator()(const COutPoint& id) const noexcept(false)
  50      {
  51          return SipHashUint256Extra(k0, k1, id.hash, id.n);
  52      }
  53  };
  54  
  55  struct FilterHeaderHasher
  56  {
  57      size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); }
  58  };
  59  
  60  /**
  61   * We're hashing a nonce into the entries themselves, so we don't need extra
  62   * blinding in the set hash computation.
  63   *
  64   * This may exhibit platform endian dependent behavior but because these are
  65   * nonced hashes (random) and this state is only ever used locally it is safe.
  66   * All that matters is local consistency.
  67   */
  68  class SignatureCacheHasher
  69  {
  70  public:
  71      template <uint8_t hash_select>
  72      uint32_t operator()(const uint256& key) const
  73      {
  74          static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
  75          uint32_t u;
  76          std::memcpy(&u, key.begin()+4*hash_select, 4);
  77          return u;
  78      }
  79  };
  80  
  81  struct BlockHasher
  82  {
  83      // this used to call `GetCheapHash()` in uint256, which was later moved; the
  84      // cheap hash function simply calls ReadLE64() however, so the end result is
  85      // identical
  86      size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); }
  87  };
  88  
  89  class SaltedSipHasher
  90  {
  91  private:
  92      /** Salt */
  93      const uint64_t m_k0, m_k1;
  94  
  95  public:
  96      SaltedSipHasher();
  97  
  98      size_t operator()(const Span<const unsigned char>& script) const;
  99  };
 100  
 101  #endif // LIMENKA_UTIL_HASHER_H
 102