Skip to content

Conversation

@knst
Copy link
Collaborator

@knst knst commented Dec 8, 2025

Issue being fixed or feature implemented

When funding a transaction with external inputs, instead of providing solving data, a user may want to just provide the maximum signed size of that input. This is particularly useful in cases where the input is nonstandard as our dummy signer is unable to handle those inputs.

The input size can be provided to any input regardless of whether it belongs to the wallet and the provided size will always be used regardless of any calculated input size. This allows the user to override the calculated input size which may overestimate in some circumstances due to missing information (e.g. if the private key is not known, a maximum size signature will be used, but the actual signer may be doing additional work which reduces the size of the signature).

For send and walletcreatefundedpsbt, the input size is specified in a size field in an input object. For fundrawtransaction, a new input_sizes field is added to the options object. This is an array of objects consisting of a txid, vout, and size.

What was done?

Bitcoin backport bitcoin#23201 and related fixes.
This backport is not trivial to do, not trivial to dashify, and not trivial to review, so, it has own PR.

Please note, that implementation of FillInputToWeight is different with Bitcoin Core. Due missing stack of "segregated data" we can't get exactly the same size, it maybe different up to 2 bytes.

 /*
// We will want to subtract the size of the Compact Size UInt that will also be serialized.
// However doing so when the size is near a boundary can result in a problem where it is not
// possible to have a stack element size and combination to exactly equal a target.
// So we allow to fullfill transaction 2 byte less in this situation.
*/

How Has This Been Tested?

Run unit & functional tests

Breaking Changes

N/A

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • 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

@knst knst added this to the 23.1 milestone Dec 8, 2025
@knst knst changed the title backport: bitcoin/bitcoin#23201, bitcoin/bitcoin#25551 backport: bitcoin/bitcoin#23201, bitcoin/bitcoin#25551 (external signer, user provided size of tx) Dec 8, 2025
@github-actions
Copy link

github-actions bot commented Dec 8, 2025

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Walkthrough

Adds per-input serialized-weight hints throughout wallet funding and signing. CCoinControl gains SetInputWeight/HasInputWeight/GetInputWeight and an internal map to store per-outpoint weights. RPC surfaces (fundrawtransaction, send, walletcreatefundedpsbt) accept and validate per-input input_sizes, which are moved into options by SetOptionsInputWeights and applied to CCoinControl. FundTransaction and coin selection consult these input weights when estimating input bytes. A new wallet::FillInputToWeight helper is added and used in DummySignTx to pre-fill inputs to requested weight. Unit and functional tests were added/updated to cover boundaries and fee effects.

Sequence Diagram

sequenceDiagram
    participant User
    participant RPC as RPC Layer (spend.cpp)
    participant CC as CCoinControl
    participant CS as CoinSelection / FundTransaction
    participant Sign as Signing (DummySignTx / wallet.cpp)

    User->>RPC: Call fund/send/walletcreatefundedpsbt with inputs incl. input_sizes
    RPC->>RPC: SetOptionsInputWeights(inputs, options)
    RPC->>CC: SetInputWeight(outpoint, weight) for each input
    RPC->>CS: FundTransaction(..., coin_control, options)
    CS->>CC: HasInputWeight(outpoint)?
    alt weight present
        CC-->>CS: true
        CS->>CC: GetInputWeight(outpoint)
        CS->>CS: Use provided weight to compute input_bytes (affects selection/fees)
    else no weight
        CC-->>CS: false
        CS->>CS: Use estimated input size
    end
    CS-->>RPC: Return funded tx/psbt
    RPC->>Sign: DummySignTx(tx/psbt, coin_control)
    Sign->>CC: HasInputWeight(outpoint)?
    alt weight present
        CC-->>Sign: true
        Sign->>Sign: FillInputToWeight(txin, target_weight)
        Sign->>Sign: Skip signing for that input
    else no weight
        CC-->>Sign: false
        Sign->>Sign: Normal signing flow
    end
    Sign-->>RPC: Signed/finalized tx or PSBT
    RPC-->>User: Result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Inspect CCoinControl additions: key type correctness, map usage, const-correctness.
  • Review SetOptionsInputWeights parsing/validation and RPC error messages for edge cases.
  • Audit FundTransaction/Coin Selection changes where input_bytes can be overridden for solvability and fee calculations.
  • Validate FillInputToWeight implementation and its integration in DummySignTx for CompactSize boundary and off-by-one behavior.
  • Run and review updated unit and functional tests for determinism and coverage.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.83% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately references the Bitcoin Core PRs being backported and hints at the feature (external signer, user-provided transaction size), though it is somewhat abbreviated and technical.
Description check ✅ Passed The description comprehensively explains the feature being implemented, the motivation for it, how it works across different RPC methods, implementation notes about differences from Bitcoin Core, and testing status.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 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

🧹 Nitpick comments (3)
test/functional/wallet_send.py (1)

542-542: Use string literal for Decimal to avoid float precision issues.

"Unfortunately, most decimal fractions cannot be represented exactly as binary fractions." Using Decimal(0.0001) with a float literal may introduce precision errors.

-        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal(0.0001))
+        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal("0.0001"))
test/functional/rpc_fundrawtransaction.py (2)

10-10: Remove unused import.

Static analysis correctly identifies that ceil from math is imported but never used in this file.

-from math import ceil

1028-1028: Use string literal for Decimal to avoid float precision issues.

Same as in wallet_send.py, using Decimal(0.0001) with a float literal may introduce precision errors.

-        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal(0.0001))
+        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal("0.0001"))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3d61f2 and 151c1a59f7ea65adfbe0548e52e1d2ea513751e7.

📒 Files selected for processing (9)
  • src/wallet/coincontrol.h (2 hunks)
  • src/wallet/rpc/spend.cpp (9 hunks)
  • src/wallet/spend.cpp (1 hunks)
  • src/wallet/test/spend_tests.cpp (1 hunks)
  • src/wallet/wallet.cpp (2 hunks)
  • src/wallet/wallet.h (1 hunks)
  • test/functional/rpc_fundrawtransaction.py (3 hunks)
  • test/functional/rpc_psbt.py (3 hunks)
  • test/functional/wallet_send.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{cpp,h,hpp,cc}

📄 CodeRabbit inference engine (CLAUDE.md)

Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1

Files:

  • src/wallet/wallet.h
  • src/wallet/test/spend_tests.cpp
  • src/wallet/spend.cpp
  • src/wallet/coincontrol.h
  • src/wallet/rpc/spend.cpp
  • src/wallet/wallet.cpp
src/wallet/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Wallet implementation must use Berkeley DB and SQLite

Files:

  • src/wallet/wallet.h
  • src/wallet/test/spend_tests.cpp
  • src/wallet/spend.cpp
  • src/wallet/coincontrol.h
  • src/wallet/rpc/spend.cpp
  • src/wallet/wallet.cpp
src/{test,wallet/test}/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework

Files:

  • src/wallet/test/spend_tests.cpp
test/functional/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Functional tests in test/functional/ must be written in Python (minimum version specified in .python-version) and depend on dashd and dash-node

Files:

  • test/functional/wallet_send.py
  • test/functional/rpc_fundrawtransaction.py
  • test/functional/rpc_psbt.py
🧠 Learnings (7)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/wallet/test/spend_tests.cpp
  • src/wallet/rpc/spend.cpp
  • test/functional/rpc_fundrawtransaction.py
  • test/functional/rpc_psbt.py
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay

Applied to files:

  • src/wallet/test/spend_tests.cpp
  • src/wallet/rpc/spend.cpp
  • src/wallet/wallet.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs

Applied to files:

  • src/wallet/spend.cpp
  • src/wallet/coincontrol.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-01-14T08:37:16.955Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6530
File: src/validation.cpp:360-362
Timestamp: 2025-01-14T08:37:16.955Z
Learning: The UpdateTransactionsFromBlock() method in txmempool.cpp takes parameters in the order: vHashUpdate, ancestor_size_limit, ancestor_count_limit. The size limit comes before the count limit.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • test/functional/rpc_fundrawtransaction.py
  • test/functional/rpc_psbt.py
🧬 Code graph analysis (9)
src/wallet/wallet.h (1)
src/wallet/wallet.cpp (2)
  • FillInputToWeight (1661-1694)
  • FillInputToWeight (1661-1661)
src/wallet/test/spend_tests.cpp (1)
src/wallet/wallet.cpp (2)
  • FillInputToWeight (1661-1694)
  • FillInputToWeight (1661-1661)
test/functional/wallet_send.py (2)
test/functional/test_framework/util.py (3)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (3)
  • send (797-994)
  • send (797-797)
  • tx (981-981)
src/wallet/spend.cpp (1)
src/policy/policy.h (1)
  • GetVirtualTransactionSize (118-121)
src/wallet/coincontrol.h (4)
src/wallet/spend.cpp (1)
  • outpoint (150-150)
src/wallet/wallet.cpp (1)
  • outpoint (1093-1093)
src/wallet/interfaces.cpp (4)
  • outpoint (399-399)
  • outpoint (399-399)
  • outpoint (400-400)
  • outpoint (400-400)
src/wallet/coinjoin.cpp (2)
  • outpoint (510-510)
  • outpoint (560-560)
src/wallet/rpc/spend.cpp (2)
src/rpc/util.cpp (2)
  • ParseHashO (106-109)
  • ParseHashO (106-106)
src/rpc/rawtransaction_util.cpp (2)
  • ConstructTransaction (24-132)
  • ConstructTransaction (24-24)
test/functional/rpc_fundrawtransaction.py (2)
test/functional/test_framework/util.py (4)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_greater_than (77-79)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (4)
  • fundrawtransaction (603-704)
  • fundrawtransaction (603-603)
  • signrawtransactionwithwallet (706-795)
  • signrawtransactionwithwallet (706-706)
src/wallet/wallet.cpp (1)
src/serialize.h (1)
  • GetSizeOfCompactSize (245-251)
test/functional/rpc_psbt.py (3)
test/functional/test_framework/util.py (2)
  • assert_greater_than (77-79)
  • assert_raises_rpc_error (132-148)
test/functional/test_framework/test_node.py (1)
  • get_wallet_rpc (363-369)
src/wallet/rpc/spend.cpp (2)
  • walletcreatefundedpsbt (1075-1208)
  • walletcreatefundedpsbt (1075-1075)
🪛 Flake8 (7.3.0)
test/functional/rpc_fundrawtransaction.py

[error] 10-10: 'math.ceil' imported but unused

(F401)

🪛 Ruff (0.14.7)
test/functional/wallet_send.py

542-542: Decimal() called with float literal argument

Replace with string literal

(RUF032)

test/functional/rpc_fundrawtransaction.py

1028-1028: Decimal() called with float literal argument

Replace with string literal

(RUF032)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: Lint / Run linters
🔇 Additional comments (17)
src/wallet/spend.cpp (1)

553-556: Preset-input size override via CCoinControl weight is consistent and correct

Using HasInputWeight/GetInputWeight here to override input_bytes with GetVirtualTransactionSize(...) cleanly integrates caller‑supplied weights into coin selection and solvability checks, and preserves the existing -1 error path for inputs without a weight. This matches the intended behavior for external/nonstandard inputs.

src/wallet/wallet.h (1)

1134-1134: New FillInputToWeight API declaration is well-placed and consistent

The FillInputToWeight declaration in the wallet namespace matches its implementation and test usage, and sits logically next to DummySignInput as another input‑sizing helper.

src/wallet/wallet.cpp (2)

1661-1694: FillInputToWeight correctly pads inputs to a bounded target size

The helper cleanly enforces its preconditions (empty scriptSig, nondecreasing size) and uses compact‑size accounting so that the final serialized input size is guaranteed within [target_weight-2, target_weight]. This matches the documented 2‑byte tolerance and is exercised by the new unit tests.


1704-1712: DummySignTx integration with per-input weights behaves as intended

Short‑circuiting to FillInputToWeight when HasInputWeight(txin.prevout) is true lets callers fully control fee estimation for those inputs, and intentionally skips producing dummy signatures afterward. On failure, the function exits early, allowing higher‑level code to surface “missing solving data / bad weight” conditions as before.

src/wallet/coincontrol.h (1)

132-147: Per-input weight tracking in CCoinControl is coherent and minimally scoped

The new m_input_weights map and its SetInputWeight / HasInputWeight / GetInputWeight accessors integrate cleanly with existing COutPoint-keyed state, and match how the weights are consumed in coin selection and dummy signing. The assert in GetInputWeight is appropriate given current usage patterns.

Also applies to: 162-163

src/wallet/test/spend_tests.cpp (1)

61-106: FillInputToWeight tests thoroughly exercise edge cases and compact-size boundaries

The new helper and FillInputToWeightTest cover negative/too‑small targets, the exact empty‑input size, and multiple compact‑size transitions, verifying both overall serialized size and scriptSig length. This gives good confidence that FillInputToWeight behaves correctly across its range of expected inputs.

src/wallet/rpc/spend.cpp (4)

531-560: LGTM - Input size parsing and validation is thorough.

The validation logic correctly enforces:

  • vout must be present and non-negative
  • size must be present, at least 41 bytes (minimum input size), and at most MAX_STANDARD_TX_SIZE
  • The CHECK_NONFATAL(min_input_size == 41) assertion documents the expected minimum

The use of size in the RPC API (vs. weight in the internal API) is appropriate for Dash's non-SegWit transaction format where size and weight are equivalent.


586-601: Prevent options conflict for input sizes specified in inputs.

The helper correctly:

  1. Rejects input_sizes in options when inputs specify sizes (preventing ambiguity)
  2. Early-returns if no inputs
  3. Extracts only inputs that have a size field

One consideration: When inputs has elements but none contain size, this still pushes an empty input_sizes array to options. This is harmless but slightly redundant.


946-947: LGTM - Input weights correctly propagated in send RPC.

The call to SetOptionsInputWeights properly extracts size hints from options["inputs"] before passing to FundTransaction.


1174-1184: LGTM - Input weights correctly propagated in walletcreatefundedpsbt.

The options object is properly made mutable, SetOptionsInputWeights extracts size hints from inputs, and the modified options are passed to FundTransaction.

test/functional/wallet_send.py (1)

506-542: LGTM - Comprehensive test coverage for input weight functionality.

The test correctly:

  1. Computes input weight from the finalized PSBT
  2. Tests error condition when input_sizes is in options instead of inputs
  3. Validates funding works with explicit input weights
  4. Verifies mempool acceptance and fee calculation
test/functional/rpc_fundrawtransaction.py (2)

981-986: LGTM - Comprehensive error condition coverage for input_sizes validation.

Tests correctly verify all validation paths:

  • Missing vout key
  • Negative vout value
  • Missing size key
  • Size below minimum (40 bytes, which is less than 41)
  • Negative size
  • Size exceeding maximum standard tx size

1010-1033: LGTM - Weight-based funding tests are thorough.

The tests correctly verify:

  • Funding with explicit input weights works and passes mempool acceptance
  • Lower weight results in lower fee
  • Higher weight results in higher fee
  • Explicit weight overrides calculated weight when solving data is provided
  • Fee rate calculation is correct with explicit weight
  • Boundary values at csuint thresholds (255, 65539) don't cause issues
test/functional/rpc_psbt.py (4)

467-475: LGTM - Test setup for external input funding with PSBT.

The test correctly:

  1. Logs the test section
  2. Creates a new wallet "extfund" on node 1
  3. Sets up the necessary infrastructure for external input testing

507-521: Input weight calculation includes buffer for potential scriptwitness variation.

The formula input_weight = ((41 + len_scriptsig + 2) * 4) + len_scriptwitness includes a 2-byte buffer. This is appropriate for weight calculation in a SegWit-aware context, though Dash doesn't use SegWit. The calculation appears adapted from Bitcoin Core's approach.

For Dash's non-SegWit context, the simpler formula might be 41 + len_scriptsig, but the current approach is conservative and aligns with the backported code's comments about allowing up to 2-byte differences.

Please verify that this weight calculation formula aligns with the FillInputToWeight implementation mentioned in the PR notes, which permits up to 2-byte differences due to missing segregated-data stack handling.


523-563: LGTM - Comprehensive input weight testing via walletcreatefundedpsbt.

The tests correctly verify:

  1. Error when input_sizes is specified in options instead of inputs
  2. Funding with explicit input weight succeeds and passes mempool acceptance
  3. Lower weight produces lower fee
  4. Higher weight produces higher fee
  5. Explicit weight overrides calculated weight when solving data is provided

565-577: LGTM - Tests weight override for wallet inputs after descriptor import.

After importing the descriptor into the wallet, the test verifies that explicitly provided weights still override the wallet's calculated weight for inputs it can solve. This ensures the weight override behavior is consistent for both external and wallet inputs.

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: 0

♻️ Duplicate comments (1)
src/wallet/rpc/spend.cpp (1)

643-653: RPC documentation structure matches backport pattern.

Per the past review discussion and retrieved learnings, backported changes should match the original upstream PRs. This RPC argument structure for input_sizes follows the same pattern used in Bitcoin Core's implementation. Based on learnings, backported code should be preserved as-is unless there are genuine bugs.

🧹 Nitpick comments (2)
test/functional/wallet_send.py (1)

542-542: Use string literal for Decimal to avoid floating-point precision issues.

Per static analysis hint (RUF032), Decimal() should be called with a string literal instead of a float literal to avoid potential floating-point representation issues.

-        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal(0.0001))
+        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal("0.0001"))
test/functional/rpc_fundrawtransaction.py (1)

1027-1027: Use string literal for Decimal to avoid floating-point precision issues.

Per static analysis hint (RUF032), Decimal() should be called with a string literal instead of a float literal.

-        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal(0.0001))
+        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal("0.0001"))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 151c1a59f7ea65adfbe0548e52e1d2ea513751e7 and 0a38158c7cb467c2eeda0a303a998428cd89f556.

📒 Files selected for processing (9)
  • src/wallet/coincontrol.h (2 hunks)
  • src/wallet/rpc/spend.cpp (9 hunks)
  • src/wallet/spend.cpp (1 hunks)
  • src/wallet/test/spend_tests.cpp (1 hunks)
  • src/wallet/wallet.cpp (2 hunks)
  • src/wallet/wallet.h (1 hunks)
  • test/functional/rpc_fundrawtransaction.py (3 hunks)
  • test/functional/rpc_psbt.py (3 hunks)
  • test/functional/wallet_send.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/wallet/wallet.h
  • src/wallet/wallet.cpp
  • src/wallet/spend.cpp
  • src/wallet/test/spend_tests.cpp
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{cpp,h,hpp,cc}

📄 CodeRabbit inference engine (CLAUDE.md)

Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1

Files:

  • src/wallet/rpc/spend.cpp
  • src/wallet/coincontrol.h
src/wallet/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Wallet implementation must use Berkeley DB and SQLite

Files:

  • src/wallet/rpc/spend.cpp
  • src/wallet/coincontrol.h
test/functional/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Functional tests in test/functional/ must be written in Python (minimum version specified in .python-version) and depend on dashd and dash-node

Files:

  • test/functional/rpc_fundrawtransaction.py
  • test/functional/rpc_psbt.py
  • test/functional/wallet_send.py
🧠 Learnings (8)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/wallet/rpc/spend.cpp
  • test/functional/rpc_psbt.py
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-25T07:08:51.918Z
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-01-14T08:37:16.955Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6530
File: src/validation.cpp:360-362
Timestamp: 2025-01-14T08:37:16.955Z
Learning: The UpdateTransactionsFromBlock() method in txmempool.cpp takes parameters in the order: vHashUpdate, ancestor_size_limit, ancestor_count_limit. The size limit comes before the count limit.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • test/functional/rpc_fundrawtransaction.py
  • test/functional/rpc_psbt.py
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs

Applied to files:

  • src/wallet/coincontrol.h
🧬 Code graph analysis (3)
test/functional/rpc_fundrawtransaction.py (2)
test/functional/test_framework/util.py (4)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_greater_than (77-79)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (4)
  • fundrawtransaction (603-704)
  • fundrawtransaction (603-603)
  • signrawtransactionwithwallet (706-795)
  • signrawtransactionwithwallet (706-706)
test/functional/rpc_psbt.py (2)
test/functional/test_framework/util.py (2)
  • assert_greater_than (77-79)
  • assert_raises_rpc_error (132-148)
test/functional/test_framework/test_node.py (1)
  • get_wallet_rpc (363-369)
src/wallet/coincontrol.h (4)
src/wallet/spend.cpp (1)
  • outpoint (150-150)
src/wallet/wallet.cpp (1)
  • outpoint (1093-1093)
src/wallet/interfaces.cpp (4)
  • outpoint (399-399)
  • outpoint (399-399)
  • outpoint (400-400)
  • outpoint (400-400)
src/wallet/coinjoin.cpp (2)
  • outpoint (510-510)
  • outpoint (560-560)
🪛 Ruff (0.14.7)
test/functional/rpc_fundrawtransaction.py

1027-1027: Decimal() called with float literal argument

Replace with string literal

(RUF032)

test/functional/wallet_send.py

542-542: Decimal() called with float literal argument

Replace with string literal

(RUF032)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: linux64_multiprocess-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: arm-linux-build / Build source
🔇 Additional comments (15)
src/wallet/coincontrol.h (2)

132-147: LGTM! Clean API for per-input weight tracking.

The three new methods follow a consistent pattern: SetInputWeight to store, HasInputWeight to check existence, and GetInputWeight with an assert precondition requiring callers to verify existence first. This matches the usage pattern in src/wallet/spend.cpp where HasInputWeight is always checked before GetInputWeight.


162-163: Comment accurately reflects Dash context.

The comment notes "weight (equals to size)" which is correct for Dash since there's no segregated witness data, making weight equivalent to serialized size. This aligns with the PR description noting the backport differs from Bitcoin Core due to missing segregated-data stack handling.

src/wallet/rpc/spend.cpp (4)

5-5: New include is appropriate.

The consensus/validation.h include is needed for MAX_STANDARD_TX_SIZE used in the size validation at line 554.


531-560: Robust input_sizes validation logic.

The parsing correctly validates:

  • txid via ParseHashO
  • vout presence, type, and non-negativity
  • size presence, minimum bound (41 bytes for outpoint + sequence + empty scriptSig), and maximum bound (MAX_STANDARD_TX_SIZE)

The CHECK_NONFATAL(min_input_size == 41) is a good compile-time sanity check ensuring the constant matches expectations.


586-601: SetOptionsInputWeights correctly enforces input specification location.

The guard at line 588-590 prevents users from specifying input_sizes in options when using send or walletcreatefundedpsbt, enforcing that sizes must be specified inline with inputs. The function then extracts and consolidates size specifications from inputs into the options for downstream processing.


1174-1184: Correct integration in walletcreatefundedpsbt.

The code properly:

  1. Creates a mutable copy of options if provided, or an empty object
  2. Calls SetOptionsInputWeights to extract per-input sizes from the inputs array
  3. Passes the enriched options to FundTransaction
test/functional/wallet_send.py (2)

506-514: Input weight calculation logic looks correct.

The code correctly:

  1. Decodes the PSBT to find the external input
  2. Locates the matching input by txid/vout
  3. Calculates input_weight = 41 + len_scriptsig - 1 where 41 is the base input size (outpoint + sequence + 1-byte scriptSig length), and the -1 compensates for the length byte already included in the base.

517-523: Good coverage for error path.

The test correctly verifies that specifying input_sizes in the options object (rather than inline with inputs) raises the expected RPC error with code -8.

test/functional/rpc_fundrawtransaction.py (3)

980-985: Comprehensive error path coverage for input_sizes validation.

The tests cover all validation scenarios:

  • Missing vout key
  • Negative vout
  • Missing size key
  • Size below minimum (40, -1)
  • Size above maximum (400001)

1000-1006: Input weight calculation is well-documented.

The calculation input_weight = signed_weight - unsigned_weight + 41 correctly derives the input's signing overhead by comparing signed vs unsigned transaction sizes, then adding back the base input components (prevout, sequence, 1-byte scriptSig length).


1030-1031: Good boundary testing for CompactSize encoding.

Testing at sizes 255 and 65539 validates correct handling at CompactSize encoding boundaries (1-byte to 3-byte, and 3-byte to 5-byte transitions), ensuring the weight serialization doesn't have off-by-one issues at these thresholds.

test/functional/rpc_psbt.py (4)

17-17: Import added for new assertion.

The assert_greater_than import is needed for the fee comparison assertions in the new weight-based tests.


515-521: Input weight formula includes witness handling (safely degenerates for Dash).

The formula input_weight = ((41 + len_scriptsig + 2) * 4) + len_scriptwitness is designed for Bitcoin's witness weight calculation. For Dash (no SegWit), len_scriptwitness will always be 0, and the formula correctly computes the input weight as (41 + len_scriptsig + 2) * 4. The +2 buffer provides margin for signature size variance.


523-531: Error path test for options-based input_sizes.

Consistent with wallet_send.py, this test verifies that specifying input_sizes in the options object raises RPC error -8 with the expected message.


533-577: Comprehensive PSBT weight-based funding tests.

The tests cover:

  1. Funding with exact input weight → mempool acceptance
  2. Lower weight → lower fee (line 549)
  3. Higher weight → higher fee (line 556)
  4. Provided weight overrides solving_data calculated weight (line 563)
  5. Wallet inputs also respect provided weights after descriptor import (lines 566-577)

This provides excellent coverage of the new input weight functionality.

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

♻️ Duplicate comments (1)
src/wallet/rpc/spend.cpp (1)

643-657: fundrawtransaction input_sizes RPC arg now correctly models an array of objects.

The input_sizes option is documented as an ARR whose elements are OBJ containing txid, vout, and size. This matches the actual accepted format and the upstream Bitcoin structure the backport is based on, and resolves the earlier array-of-scalars mismatch.

🧹 Nitpick comments (3)
test/functional/wallet_send.py (1)

506-543: Align Decimal usage and keep per-input-size test logic as-is

The new block that decodes the PSBT, derives an input_weight hint from final_scriptSig, checks the input_sizes error path, and then exercises funding with a provided size field is well-structured and ties directly into the new wallet behavior. The final assert_fee_amount using testmempoolaccept is a good end‑to‑end check.

One small nit: to avoid any float‑to‑Decimal rounding surprises and to match the rest of the file, prefer a string literal here:

-        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal(0.0001))
+        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal("0.0001"))
src/wallet/rpc/spend.cpp (1)

586-601: SetOptionsInputWeights helper and its use in send/walletcreatefundedpsbt are sound, with a tiny optional polish.

  • SetOptionsInputWeights correctly:
    • Rejects options that already define input_sizes, enforcing that hints are supplied via inputs objects, not directly in options.
    • Scans the provided inputs array and builds input_sizes only for entries that actually define size, so other inputs remain unaffected.
  • In both send and walletcreatefundedpsbt, copying the options into a local UniValue options{...} before passing it to SetOptionsInputWeights and then to FundTransaction is the right pattern: it avoids mutating request.params while still letting FundTransaction see the synthesized input_sizes.
  • Behavior with omitted or empty inputs is safe: inputs.size() == 0 short-circuits before any work.

Minor optional polish: you could skip pushing an "input_sizes" key when sizes remains empty, but this is purely cosmetic and has no behavioral impact.

Also applies to: 903-951, 1178-1189

test/functional/rpc_fundrawtransaction.py (1)

994-1032: Behavioral tests for size hints look solid; consider avoiding Decimal with a float literal.

  • The two-step signing flow (signed_tx1 from the external-funding wallet, signed_tx2 from node 0) correctly isolates the external input’s contribution to transaction size.
  • Deriving input_weight from the size delta and then checking:
    • funding success with an exact hint,
    • monotonicity of fees when shrinking/growing the hint,
    • that an explicit input_sizes entry overrides solving-data–based estimation, and
    • a specific feerate target via assert_fee_amount,
      gives strong end-to-end coverage of the new feature, including the “csuint boundary” cases.

Minor nit from Ruff (RUF032): Decimal(0.0001) is constructed from a binary float, which can introduce tiny rounding artifacts. It’s safer and more idiomatic to pass a string literal:

-        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal(0.0001))
+        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal("0.0001"))

This keeps the test entirely in exact decimal space.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a38158c7cb467c2eeda0a303a998428cd89f556 and e34d649da4d90df537fc020758253114e8c872d0.

📒 Files selected for processing (9)
  • src/wallet/coincontrol.h (2 hunks)
  • src/wallet/rpc/spend.cpp (9 hunks)
  • src/wallet/spend.cpp (1 hunks)
  • src/wallet/test/spend_tests.cpp (1 hunks)
  • src/wallet/wallet.cpp (2 hunks)
  • src/wallet/wallet.h (1 hunks)
  • test/functional/rpc_fundrawtransaction.py (3 hunks)
  • test/functional/rpc_psbt.py (3 hunks)
  • test/functional/wallet_send.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/wallet/wallet.h
  • src/wallet/coincontrol.h
  • test/functional/rpc_psbt.py
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{cpp,h,hpp,cc}

📄 CodeRabbit inference engine (CLAUDE.md)

Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1

Files:

  • src/wallet/test/spend_tests.cpp
  • src/wallet/wallet.cpp
  • src/wallet/rpc/spend.cpp
  • src/wallet/spend.cpp
src/{test,wallet/test}/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework

Files:

  • src/wallet/test/spend_tests.cpp
src/wallet/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Wallet implementation must use Berkeley DB and SQLite

Files:

  • src/wallet/test/spend_tests.cpp
  • src/wallet/wallet.cpp
  • src/wallet/rpc/spend.cpp
  • src/wallet/spend.cpp
test/functional/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Functional tests in test/functional/ must be written in Python (minimum version specified in .python-version) and depend on dashd and dash-node

Files:

  • test/functional/rpc_fundrawtransaction.py
  • test/functional/wallet_send.py
🧠 Learnings (15)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay

Applied to files:

  • src/wallet/test/spend_tests.cpp
  • src/wallet/wallet.cpp
  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • test/functional/rpc_fundrawtransaction.py
  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-25T07:08:51.918Z
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-11T17:16:36.654Z
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-13T12:37:12.357Z
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-04T18:24:27.241Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-02-06T14:34:30.466Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-01T07:46:37.840Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-19T14:57:31.801Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-01-14T08:37:16.955Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6530
File: src/validation.cpp:360-362
Timestamp: 2025-01-14T08:37:16.955Z
Learning: The UpdateTransactionsFromBlock() method in txmempool.cpp takes parameters in the order: vHashUpdate, ancestor_size_limit, ancestor_count_limit. The size limit comes before the count limit.

Applied to files:

  • src/wallet/rpc/spend.cpp
🧬 Code graph analysis (6)
src/wallet/test/spend_tests.cpp (1)
src/wallet/wallet.cpp (2)
  • FillInputToWeight (1661-1694)
  • FillInputToWeight (1661-1661)
test/functional/rpc_fundrawtransaction.py (1)
test/functional/test_framework/util.py (4)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_greater_than (77-79)
  • assert_fee_amount (44-52)
src/wallet/wallet.cpp (1)
src/serialize.h (1)
  • GetSizeOfCompactSize (245-251)
test/functional/wallet_send.py (2)
test/functional/test_framework/util.py (3)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (5)
  • send (801-998)
  • send (801-801)
  • walletprocesspsbt (1000-1077)
  • walletprocesspsbt (1000-1000)
  • tx (985-985)
src/wallet/rpc/spend.cpp (3)
src/rpc/util.cpp (2)
  • ParseHashO (106-109)
  • ParseHashO (106-106)
src/rpc/request.cpp (3)
  • JSONRPCError (56-62)
  • JSONRPCError (56-56)
  • request (31-31)
src/rpc/rawtransaction_util.cpp (2)
  • ConstructTransaction (24-132)
  • ConstructTransaction (24-24)
src/wallet/spend.cpp (1)
src/policy/policy.h (1)
  • GetVirtualTransactionSize (118-121)
🪛 Cppcheck (2.18.0)
src/wallet/test/spend_tests.cpp

[information] 80-80: Include file

(missingIncludeSystem)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

src/wallet/wallet.cpp

[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

src/wallet/rpc/spend.cpp

[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

src/wallet/spend.cpp

[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

🪛 Ruff (0.14.8)
test/functional/rpc_fundrawtransaction.py

1027-1027: Decimal() called with float literal argument

Replace with string literal

(RUF032)

test/functional/wallet_send.py

542-542: Decimal() called with float literal argument

Replace with string literal

(RUF032)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: Lint / Run linters
🔇 Additional comments (7)
src/wallet/spend.cpp (1)

553-556: Confirm GetInputWeight units match GetVirtualTransactionSize expectations

The override to set input_bytes from coin_control.GetInputWeight(outpoint) via GetVirtualTransactionSize(..., 0, 0) is structurally correct and matches the intent that an explicit hint should trump the dummy estimate.

Given GetInputWeight is also passed directly into FillInputToWeight elsewhere, please double‑check that its unit (bytes vs. BIP141 weight units) is consistent with both FillInputToWeight and GetVirtualTransactionSize so fee estimation can’t be skewed for preset inputs. No change requested if this already matches upstream semantics and tests.

src/wallet/test/spend_tests.cpp (1)

61-106: FillInputToWeight tests precisely cover compactsize boundary behavior

The TestFillInputToWeight helper and FillInputToWeightTest exercise the negative/edge cases and the 1‑byte and 3‑byte compactsize boundaries thoroughly. The expected scriptSig sizes line up with the current FillInputToWeight implementation and its ±2‑byte allowance, so this gives good protection against regressions.

src/wallet/wallet.cpp (2)

1661-1694: FillInputToWeight implementation aligns with tests and boundary assumptions

The helper correctly enforces target_weight >= current_size, adjusts for compactsize length changes, and guarantees the final serialized size is in [target_weight - 2, target_weight]. This matches the new unit test expectations and keeps behavior predictable around 1‑byte/3‑byte compactsize transitions. The assert(txin.scriptSig.empty()) precondition is appropriate given current usage in dummy‑sign flows.


1704-1711: Per-input weight integration in DummySignTx looks correct; verify unit consistency

Short‑circuiting DummySignTx to call FillInputToWeight when coin_control has an input weight for txin.prevout is logically sound: it uses the explicit hint instead of constructing a dummy signature and skips signing for that input, which is fine for size estimation.

As with the spend-side override, it’s worth confirming that the GetInputWeight value passed here is in the same units that FillInputToWeight and any fee/vsize calculations expect, so that hinting a size for an input cannot systematically under‑ or over‑estimate fees.

src/wallet/rpc/spend.cpp (2)

5-5: Include of consensus/validation.h is appropriate for MAX_STANDARD_TX_SIZE.

The new include cleanly provides MAX_STANDARD_TX_SIZE used in the input_sizes validation block; no issues with dependency direction here.


396-427: input_sizes validation and coin-control plumbing look correct and match tests.

  • Adding "input_sizes" to RPCTypeCheckObj ensures the new option is recognized and type-checked as an array, preserving strict-key behavior.
  • The parsing loop correctly:
    • Enforces txid via ParseHashO.
    • Requires numeric, non-negative vout with clear error messages that match the new functional tests.
    • Requires numeric size, enforces a lower bound of GetSerializeSize(CTxIn()) == 41 and an upper bound of MAX_STANDARD_TX_SIZE, again with messages the tests expect.
    • Stores the hint via coinControl.SetInputWeight(COutPoint(txid, vout), size) so the wallet’s funding logic can consume it.

This aligns with the PR’s goal of letting callers override estimated input sizes for funding and fee calculation, without impacting legacy callers.

Also applies to: 531-560

test/functional/rpc_fundrawtransaction.py (1)

971-985: New input_sizes error-path coverage aligns with the C++ validation logic.

The added cases (missing vout, negative vout, missing size, too-small or negative size, and overly large size) all:

  • Use the new input_sizes option in the same shape the RPC expects.
  • Assert RPC_INVALID_PARAMETER (-8) with substrings that match the C++ error messages in FundTransaction.

This gives good coverage of the new validation without changing existing behavior for the solving-data error cases.

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

🧹 Nitpick comments (1)
test/functional/wallet_send.py (1)

506-543: Minor test polish: avoid float to Decimal, optionally guard input index

Two small suggestions here:

  • At Line 542, prefer a string literal for Decimal to avoid any floating‑point representation surprises and satisfy Ruff:
-        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal(0.0001))
+        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal("0.0001"))
  • (Optional) If you want extra robustness, consider asserting that the external UTXO was actually found before using input_idx, e.g. initialize it to None and assert input_idx is not None after the loop.

The overall per‑input size test logic and fee validation look solid.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e34d649da4d90df537fc020758253114e8c872d0 and 43d173a622f0b68a4b74df51453679f61d10dfd2.

📒 Files selected for processing (9)
  • src/wallet/coincontrol.h (2 hunks)
  • src/wallet/rpc/spend.cpp (9 hunks)
  • src/wallet/spend.cpp (1 hunks)
  • src/wallet/test/spend_tests.cpp (1 hunks)
  • src/wallet/wallet.cpp (2 hunks)
  • src/wallet/wallet.h (1 hunks)
  • test/functional/rpc_fundrawtransaction.py (3 hunks)
  • test/functional/rpc_psbt.py (3 hunks)
  • test/functional/wallet_send.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/wallet/wallet.h
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{cpp,h,hpp,cc}

📄 CodeRabbit inference engine (CLAUDE.md)

Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1

Files:

  • src/wallet/test/spend_tests.cpp
  • src/wallet/coincontrol.h
  • src/wallet/rpc/spend.cpp
  • src/wallet/spend.cpp
  • src/wallet/wallet.cpp
src/{test,wallet/test}/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework

Files:

  • src/wallet/test/spend_tests.cpp
src/wallet/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Wallet implementation must use Berkeley DB and SQLite

Files:

  • src/wallet/test/spend_tests.cpp
  • src/wallet/coincontrol.h
  • src/wallet/rpc/spend.cpp
  • src/wallet/spend.cpp
  • src/wallet/wallet.cpp
test/functional/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Functional tests in test/functional/ must be written in Python (minimum version specified in .python-version) and depend on dashd and dash-node

Files:

  • test/functional/wallet_send.py
  • test/functional/rpc_fundrawtransaction.py
  • test/functional/rpc_psbt.py
🧠 Learnings (17)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{test,wallet/test}/**/*.{cpp,h} : Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework

Applied to files:

  • src/wallet/test/spend_tests.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs

Applied to files:

  • src/wallet/coincontrol.h
  • src/wallet/spend.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • test/functional/rpc_fundrawtransaction.py
  • src/wallet/rpc/spend.cpp
  • test/functional/rpc_psbt.py
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/wallet/rpc/spend.cpp
  • test/functional/rpc_psbt.py
📚 Learning: 2025-10-25T07:08:51.918Z
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-11T17:16:36.654Z
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-13T12:37:12.357Z
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-04T18:24:27.241Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-02-06T14:34:30.466Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-01T07:46:37.840Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-19T14:57:31.801Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-06-06T11:53:09.094Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6665
File: src/evo/providertx.h:82-82
Timestamp: 2025-06-06T11:53:09.094Z
Learning: In ProTx serialization code (SERIALIZE_METHODS), version checks should use hardcoded maximum flags (/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true) rather than deployment-based flags. This is because serialization code should be able to deserialize any structurally valid ProTx up to the maximum version the code knows how to handle, regardless of current consensus validity. Validation code, not serialization code, is responsible for checking whether a ProTx version is consensus-valid based on deployment status.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-01-14T08:37:16.955Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6530
File: src/validation.cpp:360-362
Timestamp: 2025-01-14T08:37:16.955Z
Learning: The UpdateTransactionsFromBlock() method in txmempool.cpp takes parameters in the order: vHashUpdate, ancestor_size_limit, ancestor_count_limit. The size limit comes before the count limit.

Applied to files:

  • src/wallet/rpc/spend.cpp
🧬 Code graph analysis (8)
src/wallet/test/spend_tests.cpp (1)
src/wallet/wallet.cpp (2)
  • FillInputToWeight (1661-1694)
  • FillInputToWeight (1661-1661)
test/functional/wallet_send.py (2)
test/functional/test_framework/util.py (3)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (5)
  • send (800-996)
  • send (800-800)
  • walletprocesspsbt (998-1075)
  • walletprocesspsbt (998-998)
  • tx (983-983)
src/wallet/coincontrol.h (4)
src/wallet/spend.cpp (1)
  • outpoint (150-150)
src/wallet/wallet.cpp (1)
  • outpoint (1093-1093)
src/wallet/interfaces.cpp (4)
  • outpoint (399-399)
  • outpoint (399-399)
  • outpoint (400-400)
  • outpoint (400-400)
src/wallet/coinjoin.cpp (2)
  • outpoint (510-510)
  • outpoint (560-560)
test/functional/rpc_fundrawtransaction.py (2)
test/functional/test_framework/util.py (4)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_greater_than (77-79)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (4)
  • fundrawtransaction (603-707)
  • fundrawtransaction (603-603)
  • signrawtransactionwithwallet (709-798)
  • signrawtransactionwithwallet (709-709)
src/wallet/rpc/spend.cpp (2)
src/rpc/util.cpp (2)
  • ParseHashO (106-109)
  • ParseHashO (106-106)
src/rpc/rawtransaction_util.cpp (2)
  • ConstructTransaction (24-132)
  • ConstructTransaction (24-24)
test/functional/rpc_psbt.py (2)
test/functional/test_framework/util.py (3)
  • assert_greater_than (77-79)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
test/functional/test_framework/test_node.py (1)
  • get_wallet_rpc (363-369)
src/wallet/spend.cpp (1)
src/policy/policy.h (1)
  • GetVirtualTransactionSize (118-121)
src/wallet/wallet.cpp (1)
src/serialize.h (1)
  • GetSizeOfCompactSize (245-251)
🪛 Cppcheck (2.18.0)
src/wallet/test/spend_tests.cpp

[information] 80-80: Include file

(missingIncludeSystem)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

src/wallet/rpc/spend.cpp

[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

src/wallet/spend.cpp

[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

src/wallet/wallet.cpp

[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)


[information] Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information.

(toomanyconfigs)

🪛 Ruff (0.14.8)
test/functional/wallet_send.py

542-542: Decimal() called with float literal argument

Replace with string literal

(RUF032)

test/functional/rpc_fundrawtransaction.py

1027-1027: Decimal() called with float literal argument

Replace with string literal

(RUF032)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: Lint / Run linters
🔇 Additional comments (22)
src/wallet/rpc/spend.cpp (8)

5-5: LGTM - include added for MAX_STANDARD_TX_SIZE.

The new include is required for the MAX_STANDARD_TX_SIZE constant used in the input_sizes validation at line 554.


531-560: Input sizes parsing is well-structured with proper validation.

The parsing logic correctly validates:

  • Required txid field via ParseHashO (throws on missing/invalid)
  • Required vout field with non-negative check
  • Required size field with bounds check [41, MAX_STANDARD_TX_SIZE]

The CHECK_NONFATAL assertion at line 550 serves as a runtime sanity check that the minimum serialized input size matches the expected 41 bytes (outpoint + sequence + empty scriptSig).


586-601: SetOptionsInputWeights correctly transfers per-input sizes from inputs to options.

The function properly:

  1. Prevents duplicate specification by checking if input_sizes already exists in options
  2. Returns early if no inputs are provided
  3. Collects only inputs that specify a size field
  4. Adds the collected data as input_sizes to options for downstream processing

This design keeps size hints specified alongside each input rather than requiring a separate options field in send and walletcreatefundedpsbt.


643-656: RPC documentation structure is correct.

The input_sizes array now properly documents its elements with an intermediate OBJ wrapper, matching the expected JSON format [{"txid": ..., "vout": ..., "size": ...}, ...]. This addresses the previously identified structural issue.


845-848: LGTM - size field added to send RPC inputs.

The documentation clearly describes the size parameter as the maximum serialized size in bytes, with appropriate guidance about DER signature sizing.


948-949: LGTM - proper integration with SetOptionsInputWeights.

The call correctly processes options["inputs"] before FundTransaction, ensuring per-input sizes are transferred to the options object for downstream processing.


1092-1095: LGTM - size field added to walletcreatefundedpsbt inputs.

Consistent with the send RPC, the size parameter documentation is appropriate.


1175-1185: LGTM - proper options initialization and input weights handling.

The options object is correctly initialized from params (or as empty VOBJ if null), and SetOptionsInputWeights is called before FundTransaction to transfer per-input sizes from the inputs array to the options.

test/functional/rpc_fundrawtransaction.py (4)

972-973: LGTM - test now uses partial spend for external input.

Using ext_utxo["amount"] / 2 allows the test to verify that funding works with an external input that doesn't cover the full output, triggering the "Insufficient funds" path correctly.


980-986: Comprehensive input_sizes validation error tests.

Good coverage of error conditions:

  • Missing vout key
  • Negative vout value
  • Missing size key
  • Size below minimum (40 < 41)
  • Negative size (also < 41)
  • Size exceeding MAX_STANDARD_TX_SIZE

1000-1006: Input weight calculation is appropriate for Dash.

Unlike the segwit weight formula in Bitcoin Core, this calculates input size from the difference between signed and unsigned transaction sizes plus the fixed 41-byte overhead (prevout + sequence + empty scriptSig). This correctly derives the actual serialized input size for Dash.


1029-1031: LGTM - boundary tests for CompactSize encoding.

Testing at size 255 and 65539 exercises the boundaries where CompactSize encoding changes from 1-byte to 3-byte and 3-byte to 5-byte representations, ensuring the weight calculations handle these correctly.

test/functional/rpc_psbt.py (6)

17-17: LGTM - import added for fee comparison assertions.

The assert_greater_than utility is used for comparing fees between different input weight configurations.


467-474: LGTM - test setup for PSBT external input funding.

Creates a dedicated "extfund" wallet on node 1 for testing PSBT funding with external inputs.


523-531: LGTM - error condition test for input_sizes in options.

Verifies that specifying input_sizes in options (rather than per-input size field) correctly triggers the expected error message, ensuring users provide size hints in the proper location.


533-563: Comprehensive weight-based funding tests.

Good test coverage for:

  • Funding with exact input weight
  • Mempool acceptance validation
  • Fee comparison with lower/higher weights
  • Weight override when solving_data is also provided

The relative comparisons (lower weight → lower fee, higher weight → higher fee) correctly validate the weight-to-fee relationship regardless of absolute weight values.


565-577: LGTM - wallet input weight override test.

After importing the descriptor into the wallet, tests verify that explicitly provided weights override the wallet's calculated weights, ensuring consistent behavior for both external and wallet-owned inputs.


515-521: The weight calculation formula in this code is correct for Dash's non-SegWit implementation. For non-SegWit transactions, weight is properly defined as 4× the serialized transaction size in bytes; the formula input_weight = ((41 + len_scriptsig + 2) * 4) + len_scriptwitness correctly yields this since len_scriptwitness is always 0 in Dash. The weight unit is not intended to equal byte size—it is a standard metric where non-SegWit weight = 4× bytes. No adjustment is needed for Dash-specific handling.

Likely an incorrect or invalid review comment.

src/wallet/spend.cpp (1)

553-556: Per‑input size override in SelectCoins looks correct

Using HasInputWeight/GetInputWeight to override input_bytes via GetVirtualTransactionSize(...) for preset inputs cleanly matches the intended “caller-supplied size wins” behavior and is safely guarded.

src/wallet/wallet.cpp (1)

1661-1694: FillInputToWeight and DummySignTx integration are consistent and well‑bounded

FillInputToWeight’s use of GetSizeOfCompactSize and the [target_weight-2, target_weight] postcondition matches the new unit tests, and the DummySignTx path that calls it when HasInputWeight is set cleanly bypasses normal dummy signing without violating the empty‑scriptSig precondition. No correctness or safety issues spotted.

Also applies to: 1704-1711

src/wallet/test/spend_tests.cpp (1)

61-106: FillInputToWeight tests give good edge‑case coverage

The new helper and FillInputToWeightTest exercise negative/low targets and CompactSize boundaries, matching the implementation’s guarantees and catching regressions in serialization behavior.

src/wallet/coincontrol.h (1)

132-148: Per‑input weight tracking in CCoinControl is straightforward and safe

The new m_input_weights map plus SetInputWeight / HasInputWeight / GetInputWeight accessors are minimal and correctly encapsulated; existing uses check HasInputWeight before calling GetInputWeight, so the internal assert is safe.

Also applies to: 162-163

funded_tx4 = wallet.fundrawtransaction(raw_tx, {"input_sizes": [{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "size": high_input_weight}], "fee_rate": 10})
input_add_weight = high_input_weight - 41
tx4_size = wallet.decoderawtransaction(funded_tx4["hex"])["size"] + input_add_weight
assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal(0.0001))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use string literal with Decimal to avoid float precision issues.

The static analysis correctly identifies that Decimal(0.0001) uses a float literal which can introduce precision errors. Use a string literal instead.

-        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal(0.0001))
+        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal("0.0001"))
📝 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
assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal(0.0001))
assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal("0.0001"))
🧰 Tools
🪛 Ruff (0.14.8)

1027-1027: Decimal() called with float literal argument

Replace with string literal

(RUF032)

🤖 Prompt for AI Agents
In test/functional/rpc_fundrawtransaction.py around line 1027, the code
constructs a Decimal using a float literal (Decimal(0.0001)), which can
introduce precision errors; change it to use a string literal instead
(Decimal("0.0001")) so the Decimal is created exactly.

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: 0

♻️ Duplicate comments (1)
test/functional/rpc_fundrawtransaction.py (1)

971-986: External-input size tests match C++ semantics; use string literal for Decimal

The new external-input tests:

  • Correctly exercise input_sizes validation (missing/negative vout, missing/too-small/too-large size) against the FundTransaction error messages.
  • Verify that providing an explicit per-input size affects fees monotonically and that the specified size overrides solving-data-based estimates, including at compactsize boundaries.

Minor (already flagged previously): Decimal(0.0001) at line 1027 should use a string literal to avoid float-rounding issues:

-        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal(0.0001))
+        assert_fee_amount(funded_tx4["fee"], tx4_size, Decimal("0.0001"))

Also applies to: 994-1032

🧹 Nitpick comments (1)
test/functional/wallet_send.py (1)

506-543: External-input size wiring looks correct; adjust Decimal literal for precision

The PSBT decoding, external-input index lookup, and use of the size field in inputs are consistent with the new SetOptionsInputWeights/input_sizes behavior, including the explicit rejection of input_sizes inside options.

Minor: Decimal(0.0001) constructs from a float and can introduce tiny precision issues. Prefer a string literal here:

-        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal(0.0001))
+        assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal("0.0001"))
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 43d173a622f0b68a4b74df51453679f61d10dfd2 and 070e10f.

📒 Files selected for processing (9)
  • src/wallet/coincontrol.h (2 hunks)
  • src/wallet/rpc/spend.cpp (9 hunks)
  • src/wallet/spend.cpp (1 hunks)
  • src/wallet/test/spend_tests.cpp (1 hunks)
  • src/wallet/wallet.cpp (2 hunks)
  • src/wallet/wallet.h (1 hunks)
  • test/functional/rpc_fundrawtransaction.py (3 hunks)
  • test/functional/rpc_psbt.py (3 hunks)
  • test/functional/wallet_send.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/wallet/spend.cpp
  • src/wallet/wallet.cpp
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{cpp,h,hpp,cc}

📄 CodeRabbit inference engine (CLAUDE.md)

Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1

Files:

  • src/wallet/wallet.h
  • src/wallet/test/spend_tests.cpp
  • src/wallet/coincontrol.h
  • src/wallet/rpc/spend.cpp
src/wallet/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Wallet implementation must use Berkeley DB and SQLite

Files:

  • src/wallet/wallet.h
  • src/wallet/test/spend_tests.cpp
  • src/wallet/coincontrol.h
  • src/wallet/rpc/spend.cpp
src/{test,wallet/test}/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework

Files:

  • src/wallet/test/spend_tests.cpp
test/functional/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Functional tests in test/functional/ must be written in Python (minimum version specified in .python-version) and depend on dashd and dash-node

Files:

  • test/functional/rpc_psbt.py
  • test/functional/rpc_fundrawtransaction.py
  • test/functional/wallet_send.py
🧠 Learnings (16)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs

Applied to files:

  • src/wallet/coincontrol.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/wallet/rpc/spend.cpp
  • test/functional/rpc_psbt.py
📚 Learning: 2025-10-25T07:08:51.918Z
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-11T17:16:36.654Z
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-10-13T12:37:12.357Z
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-04T18:24:27.241Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-02-06T14:34:30.466Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • src/wallet/rpc/spend.cpp
  • test/functional/rpc_psbt.py
  • test/functional/rpc_fundrawtransaction.py
📚 Learning: 2025-08-01T07:46:37.840Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-08-19T14:57:31.801Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-06-06T11:53:09.094Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6665
File: src/evo/providertx.h:82-82
Timestamp: 2025-06-06T11:53:09.094Z
Learning: In ProTx serialization code (SERIALIZE_METHODS), version checks should use hardcoded maximum flags (/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true) rather than deployment-based flags. This is because serialization code should be able to deserialize any structurally valid ProTx up to the maximum version the code knows how to handle, regardless of current consensus validity. Validation code, not serialization code, is responsible for checking whether a ProTx version is consensus-valid based on deployment status.

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing

Applied to files:

  • src/wallet/rpc/spend.cpp
📚 Learning: 2025-01-14T08:37:16.955Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6530
File: src/validation.cpp:360-362
Timestamp: 2025-01-14T08:37:16.955Z
Learning: The UpdateTransactionsFromBlock() method in txmempool.cpp takes parameters in the order: vHashUpdate, ancestor_size_limit, ancestor_count_limit. The size limit comes before the count limit.

Applied to files:

  • src/wallet/rpc/spend.cpp
🧬 Code graph analysis (6)
src/wallet/wallet.h (1)
src/wallet/wallet.cpp (2)
  • FillInputToWeight (1661-1692)
  • FillInputToWeight (1661-1661)
src/wallet/test/spend_tests.cpp (1)
src/wallet/wallet.cpp (2)
  • FillInputToWeight (1661-1692)
  • FillInputToWeight (1661-1661)
src/wallet/rpc/spend.cpp (1)
src/rpc/util.cpp (2)
  • ParseHashO (106-109)
  • ParseHashO (106-106)
test/functional/rpc_psbt.py (3)
test/functional/test_framework/util.py (2)
  • assert_greater_than (77-79)
  • assert_raises_rpc_error (132-148)
test/functional/test_framework/test_node.py (1)
  • get_wallet_rpc (363-369)
src/wallet/rpc/spend.cpp (4)
  • sendtoaddress (119-221)
  • sendtoaddress (119-119)
  • walletcreatefundedpsbt (1077-1209)
  • walletcreatefundedpsbt (1077-1077)
test/functional/rpc_fundrawtransaction.py (2)
test/functional/test_framework/util.py (4)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_greater_than (77-79)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (2)
  • fundrawtransaction (603-707)
  • fundrawtransaction (603-603)
test/functional/wallet_send.py (2)
test/functional/test_framework/util.py (3)
  • assert_raises_rpc_error (132-148)
  • assert_equal (69-74)
  • assert_fee_amount (44-52)
src/wallet/rpc/spend.cpp (3)
  • send (800-996)
  • send (800-800)
  • tx (983-983)
🪛 Ruff (0.14.8)
test/functional/rpc_fundrawtransaction.py

1027-1027: Decimal() called with float literal argument

Replace with string literal

(RUF032)

test/functional/wallet_send.py

542-542: Decimal() called with float literal argument

Replace with string literal

(RUF032)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: linux64_multiprocess-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
🔇 Additional comments (5)
src/wallet/wallet.h (1)

1132-1135: New FillInputToWeight declaration is consistent and well-placed

The declaration matches the implementation in wallet.cpp and is correctly exposed in the wallet namespace next to DummySignInput. No issues here.

src/wallet/test/spend_tests.cpp (1)

61-106: FillInputToWeight tests thoroughly cover edge cases

The new helper and test case correctly mirror FillInputToWeight’s behavior, including failure on too-small targets and boundary behavior for compactsize encodings. This gives good coverage without overcomplicating the test.

src/wallet/coincontrol.h (1)

132-148: Per-input weight tracking in CCoinControl is straightforward and sound

The new SetInputWeight/HasInputWeight/GetInputWeight methods and the backing m_input_weights map provide a clear, minimal API for per-input sizes. The assert in GetInputWeight is appropriate as a precondition check given callers are expected to guard with HasInputWeight().

Also applies to: 163-164

src/wallet/rpc/spend.cpp (1)

425-427: input_sizes plumbing and validation are coherent and match the new tests

The new input_sizes handling in FundTransaction, the SetOptionsInputWeights helper, and the RPC argument/docs updates (fundrawtransaction options, send inputs[].size, and walletcreatefundedpsbt inputs[].size) are internally consistent:

  • Options type-checking includes input_sizes as an array.
  • FundTransaction validates txid/vout presence, enforces size ∈ [GetSerializeSize(CTxIn()), MAX_STANDARD_TX_SIZE], and wires values into CCoinControl::SetInputWeight.
  • SetOptionsInputWeights correctly enforces that sizes come via inputs[*].size rather than an input_sizes option, which aligns with the functional tests.
  • send() and walletcreatefundedpsbt() both normalize their options, derive input_sizes from inputs, and then delegate to FundTransaction, so the behavior is uniform across RPCs.

Given the corresponding functional and unit tests, this looks like a faithful backport with correct Dash-specific renaming.

Also applies to: 531-560, 586-601, 643-656, 845-848, 940-949, 997-1207

test/functional/rpc_psbt.py (1)

17-20: PSBT external-input size tests correctly exercise the new API

The added PSBT tests:

  • Use external UTXOs and walletcreatefundedpsbt to validate that input_sizes must come via inputs[*].size, not via the options object.
  • Confirm that providing a per-input size affects the computed fee monotonically (smaller size → lower fee, larger size → higher fee) and that explicit sizes override solving-data-based estimates for both external and wallet-owned inputs.

The new assert_greater_than import is used appropriately, and the scenarios line up with the C++ SetOptionsInputWeights and FundTransaction behavior.

Also applies to: 467-578

laanwj and others added 2 commits December 17, 2025 08:47
…n funding a transaction

3866272 tests: Test specifying input weights (Andrew Chow)
6fa762a rpc, wallet: Allow users to specify input weights (Andrew Chow)
808068e wallet: Allow user specified input size to override (Andrew Chow)
4060c50 wallet: add input weights to CCoinControl (Andrew Chow)

Pull request description:

  When funding a transaction with external inputs, instead of providing solving data, a user may want to just provide the maximum signed size of that input. This is particularly useful in cases where the input is nonstandard as our dummy signer is unable to handle those inputs.

  The input weight can be provided to any input regardless of whether it belongs to the wallet and the provided weight will always be used regardless of any calculated input weight. This allows the user to override the calculated input weight which may overestimate in some circumstances due to missing information (e.g. if the private key is not known, a maximum size signature will be used, but the actual signer may be doing additional work which reduces the size of the signature).

  For `send` and `walletcreatefundedpsbt`, the input weight is specified in a `weight` field in an input object. For `fundrawtransaction`,  a new `input_weights` field is added to the `options` object. This is an array of objects consisting of a txid, vout, and weight.

  Closes bitcoin#23187

ACKs for top commit:
  instagibbs:
    reACK bitcoin@3866272
  glozow:
    reACK 3866272 via range-diff
  t-bast:
    ACK bitcoin@3866272

Tree-SHA512: 2c8b471ee537c62a51389b7c4e86b5ac1c3a223b444195042be8117b3c83e29c0619463610b950cbbd1648d3ed01ecc5bb0b3c4f39640680da9157763b9b9f9f
…shes over silent ignore

fa277cd univalue: Throw exception on invalid pushes over silent ignore (MacroFake)
ccccc17 refactor: Default options in walletcreatefundedpsbt to VOBJ instead of VNULL (MacroFake)

Pull request description:

  The return value of the `push*` helpers is never used, but important to determine if the operation was successful. One way to fix this would be to add the "nodiscard" attribute. However, this would make the code (and this diff) overly verbose for no reason.

  So fix it by removing the never used return value. Also, fail verbosely in case of a programming mistake.

ACKs for top commit:
  furszy:
    code ACK fa277cd

Tree-SHA512: ef212a5bf5ae6bbad20acc4dafa3715521e81544185988d1eab724f440e4864a27e686aff51d5bc51b3017892c2eb8e577bcb8f37e8ddbaa0d8833bb622f2f9c
Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

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

utACK 070e10f

@PastaPastaPasta PastaPastaPasta merged commit d4ae23e into dashpay:develop Dec 19, 2025
70 of 73 checks passed
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.

5 participants