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

Introduce canonicalization modifiers. #1808

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

Conversation

evanlinjin
Copy link
Member

Partially Fixes #1748

Description

Add the ability to modify the canonicalization algorithm. Right now, the only modifier is assume_canonical which takes in a Vec (ordered list) of txids and superimposes it on the canonicalization algorithm. Txs later in the list (higher index) have a higher priority (in case of conflicts).

This is a "partial fix" because I haven't figured out how to expose this on the bdk_wallet level yet (some thoughts on this will be very appreciated).

Notes to the reviewers

None at the moment.

Changelog notice

  • Added CanonicalizationMods to allow the caller to modify the canonicalization algorithm. This in a new parameter on CanonicalIter::new.

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

Bugfixes:

  • This pull request breaks the existing API
  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

@evanlinjin evanlinjin self-assigned this Jan 23, 2025
@evanlinjin evanlinjin added the api A breaking API change label Jan 23, 2025
@evanlinjin evanlinjin added this to the 1.1.0 milestone Jan 23, 2025
Introduce `CanonicalizationMods` which is passed in to
`CanonicalIter::new`.

`CanonicalizationMods::assume_canonical` is the only field right now.
This contains a list of txids that we assume to be canonical,
superceding any other canonicalization rules.
Also change `TxTemplate` API to allow for testing with
`assume_canonical`.
@notmandatory
Copy link
Member

Would it make sense to add CanonicalizationMods as a field of TxGraph ?

This way the existing TxGraph method signatures don't change, you'd just need a new function to add TxIds to the CanonicalizationMods in the TxGraph.

And if you could only add new TxIds to your CanonicalizationMods this should still be monotone right?

Then you could also add the CanonicalizationMods data to the tx_graph::Changeset so it's persisted. Of course you'd need to update the persistence crates but wouldn't users need/want to persist these mods anyway so a reloaded wallet shows the same balance and utxos?

For Wallet I'm imaging some higher level functions for the things a wallet user needs. For instance (based on suggestions in #1748):

  1. change TxBuilder::finish to insert new unbroadcast tx and add a canonical mod so their inputs won't be double spent
  2. add a canonical mod for a new RBF tx so it has precedence over the unconfirmed tx it's replacing
  3. list unbroadcast tx (found in CanonicalizationMods but not seen)
  4. add an option to TxBuilder to include inputs from unbroadcast tx(s), the new tx has higher canonicalization
  5. remove tx from CanonicalizationMods after seen in mempool (or would this make TxGraph not monotone?)

use bdk_core::BlockId;
use bitcoin::{Transaction, Txid};

/// Modifies the canonicalization algorithm.
#[derive(Debug, Default, Clone)]
pub struct CanonicalizationMods {
Copy link
Contributor

Choose a reason for hiding this comment

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

"Params" feels more idiomatic.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, it also aligns better with other usages in the project, i.e: TxParams, LoadParams.


impl CanonicalizationMods {
/// No mods.
pub const NONE: Self = Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

Dunno if we need this. Default is enough.

// We want to be able to replace an unsigned tx with a signed tx.
// The tx with more weight has precedence (and tiebreak with the actual tx data).
// We can also check whether the witness is valid and also prioritize signatures
// with less weight, but that is more work and this solution is good enough.
Copy link
Contributor

Choose a reason for hiding this comment

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

Prediction: It's less lines of code than this comment to just do it correctly.

@LLFourn
Copy link
Contributor

LLFourn commented Jan 28, 2025

ConceptACK. Would be nice to have draft PR built on this that resolves #1748 so we know that this is all that's needed at the chain level before merging this.

Copy link
Contributor

@oleonardolima oleonardolima left a comment

Choose a reason for hiding this comment

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

cACK 0f00cdb

use bdk_core::BlockId;
use bitcoin::{Transaction, Txid};

/// Modifies the canonicalization algorithm.
#[derive(Debug, Default, Clone)]
pub struct CanonicalizationMods {
Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, it also aligns better with other usages in the project, i.e: TxParams, LoadParams.

@notmandatory notmandatory removed this from the 1.1.0 milestone Feb 4, 2025
@notmandatory
Copy link
Member

Took this out of the bdk_wallet 1.1 milestone since tagging the release tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api A breaking API change
Projects
Status: Needs Review
Development

Successfully merging this pull request may close these issues.

Don't double spend created transaction just because they haven't been broadcasted
4 participants