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

Verify maker & taker fee transactions via Mempool lookup #5160

Merged
merged 2 commits into from Mar 17, 2021
Merged

Verify maker & taker fee transactions via Mempool lookup #5160

merged 2 commits into from Mar 17, 2021

Conversation

ghost
Copy link

@ghost ghost commented Feb 6, 2021

Closes #5119

  • Queries mempool at checkOfferAvailability stage (take offer).
  • Validates maker transaction and trading fee.
  • Indicates status at UI level (see screenshots below)
  • Queries mempool at trade initiation (step 1&2) before fiat payment initiated.
  • Maker validates taker transaction and trading fee.
  • Informs user to open a dispute if the trading fees were not paid
  • Arbitrator ticket informs about the confirmation status of delayed payout

Screenshots

https://imgur.com/a/tSaUgRL


Safeguards

Can be disabled universally via a filter, and individually via config setting.

In regtest mode the API calls are bypassed, returning success status.


Accuracy

The fee schedule is set via DAO parameters. Therefore checking that the correct fee was paid involves comparing the block height of an offer Tx to the DAO parameters which were relevant at that time.

I observed some variance in fee payments, perhaps because different users nodes may have been out of consensus with the DAO state.

The validation code has a threshold at which it considers fees paid to be acceptable. Currently this is set at 95%, i.e. if the fee paid is >= 95% of what was expected, the validation passes.

Very old offers (of which there are a handful still out there), use fee addresses which are not known but perhaps were used prior to the DAO. So a threshold of blockheight 599999 is used such that the unknown fee addresses are allowed to pass when the offer Tx is older than the threshold. Alternatively we could add 1PUXU1M... and 18GzH11... to the validator's list of accepted fee addresses.

private final double feeTolerance = 0.95;     // we expect fees to be at least 95% of target
private final long blockTolerance = 599999L;  // allow really old offers with weird fee addresses

Out of ~450 current offers ~9 are flagged as having underpaid the trading fee.


Checks own open offers

To implement the requirement that one's own offers be checked I integrated a validation in the TriggerPriceService so that if an offer is found to be bad it gets automatically disabled. This can help prevent the issues we've been seeing of offers that do not get published to the mempool for hours/days sometimes. Now if an offer Tx is not found, it will get disabled and the user will be motivated to investigate.


Testing

Tests were written in TxValidatorTest to check the various error scenarios, be it underpaid BSQ, BTC, unknown fee address, or unknown tx. Most of the tests use data from real-world scenarios like the dust-fee scam.


PR Checklist:

  • Validate offer maker tx and fees.
  • Arbitrator checks that delayed payout tx is confirmed.
  • Verify deposit tx inputs match maker/taker outputs.
  • Maker verify taker fee payment.
  • Validates own open offers, disables ones that are bad.

@Conza88
Copy link

Conza88 commented Feb 6, 2021

I thought it did this already 😳

@ripcurlx
Copy link
Contributor

I thought it did this already 😳

Only for transactions that are linked to your wallet (e.g. Bisq fee tx of the trading peer wasn't checked)

@ghost ghost marked this pull request as draft February 14, 2021 04:51
@ghost ghost closed this Feb 17, 2021
@ghost ghost reopened this Feb 17, 2021
@ghost ghost changed the title Verify maker fee transactions Verify maker & taker fee transactions via Mempool lookup Feb 17, 2021
@Conza88
Copy link

Conza88 commented Feb 17, 2021

  • If there is a problem it warns user to back out (user can still continue).

Would there be a scenario when that was ever advisable? Or worth doing?

@ghost ghost mentioned this pull request Feb 28, 2021
@ghost ghost marked this pull request as ready for review March 12, 2021 23:55
long feeValue = jsonVIn0Value.getAsLong() - jsonFeeValue.getAsLong();
// if the first output (BSQ) is greater than the first input (BSQ) include the second input (presumably BSQ)
if (jsonFeeValue.getAsLong() > jsonVIn0Value.getAsLong()) {
// in this case 2 or more UTXOs were spent to pay the fee:
Copy link
Contributor

Choose a reason for hiding this comment

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

The code handles only the case of 1 or 2 BSQ inputs. Maybe also add a comment that we building on the concention that BSQ inputs are the before BTC inputs, which is not a consensus rule (for outputs it is) but our code handles it like that, so for the fee check that is good enough as we do not expect that ppl use custom txs for those txs.
It could be also a rare case that there is no BSQ change output. That can be if the input is exactly the amount to be burned or if the change is < dust, then it gets added to miner fee.

Another issue is that we do not check if the burned satoshis are BSQ or BTC. That would require that the tx is confirmed as only at confirmation the BSQ explorers recognize a BSQ tx. As confirmation will happen later we need to do that check after the deposit tx is confirmed in the trade protocol. So before the buyer sends the fiat he will check the takers BSQ fee it the BSQ explorer returns it as a valid BSQ tx and then before the seller confirms receipt to check the makers fee tx.

JsonObject jsonVin0 = jsonVin.get(0).getAsJsonObject();
JsonObject jsonVout0 = jsonVout.get(0).getAsJsonObject();
JsonElement jsonVIn0Value = jsonVin0.getAsJsonObject("prevout").get("value");
JsonElement jsonFeeValue = jsonVout0.get("value");
Copy link
Contributor

Choose a reason for hiding this comment

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

The BSQ fee check is tricky. Maybe a better approach is to postpone it directly to the trade protocol states when the deposit tx is confirmed and use the BSQ explorer for delivering the fee.
In BsqWalletService.completeBsqTradingFeeTx there have been added a while ago a change which made the input 0 a BTC output in case there is no BSQ output. I think that change is not needed (at least I tested it without and it worked, but don't want to touch that at the moment...). So to take that additional option into account all gets more complicated....

@ghost
Copy link
Author

ghost commented Mar 14, 2021

👍 Thanks @chimp1984 for the review & suggestions. I applied your changes, and will think about the suggestion of checking BSQ fees using a BSQ explorer.

@ripcurlx
Copy link
Contributor

@jmacxx I'm reviewing this PR right now and think it would be great to get it into v1.6.0. Could you please resolve the conflicts mentioned and I'm happy to merge it after a positive review.

@ripcurlx
Copy link
Contributor

ripcurlx commented Mar 17, 2021

I just got following error while trying to open a dispute as mediator:

März-17 15:33:03.377 [JavaFX Application Thread] ERROR bisq.common.setup.CommonSetup: Uncaught Exception from thread JavaFX Application Thread 
März-17 15:33:03.377 [JavaFX Application Thread] ERROR bisq.common.setup.CommonSetup: throwableMessage= null 
März-17 15:33:03.378 [JavaFX Application Thread] ERROR bisq.common.setup.CommonSetup: throwableClass= class java.lang.NullPointerException 
März-17 15:33:03.381 [JavaFX Application Thread] ERROR bisq.common.setup.CommonSetup: Stack trace:
java.lang.NullPointerException
	at bisq.core.provider.mempool.TxValidator.initialSanityChecks(TxValidator.java:260)
	at bisq.core.provider.mempool.TxValidator.parseJsonValidateTx(TxValidator.java:131)

This happens as jsonTxt is "" on Regtest.

@ripcurlx
Copy link
Contributor

ripcurlx commented Mar 17, 2021

It wasn't changed in this PR, but I missed it in the other one.
Please don't use version-new as class to highlight this text, as there might be a problem in the future if someone changes this class. It also shows a hand icon which indicates that this underlined label is clickable.

tradePeriodEnd.getStyleClass().add("version-new"); // highlight field when the trade period is still active

Better would be e.g. to create a new class .alert without underline and hand, so it doesn't look like a link.

.alert {
    -fx-text-fill: -bs-rd-error-red;
}

Bildschirmfoto 2021-03-17 um 16 08 06

@ripcurlx
Copy link
Contributor

And one more thing I missed in the other PR and feels a little bit weird for the user. If a dispute is closed you get the notification popup. When you click on it, it opens the support section and the issue is selected. But it is greyed out and users might not know what to do. Maybe it is better to open in this case automatically the same action as a double click would trigger. WDYT?

@ripcurlx
Copy link
Contributor

Also it would be good to show a (1) badge over the chat icon for the system message, so people are looking into it. In the past the chat was open by default in-line. So at least a notification would be good.

@ripcurlx ripcurlx added this to the v1.6.0 milestone Mar 17, 2021
jmacxx added 2 commits March 17, 2021 16:23
apply @chimp1984 patch.txt code review suggestions
taker tx check moved to trade step 2, after confirmation
solve issue with calculating expected fees for unconfirmed tx
resolve conflict with PR5207 (Disputes UI)
check new offers after 1 block; check Json string not null; warn -> info
remove unused parameter
remove debugging log.warn message
Copy link
Contributor

@ripcurlx ripcurlx left a comment

Choose a reason for hiding this comment

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

ACK - tested it on Regtest and Mainnet. So far everything is looking fine besides the minor issues that are fixed now.

@ghost ghost deleted the mempool_check_maker_tx branch May 29, 2022 22:49
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.

Add mempool lookup for trade transactions
3 participants