Skip to content

Instantly share code, notes, and snippets.

@t-bast
Last active January 3, 2024 14:07
Show Gist options
  • Save t-bast/aec9ef80ff321e8fe27089f339421b53 to your computer and use it in GitHub Desktop.
Save t-bast/aec9ef80ff321e8fe27089f339421b53 to your computer and use it in GitHub Desktop.
Coin selection for liquidity providers

Coin selection for liquidity providers

Bitcoin Core's coin selection algorithms optimizes mostly for the following metrics:

  • keep a low utxo count by consolidating regularly
  • avoid creating a change output
  • when a change output is needed, use an amount equivalent to the payment (for privacy)

This doesn't match what liquidity providers need. Liquidity providers need to:

  • keep a large enough utxo pool
  • keep a diversity of utxo amounts that matches what we're selling
  • use as few inputs as possible when funding transactions
  • avoid creating change outputs most of the time

We'll need to either tweak the existing coin selection algorithms to match those goals, or write our own coin selection algorithm. Ideally this will take the form of a branch on top of Bitcoin Core's release branches, that is easy to rebase from one release to the other. Even more ideally this code would be accepted into Bitcoin Core.

Parameters to the algorithm

Utxo set target

We'd like to configure our Bitcoin Core node with a description of our ideal utxo set, which consists of buckets of specific amounts. This would probably be an array of the following form:

[
    {
        "bucket_start_satoshis": 10000,
        "bucket_end_satoshis": 25000,
        "target_utxo_count": 150,
    },
    {
        "bucket_start_satoshis": 50000,
        "bucket_end_satoshis": 75000,
        "target_utxo_count": 50,
    },
    {
        "bucket_start_satoshis": 200000,
        "bucket_end_satoshis": 250000,
        "target_utxo_count": 20,
    },
    {
        "bucket_start_satoshis": 1000000,
        "bucket_end_satoshis": 1400000,
        "target_utxo_count": 5,
    }
]

Bitcoin Core should try to make our utxo set converge towards that ideal utxo set. That ideal utxo set is crafted by the node operator to ensure that most funding attempts require few inputs for its expected business operations.

Bucket refill feerate

Since one of the goals of the coin selection algorithm is to produce transactions that don't have any change output, the buckets will gradually empty themselves. There should be two mechanisms to refill the utxo buckets:

  • opportunistic refill
  • low-feerate active refill

Whenever we're unable to produce a transaction that doesn't have a change output, we should opportunistically create change outputs that refill the most depleted buckets (even if that means adding more inputs).

If the current mempool feerate is below a configured threshold (bucket_refill_feerate), we should actively create change outputs to refill depleted buckets (note that it's perfectly fine, and even beneficial to create multiple change outputs in one single transaction).

Otherwise, when we're running too low on utxos in some buckets (with a threshold to be defined), we should force the creation of change outputs, regardless of the current feerate.

We probably don't need an algorithm that finds an optimal solution in terms of fees, since this is a long term game, where creating new change outputs may cost us more now, but save us some money later.

Passing those parameters

The parameters from the previous section should be persistent, but it would be nice to be able to update them without having to restart bitcoind. Not sure how that would work though (maybe bitcoind could regularly read from a configuration file?).

Algorithm steps

TODO!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment