utxostack / rgbpp-sdk

Utilities for Bitcoin and RGB++ asset integration
ISC License
53 stars 18 forks source link

fix(rgbpp-sdk/btc): fee estimation/collection issues #90

Closed ShookLyngs closed 7 months ago

ShookLyngs commented 7 months ago

Changes

  1. Fix when sum(ins) > sum(outs) && change < fee, the returned change is incorrect (found by @duanyytop)
  2. Fix when outs has only an OP_RETURN output, and ins has no UTXOs specified, the collection is skipped

Details

When sum(ins) > sum(outs) && change < fee

Previously when the sum of ins is greater than the sum of outs, the process goes in the returning phase. But when calculating the return amount with extraSatoshiInInputs - fee, the fee can actually be greater then the extraSatoshiInInputs, in that case, the returning amount is a negative number.

To address the issue, I changed the check statement:

The logic change should prevent errors when there is change to be returned, but the change is less than the fee. In this situation, it should always collect for more instead of returning a negative value.

When sum(ins) == sum(outs) == 0

When the BTC TX initialized as the following, the sum(ins) and sum(outs) are both zero:

ins(0):

outs(1):
- OP_RETURN output, value=0

When the inputs list has no length, the PSBT cannot be signed or finalized, and the fee estimation cannot be processed if the PSBT isn't finalized. The process will throw an error in that case, even though this is a possible situation for an initial transaction.

To resolve this issue, I added a protection check:

const safeToProcess = inputsTotal > 0 || previousFee > 0;
if (safeToProcess && canReturnChange) { 
  // ... return change
} else {
  const protectionAmount = !safeToProcess ? 1 : 0;
  await collectSatoshi({ amount: targetAmount + protectionAmount, ... })
}

The protection ensures that if the fee is 0 (not calculated yet) and the inputs list is empty, the collection must be processed once with the targeet of at least 1 satoshi, in order for the fee estimation to be calculated later on.