feature: Use different datadirs for different signets #34566

pull ekzyis wants to merge 4 commits into bitcoin:master from ekzyis:signet-datadirs changing 12 files +158 −36
  1. ekzyis commented at 7:46 PM on February 11, 2026: none

    closes #27494

    This adds support for syncing multiple signets.

    Each custom signet is stored in a different datadir, using the network magic (message start) as the suffix.

    The default signet is always stored without a suffix for backward compatibility, even if the default challenge is provided explicitly via -signetchallenge.

    This builds upon #29838.

    For those already familiar with #29838, here are the differences between #29838 and this that are visible to the user:

    [^1]: could be something for a follow-up PR, or maybe it's intentional to not mix explicit with implicit options?

    Unlike #29838, this PR does not update tests that didn't break (rpc_bind.py, interface_bitcoin_cli.py). I have found other tests where datadir_path is used in combination with self.chain (regexp: datadir_path.*chain). I considered it inconsistent to update some tests but not all of them. I've decided to not update all of them to keep the scope of this PR low until feedback. I can go through all tests in a follow-up PR to make sure they don't break when they are ever used with (custom) signet, however unlikely that might be.

    I have done some manual testing like this:

    <details> <summary>manual testing</summary>

    1. 'signet' directory is used, IBD:
    $ bitcoind -signet
    
    1. 'signet' directory is used, no IBD without -addnode (see #29838 (comment)) or existing peers.dat:
    $ bitcoind -signet -signetchallenge=512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae
    
    1. 'signet' directory is used
    $ bitcoind -conf="signet_default.conf"
    
    # signet_default.conf
    signet=1
    [signet]
    signetchallenge=512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae
    
    1. 'signet_f6ac8550' directory is used:
    $ bitcoind -conf="signet_custom.conf"
    
    # signet_custom.conf
    signet=1
    [signet]
    signetchallenge=0014d4528367459d54e1545b0d0a677d2a7d71d648e0
    

    Tested RPC with bitcoin-cli getblockchaininfo with the same options (-signet, -conf, or -signet -signetchallenge)

    </details>

    I'm new to contributing to Bitcoin Core so it's entirely possible that I've missed something obvious.

  2. DrahtBot commented at 7:47 PM on February 11, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK pinheadmz, RandyMcMillan

    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.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35011 (ci, iwyu: Fix warnings in src/script and treat them as errors by BrandonOdiwuor)
    • #34927 (test: Check that RPCs do not time out, even under load by maflcko)
    • #28690 (build: Introduce internal kernel library by sedited)

    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.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible places where named args for integral literals may be used (e.g. func(x, /*named_arg=*/0) in C++, and func(x, named_arg=0) in Python):

    • wallet_importprivkey(node, bytes_to_wif(CHALLENGE_PRIVATE_KEY), 0) in test/functional/tool_signet_miner.py

    Possible places where comparison-specific test macros should replace generic comparisons:

    • [test/functional/tool_signet_miner.py] assert get_signet_commitment(get_segwit_commitment(node)) is None -> use assert_equal(get_signet_commitment(get_segwit_commitment(node)), None)

    <sup>2026-04-21 23:20:14</sup>

  3. ekzyis marked this as a draft on Feb 11, 2026
  4. ekzyis commented at 8:04 PM on February 11, 2026: none

    Will keep this in draft until I fix why tool_signet_miner.py is failing in CI (but not locally for some reason)

    Update: Ah, it's because the CI runs it with --usecli

  5. DrahtBot added the label CI failed on Feb 11, 2026
  6. ekzyis force-pushed on Feb 11, 2026
  7. ekzyis force-pushed on Feb 12, 2026
  8. ekzyis force-pushed on Feb 12, 2026
  9. ekzyis renamed this:
    feature: Use separate datadirs for each signet
    feature: Use different datadirs for different signets
    on Feb 12, 2026
  10. ekzyis force-pushed on Feb 12, 2026
  11. ekzyis force-pushed on Feb 12, 2026
  12. DrahtBot removed the label CI failed on Feb 12, 2026
  13. ekzyis marked this as ready for review on Feb 12, 2026
  14. ekzyis force-pushed on Feb 12, 2026
  15. sedited commented at 5:09 PM on March 8, 2026: contributor

    This hasn't gotten any attention so far. @ajtowns do you want to take a look here since you opened the original issue?

  16. ekzyis force-pushed on Apr 6, 2026
  17. ekzyis commented at 11:12 PM on April 6, 2026: none

    rebased on master (b730dc3301f)

  18. in test/functional/feature_signet.py:125 in c4765b3c3a outdated
     120 | +        self.log.info("Test that the signet data directory with -signetchallenge=51 is 'signet_51'")
     121 | +        assert_node_datadir(self.nodes[0], "signet_51")
     122 | +
     123 | +        self.log.info("Test that the main signet data directory is 'signet'")
     124 | +        assert_node_datadir(self.nodes[3], "signet")
     125 | +
    


    ViniciusCestarii commented at 1:23 PM on April 8, 2026:

    Missing a test that verifies truncation to 16 chars for a longer challenge. The 522103ad5e... signet challenge would work. Just add an assert_node_datadir(self.nodes[4], "signet_522103ad5e0edad1") check.


    ekzyis commented at 1:43 PM on April 8, 2026:

    Oh, right, thanks! Done in a2d755132b4

  19. in src/chainparamsbase.cpp:40 in c4765b3c3a outdated
      32 | @@ -33,6 +33,18 @@ const CBaseChainParams& BaseParams()
      33 |      return *globalChainBaseParams;
      34 |  }
      35 |  
      36 | +std::string GetSignetDataDir()
      37 | +{
      38 | +    std::string base_data_dir = "signet";
      39 | +    const std::string signet_challenge = gArgs.GetArg("-signetchallenge", "");
      40 | +    const std::string default_signet_challenge = "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae";
    


    ViniciusCestarii commented at 1:38 PM on April 8, 2026:

    The default signet challenge string is now duplicated in chainparamsbase.cpp and kernel/chainparams.cpp (and also in the Python test framework). I'm not sure if this is actually a problem, but could this be defined as a shared constant? I'm still learning the codebase, so I'd appreciate some input for better practices here.


    ekzyis commented at 1:46 PM on April 8, 2026:

    I had the same question, and since I’m also new, I was hoping for feedback from more experienced developers as well


    ekzyis commented at 2:19 PM on April 8, 2026:

    I fixed this in 63cf3340748.

    I added test/functional/test_framework/signet.py so test_node.py and feature_signet.py can import the constant from there.

    For the C++ code, I'm now using HexStr(CChainParams::SigNet({})->GetConsensus().signet_challenge).

    Thanks for making me look into it again!


    ekzyis commented at 2:21 PM on April 8, 2026:

    Oh, this introduced a circular dependency:

    A new circular dependency in the form of "chainparams -> chainparamsbase -> chainparams" appears to have been introduced.

    https://github.com/bitcoin/bitcoin/actions/runs/24139839220/job/70438028501?pr=34566


    ekzyis commented at 3:34 PM on April 8, 2026:

    Fixed in 364969087e0. I accidentally included <chainparams.h> in chainparamsbase.cpp instead of <kernel/chainparams.h>.

  20. ekzyis force-pushed on Apr 8, 2026
  21. ekzyis force-pushed on Apr 8, 2026
  22. DrahtBot added the label CI failed on Apr 8, 2026
  23. ekzyis marked this as a draft on Apr 8, 2026
  24. ekzyis force-pushed on Apr 8, 2026
  25. DrahtBot removed the label CI failed on Apr 8, 2026
  26. in test/functional/tool_signet_miner.py:131 in 364969087e outdated
     127 | @@ -121,33 +128,33 @@ def run_test(self):
     128 |          node = self.nodes[0]
     129 |          # import private key needed for signing block
     130 |          wallet_importprivkey(node, bytes_to_wif(CHALLENGE_PRIVATE_KEY), 0)
     131 | -        self.mine_block(node)
     132 | +        self.mine_block(node, self.extra_args[0])
    


    pinheadmz commented at 4:02 PM on April 8, 2026:

    what is the extra_args parameter for?


    ekzyis commented at 5:22 PM on April 8, 2026:

    This passes the signet challenge of the node to mine_block. It's required to pass -signetchallenge to the RPC. Without it, RPC authentication fails because the cookie isn't found. It will look in the default signet datadir:

    $ build/test/functional/test_runner.py tool_signet_miner.py
    Temporary test directory at /tmp/nix-shell-115046-4006075642/test_runner_₿_šŸƒ_20260408_191958
    Remaining jobs: [tool_signet_miner.py]
    1/1 - tool_signet_miner.py failed, Duration: 0 s
    
    stdout:
    2026-04-08T17:19:58.648068Z TestFramework (INFO): PRNG seed is: 8822581970357866232
    2026-04-08T17:19:58.698730Z TestFramework (INFO): Initializing test directory /tmp/nix-shell-115046-4006075642/test_runner_₿_šŸƒ_20260408_191958/tool_signet_miner_0
    2026-04-08T17:19:59.085274Z TestFramework (INFO): Signet node with single signature challenge
    error: Authorization failed: Failed to read cookie file and no rpcpassword was specified. Configuration file: (/tmp/nix-shell-115046-4006075642/test_runner_₿_šŸƒ_20260408_191958/tool_signet_miner_0/node0/bitcoin.conf)
    

    pinheadmz commented at 5:31 PM on April 17, 2026:

    I think it would make more sense if you just changed the name of the argument then:

    def mine_block(self, node, extra_args):
    

    Since this is how its being used (just appending args to a CLI command)


    ekzyis commented at 5:48 PM on April 21, 2026:

    Done in 8824d95819

  27. pinheadmz commented at 4:03 PM on April 8, 2026: member

    concept ACK, I use a lot of different signets for educational projects and we could really use this. Personally I feel like using the magic bytes (message start) makes more sense and is less likely to collide between signet challenges

  28. ekzyis marked this as ready for review on Apr 8, 2026
  29. ekzyis force-pushed on Apr 8, 2026
  30. ekzyis force-pushed on Apr 8, 2026
  31. DrahtBot added the label CI failed on Apr 8, 2026
  32. ekzyis force-pushed on Apr 8, 2026
  33. ekzyis commented at 8:09 PM on April 8, 2026: none

    concept ACK, I use a lot of different signets for educational projects and we could really use this. Personally I feel like using the magic bytes (message start) makes more sense and is less likely to collide between signet challenges

    Right! 77cd6c99306 uses magic bytes as the suffix. Additionally to what you mentioned, I also like this for these reasons:

    • makes directory names shorter (was also mentioned in #29383 (comment))
    • consistent suffix length, independent of challenge length

    Updated commit message and PR description.

  34. DrahtBot removed the label CI failed on Apr 8, 2026
  35. RandyMcMillan commented at 2:31 PM on April 9, 2026: contributor

    concept ACK

  36. ekzyis force-pushed on Apr 10, 2026
  37. ekzyis commented at 11:50 AM on April 10, 2026: none

    I think "notable new feature" and "visible change to the end-user experience" from developer-notes.md apply here, so I added release notes in f283eaa.

  38. in src/chainparamsbase.cpp:43 in f283eaac1d outdated
      37 | @@ -33,6 +38,28 @@ const CBaseChainParams& BaseParams()
      38 |      return *globalChainBaseParams;
      39 |  }
      40 |  
      41 | +std::string GetSignetDataDir()
      42 | +{
      43 | +    std::string base_data_dir = "signet";
    


    pinheadmz commented at 5:00 PM on April 17, 2026:

    could be constexpr std::string_view base_data_dir = "signet";


    ekzyis commented at 11:44 AM on April 21, 2026:

    Would it be worth it if I have to cast to std::string anyway on return?

    diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
    index 8dc0296649..addd1551b0 100644
    --- a/src/chainparamsbase.cpp
    +++ b/src/chainparamsbase.cpp
    @@ -40,10 +40,10 @@ const CBaseChainParams& BaseParams()
    
     std::string GetSignetDataDir()
     {
    -    std::string base_data_dir = "signet";
    +    constexpr std::string_view base_data_dir{"signet"};
         const std::string challenge_hex = gArgs.GetArg("-signetchallenge", "");
         if (challenge_hex.empty()) {
    -        return base_data_dir;
    +        return std::string(base_data_dir);
         }
    
         const std::vector<uint8_t> challenge_bytes = ParseHex<uint8_t>(challenge_hex);
    @@ -55,9 +55,9 @@ std::string GetSignetDataDir()
    
         const MessageStartChars default_msg_start = CChainParams::SigNet({})->MessageStart();
         if (msg_start == default_msg_start) {
    -        return base_data_dir;
    +        return std::string(base_data_dir);
         }
    -    return base_data_dir + "_" + HexStr(msg_start);
    +    return std::string(base_data_dir) + "_" + HexStr(msg_start);
     }
    
     /**
    
    

    CBaseChainParams expects std::string, so afaict, I have to use std::string as the return type of GetSignetDataDir().

  39. in src/chainparamsbase.cpp:49 in f283eaac1d outdated
      44 | +    const std::string challenge_hex = gArgs.GetArg("-signetchallenge", "");
      45 | +    if (challenge_hex.empty()) {
      46 | +        return base_data_dir;
      47 | +    }
      48 | +
      49 | +    const std::vector<uint8_t> challenge_bytes = ParseHex<uint8_t>(challenge_hex);
    


    pinheadmz commented at 5:02 PM on April 17, 2026:

    is challenge_hex guaranteed to be valid hex at this point? Otherwise I think this is empty but that might be ok since I'm fairly certain we'd fail later on if the challenge isnt valid.


    ekzyis commented at 1:10 PM on April 21, 2026:

    is challenge_hex guaranteed to be valid hex at this point?

    Good question! No. This line in chainparamsbase.cpp gets hit before we fail because of invalid hex here in chainparams.cpp:

    https://github.com/bitcoin/bitcoin/blob/0c0f75eaaf173d31d31317ba396a6a94baac868a/src/chainparams.cpp#L36-L39

    I don't see this having any undesired side effect like creating a datadir that can't be used, though, so I also think it's okay.

    It just reminds me that I originally intended this functionality to be part of CChainParams instead of CBaseChainParams, but DataDir() is part of the CBaseChainParams interface. I explored conditionally adding -datadir with SoftSetArg like we do for other options, but then we would still create a "signet" folder inside it.

  40. in src/chainparamsbase.cpp:59 in f283eaac1d
      54 | +    std::copy_n(hash.begin(), 4, msg_start.begin());
      55 | +
      56 | +    const MessageStartChars default_msg_start = CChainParams::SigNet({})->MessageStart();
      57 | +    if (msg_start == default_msg_start) {
      58 | +        return base_data_dir;
      59 | +    }
    


    pinheadmz commented at 5:15 PM on April 17, 2026:

    What if the hard-coded default signet challenge was moved from kernel/chainparams.cpp to src/signet.h as a constexpr. Then you can just compare the actual challenge provided by the user string-to-string (although probably need ToLower for case sensitivity)

      // signet.h                                                                                                                                                                                                                                                                                                   
      constexpr std::string_view SIGNET_DEFAULT_CHALLENGE{                                                                                                                                                                                                                                                                      
          "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae"
      };                                                                                                                                                                                                                                                                                                                        
    
                  
      if (challenge_hex.empty() || challenge_hex == SIGNET_DEFAULT_CHALLENGE) {
          return std::string(base_data_dir);                                                                                                                                                                                                                                                                                    
      }
    

    pinheadmz commented at 5:25 PM on April 17, 2026:

    I wonder if the message start method could be de-duplicated into signet.h, cpp as well ?


    ekzyis commented at 5:49 PM on April 21, 2026:

    Done in 2fd5da15ea

    I had to update src/CMakeLists.txt, see commit message

    probably need ToLower for case sensitivity

    I considered to add a test for this, but I think it would be too granular

    edit: Okay, looking at CI, I think I need to update other CMakeLists.txt, too

  41. in test/functional/feature_signet.py:117 in f283eaac1d outdated
     112 | +            assert_equal(path.basename(datadir), expected_dirname)
     113 | +            # check if the directory exists
     114 | +            assert datadir.is_dir()
     115 | +            # check if the directory is being used
     116 | +            rpc_log_path = node.getrpcinfo()['logpath']
     117 | +            assert rpc_log_path.startswith(str(datadir))
    


    pinheadmz commented at 5:26 PM on April 17, 2026:

    Since you're using startswith here is there a risk of signet being confused with signet_XXXXXXXX ?


    ekzyis commented at 1:39 PM on April 21, 2026:

    No, this would be caught when checking the directory name in line 111.

    For example:

    diff --git a/test/functional/feature_signet.py b/test/functional/feature_signet.py
    index 9bc8353785..81f0246b22 100755
    --- a/test/functional/feature_signet.py
    +++ b/test/functional/feature_signet.py
    @@ -117,7 +117,7 @@ class SignetBasicTest(BitcoinTestFramework):
                 assert rpc_log_path.startswith(str(datadir) + "/")
    
             self.log.info("Test that the signet data directory with custom -signetchallenge uses network magic as suffix")
    -        assert_node_datadir(self.nodes[0], f"signet_{message_start(self.signets[0].challenge)}")
    +        assert_node_datadir(self.nodes[0], f"signet")
             assert_node_datadir(self.nodes[4], f"signet_{message_start(self.signets[2].challenge)}")
    
             self.log.info("Test that the main signet data directory is 'signet'")
    
    $ python feature_signet.py
    ...
    Traceback (most recent call last):
      File "/home/ekzyis/prog/bitcoin/test/functional/test_framework/test_framework.py", line 143, in main
        self.run_test()
        ~~~~~~~~~~~~~^^
      File "/home/ekzyis/prog/bitcoin/build/test/functional/feature_signet.py", line 120, in run_test
        assert_node_datadir(self.nodes[0], f"signet")
        ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/ekzyis/prog/bitcoin/build/test/functional/feature_signet.py", line 112, in assert_node_datadir
        assert_equal(path.basename(datadir), expected_dirname)
        ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/ekzyis/prog/bitcoin/test/functional/test_framework/util.py", line 83, in assert_equal
        raise AssertionError("not(%s)" % " == ".join(str(arg) for arg in (thing1, thing2) + args))
    AssertionError: not(signet_54d26fbd == signet)
    
  42. pinheadmz commented at 5:41 PM on April 17, 2026: member

    code review at f283eaac1dd41fb86c15eac4c734e1bc919134b7 some thoughts:

    • I think this is too much for one commit. See if you can pull out any refactors into the first commit, then make your change (with any tests that MUST be changed to stay passing), add more tests next, and finally the release note can even be on its own commit.
    • There are probably other doc files that could use notes about this change along with the release note (files.md for example)
    • I'm not sure how to address this but the bitcoin.conf file has these network sections like [regtest] and [signet]. But that section would include the signetchallenge so I don't think a user would need more than one signet section in their conf. But a user switching between signets might have hard-coded peers like connect= in the signet section of their conf, and that could be an issue when switching networks. Just wondering if you have any thoughts about that.

    Otherwise it's looking good! I built on macos/arm64 and ran the functional tests with and without --usecli. Played with the feature on default and custom signets.

  43. ekzyis force-pushed on Apr 21, 2026
  44. ekzyis marked this as a draft on Apr 21, 2026
  45. ekzyis commented at 6:34 PM on April 21, 2026: none

    I think this is too much for one commit. See if you can pull out any refactors into the first commit, then make your change (with any tests that MUST be changed to stay passing), add more tests next, and finally the release note can even be on its own commit.

    I split it into four commits as suggested

    There are probably other doc files that could use notes about this change along with the release note (files.md for example)

    I updated files.md but I haven't found other documentation about datadirs that need an update

    [...] Just wondering if you have any thoughts about that.

    I think different peers for each signet is an argument for supporting more than one signet section in the config (in a follow-up PR) as mentioned in #29838 (comment).


    Looks like my refactor in 2fd5da15ea broke all kinds of builds. I put this into draft until I fixed them.

  46. DrahtBot added the label CI failed on Apr 21, 2026
  47. DrahtBot commented at 6:35 PM on April 21, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task test ancestor commits: https://github.com/bitcoin/bitcoin/actions/runs/24737621566/job/72368627292</sub> <sub>LLM reason (✨ experimental): CTest failed because test_kernel (the only failing test) returned a non-zero status, causing the CI to exit with code 8.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  48. ekzyis force-pushed on Apr 21, 2026
  49. ekzyis force-pushed on Apr 21, 2026
  50. ekzyis force-pushed on Apr 21, 2026
  51. DrahtBot removed the label CI failed on Apr 21, 2026
  52. ekzyis commented at 9:55 PM on April 21, 2026: none

    12d77c9d8a rebased on master (875faa29e1) to resolve a conflict in src/kernel/CMakeLists.txt

    5912565c81 I resolved the conflict by not adding a line to src/kernel/CMakeLists.txt

  53. ekzyis marked this as ready for review on Apr 21, 2026
  54. ekzyis force-pushed on Apr 21, 2026
  55. refactor: Import signet constant and helper from signet.h
    We want to avoid duplicate code in the following commit, so we import the
    signet default challenge and a function to calculate the message start from the
    signet header file.
    
    The source list for the `bitcoin_common` target now includes signet.cpp because
    kernel/chainparams.cpp depends on it. The targets `bitcoin_node` and `fuzz`
    include `bitcoin_common`, so signet.cpp was removed from there.
    5f36512c27
  56. Use different datadirs for different signets
    This adds support for syncing multiple signets.
    
    Each custom signet is stored in a different datadir, using the network magic
    (message start) as the suffix.
    
    The default signet is always stored without a suffix for backward compatibility,
    even if the default challenge is provided explicitly via -signetchallenge.
    
    Co-authored-by: Brandon Odiwuor <brandon.odiwuor@gmail.com>
    52a28dc6b6
  57. test: Add signet datadir tests
    Co-authored-by: Brandon Odiwuor <brandon.odiwuor@gmail.com>
    dd3df1101b
  58. doc: Update documentation for signet datadir 5912565c81
  59. ekzyis force-pushed on Apr 21, 2026
  60. DrahtBot added the label CI failed on Apr 21, 2026
  61. DrahtBot commented at 11:20 PM on April 21, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task test ancestor commits: https://github.com/bitcoin/bitcoin/actions/runs/24751140594/job/72414298229</sub> <sub>LLM reason (✨ experimental): CI failed because the C++ build errored while compiling chainparamsbase.cpp (bitcoin_common / variant operator __OP), causing gmake to exit with code 1.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  62. DrahtBot removed the label CI failed on Apr 22, 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-05-04 00:12 UTC

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