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

Support address re-use in Receive Chain Swap #432

Open
ok300 opened this issue Aug 2, 2024 · 9 comments · May be fixed by #471
Open

Support address re-use in Receive Chain Swap #432

ok300 opened this issue Aug 2, 2024 · 9 comments · May be fixed by #471
Assignees
Milestone

Comments

@ok300
Copy link
Contributor

ok300 commented Aug 2, 2024

Scenario:

  • Receive Chain Swap is created and successfully completed
  • 24h later, new (BTC) funds are sent to the same (BTC) Lockup Address
  • 10h later:
    • on Boltz, the swap state is transaction.claimed (the final status from the initial completed swap)
    • on SDK, the swap status is Refundable

Example instance: testnet swap 7u5RFB8HQNdp

On SDK startup:

[2024-08-02 10:21:36.862 INFO breez_sdk_liquid::chain_swap:142] Chain Swap 7u5RFB8HQNdp has 5000 confirmed and 0 unconfirmed sats
[2024-08-02 10:21:36.862 INFO breez_sdk_liquid::chain_swap:153] Chain Swap 7u5RFB8HQNdp has 5000 unspent sats. Setting the swap to refundable
[2024-08-02 10:21:36.862 INFO breez_sdk_liquid::chain_swap:547] Transitioning Chain swap 7u5RFB8HQNdp to Refundable (server_lockup_tx_id = None, user_lockup_tx_id = None, claim_tx_id = None), refund_tx_id = None)
@dangeross
Copy link
Collaborator

This should be correct, as the additionally sent BTC amount needs to be refunded back to the sender using prepare_refund / refund

@ok300
Copy link
Contributor Author

ok300 commented Aug 2, 2024

Don't we also need the matching Boltz status for a swap to be actually refundable?

For the swap states swap.expired where bitcoin were sent and transaction.lockupFailed, the user needs to submit a refund transaction to reclaim the locked chain bitcoin.
https://docs.boltz.exchange/v/api/lifecycle#chain-swaps

The Boltz status is transaction.claimed.

@roeierez
Copy link
Member

roeierez commented Aug 7, 2024

@ok300 why do we care about the swapper status here? If we know use added more funds to that address then it seems right to me to mark it as refundable. Where do you see an issue here?

@ok300
Copy link
Contributor Author

ok300 commented Aug 13, 2024

True, we don't need it. I thought we need the swapper status to agree with our status (refundable), but the refund doesn't need interaction as we can build the refund tx ourselves.

Then the key question is: do we support address re-use?

If yes:

  • the swap should be marked as Refundable if new BTC funds are sent to the BTC lockup address after the swap completes (true today)
  • we now store one optional refund_tx_id, we should instead store a vector of refund txs (or only a single "latest" refund tx id?)
  • we have to revamp our new_refund method, as it now only takes the first utxo when building the refund tx (there could be more than one)

@ok300 ok300 changed the title On Receive Chain Swap address re-use, we incorrectly mark the swap as refundable TBD: Support address re-use in Receive Chain Swap? Aug 13, 2024
@roeierez
Copy link
Member

I think the important items here are:

  1. Make sure we mark as refundable a swap in such case (that has another utxo after use or expiration). This will ensure the user won't loose funds
  2. The refund should consider all inputs and not only the first utxo.

I am not sure if we need atm to change the refund_tx_id field to be a vector as we can define it as the last_refund_tx_id (unless it has a bad affect on our logic)

@roeierez roeierez added this to the v0.1.2 milestone Aug 14, 2024
@ok300
Copy link
Contributor Author

ok300 commented Sep 4, 2024

I ran some tests and have two questions:

  1. If we have a Receive Chain Swap that is
  • completed successfully
  • receives new funds at the lockup address at a block height that is way before the timeout_block_height

then non-cooperative refund will only work after timeout_block_height. This means until then, these funds cannot be used or refunded, even though we know the swap can only be refunded.

Q: Is this desired behavior?

  1. I noticed we only monitor chain swaps for this amount of blocks
/// Number of blocks to monitor a swap after its timeout block height
pub const CHAIN_SWAP_MONITORING_PERIOD_BITCOIN_BLOCKS: u32 = 4320;

This means if address re-use happens after this time (30 days), we will not pick it up.

Q: should I remove this and instead let it monitor chain swaps forever?

@roeierez
Copy link
Member

roeierez commented Sep 4, 2024

: Is this desired behavior?

It is the only option. non-cooperative refund can't work within the lock height range.

should I remove this and instead let it monitor chain swaps forever?

It is a tradeoff so we won't get into performance issues. Users can use the rescan_swaps themselves in that cases (or periodically).

@ok300
Copy link
Contributor Author

ok300 commented Sep 4, 2024

: Is this desired behavior?

It is the only option. non-cooperative refund can't work within the lock height range.

Forgot to mention: this also means list_refundables only shows it as refundable after the lock height timeout.

In normal cases (no address re-use), refundable swaps are shown in list_refundables as soon as we know it can be refunded, because

  • we get that state from Boltz (but with address re-use, Boltz doesn't mark it as refundable, so we can't rely on this anymore) and
  • cooperative refund works (but with address re-use, it doesn't).

So it is correct (and the only possible way) that list_refundables only shows such swaps as refundable after the lock height timeout.

I will document this in the docs.

  • Update refund docs: describe particularities of refunding Receive Chain Swaps with address re-use

@ok300
Copy link
Contributor Author

ok300 commented Sep 6, 2024

Short update:

Testing the situation above (address re-use + attempt refund after lock height timeout) I found that:

  • list_refundables correctly shows the swap as refundable, but only shows the swap amount instead of the actual refundable amount (script_balance.confirmed)

    This can be fixed by having our list_refundables do an onchain lookup for the current confirmed balance in the lockup script.

  • prepare_refund and refund will only consider the first utxo, so it doesn't refund the full amount. This is part of the Boltz client logic that builds the refund tx:

    https://github.com/SatoshiPortal/boltz-rust/blob/9072939c162bab8370cfcfe75a458319f289b160/src/swaps/bitcoin.rs#L508

    For this, I'll prepare a fix in the Boltz client crate to consider all available utxos for the non-cooperative refund.

@ok300 ok300 changed the title TBD: Support address re-use in Receive Chain Swap? Support address re-use in Receive Chain Swap Sep 6, 2024
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 a pull request may close this issue.

3 participants