Skip to content

backport: Merge bitcoin#28523, 26638, 28976, 27822, 28671#7358

Draft
vijaydasmp wants to merge 3 commits into
dashpay:developfrom
vijaydasmp:June_2026_4
Draft

backport: Merge bitcoin#28523, 26638, 28976, 27822, 28671#7358
vijaydasmp wants to merge 3 commits into
dashpay:developfrom
vijaydasmp:June_2026_4

Conversation

@vijaydasmp

Copy link
Copy Markdown

bitcoin backports

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@vijaydasmp vijaydasmp changed the title backport: Merge bitcoin#28523 backport: Merge bitcoin#28523, 26638, 28976, 26289 Jun 13, 2026
@vijaydasmp vijaydasmp force-pushed the June_2026_4 branch 2 times, most recently from 236ba33 to 9d9ed5a Compare June 14, 2026 04:33
@vijaydasmp vijaydasmp changed the title backport: Merge bitcoin#28523, 26638, 28976, 26289 backport: Merge bitcoin#28523, 26638, 28976, (scripted-diff) 27822 Jun 14, 2026
@vijaydasmp vijaydasmp force-pushed the June_2026_4 branch 6 times, most recently from 19e166d to daa0925 Compare June 15, 2026 03:20
@vijaydasmp vijaydasmp changed the title backport: Merge bitcoin#28523, 26638, 28976, (scripted-diff) 27822 backport: Merge bitcoin#28523, 26638, 28976, 27822 Jun 15, 2026
@vijaydasmp vijaydasmp changed the title backport: Merge bitcoin#28523, 26638, 28976, 27822 backport: Merge bitcoin#28523, 26638, 28976, 27822, 28671 Jun 15, 2026
…n table entries

352d5eb test: getrawaddrman RPC (0xb10c)
da384a2 rpc: getrawaddrman for addrman entries (0xb10c)

Pull request description:

  Inspired by `getaddrmaninfo` (bitcoin#27511), this adds a hidden/test-only `getrawaddrman` RPC. The RPC returns information on all addresses in the address manager new and tried tables. Addrman table contents can be used in tests and during development.

  The RPC result encodes the `bucket` and `position`, the internal location of addresses in the tables, in the address object's string key. This allows users to choose to consume or to ignore the location information. If the internals of the address manager implementation change, the location encoding might change too.

  ```
  getrawaddrman

  EXPERIMENTAL warning: this call may be changed in future releases.

  Returns information on all address manager entries for the new and tried tables.

  Result:
  {                                  (json object)
    "table" : {                      (json object) buckets with addresses in the address manager table ( new, tried )
      "bucket/position" : {          (json object) the location in the address manager table (<bucket>/<position>)
        "address" : "str",           (string) The address of the node
        "port" : n,                  (numeric) The port number of the node
        "network" : "str",           (string) The network (ipv4, ipv6, onion, i2p, cjdns) of the address
        "services" : n,              (numeric) The services offered by the node
        "time" : xxx,                (numeric) The UNIX epoch time when the node was last seen
        "source" : "str",            (string) The address that relayed the address to us
        "source_network" : "str"     (string) The network (ipv4, ipv6, onion, i2p, cjdns) of the source address
      },
      ...
    },
    ...
  }

  Examples:
  > bitcoin-cli getrawaddrman
  > curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getrawaddrman", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
  ```

ACKs for top commit:
  willcl-ark:
    reACK 352d5eb
  amitiuttarwar:
    reACK 352d5eb
  stratospher:
    reACK 352d5eb.
  achow101:
    ACK 352d5eb

Tree-SHA512: cc462666b5c709617c66b0e3e9a17c4c81e9e295f91bdd9572492d1cb6466fc9b6d48ee805ebe82f9f16010798370effe5c8f4db15065b8c7c0d8637675d615e
@vijaydasmp

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 74c2e6f097

ℹ️ 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".

@vijaydasmp vijaydasmp marked this pull request as ready for review June 16, 2026 04:19
@thepastaclaw

thepastaclaw commented Jun 16, 2026

Copy link
Copy Markdown

✅ Review complete (commit 3c47eb7)

@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: 74c2e6f097

ℹ️ 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/wallet/wallet.cpp Outdated
Comment on lines +4798 to +4801
// Do the migration of keys and scripts for non-blank wallets, and cleanup if it fails
success = local_wallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
if (!success) {
success = DoMigration(*local_wallet, context, error, res);

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 Do not treat blank wallets as fully migrated

When migratewallet is run on a blank legacy wallet, this branch marks the operation successful immediately after converting the database to SQLite, so DoMigration/ApplyMigrationData never runs and the wallet never gets WALLET_FLAG_DESCRIPTORS or has its legacy ScriptPubKeyMan removed. The RPC will report success while the reloaded wallet is still descriptors=false; a subsequent retry then fails at MigrateToSQLite because the database is already SQLite, leaving blank legacy wallets half-migrated.

Useful? React with 👍 / 👎.

Comment on lines 260 to 261
if self.is_sqlite_compiled():
self.options.descriptors = True

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 Keep legacy-only tests creating legacy wallets

With this default flipped to descriptors=True, RPCOverloadWrapper.createwallet() now passes descriptors=True for tests that omit the argument. wallet_migration.py still creates basic2 with createwallet(wallet_name="basic2", blank=True) and then calls sethdseed, which is legacy-only, so on normal SQLite+BDB test builds this test creates a descriptor blank wallet and fails before exercising the migration path.

Useful? React with 👍 / 👎.

@vijaydasmp vijaydasmp marked this pull request as draft June 16, 2026 04:24
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR bundles four independent changes. First, it adds a GetEntries(bool from_tried) enumeration API to AddrManImpl and AddrMan that scans the tried or new bucket tables and returns (AddrInfo, AddressPosition) pairs, then exposes this through a new hidden getrawaddrman RPC with supporting functional and fuzz tests. Second, it renames UniValue::__pushKV to pushKVEnd in the library header, implementation, and all call sites across RPC, util, wallet, and test files. Third, it renames TxOrphanage::_EraseTx to EraseTxNoLock in the header and all internal call sites. Fourth, it hardens wallet migration by replacing hard asserts with Assume guards, switching descriptor-wallet detection to use IsWalletFlagSet, adding blank-wallet skip logic in MigrateLegacyToDescriptor, and adding a test_blank functional test with a refactored create_legacy_wallet helper.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • dashpay/dash#7275: Introduces the core migratewallet RPC and MigrateLegacyToDescriptor plumbing that this PR hardens with Assume guards, blank-wallet handling, and updated descriptor-detection logic in src/wallet/wallet.cpp.
  • dashpay/dash#6897: Modifies the same UniValue::__pushKV path in src/univalue that this PR renames to pushKVEnd across the library and all call sites.

Suggested reviewers

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

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.91% 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 accurately identifies this as a backport of five specific Bitcoin pull requests (#28523, #26638, #28976, #27822, #28671), which matches the changeset's multi-part nature.
Description check ✅ Passed The description 'bitcoin backports' is minimal but directly relates to the changeset, which consists entirely of backported changes from Bitcoin repositories.
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/functional/wallet_migration.py (1)

178-180: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Create basic2 through the legacy helper before calling sethdseed.

createwallet(..., blank=True) omits descriptors=False, so it now creates a descriptor wallet by default; CI is failing when the next line calls legacy-only sethdseed.

Proposed fix
-        self.nodes[0].createwallet(wallet_name="basic2", blank=True)
-        basic2 = self.nodes[0].get_wallet_rpc("basic2")
+        basic2 = self.create_legacy_wallet("basic2", blank=True)
         basic2.sethdseed(True, BASIC2_SEED_WIF)
🤖 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/wallet_migration.py` around lines 178 - 180, The createwallet
call for basic2 is missing the descriptors parameter, causing it to create a
descriptor wallet by default when blank=True is used. Since sethdseed is a
legacy-only method that cannot work with descriptor wallets, you need to
explicitly add descriptors=False to the createwallet call to ensure it creates a
legacy wallet. This will allow the subsequent sethdseed call with
BASIC2_SEED_WIF to work correctly.

Source: Pipeline failures

🤖 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/univalue/include/univalue.h`:
- Line 90: The modification to src/univalue/include/univalue.h violates the
repository rule forbidding changes to vendored dependencies. The pushKVEnd
method addition at line 90 modifies vendored UniValue code which must remain
untouched. To fix this, either revert the changes to src/univalue/** and instead
adapt all external callers to work with the original UniValue API, or obtain
explicit documented approval from the maintainers for an exception to the
vendored code policy before proceeding with this backport.

In `@test/functional/rpc_net.py`:
- Around line 453-455: The assert_approx call is comparing result["time"] (from
node mocktime) against wall-clock time.time(), which can cause nondeterministic
failures on slow runners. Replace time.time() with the corresponding mocktime
value to ensure the assertion compares mocktime against mocktime consistently.
Check the test setup or node context to determine the correct mocktime accessor
or method to use instead of time.time().

---

Outside diff comments:
In `@test/functional/wallet_migration.py`:
- Around line 178-180: The createwallet call for basic2 is missing the
descriptors parameter, causing it to create a descriptor wallet by default when
blank=True is used. Since sethdseed is a legacy-only method that cannot work
with descriptor wallets, you need to explicitly add descriptors=False to the
createwallet call to ensure it creates a legacy wallet. This will allow the
subsequent sethdseed call with BASIC2_SEED_WIF to work correctly.
🪄 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: fcbfdde3-397b-41b8-850a-c0929bd4cce7

📥 Commits

Reviewing files that changed from the base of the PR and between 77cf281 and 74c2e6f.

📒 Files selected for processing (19)
  • src/addrman.cpp
  • src/addrman.h
  • src/addrman_impl.h
  • src/rpc/client.cpp
  • src/rpc/mempool.cpp
  • src/rpc/net.cpp
  • src/test/fuzz/rpc.cpp
  • src/test/settings_tests.cpp
  • src/txorphanage.cpp
  • src/txorphanage.h
  • src/univalue/include/univalue.h
  • src/univalue/lib/univalue.cpp
  • src/univalue/test/object.cpp
  • src/util/settings.cpp
  • src/wallet/rpc/addresses.cpp
  • src/wallet/wallet.cpp
  • test/functional/rpc_net.py
  • test/functional/test_framework/test_framework.py
  • test/functional/wallet_migration.py

void push_backV(It first, It last);

void __pushKV(std::string key, UniValue val);
void pushKVEnd(std::string key, UniValue val);

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 | 🏗️ Heavy lift

Do not modify vendored UniValue sources without an explicit exception.

Line 90 introduces an API rename inside src/univalue/**, which violates the repository rule forbidding edits to vendored dependencies. Please either (a) keep vendor code untouched and adapt callers externally, or (b) document/approve an explicit exception for this backport.

As per coding guidelines: src/{crc32c,dashbls,gsl,immer,leveldb,minisketch,secp256k1,univalue,crypto/{ctaes,x11}}/**: “Do not make changes to vendored dependencies…”.

🤖 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/univalue/include/univalue.h` at line 90, The modification to
src/univalue/include/univalue.h violates the repository rule forbidding changes
to vendored dependencies. The pushKVEnd method addition at line 90 modifies
vendored UniValue code which must remain untouched. To fix this, either revert
the changes to src/univalue/** and instead adapt all external callers to work
with the original UniValue API, or obtain explicit documented approval from the
maintainers for an exception to the vendored code policy before proceeding with
this backport.

Source: Coding guidelines

Comment thread test/functional/rpc_net.py Outdated
Comment on lines +453 to +455
# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)

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 | ⚡ Quick win

Use mock time in the assertion to avoid reintroducing flakiness.

result["time"] is produced from node mocktime, but this check compares it to wall-clock time.time(). On slow runners, this can still fail nondeterministically.

🛠️ Suggested fix
-            # To avoid failing on slow test runners, use a 10s vspan here.
-            assert_approx(result["time"], time.time(), vspan=10)
+            # Addrman timestamps are based on node mocktime set earlier.
+            assert_equal(result["time"], self.addr_time)
📝 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
# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)
# Addrman timestamps are based on node mocktime set earlier.
assert_equal(result["time"], self.addr_time)
🤖 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/rpc_net.py` around lines 453 - 455, The assert_approx call is
comparing result["time"] (from node mocktime) against wall-clock time.time(),
which can cause nondeterministic failures on slow runners. Replace time.time()
with the corresponding mocktime value to ensure the assertion compares mocktime
against mocktime consistently. Check the test setup or node context to determine
the correct mocktime accessor or method to use instead of time.time().

@thepastaclaw thepastaclaw 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.

Code Review

Policy gate: an agent-reported missing upstream prerequisite was restored as a blocking finding. This PR is a full Bitcoin backport, and omitted upstream hunks require their prerequisite PRs unless the finding is explicitly allowlisted (intentional_exclusion / policy_override). The agent's original evidence is preserved in the finding(s) below.

Prior verifier summary (overridden by policy gate): Two blocking issues in the backport test adaptations. (1) The bitcoin#28671 backport is incomplete: mocktime was added in test_addpeeraddress, but the paired assert_approx→assert_equal change in check_addr_information was dropped, so the test remains as flaky as it was upstream (and arguably worse, since the mocked time is now frozen while the wall-clock comparison keeps advancing). (2) The bitcoin#26638 prefer-sqlite change flipped the default wallet type to descriptors in the test framework, which breaks the Dash-specific basic2 block in wallet_migration.py — createwallet(blank=True) now produces a descriptor wallet, but the immediate sethdseed call is legacy-only. One nitpick: duplicate class AddrInfo; forward declaration in addrman.h. A soft bitcoin#26485 prerequisite claim from the Codex backport-reviewer was dropped — Dash has no remaining __pushKV references and the rename is complete for the current tree.

🔴 5 blocking | 💬 1 nitpick(s)

2 additional finding(s) omitted (not in diff).

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `test/functional/rpc_net.py`:
- [BLOCKING] test/functional/rpc_net.py:453-454: bitcoin#28671 backport is incomplete: time assertion still uses wall-clock, mocktime is dead code
  The upstream PR bitcoin#28671 has two paired changes: (1) freeze the addr's nTime by setting mocktime before `addpeeraddress`, and (2) compare the returned time against that frozen mocktime instead of wall-clock `time.time()`. Commit 74c2e6f097 only applied (1) — `self.addr_time = int(time.time())` and `node.setmocktime(self.addr_time)` at lines 359-360 — but left line 454 as `assert_approx(result["time"], time.time(), vspan=10)`, and `self.addr_time` is never referenced again. The mocktime setup is therefore dead code, and the test is at least as flaky on slow runners as it was before the cherry-pick: addrman entries now have a frozen `nTime` equal to `self.addr_time`, while `time.time()` keeps advancing through the subsequent RPC steps. On slow CI (the s390x/qemu case the upstream PR targets), the delta will eventually exceed 10s and fail deterministically. Drop the partial change or finish it by comparing against `self.addr_time`.
- [BLOCKING] test/functional/rpc_net.py:453-454: Incomplete cherry-pick of bitcoin#28671: missing assert_equal replacement
  Upstream PR #28671 has two paired changes:

  1. Set mocktime so the addr's `nTime` is deterministic (`self.addr_time = int(time.time())` + `node.setmocktime(self.addr_time)`).
  2. Replace the flaky `assert_approx(result["time"], time.time(), vspan=10)` with `assert_equal(result["time"], self.addr_time)`.

  Dash's merge commit 74c2e6f097 only applied change (1). The second hunk was dropped during the cherry-pick. The relevant code at `test/functional/rpc_net.py:453-454` still reads:

To avoid failing on slow test runners, use a 10s vspan here.

assert_approx(result["time"], time.time(), vspan=10)


Upstream diff for the same region:

  •        # To avoid failing on slow test runners, use a 10s vspan here.
    
  •        assert_approx(result["time"], time.time(), vspan=10)
    
  •        assert_equal(result["time"], self.addr_time)
    

Consequences:
- The PR's stated purpose ("Fix failing time check") is not actually achieved — the original `assert_approx(... vspan=10)` flakiness on slow runners remains.
- With `setmocktime` now in effect, `result["time"]` is frozen at `self.addr_time`, but the assertion still compares against the wall-clock `time.time()`, which keeps advancing. On a sufficiently slow runner the delta will exceed 10s and the test will fail more deterministically than before the cherry-pick.

Fix: drop lines 453-454 and replace with `assert_equal(result["time"], self.addr_time)` (matches upstream exactly). Evidence: `git diff f4049eaf08^1...f4049eaf08 -- test/functional/rpc_net.py` shows the missing hunk; `git diff 74c2e6f097~1...74c2e6f097 -- test/functional/rpc_net.py` does not contain it.

---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
- [BLOCKING] test/functional/rpc_net.py:453-454: Incomplete conflict resolution: bitcoin#28671
bitcoin#28671's actual fix is to compare getrawaddrman entry times against the mocked timestamp captured before addpeeraddress. Upstream f4049eaf08 changes the assertion to assert_equal(result["time"], self.addr_time). Dash's backport adds self.addr_time and node.setmocktime(self.addr_time) in test_addpeeraddress, but leaves check_addr_information using assert_approx(result["time"], time.time(), vspan=10). That preserves the slow-runner failure the upstream PR fixed: if enough time passes between insertion and validation, the addrman entry time is the mocked value, not current wall time.

---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

In `test/functional/wallet_migration.py`:
- [BLOCKING] test/functional/wallet_migration.py:178-180: basic2 must be created as a legacy wallet — prefer-sqlite default breaks the subsequent sethdseed
bitcoin#26638 flips the wallet-test framework default from BDB/legacy to SQLite/descriptors when SQLite is compiled in, and `WalletMigrationTest` requires SQLite. `TestNode.createwallet()` (test_framework/test_node.py:902-907) falls back to `self.descriptors` (= `self.options.descriptors`) when the caller does not pass an explicit `descriptors=` arg, so `self.nodes[0].createwallet(wallet_name="basic2", blank=True)` now creates a descriptor wallet. The next line, `basic2.sethdseed(True, BASIC2_SEED_WIF)`, is legacy-only (gated by `EnsureLegacyScriptPubKeyMan`) and will raise before the test reaches the migration scenario. The upstream PR converted the adjacent `multisig1`, `imports0`, `watchonly0`, and `watchonly1` blocks to `self.create_legacy_wallet(...)` for exactly this reason, but the Dash-specific `basic2` block (added in the bitcoin#19602 backport) was not adapted in this PR. Route the basic2 creation through `create_legacy_wallet` so it stays BDB regardless of the framework default.

In `src/rpc/server.cpp`:
- [BLOCKING] src/rpc/server.cpp:407-455: Missing prerequisite: bitcoin#26485
bitcoin#27822 renamed UniValue::__pushKV to pushKVEnd in every upstream call site, including src/rpc/server.cpp's named-only RPC option handling: upstream changed options.__pushKV(fr->first, *fr->second) to options.pushKVEnd(fr->first, *fr->second). Dash's transformNamedArguments still takes std::vector<std::string> and has no named_only/options branch, so that upstream hunk is absent. Tracing the missing block with git log -S "named_only" points to 34ac3f438a, Merge bitcoin/bitcoin#26485: RPC: Accept options as named-only parameters. This is soft because Dash has no remaining __pushKV references and the rename itself compiles, but it is still missing upstream content touched by the backported PR.

---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

Comment thread test/functional/rpc_net.py Outdated
Comment on lines +453 to +454
# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Blocking: bitcoin#28671 backport is incomplete: time assertion still uses wall-clock, mocktime is dead code

The upstream PR bitcoin#28671 has two paired changes: (1) freeze the addr's nTime by setting mocktime before addpeeraddress, and (2) compare the returned time against that frozen mocktime instead of wall-clock time.time(). Commit 74c2e6f only applied (1) — self.addr_time = int(time.time()) and node.setmocktime(self.addr_time) at lines 359-360 — but left line 454 as assert_approx(result["time"], time.time(), vspan=10), and self.addr_time is never referenced again. The mocktime setup is therefore dead code, and the test is at least as flaky on slow runners as it was before the cherry-pick: addrman entries now have a frozen nTime equal to self.addr_time, while time.time() keeps advancing through the subsequent RPC steps. On slow CI (the s390x/qemu case the upstream PR targets), the delta will eventually exceed 10s and fail deterministically. Drop the partial change or finish it by comparing against self.addr_time.

Suggested change
# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)
assert_equal(result["time"], self.addr_time)

source: ['claude', 'codex']

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved in this update — bitcoin#28671 backport is incomplete: time assertion still uses wall-clock, mocktime is dead code no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

Comment thread src/addrman.h Outdated
Comment on lines +37 to +39
class AddrInfo;
class AddrManImpl;
class AddrInfo;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💬 Nitpick: Duplicate forward declaration of class AddrInfo

The bitcoin#28523 backport added class AddrInfo; at line 39 right after class AddrManImpl;, but class AddrInfo; already appears at line 37. Harmless to the compiler, but clearly a merge-resolution artifact worth removing.

Suggested change
class AddrInfo;
class AddrManImpl;
class AddrInfo;
class AddrInfo;
class AddrManImpl;

source: ['claude']

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved in this update — Duplicate forward declaration of class AddrInfo no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

Comment thread test/functional/rpc_net.py Outdated
Comment on lines +453 to +454
# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Blocking: Incomplete cherry-pick of bitcoin#28671: missing assert_equal replacement

Upstream PR bitcoin#28671 has two paired changes:

  1. Set mocktime so the addr's nTime is deterministic (self.addr_time = int(time.time()) + node.setmocktime(self.addr_time)).
  2. Replace the flaky assert_approx(result["time"], time.time(), vspan=10) with assert_equal(result["time"], self.addr_time).

Dash's merge commit 74c2e6f only applied change (1). The second hunk was dropped during the cherry-pick. The relevant code at test/functional/rpc_net.py:453-454 still reads:

# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)

Upstream diff for the same region:

-            # To avoid failing on slow test runners, use a 10s vspan here.
-            assert_approx(result["time"], time.time(), vspan=10)
+            assert_equal(result["time"], self.addr_time)

Consequences:

  • The PR's stated purpose ("Fix failing time check") is not actually achieved — the original assert_approx(... vspan=10) flakiness on slow runners remains.
  • With setmocktime now in effect, result["time"] is frozen at self.addr_time, but the assertion still compares against the wall-clock time.time(), which keeps advancing. On a sufficiently slow runner the delta will exceed 10s and the test will fail more deterministically than before the cherry-pick.

Fix: drop lines 453-454 and replace with assert_equal(result["time"], self.addr_time) (matches upstream exactly). Evidence: git diff f4049eaf08^1...f4049eaf08 -- test/functional/rpc_net.py shows the missing hunk; git diff 74c2e6f097~1...74c2e6f097 -- test/functional/rpc_net.py does not contain it.


Policy gate (backport-prereq-restore): For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. intentional_exclusion: true or a matching entry in policy_overrides). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

Suggested change
# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)
- # To avoid failing on slow test runners, use a 10s vspan here.
- assert_approx(result["time"], time.time(), vspan=10)
+ assert_equal(result["time"], self.addr_time)

source: ['claude-backport-reviewer']

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved in this update — Incomplete cherry-pick of bitcoin#28671: missing assert_equal replacement no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

Comment thread test/functional/rpc_net.py Outdated
Comment on lines +453 to +454
# To avoid failing on slow test runners, use a 10s vspan here.
assert_approx(result["time"], time.time(), vspan=10)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Blocking: Incomplete conflict resolution: bitcoin#28671

bitcoin#28671's actual fix is to compare getrawaddrman entry times against the mocked timestamp captured before addpeeraddress. Upstream f4049ea changes the assertion to assert_equal(result["time"], self.addr_time). Dash's backport adds self.addr_time and node.setmocktime(self.addr_time) in test_addpeeraddress, but leaves check_addr_information using assert_approx(result["time"], time.time(), vspan=10). That preserves the slow-runner failure the upstream PR fixed: if enough time passes between insertion and validation, the addrman entry time is the mocked value, not current wall time.


Policy gate (backport-prereq-restore): For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. intentional_exclusion: true or a matching entry in policy_overrides). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

source: ['codex-backport-reviewer']

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved in this update — Incomplete conflict resolution: bitcoin#28671 no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

@vijaydasmp vijaydasmp force-pushed the June_2026_4 branch 2 times, most recently from b05b97c to 5bc72fc Compare June 16, 2026 05:52
vijaydasmp and others added 2 commits June 16, 2026 11:27
fa4c683 test: Fix failing time check in rpc_net.py (MarcoFalke)

Pull request description:

  This check fails on slow runners, such as s390x qemu.

  Fix it by using mocktime.

  See bitcoin#28523 (comment)

ACKs for top commit:
  0xB10C:
    ACK fa4c683
  pinheadmz:
    ACK fa4c683
  brunoerg:
    crACK fa4c683

Tree-SHA512: 83fb534682e11e97537dc89de8c16f206f38af1a892a2d5970c02684c05eaea8fc9adba3159f16b2440ca0b3871d513a0562a6f3a38f19a5574a47be0919e42f
@vijaydasmp vijaydasmp requested a review from thepastaclaw June 16, 2026 06:29

@thepastaclaw thepastaclaw 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.

Code Review

Policy gate: an agent-reported missing upstream prerequisite was restored as a blocking finding. This PR is a full Bitcoin backport, and omitted upstream hunks require their prerequisite PRs unless the finding is explicitly allowlisted (intentional_exclusion / policy_override). The agent's original evidence is preserved in the finding(s) below.

Prior verifier summary (overridden by policy gate): PR #7358's title declares 5 Bitcoin backports (28523, 26638, 28976, 27822, 28671) but the head at 3c47eb7 contains merge commits for only 3 of them — bitcoin#26638 (test: prefer sqlite for wallet tests) and bitcoin#28976 (wallet: fix migration of blank wallets) are missing entirely. The 3 present backports also have an intra-PR ordering hazard: the bitcoin#28523 cherry-pick uses UniValue::pushKVEnd, which is not introduced until the following bitcoin#27822 cherry-pick, so the intermediate commit is not bisect-buildable. Final-tree behavior compiles and runs correctly, but the PR does not match its stated scope.

🔴 7 blocking | 🟡 1 suggestion(s)

5 additional finding(s) omitted (not in diff).

2 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/wallet/wallet.cpp`:
- [BLOCKING] src/wallet/wallet.cpp:1: PR title declares 5 backports but branch contains only 3 — bitcoin#26638 and bitcoin#28976 are missing
  The PR title is `backport: Merge bitcoin#28523, 26638, 28976, 27822, 28671`, but `git log develop..3c47eb777a` shows only three Bitcoin merge commits: a5264f984a (#28523), c34e457774 (#27822), 3c47eb777a (#28671). The #26638 (test: prefer sqlite for wallet tests) and #28976 (wallet: Fix migration of blank wallets) merge commits are not present on this head — they exist on a sibling branch (`dac3c8d477`, `0c247480bc`) but were not pushed here.

  Verification of the Dash tree at HEAD confirms the upstream behavior changes from those two PRs are absent:
  - `test/functional/test_framework/test_framework.py` still prefers BDB over SQLite (no #26638 adaptation).
  - `src/wallet/wallet.cpp` still gates the migration pre-check on `GetLegacyScriptPubKeyMan()` rather than `WALLET_FLAG_DESCRIPTORS`, and unconditionally runs `DoMigration` for blank legacy wallets (no #28976 fix). The upstream blank-wallet migration bug remains.

  Either restore the two missing cherry-picks to this branch or update the PR title/description to accurately reflect the three backports that are actually included.
- [BLOCKING] src/wallet/wallet.cpp:4745-4794: Missing upstream backport: bitcoin#28976
  The PR title includes bitcoin#28976, but at requested head 3c47eb777a the commit is not in upstream/develop..HEAD and the wallet migration fix is absent. Upstream #28976 changed the pre-migration check from GetLegacyScriptPubKeyMan() to WALLET_FLAG_DESCRIPTORS and skips DoMigration for WALLET_FLAG_BLANK_WALLET so blank legacy wallets can migrate. Dash still has the pre-PR code: it treats a missing legacy ScriptPubKeyMan as already-descriptor and always calls DoMigration after SQLite migration, so the upstream blank-wallet migration bug remains.

  ---
  **Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

In `src/rpc/net.cpp`:
- [SUGGESTION] src/rpc/net.cpp:1202: Reorder cherry-picks: bitcoin#28523 uses pushKVEnd before bitcoin#27822 introduces it (bisect hazard)
  The series orders the merges as a5264f984a (bitcoin#28523) → c34e457774 (bitcoin#27822) → 3c47eb777a (bitcoin#28671). Bitcoin#28523's new `AddrmanTableToJSON` calls `table.pushKVEnd(...)` (src/rpc/net.cpp:1202), but `UniValue::pushKVEnd` is introduced only by bitcoin#27822, which is the next commit in this PR.

  Verified: `git show a5264f984a:src/univalue/include/univalue.h` still declares only `__pushKV`, not `pushKVEnd`. Commit a5264f984a therefore does not compile in isolation, breaking `git bisect` across these two commits. The final HEAD is fine because 27822 is applied.

  Upstream chronological order is bitcoin#27822 (2023-06-21) → bitcoin#28523 (2023-10-03). Please reorder the cherry-picks to match upstream so every intermediate commit builds. (If you also restore #26638/#28976 per the other finding, this is a good opportunity to fix the order while re-pushing.)
- [BLOCKING] src/rpc/net.cpp:1202: Commit ordering: 28523 uses pushKVEnd before 27822 introduces it (bisect hazard)
  Within this PR the commits are ordered a5264f984a (Merge bitcoin#28523) → c34e457774 (Merge bitcoin#27822) → 3c47eb777a (Merge bitcoin#28671). bitcoin#28523's new `AddrmanTableToJSON` calls `table.pushKVEnd(...)` (src/rpc/net.cpp:1202), but `pushKVEnd` is only introduced by bitcoin#27822, which is the *next* commit. Verified: `git show a5264f984a:src/univalue/include/univalue.h` shows only `__pushKV`, not `pushKVEnd`. Result: commit a5264f984a does not compile in isolation. The final tree at HEAD is fine (27822 is applied), and runtime behavior is unaffected, but this breaks `git bisect` between these two commits. Upstream chronological order is 27822 (2023-06-21) → 28523 (2023-10-03); please reorder the cherry-picks to match.

  ---
  **Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
- [BLOCKING] src/rpc/net.cpp:1: PR title references 5 backports but branch contains only 3
  PR #7358 title declares `bitcoin#28523, 26638, 28976, 27822, 28671`. The head SHA 3c47eb777a only includes 28523, 27822, and 28671. Sibling branch `pr-review-7358` (different head) does contain 26638 and 28976. Confirm whether 26638 and 28976 are intentionally dropped from this head or if a rebase/push lost them. If dropped intentionally, update the PR title; if not, restore the missing cherry-picks. (No prerequisite analysis was performed on 26638/28976 since they're not in the reviewed tree.)

  ---
  **Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
- [BLOCKING] src/rpc/net.cpp:1202: Missing prerequisite before cherry-pick: bitcoin#27822
  Dash commit a5264f984a, the bitcoin#28523 backport, adds a call to table.pushKVEnd(...). In upstream, bitcoin#28523's parent already had UniValue::pushKVEnd because bitcoin#27822 was merged earlier. In Dash, a5264f984a^ still declares only UniValue::__pushKV, and pushKVEnd is introduced later by c34e457774. This means the dependency chain is present only in the final head, not at the cherry-pick point; the 28523 commit itself is unbuildable. The same commit also adds a test using time.time() before Dash adds the import in the later 28671 adaptation.

  ---
  **Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

In `test/functional/test_framework/test_framework.py`:
- [BLOCKING] test/functional/test_framework/test_framework.py:259-263: Missing upstream backport: bitcoin#26638
  The PR title includes bitcoin#26638, but at requested head 3c47eb777a the commit is not in upstream/develop..HEAD and the hunks are absent. Upstream #26638 changed the wallet test framework to prefer SQLite over BDB and updated wallet_migration.py's create_legacy_wallet helper to explicitly create legacy BDB wallets with descriptors=False. Dash still has the pre-PR behavior here: Prefer BDB unless unavailable, and wallet_migration.py still calls createwallet(wallet_name=wallet_name) without the upstream helper changes.

  ---
  **Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

In `src/rpc/server.cpp`:
- [BLOCKING] src/rpc/server.cpp:432-450: Missing prerequisite: bitcoin#26485
  Upstream bitcoin#27822 renamed an __pushKV use inside transformNamedArguments' named-only RPC parameter handling. Dash does not have that block: current code still iterates over const std::string& argNamePattern and lacks the named_only/options handling present in upstream's pre-27822 state. That upstream block was introduced by bitcoin#26485 (OBJ_NAMED_PARAMS). This is a soft prerequisite gap because the rename backport has no remaining __pushKV use in Dash, but a full upstream-state comparison shows the modified section depends on #26485.

  ---
  **Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

Comment thread src/rpc/net.cpp
// Address manager tables have unique entries so there is no advantage
// in using UniValue::pushKV, which checks if the key already exists
// in O(N). UniValue::pushKVEnd is used instead which currently is O(1).
table.pushKVEnd(key.str(), AddrmanEntryToJSON(info));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Suggestion: Reorder cherry-picks: bitcoin#28523 uses pushKVEnd before bitcoin#27822 introduces it (bisect hazard)

The series orders the merges as a5264f9 (bitcoin#28523) → c34e457 (bitcoin#27822) → 3c47eb7 (bitcoin#28671). bitcoin#28523's new AddrmanTableToJSON calls table.pushKVEnd(...) (src/rpc/net.cpp:1202), but UniValue::pushKVEnd is introduced only by bitcoin#27822, which is the next commit in this PR.

Verified: git show a5264f984a:src/univalue/include/univalue.h still declares only __pushKV, not pushKVEnd. Commit a5264f9 therefore does not compile in isolation, breaking git bisect across these two commits. The final HEAD is fine because 27822 is applied.

Upstream chronological order is bitcoin#27822 (2023-06-21) → bitcoin#28523 (2023-10-03). Please reorder the cherry-picks to match upstream so every intermediate commit builds. (If you also restore bitcoin#26638/bitcoin#28976 per the other finding, this is a good opportunity to fix the order while re-pushing.)

source: ['claude', 'codex']

Comment thread src/rpc/net.cpp
// Address manager tables have unique entries so there is no advantage
// in using UniValue::pushKV, which checks if the key already exists
// in O(N). UniValue::pushKVEnd is used instead which currently is O(1).
table.pushKVEnd(key.str(), AddrmanEntryToJSON(info));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Blocking: Commit ordering: 28523 uses pushKVEnd before 27822 introduces it (bisect hazard)

Within this PR the commits are ordered a5264f9 (Merge bitcoin#28523) → c34e457 (Merge bitcoin#27822) → 3c47eb7 (Merge bitcoin#28671). bitcoin#28523's new AddrmanTableToJSON calls table.pushKVEnd(...) (src/rpc/net.cpp:1202), but pushKVEnd is only introduced by bitcoin#27822, which is the next commit. Verified: git show a5264f984a:src/univalue/include/univalue.h shows only __pushKV, not pushKVEnd. Result: commit a5264f9 does not compile in isolation. The final tree at HEAD is fine (27822 is applied), and runtime behavior is unaffected, but this breaks git bisect between these two commits. Upstream chronological order is 27822 (2023-06-21) → 28523 (2023-10-03); please reorder the cherry-picks to match.


Policy gate (backport-prereq-restore): For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. intentional_exclusion: true or a matching entry in policy_overrides). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

source: ['claude-backport-reviewer']

Comment thread src/rpc/net.cpp
// Address manager tables have unique entries so there is no advantage
// in using UniValue::pushKV, which checks if the key already exists
// in O(N). UniValue::pushKVEnd is used instead which currently is O(1).
table.pushKVEnd(key.str(), AddrmanEntryToJSON(info));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Blocking: Missing prerequisite before cherry-pick: bitcoin#27822

Dash commit a5264f9, the bitcoin#28523 backport, adds a call to table.pushKVEnd(...). In upstream, bitcoin#28523's parent already had UniValue::pushKVEnd because bitcoin#27822 was merged earlier. In Dash, a5264f9^ still declares only UniValue::__pushKV, and pushKVEnd is introduced later by c34e457. This means the dependency chain is present only in the final head, not at the cherry-pick point; the 28523 commit itself is unbuildable. The same commit also adds a test using time.time() before Dash adds the import in the later 28671 adaptation.


Policy gate (backport-prereq-restore): For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. intentional_exclusion: true or a matching entry in policy_overrides). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.

source: ['codex-backport-reviewer']

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.

4 participants