Skip to content

backport: Merge bitcoin#31718, 28857, 28825, 29361, 26533, 27302, 29034#7376

Draft
vijaydasmp wants to merge 7 commits into
dashpay:developfrom
vijaydasmp:July_2026_1
Draft

backport: Merge bitcoin#31718, 28857, 28825, 29361, 26533, 27302, 29034#7376
vijaydasmp wants to merge 7 commits into
dashpay:developfrom
vijaydasmp:July_2026_1

Conversation

@vijaydasmp

@vijaydasmp vijaydasmp commented Jun 22, 2026

Copy link
Copy Markdown

bitcoin backports

fanquake and others added 7 commits June 21, 2026 22:17
81b9800 fix typos (wgyt)

Pull request description:

ACKs for top commit:
  maflcko:
    lgtm ACK 81b9800

Tree-SHA512: 6a4f718c0afb0e3bf80ab7fa7fed32f882614c60b6e4972f54584aecac2f19384d781232e923a47b72d76229af907ebf7717d7b34f9be6c00394ce5d7ed0b8d4
1e5b861 test: Add test for array serialization (TheCharlatan)
d49d198 refactor: Initialize magic bytes in constructor initializer (TheCharlatan)

Pull request description:

  This is a followup-PR for bitcoin#28423

  * Initialize magic bytes in constructor
  * Add a small unit test for serializing arrays.

ACKs for top commit:
  sipa:
    utACK 1e5b861
  maflcko:
    lgtm ACK 1e5b861

Tree-SHA512: 0f58d2332dc501ca9fd419f40ed4f977c83dce0169e9a0eee1ffc9f8daa2d2ef7e7df18205ba076f55d90ae6c4a20d2b51ab303150d38470a962bcc58a66f6e7
6a91791 fuzz: allow fake and duplicate inputs in tx_package_eval target (Greg Sanders)
a0626cc fuzz: allow reaching MempoolAcceptResult::ResultType::DIFFERENT_WITNESS in tx_package_eval target (Greg Sanders)

Pull request description:

  Exercises `DIFFERENT_WITNESS` by using "blank" WSH() and allowing witness to determine wtxid, and attempts to make invalid/duplicate inputs.

ACKs for top commit:
  dergoegge:
    Coverage looks good to me ACK 6a91791

Tree-SHA512: db894f5f5b81c6b454874baf11f296462832285f41ccb09f23c0db92b9abc98f8ecacd72fc8f60dc92cb7947f543a2e55bed2fd210b0e8ca7c7d5389d90b14af
fad0faf refactor: Fix timedata includes (MarcoFalke)

Pull request description:

  Remove unused includes. Also, fixup comments, see https://github.com/bitcoin/bitcoin/pull/28956/files#r1464827885. Also, add missing includes to `chain.h` while touching it.

ACKs for top commit:
  achow101:
    ACK fad0faf
  dergoegge:
    utACK fad0faf
  stickies-v:
    ACK fad0faf

Tree-SHA512: 45e86f2eb90f0e37012bd83bf30259719e0e58ede18b31f51ca8a6f6d23e6ca4d060fc0f56f821a711cbdb45792b82cf780f5ae3226680d7a966471990f352bc
…s on startup

3141eab test: add functional test for ScanAndUnlinkAlreadyPrunedFiles (Andrew Toth)
e252909 test: add unit test for ScanAndUnlinkAlreadyPrunedFiles (Andrew Toth)
77557dd prune: scan and unlink already pruned block files on startup (Andrew Toth)

Pull request description:

  There are a few cases where we can mark a block and undo file as pruned in our block index, but not actually remove the files from disk.
  1. If we call `FindFilesToPrune` or `FindFilesToPruneManual` and crash before `UnlinkPrunedFiles`.
  2. If on Windows there is an open file handle to the file somewhere else when calling `fs::remove` in `UnlinkPrunedFiles` (https://en.cppreference.com/w/cpp/filesystem/remove, https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilew#remarks). This could be from another process, or if we are calling `ReadBlockFromDisk`/`ReadRawBlockFromDisk` without having a lock on `cs_main` (which has been allowed since bitcoin@ccd8ef6).

  This PR mitigates this by scanning all pruned block files on startup after `LoadBlockIndexDB` and unlinking them again.

ACKs for top commit:
  achow101:
    ACK 3141eab
  pablomartin4btc:
    re-ACK with added functional test 3141eab.
  furszy:
    Code review ACK 3141eab
  theStack:
    Code-review ACK 3141eab

Tree-SHA512: 6c73bc57838ad1b7e5d441af3c4d6bf4c61c4382e2b86485e57fbb74a61240710c0ceeceb8b4834e610ecfa3175c6955c81ea4b2285fee11ca6383f472979d8d
eefe569 bugfix: Fix incorrect debug.log config file path (Ryan Ofsky)
3746f00 init: Error if ignored bitcoin.conf file is found (Ryan Ofsky)
398c371 lint: Fix lint-format-strings false positives when format specifiers have argument positions (Ryan Ofsky)

Pull request description:

  Show an error on startup if a bitcoin datadir that is being used contains a `bitcoin.conf` file that is ignored. There are two cases where this could happen:

  - One case reported in [bitcoin#27246 (comment)](bitcoin#27246 (comment)) happens when a `bitcoin.conf` file in the default datadir (e.g. `$HOME/.bitcoin/bitcoin.conf`) has a `datadir=/path` line that sets different datadir containing a second `bitcoin.conf` file. Currently the second `bitcoin.conf` file is ignored with no warning.

  - Another way this could happen is if a `-conf=` command line argument points to a configuration file with a `datadir=/path` line and that path contains a `bitcoin.conf` file, which is currently ignored.

  This change only adds an error message and doesn't change anything about way settings are applied. It also doesn't trigger errors if there are redundant `-datadir` or `-conf` settings pointing at the same configuration file, only if they are pointing at different files and one file is being ignored.

ACKs for top commit:
  pinheadmz:
    re-ACK eefe569
  willcl-ark:
    re-ACK eefe569
  TheCharlatan:
    ACK eefe569

Tree-SHA512: 939a98a4b271b5263d64a2df3054c56fcde94784edf6f010d78693a371c38aa03138ae9cebb026b6164bbd898d8fd0845a61a454fd996e328fd7bcf51c580c2b
… using `platform.system()`

878d914 doc: test: mention OS detection preferences in style guideline (Sebastian Falbesoner)
4c65ac9 test: detect OS consistently using `platform.system()` (Sebastian Falbesoner)
37324ae test: use `skip_if_platform_not_linux` helper where possible (Sebastian Falbesoner)

Pull request description:

  There are at least three ways to detect the operating system in Python3:
  - `os.name` (https://docs.python.org/3.9/library/os.html#os.name)
  - `sys.platform` (https://docs.python.org/3.9/library/sys.html#sys.platform)
  - `platform.system()` (https://docs.python.org/3.9/library/platform.html#platform.system)

  We are currently using all of them in functional tests (both in individual tests and shared test framework code), which seems a bit messy. This PR consolidates into using `platform.system()`, as it appears to be one most consistent and easy to read (see also [IRC discussion](https://bitcoin-irc.chaincode.com/bitcoin-core-dev/2023-12-08#989301;) and table below). `sys.platform` is inconsistent as it has the major version number encoded for BSD systems, which doesn't make much sense for e.g. OpenBSD, where there is no concept of major versions, but instead the version is simply increased by 0.1 on each release.

  Note that `os.name` is still useful to detect whether we are running a POSIX system (see `BitcoinTestFramework.skip_if_platform_not_posix`), so for this use-case it is kept as only exception. The following table shows values for common operating systems, found via
  ```
  $ python3 -c "import os; import sys; import platform; print(os.name, sys.platform, platform.system())"
  ```

  |     OS       | os.name | sys.platform | platform.system()  |
  |--------------|---------|--------------|--------------------|
  | Linux 6.2.0  |  posix  |   linux      |      Linux         |
  | MacOS*       |  posix  |   darwin     |      Darwin        |
  | OpenBSD 7.4  |  posix  |   openbsd7   |      OpenBSD       |
  | Windows*     |  nt     |   win32      |      Windows       |

  \* = I neither have a MacOS nor a Windows machine available, so I extracted the values from documentation and our current code. Also I'm relying on CI for testing the relevant code-paths. Having reviewers to this this locally would be very appreciated, if this gets Concept ACKed.

ACKs for top commit:
  kevkevinpal:
    ACK [878d914](bitcoin@878d914)
  achow101:
    ACK 878d914
  hebasto:
    ACK 878d914, I have reviewed the code and it looks OK.
  pablomartin4btc:
    tACK 878d914

Tree-SHA512: 24513d493e47f572028c843260b81c47c2c29bfb701991050255c9f9529cd19065ecbc7b3b6e15619da7f3f608b4825c345ce6fee30d8fd1eaadbd08cff400fc
@github-actions

Copy link
Copy Markdown

This pull request has conflicts, please rebase.

@vijaydasmp vijaydasmp changed the title backport: Merge bitcoin#31718 backport: Merge bitcoin#31718, 28857, 28825, 29361, 26533, 27302, 29034 Jun 22, 2026
@github-actions

Copy link
Copy Markdown

@vijaydasmp vijaydasmp marked this pull request as ready for review June 22, 2026 15:01
@vijaydasmp vijaydasmp marked this pull request as draft June 22, 2026 15:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dfb30988e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/init.cpp
argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-allowignoredconf", strprintf("For backwards compatibility, treat an unused %s file in the datadir as a warning, not an error.", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Implement ignored-conf handling for the new option

This registers -allowignoredconf, but ArgsManager::ReadConfigFiles() still has no logic to detect an ignored datadir config file or to downgrade that error when this flag is set. In the scenario added by test_ignored_conf, -conf=<temp> points back to a datadir that already has dash.conf, but startup will succeed and silently ignore that datadir config instead of failing or warning, so the new default functional test fails and users get a no-op safety option.

Useful? React with 👍 / 👎.

Comment on lines +133 to +134
conf_path = default_datadir / "bitcoin.conf"
conf_path.write_text(f"datadir={node.datadir}\n{conf_text}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use Dash config names in default-datadir tests

Here the test writes bitcoin.conf under the helper's Bitcoin default directory, but Dash reads $HOME/.dashcore/dash.conf on Unix-like systems and ~/Library/Application Support/DashCore/dash.conf on macOS. Once the test removes -datadir, dashd ignores this file and starts from an unconfigured default datadir/RPC port, so test_config_file_log and the same pattern in test_ignored_default_conf time out instead of checking the intended config behavior.

Useful? React with 👍 / 👎.

Comment on lines +267 to 271
star, star_pos_num = re.match(r"(?:.*?(\*(?:(\d+)\$)?)|)", m.group(1)).groups()
if star_pos_num is not None:
max_pos = max(max_pos, int(star_pos_num))
elif star is not None:
n += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Count every dynamic width/precision argument

For non-positional format strings with both dynamic width and precision, such as %*.*f, there are two * arguments plus the value, but this regex only captures the first * in the specifier. count_format_specifiers('%*.*f') now returns 2 instead of 3, so the lint can miss calls that are missing one argument when dynamic precision is used.

Useful? React with 👍 / 👎.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR bundles four independent tracks: (1) a new BlockManager::ScanAndUnlinkAlreadyPrunedFiles() method, called from LoadBlockIndex, that detects and removes pruned blk/rev files still on disk after a crash or open-fd scenario, backed by a unit test and a new functional test; (2) a -allowignoredconf startup option and associated functional tests that detect when bitcoin.conf in the active datadir is silently ignored due to a conflicting -conf= argument; (3) a broad migration of os.name/sys.platform OS detection to platform.system() across all functional tests, plus TestNode.start(env=) and get_temp_default_datadir() test framework additions; and (4) miscellaneous C++ include cleanups, V1Transport::m_magic_bytes constification, std::array serialization tests, P2WSH empty-script test constants, a format-string lint fix, and several typo corrections.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • PastaPastaPasta
  • thepastaclaw
  • UdjinM6
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly refers to specific Bitcoin Core PR numbers being backported, clearly summarizing the main change of integrating seven upstream pull requests.
Description check ✅ Passed The description is minimal but directly related to the changeset—it indicates this is a bitcoin backport, which aligns with the actual backport nature of the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/node/miner.cpp`:
- Line 24: The include change removed timedata.h but miner.cpp calls
GetAdjustedTime() on lines 52 and 221, which is defined in timedata.h and not
available in util/time.h. Either restore the `#include` <timedata.h> directive at
the top of miner.cpp, or move the GetAdjustedTime() function definition from
timedata.h to util/time.h and update the corresponding header file to ensure
miner.cpp can resolve the symbol.

In `@test/functional/feature_config_args.py`:
- Around line 116-150: The test_config_file_log function and related tests
contain hardcoded references to "bitcoin.conf" which should be "dash.conf" since
the repository uses "dash.conf" as the configuration filename. Replace all
occurrences of "bitcoin.conf" with "dash.conf" in the conf_path path creation
(where it constructs the configuration file path using pathlib.Path), in the
start_node method call arguments (where -conf parameter is specified), and in
any file write operations that create the configuration file. Additionally,
update any assertion messages and expected_msgs parameters that reference the
configuration filename to use "dash.conf" instead of "bitcoin.conf".

In `@test/lint/run-lint-format-strings.py`:
- Around line 267-271: The regex match on line 267 only captures the first `*`
in the format specifier string, causing format specifiers with multiple `*`
characters (like `%*.*d`) to be undercounted. Replace the single re.match call
with re.finditer or re.findall to find all occurrences of the `*` pattern in
m.group(1), then iterate through each match to properly count all positional
arguments and increment n for each `*` specifier found.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 35f19a2a-66e5-4557-be3e-60a0c05e17ad

📥 Commits

Reviewing files that changed from the base of the PR and between a59ad9e and dfb3098.

📒 Files selected for processing (33)
  • ci/README.md
  • contrib/guix/README.md
  • contrib/tracing/README.md
  • contrib/tracing/log_raw_p2p_msgs.py
  • doc/release-notes-27302.md
  • src/chain.h
  • src/init.cpp
  • src/net.cpp
  • src/net.h
  • src/net_processing.cpp
  • src/node/blockstorage.cpp
  • src/node/blockstorage.h
  • src/node/miner.cpp
  • src/qt/test/test_main.cpp
  • src/rpc/mining.cpp
  • src/test/blockmanager_tests.cpp
  • src/test/serialize_tests.cpp
  • src/test/util/script.h
  • src/timedata.h
  • src/validation.cpp
  • test/functional/README.md
  • test/functional/feature_bind_extra.py
  • test/functional/feature_config_args.py
  • test/functional/feature_init.py
  • test/functional/feature_notifications.py
  • test/functional/feature_remove_pruned_files_on_startup.py
  • test/functional/rpc_bind.py
  • test/functional/test_framework/p2p.py
  • test/functional/test_framework/test_node.py
  • test/functional/test_framework/util.py
  • test/functional/test_runner.py
  • test/functional/wallet_multiwallet.py
  • test/lint/run-lint-format-strings.py
💤 Files with no reviewable changes (1)
  • src/timedata.h

Comment thread src/node/miner.cpp
#include <timedata.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/time.h>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check for orphaned timedata symbols in miner.cpp after include swap

# Search for timedata usage in miner.cpp
echo "=== Checking for timedata symbol usage in miner.cpp ==="
rg -n 'timedata|dNtpOffset' src/node/miner.cpp || echo "No timedata symbol references found"

# Verify util/time.h exports needed symbols
echo ""
echo "=== Checking util/time.h for time symbols ==="
grep -E '(GetTime|GetAdjustedTime|dNtpOffset)' src/util/time.h || echo "Time symbols may not be in util/time.h"

Repository: dashpay/dash

Length of output: 282


🏁 Script executed:

#!/bin/bash
# Check what time functions miner.cpp actually uses
echo "=== Time-related function calls in miner.cpp ==="
rg -n '(GetTime|GetAdjustedTime|GetSystemTimeInSeconds|dNtpOffset)' src/node/miner.cpp

# Also check for any remaining includes that might provide time functionality
echo ""
echo "=== All includes in miner.cpp ==="
head -30 src/node/miner.cpp | grep '^`#include`'

Repository: dashpay/dash

Length of output: 1009


🏁 Script executed:

#!/bin/bash
# Find GetAdjustedTime definition
echo "=== Searching for GetAdjustedTime definition ==="
rg -n 'GetAdjustedTime' --type cpp --type h | head -20

# Check full util/time.h content to see all exports
echo ""
echo "=== Full util/time.h content ==="
cat src/util/time.h

Repository: dashpay/dash

Length of output: 7294


🏁 Script executed:

#!/bin/bash
# Check if timedata.h is included transitively
echo "=== Checking node/miner.h for timedata.h include ==="
rg -n 'timedata' src/node/miner.h

echo ""
echo "=== Checking validation.h for timedata.h include ==="
rg -n 'timedata' src/validation.h | head -5

echo ""
echo "=== Checking chain.h for timedata.h include ==="
rg -n 'timedata' src/chain.h

echo ""
echo "=== Full search for timedata.h includes ==="
rg '`#include`.*timedata' --type h --type cpp | grep -E '(chain\.h|validation\.h|node/miner\.h|pow\.h)'

Repository: dashpay/dash

Length of output: 257


🏁 Script executed:

#!/bin/bash
# Check what headers transitively include timedata.h
echo "=== Which headers include timedata.h ==="
rg '`#include`.*timedata\.h' --type h --type cpp

echo ""
echo "=== Does pow.h include timedata ==="
cat src/pow.h | grep -E '(timedata|GetAdjustedTime)' || echo "Not found in pow.h"

echo ""
echo "=== Verify miner.cpp would have access to GetAdjustedTime ==="
# Check if any of miner's includes transitively get timedata.h
for header in consensus/consensus.h consensus/validation.h pow.h; do
  if rg '`#include`.*timedata' "src/$header" > /dev/null 2>&1; then
    echo "$header includes timedata.h"
  fi
done
echo "Done checking transitive includes"

Repository: dashpay/dash

Length of output: 1053


🏁 Script executed:

#!/bin/bash
# Check if validation.h or pow.h indirectly include timedata.h
echo "=== Check validation.h includes ==="
head -50 src/validation.h | grep '`#include`'

echo ""
echo "=== Check pow.h includes ==="
head -50 src/pow.h | grep '`#include`'

echo ""
echo "=== Comprehensive check: trace includes from miner.cpp ==="
# For key headers, check if they include timedata
for header in src/validation.h src/pow.h src/consensus/consensus.h src/chainparams.h; do
  if [ -f "$header" ]; then
    result=$(grep '`#include`.*timedata' "$header")
    if [ -n "$result" ]; then
      echo "$header INCLUDES timedata.h"
    fi
  fi
done
echo "Check complete"

Repository: dashpay/dash

Length of output: 1050


Add timedata.h include or implement GetAdjustedTime() in util/time.h.

The include swap removes timedata.h but miner.cpp calls GetAdjustedTime() on lines 52 and 221. This function is defined in timedata.h, and util/time.h does not provide it. No transitive includes supply this symbol. Either restore #include <timedata.h> or relocate GetAdjustedTime() to util/time.h.

🧰 Tools
🪛 Cppcheck (2.21.0)

[error] 24-24: #error No known always_inline attribute for this platform.

(preprocessorErrorDirective)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/node/miner.cpp` at line 24, The include change removed timedata.h but
miner.cpp calls GetAdjustedTime() on lines 52 and 221, which is defined in
timedata.h and not available in util/time.h. Either restore the `#include`
<timedata.h> directive at the top of miner.cpp, or move the GetAdjustedTime()
function definition from timedata.h to util/time.h and update the corresponding
header file to ensure miner.cpp can resolve the symbol.

Comment on lines +116 to +150
def test_config_file_log(self):
# Disable this test for windows currently because trying to override
# the default datadir through the environment does not seem to work.
if platform.system() == "Windows":
return

self.log.info('Test that correct configuration path is changed when configuration file changes the datadir')

# Create a temporary directory that will be treated as the default data
# directory by bitcoind.
env, default_datadir = util.get_temp_default_datadir(pathlib.Path(self.options.tmpdir, "test_config_file_log"))
default_datadir.mkdir(parents=True)

# Write a bitcoin.conf file in the default data directory containing a
# datadir= line pointing at the node datadir.
node = self.nodes[0]
conf_text = pathlib.Path(node.bitcoinconf).read_text()
conf_path = default_datadir / "bitcoin.conf"
conf_path.write_text(f"datadir={node.datadir}\n{conf_text}")

# Drop the node -datadir= argument during this test, because if it is
# specified it would take precedence over the datadir setting in the
# config file.
node_args = node.args
node.args = [arg for arg in node.args if not arg.startswith("-datadir=")]

# Check that correct configuration file path is actually logged
# (conf_path, not node.bitcoinconf)
with self.nodes[0].assert_debug_log(expected_msgs=[f"Config file: {conf_path}"]):
self.start_node(0, ["-allowignoredconf"], env=env)
self.stop_node(0)

# Restore node arguments after the test
node.args = node_args

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Core config filename and config-path wiring =="
rg -n -C2 "BITCOIN_CONF_FILENAME|GetConfigFilePath|ReadConfigFiles" src/util src/init.cpp

echo
echo "== Functional framework config filename usage =="
rg -n -C2 "bitcoinconf|dash\\.conf|bitcoin\\.conf|write_config|initialize_datadir" \
  test/functional/test_framework test/functional/feature_config_args.py

Repository: dashpay/dash

Length of output: 22289


Replace hardcoded "bitcoin.conf" with "dash.conf" throughout the test.

The repository uses "dash.conf" as the configuration filename (defined in src/util/system.cpp:90 and used by the test framework in test/functional/test_framework/test_node.py:83). The new tests hardcode "bitcoin.conf" in multiple locations, which will cause them to fail:

  • Line 133: conf_path = default_datadir / "bitcoin.conf" → should be "dash.conf"
  • Line 335: self.start_node(0, [f'-conf={node.datadir}/bitcoin.conf']) → should be "dash.conf"
  • Line 357: (default_datadir / "bitcoin.conf").write_text(...) → should be "dash.conf"

Also update the assertion messages on lines 328 and 365 to reference "dash.conf" instead of "bitcoin.conf".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/feature_config_args.py` around lines 116 - 150, The
test_config_file_log function and related tests contain hardcoded references to
"bitcoin.conf" which should be "dash.conf" since the repository uses "dash.conf"
as the configuration filename. Replace all occurrences of "bitcoin.conf" with
"dash.conf" in the conf_path path creation (where it constructs the
configuration file path using pathlib.Path), in the start_node method call
arguments (where -conf parameter is specified), and in any file write operations
that create the configuration file. Additionally, update any assertion messages
and expected_msgs parameters that reference the configuration filename to use
"dash.conf" instead of "bitcoin.conf".

Comment on lines +267 to 271
star, star_pos_num = re.match(r"(?:.*?(\*(?:(\d+)\$)?)|)", m.group(1)).groups()
if star_pos_num is not None:
max_pos = max(max_pos, int(star_pos_num))
elif star is not None:
n += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Confirm the current single-star logic exists in the changed file
rg -n "star, star_pos_num = re.match" test/lint/run-lint-format-strings.py

# Reproduce current behavior with equivalent logic (read-only verification)
python - <<'PY'
import re

def count_like_current(format_string):
    format_string = format_string.replace('%%', 'X')
    n = max_pos = 0
    for m in re.finditer("%(.*?)[aAcdeEfFgGinopsuxX]", format_string, re.DOTALL):
        pos_num, = re.match(r"(?:(^\d+)\$)?", m.group(1)).groups()
        if pos_num is not None:
            max_pos = max(max_pos, int(pos_num))
        else:
            n += 1
        star, star_pos_num = re.match(r"(?:.*?(\*(?:(\d+)\$)?)|)", m.group(1)).groups()
        if star_pos_num is not None:
            max_pos = max(max_pos, int(star_pos_num))
        elif star is not None:
            n += 1
    return max(n, max_pos)

cases = [
    ("%*.*d", 3),
    ("%2$*3$.*4$d", 4),
]
for fmt, expected in cases:
    got = count_like_current(fmt)
    print(f"{fmt}: got={got}, expected={expected}, {'OK' if got == expected else 'MISMATCH'}")
PY

Repository: dashpay/dash

Length of output: 224


Count all * argument specifiers, not just the first one.

The regex pattern on line 267 only captures the first * in a format specifier. Format specifiers like %*.*d and %2$*3$.*4$d are undercounted, producing false negatives in the lint check.

Proposed fix
-        star, star_pos_num = re.match(r"(?:.*?(\*(?:(\d+)\$)?)|)", m.group(1)).groups()
-        if star_pos_num is not None:
-            max_pos = max(max_pos, int(star_pos_num))
-        elif star is not None:
-            n += 1
+        for star_match in re.finditer(r"\*(?:(\d+)\$)?", m.group(1)):
+            star_pos_num = star_match.group(1)
+            if star_pos_num is not None:
+                max_pos = max(max_pos, int(star_pos_num))
+            else:
+                n += 1
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
star, star_pos_num = re.match(r"(?:.*?(\*(?:(\d+)\$)?)|)", m.group(1)).groups()
if star_pos_num is not None:
max_pos = max(max_pos, int(star_pos_num))
elif star is not None:
n += 1
for star_match in re.finditer(r"\*(?:(\d+)\$)?", m.group(1)):
star_pos_num = star_match.group(1)
if star_pos_num is not None:
max_pos = max(max_pos, int(star_pos_num))
else:
n += 1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/lint/run-lint-format-strings.py` around lines 267 - 271, The regex match
on line 267 only captures the first `*` in the format specifier string, causing
format specifiers with multiple `*` characters (like `%*.*d`) to be
undercounted. Replace the single re.match call with re.finditer or re.findall to
find all occurrences of the `*` pattern in m.group(1), then iterate through each
match to properly count all positional arguments and increment n for each `*`
specifier found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants