Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spend: warn when overpaying fee #905

Merged

Conversation

jp1ac4
Copy link
Collaborator

@jp1ac4 jp1ac4 commented Jan 3, 2024

This is a first step towards #811. The GUI will be updated in a follow-up PR.

It adds a warning if there is any change/excess available that has been added to the fee, building on the assumption from bitcoindevkit/coin-select#14 that the decision whether to include change depends on whether the excess is over a threshold. The function select_coins_for_spend() now returns this threshold so that the caller can check if the possible change amount is above it.

I've used an enum for the different warnings, but could use strings directly.

If the approach looks fine, I'll add some tests.

Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

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

Approach ACK for the interface, i'm just unsure we need more than just the excess value and change amount.

src/spend.rs Outdated Show resolved Hide resolved
src/spend.rs Outdated Show resolved Hide resolved
src/spend.rs Outdated Show resolved Hide resolved
src/commands/mod.rs Outdated Show resolved Hide resolved
@jp1ac4 jp1ac4 force-pushed the return-excess-from-coin-selection branch from b38264d to 5ed64af Compare January 5, 2024 01:45
@jp1ac4 jp1ac4 changed the title [WIP] spend: warn when adding change/excess to fees spend: warn when overpaying fee Jan 5, 2024
@jp1ac4 jp1ac4 marked this pull request as ready for review January 5, 2024 01:55
doc/API.md Outdated Show resolved Hide resolved
Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

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

ACK. Good unit test. Got a couple comments mostly on documentation stuff. Needs rebase.

It's always good to have a sanity check of the interface as consumed externally from the functional tests:

diff --git a/tests/test_spend.py b/tests/test_spend.py
index 94ba1a5..446acf7 100644
--- a/tests/test_spend.py
+++ b/tests/test_spend.py
@@ -26,6 +26,9 @@ def test_spend_change(lianad, bitcoind):
     assert len(spend_psbt.o) == 3
     assert len(spend_psbt.tx.vout) == 3
 
+    # Since the transaction contains a change output there is no warning.
+    assert len(res["warnings"]) == 0
+
     # Sign and broadcast this first Spend transaction.
     signed_psbt = lianad.signer.sign_psbt(spend_psbt)
     lianad.rpc.updatespend(signed_psbt.to_base64())
@@ -46,6 +49,7 @@ def test_spend_change(lianad, bitcoind):
     }
     res = lianad.rpc.createspend(destinations, outpoints, 2)
     spend_psbt = PSBT.from_base64(res["psbt"])
+    assert len(res["warnings"]) == 0
 
     # We can sign and broadcast it.
     signed_psbt = lianad.signer.sign_psbt(spend_psbt)
@@ -110,6 +114,7 @@ def test_coin_marked_spent(lianad, bitcoind):
     res = lianad.rpc.createspend(destinations, [outpoint], 6)
     psbt = PSBT.from_base64(res["psbt"])
     sign_and_broadcast(psbt)
+    assert len(res["warnings"]) == 0
 
     # Spend the second coin without a change output
     outpoint = next(
@@ -123,6 +128,8 @@ def test_coin_marked_spent(lianad, bitcoind):
     res = lianad.rpc.createspend(destinations, [outpoint], 1)
     psbt = PSBT.from_base64(res["psbt"])
     sign_and_broadcast(psbt)
+    assert len(res["warnings"]) == 1
+    assert res["warnings"][0] == ""
 
     # Spend the third coin to an address of ours, no change
     outpoints = [
@@ -136,6 +143,8 @@ def test_coin_marked_spent(lianad, bitcoind):
     res = lianad.rpc.createspend(destinations, [outpoints[0]], 1)
     psbt = PSBT.from_base64(res["psbt"])
     sign_and_broadcast(psbt)
+    assert len(res["warnings"]) == 1
+    assert res["warnings"][0] == ""
 
     # Spend the fourth coin to an address of ours, with change
     destinations = {
@@ -144,6 +153,7 @@ def test_coin_marked_spent(lianad, bitcoind):
     res = lianad.rpc.createspend(destinations, [outpoints[1]], 18)
     psbt = PSBT.from_base64(res["psbt"])
     sign_and_broadcast(psbt)
+    assert len(res["warnings"]) == 0
 
     # Batch spend the fourth and fifth coins
     outpoint = next(
@@ -159,6 +169,7 @@ def test_coin_marked_spent(lianad, bitcoind):
     res = lianad.rpc.createspend(destinations, [outpoints[2], outpoint], 2)
     psbt = PSBT.from_base64(res["psbt"])
     sign_and_broadcast(psbt)
+    assert len(res["warnings"]) == 0
 
     # All the spent coins must have been detected as such
     all_deposits = (deposit_a, deposit_b, deposit_c, deposit_d)

I've left out the error string assertion as "" since the current string is going to change.

src/spend.rs Outdated Show resolved Hide resolved
src/spend.rs Outdated Show resolved Hide resolved
doc/API.md Outdated Show resolved Hide resolved
doc/API.md Outdated Show resolved Hide resolved
@jp1ac4 jp1ac4 force-pushed the return-excess-from-coin-selection branch from 5ed64af to 5a15c74 Compare January 11, 2024 20:16
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Jan 11, 2024

I've now made the suggested changes.

selector
.excess(target, drain_novalue)
.max(0) // negative excess would mean insufficient funds to pay for change output
Copy link
Member

@darosior darosior Jan 13, 2024

Choose a reason for hiding this comment

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

So this can only happen if we've got a selection without change such as adding a change output would decrease the feerate below the target? Any other reason for a negative excess here would be a logic error because at this point we do indeed have enough funds?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's right, the selected coins here have enough value without a change output and so the negative excess would mean that the selected coins don't have enough value to pay the extra weight for the change output at the target feerate.

Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

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

ACK 5a15c74

@darosior darosior merged commit 501dce4 into wizardsardine:master Jan 13, 2024
18 checks passed
@jp1ac4 jp1ac4 deleted the return-excess-from-coin-selection branch January 18, 2024 10:29
edouardparis added a commit that referenced this pull request Feb 27, 2024
85f5a68 gui(spend): display warnings for draft PSBTs (jp1ac4)

Pull request description:

  This is to complete #811.

  It displays any warnings generated by `createspend` on the draft PSBT view, which could currently be those from #905 and #873. Once the PSBT has been saved, these warnings will no longer be shown.

  Below are some screenshots.

  With a warning:
  ![image](https://github.com/wizardsardine/liana/assets/121959000/fb2167d9-4800-4849-8622-ff20ac55623e)

  ![image](https://github.com/wizardsardine/liana/assets/121959000/e1ab9ec2-00ae-457f-81e1-9b3a2863af31)

  Without a warning:
  ![image](https://github.com/wizardsardine/liana/assets/121959000/73b5b4bd-55b5-40ee-b587-4f57bfd57b4c)

  ![image](https://github.com/wizardsardine/liana/assets/121959000/e9b23d4e-bb13-4ae7-944e-258f9c9a0abd)

ACKs for top commit:
  edouardparis:
    ACK 85f5a68

Tree-SHA512: b9875801f7607f6f824ad9ab5182e93aa533ba2bbb8f9a4168c4a2a779a8f39cf77dc0b24eac7c99a0fce36c486c126144d23b0cb7ecec27ebc145ea2ffdb212
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.

2 participants