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

commands: require change for self-send #832

Merged
merged 2 commits into from
Nov 24, 2023

Conversation

jp1ac4
Copy link
Collaborator

@jp1ac4 jp1ac4 commented Nov 23, 2023

This adds a new LowestFeeChangeCondition metric for use in coin selection. It's the same as LowestFee with the option to only find solutions with change.

This option is then used for self-sends to ensure only a solution with change will be returned.

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.

How about making this error:

liana/src/commands/mod.rs

Lines 556 to 578 in ed35a79

// If necessary, add a change output.
if change_amount.to_sat() > 0 {
// Don't forget to update our next change index!
let next_index = change_index
.increment()
.expect("Must not get into hardened territory");
db_conn.set_change_index(next_index, &self.secp);
check_output_value(change_amount)?;
// TODO: shuffle once we have Taproot
change_txo.value = change_amount.to_sat();
tx.output.push(change_txo);
psbt_outs.push(PsbtOut {
bip32_derivation: change_desc.bip32_derivations(),
..PsbtOut::default()
});
} else if is_self_send {
return Err(CommandError::InsufficientFunds(
selected_coins.iter().map(|c| c.amount).sum(),
None,
feerate_vb,
));
}

A sanity check failure instead? It should never happen now: we would always fail the coin selection above before.

// Select more coins until target is met and change condition satisfied.
loop {
let drain = change_policy(&selector, target);
if selector.is_target_met(target, drain) && (drain.is_some() | !must_have_change) {
Copy link
Member

Choose a reason for hiding this comment

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

Did you mean to use a binary or here?

Suggested change
if selector.is_target_met(target, drain) && (drain.is_some() | !must_have_change) {
if selector.is_target_met(target, drain) && (drain.is_some() || !must_have_change) {

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oops, thanks for spotting. That should be a logical or. I'll change it.

@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 23, 2023

A sanity check failure instead? It should never happen now: we would always fail the coin selection above before.

Ah yes, that's true. I think in that case the sanity check would already catch it, as it checks for tx.output.is_empty(). So it should be enough just to remove the else if is_self_send { ... } check in the snippet above.

@jp1ac4 jp1ac4 force-pushed the lowest-fee-with-change-metric branch 2 times, most recently from 2444b13 to 7a188f2 Compare November 23, 2023 14:09
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 23, 2023

I've now made the suggested changes, and also made a small fix to the documentation.

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 7a188f2

Looks good to me, but since more concepts from create_spend are bleeding into select_coins_for_spend (the self-send) we should either document it or tweak its interface a bit.

@@ -569,12 +569,6 @@ impl DaemonControl {
bip32_derivation: change_desc.bip32_derivations(),
..PsbtOut::default()
});
} else if is_self_send {
Copy link
Member

Choose a reason for hiding this comment

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

Would have been nice to have a comment above about how change_amount must be positive in case of a self send, and how if this doesn't hold the sanity checks will catch this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah yes, I'll do that.

long_term_feerate,
change_policy: &change_policy,
};
let must_have_change = base_tx.output.is_empty(); // must have change if it is a self-send
Copy link
Member

Choose a reason for hiding this comment

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

The doc-comment of the function should be updated to document this.

Copy link
Member

Choose a reason for hiding this comment

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

I think even better would be to pass it as a parameter, so this function does not have any notion of self-send: it just exposes an interface to select coins such as there is always a change. And we set this in create_spend where we already have this notion of self-spend.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The new parameter sounds good, will add that.

This adds a new `LowestFeeChangeCondition` metric for use in
coin selection. It's the same as `LowestFee` with the option
to only find solutions with change.

This option is then used for self-sends to ensure only a solution
with change will be returned.
@jp1ac4 jp1ac4 force-pushed the lowest-fee-with-change-metric branch from 7a188f2 to 6123b87 Compare November 24, 2023 10:14
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 24, 2023

I've made the suggested changes and also fixed, in a separate commit, an unrelated part of documentation for select_coins_for_spend.

@darosior
Copy link
Member

ACK 6123b87

@darosior darosior merged commit cecc1a0 into wizardsardine:master Nov 24, 2023
18 checks passed
@jp1ac4 jp1ac4 deleted the lowest-fee-with-change-metric branch November 24, 2023 10:47
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