-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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 loss of mailbox messages during SPV resync #6376
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think its better and more safe to protect the init method as otherwise the mailbox could be applied with unintended consequences.
Here is a patch of my suggestion (does not cover the UI change):
Index: p2p/src/main/java/bisq/network/p2p/mailbox/MailboxMessageService.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/p2p/src/main/java/bisq/network/p2p/mailbox/MailboxMessageService.java b/p2p/src/main/java/bisq/network/p2p/mailbox/MailboxMessageService.java
--- a/p2p/src/main/java/bisq/network/p2p/mailbox/MailboxMessageService.java (revision 84a1cd626d246726303cbc4fe595fec3473015c2)
+++ b/p2p/src/main/java/bisq/network/p2p/mailbox/MailboxMessageService.java (date 1669326934458)
@@ -128,6 +128,8 @@
private final Map<String, MailboxItem> mailboxItemsByUid = new HashMap<>();
private boolean isBootstrapped;
+ private boolean allServicesInitialized;
+ private boolean initAfterBootstrapped;
@Inject
public MailboxMessageService(NetworkNode networkNode,
@@ -215,6 +217,12 @@
// API
///////////////////////////////////////////////////////////////////////////////////////////
+ // We wait until all services are ready to avoid some edge cases as in https://github.com/bisq-network/bisq/issues/6367
+ public void onAllServicesInitialized() {
+ allServicesInitialized = true;
+ init();
+ }
+
// We don't listen on requestDataManager directly as we require the correct
// order of execution. The p2pService is handling the correct order of execution and we get called
// directly from there.
@@ -226,11 +234,18 @@
// second stage starup for MailboxMessageService ... apply existing messages to their modules
public void initAfterBootstrapped() {
- // Only now we start listening and processing. The p2PDataStorage is our cache for data we have received
- // after the hidden service was ready.
- addHashMapChangedListener();
- onAdded(p2PDataStorage.getMap().values());
- maybeRepublishMailBoxMessages();
+ initAfterBootstrapped = true;
+ init();
+ }
+
+ private void init() {
+ if (allServicesInitialized && initAfterBootstrapped) {
+ // Only now we start listening and processing. The p2PDataStorage is our cache for data we have received
+ // after the hidden service was ready.
+ addHashMapChangedListener();
+ onAdded(p2PDataStorage.getMap().values());
+ maybeRepublishMailBoxMessages();
+ }
}
Index: core/src/main/java/bisq/core/app/DomainInitialisation.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/main/java/bisq/core/app/DomainInitialisation.java b/core/src/main/java/bisq/core/app/DomainInitialisation.java
--- a/core/src/main/java/bisq/core/app/DomainInitialisation.java (revision 84a1cd626d246726303cbc4fe595fec3473015c2)
+++ b/core/src/main/java/bisq/core/app/DomainInitialisation.java (date 1669326857062)
@@ -58,6 +58,7 @@
import bisq.core.user.User;
import bisq.network.p2p.P2PService;
+import bisq.network.p2p.mailbox.MailboxMessageService;
import bisq.common.ClockWatcher;
import bisq.common.persistence.PersistenceManager;
@@ -115,6 +116,7 @@
private final TriggerPriceService triggerPriceService;
private final MempoolService mempoolService;
private final OpenBsqSwapOfferService openBsqSwapOfferService;
+ private final MailboxMessageService mailboxMessageService;
@Inject
public DomainInitialisation(ClockWatcher clockWatcher,
@@ -154,7 +156,8 @@
DaoStateSnapshotService daoStateSnapshotService,
TriggerPriceService triggerPriceService,
MempoolService mempoolService,
- OpenBsqSwapOfferService openBsqSwapOfferService) {
+ OpenBsqSwapOfferService openBsqSwapOfferService,
+ MailboxMessageService mailboxMessageService) {
this.clockWatcher = clockWatcher;
this.tradeLimits = tradeLimits;
this.arbitrationManager = arbitrationManager;
@@ -193,6 +196,7 @@
this.triggerPriceService = triggerPriceService;
this.mempoolService = mempoolService;
this.openBsqSwapOfferService = openBsqSwapOfferService;
+ this.mailboxMessageService = mailboxMessageService;
}
public void initDomainServices(Consumer<String> rejectedTxErrorMessageHandler,
@@ -277,6 +281,8 @@
triggerPriceService.onAllServicesInitialized();
mempoolService.onAllServicesInitialized();
+ mailboxMessageService.onAllServicesInitialized();
+
if (revolutAccountsUpdateHandler != null) {
revolutAccountsUpdateHandler.accept(user.getPaymentAccountsAsObservable().stream()
.filter(paymentAccount -> paymentAccount instanceof RevolutAccount)
Applied the code changes from @HenrikJannsen and re-tested. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK
Hi @jmacxx I had a user that appears to have lost a mediation ticket during an SPV resync.
Does this feature enable mediations and arbitrations opened during an SPV resync not to get lost? I have the logs if helpful. |
|
I did a few tests with the following results: Alice and Bob have a trade in process.
Presumably the messaging layer decides to store the message in a mailbox if it cannot make a connection. I'm not sure how scenario (b) can be solved. |
Mediator will always try to send a message again if a trader does not reply. Could something be done on the subsequent attempts? Maybe checking to see if a mediation ticket exists on the traders instance and opening one if that is not the case. |
Fixes #6367
When SPV resync is performed from the UI, the app is started but the wallet does a resync and then needs another restart. Unfortunately per #6367, during SPV resync mailbox messages can still be received but are tossed by the recipients due to the app not being ready. The MailboxMessageService was unaware of this and deleted the unprocessed messages from the network. The fix is to pass a widely used
onAllServicesInitialized
flag so that the MailboxMessageService can make the decision to not remove messages before the app is ready to process them.During testing, observed an NPE when the NetworkSettingsView is the first screen shown (happens after clicking the
Delete SPV file and resync
button and restarting). Included a fix for that NPE here.Test case: