diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java index 3299d2c0..c39f7bbf 100644 --- a/core/src/main/java/bisq/core/api/CoreOffersService.java +++ b/core/src/main/java/bisq/core/api/CoreOffersService.java @@ -111,7 +111,9 @@ public class CoreOffersService { .filter(o -> !o.isMyOffer(keyRing)) .filter(o -> { Result result = offerFilter.canTakeOffer(o, coreContext.isApiUser()); - return result.isValid() || result == Result.HAS_NO_PAYMENT_ACCOUNT_VALID_FOR_OFFER; + boolean valid = result.isValid() || result == Result.HAS_NO_PAYMENT_ACCOUNT_VALID_FOR_OFFER; + if (!valid) log.warn("Cannot take offer " + o.getId() + " with invalid state : " + result); + return valid; }) .findAny().orElseThrow(() -> new IllegalStateException(format("offer with id '%s' not found", id))); diff --git a/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java b/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java index 31780fc4..07cdf01e 100644 --- a/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java @@ -155,7 +155,7 @@ public class XmrWalletService { public MoneroWallet getWallet() { State state = walletsSetup.getWalletConfig().state(); - checkState(state == State.STARTING || state == State.RUNNING, "Cannot call until startup is complete"); + checkState(state == State.STARTING || state == State.RUNNING, "Cannot call until startup is complete, but state is: " + state); return wallet; } diff --git a/core/src/main/java/bisq/core/offer/OfferFilterService.java b/core/src/main/java/bisq/core/offer/OfferFilterService.java index 518da981..8bf69ef9 100644 --- a/core/src/main/java/bisq/core/offer/OfferFilterService.java +++ b/core/src/main/java/bisq/core/offer/OfferFilterService.java @@ -224,6 +224,6 @@ public class OfferFilterService { public boolean hasValidSignature(Offer offer) { Arbitrator arbitrator = user.getAcceptedArbitratorByAddress(offer.getOfferPayload().getArbitratorSigner()); if (arbitrator == null) return false; // invalid arbitrator - return TradeUtils.isArbitratorSignatureValid(offer.getOfferPayload(), arbitrator); + return TradeUtils.isArbitratorSignatureValid(offer, arbitrator); } } diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java index 4758c4da..05ee2ba1 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/AddToOfferBook.java @@ -23,6 +23,8 @@ import bisq.core.offer.placeoffer.PlaceOfferModel; import bisq.common.taskrunner.Task; import bisq.common.taskrunner.TaskRunner; +import static com.google.common.base.Preconditions.checkNotNull; + public class AddToOfferBook extends Task { public AddToOfferBook(TaskRunner taskHandler, PlaceOfferModel model) { @@ -33,6 +35,7 @@ public class AddToOfferBook extends Task { protected void run() { try { runInterceptHook(); + checkNotNull(model.getSignOfferResponse().getSignedOfferPayload().getArbitratorSignature(), "Offer's arbitrator signature is null: " + model.getOffer().getId()); model.getOfferBookService().addOffer(new Offer(model.getSignOfferResponse().getSignedOfferPayload()), () -> { model.setOfferAddedToOfferBook(true); diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerProcessSignOfferResponse.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerProcessSignOfferResponse.java index 2d631be2..8231a19b 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerProcessSignOfferResponse.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerProcessSignOfferResponse.java @@ -38,9 +38,11 @@ public class MakerProcessSignOfferResponse extends Task { try { runInterceptHook(); - // validate arbitrator signature + // get arbitrator Arbitrator arbitrator = checkNotNull(model.getUser().getAcceptedArbitratorByAddress(offer.getOfferPayload().getArbitratorSigner()), "user.getAcceptedArbitratorByAddress(arbitratorSigner) must not be null"); - if (!TradeUtils.isArbitratorSignatureValid(model.getSignOfferResponse().getSignedOfferPayload(), arbitrator)) { + + // validate arbitrator signature + if (!TradeUtils.isArbitratorSignatureValid(new Offer(model.getSignOfferResponse().getSignedOfferPayload()), arbitrator)) { throw new RuntimeException("Offer payload has invalid arbitrator signature"); } diff --git a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java index 321c20b6..139d3f12 100644 --- a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java +++ b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java @@ -669,7 +669,7 @@ public final class ArbitrationManager extends DisputeManager { - closeChat(); - this.selectedDispute = selectedDispute; + closeChat(); + this.selectedDispute = selectedDispute; + selectedDispute.getChatMessages().forEach(m -> m.setWasDisplayed(true)); + disputeManager.requestPersistence(); + + ChatView chatView = new ChatView(disputeManager, formatter, counterpartyName); + chatView.setAllowAttachments(true); + chatView.setDisplayHeader(false); + chatView.initialize(); + + AnchorPane pane = new AnchorPane(chatView); + pane.setPrefSize(760, 500); + AnchorPane.setLeftAnchor(chatView, 10d); + AnchorPane.setRightAnchor(chatView, 10d); + AnchorPane.setTopAnchor(chatView, -20d); + AnchorPane.setBottomAnchor(chatView, 10d); + pane.getStyleClass().add("dispute-chat-border"); + Button closeDisputeButton = null; + if (!selectedDispute.isClosed() && !disputeManager.isTrader(selectedDispute)) { + closeDisputeButton = new AutoTooltipButton(Res.get("support.closeTicket")); + closeDisputeButton.setOnAction(e -> chatCallback.onCloseDisputeFromChatWindow(selectedDispute)); + } + chatView.display(concreteDisputeSession, closeDisputeButton, pane.widthProperty()); + chatView.activate(); + chatView.scrollToBottom(); + chatPopupStage = new Stage(); + chatPopupStage.setTitle(Res.get("disputeChat.chatWindowTitle", selectedDispute.getShortTradeId()) + + " " + selectedDispute.getRoleString()); + StackPane owner = MainView.getRootContainer(); + Scene rootScene = owner.getScene(); + chatPopupStage.initOwner(rootScene.getWindow()); + chatPopupStage.initModality(Modality.NONE); + chatPopupStage.initStyle(StageStyle.DECORATED); + chatPopupStage.setOnHiding(event -> { + chatView.deactivate(); + // at close we set all as displayed. While open we ignore updates of the numNewMsg in the list icon. selectedDispute.getChatMessages().forEach(m -> m.setWasDisplayed(true)); disputeManager.requestPersistence(); - - ChatView chatView = new ChatView(disputeManager, formatter, counterpartyName); - chatView.setAllowAttachments(true); - chatView.setDisplayHeader(false); - chatView.initialize(); - - AnchorPane pane = new AnchorPane(chatView); - pane.setPrefSize(760, 500); - AnchorPane.setLeftAnchor(chatView, 10d); - AnchorPane.setRightAnchor(chatView, 10d); - AnchorPane.setTopAnchor(chatView, -20d); - AnchorPane.setBottomAnchor(chatView, 10d); - pane.getStyleClass().add("dispute-chat-border"); - Button closeDisputeButton = null; - if (!selectedDispute.isClosed() && !disputeManager.isTrader(selectedDispute)) { - closeDisputeButton = new AutoTooltipButton(Res.get("support.closeTicket")); - closeDisputeButton.setOnAction(e -> chatCallback.onCloseDisputeFromChatWindow(selectedDispute)); - } - chatView.display(concreteDisputeSession, closeDisputeButton, pane.widthProperty()); - chatView.activate(); - chatView.scrollToBottom(); - chatPopupStage = new Stage(); - chatPopupStage.setTitle(Res.get("disputeChat.chatWindowTitle", selectedDispute.getShortTradeId()) - + " " + selectedDispute.getRoleString()); - StackPane owner = MainView.getRootContainer(); - Scene rootScene = owner.getScene(); - chatPopupStage.initOwner(rootScene.getWindow()); - chatPopupStage.initModality(Modality.NONE); - chatPopupStage.initStyle(StageStyle.DECORATED); - chatPopupStage.setOnHiding(event -> { - chatView.deactivate(); - // at close we set all as displayed. While open we ignore updates of the numNewMsg in the list icon. - selectedDispute.getChatMessages().forEach(m -> m.setWasDisplayed(true)); - disputeManager.requestPersistence(); - chatPopupStage = null; - }); - - Scene scene = new Scene(pane); - CssTheme.loadSceneStyles(scene, preferences.getCssTheme(), false); - scene.addEventHandler(KeyEvent.KEY_RELEASED, ev -> { - if (ev.getCode() == KeyCode.ESCAPE) { - ev.consume(); - chatPopupStage.hide(); - } - }); - chatPopupStage.setScene(scene); - chatPopupStage.setOpacity(0); - chatPopupStage.show(); - - xPositionListener = (observable, oldValue, newValue) -> chatPopupStageXPosition = (double) newValue; - chatPopupStage.xProperty().addListener(xPositionListener); - yPositionListener = (observable, oldValue, newValue) -> chatPopupStageYPosition = (double) newValue; - chatPopupStage.yProperty().addListener(yPositionListener); - - if (chatPopupStageXPosition == -1) { - Window rootSceneWindow = rootScene.getWindow(); - double titleBarHeight = rootSceneWindow.getHeight() - rootScene.getHeight(); - chatPopupStage.setX(Math.round(rootSceneWindow.getX() + (owner.getWidth() - chatPopupStage.getWidth() / 4 * 3))); - chatPopupStage.setY(Math.round(rootSceneWindow.getY() + titleBarHeight + (owner.getHeight() - chatPopupStage.getHeight() / 4 * 3))); - } else { - chatPopupStage.setX(chatPopupStageXPosition); - chatPopupStage.setY(chatPopupStageYPosition); - } - - // Delay display to next render frame to avoid that the popup is first quickly displayed in default position - // and after a short moment in the correct position - UserThread.execute(() -> chatPopupStage.setOpacity(1)); + chatPopupStage = null; }); + + Scene scene = new Scene(pane); + CssTheme.loadSceneStyles(scene, preferences.getCssTheme(), false); + scene.addEventHandler(KeyEvent.KEY_RELEASED, ev -> { + if (ev.getCode() == KeyCode.ESCAPE) { + ev.consume(); + chatPopupStage.hide(); + } + }); + chatPopupStage.setScene(scene); + chatPopupStage.setOpacity(0); + chatPopupStage.show(); + + xPositionListener = (observable, oldValue, newValue) -> chatPopupStageXPosition = (double) newValue; + chatPopupStage.xProperty().addListener(xPositionListener); + yPositionListener = (observable, oldValue, newValue) -> chatPopupStageYPosition = (double) newValue; + chatPopupStage.yProperty().addListener(yPositionListener); + + if (chatPopupStageXPosition == -1) { + Window rootSceneWindow = rootScene.getWindow(); + double titleBarHeight = rootSceneWindow.getHeight() - rootScene.getHeight(); + chatPopupStage.setX(Math.round(rootSceneWindow.getX() + (owner.getWidth() - chatPopupStage.getWidth() / 4 * 3))); + chatPopupStage.setY(Math.round(rootSceneWindow.getY() + titleBarHeight + (owner.getHeight() - chatPopupStage.getHeight() / 4 * 3))); + } else { + chatPopupStage.setX(chatPopupStageXPosition); + chatPopupStage.setY(chatPopupStageYPosition); + } + + // Delay display to next render frame to avoid that the popup is first quickly displayed in default position + // and after a short moment in the correct position + UserThread.execute(() -> chatPopupStage.setOpacity(1)); } } diff --git a/p2p/src/main/java/bisq/network/p2p/network/Connection.java b/p2p/src/main/java/bisq/network/p2p/network/Connection.java index 6b4f8bab..4fd4ff77 100644 --- a/p2p/src/main/java/bisq/network/p2p/network/Connection.java +++ b/p2p/src/main/java/bisq/network/p2p/network/Connection.java @@ -112,7 +112,6 @@ public class Connection implements HasCapabilities, Runnable, MessageListener { private static final int MAX_PERMITTED_MESSAGE_SIZE = 10 * 1024 * 1024; // 10 MB (425 offers resulted in about 660 kb, mailbox msg will add more to it) offer has usually 2 kb, mailbox 3kb. //TODO decrease limits again after testing private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(180); - private static final int MAX_CONNECTION_THREADS = 10; public static int getPermittedMessageSize() { return PERMITTED_MESSAGE_SIZE; @@ -131,7 +130,6 @@ public class Connection implements HasCapabilities, Runnable, MessageListener { @Getter private final String uid; private final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(runnable -> new Thread(runnable, "Connection.java executor-service")); - private final ExecutorService connectionThreadPool = Executors.newFixedThreadPool(MAX_CONNECTION_THREADS); // holder of state shared between InputHandler and Connection @Getter