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

Fix withdrawal fee calculation & the min relay fee problem. #6544

Merged
merged 1 commit into from Jan 28, 2023
Merged

Fix withdrawal fee calculation & the min relay fee problem. #6544

merged 1 commit into from Jan 28, 2023

Conversation

ghost
Copy link

@ghost ghost commented Jan 27, 2023

1.0 sat/vB withdrawals were sometimes sent at 0.995 sat/vB and rejected by the network. Fixes #6493

Description of the problem:

Fee estimation for withdrawals has a bug which can be seen if you repeatedly request the withdrawal of the same UTXO and observe the fee shown; it varies slightly.

Worse than that is when a withdrawal is started (after you've seen the preview and confirmed), Bisq re-calculates the tx using the fee calculated earler and the actual receive address, but the tx can end up being larger than what it used in the preview.

The main problem here is that in the case where user chose 1 sat/vB, the sent tx can end up being below the min relay fee (less than 1 sat/vB) and is rejected by nodes. The user is left with a corrupted wallet and has to do an SPV resync. See example reported in #6493.

Why does this happen? See the fee estimation code here:

fee = txFeeForWithdrawalPerVbyte.multiply(txVsize);
// We use a dummy address for the output
// We don't know here whether the output is segwit or not but we don't care too much because the size of
// a segwit ouput is just 3 byte smaller than the size of a legacy ouput.
final String dummyReceiver = SegwitAddress.fromKey(params, new ECKey()).toString();
SendRequest sendRequest = getSendRequestForMultipleAddresses(fromAddresses, dummyReceiver, amount, fee, null, aesKey);
wallet.completeTx(sendRequest);
tx = sendRequest.tx;
txVsize = tx.getVsize();
printTx("FeeEstimationTransactionForMultipleAddresses", tx);

It creates a random receive address for purposes of calculating the fee. The problem with this is two-fold:

  • The address used for estimation can end up taking less tx space than the actual receiver address, resulting in a send tx which uses a smaller fee than requested (as the above code comment says)
  • The receiver address, being random, will result in a signature that can vary in length (signatures are sometimes 72 bytes sometimes 71 depending on the content being signed). That is why when you repeatedly do a "send preview" the shown fee rate varies by a small percentage.

Fix implemented here:

The withdrawal fee estimation should use the actual address the user has chosen to send to, therefore eliminating all variability in results. The sent tx will be exactly the same as the tx used in the preview, therefore fixing the problem of lower than 1 sat/vB transactions.

Copy link
Collaborator

@HenrikJannsen HenrikJannsen left a comment

Choose a reason for hiding this comment

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

utACK

Copy link
Contributor

@alejandrogarcia83 alejandrogarcia83 left a comment

Choose a reason for hiding this comment

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

utACK

@alejandrogarcia83 alejandrogarcia83 merged commit f43b5fe into bisq-network:master Jan 28, 2023
@alejandrogarcia83 alejandrogarcia83 added this to the v1.9.10 milestone Jan 28, 2023
@ghost ghost mentioned this pull request Feb 9, 2023
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 this pull request may close these issues.

Withdrawal TX not accepted by peers. Fee too low.
2 participants