backport: Merge bitcoin/bitcoin#26733 - #7119
cryptotura wants to merge 1 commit into
Conversation
…tractfeefrom` parameter 057057a Add test for `sendmany` rpc that uses `subtractfeefrom` parameter (Yusuf Sahin HAMZA) Pull request description: This PR adds test that uses `sendmany` rpc to send **BTC** to multiple addresses using `subtractfeefrom` parameter, then checks receiver addresses balances to make sure fees are subtracted correctly. ACKs for top commit: achow101: ACK 057057a Tree-SHA512: 51167120d489f0ff7b8b9855424d07cb55a8965984f904643cddf45e7a08c350eaded498c350ec9c660edf72c2f128ec142347c9c79d5043d9f6cd481b15cd7e
✅ No Merge Conflicts DetectedThis PR currently has no conflicts with other open PRs. |
WalkthroughThe changes add two new test scenarios to the wallet functionality tests. The first scenario tests the sendmany operation with an explicit fee_rate parameter, where transaction fees are subtracted from multiple recipients. It creates addresses, sends DASH to them with fee subtraction enabled, advances the network, and verifies the received amounts reflect the fee deductions. The second scenario introduces a parallel test path that exercises explicit fee_rate specification alongside existing fee-rate tests, validating outcomes for sendtoaddress and sendmany operations. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
|
🕓 Review not started yet because this PR is a draft.
Commit 5e32a3e. Normal review starts when eligible; priority review starts as soon as a slot is available. |
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Clean backport of bitcoin#26733 — adds a test for sendmany RPC with subtractfeefrom parameter. The test sends 5 DASH to two addresses with fee subtracted from both, then verifies balances. No behavioral changes, test-only addition. The adaptation from BTC to DASH naming (sat/vB → duff/B in the log message that follows) is consistent with existing conventions.
Reviewed commit: 5e32a3e
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Small test backport of bitcoin#26733. One blocking issue: the exact-equality fee-split assertion does not match Dash wallet behavior (first SFFO recipient absorbs the remainder when fee is not evenly divisible). A follow-up adaptation commit already exists on a parallel branch (9b8ed10) confirming this failure mode. One merge-resolution nitpick: the cherry-pick produced two near-duplicate log headers around the new SFFO block.
Reviewed commit: 5e32a3e
🔴 1 blocking | 💬 1 nitpick(s)
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/functional/wallet_basic.py`:
- [BLOCKING] lines 290-292: Exact-equality SFFO assertion does not match Dash fee-splitting (test will fail spuriously on odd fees)
These assertions require both recipients to receive exactly `5 + tx['fee'] / 2`, but `src/wallet/spend.cpp:1024-1029` divides the fee with integer arithmetic and makes the *first* SFFO recipient pay the remainder (`to_reduce % outputs_to_subtract_fee_from`). With two outputs and an odd `to_reduce`, the two recipients differ by one duff and at least one of these `assert_equal`s will fail for a perfectly valid transaction. This is not theoretical: a Dash-side follow-up commit (`9b8ed10e40` "fix: adapt sendmany subtractfeefrom test for Dash fee precision") already exists on a parallel branch reworking exactly these three lines into a sum-and-tolerance check, confirming the upstream assertion was observed to fail in Dash CI. The same idiom is used in `rpc_fundrawtransaction.py`, which already encodes the tolerance invariant. The backport should fold that adaptation in here rather than landing the upstream form unchanged.
| expected_bal = Decimal('5') + (tx['fee'] / 2) | ||
| assert_equal(self.nodes[0].getreceivedbyaddress(a0), expected_bal) | ||
| assert_equal(self.nodes[0].getreceivedbyaddress(a1), expected_bal) |
There was a problem hiding this comment.
🔴 Blocking: Exact-equality SFFO assertion does not match Dash fee-splitting (test will fail spuriously on odd fees)
These assertions require both recipients to receive exactly 5 + tx['fee'] / 2, but src/wallet/spend.cpp:1024-1029 divides the fee with integer arithmetic and makes the first SFFO recipient pay the remainder (to_reduce % outputs_to_subtract_fee_from). With two outputs and an odd to_reduce, the two recipients differ by one duff and at least one of these assert_equals will fail for a perfectly valid transaction. This is not theoretical: a Dash-side follow-up commit (9b8ed10e40 "fix: adapt sendmany subtractfeefrom test for Dash fee precision") already exists on a parallel branch reworking exactly these three lines into a sum-and-tolerance check, confirming the upstream assertion was observed to fail in Dash CI. The same idiom is used in rpc_fundrawtransaction.py, which already encodes the tolerance invariant. The backport should fold that adaptation in here rather than landing the upstream form unchanged.
💡 Suggested change
| expected_bal = Decimal('5') + (tx['fee'] / 2) | |
| assert_equal(self.nodes[0].getreceivedbyaddress(a0), expected_bal) | |
| assert_equal(self.nodes[0].getreceivedbyaddress(a1), expected_bal) | |
| a0_received = self.nodes[0].getreceivedbyaddress(a0) | |
| a1_received = self.nodes[0].getreceivedbyaddress(a1) | |
| # Fee subtraction is rounded to whole duffs, so the split across equal | |
| # recipients can differ by one duff. | |
| assert_equal(a0_received + a1_received, Decimal('10') + tx['fee']) | |
| assert_greater_than(Decimal('5'), a0_received) | |
| assert_greater_than(Decimal('5'), a1_received) | |
| assert_greater_than(Decimal('0.00000002'), abs(a0_received - a1_received)) |
source: ['codex']
🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/functional/wallet_basic.py`:
- [BLOCKING] lines 290-292: Exact-equality SFFO assertion does not match Dash fee-splitting (test will fail spuriously on odd fees)
These assertions require both recipients to receive exactly `5 + tx['fee'] / 2`, but `src/wallet/spend.cpp:1024-1029` divides the fee with integer arithmetic and makes the *first* SFFO recipient pay the remainder (`to_reduce % outputs_to_subtract_fee_from`). With two outputs and an odd `to_reduce`, the two recipients differ by one duff and at least one of these `assert_equal`s will fail for a perfectly valid transaction. This is not theoretical: a Dash-side follow-up commit (`9b8ed10e40` "fix: adapt sendmany subtractfeefrom test for Dash fee precision") already exists on a parallel branch reworking exactly these three lines into a sum-and-tolerance check, confirming the upstream assertion was observed to fail in Dash CI. The same idiom is used in `rpc_fundrawtransaction.py`, which already encodes the tolerance invariant. The backport should fold that adaptation in here rather than landing the upstream form unchanged.
| assert_equal(self.nodes[0].getreceivedbyaddress(a0), expected_bal) | ||
| assert_equal(self.nodes[0].getreceivedbyaddress(a1), expected_bal) | ||
|
|
||
| self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") |
There was a problem hiding this comment.
💬 Nitpick: Duplicate/inconsistent log header introduced by the merge resolution
Upstream bitcoin#26733 inserted the new SFFO block immediately above its own existing log line "...explicit fee rate in sat/vB". Dash had previously renamed that line to duff/B at line 279. The merge resolution kept the renamed duff/B line at 279 and re-added the upstream sat/vB line at 294, leaving two near-duplicate headers bracketing the SFFO block. Two consequences: (a) line 294 uses upstream sat/vB terminology, inconsistent with every other fee-rate string in this file (lines 322, 327, 334, 509, 540, 545, 552 all say duff/B); (b) the pre-existing line-279 header now sits above the SFFO block instead of the fee_rate block it was written to describe, so it mislabels what runs next. Simplest fix: drop the re-added line 294 entirely so the existing duff/B line at 279 once again prefaces the fee_rate test block, and add a dedicated self.log.info("Test sendmany with subtractfeefrom") for the new block.
source: ['claude']
There was a problem hiding this comment.
| self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") | |
| + self.log.info("Test sendmany with fee_rate param (explicit fee rate in duff/B)") | |
| - self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") |
knst
left a comment
There was a problem hiding this comment.
comment has been de-dashified, need to revert this change
| assert_equal(self.nodes[0].getreceivedbyaddress(a0), expected_bal) | ||
| assert_equal(self.nodes[0].getreceivedbyaddress(a1), expected_bal) | ||
|
|
||
| self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") |
There was a problem hiding this comment.
| self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") | |
| + self.log.info("Test sendmany with fee_rate param (explicit fee rate in duff/B)") | |
| - self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") |
| node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('100'), fee_per_byte, count_bytes(self.nodes[2].gettransaction(txid)['hex'])) | ||
|
|
||
| self.log.info("Test sendmany with fee_rate param (explicit fee rate in duff/B)") | ||
| # Sendmany 5 DASH to two addresses with subtracting fee from both addresses |
There was a problem hiding this comment.
- self.log.info("Test sendmany with fee_rate param (explicit fee rate in duff/B)")|
Converted to draft: multiple comments with changes-requests + CI failures. |
backporting