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

feat(wallet): add TxBuilder::replace_tx #1799

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ValuedMammal
Copy link
Contributor

This PR adds a new method TxBuilder::replace_tx that offers a simple way of creating replacements without relying on the mechanics of build_fee_bump. See #1374 for context and motivating discussion.

In summary, there are a few limitations with the current build_fee_bump:

  1. It doesn't prevent the wallet from accidentally selecting the outputs of the replaced tx as inputs to the replacement
  2. The UX is somewhat rigid because it assumes all of the same inputs and outputs should appear in the replacement. (however despite this second point we somehow neglect to reuse the original drain script?)

In contrast replace_tx is useful when we only need to create a conflict and flexible enough to further tweak the parameters as desired.

Notes to the reviewers

  • TxBuilder::add_utxos is modified to look for potentially spent outputs, provided that the builder is in a bump-fee context.

  • 1e9caf4 should probably be a separate patch.

Changelog notice

wallet: Added method TxBuilder::replace_tx

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature

- Add method `TxBuilder::previous_fee` for getting the previous
feerate of the replaced tx
Comment on lines +389 to +394
// add previous fee
if let Ok(absolute) = self.wallet.calculate_fee(&tx) {
let rate = absolute / tx.weight();
let previous_fee = PreviousFee { absolute, rate };
self.params.bumping_fee = Some(previous_fee);
}
Copy link
Member

Choose a reason for hiding this comment

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

Should we still allow replacement if we can't determine the previous tx's fee/feerate?

Copy link
Member

@evanlinjin evanlinjin left a comment

Choose a reason for hiding this comment

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

ConceptACK, ApproachACK.

Just need to make sure we don't use descendant outputs from tx we are trying to replace.

It's out of the scope of this PR, the inability to set both feerate/fee amount constraints together really bothers me. We should probably switch to the bdk_coin_select crate soon.

Comment on lines +400 to +403
// do not try to spend the outputs of the tx being replaced
self.params
.unspendable
.extend((0..tx.output.len()).map(|vout| OutPoint::new(txid, vout as u32)));
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 we also need to add the children outputs of the tx being replaced.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe one more test to make sure we don't use descendant outputs of the tx we are trying to replace.

/// - If none of the inputs are owned by this wallet
///
/// [`finish`]: TxBuilder::finish
pub fn replace_tx(&mut self, txid: Txid) -> Result<&mut Self, ReplaceTxError> {
Copy link
Member

Choose a reason for hiding this comment

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

Should probably warn that we don't help keep the original tx's recipient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

2 participants