refactor: bitcoin-config.h includes cleanup #29404

pull theuni wants to merge 1 commits into bitcoin:master from theuni:cleanup-config-h-headers2 changing 56 files +148 −76
  1. theuni commented at 6:19 pm on February 7, 2024: member

    As mentioned in #26924 (comment) and #29263 (comment), it is currently not safe to remove bitcoin-config.h includes from headers because some unrelated file might be depending on it.

    See also #26972 for discussion.

    Solve this by including the file directly everywhere it’s required, regardless of whether or not it’s already included by another header.

    There should be no functional change here, but it will allow us to safely remove includes from headers in the future.

    I’m afraid it’s a bit tedious to reproduce these commits, but it’s reasonably straightforward: Edit: See note below

     0# All commands executed from the src/ subdir.
     1
     2# Collect all tokens from bitcoin-config.h.in
     3# Isolate the tokens and remove blank lines
     4# Replace newlines with | and remove the last trailing one
     5# Collect all files which use these tokens
     6# Filter out subprojects (proper forwarding can be verified from Makefiles)
     7# Filter out .rc files
     8# Save to a text file
     9git grep -E -l `grep undef config/bitcoin-config.h.in | cut -d" " -f2 | grep -v '^$' | tr '\n' '|' | sed 's/|$//'` | grep -v -e "^leveldb/" -e "^secp256k1/" -e "^crc32c/" -e "^minisketch/" -e "^Makefile" -e "\.rc$" > files-with-config-include.txt
    10
    11# Find all files from the above list which don't include bitcoin-config.h
    12git grep -L -E "config/bitcoin-config.h" -- `cat files-with-config-include.txt`
    13
    14# Include them manually with the exception of some files in crypto:
    15# crypto/sha256_arm_shani.cpp crypto/sha256_avx2.cpp crypto/sha256_sse41.cpp crypto/sha256_x86_shani.cpp
    16# These are exceptions which don't use bitcoin-config.h, rather the Makefile.am adds these cppflags manually.
    17
    18# Commit changes. This should match the first commit of this PR.
    19
    20# Use the same search as above to find all files which DON'T use any config tokens
    21git grep -E -L `grep undef config/bitcoin-config.h.in | cut -d" " -f2 | grep -v '^$' | tr '\n' '|' | sed 's/|$//'` | grep -v -e "^leveldb/" -e "^secp256k1/" -e "^crc32c/" -e "^minisketch/" -e "^Makefile" -e "\.rc$" > files-without-config-include.txt
    22
    23# Manually remove the includes and commit changes. This should match the second commit of this PR.
    

    Edit: I’ll keep this old description for posterity, but the manual approach has been replaced with a scripted diff from TheCharlatan

  2. DrahtBot commented at 6:19 pm on February 7, 2024: contributor

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

    Code Coverage

    For detailed information about the code coverage, see the test coverage report.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK maflcko, TheCharlatan, hebasto, fanquake
    Concept ACK jonatack, epiccurious

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

  3. theuni commented at 6:22 pm on February 7, 2024: member

    Ping @maflcko

    This (or something like it) is a prerequisite for #29404.

    There doesn’t seem to be any sane way to make this a scripted diff or a clang-tidy transform, so it would be great if someone could reproduce my results.

  4. theuni force-pushed on Feb 7, 2024
  5. theuni commented at 7:41 pm on February 7, 2024: member

    Removed the include from interfaces/wallet.h which snuck in because of a comment:

    0//! function will be undefined in builds where ENABLE_WALLET is false.
    

    That was the only example of a false-positive that I managed to find.

  6. TheCharlatan commented at 12:12 pm on February 8, 2024: contributor

    I validated the patch by running: > iwyu_tool -p . -j $(nproc) -- -Xiwyu --max_line_length=180 -I/usr/lib/llvm-14/lib/clang/14/include/ -Xiwyu --mapping_file=/home/drgrid/bitcoin/contrib/devtools/iwyu/bitcoin.core.imp > iwyu_output.txt > cat iwyu_output.txt | awk '/should remove these lines:/ {file=$1} /- #include <config\/bitcoin-config.h>/ {split($NF, a, "-"); line=a[1]; if (!seen[file, line]++) print file " " a[1]}' | while read -r file line; do sed -i -e "$((line-1)),$((line+2))d" "src/$file"; done; > cat iwyu_output.txt | awk '/should add these lines:/ {file=$1} /^#include "bitcoin-config.h"/ {if (!seen[file]++) print file ";" "#include <config/bitcoin-config.h>" " " substr($0, index($0, "//"))}' | while IFS=";" read -r file include; do sed -i "/\/\/ file COPYING or http:\/\/www.opensource.org\/licenses\/mit-license.php\./a \\\\n\#if defined(HAVE_CONFIG_H)\\n$include\\n\#endif" "src/$file" ; done

    The script misses a few of the cases, because some subset of the bitcoin-config.h symbols are left commented or undefined, meaning IWYU is not capable of picking up on them. It does add the commented required symbol names though, which should be part of this patch in my opinion. I’ll try to come back with a scripted-diff solution for this.

    Maybe a tidy plugin doing a full text search during the pre-processor hook could work, which would be kind of similar to the process you already posted here. So I guess we could add a little rust lint job for this instead?

  7. in src/addrman.cpp:6 in 70171e012a outdated
    2@@ -3,6 +3,10 @@
    3 // Distributed under the MIT software license, see the accompanying
    4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
    5 
    6+#if defined(HAVE_CONFIG_H)
    


    maflcko commented at 3:43 pm on February 8, 2024:

    unrelated question: Is there any reason for this check? I understand that it is possible to leave the symbol unset and then set any symbols over the command line, but is anyone doing this, or is it realistic that anyone will ever do it?

    If not, it could make sense to unconditionally include the config header?

    Otherwise, I could see a bug silently sneak in when there is a typo in this line, such as #if defined(_HAVE_CONFIG_H) (or any other intentional or accidental typo)


    theuni commented at 8:30 pm on February 8, 2024:

    There are several headers (serialization comes to mind) that are very handy to use just by copying them out of our tree and using them as-is without a buildsystem. I do this quite often myself. I’d hate to give it up, but it’s also become a goal of mine to remove the need for any autoconf defines for low-level files like that. Not a hard goal, just a nice-to-have. And with c++20 we’re nearly there. See #29263 for a PR that does a good bit in this regard.

    It would also be a nice property for libbitcoinkernel though :)


    maflcko commented at 9:35 am on February 9, 2024:

    My thinking was that removing the guard doesn’t preclude to copy the header and use it elsewhere, instead it makes it obvious that some features are disabled, or may be misdetected (which could lead to bugs). The overhead of removing a single line of code after creating the copy seems worth it to notify the user of this fact? Also, the overall overhead of all users copying a few headers and having to remove a single line in some of them should be much less than the overhead on Bitcoin Core having to add at least two lines of code for each such include manually. (For example, IWYU doesn’t do it itself).

    So it seems like a win-win to me, but no strong opinion.


    maflcko commented at 8:25 am on February 13, 2024:
    Unless there’s an objection, I’d follow up with this in a follow-up?
  8. maflcko commented at 4:34 pm on February 8, 2024: member

    Include them manually with the exception of some files in crypto:

    unrelated question: Is there a reason they need to use the flag at all? The files are never compiled and linked when the flag isn’t set, so making them appear “empty” when the flag isn’t set is not needed?

  9. jonatack commented at 7:55 pm on February 8, 2024: contributor
    Concept ACK
  10. theuni commented at 8:26 pm on February 8, 2024: member

    Include them manually with the exception of some files in crypto:

    unrelated question: Is there a reason they need to use the flag at all? The files are never compiled and linked when the flag isn’t set, so making them appear “empty” when the flag isn’t set is not needed?

    Yeah, I agree. If there’s some historical reason for this, I’ve forgotten it. It makes sense to me to make it either optionally compiled or optionally opted in (or out) via a define, but I don’t see the need for both.

    I do seem to remember some tools (ar or ld) that didn’t like dealing with an empty file. So maybe it started as being unconditionally compiled with an ifdef to control, and became additionally guarded at the buildsystem level on top to account for those tools?

  11. TheCharlatan commented at 8:35 am on February 9, 2024: contributor

    Made this into a scripted-diff here: https://github.com/TheCharlatan/bitcoin/commit/e4186f771294a8b112bac759f92ea5e4bef8f168

    There are no differences with the patch in this PR, besides a single whitespace issue. Feel free to pick the commit and make this into a scripted-diff as well, though I’m not sure if it is worth it, since the script is a bit dense.

  12. epiccurious commented at 11:55 pm on February 10, 2024: none
    Concept ACK 70171e012a7cd6723aa2b07a3fb3d93920ec2010.
  13. theuni commented at 11:18 pm on February 12, 2024: member

    There doesn’t seem to be any sane way to make this a scripted diff @TheCharlatan saw this and said “hold my beer”. Amazing!

  14. theuni force-pushed on Feb 12, 2024
  15. theuni force-pushed on Feb 12, 2024
  16. DrahtBot added the label CI failed on Feb 12, 2024
  17. theuni force-pushed on Feb 12, 2024
  18. theuni commented at 11:41 pm on February 12, 2024: member

    Replaced my commit with @TheCharlatan’s artwork above.

    It doesn’t work in the c-i environment because bitcoin-config.h.in is missing. I added an ./autogen.sh to the script but that doesn’t help because that env doesn’t have autoconf.

    Next I tried prepending with a bare autoheader, which should be all that’s actually needed, but that’s missing too.

    Sadly, I’m not sure it’s worth continuing with this. Even if it does work, the verify script would have to modify the user’s tree which isn’t very nice :(

  19. TheCharlatan commented at 8:16 am on February 13, 2024: contributor

    Re #29404 (comment)

    It doesn’t work in the c-i environment because bitcoin-config.h.in is missing. I added an ./autogen.sh to the script but that doesn’t help because that env doesn’t have autoconf.

    Could just replace the first command then. Not as nice, but for the purpose of this PR, reviewers can run the mentioned command manually: https://github.com/TheCharlatan/bitcoin/commit/b78e3ce41168600a1e73cb079b7eba07893753c4 (also applies some fixes, because the verify script uses sh and not bash :P).

  20. theuni commented at 6:37 pm on February 13, 2024: member

    @TheCharlatan Sure, agreed it’s better than nothing. Not quite self-contained, but given that a few of us have independently arrived at what the correct diff should be, it’s easy to tell if it’s correct.

    Will take that commit.

  21. scripted-diff: Fix bitcoin_config_h includes
    -BEGIN VERIFY SCRIPT-
    
    regex_string='^(?!//).*(AC_APPLE_UNIVERSAL_BUILD|BOOST_PROCESS_USE_STD_FS|CHAR_EQUALS_INT8|CLIENT_VERSION_BUILD|CLIENT_VERSION_IS_RELEASE|CLIENT_VERSION_MAJOR|CLIENT_VERSION_MINOR|COPYRIGHT_HOLDERS|COPYRIGHT_HOLDERS_FINAL|COPYRIGHT_HOLDERS_SUBSTITUTION|COPYRIGHT_YEAR|ENABLE_ARM_SHANI|ENABLE_AVX2|ENABLE_EXTERNAL_SIGNER|ENABLE_SSE41|ENABLE_TRACING|ENABLE_WALLET|ENABLE_X86_SHANI|ENABLE_ZMQ|HAVE_BOOST|HAVE_BUILTIN_CLZL|HAVE_BUILTIN_CLZLL|HAVE_BYTESWAP_H|HAVE_CLMUL|HAVE_CONSENSUS_LIB|HAVE_CXX20|HAVE_DECL_BE16TOH|HAVE_DECL_BE32TOH|HAVE_DECL_BE64TOH|HAVE_DECL_BSWAP_16|HAVE_DECL_BSWAP_32|HAVE_DECL_BSWAP_64|HAVE_DECL_FORK|HAVE_DECL_FREEIFADDRS|HAVE_DECL_GETIFADDRS|HAVE_DECL_HTOBE16|HAVE_DECL_HTOBE32|HAVE_DECL_HTOBE64|HAVE_DECL_HTOLE16|HAVE_DECL_HTOLE32|HAVE_DECL_HTOLE64|HAVE_DECL_LE16TOH|HAVE_DECL_LE32TOH|HAVE_DECL_LE64TOH|HAVE_DECL_PIPE2|HAVE_DECL_SETSID|HAVE_DECL_STRERROR_R|HAVE_DEFAULT_VISIBILITY_ATTRIBUTE|HAVE_DLFCN_H|HAVE_DLLEXPORT_ATTRIBUTE|HAVE_ENDIAN_H|HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR|HAVE_FDATASYNC|HAVE_GETENTROPY_RAND|HAVE_GETRANDOM|HAVE_GMTIME_R|HAVE_INTTYPES_H|HAVE_LIBADVAPI32|HAVE_LIBCOMCTL32|HAVE_LIBCOMDLG32|HAVE_LIBGDI32|HAVE_LIBIPHLPAPI|HAVE_LIBKERNEL32|HAVE_LIBOLE32|HAVE_LIBOLEAUT32|HAVE_LIBSHELL32|HAVE_LIBSHLWAPI|HAVE_LIBUSER32|HAVE_LIBUUID|HAVE_LIBWINMM|HAVE_LIBWS2_32|HAVE_MALLOC_INFO|HAVE_MALLOPT_ARENA_MAX|HAVE_MINIUPNPC_MINIUPNPC_H|HAVE_MINIUPNPC_UPNPCOMMANDS_H|HAVE_MINIUPNPC_UPNPERRORS_H|HAVE_NATPMP_H|HAVE_O_CLOEXEC|HAVE_POSIX_FALLOCATE|HAVE_PTHREAD|HAVE_PTHREAD_PRIO_INHERIT|HAVE_STDINT_H|HAVE_STDIO_H|HAVE_STDLIB_H|HAVE_STRERROR_R|HAVE_STRINGS_H|HAVE_STRING_H|HAVE_STRONG_GETAUXVAL|HAVE_SYSCTL|HAVE_SYSCTL_ARND|HAVE_SYSTEM|HAVE_SYS_ENDIAN_H|HAVE_SYS_PRCTL_H|HAVE_SYS_RESOURCES_H|HAVE_SYS_SELECT_H|HAVE_SYS_STAT_H|HAVE_SYS_SYSCTL_H|HAVE_SYS_TYPES_H|HAVE_SYS_VMMETER_H|HAVE_THREAD_LOCAL|HAVE_TIMINGSAFE_BCMP|HAVE_UNISTD_H|HAVE_VM_VM_PARAM_H|LT_OBJDIR|PACKAGE_BUGREPORT|PACKAGE_NAME|PACKAGE_STRING|PACKAGE_TARNAME|PACKAGE_URL|PACKAGE_VERSION|PTHREAD_CREATE_JOINABLE|QT_QPA_PLATFORM_ANDROID|QT_QPA_PLATFORM_COCOA|QT_QPA_PLATFORM_MINIMAL|QT_QPA_PLATFORM_WINDOWS|QT_QPA_PLATFORM_XCB|QT_STATICPLUGIN|STDC_HEADERS|STRERROR_R_CHAR_P|USE_ASM|USE_BDB|USE_DBUS|USE_NATPMP|USE_QRCODE|USE_SQLITE|USE_UPNP|_FILE_OFFSET_BITS|_LARGE_FILES)'
    
    exclusion_files=":(exclude)src/minisketch :(exclude)src/crc32c :(exclude)src/secp256k1 :(exclude)src/crypto/sha256_arm_shani.cpp :(exclude)src/crypto/sha256_avx2.cpp :(exclude)src/crypto/sha256_sse41.cpp :(exclude)src/crypto/sha256_x86_shani.cpp"
    
    git grep --perl-regexp --files-with-matches "$regex_string" -- '*.cpp' $exclusion_files | xargs git grep -L "bitcoin-config.h" | while read -r file; do line_number=$(awk -v my_file="$file" '/\/\/ file COPYING or https?:\/\/www.opensource.org\/licenses\/mit-license.php\./ {line = NR} /^\/\// && NR == line + 1 {while(getline && /^\/\//) line = NR} END {print line+1}' "$file"); sed -i "${line_number}i\\\\n\#if defined(HAVE_CONFIG_H)\\n#include <config/bitcoin-config.h>\\n\#endif" "$file"; done;
    
    git grep --perl-regexp --files-with-matches "$regex_string" -- '*.h' $exclusion_files | xargs git grep -L "bitcoin-config.h" | while read -r file; do sed -i "/#define.*_H/a \\\\n\#if defined(HAVE_CONFIG_H)\\n#include <config/bitcoin-config.h>\\n\#endif" "$file"; done;
    
    for file in $(git grep --files-with-matches 'bitcoin-config.h' -- '*.cpp' '*.h' $exclusion_files); do if ! grep -q --perl-regexp "$regex_string" $file; then sed -i '/HAVE_CONFIG_H/{N;N;N;d;}' $file; fi; done;
    
    -END VERIFY SCRIPT-
    
    The first command creates a regular expression for matching all bitcoin-config.h symbols in the following form: ^(?!//).*(AC_APPLE_UNIVERSAL_BUILD|BOOST_PROCESS_USE_STD_FS|...|_LARGE_FILES). It was generated with:
    ./autogen.sh && printf '^(?!//).*(%s)' $(awk '/^#undef/ {print $2}' src/config/bitcoin-config.h.in | paste -sd "|" -)
    
    The second command holds a list of files and directories that should not be processed. These include subtree directories as well as some crypto files that already get their symbols through the makefile.
    
    The third command checks for missing bitcoin-config headers in .cpp files and adds the header if it is missing.
    
    The fourth command checks for missing bitcoin-config headers in .h files and adds the header if it is missing.
    
    The fifth command checks for unneeded bitcoin-config headers in sources files and removes the header if it is unneeded.
    9d1dbbd4ce
  22. theuni force-pushed on Feb 13, 2024
  23. DrahtBot removed the label CI failed on Feb 13, 2024
  24. hebasto commented at 1:34 pm on February 15, 2024: member

    Concept ACK.

    #29404 (comment):

    So I guess we could add a little … lint job for this instead?

    Agree. Without a linter, the code might be drifted back in its current state.

  25. maflcko commented at 2:26 pm on February 15, 2024: member

    It would be interesting where this changes the code. I presume the places are:

    • The timingsafe_bcmp impl in the code was previously always picked. Now it may or may not be picked.
    • LogQtInfo will always print “dynamic” for plugin. Now it will print the correct thing.

    Also, there is an iwyu false-positive in the CI output:

    0httpserver.cpp should remove these lines:
    1- #include <config/bitcoin-config.h>  // lines 6-6
    
  26. maflcko commented at 2:26 pm on February 15, 2024: member

    ACK 9d1dbbd4ceb8c04340927f5127195dc306adf3f 🚪

    Signature:

    0untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
    1RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
    2trusted comment: ACK 9d1dbbd4ceb8c04340927f5127195dc306adf3f 🚪
    3HvZ6TDJIggqv10zJMB4fjX1k9ctbrU9io7T5b+6A1S7hmM31kL4OefrOTWQjQYmPiOyhpWQSXrt38WoH8hVgBw==
    
  27. DrahtBot requested review from hebasto on Feb 15, 2024
  28. DrahtBot requested review from jonatack on Feb 15, 2024
  29. theuni commented at 8:16 pm on February 15, 2024: member
    * The `timingsafe_bcmp` impl in the code was previously always picked. Now it may or may not be picked.
    

    At least for now, this one should be coming from crypto/common.h. That wouldn’t have been the case after #29263 though.

  30. maflcko commented at 9:00 pm on February 15, 2024: member
    Ah, good point. So it looks like right now this is a refactor, and shouldn’t change the binary on any platform? If you agree, you can add the refactor: prefix to the pull request title.
  31. theuni renamed this:
    bitcoin-config.h includes cleanup
    refactor: bitcoin-config.h includes cleanup
    on Feb 16, 2024
  32. DrahtBot added the label Refactoring on Feb 16, 2024
  33. theuni commented at 5:37 pm on February 16, 2024: member
    PR title an description updated.
  34. maflcko requested review from TheCharlatan on Feb 19, 2024
  35. maflcko added the label DrahtBot Guix build requested on Feb 19, 2024
  36. TheCharlatan approved
  37. TheCharlatan commented at 12:21 pm on February 19, 2024: contributor
    ACK 9d1dbbd4ceb8c04340927f5127195dc306adf3fc
  38. hebasto approved
  39. hebasto commented at 3:00 pm on February 19, 2024: member
    ACK 9d1dbbd4ceb8c04340927f5127195dc306adf3fc, I have reviewed the code and it looks OK.
  40. DrahtBot commented at 9:22 pm on February 19, 2024: contributor

    Guix builds (on x86_64)

    File commit 3cbc8cbc71d3d6ecfaf41164ce59c24ac94bae99(master) commit 82f19dbca57619d2909df95af044e9c3f76da2b1(master and this pull)
    SHA256SUMS.part 09096ba05ec1a6ce... 7284c7b9f9a4b068...
    *-aarch64-linux-gnu-debug.tar.gz eefa1f348909dab6... f531cd0946ea0f03...
    *-aarch64-linux-gnu.tar.gz 80431debc5f713f7... 82cd8e0853c524c0...
    *-arm-linux-gnueabihf-debug.tar.gz b64d310d6443013f... 39ce34d8ab85ac06...
    *-arm-linux-gnueabihf.tar.gz 1dec607fce40d7e0... 77eb89bbe0e3b5c5...
    *-arm64-apple-darwin-unsigned.tar.gz 6f73fe8dd6032796... a144ae3c6e139d5a...
    *-arm64-apple-darwin-unsigned.zip fc0415d43de4272f... 4b0ecae3e5d09d83...
    *-arm64-apple-darwin.tar.gz 898fe2cffff08af3... a58329b6796a43e5...
    *-powerpc64-linux-gnu-debug.tar.gz 61ed4d97bc1cdab0... aab697e4a0866714...
    *-powerpc64-linux-gnu.tar.gz 12088845cd03ff54... 3ce6353da3475758...
    *-powerpc64le-linux-gnu-debug.tar.gz fe7761ddb8daa8f3... 8541e4f5221d015e...
    *-powerpc64le-linux-gnu.tar.gz 31f3ac1830488de5... d30035e906c99a5d...
    *-riscv64-linux-gnu-debug.tar.gz 87208aa0655bc41a... 4db9363189ca6480...
    *-riscv64-linux-gnu.tar.gz d64326ec00c6da8e... 0d0202fbfcbd36a0...
    *-x86_64-apple-darwin-unsigned.tar.gz 455bcb971dd9c82f... 0eccae1bf1946fe1...
    *-x86_64-apple-darwin-unsigned.zip 21d3464f68f9e37d... 96de578eb7de8a2b...
    *-x86_64-apple-darwin.tar.gz 94eb1efdaf765b77... 3eaa9f86f279e7b0...
    *-x86_64-linux-gnu-debug.tar.gz 0e8067199808b910... d70b2547c0dba4ce...
    *-x86_64-linux-gnu.tar.gz 4db39dd75d018295... d64e0496fcc5c1e3...
    *.tar.gz 84a94e3093081baf... dc3912e76f3a627d...
    guix_build.log f1d3772a0147f2b8... 495f89b1b7b4db63...
    guix_build.log.diff a68ca74e42e7a50f...
  41. DrahtBot removed the label DrahtBot Guix build requested on Feb 19, 2024
  42. fanquake commented at 11:34 am on February 20, 2024: member
    Note there are at least two defines missing from the scriptied diff (_TIME_BITS & __MINGW_USE_VC2005_COMPAT), if using Autoconf 2.72 , however that should not make a difference here. Looks like WORDS_BIGENDIAN is also missing, but that should also be ok.
  43. maflcko commented at 11:54 am on February 20, 2024: member

    Looks like WORDS_BIGENDIAN is also missing, but that should also be ok.

    It is covered in #29408, in any case.

  44. fanquake approved
  45. fanquake commented at 1:06 pm on February 20, 2024: member
    ACK 9d1dbbd4ceb8c04340927f5127195dc306adf3fc
  46. fanquake merged this on Feb 20, 2024
  47. fanquake closed this on Feb 20, 2024


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: 2024-12-03 18:12 UTC

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