Skip to content

Comments

backport: bitcoin#23508, #24187, #24528, #24579, #25412 (deployment backports)#6888

Open
kwvg wants to merge 6 commits intodashpay:developfrom
kwvg:deploy_bps
Open

backport: bitcoin#23508, #24187, #24528, #24579, #25412 (deployment backports)#6888
kwvg wants to merge 6 commits intodashpay:developfrom
kwvg:deploy_bps

Conversation

@kwvg
Copy link
Collaborator

@kwvg kwvg commented Oct 14, 2025

Additional Information

Breaking Changes

Requesting deployment information from getblockchaininfo is now deprecated (replaced by getdeploymentinfo) and restoring old behaviour will require the runtime flag -deprecatedrpc=softforks.

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas (note: N/A)
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@kwvg kwvg added this to the 23 milestone Oct 14, 2025
@github-actions
Copy link

github-actions bot commented Oct 14, 2025

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@github-actions
Copy link

This pull request has conflicts, please rebase.

@kwvg kwvg changed the title backport: merge bitcoin#23508, #24187, #24528, #24579, #24595, #25830, #25412 (deployment backports) backport: merge bitcoin#24595, 25830 (deployment backports) Oct 19, 2025
@kwvg kwvg force-pushed the deploy_bps branch 2 times, most recently from f57c351 to ffc7fdd Compare October 19, 2025 19:11
@github-actions
Copy link

This pull request has conflicts, please rebase.

@kwvg kwvg modified the milestones: 23, 23.1 Oct 21, 2025
@kwvg kwvg changed the title backport: merge bitcoin#24595, 25830 (deployment backports) backport: bitcoin#23508, #24187, #24528, #24579, #25412 (deployment backports) Oct 23, 2025
@kwvg kwvg added the RPC Some notable changes to RPC params/behaviour/descriptions label Oct 23, 2025
@kwvg kwvg requested a review from PastaPastaPasta October 23, 2025 15:51
@github-actions
Copy link

This pull request has conflicts, please rebase.

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

This pull request has conflicts, please rebase.

@kwvg kwvg marked this pull request as ready for review February 25, 2026 01:56
@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 669af55 and 1019d64.

📒 Files selected for processing (1)
  • src/rpc/blockchain.cpp

Walkthrough

The changes add a new RPC getdeploymentinfo and REST endpoints (/rest/deploymentinfo and /rest/deploymentinfo/.json) to expose deployment (softfork) state at the chain tip or at a supplied block. Softfork/VersionBits logic was refactored to compute deployment state from an arbitrary blockindex via a new DeploymentInfo path and to record per-block signalling history (threading an optional signalling_blocks vector through VersionBits statistics). getblockchaininfo was updated to optionally emit legacy softforks via the new DeploymentInfo path when deprecated RPCs are enabled. Extensive test updates and REST documentation were added to use and validate the new interfaces.

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant REST as REST/RPC Handler
    participant Chain as Blockchain
    participant Deploy as DeploymentInfo
    participant VB as VersionBits

    Client->>REST: GET /rest/deploymentinfo[/{blockhash}]
    REST->>Chain: Validate blockhash (optional) / lookup CBlockIndex
    Chain-->>REST: CBlockIndex
    REST->>Deploy: DeploymentInfo(CBlockIndex)
    Deploy->>VB: GetStateStatisticsFor(CBlockIndex, &signalling_blocks)
    VB-->>Deploy: BIP9Stats + signalling_blocks
    Deploy-->>REST: Aggregated deployments JSON
    REST-->>Client: HTTP 200 JSON {blockhash, height, deployments}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.28% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately references the upstream Bitcoin PR numbers being backported and describes the primary change—adding deployment information endpoints and deprecating the old getblockchaininfo softforks field.
Description check ✅ Passed The description clearly explains the purpose, dependencies, breaking changes, behavioral differences from upstream, and necessary test adjustments, all directly related to the changeset.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
src/rpc/blockchain.cpp (1)

1456-1462: ⚠️ Potential issue | 🟠 Major

Remove duplicate min_activation_height field in bip9 output.

Line 1456 already emits min_activation_height, and Line 1461 emits it again. This produces duplicate JSON keys in the same object, which is ambiguous for clients.

Proposed fix
     bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout);
     bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
     bip9.pushKV("ehf", chainman.GetConsensus().vDeployments[id].useEHF);
     if (auto it = signals.find(chainman.GetConsensus().vDeployments[id].bit); it != signals.end()) {
         bip9.pushKV("ehf_height", it->second);
     }
-    bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/blockchain.cpp` around lines 1456 - 1462, The bip9 JSON object is
emitting "min_activation_height" twice (via bip9.pushKV("min_activation_height",
chainman.GetConsensus().vDeployments[id].min_activation_height)); remove the
duplicate pushKV call so the field is only added once; locate the repeated call
near the block that also sets "ehf" and optional "ehf_height" (references:
bip9.pushKV, chainman.GetConsensus().vDeployments[id].min_activation_height,
signals) and delete the second occurrence to avoid duplicate JSON keys.
test/functional/rpc_blockchain.py (1)

194-252: ⚠️ Potential issue | 🟡 Minor

Fix Flake8 E121 — continuation line under-indented for hanging indent (Line 198)

The dict literal passed to assert_equal starting at Line 197 has inconsistent hanging indent, triggering Flake8 E121.

🔧 Proposed fix
-        assert_equal(gdi_result, {
-          "hash": blockhash,
-          "height": height,
-          "deployments": {
+        assert_equal(gdi_result, {
+            "hash": blockhash,
+            "height": height,
+            "deployments": {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/functional/rpc_blockchain.py` around lines 194 - 252, The dict literal
in check_signalling_deploymentinfo_result passed to assert_equal has
inconsistent hanging indentation causing Flake8 E121; reformat the multi-line
dict so the continuation lines are aligned under the opening parenthesis (or the
first key) of the assert_equal call and ensure nested dicts maintain consistent
indentation; update the block inside check_signalling_deploymentinfo_result (the
big "deployments" dict and its nested bip9/testdummy entries) so all
continuation lines use the same indent level and closing braces line up to
remove the E121 violation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/rest.cpp`:
- Around line 639-653: jsonRequest.params is created as an array
(UniValue::VARR) but the code uses pushKV("blockhash", ...) which requires an
object and will throw; change the code that adds the optional blockhash
positional RPC parameter to use jsonRequest.params.push_back(...) with the
string/hash value instead of pushKV, keeping the existing validation flow
(ParseHashStr / ParseHashV checks, chainman lookup via WITH_LOCK(::cs_main,
...)) and ensuring the RPC call to getdeploymentinfo receives the positional
argument as expected.

---

Outside diff comments:
In `@src/rpc/blockchain.cpp`:
- Around line 1456-1462: The bip9 JSON object is emitting
"min_activation_height" twice (via bip9.pushKV("min_activation_height",
chainman.GetConsensus().vDeployments[id].min_activation_height)); remove the
duplicate pushKV call so the field is only added once; locate the repeated call
near the block that also sets "ehf" and optional "ehf_height" (references:
bip9.pushKV, chainman.GetConsensus().vDeployments[id].min_activation_height,
signals) and delete the second occurrence to avoid duplicate JSON keys.

In `@test/functional/rpc_blockchain.py`:
- Around line 194-252: The dict literal in
check_signalling_deploymentinfo_result passed to assert_equal has inconsistent
hanging indentation causing Flake8 E121; reformat the multi-line dict so the
continuation lines are aligned under the opening parenthesis (or the first key)
of the assert_equal call and ensure nested dicts maintain consistent
indentation; update the block inside check_signalling_deploymentinfo_result (the
big "deployments" dict and its nested bip9/testdummy entries) so all
continuation lines use the same indent level and closing braces line up to
remove the E121 violation.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d71b89c and 669af55.

📒 Files selected for processing (19)
  • doc/REST-interface.md
  • doc/release-notes-6888.md
  • src/rest.cpp
  • src/rpc/blockchain.cpp
  • src/test/fuzz/rpc.cpp
  • src/test/fuzz/versionbits.cpp
  • src/versionbits.cpp
  • src/versionbits.h
  • test/functional/feature_asset_locks.py
  • test/functional/feature_cltv.py
  • test/functional/feature_dersig.py
  • test/functional/feature_governance.py
  • test/functional/feature_mnehf.py
  • test/functional/feature_new_quorum_type_activation.py
  • test/functional/interface_rest.py
  • test/functional/rpc_blockchain.py
  • test/functional/test_framework/blocktools.py
  • test/functional/test_framework/util.py
  • test/functional/wallet_signrawtransactionwithwallet.py

Comment on lines +639 to +653
jsonRequest.params = UniValue(UniValue::VARR);

if (!hash_str.empty()) {
uint256 hash;
if (!ParseHashStr(hash_str, hash)) {
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hash_str);
}

const ChainstateManager* chainman = GetChainman(context, req);
if (!chainman) return false;
if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(ParseHashV(hash_str, "blockhash")))) {
return RESTERR(req, HTTP_BAD_REQUEST, "Block not found");
}

jsonRequest.params.pushKV("blockhash", hash_str);
Copy link

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:

# First, let's look at the actual code in src/rest.cpp at the specified lines
head -n 680 src/rest.cpp | tail -n 50

Repository: dashpay/dash

Length of output: 1788


🏁 Script executed:

# Search for UniValue API definitions to understand pushKV behavior
fd -t f 'univalue.h' | head -5

Repository: dashpay/dash

Length of output: 87


🏁 Script executed:

# Check what UniValue types are available and their methods
rg -A 20 'class UniValue' src/univalue/ 2>/dev/null | head -100

Repository: dashpay/dash

Length of output: 1667


🏁 Script executed:

# Look for UniValue pushKV and push_back definitions with context
rg 'void push_back|void pushKV' src/univalue/ -A 3

Repository: dashpay/dash

Length of output: 1429


🏁 Script executed:

# Check how other REST handlers use jsonRequest.params
rg -n 'jsonRequest\.params\.(push|pushKV)' src/rest.cpp

Repository: dashpay/dash

Length of output: 121


🏁 Script executed:

# Find pushKV implementation
rg -A 10 'void.*pushKV' src/univalue/ -m 50

Repository: dashpay/dash

Length of output: 2497


🏁 Script executed:

# Find push_back implementation
rg -A 10 'void.*push_back\(' src/univalue/ | grep -v utf

Repository: dashpay/dash

Length of output: 1328


🏁 Script executed:

# Check the getdeploymentinfo RPC method to see what it expects
rg -B 5 -A 15 'getdeploymentinfo\(' src/rpc/

Repository: dashpay/dash

Length of output: 1380


🏁 Script executed:

# Look at other REST handlers that pass params to RPC methods to see the pattern
rg -B 3 -A 3 'jsonRequest\.params\.(push_back|pushKV)' src/rest.cpp | head -50

Repository: dashpay/dash

Length of output: 279


🏁 Script executed:

# Check if there's checkType method that would fail on type mismatch
rg -B 2 -A 5 'checkType' src/univalue/lib/univalue.cpp | head -30

Repository: dashpay/dash

Length of output: 626


🏁 Script executed:

# Look at other REST handlers to see how they construct params
rg -B 5 -A 10 'jsonRequest\.params = UniValue' src/rest.cpp

Repository: dashpay/dash

Length of output: 1270


🏁 Script executed:

# Specifically check if any other handlers use pushKV on a VARR
rg -B 10 'jsonRequest\.params.*VARR' src/rest.cpp | grep -A 10 'params = '

Repository: dashpay/dash

Length of output: 408


Use positional array argument instead of pushKV for RPC params.

jsonRequest.params is initialized as an array (VARR), but Line 653 uses pushKV(). Since pushKV() calls checkType(VOBJ) and will throw an exception when called on an array type, this breaks passing the optional blockhash parameter to the RPC handler. The getdeploymentinfo RPC expects a positional argument, so use push_back() instead.

Proposed fix
-            jsonRequest.params.pushKV("blockhash", hash_str);
+            jsonRequest.params.push_back(hash_str);
📝 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
jsonRequest.params = UniValue(UniValue::VARR);
if (!hash_str.empty()) {
uint256 hash;
if (!ParseHashStr(hash_str, hash)) {
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hash_str);
}
const ChainstateManager* chainman = GetChainman(context, req);
if (!chainman) return false;
if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(ParseHashV(hash_str, "blockhash")))) {
return RESTERR(req, HTTP_BAD_REQUEST, "Block not found");
}
jsonRequest.params.pushKV("blockhash", hash_str);
jsonRequest.params = UniValue(UniValue::VARR);
if (!hash_str.empty()) {
uint256 hash;
if (!ParseHashStr(hash_str, hash)) {
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hash_str);
}
const ChainstateManager* chainman = GetChainman(context, req);
if (!chainman) return false;
if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(ParseHashV(hash_str, "blockhash")))) {
return RESTERR(req, HTTP_BAD_REQUEST, "Block not found");
}
jsonRequest.params.push_back(hash_str);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rest.cpp` around lines 639 - 653, jsonRequest.params is created as an
array (UniValue::VARR) but the code uses pushKV("blockhash", ...) which requires
an object and will throw; change the code that adds the optional blockhash
positional RPC parameter to use jsonRequest.params.push_back(...) with the
string/hash value instead of pushKV, keeping the existing validation flow
(ParseHashStr / ParseHashV checks, chainman lookup via WITH_LOCK(::cs_main,
...)) and ensuring the RPC call to getdeploymentinfo receives the positional
argument as expected.

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

Labels

RPC Some notable changes to RPC params/behaviour/descriptions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants