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

BTC Replace by Fee (RBF) feature: Allow a BTC transaction to be replaced with a higher fee #82

Closed
Flouse opened this issue Mar 31, 2024 · 3 comments · Fixed by #150
Closed
Assignees
Labels
enhancement New feature or request

Comments

@Flouse
Copy link
Contributor

Flouse commented Mar 31, 2024

Enabling the RBF feature (allowing transactions to be replaced) is easy, but how to sign and send the same transaction again is a problem. The issue is that when we got the UTXOs to construct a transaction, we got them from the btc-assets-api. And once the transaction is constructed, it no longer contains some required properties for us to "reverse" the whole construction process and convert a Transaction to a PSBT.

For example, how does the process know which output (vout) in the transaction can be altered in order to pay more fees? And besides, what's the dust limit for each output? Since outputs can be normal UTXOs (dust_limit=1,0000) or RGBPP UTXOs (dust_limit=546)._limit=546).

Originally posted by @ShookLyngs in #37 (comment)

References

@Flouse Flouse added enhancement New feature or request P-Medium labels Apr 27, 2024
@ShookLyngs
Copy link
Collaborator

ShookLyngs commented Apr 29, 2024

Full RBF

Here's an example of Full RBF processed on testnet. Let's look at the stats:

  • TX_1: 1 input, 2 outputs, 1 sat/vB fee rate, not sequenced (no Opt-in RBF support)
  • TX_2: 3 input, 3 outputs, 50 sat/vB fee rate, it referenced the same inputs[0] as TX_1

You can review the TX_2 here: fc081ae0faca52c421e6d7c3e37cb62f4e3ef3701fd4b42ce0bfc4045a3eb817.

The two transactions have the same inputs[0], outputs[0], and outputs[1]. The idea was to not overcomplicate things at first, and just start simple by ignoring the existing inputs/outputs (don't edit them at all) in TX_1. The stretegy gives us the advantage of avoiding unknown issues and still achieving our goal: transaction acceleration.

However, this method also has a disadvantage: In order to construct the RBF transaction (TX_2), the sender must have a balance more than sufficient, and additionally, the sender must have at least one more UTXO in the wallet.

TX_1

Transaction

{
  version: 2,
  locktime: 0,
  ins: [
    {
      hash: <Buffer b4 35 45 08 e6 0a 6b 23 2e a6 68 4a ae ed 97 9d ec 31 03 31 f5 e7 76 c0 1b d2 f2 f1 d3 f4 1f d8>,
      index: 1,
      script: <Buffer >,
      sequence: 4294967295,
      witness: [Array]
    }
  ],
  outs: [
    {
      script: <Buffer 00 14 db f4 36 0c 07 91 09 8b 0b 14 67 9e 5e 78 01 5d f3 f2 ca ad>,
      value: 1000
    },
    {
      script: <Buffer 00 14 db f4 36 0c 07 91 09 8b 0b 14 67 9e 5e 78 01 5d f3 f2 ca ad>,
      value: 5846
    }
  ]
}

Hex

02000000000101b4354508e60a6b232ea6684aaeed979dec310331f5e776c01bd2f2f1d3f41fd80100000000ffffffff02e803000000000000160014dbf4360c0791098b0b14679e5e78015df3f2caadd616000000000000160014dbf4360c0791098b0b14679e5e78015df3f2caad024730440220051d74a7330739b7c5e33cdac67378ec972e6688d585bc8f4f2b2dc3c45e034d02204b5c6edc230871b5a717453d8c43bd712ef52eab9d596863e54d16b6ce2ebe5e0121037dff8ff2e0bd222690d785f9277e0c4800fc88b0fad522f1442f21a8226253ce00000000

TX_2

Transaction

{
  version: 2,
  locktime: 0,
  ins: [
    {
      hash: <Buffer b4 35 45 08 e6 0a 6b 23 2e a6 68 4a ae ed 97 9d ec 31 03 31 f5 e7 76 c0 1b d2 f2 f1 d3 f4 1f d8>,
      index: 1,
      script: <Buffer >,
      sequence: 4294967295,
      witness: [Array]
    },
    {
      hash: <Buffer 61 e1 32 7f e8 f2 9b c3 28 fe 1a b1 1a da da 38 2d ec b6 4a be 1a fd 06 91 4f c5 e8 98 b7 39 67>,
      index: 0,
      script: <Buffer >,
      sequence: 4294967295,
      witness: [Array]
    },
    {
      hash: <Buffer 61 e1 32 7f e8 f2 9b c3 28 fe 1a b1 1a da da 38 2d ec b6 4a be 1a fd 06 91 4f c5 e8 98 b7 39 67>,
      index: 1,
      script: <Buffer >,
      sequence: 4294967295,
      witness: [Array]
    }
  ],
  outs: [
    {
      script: <Buffer 00 14 db f4 36 0c 07 91 09 8b 0b 14 67 9e 5e 78 01 5d f3 f2 ca ad>,
      value: 1000
    },
    {
      script: <Buffer 00 14 db f4 36 0c 07 91 09 8b 0b 14 67 9e 5e 78 01 5d f3 f2 ca ad>,
      value: 5846
    },
    {
      script: <Buffer 00 14 db f4 36 0c 07 91 09 8b 0b 14 67 9e 5e 78 01 5d f3 f2 ca ad>,
      value: 827110
    }
  ]
}

Hex

02000000000103b4354508e60a6b232ea6684aaeed979dec310331f5e776c01bd2f2f1d3f41fd80100000000ffffffff61e1327fe8f29bc328fe1ab11adada382decb64abe1afd06914fc5e898b739670000000000ffffffff61e1327fe8f29bc328fe1ab11adada382decb64abe1afd06914fc5e898b739670100000000ffffffff03e803000000000000160014dbf4360c0791098b0b14679e5e78015df3f2caadd616000000000000160014dbf4360c0791098b0b14679e5e78015df3f2caade69e0c0000000000160014dbf4360c0791098b0b14679e5e78015df3f2caad02473044022043941307f1541b408c9d97345ece962fac4dca1a586fb8f9bea9117eb6fcaac7022038d2cbe37a31800decde535e6cf366de52ddfdec78ac56259751cd533239d6690121037dff8ff2e0bd222690d785f9277e0c4800fc88b0fad522f1442f21a8226253ce02473044022002cfed86d563c2d488e9af576bc63562720a32e7e8e2b16243abad84b37b15c7022039cdc2de0bb47ab170a1e6f39022d894555b4730cd08185a0588c892792c3c060121037dff8ff2e0bd222690d785f9277e0c4800fc88b0fad522f1442f21a8226253ce02483045022100aede6ebc905c25ae7d8d2316ab7569d946ce4c29c90c77380df96aae8d2ea0070220295ed0d980c65292682663ec8169287b916569772501cb4a018dde5a6adeb4ff0121037dff8ff2e0bd222690d785f9277e0c4800fc88b0fad522f1442f21a8226253ce00000000

@Flouse Flouse linked a pull request May 1, 2024 that will close this issue
@Flouse Flouse changed the title BTC Replace by Fee (RBF) feature: Allow a BTC transaction to be replaced BTC Replace by Fee (RBF) feature: Allow a BTC transaction to be replaced with a higher fee May 10, 2024
@Flouse
Copy link
Contributor Author

Flouse commented May 14, 2024

TX_1 was replaced by TX_2

Discussion

Let's say TX_1 has an isomophic rgbpp_ckb_tx_virtual. And there is a job of TX_1 in the assets-api's RGB++ CKB transaction Queue, called TX_1's job.

How to automatically add TX_2's job to the RGB++ CKB transaction Queue when TX_1 is replaced by TX_2?

  1. Monitor Bitcoin Mempool, and detect TX_1 Replacement
    Continuously monitor the Bitcoin mempool for any new transactions that spend one of the inputs of TX_1.
    When a new transaction (TX_2) spending inputs from TX_1 is detected, identify if TX_2 is a replacement for TX_1 based on criteria like higher fee rate, same inputs, etc.
  1. Verify TX_2 Validity
    Verify that TX_2 is a valid RGB++ transaction by checking if it contains the right RGB++ commitment.

  2. Add TX_2's Job to Queue
    Add a new job for TX_2 to the RGB++ CKB transaction Queue, including the TX_2_txid and the related rgbpp_ckb_tx_virtual, a.k.a TX_1's rgbpp_ckb_tx_virtual.

Why this feature is required?

Sometimes the RBF BTC transaction is submitted by other BTC RBF service providers, not through rgbpp-sdk. in this case, the TX_2's job may not be processed.

This process ensures that when TX_1 is replaced by TX_2 on the Bitcoin network, the RGB++ CKB transaction Queue is automatically updated with the new job for TX_2, allowing for seamless processing of the BTC RBF workflow.

Priority: Low

cc @ShookLyngs @ahonn

@ShookLyngs
Copy link
Collaborator

ShookLyngs commented May 14, 2024

Monitor Bitcoin Mempool, and detect TX_1 Replacement

Maybe these APIs can help:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants