Replace -Wthread-safety-analysis with broader -Wthread-safety #18635

pull hebasto wants to merge 5 commits into bitcoin:master from hebasto:200414-threads changing 9 files +34 −24
  1. hebasto commented at 5:17 pm on April 14, 2020: member
    This PR gets rid of -Wthread-safety-attributes and -Wthread-safety-precise warnings, and replaces -Wthread-safety-analysis compiler option with the broader -Wthread-safety one.
  2. hebasto marked this as a draft on Apr 14, 2020
  3. hebasto renamed this:
    Revert "Annotate AssertLockHeld() with ASSERT_CAPABILITY() for thread safety analysis"
    [WIP] Revert "Annotate AssertLockHeld() with ASSERT_CAPABILITY() for thread safety analysis"
    on Apr 14, 2020
  4. hebasto force-pushed on Apr 14, 2020
  5. hebasto renamed this:
    [WIP] Revert "Annotate AssertLockHeld() with ASSERT_CAPABILITY() for thread safety analysis"
    Suppress -Wthread-safety-attributes warning spam
    on Apr 14, 2020
  6. hebasto marked this as ready for review on Apr 14, 2020
  7. fanquake requested review from ajtowns on May 7, 2020
  8. in src/sync.cpp:197 in b6e44c3fd4 outdated
    193+            return;
    194+    tfm::format(std::cerr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
    195+    abort();
    196+}
    197+
    198+void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, Mutex* cs)
    


    ajtowns commented at 3:30 am on May 7, 2020:

    Rather than duplicating the function, you can use a template:

    0template<typename PARENT>
    1void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, AnnotatedMixin<PARENT>* cs)
    2{ ... }
    3
    4template void AssertLockHeldInternal(const char*, const char*, int, Mutex*);
    5template void AssertLockHeldInternal(const char*, const char*, int, RecursiveMutex*);
    

    That means changing the header to:

    0template<typename PARENT>
    1void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, AnnotatedMixin<PARENT>* cs) ASSERT_EXCLUSIVE_LOCK(cs);
    

    to match.

    Or alternatively, don’t touch sync.cpp file at all, drop the ASSERT_EXCLUSIVE_LOCK(cs) from AssertLockHeldInternal and change AssertLockHeld to:

    0template<typename PARENT>
    1void static inline AssertLockHeldInternalTyped(const char* pszName, const char* pszFile, int nLine, AnnotatedMixin<PARENT>* cs) ASSERT_EXCLUSIVE_LOCK(cs) { AssertLockHeldInternal(pszName, pszFile, nLine, (void*)cs); };
    2
    3#define AssertLockHeld(cs) AssertLockHeldInternalTyped(#cs, __FILE__, __LINE__, &cs)
    

    vasild commented at 10:16 am on May 7, 2020:

    Right, in C the “any type” is void*, whereas in C++ we have templates.

    That void* typecast at the bottom of the comment above is like sweeping it under the carpet and it still leaves the possibility to use AssertLockHeldInternal() in a type unsafe way (because it takes void* argument).


    hebasto commented at 9:17 am on May 9, 2020:
  9. in src/sync.h:120 in b6e44c3fd4 outdated
    116@@ -110,7 +117,7 @@ class LOCKABLE AnnotatedMixin : public PARENT
    117 using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
    118 
    119 /** Wrapped mutex: supports waiting but not recursive locking */
    120-typedef AnnotatedMixin<std::mutex> Mutex;
    121+using Mutex = AnnotatedMixin<std::mutex>;
    


    ajtowns commented at 3:31 am on May 7, 2020:
    No need to repeat the definitions of Mutex and RecursiveMutex after you added the definitions above.

    hebasto commented at 9:17 am on May 9, 2020:
  10. ajtowns commented at 4:37 am on May 7, 2020: member
    It’s not clear to me what the value of adding -Wthread-safety-attributes is, but better typing makes sense in general to me.
  11. hebasto commented at 7:47 am on May 7, 2020: member

    @ajtowns

    It’s not clear to me what the value of adding -Wthread-safety-attributes is, but better typing makes sense in general to me.

    From the Thread Safety Analysis docs:

    -Wthread-safety-attributes: Sanity checks on attribute syntax.

  12. vasild commented at 10:09 am on May 7, 2020: member

    Concept ACK

    I confirm that if master (3b1e28924) is compiled with -Wthread-safety-attributes then some warnings are shown. This patch fixes all such warnings (Clang 11, FreeBSD 12).

    I agree with @ajtowns that it would be better to use a template than duplicating the function body. Further, instead of template<typename PARENT> / AnnotatedMixin<PARENT>* cs we can use template <typename MutexType> / MutexType* cs - that is simpler and removes the need to move the Mutex and RecursiveMutex definitions higher in sync.h. Just to be explicit, this is what I mean:

     0diff --git i/src/sync.cpp w/src/sync.cpp
     1index 67779b33a..8fc7f5d97 100644
     2--- i/src/sync.cpp
     3+++ w/src/sync.cpp
     4@@ -182,29 +182,25 @@ std::string LocksHeld()
     5     std::string result;
     6     for (const std::pair<void*, CLockLocation>& i : g_lockstack)
     7         result += i.second.ToString() + std::string("\n");
     8     return result;
     9 }
    10 
    11-void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, RecursiveMutex* cs)
    12+template <typename MutexType>
    13+void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs)
    14 {
    15     for (const std::pair<void*, CLockLocation>& i : g_lockstack)
    16         if (i.first == cs)
    17             return;
    18     tfm::format(std::cerr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
    19     abort();
    20 }
    21 
    22-void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, Mutex* cs)
    23-{
    24-    for (const std::pair<void*, CLockLocation>& i : g_lockstack)
    25-        if (i.first == cs)
    26-            return;
    27-    tfm::format(std::cerr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
    28-    abort();
    29-}
    30+// Explicitly instantiate for Mutex and RecursiveMutex.
    31+template void AssertLockHeldInternal(const char*, const char*, int, Mutex*);
    32+template void AssertLockHeldInternal(const char*, const char*, int, RecursiveMutex*);
    33 
    34 void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
    35 {
    36     for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
    37         if (i.first == cs) {
    38             tfm::format(std::cerr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
    39diff --git i/src/sync.h w/src/sync.h
    40index 78adf29c0..60e5a87ae 100644
    41--- i/src/sync.h
    42+++ w/src/sync.h
    43@@ -11,17 +11,12 @@
    44 
    45 #include <condition_variable>
    46 #include <mutex>
    47 #include <string>
    48 #include <thread>
    49 
    50-template <typename PARENT>
    51-class AnnotatedMixin;
    52-using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
    53-using Mutex = AnnotatedMixin<std::mutex>;
    54-
    55 ////////////////////////////////////////////////
    56 //                                            //
    57 // THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //
    58 //                                            //
    59 ////////////////////////////////////////////////
    60 
    61@@ -54,14 +49,14 @@ LEAVE_CRITICAL_SECTION(mutex); // no RAII
    62 
    63 #ifdef DEBUG_LOCKORDER
    64 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
    65 void LeaveCritical();
    66 void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
    67 std::string LocksHeld();
    68-void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, RecursiveMutex* cs) ASSERT_EXCLUSIVE_LOCK(cs);
    69-void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, Mutex* cs) ASSERT_EXCLUSIVE_LOCK(cs);
    70+template <typename MutexType>
    71+void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) ASSERT_EXCLUSIVE_LOCK(cs);
    72 void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
    73 void DeleteLock(void* cs);
    74 
    75 /**
    76  * Call abort() if a potential lock order deadlock bug is detected, instead of
    77  * just logging information and throwing a logic_error. Defaults to true, and
    78@@ -69,14 +64,14 @@ void DeleteLock(void* cs);
    79  */
    80 extern bool g_debug_lockorder_abort;
    81 #else
    82 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
    83 void static inline LeaveCritical() {}
    84 void static inline CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
    85-void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, RecursiveMutex* cs) ASSERT_EXCLUSIVE_LOCK(cs) {}
    86-void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, Mutex* cs) ASSERT_EXCLUSIVE_LOCK(cs) {}
    87+template <typename MutexType>
    88+void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) ASSERT_EXCLUSIVE_LOCK(cs) {}
    89 void static inline AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
    90 void static inline DeleteLock(void* cs) {}
    91 #endif
    92 #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
    93 #define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs)
    94 
    

    Maybe add thread-safety-attributes to the warnings flags in configure.ac to make sure future changes do not introduce such warnings:

     0diff --git i/configure.ac w/configure.ac
     1index 4c9902efc..e19346e59 100644
     2--- i/configure.ac
     3+++ w/configure.ac
     4@@ -326,12 +326,13 @@ if test "x$enable_werror" = "xyes"; then
     5   if test "x$CXXFLAG_WERROR" = "x"; then
     6     AC_MSG_ERROR("enable-werror set but -Werror is not usable")
     7   fi
     8   AX_CHECK_COMPILE_FLAG([-Werror=vla],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=vla"],,[[$CXXFLAG_WERROR]])
     9   AX_CHECK_COMPILE_FLAG([-Werror=switch],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=switch"],,[[$CXXFLAG_WERROR]])
    10   AX_CHECK_COMPILE_FLAG([-Werror=thread-safety-analysis],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=thread-safety-analysis"],,[[$CXXFLAG_WERROR]])
    11+  AX_CHECK_COMPILE_FLAG([-Werror=thread-safety-attributes],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=thread-safety-attributes"],,[[$CXXFLAG_WERROR]])
    12   AX_CHECK_COMPILE_FLAG([-Werror=unused-variable],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=unused-variable"],,[[$CXXFLAG_WERROR]])
    13   AX_CHECK_COMPILE_FLAG([-Werror=date-time],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=date-time"],,[[$CXXFLAG_WERROR]])
    14   AX_CHECK_COMPILE_FLAG([-Werror=return-type],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=return-type"],,[[$CXXFLAG_WERROR]])
    15 fi
    16
    17 if test "x$CXXFLAGS_overridden" = "xno"; then
    18@@ -339,12 +340,13 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
    19   AX_CHECK_COMPILE_FLAG([-Wextra],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]])
    20   AX_CHECK_COMPILE_FLAG([-Wformat],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
    21   AX_CHECK_COMPILE_FLAG([-Wvla],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
    22   AX_CHECK_COMPILE_FLAG([-Wswitch],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wswitch"],,[[$CXXFLAG_WERROR]])
    23   AX_CHECK_COMPILE_FLAG([-Wformat-security],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
    24   AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
    25+  AX_CHECK_COMPILE_FLAG([-Wthread-safety-attributes],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety-attributes"],,[[$CXXFLAG_WERROR]])
    26   AX_CHECK_COMPILE_FLAG([-Wrange-loop-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wrange-loop-analysis"],,[[$CXXFLAG_WERROR]])
    27   AX_CHECK_COMPILE_FLAG([-Wredundant-decls],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wredundant-decls"],,[[$CXXFLAG_WERROR]])
    28   AX_CHECK_COMPILE_FLAG([-Wunused-variable],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wunused-variable"],,[[$CXXFLAG_WERROR]])
    29   AX_CHECK_COMPILE_FLAG([-Wdate-time],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wdate-time"],,[[$CXXFLAG_WERROR]])
    30
    31   dnl Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
    
  13. hebasto force-pushed on May 9, 2020
  14. hebasto commented at 9:13 am on May 9, 2020: member

    Updated:

    • addressed @ajtowns’s and @vasild’s comments
    • rebased
    • added two commits that allow to replace -Wthread-safety-analysis with broader -Wthread-safety

    The OP has been updated.

  15. hebasto renamed this:
    Suppress -Wthread-safety-attributes warning spam
    Replace -Wthread-safety-analysis with broader -Wthread-safety
    on May 9, 2020
  16. DrahtBot added the label Build system on May 9, 2020
  17. DrahtBot added the label RPC/REST/ZMQ on May 9, 2020
  18. DrahtBot added the label Wallet on May 9, 2020
  19. in src/blockencodings.cpp:113 in 6bc97d0f86 outdated
    112+        uint64_t shortid = cmpctblock.GetShortID(pool->vTxHashes[i].first);
    113         std::unordered_map<uint64_t, uint16_t>::iterator idit = shorttxids.find(shortid);
    114         if (idit != shorttxids.end()) {
    115             if (!have_txn[idit->second]) {
    116-                txn_available[idit->second] = vTxHashes[i].second->GetSharedTx();
    117+                txn_available[idit->second] = pool->vTxHashes[i].second->GetSharedTx();
    


    MarcoFalke commented at 1:54 pm on May 9, 2020:

    Since you are touching all the lines where pool is used anyway, mind to make it const, since the access is read-only?

     0diff --git a/src/blockencodings.h b/src/blockencodings.h
     1index 377ac3a1a6..6efcc8c9c9 100644
     2--- a/src/blockencodings.h
     3+++ b/src/blockencodings.h
     4@@ -125,7 +125,8 @@ class PartiallyDownloadedBlock {
     5 protected:
     6     std::vector<CTransactionRef> txn_available;
     7     size_t prefilled_count = 0, mempool_count = 0, extra_count = 0;
     8-    CTxMemPool* pool;
     9+    const CTxMemPool* pool;
    10+
    11 public:
    12     CBlockHeader header;
    13     explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {}
    

    hebasto commented at 5:30 am on May 10, 2020:
  20. MarcoFalke commented at 1:54 pm on May 9, 2020: member
    Concept ACK
  21. DrahtBot commented at 7:21 pm on May 9, 2020: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #18882 (build: fix -Wformat-security check when compiling with GCC by fanquake)
    • #18857 (build: avoid repetitions when enabling warnings in configure.ac by vasild)
    • #18354 (Use shared pointers only in validation interface by bvbfan)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  22. hebasto force-pushed on May 10, 2020
  23. hebasto commented at 5:29 am on May 10, 2020: member

    Updated 6bc97d0f860b52933b5664386576876d61ae228c -> 7a54927d2f068fef1638b3f6e3f5d7b52be22edf (pr18635.03 -> pr18635.04, diff):

    Since you are touching all the lines where pool is used anyway, mind to make it const, since the access is read-only?

  24. vasild approved
  25. vasild commented at 9:05 am on May 11, 2020: member

    ACK 7a54927d2

    It compiles locally with Clang 11 using the new flags without thread-safety related warnings.

  26. ajtowns commented at 6:46 am on May 12, 2020: member
    @hebasto Yeah, I saw the “sanity check” description, but it’s still not clear to me what that actually means. Changes for precise look good to me.
  27. ajtowns commented at 7:37 am on May 19, 2020: member
    Note that this conflicts with #16127 in that -Wthread-safety-attributes means you need to add a wrapper around any plain std::mutex instances in order to do thread safety analysis on them. Adding class LOCKABLE StdMutex : public std::mutex { }; and having #16127’s LockGuard refer to that instead of std::mutex seems to be sufficient to resolve the conflict, I think.
  28. hebasto commented at 7:50 am on May 19, 2020: member

    Note that this conflicts with #16127 in that -Wthread-safety-attributes means you need to add a wrapper around any plain std::mutex instances in order to do thread safety analysis on them. Adding class LOCKABLE StdMutex : public std::mutex { }; and having #16127’s LockGuard refer to that instead of std::mutex seems to be sufficient to resolve the conflict, I think.

    Agree. Hope #16127 will be merged soon.

  29. DrahtBot added the label Needs rebase on May 26, 2020
  30. hebasto force-pushed on May 26, 2020
  31. hebasto commented at 2:26 pm on May 26, 2020: member
    Rebased 7a54927d2f068fef1638b3f6e3f5d7b52be22edf -> 908c6c3cea5ffe3b9a9612f2327227cf3f54e5fc (pr18635.04 -> pr18635.05) due to the conflict with #18881.
  32. DrahtBot removed the label Needs rebase on May 26, 2020
  33. ryanofsky approved
  34. ryanofsky commented at 7:11 pm on May 27, 2020: member
    Code review ACK 908c6c3cea5ffe3b9a9612f2327227cf3f54e5fc. It seems good to enable more static checking here, and the code changes are simple and straightforward
  35. practicalswift commented at 7:30 pm on May 27, 2020: contributor
    ACK 908c6c3cea5ffe3b9a9612f2327227cf3f54e5fc: patch looks correct, and more compile-time checking is better! :)
  36. ajtowns commented at 2:28 am on May 28, 2020: member
    Needs update now that #16127 is merged
  37. Add thread safety annotated wrapper for std::mutex
    Co-authored-by: Anthony Towns <aj@erisian.com.au>
    79be487420
  38. refactor: Rename LockGuard to StdLockGuard for consistency with StdMutex dfb75ae49d
  39. Use template function instead of void* parameter
    This change gets rid of -Wthread-safety-attributes warning spam.
    971a468ccf
  40. Get rid of -Wthread-safety-precise warnings 9cc6eb3c9e
  41. build: Replace -Wthread-safety-analysis with broader -Wthread-safety 87766b355c
  42. hebasto force-pushed on May 28, 2020
  43. hebasto commented at 7:05 am on May 28, 2020: member

    Rebased 908c6c3cea5ffe3b9a9612f2327227cf3f54e5fc -> 87766b355c47fcb0f0dcf3f6fe359eb00227d50c (pr18635.05 -> pr18635.06) due to the conflict with #16127:

    Note that this conflicts with #16127 in that -Wthread-safety-attributes means you need to add a wrapper around any plain std::mutex instances in order to do thread safety analysis on them. Adding class LOCKABLE StdMutex : public std::mutex { }; and having #16127’s LockGuard refer to that instead of std::mutex seems to be sufficient to resolve the conflict, I think.

  44. vasild approved
  45. vasild commented at 8:22 am on May 28, 2020: member
    ACK 87766b3
  46. practicalswift commented at 10:04 am on May 28, 2020: contributor
    ACK 87766b355c47fcb0f0dcf3f6fe359eb00227d50c – patch looks correct
  47. ajtowns commented at 11:26 am on May 28, 2020: member
    ACK 87766b355c47fcb0f0dcf3f6fe359eb00227d50c
  48. MarcoFalke commented at 2:47 pm on May 28, 2020: member

    ACK 87766b355c47fcb0f0dcf3f6fe359eb00227d50c 👍

    Signature:

     0-----BEGIN PGP SIGNED MESSAGE-----
     1Hash: SHA512
     2
     3ACK 87766b355c47fcb0f0dcf3f6fe359eb00227d50c 👍
     4-----BEGIN PGP SIGNATURE-----
     5
     6iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
     7pUi4iAwAg0uiwOcah5mJaVzZrOWF2rtKNZTQjr+KEZxWCBRuq1Q+GLJ7Dsf0cqwl
     8CWtPoyfI524dIxAEANrMOqlitZ0fS7PYfgWAHDKVgS4mXaYRUEH7YKs1aShz/0u8
     9ES1GiLCtAM7WCcvjeVTwsvQ7D8hXtRDyN86oXJnJg+WWJPtp0yd2dMuWhZNvLTiF
    10hRbv03wBr632i8dSlBG5y0libBVyPBozVMYAnVKmK3ZMlrLlUwYPtFPBwOmN+4cf
    114MrST70Ks90f+6Tlo6VbSoFbIvpNLYfM1g8saQDseA0y04q0h8y0og6WnUMzNYX5
    12QwJVr3hR9t50wbiKmAsdIPmFiOTlVu1pqbckAkgNCNmrHaASgNIuRfPR9WyP8fMq
    13CWYLw0727ZsUNKxCwEp18vIWkq9wZYVbXTM8GnfpfiA8FX8OH9FH+q7uroNH784N
    14Shf9kU2DPmOEHu8MG+7htpWRjHuEN/jVWCrxsoU66g1G7jREddIKNfoLDAzmB0p9
    15PlykKQ8f
    16=ufrW
    17-----END PGP SIGNATURE-----
    

    Timestamp of file with hash 55f3dcd9f7f76a0aa36c4f8d7721a03cda9bfb278201a4ebc4c064d229aba0a4 -

  49. MarcoFalke merged this on May 28, 2020
  50. MarcoFalke closed this on May 28, 2020

  51. hebasto deleted the branch on May 28, 2020
  52. jasonbcox referenced this in commit 902d495d4e on Oct 11, 2020
  53. jasonbcox referenced this in commit 08508a1417 on Oct 11, 2020
  54. jasonbcox referenced this in commit de6770e8a3 on Oct 11, 2020
  55. jasonbcox referenced this in commit 8465ae5d5a on Oct 11, 2020
  56. deadalnix referenced this in commit 3c9a54910e on Oct 12, 2020
  57. kittywhiskers referenced this in commit c12ed3633a on Jun 5, 2021
  58. kittywhiskers referenced this in commit 7c44302d0d on Jun 5, 2021
  59. kittywhiskers referenced this in commit 231e885590 on Jun 6, 2021
  60. kittywhiskers referenced this in commit c578b6444d on Jun 6, 2021
  61. kittywhiskers referenced this in commit fbc248c5ff on Jun 6, 2021
  62. UdjinM6 referenced this in commit 878d370b3e on Jun 6, 2021
  63. UdjinM6 referenced this in commit eb652da8a7 on Jun 6, 2021
  64. kittywhiskers referenced this in commit 5b70904229 on Jun 7, 2021
  65. kittywhiskers referenced this in commit 5d9e69fc57 on Jun 8, 2021
  66. kittywhiskers referenced this in commit d532622ecd on Jun 9, 2021
  67. kittywhiskers referenced this in commit 51fababb9c on Jun 10, 2021
  68. UdjinM6 referenced this in commit a8aee57447 on Jun 11, 2021
  69. DrahtBot locked this on Feb 15, 2022

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-06-29 10:13 UTC

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