refactor: disable default std::hash for CTransactionRef #35101

pull Sjors wants to merge 2 commits into bitcoin:master from Sjors:2026/04/txref-safety changing 4 files +62 −2
  1. Sjors commented at 7:48 PM on April 17, 2026: member

    While working on #33922 I initially forgot to add CTransactionRefComp to the std::unordered_map<CTransactionRef defined there. This PR turns that into a compiler error. See #33922 (review)

    This change triggers a false positive IWYU error, and an inconsistent one at that: our CI wants <variant>, while a manual build on Ubuntu (version 0.26 with clang version 22.1.1) wants <string_view>.

    Various workarounds were discussed in:

    Addressed by back-porting:

  2. DrahtBot added the label Refactoring on Apr 17, 2026
  3. DrahtBot commented at 7:48 PM on April 17, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35101.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK vasild, w0xlt, achow101
    Approach ACK hebasto

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. in src/primitives/transaction.h:426 in 276da6236a outdated
     421 | + *  comparing by pointer. Use CTransactionRefSaltedHash or provide a custom
     422 | + *  hasher. */
     423 | +template <>
     424 | +struct hash<CTransactionRef> {
     425 | +    size_t operator()(const CTransactionRef&) const = delete;
     426 | +};
    


    hebasto commented at 5:54 PM on April 18, 2026:

    e5d04fb46a68bd884d8eefae1014aaa3dd79fa6a:

    This approach doesn't handle scenarios where a container is declared, but no member functions involving hashing are explicitly called. For example, this compiles.

    I suggest a more defensive approach relying on the conditions that must be satisfied for the std::hash<CTransactionRef> specialization to be enabled:

    template <>
    struct hash<CTransactionRef> {
        hash() = delete;
    };
    

    Here are two examples on https://godbolt.org/:

    • A container with the default hasher: fails.
    • A container with the custom hasher: passes.

    Sjors commented at 10:21 AM on April 19, 2026:

    Thanks, marking draft while I study this suggestion.


    Sjors commented at 8:35 AM on April 24, 2026:

    I added hash() = delete;, but also kept the earlier variant for clarity.

  5. in src/primitives/transaction.h:419 in 276da6236a
     414 | + * workaround.
     415 | + */
     416 | +#ifndef _LIBCPP_VERSION
     417 | +template <class T>
     418 | +struct hash; // IWYU pragma: keep
     419 | +#endif
    


    hebasto commented at 6:00 PM on April 18, 2026:

    276da6236af12bb7aee12f74f8138f2c9bb16176:

    This changes follows this suggestion, excluding libc++, which is not used in the IWYU CI job.

    Looks fine to me.


    hebasto commented at 8:34 AM on April 20, 2026:

    I can confirm that the bug has been fixed upstream in https://github.com/include-what-you-use/include-what-you-use/pull/2013.

  6. Sjors marked this as a draft on Apr 19, 2026
  7. Sjors commented at 10:55 AM on April 20, 2026: member

    Since this isn't urgent, I think I'll wait for #35101 (review) to land in a release.

  8. Sjors force-pushed on Apr 24, 2026
  9. Sjors commented at 8:19 AM on April 24, 2026: member

    I took the IWYU patch to see if it actually does the job (I still plan to wait for it to be backported to the clang_22 branch).

  10. Sjors force-pushed on Apr 24, 2026
  11. DrahtBot added the label CI failed on Apr 24, 2026
  12. Sjors commented at 8:35 AM on April 24, 2026: member

    The IWYU patch works. I also implemented @hebasto's suggestion: #35101 (review)

  13. Sjors force-pushed on Apr 24, 2026
  14. DrahtBot removed the label CI failed on Apr 24, 2026
  15. Sjors commented at 5:02 PM on April 25, 2026: member

    Apparently the patch won't be backported: https://github.com/include-what-you-use/include-what-you-use/pull/2013#issuecomment-4313034887

    So I'll just keep it here.

  16. Sjors force-pushed on Apr 25, 2026
  17. Sjors marked this as ready for review on Apr 25, 2026
  18. hebasto commented at 6:23 AM on April 27, 2026: member

    Apparently the patch won't be backported: include-what-you-use/include-what-you-use#2013 (comment)

    So I'll just keep it here.

    FWIW, the IWYU maintainer wrote:

    But if actually backported, it should be done along with the two preceding commits.

  19. hebasto commented at 6:24 AM on April 27, 2026: member

    Approach ACK 16a6b05441f0a195b3df89c8b570f57230ad0f1f.

  20. Sjors commented at 8:28 AM on April 27, 2026: member

    Previous two commits, I don't think we need them here:

  21. in ci/test/01_iwyu.patch:635 in 16a6b05441
     631 | @@ -632,3 +632,48 @@ See: https://github.com/include-what-you-use/include-what-you-use/blob/clang_21/
     632 |   };
     633 |   
     634 |   const char* stdlib_cpp_public_headers[] = {
     635 | +
    


    vasild commented at 9:15 AM on April 27, 2026:

    Offtopic, so we maintain patches for IWYU into a single file. Multiple patches appended into a single file. I think that is prone to conflicts when adding / removing stuff from that file and also a maintenance headache when two separate patches that are to be added in 01_iwyu.patch touch the same file.

    In this case the newly patched std_symbol_map.inc was not present before in 01_iwyu.patch. It would be better to keep each patchset into a separate file. So, for example in this PR a new file like 52f85e1f4d99.diff is added.


    Sjors commented at 12:26 PM on April 27, 2026:

    I moved the new patch to its own file.

  22. in ci/test/01_iwyu.patch:639 in 16a6b05441
     631 | @@ -632,3 +632,48 @@ See: https://github.com/include-what-you-use/include-what-you-use/blob/clang_21/
     632 |   };
     633 |   
     634 |   const char* stdlib_cpp_public_headers[] = {
     635 | +
     636 | +
     637 | +Map std::hash to its providing standard headers.
     638 | +Backport of https://github.com/include-what-you-use/include-what-you-use/pull/2013
     639 | +(commit 52f85e1f4d990f55fc6556d543eb051d79364a16) to the clang_22 release
    


    vasild commented at 9:18 AM on April 27, 2026:

    https://github.com/include-what-you-use/include-what-you-use/commit/52f85e1f4d990f55fc6556d543eb051d79364a16 contains changes also to mapgen/iwyu-mapgen-std-symbol.py which are omitted here. I think it is fine, just mentioning.

  23. in src/primitives/transaction.h:408 in 16a6b05441
     402 | @@ -403,4 +403,16 @@ struct CMutableTransaction
     403 |  typedef std::shared_ptr<const CTransaction> CTransactionRef;
     404 |  template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
     405 |  
     406 | +namespace std {
     407 | +/** Disable default std::hash for CTransactionRef to prevent accidentally
     408 | + *  comparing by pointer. Use CTransactionRefSaltedHash or provide a custom
    


    vasild commented at 9:20 AM on April 27, 2026:

    There is no CTransactionRefSaltedHash.


    Sjors commented at 10:38 AM on April 27, 2026:

    Indeed, that's introduced in #33922.


    Sjors commented at 12:27 PM on April 27, 2026:

    (switched to CTransactionRefHash)

  24. vasild approved
  25. vasild commented at 9:25 AM on April 27, 2026: contributor

    ACK 16a6b05441f0a195b3df89c8b570f57230ad0f1f (modulo the reference to the nonexistent CTransactionRefSaltedHash)

    <details> <summary>Show Signature</summary>

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA256
    
    ACK 16a6b05441f0a195b3df89c8b570f57230ad0f1f (modulo the reference to the nonexistent `CTransactionRefSaltedHash`)
    -----BEGIN PGP SIGNATURE-----
    
    iQQyBAEBCAAdFiEE5k2NRWFNsHVF2czBVN8G9ktVy78FAmnvK0gACgkQVN8G9ktV
    y795Ax/48s9aZJBDruwPM6yHeJx3jylMnYyUbFf0wfvwE2k6F1lAuXc4UsOPvbj2
    IHsmOkBiq7I/xA6d33FjMVbL9Hn8pAtfZHk9TJ25zD0FyMto0yIozoS9s2vGLWrE
    i1Q0+ZWk/vxB6FwAOvyxE6j6KTq8GyvplNXToHa42Fph1s5eXv+gr0LN/VeBqr2u
    aomH329Z7F9sVI/MNABVVbllo+5dvs6/4w6ODTMnTQWw/Umx8C9GjnjtyQDJAzVP
    ihSpRVpBLD5IZczv81LwmJth8vZzYA/0d16hUbhV5+IDVxoX658VYE34CHoY/8U9
    9rFiBQeYzTBA0Ky7Hpax1c57AAB+VX+bFhoWt90clfELz42yiQiHQdc5WiRAj1kw
    K/u2QfUzeiEn3tjqkMDe89AUcd3oI4p0jW9/qi3I4h4G/EZj5yzAkIGMgQAbsh6t
    czcFvF3r9qv4dXp0ML2ylmDdgZ7zMyyvaEk9N+z+5SuVkHVmEoX3+qA9Akqh1r0F
    h1RZsX3Whuwmrpq7hopCNlGNaeodludPgiWpxWHyfaFfICQFeLGSzZOg5huRIvbE
    lMlJ5UG9nVBd4cKUBTX+tpzUQbPkDUKy93TqzDiVcfYxDI++kyYLBPIzLH6EIfo1
    +kcEGkEvZSiUezb3XR+gdDccnTiH+vYOXW253zdCAIWAgUnB4xSDc6MGMvD1EbOJ
    xQXgcrvqYtWoQCid2ZrJ8DZWUNgGm8+Fua444sAamXyRPajcts8eT2re8FSN4wqn
    7wNroDhDw62NHM5NckfCFrrxfm5EVMVBAe3W4d2D9jZ0uRpYhbz8NZnzWmnghvi3
    meIr+z8Lf1IWYGHKUQ5KSMtBDSkhmhZFWR6NjLMe7BWJDfXaMem6hnevCxafqopc
    UuSwMpAqNf3oGtRCOrVRmW7G1VnuVcaEQmRq9xf07BkEWuf44WBato3hmqi4BjhE
    l2ipzsa7X1yS1bXxZyMk8KvyU1FHR4vxo64BqRb5a0HHPKQ8UXb83QCVR405vqnx
    6iOcqJGkNAT1LoPmE6RhiRKrZycSnNYhFQ0jOJ0YQX+vxp3xh85OiDarEeOsStsl
    cU+5j5dXH/4yTo3Y+vihyEQIkBoi0krMSXF5KsGpuu/YOrvTDBJBHTLPYL1TR8Q0
    KVGvDi2H1LVkZHg05mz1gaUFAvVKl4xI9Iqa9J7ysJuCphlp40vwEy5urkX0XEJD
    40f/YVldxtw+bQ/jaANfJmrHWWxvGjsWL0xyLKiQ4SfjZSFIwrmfQccmbyhXe6Ah
    8TxtBEgid5v+zP/A0sxOJe/E8Cx/agkKpN8CniftGIvSdY7WLA2jhwyjkLqpaQHZ
    qcNIKOOHCkXVbngyItPYFD4RT7X1
    =b5H5
    -----END PGP SIGNATURE-----
    

    vasild's public key is on openpgp.org

    </details>

  26. DrahtBot requested review from hebasto on Apr 27, 2026
  27. ci: backport iwyu PR 2013 std::hash mapping
    Cherry-pick include-what-you-use commit 52f85e1f4d99 onto the clang_22
    branch tracked by ci/test/00_setup_env_native_iwyu.sh, fixing the false
    positive where std::hash was mapped to <string_view>/<variant> instead of
    its real provider (<functional>, <memory>, etc).
    47d68cd981
  28. refactor: disable default std::hash for CTransactionRef
    The default std::hash for shared_ptr compares by pointer.
    
    CTransactionRefHash or a custom hasher should be used instead.
    
    Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
    a9301cfa07
  29. Sjors force-pushed on Apr 27, 2026
  30. Sjors commented at 12:31 PM on April 27, 2026: member
    • fixed comment to refer to CTransactionRefHash instead of CTransactionRefSaltedHash, see #35101 (review)
    • moved patch to its own file, see #35101 (review)
    • updated PR description to mention the patch
  31. vasild approved
  32. vasild commented at 1:47 PM on April 29, 2026: contributor

    ACK a9301cfa0730d1d08c9e982f990dfc8aa0b3a27a

    <details> <summary>Show Signature</summary>

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA256
    
    ACK a9301cfa0730d1d08c9e982f990dfc8aa0b3a27a
    -----BEGIN PGP SIGNATURE-----
    
    iQQzBAEBCAAdFiEE5k2NRWFNsHVF2czBVN8G9ktVy78FAmnyC/IACgkQVN8G9ktV
    y79PnB//YklUD5SSNq23cPz95gqzedTyyztaj34wocJaRJI5/AvaiYI/ASzeqqsQ
    rCl2BTS1uj1GSQu8odF8y4ogJwp4f148aA69xSSSU+qREHal+ftuXmPEgaAuuKPz
    NJpmOxt6L4iPXQKZ06qTRPuQb1R7ufLwXDI4usm6ouzO3rpn5D3zPWcgcU0IkgHK
    2Wd/U2UhRp47PQgzyncTicI6IG4WsRHOesbOCwfDnDo4IDfu9K7apm/KxswZfmzR
    1wV4HJrgLXbic5/XiPvhwxHosKkNsPho3NIAbZ/ELi/zgwEMc+ojVOhe3PJNKahL
    rBKbJi187SQ5+1m7oGQL0+K1wg8TILmZIItVGRXglPqta2CUmNoK1I19J8imt0F1
    Xy8pY9Lb7wzCHiEsdRl55ibdPDvN3ZsXtkDY0jlkevCwvoKJrurd1X130H+g+Alk
    2uGNO2XfnPcDhKSAlSX2pOHEYohB1uuQxuzMF5N7D6WQDo7CjJjEfp6bqWiJYUGA
    WsqhNbR6UJ2gWh7C810RL9lmnu6yVLVwuTRewi5alGsTsGCFvbCY1PepGkvQiDDL
    s3eyUMp3bfglireFfgTD/Qdd2F61XBLPChNo/fIVmuovLHPwT59z+aUycrlGwJFN
    WXakX4w5gnkbLtJ70AlABVyRD/mBsd0fZ8Tg0QC+N4qVIdfPHNxC0gKPT1i073Sv
    lbWUOOlS5v1uLOjzLvIIhiUDY3OmvIG67BZrPt23mDM/LuETHWde3UCz++xAnECT
    z19QX9iIaKEdt5hvAfIufIj+cvr2J06PQUkA/6tMV+NHxdzFjUiR96RSoCK4rqTU
    oFQVbzqAVOnogxec/eDSK5KZJhKa/Db5abVa5P7tU3tdMwaDtYGvaWaT8j2mx86O
    PA93N4FMnYWD06jcIIDMzSuKNxl1neFE0EByktENl2LSfADq5qs8maWJXUkz8ryK
    B7jzRa9dDMkU4g7gt46tsZiSr8t/5pWsLA9sW/XBmFdbiHKlVFR9OqWEFlJb6KlW
    Z32032w9tFV/h7g+NYLUV+GkD5smNMYGCxEK65hHkGvirgPZQa5xSalvV4dAo5v7
    4J+ImguWhJRLvU5d9ZIKAdHdZ6pXFsAtKBDQWmaoZprxxECphVifz1jeAaf4mdvL
    fnIM2/cAwhb98oL0tV662xIutkhATRWHjTDlgzYFhm/K4fgnxokWPj25j5rAlxOW
    uRAS2kEJWKty1uIKUmEa4qvnINnybl0NpJgNGR801vY16VXl0e30IJoMvpRPc8wW
    lo8P52ud4ma3TRbNzAwqtKd16sDrpF9YkDNMLzqfO2mq0/EY5ZUN/Rp1MK3kMFMQ
    E0dK4NdoIctv5docw1z8RnpNzX6NUw==
    =Z4cN
    -----END PGP SIGNATURE-----
    

    vasild's public key is on openpgp.org

    </details>

  33. w0xlt commented at 6:28 PM on April 30, 2026: contributor

    Concept ACK

  34. sedited commented at 9:48 AM on May 26, 2026: contributor

    Concept~0

    Not sure if this is worth it. Seems like a bug that can be caught to me.

  35. Sjors commented at 11:07 AM on May 26, 2026: member

    @sedited #33922 had multiple ACKs with that bug in it though.

  36. sedited commented at 4:49 PM on May 26, 2026: contributor

    @sedited #33922 had multiple ACKs with that bug in it though.

    Ah, I misunderstood then. My impression was you ran into this before submitting the PR.

  37. sedited requested review from ismaelsadeeq on May 26, 2026
  38. Sjors commented at 5:43 PM on May 26, 2026: member

    It was discovered here: #33922 (review)

  39. sedited requested review from maflcko on Jun 2, 2026
  40. maflcko commented at 12:46 PM on June 2, 2026: member

    It was discovered here: #33922 (comment)

    Instead of hiding the motivation for a pull request 27 comments deep into a thread, it would be better to put the motivation in the pull request description. Currently the pull description is a random collection of links to upstream iwyu threads, which seem irrelevant implementation details outside of the underlying motivation.

  41. Sjors commented at 8:23 AM on June 5, 2026: member

    @maflcko the motivation is the very first sentence of the PR description:

    While working on #33922 I initially forgot to add CTransactionRefComp to the std::unordered_map<CTransactionRef defined there.

    I added a link to the specific comment.

  42. maflcko commented at 9:22 PM on June 9, 2026: member

    Yes, I've seen that, but it doesn't say the underlying risk/downside: Comparing pointers does not compare the objects itself. Maybe that is obvious, but the code also mentions it, so I think it can't hurt to put the words in the description. (GitHub has already broken (direct) links to some review comment for some reason, so purely relying on links here doesn't seem ideal)

    But just a nit, up to you.

  43. w0xlt commented at 11:38 PM on June 9, 2026: contributor

    lgtm ACK a9301cfa0730d1d08c9e982f990dfc8aa0b3a27a

  44. achow101 commented at 5:38 PM on June 10, 2026: member

    ACK a9301cfa0730d1d08c9e982f990dfc8aa0b3a27a

  45. achow101 merged this on Jun 10, 2026
  46. achow101 closed this on Jun 10, 2026


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-06-21 21:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me