From f2e289d0a660347140a4bfe3cf991b553c0d6759 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 18:15:47 -0500 Subject: [PATCH 01/10] Add ArbitratorSelection based on tradestatistics --- .../availability/ArbitratorSelection.java | 78 +++++++++++++++++++ .../availability/ArbitratorSelectionTest.java | 68 ++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java create mode 100644 core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java diff --git a/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java b/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java new file mode 100644 index 0000000000..de1d5fd1a1 --- /dev/null +++ b/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java @@ -0,0 +1,78 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.offer.availability; + +import bisq.core.arbitration.ArbitratorManager; +import bisq.core.trade.statistics.TradeStatistics2; +import bisq.core.trade.statistics.TradeStatisticsManager; + +import bisq.common.util.Tuple2; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ArbitratorSelection { + public static String getLeastUsedArbitrator(TradeStatisticsManager tradeStatisticsManager, + ArbitratorManager arbitratorManager) { + List list = new ArrayList<>(tradeStatisticsManager.getObservableTradeStatisticsSet()); + list.sort(Comparator.comparing(TradeStatistics2::getTradeDate)); + Collections.reverse(list); + log.error("first " + list.get(0).getTradeDate()); + log.error("last " + list.get(list.size() - 1).getTradeDate()); + list = list.subList(0, 100); + log.error("list post " + list); + + List lastAddressesUsedInTrades = list.stream() + .filter(tradeStatistics2 -> tradeStatistics2.getExtraDataMap() != null) + .map(tradeStatistics2 -> tradeStatistics2.getExtraDataMap().get(TradeStatistics2.ARBITRATOR_ADDRESS)) + .collect(Collectors.toList()); + + List arbitrators = arbitratorManager.getArbitratorsObservableMap().values().stream() + .map(arbitrator -> arbitrator.getNodeAddress().getHostNameWithoutPostFix()) + .collect(Collectors.toList()); + + String result = getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + log.error("result: " + result); + return result; + } + + static String getLeastUsedArbitrator(List lastAddressesUsedInTrades, List arbitrators) { + List> arbitratorTuples = arbitrators.stream() + .map(e -> new Tuple2<>(e, new AtomicInteger(0))) + .collect(Collectors.toList()); + arbitratorTuples.forEach(tuple -> { + int count = (int) lastAddressesUsedInTrades.stream() + .filter(tuple.first::equals) + .mapToInt(e -> 1) + .count(); + tuple.second.set(count); + }); + + arbitratorTuples.sort(Comparator.comparing(e -> e.first)); + arbitratorTuples.sort(Comparator.comparingInt(e -> e.second.get())); + + return arbitratorTuples.get(0).first; + } +} diff --git a/core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java b/core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java new file mode 100644 index 0000000000..7c2c004315 --- /dev/null +++ b/core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java @@ -0,0 +1,68 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.offer.availability; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ArbitratorSelectionTest { + @Test + public void testGetLeastUsedArbitrator() { + // We get least used selected + List lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb1"); + List arbitrators = Arrays.asList("arb1", "arb2"); + String result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + assertEquals("arb2", result); + + // if all are same we use first according to alphanumeric sorting + lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb3"); + arbitrators = Arrays.asList("arb1", "arb2", "arb3"); + result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + assertEquals("arb1", result); + lastAddressesUsedInTrades = Arrays.asList("xxx", "ccc", "aaa"); + arbitrators = Arrays.asList("aaa", "ccc", "xxx"); + result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + assertEquals("aaa", result); + lastAddressesUsedInTrades = Arrays.asList("333", "000", "111"); + arbitrators = Arrays.asList("111", "333", "000"); + result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + assertEquals("000", result); + + // if winner is not in our arb list we use our arb from arbitrators even if never used in trades + lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb3"); + arbitrators = Arrays.asList("arb4"); + result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + assertEquals("arb4", result); + + // if winner (arb2) is not in our arb list we use our arb from arbitrators + lastAddressesUsedInTrades = Arrays.asList("arb1", "arb1", "arb1", "arb2"); + arbitrators = Arrays.asList("arb1"); + result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + assertEquals("arb1", result); + + // arb1 is used least + lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb2", "arb2", "arb1", "arb1", "arb2"); + arbitrators = Arrays.asList("arb1", "arb2"); + result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); + assertEquals("arb1", result); + } +} From 78a298cb138111c7b9602a642680623a73ba107a Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 18:16:34 -0500 Subject: [PATCH 02/10] Add ARBITRATOR_ADDRESS to extra map in trade statistics --- .../protocol/tasks/PublishTradeStatistics.java | 15 ++++++++++++--- .../core/trade/statistics/TradeStatistics2.java | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java index 9c3441c7b8..91d3c9c355 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java @@ -22,14 +22,18 @@ import bisq.core.offer.OfferPayload; import bisq.core.trade.Trade; import bisq.core.trade.statistics.TradeStatistics2; +import bisq.network.p2p.NodeAddress; + import bisq.common.taskrunner.TaskRunner; import java.util.HashMap; import java.util.Map; +import lombok.extern.slf4j.Slf4j; + import static com.google.common.base.Preconditions.checkNotNull; - +@Slf4j public class PublishTradeStatistics extends TradeTask { public PublishTradeStatistics(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); @@ -40,12 +44,17 @@ public class PublishTradeStatistics extends TradeTask { try { runInterceptHook(); if (trade.getDepositTx() != null) { - Map extraDataMap = null; + Map extraDataMap = new HashMap<>(); if (processModel.getReferralIdService().getOptionalReferralId().isPresent()) { - extraDataMap = new HashMap<>(); extraDataMap.put(OfferPayload.REFERRAL_ID, processModel.getReferralIdService().getOptionalReferralId().get()); } + NodeAddress arbitratorNodeAddress = trade.getArbitratorNodeAddress(); + if (arbitratorNodeAddress != null) { + String address = arbitratorNodeAddress.getHostNameWithoutPostFix(); + extraDataMap.put(TradeStatistics2.ARBITRATOR_ADDRESS, address); + } + Offer offer = trade.getOffer(); checkNotNull(offer, "offer must not ne null"); checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not ne null"); diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java index bd7ee28df8..c6e605c557 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java @@ -66,6 +66,8 @@ import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @Value public final class TradeStatistics2 implements LazyProcessedPayload, PersistableNetworkPayload, PersistableEnvelope, CapabilityRequiringPayload { + public static final String ARBITRATOR_ADDRESS = "arbAddr"; + private final OfferPayload.Direction direction; private final String baseCurrency; private final String counterCurrency; From 1e7dc5e95f3c6bbc4b72dc3acd6a90218ac6dc7c Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 18:17:15 -0500 Subject: [PATCH 03/10] Add arbitrator to OfferAvailabilityResponse --- common/src/main/proto/pb.proto | 1 + .../java/bisq/core/offer/OpenOfferManager.java | 12 +++++++++++- .../messages/OfferAvailabilityResponse.java | 17 +++++++++++++---- .../bisq/core/offer/OpenOfferManagerTest.java | 6 +++--- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/common/src/main/proto/pb.proto b/common/src/main/proto/pb.proto index 28eef44de6..2f8cba0ef4 100644 --- a/common/src/main/proto/pb.proto +++ b/common/src/main/proto/pb.proto @@ -124,6 +124,7 @@ message OfferAvailabilityResponse { AvailabilityResult availability_result = 2; repeated int32 supported_capabilities = 3; string uid = 4; + string selected_arbitrator = 5; } message RefreshOfferMessage { diff --git a/core/src/main/java/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/bisq/core/offer/OpenOfferManager.java index abedd9df1a..4f948d6547 100644 --- a/core/src/main/java/bisq/core/offer/OpenOfferManager.java +++ b/core/src/main/java/bisq/core/offer/OpenOfferManager.java @@ -17,10 +17,12 @@ package bisq.core.offer; +import bisq.core.arbitration.ArbitratorManager; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.TradeWalletService; import bisq.core.exceptions.TradePriceOutOfToleranceException; +import bisq.core.offer.availability.ArbitratorSelection; import bisq.core.offer.messages.OfferAvailabilityRequest; import bisq.core.offer.messages.OfferAvailabilityResponse; import bisq.core.offer.placeoffer.PlaceOfferModel; @@ -29,6 +31,7 @@ import bisq.core.provider.price.PriceFeedService; import bisq.core.trade.TradableList; import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.handlers.TransactionResultHandler; +import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.Preferences; import bisq.core.user.User; import bisq.core.util.Validator; @@ -100,6 +103,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe private final ClosedTradableManager closedTradableManager; private final PriceFeedService priceFeedService; private final Preferences preferences; + private final TradeStatisticsManager tradeStatisticsManager; + private final ArbitratorManager arbitratorManager; private final Storage> openOfferTradableListStorage; private final Map offersToBeEdited = new HashMap<>(); private boolean stopped; @@ -124,6 +129,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe PriceFeedService priceFeedService, Preferences preferences, PersistenceProtoResolver persistenceProtoResolver, + TradeStatisticsManager tradeStatisticsManager, + ArbitratorManager arbitratorManager, @Named(Storage.STORAGE_DIR) File storageDir) { this.keyRing = keyRing; this.user = user; @@ -135,6 +142,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe this.closedTradableManager = closedTradableManager; this.priceFeedService = priceFeedService; this.preferences = preferences; + this.tradeStatisticsManager = tradeStatisticsManager; + this.arbitratorManager = arbitratorManager; openOfferTradableListStorage = new Storage<>(storageDir, persistenceProtoResolver); @@ -586,7 +595,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe availabilityResult = AvailabilityResult.OFFER_TAKEN; } - OfferAvailabilityResponse offerAvailabilityResponse = new OfferAvailabilityResponse(request.offerId, availabilityResult); + String selectedArbitrator = ArbitratorSelection.getLeastUsedArbitrator(tradeStatisticsManager, arbitratorManager); + OfferAvailabilityResponse offerAvailabilityResponse = new OfferAvailabilityResponse(request.offerId, availabilityResult, selectedArbitrator); log.info("Send {} with offerId {} and uid {} to peer {}", offerAvailabilityResponse.getClass().getSimpleName(), offerAvailabilityResponse.getOfferId(), offerAvailabilityResponse.getUid(), peer); diff --git a/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java b/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java index dd66e4c661..4194684b85 100644 --- a/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java +++ b/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java @@ -46,12 +46,17 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup @Nullable private final List supportedCapabilities; - public OfferAvailabilityResponse(String offerId, AvailabilityResult availabilityResult) { + // Was introduced in v 0.9.0. Might be null if msg received from node with old version + @Nullable + private final String selectedArbitrator; + + public OfferAvailabilityResponse(String offerId, AvailabilityResult availabilityResult, String selectedArbitrator) { this(offerId, availabilityResult, Capabilities.getSupportedCapabilities(), Version.getP2PMessageVersion(), - UUID.randomUUID().toString()); + UUID.randomUUID().toString(), + selectedArbitrator); } @@ -63,10 +68,12 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup AvailabilityResult availabilityResult, @Nullable List supportedCapabilities, int messageVersion, - @Nullable String uid) { + @Nullable String uid, + @Nullable String selectedArbitrator) { super(messageVersion, offerId, uid); this.availabilityResult = availabilityResult; this.supportedCapabilities = supportedCapabilities; + this.selectedArbitrator = selectedArbitrator; } @Override @@ -77,6 +84,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup Optional.ofNullable(supportedCapabilities).ifPresent(e -> builder.addAllSupportedCapabilities(supportedCapabilities)); Optional.ofNullable(uid).ifPresent(e -> builder.setUid(uid)); + Optional.ofNullable(selectedArbitrator).ifPresent(e -> builder.setSelectedArbitrator(selectedArbitrator)); return getNetworkEnvelopeBuilder() .setOfferAvailabilityResponse(builder) @@ -88,6 +96,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup ProtoUtil.enumFromProto(AvailabilityResult.class, proto.getAvailabilityResult().name()), proto.getSupportedCapabilitiesList().isEmpty() ? null : proto.getSupportedCapabilitiesList(), messageVersion, - proto.getUid().isEmpty() ? null : proto.getUid()); + proto.getUid().isEmpty() ? null : proto.getUid(), + proto.getSelectedArbitrator().isEmpty() ? null : proto.getSelectedArbitrator()); } } diff --git a/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java b/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java index d94d8ba5ab..4abf33e219 100644 --- a/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java +++ b/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java @@ -37,7 +37,7 @@ public class OpenOfferManagerTest { final OpenOfferManager manager = new OpenOfferManager(null, null, p2PService, null, null, null, offerBookService, null, null, null, null, - null); + null, null, null); AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false); @@ -72,7 +72,7 @@ public class OpenOfferManagerTest { final OpenOfferManager manager = new OpenOfferManager(null, null, p2PService, null, null, null, offerBookService, null, null, null, null, - null); + null, null, null); AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false); @@ -99,7 +99,7 @@ public class OpenOfferManagerTest { final OpenOfferManager manager = new OpenOfferManager(null, null, p2PService, null, null, null, offerBookService, null, null, null, null, - null); + null, null, null); AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false); From 8bcefaa1358206a28096d1d2ebe0580f16ec421b Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 22:09:15 -0500 Subject: [PATCH 04/10] Implement new arbitrator selection rule --- common/src/main/proto/pb.proto | 2 +- .../core/arbitration/ArbitratorManager.java | 7 +++ .../p2p/seed/DefaultSeedNodeAddresses.java | 1 + .../main/java/bisq/core/offer/OpenOffer.java | 9 +++ .../bisq/core/offer/OpenOfferManager.java | 16 +++-- .../availability/ArbitratorSelection.java | 59 ++++++++++++++----- .../availability/OfferAvailabilityModel.java | 7 +++ .../ProcessOfferAvailabilityResponse.java | 10 ++++ .../messages/OfferAvailabilityResponse.java | 15 ++--- .../offer/placeoffer/PlaceOfferModel.java | 8 +++ .../placeoffer/tasks/CreateMakerFeeTx.java | 15 ++--- .../bisq/core/trade/BuyerAsMakerTrade.java | 9 ++- .../bisq/core/trade/BuyerAsTakerTrade.java | 8 ++- .../main/java/bisq/core/trade/BuyerTrade.java | 8 ++- .../bisq/core/trade/SellerAsMakerTrade.java | 8 ++- .../bisq/core/trade/SellerAsTakerTrade.java | 6 +- .../java/bisq/core/trade/SellerTrade.java | 8 ++- core/src/main/java/bisq/core/trade/Trade.java | 24 +++++++- .../java/bisq/core/trade/TradeManager.java | 15 ++++- .../trade/protocol/BuyerAsMakerProtocol.java | 2 - .../core/trade/protocol/ProcessModel.java | 10 +++- .../trade/protocol/SellerAsMakerProtocol.java | 2 - .../tasks/PublishTradeStatistics.java | 3 +- .../tasks/taker/CreateTakerFeeTx.java | 18 ++---- .../tasks/taker/TakerSelectArbitrator.java | 6 +- .../availability/ArbitratorSelectionTest.java | 16 ++--- .../bisq/desktop/main/debug/DebugView.java | 3 - 27 files changed, 209 insertions(+), 86 deletions(-) diff --git a/common/src/main/proto/pb.proto b/common/src/main/proto/pb.proto index 2f8cba0ef4..d6634adf91 100644 --- a/common/src/main/proto/pb.proto +++ b/common/src/main/proto/pb.proto @@ -124,7 +124,7 @@ message OfferAvailabilityResponse { AvailabilityResult availability_result = 2; repeated int32 supported_capabilities = 3; string uid = 4; - string selected_arbitrator = 5; + NodeAddress arbitrator = 5; } message RefreshOfferMessage { diff --git a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java b/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java index aed4ffbde6..dd2435fc8e 100644 --- a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java +++ b/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java @@ -55,6 +55,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @@ -381,4 +382,10 @@ public class ArbitratorManager { republishArbitratorTimer = null; } } + + public Optional getArbitratorByNodeAddress(NodeAddress nodeAddress) { + return arbitratorsObservableMap.containsKey(nodeAddress) ? + Optional.of(arbitratorsObservableMap.get(nodeAddress)) : + Optional.empty(); + } } diff --git a/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeAddresses.java b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeAddresses.java index 34c6d6dd18..c0079a8209 100644 --- a/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeAddresses.java +++ b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeAddresses.java @@ -91,6 +91,7 @@ class DefaultSeedNodeAddresses { // 4. Rename the directory with your local onion address // 5. Edit here your found onion address (new NodeAddress("YOUR_ONION.onion:8002") new NodeAddress("rxdkppp3vicnbgqt.onion:8002"), + new NodeAddress("4ie52dse64kaarxw.onion:8002"), // LTC mainnet new NodeAddress("acyvotgewx46pebw.onion:8003"), diff --git a/core/src/main/java/bisq/core/offer/OpenOffer.java b/core/src/main/java/bisq/core/offer/OpenOffer.java index 6e68c61eb5..bc754e9584 100644 --- a/core/src/main/java/bisq/core/offer/OpenOffer.java +++ b/core/src/main/java/bisq/core/offer/OpenOffer.java @@ -20,6 +20,8 @@ package bisq.core.offer; import bisq.core.trade.Tradable; import bisq.core.trade.TradableList; +import bisq.network.p2p.NodeAddress; + import bisq.common.Timer; import bisq.common.UserThread; import bisq.common.proto.ProtoUtil; @@ -31,8 +33,11 @@ import java.util.Date; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + @EqualsAndHashCode @Slf4j public final class OpenOffer implements Tradable { @@ -52,6 +57,10 @@ public final class OpenOffer implements Tradable { private final Offer offer; @Getter private State state; + @Getter + @Setter + @Nullable + private NodeAddress arbitratorNodeAddress; transient private Storage> storage; diff --git a/core/src/main/java/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/bisq/core/offer/OpenOfferManager.java index 4f948d6547..cadd983365 100644 --- a/core/src/main/java/bisq/core/offer/OpenOfferManager.java +++ b/core/src/main/java/bisq/core/offer/OpenOfferManager.java @@ -333,6 +333,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe tradeWalletService, bsqWalletService, offerBookService, + arbitratorManager, + tradeStatisticsManager, user); PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol( model, @@ -557,12 +559,17 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe try { Optional openOfferOptional = getOpenOfferById(request.offerId); AvailabilityResult availabilityResult; + NodeAddress arbitratorNodeAddress = null; if (openOfferOptional.isPresent()) { - if (openOfferOptional.get().getState() == OpenOffer.State.AVAILABLE) { - final Offer offer = openOfferOptional.get().getOffer(); - if (preferences.getIgnoreTradersList().stream().noneMatch(hostName -> hostName.equals(peer.getHostNameWithoutPostFix()))) { + OpenOffer openOffer = openOfferOptional.get(); + if (openOffer.getState() == OpenOffer.State.AVAILABLE) { + final Offer offer = openOffer.getOffer(); + if (preferences.getIgnoreTradersList().stream().noneMatch(hostName -> hostName.equals(peer.getHostName()))) { availabilityResult = AvailabilityResult.AVAILABLE; + arbitratorNodeAddress = ArbitratorSelection.getLeastUsedArbitrator(tradeStatisticsManager, arbitratorManager).getNodeAddress(); + openOffer.setArbitratorNodeAddress(arbitratorNodeAddress); + List acceptedArbitrators = user.getAcceptedArbitratorAddresses(); if (acceptedArbitrators != null && !acceptedArbitrators.isEmpty()) { // Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference @@ -595,8 +602,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe availabilityResult = AvailabilityResult.OFFER_TAKEN; } - String selectedArbitrator = ArbitratorSelection.getLeastUsedArbitrator(tradeStatisticsManager, arbitratorManager); - OfferAvailabilityResponse offerAvailabilityResponse = new OfferAvailabilityResponse(request.offerId, availabilityResult, selectedArbitrator); + OfferAvailabilityResponse offerAvailabilityResponse = new OfferAvailabilityResponse(request.offerId, availabilityResult, arbitratorNodeAddress); log.info("Send {} with offerId {} and uid {} to peer {}", offerAvailabilityResponse.getClass().getSimpleName(), offerAvailabilityResponse.getOfferId(), offerAvailabilityResponse.getUid(), peer); diff --git a/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java b/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java index de1d5fd1a1..e59d6bb271 100644 --- a/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java +++ b/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java @@ -17,62 +17,89 @@ package bisq.core.offer.availability; +import bisq.core.arbitration.Arbitrator; import bisq.core.arbitration.ArbitratorManager; import bisq.core.trade.statistics.TradeStatistics2; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.common.util.Tuple2; +import java.text.ParseException; +import java.text.SimpleDateFormat; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.List; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkArgument; + @Slf4j public class ArbitratorSelection { - public static String getLeastUsedArbitrator(TradeStatisticsManager tradeStatisticsManager, - ArbitratorManager arbitratorManager) { + @Getter + private static boolean isNewRuleActivated; + + static { + try { + //TODO set activation data to 1 month after release + Date activationDate = new SimpleDateFormat("dd/MM/yyyy").parse("1/10/2018"); + isNewRuleActivated = new Date().after(activationDate); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + public static Arbitrator getLeastUsedArbitrator(TradeStatisticsManager tradeStatisticsManager, + ArbitratorManager arbitratorManager) { + // We take last 100 entries from trade statistics List list = new ArrayList<>(tradeStatisticsManager.getObservableTradeStatisticsSet()); list.sort(Comparator.comparing(TradeStatistics2::getTradeDate)); Collections.reverse(list); - log.error("first " + list.get(0).getTradeDate()); - log.error("last " + list.get(list.size() - 1).getTradeDate()); - list = list.subList(0, 100); - log.error("list post " + list); + if (!list.isEmpty()) { + int max = Math.min(list.size(), 100); + list = list.subList(0, max); + } + // We stored only first 4 chars of arbitrators onion address List lastAddressesUsedInTrades = list.stream() .filter(tradeStatistics2 -> tradeStatistics2.getExtraDataMap() != null) .map(tradeStatistics2 -> tradeStatistics2.getExtraDataMap().get(TradeStatistics2.ARBITRATOR_ADDRESS)) .collect(Collectors.toList()); - List arbitrators = arbitratorManager.getArbitratorsObservableMap().values().stream() - .map(arbitrator -> arbitrator.getNodeAddress().getHostNameWithoutPostFix()) - .collect(Collectors.toList()); + Set arbitrators = arbitratorManager.getArbitratorsObservableMap().values().stream() + .map(arbitrator -> arbitrator.getNodeAddress().getHostName()) + .collect(Collectors.toSet()); String result = getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); - log.error("result: " + result); - return result; + + Optional optionalArbitrator = arbitratorManager.getArbitratorsObservableMap().values().stream() + .filter(e -> e.getNodeAddress().getHostName().equals(result)) + .findAny(); + checkArgument(optionalArbitrator.isPresent(), "optionalArbitrator has to be present"); + return optionalArbitrator.get(); } - static String getLeastUsedArbitrator(List lastAddressesUsedInTrades, List arbitrators) { + static String getLeastUsedArbitrator(List lastAddressesUsedInTrades, Set arbitrators) { + checkArgument(!arbitrators.isEmpty(), "arbitrators must nto be empty"); List> arbitratorTuples = arbitrators.stream() .map(e -> new Tuple2<>(e, new AtomicInteger(0))) .collect(Collectors.toList()); arbitratorTuples.forEach(tuple -> { int count = (int) lastAddressesUsedInTrades.stream() - .filter(tuple.first::equals) + .filter(tuple.first::startsWith) // we use only first 4 chars for comparing .mapToInt(e -> 1) .count(); tuple.second.set(count); }); - - arbitratorTuples.sort(Comparator.comparing(e -> e.first)); arbitratorTuples.sort(Comparator.comparingInt(e -> e.second.get())); - return arbitratorTuples.get(0).first; } } diff --git a/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java b/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java index 304987db16..5215664ae9 100644 --- a/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java +++ b/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java @@ -27,6 +27,9 @@ import bisq.common.crypto.PubKeyRing; import bisq.common.taskrunner.Model; import lombok.Getter; +import lombok.Setter; + +import javax.annotation.Nullable; public class OfferAvailabilityModel implements Model { @Getter @@ -38,6 +41,10 @@ public class OfferAvailabilityModel implements Model { private NodeAddress peerNodeAddress; // maker private OfferAvailabilityResponse message; + @Nullable + @Setter + @Getter + private NodeAddress selectedArbitrator; public OfferAvailabilityModel(Offer offer, PubKeyRing pubKeyRing, diff --git a/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java b/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java index e67b55295d..aa3a274f74 100644 --- a/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java +++ b/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java @@ -19,9 +19,12 @@ package bisq.core.offer.availability.tasks; import bisq.core.offer.AvailabilityResult; import bisq.core.offer.Offer; +import bisq.core.offer.availability.ArbitratorSelection; import bisq.core.offer.availability.OfferAvailabilityModel; import bisq.core.offer.messages.OfferAvailabilityResponse; +import bisq.network.p2p.NodeAddress; + import bisq.common.taskrunner.Task; import bisq.common.taskrunner.TaskRunner; @@ -39,6 +42,13 @@ public class ProcessOfferAvailabilityResponse extends Task supportedCapabilities, int messageVersion, @Nullable String uid, - @Nullable String selectedArbitrator) { + @Nullable NodeAddress arbitrator) { super(messageVersion, offerId, uid); this.availabilityResult = availabilityResult; this.supportedCapabilities = supportedCapabilities; - this.selectedArbitrator = selectedArbitrator; + this.arbitrator = arbitrator; } @Override @@ -84,7 +85,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup Optional.ofNullable(supportedCapabilities).ifPresent(e -> builder.addAllSupportedCapabilities(supportedCapabilities)); Optional.ofNullable(uid).ifPresent(e -> builder.setUid(uid)); - Optional.ofNullable(selectedArbitrator).ifPresent(e -> builder.setSelectedArbitrator(selectedArbitrator)); + Optional.ofNullable(arbitrator).ifPresent(e -> builder.setArbitrator(arbitrator.toProtoMessage())); return getNetworkEnvelopeBuilder() .setOfferAvailabilityResponse(builder) @@ -97,6 +98,6 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup proto.getSupportedCapabilitiesList().isEmpty() ? null : proto.getSupportedCapabilitiesList(), messageVersion, proto.getUid().isEmpty() ? null : proto.getUid(), - proto.getSelectedArbitrator().isEmpty() ? null : proto.getSelectedArbitrator()); + proto.hasArbitrator() ? NodeAddress.fromProto(proto.getArbitrator()) : null); } } diff --git a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java index 2b7f82dd20..6c67acf39d 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java @@ -17,11 +17,13 @@ package bisq.core.offer.placeoffer; +import bisq.core.arbitration.ArbitratorManager; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.TradeWalletService; import bisq.core.offer.Offer; import bisq.core.offer.OfferBookService; +import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.User; import bisq.common.taskrunner.Model; @@ -44,6 +46,8 @@ public class PlaceOfferModel implements Model { private final TradeWalletService tradeWalletService; private final BsqWalletService bsqWalletService; private final OfferBookService offerBookService; + private final ArbitratorManager arbitratorManager; + private final TradeStatisticsManager tradeStatisticsManager; private final User user; // Mutable @@ -59,6 +63,8 @@ public class PlaceOfferModel implements Model { TradeWalletService tradeWalletService, BsqWalletService bsqWalletService, OfferBookService offerBookService, + ArbitratorManager arbitratorManager, + TradeStatisticsManager tradeStatisticsManager, User user) { this.offer = offer; this.reservedFundsForOffer = reservedFundsForOffer; @@ -67,6 +73,8 @@ public class PlaceOfferModel implements Model { this.tradeWalletService = tradeWalletService; this.bsqWalletService = bsqWalletService; this.offerBookService = offerBookService; + this.arbitratorManager = arbitratorManager; + this.tradeStatisticsManager = tradeStatisticsManager; this.user = user; } diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java index 80c9f8b3ba..199ffb4802 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java @@ -26,10 +26,8 @@ import bisq.core.btc.wallet.TradeWalletService; import bisq.core.btc.wallet.TxBroadcaster; import bisq.core.btc.wallet.WalletService; import bisq.core.offer.Offer; +import bisq.core.offer.availability.ArbitratorSelection; import bisq.core.offer.placeoffer.PlaceOfferModel; -import bisq.core.trade.protocol.ArbitratorSelectionRule; - -import bisq.network.p2p.NodeAddress; import bisq.common.UserThread; import bisq.common.taskrunner.Task; @@ -43,8 +41,6 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkNotNull; - public class CreateMakerFeeTx extends Task { private static final Logger log = LoggerFactory.getLogger(CreateMakerFeeTx.class); private Transaction tradeFeeTx = null; @@ -64,11 +60,8 @@ public class CreateMakerFeeTx extends Task { String id = offer.getId(); BtcWalletService walletService = model.getWalletService(); - NodeAddress selectedArbitratorNodeAddress = ArbitratorSelectionRule.select(model.getUser().getAcceptedArbitratorAddresses(), - model.getOffer()); - log.debug("selectedArbitratorAddress " + selectedArbitratorNodeAddress); - Arbitrator selectedArbitrator = model.getUser().getAcceptedArbitratorByAddress(selectedArbitratorNodeAddress); - checkNotNull(selectedArbitrator, "selectedArbitrator must not be null at CreateOfferFeeTx"); + Arbitrator arbitrator = ArbitratorSelection.getLeastUsedArbitrator(model.getTradeStatisticsManager(), + model.getArbitratorManager()); Address fundingAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.OFFER_FUNDING).getAddress(); Address reservedForTradeAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress(); @@ -85,7 +78,7 @@ public class CreateMakerFeeTx extends Task { model.isUseSavingsWallet(), offer.getMakerFee(), offer.getTxFee(), - selectedArbitrator.getBtcAddress(), + arbitrator.getBtcAddress(), new TxBroadcaster.Callback() { @Override public void onSuccess(Transaction transaction) { diff --git a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java index f8651e7618..e77339f30a 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java @@ -35,6 +35,8 @@ import org.bitcoinj.core.Coin; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + @Slf4j public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade { @@ -46,10 +48,10 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade { Coin txFee, Coin takeOfferFee, boolean isCurrencyForTakerFeeBtc, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { - super(offer, txFee, takeOfferFee, isCurrencyForTakerFeeBtc, - storage, btcWalletService); + super(offer, txFee, takeOfferFee, isCurrencyForTakerFeeBtc, arbitratorNodeAddress, storage, btcWalletService); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -69,11 +71,12 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade { BtcWalletService btcWalletService, CoreProtoResolver coreProtoResolver) { PB.Trade proto = buyerAsMakerTradeProto.getTrade(); - final BuyerAsMakerTrade trade = new BuyerAsMakerTrade( + BuyerAsMakerTrade trade = new BuyerAsMakerTrade( Offer.fromProto(proto.getOffer()), Coin.valueOf(proto.getTxFeeAsLong()), Coin.valueOf(proto.getTakerFeeAsLong()), proto.getIsCurrencyForTakerFeeBtc(), + proto.hasArbitratorNodeAddress() ? NodeAddress.fromProto(proto.getArbitratorNodeAddress()) : null, storage, btcWalletService); diff --git a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java index 8de24f50c1..09c0dedc12 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java @@ -33,6 +33,8 @@ import org.bitcoinj.core.Coin; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkArgument; @Slf4j @@ -49,10 +51,11 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade { boolean isCurrencyForTakerFeeBtc, long tradePrice, NodeAddress tradingPeerNodeAddress, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { - super(offer, tradeAmount, txFee, takerFee, isCurrencyForTakerFeeBtc, tradePrice, - tradingPeerNodeAddress, storage, btcWalletService); + super(offer, tradeAmount, txFee, takerFee, isCurrencyForTakerFeeBtc, tradePrice, tradingPeerNodeAddress, + arbitratorNodeAddress, storage, btcWalletService); } @@ -81,6 +84,7 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade { proto.getIsCurrencyForTakerFeeBtc(), proto.getTradePrice(), proto.hasTradingPeerNodeAddress() ? NodeAddress.fromProto(proto.getTradingPeerNodeAddress()) : null, + proto.hasArbitratorNodeAddress() ? NodeAddress.fromProto(proto.getArbitratorNodeAddress()) : null, storage, btcWalletService), proto, diff --git a/core/src/main/java/bisq/core/trade/BuyerTrade.java b/core/src/main/java/bisq/core/trade/BuyerTrade.java index 028b906c76..4d4c297135 100644 --- a/core/src/main/java/bisq/core/trade/BuyerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerTrade.java @@ -31,6 +31,8 @@ import org.bitcoinj.core.Coin; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -43,19 +45,21 @@ public abstract class BuyerTrade extends Trade { boolean isCurrencyForTakerFeeBtc, long tradePrice, NodeAddress tradingPeerNodeAddress, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { super(offer, tradeAmount, txFee, takerFee, isCurrencyForTakerFeeBtc, tradePrice, - tradingPeerNodeAddress, storage, btcWalletService); + tradingPeerNodeAddress, arbitratorNodeAddress, storage, btcWalletService); } BuyerTrade(Offer offer, Coin txFee, Coin takerFee, boolean isCurrencyForTakerFeeBtc, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { - super(offer, txFee, takerFee, isCurrencyForTakerFeeBtc, storage, btcWalletService); + super(offer, txFee, takerFee, isCurrencyForTakerFeeBtc, arbitratorNodeAddress, storage, btcWalletService); } public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { diff --git a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java index cde34fa7b4..c78cd80bb0 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java @@ -35,6 +35,8 @@ import org.bitcoinj.core.Coin; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + @Slf4j public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade { @@ -46,9 +48,10 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade Coin txFee, Coin takerFee, boolean isCurrencyForTakerFeeBtc, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { - super(offer, txFee, takerFee, isCurrencyForTakerFeeBtc, storage, btcWalletService); + super(offer, txFee, takerFee, isCurrencyForTakerFeeBtc, arbitratorNodeAddress, storage, btcWalletService); } @@ -69,11 +72,12 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade BtcWalletService btcWalletService, CoreProtoResolver coreProtoResolver) { PB.Trade proto = sellerAsMakerTradeProto.getTrade(); - final SellerAsMakerTrade trade = new SellerAsMakerTrade( + SellerAsMakerTrade trade = new SellerAsMakerTrade( Offer.fromProto(proto.getOffer()), Coin.valueOf(proto.getTxFeeAsLong()), Coin.valueOf(proto.getTakerFeeAsLong()), proto.getIsCurrencyForTakerFeeBtc(), + proto.hasArbitratorNodeAddress() ? NodeAddress.fromProto(proto.getArbitratorNodeAddress()) : null, storage, btcWalletService); diff --git a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java index 620e792bdd..4d338dc6df 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java @@ -33,6 +33,8 @@ import org.bitcoinj.core.Coin; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkArgument; @Slf4j @@ -49,10 +51,11 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade boolean isCurrencyForTakerFeeBtc, long tradePrice, NodeAddress tradingPeerNodeAddress, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { super(offer, tradeAmount, txFee, takerFee, isCurrencyForTakerFeeBtc, tradePrice, - tradingPeerNodeAddress, storage, btcWalletService); + tradingPeerNodeAddress, arbitratorNodeAddress, storage, btcWalletService); } @@ -81,6 +84,7 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade proto.getIsCurrencyForTakerFeeBtc(), proto.getTradePrice(), proto.hasTradingPeerNodeAddress() ? NodeAddress.fromProto(proto.getTradingPeerNodeAddress()) : null, + proto.hasArbitratorNodeAddress() ? NodeAddress.fromProto(proto.getArbitratorNodeAddress()) : null, storage, btcWalletService), proto, diff --git a/core/src/main/java/bisq/core/trade/SellerTrade.java b/core/src/main/java/bisq/core/trade/SellerTrade.java index 6d67087ad0..0d56eadd85 100644 --- a/core/src/main/java/bisq/core/trade/SellerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerTrade.java @@ -31,6 +31,8 @@ import org.bitcoinj.core.Coin; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkArgument; @Slf4j @@ -42,19 +44,21 @@ public abstract class SellerTrade extends Trade { boolean isCurrencyForTakerFeeBtc, long tradePrice, NodeAddress tradingPeerNodeAddress, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { super(offer, tradeAmount, txFee, takerFee, isCurrencyForTakerFeeBtc, tradePrice, - tradingPeerNodeAddress, storage, btcWalletService); + tradingPeerNodeAddress, arbitratorNodeAddress, storage, btcWalletService); } SellerTrade(Offer offer, Coin txFee, Coin takeOfferFee, boolean isCurrencyForTakerFeeBtc, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { - super(offer, txFee, takeOfferFee, isCurrencyForTakerFeeBtc, storage, btcWalletService); + super(offer, txFee, takeOfferFee, isCurrencyForTakerFeeBtc, arbitratorNodeAddress, storage, btcWalletService); } public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index b3f398f934..38829fd4a6 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -18,6 +18,7 @@ package bisq.core.trade; import bisq.core.arbitration.Arbitrator; +import bisq.core.arbitration.ArbitratorManager; import bisq.core.arbitration.Mediator; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; @@ -29,18 +30,21 @@ import bisq.core.monetary.Volume; import bisq.core.offer.Offer; import bisq.core.offer.OfferUtil; import bisq.core.offer.OpenOfferManager; +import bisq.core.offer.availability.ArbitratorSelection; import bisq.core.payment.AccountAgeWitnessService; import bisq.core.payment.payload.PaymentMethod; import bisq.core.proto.CoreProtoResolver; import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.TradeProtocol; import bisq.core.trade.statistics.ReferralIdService; +import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.User; import bisq.network.p2p.DecryptedMessageWithPubKey; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; +import bisq.common.UserThread; import bisq.common.app.Log; import bisq.common.crypto.KeyRing; import bisq.common.crypto.PubKeyRing; @@ -373,6 +377,7 @@ public abstract class Trade implements Tradable, Model { Coin txFee, Coin takerFee, boolean isCurrencyForTakerFeeBtc, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { this.offer = offer; @@ -381,6 +386,7 @@ public abstract class Trade implements Tradable, Model { this.isCurrencyForTakerFeeBtc = isCurrencyForTakerFeeBtc; this.storage = storage; this.btcWalletService = btcWalletService; + this.arbitratorNodeAddress = arbitratorNodeAddress; txFeeAsLong = txFee.value; takerFeeAsLong = takerFee.value; @@ -398,10 +404,11 @@ public abstract class Trade implements Tradable, Model { boolean isCurrencyForTakerFeeBtc, long tradePrice, NodeAddress tradingPeerNodeAddress, + @Nullable NodeAddress arbitratorNodeAddress, Storage storage, BtcWalletService btcWalletService) { - this(offer, txFee, takerFee, isCurrencyForTakerFeeBtc, storage, btcWalletService); + this(offer, txFee, takerFee, isCurrencyForTakerFeeBtc, arbitratorNodeAddress, storage, btcWalletService); this.tradePrice = tradePrice; this.tradingPeerNodeAddress = tradingPeerNodeAddress; @@ -493,6 +500,8 @@ public abstract class Trade implements Tradable, Model { User user, FilterManager filterManager, AccountAgeWitnessService accountAgeWitnessService, + TradeStatisticsManager tradeStatisticsManager, + ArbitratorManager arbitratorManager, KeyRing keyRing, boolean useSavingsWallet, Coin fundsNeededForTrade) { @@ -508,10 +517,22 @@ public abstract class Trade implements Tradable, Model { user, filterManager, accountAgeWitnessService, + tradeStatisticsManager, + arbitratorManager, keyRing, useSavingsWallet, fundsNeededForTrade); + if (ArbitratorSelection.isNewRuleActivated()) { + Optional optionalArbitrator = processModel.getArbitratorManager().getArbitratorByNodeAddress(arbitratorNodeAddress); + if (optionalArbitrator.isPresent()) { + Arbitrator arbitrator = optionalArbitrator.get(); + arbitratorBtcPubKey = arbitrator.getBtcPubKey(); + arbitratorPubKeyRing = arbitrator.getPubKeyRing(); + UserThread.runAfter(() -> this.persist(), 1); + } + } + createTradeProtocol(); // If we have already received a msg we apply it. @@ -666,6 +687,7 @@ public abstract class Trade implements Tradable, Model { errorMessageProperty.set(errorMessage); } + //TODO can be removed after new rule is actiavted @SuppressWarnings("NullableProblems") public void setArbitratorNodeAddress(NodeAddress arbitratorNodeAddress) { this.arbitratorNodeAddress = arbitratorNodeAddress; diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 436cd72d9f..e4cb74d467 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -17,6 +17,7 @@ package bisq.core.trade; +import bisq.core.arbitration.ArbitratorManager; import bisq.core.btc.exceptions.AddressEntryException; import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BsqWalletService; @@ -116,6 +117,7 @@ public class TradeManager implements PersistedDataHost { private final TradeStatisticsManager tradeStatisticsManager; private final ReferralIdService referralIdService; private final AccountAgeWitnessService accountAgeWitnessService; + private final ArbitratorManager arbitratorManager; private final Clock clock; private final Storage> tradableListStorage; @@ -149,6 +151,7 @@ public class TradeManager implements PersistedDataHost { ReferralIdService referralIdService, PersistenceProtoResolver persistenceProtoResolver, AccountAgeWitnessService accountAgeWitnessService, + ArbitratorManager arbitratorManager, Clock clock, @Named(Storage.STORAGE_DIR) File storageDir) { this.user = user; @@ -165,6 +168,7 @@ public class TradeManager implements PersistedDataHost { this.tradeStatisticsManager = tradeStatisticsManager; this.referralIdService = referralIdService; this.accountAgeWitnessService = accountAgeWitnessService; + this.arbitratorManager = arbitratorManager; this.clock = clock; tradableListStorage = new Storage<>(storageDir, persistenceProtoResolver); @@ -313,14 +317,16 @@ public class TradeManager implements PersistedDataHost { Optional openOfferOptional = openOfferManager.getOpenOfferById(payDepositRequest.getTradeId()); if (openOfferOptional.isPresent() && openOfferOptional.get().getState() == OpenOffer.State.AVAILABLE) { - Offer offer = openOfferOptional.get().getOffer(); - openOfferManager.reserveOpenOffer(openOfferOptional.get()); + OpenOffer openOffer = openOfferOptional.get(); + Offer offer = openOffer.getOffer(); + openOfferManager.reserveOpenOffer(openOffer); Trade trade; if (offer.isBuyOffer()) trade = new BuyerAsMakerTrade(offer, Coin.valueOf(payDepositRequest.getTxFee()), Coin.valueOf(payDepositRequest.getTakerFee()), payDepositRequest.isCurrencyForTakerFeeBtc(), + openOffer.getArbitratorNodeAddress(), tradableListStorage, btcWalletService); else @@ -328,6 +334,7 @@ public class TradeManager implements PersistedDataHost { Coin.valueOf(payDepositRequest.getTxFee()), Coin.valueOf(payDepositRequest.getTakerFee()), payDepositRequest.isCurrencyForTakerFeeBtc(), + openOffer.getArbitratorNodeAddress(), tradableListStorage, btcWalletService); @@ -356,6 +363,8 @@ public class TradeManager implements PersistedDataHost { user, filterManager, accountAgeWitnessService, + tradeStatisticsManager, + arbitratorManager, keyRing, useSavingsWallet, fundsNeededForTrade); @@ -436,6 +445,7 @@ public class TradeManager implements PersistedDataHost { isCurrencyForTakerFeeBtc, tradePrice, model.getPeerNodeAddress(), + model.getSelectedArbitrator(), tradableListStorage, btcWalletService); else @@ -446,6 +456,7 @@ public class TradeManager implements PersistedDataHost { isCurrencyForTakerFeeBtc, tradePrice, model.getPeerNodeAddress(), + model.getSelectedArbitrator(), tradableListStorage, btcWalletService); diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 4784a7e816..1a064376dc 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -36,7 +36,6 @@ import bisq.core.trade.protocol.tasks.maker.MakerProcessDepositTxPublishedMessag import bisq.core.trade.protocol.tasks.maker.MakerProcessPayDepositRequest; import bisq.core.trade.protocol.tasks.maker.MakerSendPublishDepositTxRequest; import bisq.core.trade.protocol.tasks.maker.MakerSetupDepositTxListener; -import bisq.core.trade.protocol.tasks.maker.MakerVerifyArbitratorSelection; import bisq.core.trade.protocol.tasks.maker.MakerVerifyMediatorSelection; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerAccount; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; @@ -132,7 +131,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol taskRunner.addTasks( MakerProcessPayDepositRequest.class, CheckIfPeerIsBanned.class, - MakerVerifyArbitratorSelection.class, MakerVerifyMediatorSelection.class, MakerVerifyTakerAccount.class, VerifyPeersAccountAgeWitness.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index 78b798086d..41a2c9b4fd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -18,9 +18,10 @@ package bisq.core.trade.protocol; import bisq.core.app.BisqEnvironment; +import bisq.core.arbitration.ArbitratorManager; +import bisq.core.btc.model.RawTransactionInput; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; -import bisq.core.btc.model.RawTransactionInput; import bisq.core.btc.wallet.TradeWalletService; import bisq.core.filter.FilterManager; import bisq.core.network.MessageState; @@ -35,6 +36,7 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.statistics.ReferralIdService; +import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.User; import bisq.network.p2p.AckMessage; @@ -82,6 +84,8 @@ public class ProcessModel implements Model, PersistablePayload { transient private User user; transient private FilterManager filterManager; transient private AccountAgeWitnessService accountAgeWitnessService; + transient private TradeStatisticsManager tradeStatisticsManager; + transient private ArbitratorManager arbitratorManager; transient private KeyRing keyRing; transient private P2PService p2PService; transient private ReferralIdService referralIdService; @@ -229,6 +233,8 @@ public class ProcessModel implements Model, PersistablePayload { User user, FilterManager filterManager, AccountAgeWitnessService accountAgeWitnessService, + TradeStatisticsManager tradeStatisticsManager, + ArbitratorManager arbitratorManager, KeyRing keyRing, boolean useSavingsWallet, Coin fundsNeededForTrade) { @@ -242,6 +248,8 @@ public class ProcessModel implements Model, PersistablePayload { this.user = user; this.filterManager = filterManager; this.accountAgeWitnessService = accountAgeWitnessService; + this.tradeStatisticsManager = tradeStatisticsManager; + this.arbitratorManager = arbitratorManager; this.keyRing = keyRing; this.p2PService = p2PService; this.useSavingsWallet = useSavingsWallet; diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index ec8a40da17..6f586f303f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -32,7 +32,6 @@ import bisq.core.trade.protocol.tasks.maker.MakerProcessDepositTxPublishedMessag import bisq.core.trade.protocol.tasks.maker.MakerProcessPayDepositRequest; import bisq.core.trade.protocol.tasks.maker.MakerSendPublishDepositTxRequest; import bisq.core.trade.protocol.tasks.maker.MakerSetupDepositTxListener; -import bisq.core.trade.protocol.tasks.maker.MakerVerifyArbitratorSelection; import bisq.core.trade.protocol.tasks.maker.MakerVerifyMediatorSelection; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerAccount; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; @@ -127,7 +126,6 @@ public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtoc taskRunner.addTasks( MakerProcessPayDepositRequest.class, CheckIfPeerIsBanned.class, - MakerVerifyArbitratorSelection.class, MakerVerifyMediatorSelection.class, MakerVerifyTakerAccount.class, VerifyPeersAccountAgeWitness.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java index 91d3c9c355..4c4612f5b6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java @@ -51,7 +51,8 @@ public class PublishTradeStatistics extends TradeTask { NodeAddress arbitratorNodeAddress = trade.getArbitratorNodeAddress(); if (arbitratorNodeAddress != null) { - String address = arbitratorNodeAddress.getHostNameWithoutPostFix(); + // The first 4 chars are sufficient to identify an arbitrator + String address = arbitratorNodeAddress.getHostName().substring(0, 4); extraDataMap.put(TradeStatistics2.ARBITRATOR_ADDRESS, address); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java index 4a67933a29..e0aa7b03e7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java @@ -25,12 +25,9 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.TradeWalletService; import bisq.core.btc.wallet.TxBroadcaster; import bisq.core.btc.wallet.WalletService; +import bisq.core.offer.availability.ArbitratorSelection; import bisq.core.trade.Trade; -import bisq.core.trade.protocol.ArbitratorSelectionRule; import bisq.core.trade.protocol.tasks.TradeTask; -import bisq.core.user.User; - -import bisq.network.p2p.NodeAddress; import bisq.common.UserThread; import bisq.common.taskrunner.TaskRunner; @@ -42,8 +39,6 @@ import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkNotNull; - @Slf4j public class CreateTakerFeeTx extends TradeTask { private Transaction tradeFeeTx; @@ -58,13 +53,8 @@ public class CreateTakerFeeTx extends TradeTask { try { runInterceptHook(); - User user = processModel.getUser(); - NodeAddress selectedArbitratorNodeAddress = ArbitratorSelectionRule.select(user.getAcceptedArbitratorAddresses(), - processModel.getOffer()); - log.debug("selectedArbitratorAddress " + selectedArbitratorNodeAddress); - Arbitrator selectedArbitrator = user.getAcceptedArbitratorByAddress(selectedArbitratorNodeAddress); - checkNotNull(selectedArbitrator, "selectedArbitrator must not be null at CreateTakeOfferFeeTx"); - + Arbitrator arbitrator = ArbitratorSelection.getLeastUsedArbitrator(processModel.getTradeStatisticsManager(), + processModel.getArbitratorManager()); BtcWalletService walletService = processModel.getBtcWalletService(); String id = processModel.getOffer().getId(); AddressEntry addressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.OFFER_FUNDING); @@ -83,7 +73,7 @@ public class CreateTakerFeeTx extends TradeTask { processModel.isUseSavingsWallet(), trade.getTakerFee(), trade.getTxFee(), - selectedArbitrator.getBtcAddress(), + arbitrator.getBtcAddress(), new TxBroadcaster.Callback() { @Override public void onSuccess(Transaction transaction) { diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSelectArbitrator.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSelectArbitrator.java index 6f0fa0f247..4785141d24 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSelectArbitrator.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSelectArbitrator.java @@ -17,6 +17,7 @@ package bisq.core.trade.protocol.tasks.taker; +import bisq.core.offer.availability.ArbitratorSelection; import bisq.core.trade.Trade; import bisq.core.trade.protocol.ArbitratorSelectionRule; import bisq.core.trade.protocol.tasks.TradeTask; @@ -37,7 +38,10 @@ public class TakerSelectArbitrator extends TradeTask { try { runInterceptHook(); - trade.setArbitratorNodeAddress(ArbitratorSelectionRule.select(processModel.getUser().getAcceptedArbitratorAddresses(), processModel.getOffer())); + // TODO can be removed after new rule is activated + if (!ArbitratorSelection.isNewRuleActivated()) { + trade.setArbitratorNodeAddress(ArbitratorSelectionRule.select(processModel.getUser().getAcceptedArbitratorAddresses(), processModel.getOffer())); + } complete(); } catch (Throwable t) { diff --git a/core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java b/core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java index 7c2c004315..428f1246bf 100644 --- a/core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java +++ b/core/src/test/java/bisq/core/offer/availability/ArbitratorSelectionTest.java @@ -18,7 +18,9 @@ package bisq.core.offer.availability; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.junit.Test; @@ -29,39 +31,39 @@ public class ArbitratorSelectionTest { public void testGetLeastUsedArbitrator() { // We get least used selected List lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb1"); - List arbitrators = Arrays.asList("arb1", "arb2"); + Set arbitrators = new HashSet<>(Arrays.asList("arb1", "arb2")); String result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); assertEquals("arb2", result); // if all are same we use first according to alphanumeric sorting lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb3"); - arbitrators = Arrays.asList("arb1", "arb2", "arb3"); + arbitrators = new HashSet<>(Arrays.asList("arb1", "arb2", "arb3")); result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); assertEquals("arb1", result); lastAddressesUsedInTrades = Arrays.asList("xxx", "ccc", "aaa"); - arbitrators = Arrays.asList("aaa", "ccc", "xxx"); + arbitrators = new HashSet<>(Arrays.asList("aaa", "ccc", "xxx")); result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); assertEquals("aaa", result); lastAddressesUsedInTrades = Arrays.asList("333", "000", "111"); - arbitrators = Arrays.asList("111", "333", "000"); + arbitrators = new HashSet<>(Arrays.asList("111", "333", "000")); result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); assertEquals("000", result); // if winner is not in our arb list we use our arb from arbitrators even if never used in trades lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb3"); - arbitrators = Arrays.asList("arb4"); + arbitrators = new HashSet<>(Arrays.asList("arb4")); result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); assertEquals("arb4", result); // if winner (arb2) is not in our arb list we use our arb from arbitrators lastAddressesUsedInTrades = Arrays.asList("arb1", "arb1", "arb1", "arb2"); - arbitrators = Arrays.asList("arb1"); + arbitrators = new HashSet<>(Arrays.asList("arb1")); result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); assertEquals("arb1", result); // arb1 is used least lastAddressesUsedInTrades = Arrays.asList("arb1", "arb2", "arb2", "arb2", "arb1", "arb1", "arb2"); - arbitrators = Arrays.asList("arb1", "arb2"); + arbitrators = new HashSet<>(Arrays.asList("arb1", "arb2")); result = ArbitratorSelection.getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators); assertEquals("arb1", result); } diff --git a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java index 19ef6db449..328ea019be 100644 --- a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java +++ b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java @@ -40,7 +40,6 @@ import bisq.core.trade.protocol.tasks.maker.MakerProcessDepositTxPublishedMessag import bisq.core.trade.protocol.tasks.maker.MakerProcessPayDepositRequest; import bisq.core.trade.protocol.tasks.maker.MakerSendPublishDepositTxRequest; import bisq.core.trade.protocol.tasks.maker.MakerSetupDepositTxListener; -import bisq.core.trade.protocol.tasks.maker.MakerVerifyArbitratorSelection; import bisq.core.trade.protocol.tasks.maker.MakerVerifyMediatorSelection; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerAccount; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; @@ -108,7 +107,6 @@ public class DebugView extends InitializableView { FXCollections.observableArrayList(Arrays.asList( MakerProcessPayDepositRequest.class, CheckIfPeerIsBanned.class, - MakerVerifyArbitratorSelection.class, MakerVerifyMediatorSelection.class, MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, @@ -187,7 +185,6 @@ public class DebugView extends InitializableView { FXCollections.observableArrayList(Arrays.asList( MakerProcessPayDepositRequest.class, CheckIfPeerIsBanned.class, - MakerVerifyArbitratorSelection.class, MakerVerifyMediatorSelection.class, MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, From 308d9d63a45c38be818bd3c03016ac88aee79d60 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 22:11:43 -0500 Subject: [PATCH 05/10] Remove autoSelectArbitratorsCheckBox --- .../main/settings/preferences/PreferencesView.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java index bf9bc87ef9..8924d4237b 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java @@ -94,7 +94,7 @@ public class PreferencesView extends ActivatableViewAndModel preferredTradeCurrencyComboBox; private ComboBox selectBaseCurrencyNetworkComboBox; - private CheckBox useAnimationsCheckBox, autoSelectArbitratorsCheckBox, avoidStandbyModeCheckBox, + private CheckBox useAnimationsCheckBox, avoidStandbyModeCheckBox, showOwnOffersInOfferBook, sortMarketCurrenciesNumericallyCheckBox, useCustomFeeCheckbox; private int gridRow = 0; private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, referralIdInputTextField; @@ -180,7 +180,7 @@ public class PreferencesView extends ActivatableViewAndModel deviationInputTextField.setText(formatter.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); }; - // autoSelectArbitrators - autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, - Res.get("setting.preferences.autoSelectArbitrators"), "").second; - // ignoreTraders ignoreTradersListInputTextField = addLabelInputTextField(root, ++gridRow, Res.get("setting.preferences.ignorePeers")).second; @@ -649,9 +645,6 @@ public class PreferencesView extends ActivatableViewAndModel preferences.resetDontShowAgain()); - autoSelectArbitratorsCheckBox.setSelected(preferences.isAutoSelectArbitrators()); - autoSelectArbitratorsCheckBox.setOnAction(e -> preferences.setAutoSelectArbitrators(autoSelectArbitratorsCheckBox.isSelected())); - // We use opposite property (useStandbyMode) in preferences to have the default value (false) set as we want it, // so users who update gets set avoidStandbyMode=true (useStandbyMode=false) avoidStandbyModeCheckBox.setSelected(!preferences.isUseStandbyMode()); @@ -703,7 +696,6 @@ public class PreferencesView extends ActivatableViewAndModel Date: Tue, 2 Oct 2018 22:27:01 -0500 Subject: [PATCH 06/10] Add arbitrator_node_address to PB --- common/src/main/proto/pb.proto | 1 + .../src/main/java/bisq/core/offer/OpenOffer.java | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/common/src/main/proto/pb.proto b/common/src/main/proto/pb.proto index d6634adf91..f32616fdd2 100644 --- a/common/src/main/proto/pb.proto +++ b/common/src/main/proto/pb.proto @@ -1050,6 +1050,7 @@ message OpenOffer { Offer offer = 1; State state = 2; + NodeAddress arbitrator_node_address = 3; } message Tradable { diff --git a/core/src/main/java/bisq/core/offer/OpenOffer.java b/core/src/main/java/bisq/core/offer/OpenOffer.java index bc754e9584..cc8999ecc1 100644 --- a/core/src/main/java/bisq/core/offer/OpenOffer.java +++ b/core/src/main/java/bisq/core/offer/OpenOffer.java @@ -30,6 +30,7 @@ import bisq.common.storage.Storage; import io.bisq.generated.protobuffer.PB; import java.util.Date; +import java.util.Optional; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -74,9 +75,10 @@ public final class OpenOffer implements Tradable { // PROTO BUFFER /////////////////////////////////////////////////////////////////////////////////////////// - private OpenOffer(Offer offer, State state) { + private OpenOffer(Offer offer, State state, @Nullable NodeAddress arbitratorNodeAddress) { this.offer = offer; this.state = state; + this.arbitratorNodeAddress = arbitratorNodeAddress; if (this.state == State.RESERVED) setState(State.AVAILABLE); @@ -84,15 +86,19 @@ public final class OpenOffer implements Tradable { @Override public PB.Tradable toProtoMessage() { - return PB.Tradable.newBuilder().setOpenOffer(PB.OpenOffer.newBuilder() + PB.OpenOffer.Builder builder = PB.OpenOffer.newBuilder() .setOffer(offer.toProtoMessage()) - .setState(PB.OpenOffer.State.valueOf(state.name()))) - .build(); + .setState(PB.OpenOffer.State.valueOf(state.name())); + + Optional.ofNullable(arbitratorNodeAddress).ifPresent(nodeAddress -> builder.setArbitratorNodeAddress(nodeAddress.toProtoMessage())); + + return PB.Tradable.newBuilder().setOpenOffer(builder).build(); } public static Tradable fromProto(PB.OpenOffer proto) { return new OpenOffer(Offer.fromProto(proto.getOffer()), - ProtoUtil.enumFromProto(OpenOffer.State.class, proto.getState().name())); + ProtoUtil.enumFromProto(OpenOffer.State.class, proto.getState().name()), + proto.hasArbitratorNodeAddress() ? NodeAddress.fromProto(proto.getArbitratorNodeAddress()) : null); } From cb17b008a3f331335cda39810a1a88568c2257c2 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 22:35:16 -0500 Subject: [PATCH 07/10] Remove arbitrator selection view --- core/src/main/java/bisq/core/user/User.java | 1 + .../resources/i18n/displayStrings.properties | 7 +- .../ArbitratorListItem.java | 62 ---- .../ArbitratorSelectionView.fxml | 34 -- .../ArbitratorSelectionView.java | 348 ------------------ .../ArbitratorSelectionViewModel.java | 175 --------- .../account/settings/AccountSettingsView.java | 10 +- .../desktop/main/offer/MutableOfferView.java | 15 +- .../main/offer/offerbook/OfferBookView.java | 11 +- .../main/offer/takeoffer/TakeOfferView.java | 12 +- .../overlays/windows/OfferDetailsWindow.java | 8 +- 11 files changed, 12 insertions(+), 671 deletions(-) delete mode 100644 desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorListItem.java delete mode 100644 desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.fxml delete mode 100644 desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.java delete mode 100644 desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java diff --git a/core/src/main/java/bisq/core/user/User.java b/core/src/main/java/bisq/core/user/User.java index bbb42653ff..f570c6b88f 100644 --- a/core/src/main/java/bisq/core/user/User.java +++ b/core/src/main/java/bisq/core/user/User.java @@ -380,6 +380,7 @@ public final class User implements PersistedDataHost { return userPayload.getRegisteredMediator(); } + //TODO @Nullable public List getAcceptedArbitrators() { return userPayload.getAcceptedArbitrators(); diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index a7e5afd556..4fbd17fe65 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -828,7 +828,6 @@ settings.tab.about=About setting.preferences.general=General preferences setting.preferences.explorer=Bitcoin block explorer: setting.preferences.deviation=Max. deviation from market price: -setting.preferences.autoSelectArbitrators=Auto select arbitrators: setting.preferences.avoidStandbyMode=Avoid standby mode: setting.preferences.deviationToLarge=Values higher than {0}% are not allowed. setting.preferences.txFee=Withdrawal transaction fee (satoshis/byte): @@ -941,7 +940,6 @@ Bisq is a decentralized exchange – meaning all of your data is kept on your co account.menu.paymentAccount=National currency accounts account.menu.altCoinsAccountView=Altcoin accounts -account.menu.arbitratorSelection=Arbitrator selection account.menu.password=Wallet password account.menu.seedWords=Wallet seed account.menu.backup=Backup @@ -1625,7 +1623,6 @@ offerDetailsWindow.agree=I agree: offerDetailsWindow.tac=Terms and conditions: offerDetailsWindow.confirm.maker=Confirm: Place offer to {0} bitcoin offerDetailsWindow.confirm.taker=Confirm: Take offer to {0} bitcoin -offerDetailsWindow.warn.noArbitrator=You have no arbitrator selected.\nPlease select at least one arbitrator. offerDetailsWindow.creationDate=Creation date: offerDetailsWindow.makersOnion=Maker's onion address: @@ -1759,8 +1756,7 @@ popup.warning.tradePeriod.halfReached=Your trade with ID {0} has reached the hal popup.warning.tradePeriod.ended=Your trade with ID {0} has reached the max. allowed trading period and is not completed.\n\nThe trade period ended on {1}\n\nPlease check your trade at \"Portfolio/Open trades\" for contacting the arbitrator. popup.warning.noTradingAccountSetup.headline=You have not setup a trading account popup.warning.noTradingAccountSetup.msg=You need to setup a national currency or altcoin account before you can create an offer.\nDo you want to setup an account? -popup.warning.noArbitratorSelected.headline=You don't have an arbitrator selected. -popup.warning.noArbitratorSelected.msg=You need to setup at least one arbitrator to be able to trade.\nDo you want to do this now? +popup.warning.noArbitratorsAvailable=There are no arbitrators available. popup.warning.notFullyConnected=You need to wait until you are fully connected to the network.\nThat might take up to about 2 minutes at startup. popup.warning.notSufficientConnectionsToBtcNetwork=You need to wait until you have at least {0} connections to the Bitcoin network. popup.warning.downloadNotComplete=You need to wait until the download of missing Bitcoin blocks is complete. @@ -1928,7 +1924,6 @@ txIdTextField.blockExplorerIcon.tooltip=Open a blockchain explorer with that tra navigation.account=\"Account\" navigation.account.walletSeed=\"Account/Wallet seed\" -navigation.arbitratorSelection=\"Arbitrator selection\" navigation.funds.availableForWithdrawal=\"Fund/Send funds\" navigation.portfolio.myOpenOffers=\"Portfolio/My open offers\" navigation.portfolio.pending=\"Portfolio/Open trades\" diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorListItem.java b/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorListItem.java deleted file mode 100644 index 0bd5967a2a..0000000000 --- a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorListItem.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.desktop.main.account.content.arbitratorselection; - -import bisq.core.arbitration.Arbitrator; -import bisq.core.util.BSFormatter; - -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; - -import java.util.Date; - -public class ArbitratorListItem { - public final Arbitrator arbitrator; - private final BSFormatter formatter; - private final BooleanProperty isSelected = new SimpleBooleanProperty(); - - public ArbitratorListItem(Arbitrator arbitrator, BSFormatter formatter) { - this.arbitrator = arbitrator; - this.formatter = formatter; - } - - public String getAddressString() { - return arbitrator != null ? arbitrator.getNodeAddress().getFullAddress() : ""; - } - - public String getLanguageCodes() { - return arbitrator != null && arbitrator.getLanguageCodes() != null ? - formatter.languageCodesToString(arbitrator.getLanguageCodes()) : ""; - } - - public String getRegistrationDate() { - return arbitrator != null ? formatter.formatDate(new Date(arbitrator.getRegistrationDate())) : ""; - } - - public boolean getIsSelected() { - return isSelected.get(); - } - - public BooleanProperty isSelectedProperty() { - return isSelected; - } - - public void setIsSelected(boolean isSelected) { - this.isSelected.set(isSelected); - } -} diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.fxml b/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.fxml deleted file mode 100644 index 1cd64e9105..0000000000 --- a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.fxml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.java b/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.java deleted file mode 100644 index b06fc5094c..0000000000 --- a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionView.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.desktop.main.account.content.arbitratorselection; - -import bisq.desktop.common.view.ActivatableViewAndModel; -import bisq.desktop.common.view.FxmlView; -import bisq.desktop.components.AutoTooltipButton; -import bisq.desktop.components.AutoTooltipCheckBox; -import bisq.desktop.components.AutoTooltipLabel; -import bisq.desktop.components.AutoTooltipTableColumn; -import bisq.desktop.components.TableGroupHeadline; -import bisq.desktop.main.overlays.popups.Popup; -import bisq.desktop.util.FormBuilder; -import bisq.desktop.util.ImageUtil; -import bisq.desktop.util.Layout; - -import bisq.core.locale.LanguageUtil; -import bisq.core.locale.Res; - -import bisq.common.UserThread; -import bisq.common.util.Tuple2; - -import javax.inject.Inject; - -import javafx.scene.control.Button; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; -import javafx.scene.control.TableCell; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableRow; -import javafx.scene.control.TableView; -import javafx.scene.control.Tooltip; -import javafx.scene.image.ImageView; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.GridPane; - -import javafx.geometry.HPos; -import javafx.geometry.Insets; -import javafx.geometry.VPos; - -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.ReadOnlyObjectWrapper; -import javafx.beans.value.ChangeListener; - -import javafx.collections.ListChangeListener; - -import javafx.util.Callback; -import javafx.util.StringConverter; - -import static bisq.desktop.util.FormBuilder.addCheckBox; -import static bisq.desktop.util.FormBuilder.addTitledGroupBg; - -@FxmlView -public class ArbitratorSelectionView extends ActivatableViewAndModel { - - private final ArbitratorSelectionViewModel model; - - private ListView languagesListView; - private ComboBox languageComboBox; - private TableView tableView; - private int gridRow = 0; - private CheckBox autoSelectAllMatchingCheckBox; - private ListChangeListener listChangeListener; - private ListChangeListener languageCodesListChangeListener; - private ChangeListener isSelectedChangeListener; - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor, lifecycle - /////////////////////////////////////////////////////////////////////////////////////////// - - @Inject - private ArbitratorSelectionView(ArbitratorSelectionViewModel model) { - super(model); - this.model = model; - } - - @Override - public void initialize() { - addLanguageGroup(); - addArbitratorsGroup(); - listChangeListener = c -> languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2); - } - - @Override - protected void activate() { - languagesListView.getItems().addListener(listChangeListener); - languageComboBox.setItems(model.allLanguageCodes); - languagesListView.setItems(model.languageCodes); - languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2); - - tableView.setItems(model.arbitratorListItems); - // TODO should scale with stage resize - tableView.setPrefHeight(200); - - autoSelectAllMatchingCheckBox.setSelected(model.getAutoSelectArbitrators()); - } - - @Override - protected void deactivate() { - languagesListView.getItems().removeListener(listChangeListener); - if (languageCodesListChangeListener != null) - model.languageCodes.removeListener(languageCodesListChangeListener); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // UI actions - /////////////////////////////////////////////////////////////////////////////////////////// - - private void onAddLanguage() { - model.onAddLanguage(languageComboBox.getSelectionModel().getSelectedItem()); - UserThread.execute(() -> languageComboBox.getSelectionModel().clearSelection()); - } - - private void onRemoveLanguage(String locale) { - model.onRemoveLanguage(locale); - - if (languagesListView.getItems().size() == 0) { - new Popup<>().warning(Res.get("account.arbitratorSelection.minOneArbitratorRequired")).show(); - model.onAddLanguage(LanguageUtil.getDefaultLanguageLocaleAsCode()); - } - } - - private void onAddArbitrator(ArbitratorListItem arbitratorListItem) { - model.onAddArbitrator(arbitratorListItem.arbitrator); - } - - private void onRemoveArbitrator(ArbitratorListItem arbitratorListItem) { - model.onRemoveArbitrator(arbitratorListItem.arbitrator); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // UI builder - /////////////////////////////////////////////////////////////////////////////////////////// - - private void addLanguageGroup() { - addTitledGroupBg(root, gridRow, 1, Res.get("account.arbitratorSelection.whichLanguages")); - - Tuple2> tuple = FormBuilder.addLabelListView(root, gridRow, Res.get("shared.yourLanguage"), Layout.FIRST_ROW_DISTANCE); - GridPane.setValignment(tuple.first, VPos.TOP); - languagesListView = tuple.second; - languagesListView.setMinHeight(3 * Layout.LIST_ROW_HEIGHT + 2); - languagesListView.setMaxHeight(6 * Layout.LIST_ROW_HEIGHT + 2); - languagesListView.setCellFactory(new Callback, ListCell>() { - @Override - public ListCell call(ListView list) { - return new ListCell() { - final Label label = new AutoTooltipLabel(); - final ImageView icon = ImageUtil.getImageViewById(ImageUtil.REMOVE_ICON); - final Button removeButton = new AutoTooltipButton("", icon); - final AnchorPane pane = new AnchorPane(label, removeButton); - - { - label.setLayoutY(5); - removeButton.setId("icon-button"); - AnchorPane.setRightAnchor(removeButton, 0d); - } - - @Override - public void updateItem(final String item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) { - label.setText(LanguageUtil.getDisplayName(item)); - removeButton.setOnAction(e -> onRemoveLanguage(item)); - setGraphic(pane); - } else { - setGraphic(null); - } - } - }; - } - }); - - languageComboBox = FormBuilder.addLabelComboBox(root, ++gridRow, "", 15).second; - languageComboBox.setPromptText(Res.get("shared.addLanguage")); - languageComboBox.setConverter(new StringConverter() { - @Override - public String toString(String code) { - return LanguageUtil.getDisplayName(code); - } - - @Override - public String fromString(String s) { - return null; - } - }); - languageComboBox.setOnAction(e -> onAddLanguage()); - } - - private void addArbitratorsGroup() { - TableGroupHeadline tableGroupHeadline = new TableGroupHeadline(Res.get("account.arbitratorSelection.whichDoYouAccept")); - GridPane.setRowIndex(tableGroupHeadline, ++gridRow); - GridPane.setColumnSpan(tableGroupHeadline, 2); - GridPane.setMargin(tableGroupHeadline, new Insets(40, -10, -10, -10)); - root.getChildren().add(tableGroupHeadline); - - tableView = new TableView<>(); - GridPane.setRowIndex(tableView, gridRow); - GridPane.setColumnSpan(tableView, 2); - GridPane.setMargin(tableView, new Insets(60, -10, 5, -10)); - root.getChildren().add(tableView); - - autoSelectAllMatchingCheckBox = addCheckBox(root, ++gridRow, Res.get("account.arbitratorSelection.autoSelect")); - GridPane.setColumnSpan(autoSelectAllMatchingCheckBox, 2); - GridPane.setHalignment(autoSelectAllMatchingCheckBox, HPos.LEFT); - GridPane.setColumnIndex(autoSelectAllMatchingCheckBox, 0); - GridPane.setMargin(autoSelectAllMatchingCheckBox, new Insets(0, -10, 0, -10)); - autoSelectAllMatchingCheckBox.setOnAction(event -> - model.setAutoSelectArbitrators(autoSelectAllMatchingCheckBox.isSelected())); - - TableColumn dateColumn = new AutoTooltipTableColumn<>(Res.get("account.arbitratorSelection.regDate")); - dateColumn.setSortable(false); - dateColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().getRegistrationDate())); - dateColumn.setMinWidth(140); - dateColumn.setMaxWidth(140); - - TableColumn nameColumn = new AutoTooltipTableColumn<>(Res.get("shared.onionAddress")); - nameColumn.setSortable(false); - nameColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().getAddressString())); - nameColumn.setMinWidth(90); - - TableColumn languagesColumn = new AutoTooltipTableColumn<>(Res.get("account.arbitratorSelection.languages")); - languagesColumn.setSortable(false); - languagesColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().getLanguageCodes())); - languagesColumn.setMinWidth(130); - - TableColumn selectionColumn = new AutoTooltipTableColumn( - Res.get("shared.accept")) { - { - setMinWidth(60); - setMaxWidth(60); - setSortable(false); - } - }; - selectionColumn.setCellValueFactory((arbitrator) -> new ReadOnlyObjectWrapper<>(arbitrator.getValue())); - selectionColumn.setCellFactory( - new Callback, TableCell>() { - @Override - public TableCell call(TableColumn column) { - return new TableCell() { - private final CheckBox checkBox = new AutoTooltipCheckBox(); - private TableRow tableRow; - private BooleanProperty selectedProperty; - - private void updateDisableState(final ArbitratorListItem item) { - boolean selected = model.isAcceptedArbitrator(item.arbitrator); - item.setIsSelected(selected); - - boolean hasMatchingLanguage = model.hasMatchingLanguage(item.arbitrator); - if (!hasMatchingLanguage) { - model.onRemoveArbitrator(item.arbitrator); - if (selected) - item.setIsSelected(false); - } - - boolean isMyOwnRegisteredArbitrator = model.isMyOwnRegisteredArbitrator(item.arbitrator); - checkBox.setDisable(!hasMatchingLanguage || isMyOwnRegisteredArbitrator); - - tableRow = getTableRow(); - if (tableRow != null) { - tableRow.setOpacity(hasMatchingLanguage && !isMyOwnRegisteredArbitrator ? 1 : 0.4); - - if (isMyOwnRegisteredArbitrator) { - String text = Res.get("account.arbitratorSelection.cannotSelectHimself"); - tableRow.setTooltip(new Tooltip(text)); - tableRow.setOnMouseClicked(e -> new Popup<>().warning( - text).show()); - } else if (!hasMatchingLanguage) { - tableRow.setTooltip(new Tooltip(Res.get("account.arbitratorSelection.noMatchingLang"))); - tableRow.setOnMouseClicked(e -> new Popup<>() - .warning(Res.get("account.arbitratorSelection.noLang")).show()); - } else { - tableRow.setOnMouseClicked(null); - tableRow.setTooltip(null); - } - } - } - - @Override - public void updateItem(final ArbitratorListItem item, boolean empty) { - super.updateItem(item, empty); - - if (item != null && !empty) { - selectedProperty = item.isSelectedProperty(); - languageCodesListChangeListener = c -> updateDisableState(item); - model.languageCodes.addListener(languageCodesListChangeListener); - - isSelectedChangeListener = (observable, oldValue, newValue) -> checkBox.setSelected(newValue); - selectedProperty.addListener(isSelectedChangeListener); - - checkBox.setSelected(model.isAcceptedArbitrator(item.arbitrator)); - checkBox.setOnAction(e -> { - if (checkBox.isSelected()) { - onAddArbitrator(item); - } else if (model.isDeselectAllowed(item)) { - onRemoveArbitrator(item); - } else { - new Popup<>().warning(Res.get("account.arbitratorSelection.minOne")).show(); - checkBox.setSelected(true); - } - item.setIsSelected(checkBox.isSelected()); - } - ); - - updateDisableState(item); - setGraphic(checkBox); - } else { - model.languageCodes.removeListener(languageCodesListChangeListener); - if (selectedProperty != null) - selectedProperty.removeListener(isSelectedChangeListener); - - setGraphic(null); - - checkBox.setOnAction(null); - if (tableRow != null) - tableRow.setOnMouseClicked(null); - } - } - }; - } - }); - - //noinspection unchecked - tableView.getColumns().addAll(dateColumn, nameColumn, languagesColumn, selectionColumn); - tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); - } -} - diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java b/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java deleted file mode 100644 index 2d6039992d..0000000000 --- a/desktop/src/main/java/bisq/desktop/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.desktop.main.account.content.arbitratorselection; - -import bisq.desktop.common.model.ActivatableDataModel; - -import bisq.core.arbitration.Arbitrator; -import bisq.core.arbitration.ArbitratorManager; -import bisq.core.locale.LanguageUtil; -import bisq.core.user.Preferences; -import bisq.core.user.User; -import bisq.core.util.BSFormatter; - -import bisq.network.p2p.NodeAddress; - -import bisq.common.crypto.KeyRing; - -import com.google.inject.Inject; - -import javafx.collections.FXCollections; -import javafx.collections.MapChangeListener; -import javafx.collections.ObservableList; - -import java.util.stream.Collectors; - -class ArbitratorSelectionViewModel extends ActivatableDataModel { - private final User user; - private final ArbitratorManager arbitratorManager; - private final Preferences preferences; - private final KeyRing keyRing; - private final BSFormatter formatter; - final ObservableList languageCodes = FXCollections.observableArrayList(); - final ObservableList arbitratorListItems = FXCollections.observableArrayList(); - final ObservableList allLanguageCodes = FXCollections.observableArrayList(LanguageUtil.getAllLanguageCodes()); - private final MapChangeListener arbitratorMapChangeListener; - - @Inject - public ArbitratorSelectionViewModel(User user, ArbitratorManager arbitratorManager, Preferences preferences, - KeyRing keyRing, BSFormatter formatter) { - this.user = user; - this.arbitratorManager = arbitratorManager; - this.preferences = preferences; - this.keyRing = keyRing; - this.formatter = formatter; - - arbitratorMapChangeListener = change -> applyArbitratorMap(); - } - - private void applyArbitratorMap() { - arbitratorListItems.clear(); - arbitratorListItems.addAll(arbitratorManager.getArbitratorsObservableMap().values().stream() - .map(e -> new ArbitratorListItem(e, formatter)).collect(Collectors.toList())); - } - - @Override - protected void activate() { - languageCodes.setAll(user.getAcceptedLanguageLocaleCodes()); - arbitratorManager.getArbitratorsObservableMap().addListener(arbitratorMapChangeListener); - arbitratorManager.updateArbitratorMap(); - applyArbitratorMap(); - - updateAutoSelectArbitrators(); - } - - @Override - protected void deactivate() { - arbitratorManager.getArbitratorsObservableMap().removeListener(arbitratorMapChangeListener); - } - - void onAddLanguage(String code) { - if (code != null) { - boolean changed = user.addAcceptedLanguageLocale(code); - if (changed) - languageCodes.add(code); - } - - updateAutoSelectArbitrators(); - } - - void onRemoveLanguage(String code) { - if (code != null) { - boolean changed = user.removeAcceptedLanguageLocale(code); - if (changed) - languageCodes.remove(code); - } - - updateAutoSelectArbitrators(); - } - - void onAddArbitrator(Arbitrator arbitrator) { - if (!arbitratorIsTrader(arbitrator)) { - user.addAcceptedArbitrator(arbitrator); - - // TODO we mirror arbitrator data for mediator as long we have not impl. it in the UI - user.addAcceptedMediator(ArbitratorManager.getMediator(arbitrator)); - } - } - - void onRemoveArbitrator(Arbitrator arbitrator) { - if (arbitrator != null) { - user.removeAcceptedArbitrator(arbitrator); - - // TODO we mirror arbitrator data for mediator as long we have not impl. it in the UI - user.removeAcceptedMediator(ArbitratorManager.getMediator(arbitrator)); - } - } - - public boolean isDeselectAllowed(ArbitratorListItem arbitratorListItem) { - return arbitratorListItem != null - && user.getAcceptedArbitrators() != null - && user.getAcceptedArbitrators().size() > 1; - } - - public boolean isAcceptedArbitrator(Arbitrator arbitrator) { - return arbitrator != null && - user.getAcceptedArbitrators() != null && - user.getAcceptedArbitrators().contains(arbitrator) && - !isMyOwnRegisteredArbitrator(arbitrator); - } - - public boolean arbitratorIsTrader(Arbitrator arbitrator) { - return keyRing.getPubKeyRing().equals(arbitrator.getPubKeyRing()); - } - - public boolean hasMatchingLanguage(Arbitrator arbitrator) { - return user.hasMatchingLanguage(arbitrator); - } - - public boolean isMyOwnRegisteredArbitrator(Arbitrator arbitrator) { - return user.isMyOwnRegisteredArbitrator(arbitrator); - } - - private void updateAutoSelectArbitrators() { - if (preferences.isAutoSelectArbitrators()) { - arbitratorListItems.stream().forEach(item -> { - Arbitrator arbitrator = item.arbitrator; - if (!isMyOwnRegisteredArbitrator(arbitrator)) { - if (hasMatchingLanguage(arbitrator)) { - onAddArbitrator(arbitrator); - item.setIsSelected(true); - } else { - onRemoveArbitrator(arbitrator); - item.setIsSelected(false); - } - } else { - item.setIsSelected(false); - } - }); - } - } - - public void setAutoSelectArbitrators(boolean doAutoSelect) { - preferences.setAutoSelectArbitrators(doAutoSelect); - updateAutoSelectArbitrators(); - } - - public boolean getAutoSelectArbitrators() { - return preferences.isAutoSelectArbitrators(); - } -} diff --git a/desktop/src/main/java/bisq/desktop/main/account/settings/AccountSettingsView.java b/desktop/src/main/java/bisq/desktop/main/account/settings/AccountSettingsView.java index 7db7447d66..e0ba0a74fa 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/settings/AccountSettingsView.java +++ b/desktop/src/main/java/bisq/desktop/main/account/settings/AccountSettingsView.java @@ -28,7 +28,6 @@ import bisq.desktop.components.AutoTooltipToggleButton; import bisq.desktop.main.MainView; import bisq.desktop.main.account.AccountView; import bisq.desktop.main.account.content.altcoinaccounts.AltCoinAccountsView; -import bisq.desktop.main.account.content.arbitratorselection.ArbitratorSelectionView; import bisq.desktop.main.account.content.backup.BackupView; import bisq.desktop.main.account.content.fiataccounts.FiatAccountsView; import bisq.desktop.main.account.content.notifications.MobileNotificationsView; @@ -64,7 +63,7 @@ public class AccountSettingsView extends ActivatableViewAndModel { private final Navigation navigation; - private MenuItem paymentAccount, altCoinsAccountView, arbitratorSelection, notifications, password, seedWords, backup; + private MenuItem paymentAccount, altCoinsAccountView, notifications, password, seedWords, backup; private Navigation.Listener listener; @FXML @@ -95,21 +94,18 @@ public class AccountSettingsView extends ActivatableViewAndModel { ToggleGroup toggleGroup = new ToggleGroup(); paymentAccount = new MenuItem(navigation, toggleGroup, Res.get("account.menu.paymentAccount"), FiatAccountsView.class, AwesomeIcon.MONEY); altCoinsAccountView = new MenuItem(navigation, toggleGroup, Res.get("account.menu.altCoinsAccountView"), AltCoinAccountsView.class, AwesomeIcon.LINK); - arbitratorSelection = new MenuItem(navigation, toggleGroup, Res.get("account.menu.arbitratorSelection"), - ArbitratorSelectionView.class, AwesomeIcon.USER_MD); notifications = new MenuItem(navigation, toggleGroup, Res.get("account.menu.notifications"), MobileNotificationsView.class, AwesomeIcon.BELL); password = new MenuItem(navigation, toggleGroup, Res.get("account.menu.password"), PasswordView.class, AwesomeIcon.UNLOCK_ALT); seedWords = new MenuItem(navigation, toggleGroup, Res.get("account.menu.seedWords"), SeedWordsView.class, AwesomeIcon.KEY); backup = new MenuItem(navigation, toggleGroup, Res.get("account.menu.backup"), BackupView.class, AwesomeIcon.CLOUD_DOWNLOAD); - leftVBox.getChildren().addAll(paymentAccount, altCoinsAccountView, arbitratorSelection, notifications, password, seedWords, backup); + leftVBox.getChildren().addAll(paymentAccount, altCoinsAccountView, notifications, password, seedWords, backup); } @Override protected void activate() { paymentAccount.activate(); altCoinsAccountView.activate(); - arbitratorSelection.activate(); notifications.activate(); password.activate(); seedWords.activate(); @@ -135,7 +131,6 @@ public class AccountSettingsView extends ActivatableViewAndModel { paymentAccount.deactivate(); altCoinsAccountView.deactivate(); - arbitratorSelection.deactivate(); notifications.deactivate(); password.deactivate(); seedWords.deactivate(); @@ -148,7 +143,6 @@ public class AccountSettingsView extends ActivatableViewAndModel { if (view instanceof FiatAccountsView) paymentAccount.setSelected(true); else if (view instanceof AltCoinAccountsView) altCoinsAccountView.setSelected(true); - else if (view instanceof ArbitratorSelectionView) arbitratorSelection.setSelected(true); else if (view instanceof MobileNotificationsView) notifications.setSelected(true); else if (view instanceof PasswordView) password.setSelected(true); else if (view instanceof SeedWordsView) seedWords.setSelected(true); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java index f66c144bde..0e87e6d2b2 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java @@ -30,7 +30,6 @@ import bisq.desktop.components.InputTextField; import bisq.desktop.components.TitledGroupBg; import bisq.desktop.main.MainView; import bisq.desktop.main.account.AccountView; -import bisq.desktop.main.account.content.arbitratorselection.ArbitratorSelectionView; import bisq.desktop.main.account.content.fiataccounts.FiatAccountsView; import bisq.desktop.main.account.settings.AccountSettingsView; import bisq.desktop.main.dao.DaoView; @@ -352,13 +351,7 @@ public abstract class MutableOfferView extends }); } } else { - new Popup<>().headLine(Res.get("popup.warning.noArbitratorSelected.headline")) - .instruction(Res.get("popup.warning.noArbitratorSelected.msg")) - .actionButtonTextWithGoTo("navigation.arbitratorSelection") - .onAction(() -> { - navigation.setReturnPath(navigation.getCurrentPath()); - navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, ArbitratorSelectionView.class); - }).show(); + new Popup<>().warning(Res.get("popup.warning.noArbitratorsAvailable")).show(); } } else { showInsufficientBsqFundsForBtcFeePaymentPopup(); @@ -728,9 +721,9 @@ public abstract class MutableOfferView extends }; volumeListener = (observable, oldValue, newValue) -> { - if (!newValue.equals("") && CurrencyUtil.isFiatCurrency(model.tradeCurrencyCode.get())) { - volumeInfoInputTextField.setContentForPrivacyPopOver(createPopoverLabel(Res.get("offerbook.info.roundedFiatVolume"))); - } + if (!newValue.equals("") && CurrencyUtil.isFiatCurrency(model.tradeCurrencyCode.get())) { + volumeInfoInputTextField.setContentForPrivacyPopOver(createPopoverLabel(Res.get("offerbook.info.roundedFiatVolume"))); + } }; marketPriceMarginListener = (observable, oldValue, newValue) -> { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java index 2abec4eeae..b813887718 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java @@ -29,7 +29,6 @@ import bisq.desktop.components.InfoAutoTooltipLabel; import bisq.desktop.components.PeerInfoIcon; import bisq.desktop.main.MainView; import bisq.desktop.main.account.AccountView; -import bisq.desktop.main.account.content.arbitratorselection.ArbitratorSelectionView; import bisq.desktop.main.account.content.fiataccounts.FiatAccountsView; import bisq.desktop.main.account.settings.AccountSettingsView; import bisq.desktop.main.funds.FundsView; @@ -408,10 +407,7 @@ public class OfferBookView extends ActivatableViewAndModel().warning(Res.get("popup.warning.noArbitratorsAvailable")).show(); } else { createOfferButton.setDisable(true); offerActionHandler.onCreateOffer(model.getSelectedTradeCurrency()); @@ -429,10 +425,7 @@ public class OfferBookView extends ActivatableViewAndModel().warning(Res.get("popup.warning.noArbitratorsAvailable")).show(); } else if (!isPaymentAccountValidForOffer) { openPopupForMissingAccountSetup(Res.get("offerbook.warning.noMatchingAccount.headline"), Res.get("offerbook.warning.noMatchingAccount.msg"), diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java index 3ff1be7037..193af9326a 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java @@ -30,9 +30,6 @@ import bisq.desktop.components.InfoTextField; import bisq.desktop.components.InputTextField; import bisq.desktop.components.TitledGroupBg; import bisq.desktop.main.MainView; -import bisq.desktop.main.account.AccountView; -import bisq.desktop.main.account.content.arbitratorselection.ArbitratorSelectionView; -import bisq.desktop.main.account.settings.AccountSettingsView; import bisq.desktop.main.dao.DaoView; import bisq.desktop.main.dao.wallet.BsqWalletView; import bisq.desktop.main.dao.wallet.receive.BsqReceiveView; @@ -393,14 +390,7 @@ public class TakeOfferView extends ActivatableViewAndModel().headLine(Res.get("popup.warning.noArbitratorSelected.headline")) - .instruction(Res.get("popup.warning.noArbitratorSelected.msg")) - .actionButtonTextWithGoTo("navigation.arbitratorSelection") - .onAction(() -> { - navigation.setReturnPath(navigation.getCurrentPath()); - navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, - ArbitratorSelectionView.class); - }).show(); + new Popup<>().warning(Res.get("popup.warning.noArbitratorsAvailable")).show(); } } else { showInsufficientBsqFundsForBtcFeePaymentPopup(); diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java index 59ce275c25..b374192dcd 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java @@ -19,10 +19,6 @@ package bisq.desktop.main.overlays.windows; import bisq.desktop.Navigation; import bisq.desktop.components.BusyAnimation; -import bisq.desktop.main.MainView; -import bisq.desktop.main.account.AccountView; -import bisq.desktop.main.account.content.arbitratorselection.ArbitratorSelectionView; -import bisq.desktop.main.account.settings.AccountSettingsView; import bisq.desktop.main.overlays.Overlay; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.util.Layout; @@ -398,9 +394,7 @@ public class OfferDetailsWindow extends Overlay { takeOfferHandlerOptional.get().run(); } } else { - new Popup<>().warning(Res.get("offerDetailsWindow.warn.noArbitrator")).show(); - navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, - ArbitratorSelectionView.class); + new Popup<>().warning(Res.get("popup.warning.noArbitratorsAvailable")).show(); } }); } From 6346b1457784d9d0738cc04bb48d52d67c867569 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 22:47:16 -0500 Subject: [PATCH 08/10] Remove hasMatchingArbitrator check --- .../desktop/main/offer/offerbook/OfferBookView.java | 11 ++--------- .../main/offer/offerbook/OfferBookViewModel.java | 13 ------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java index b813887718..fbe7a3999b 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java @@ -416,7 +416,6 @@ public class OfferBookView extends ActivatableViewAndModel().warning(Res.get("popup.warning.noArbitratorsAvailable")).show(); - } else if (!isPaymentAccountValidForOffer) { + if (!isPaymentAccountValidForOffer) { openPopupForMissingAccountSetup(Res.get("offerbook.warning.noMatchingAccount.headline"), Res.get("offerbook.warning.noMatchingAccount.msg"), FiatAccountsView.class, @@ -796,7 +793,7 @@ public class OfferBookView extends ActivatableViewAndModel() { final ImageView iconView = new ImageView(); final Button button = new AutoTooltipButton(); - boolean isTradable, isPaymentAccountValidForOffer, hasMatchingArbitrator, + boolean isTradable, isPaymentAccountValidForOffer, hasSameProtocolVersion, isIgnored, isOfferBanned, isCurrencyBanned, isPaymentMethodBanned, isNodeAddressBanned, isInsufficientTradeLimit; @@ -817,7 +814,6 @@ public class OfferBookView extends ActivatableViewAndModel onShowInfo(offer, isPaymentAccountValidForOffer, - hasMatchingArbitrator, hasSameProtocolVersion, isIgnored, isOfferBanned, diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java index 6d1da6414f..7cf276297c 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java @@ -536,19 +536,6 @@ class OfferBookViewModel extends ActivatableViewModel { }); } - boolean hasMatchingArbitrator(Offer offer) { - final List acceptedArbitratorAddresses = user.getAcceptedArbitratorAddresses(); - if (acceptedArbitratorAddresses != null) { - for (NodeAddress offerArbitratorNodeAddress : offer.getArbitratorNodeAddresses()) { - for (NodeAddress acceptedArbitratorNodeAddress : acceptedArbitratorAddresses) { - if (offerArbitratorNodeAddress.equals(acceptedArbitratorNodeAddress)) - return true; - } - } - } - return false; - } - boolean isIgnored(Offer offer) { return preferences.getIgnoreTradersList().stream() .anyMatch(i -> i.equals(offer.getMakerNodeAddress().getHostNameWithoutPostFix())); From 984c305b774dd422d81d5fa50333d746853a82bf Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 22:48:07 -0500 Subject: [PATCH 09/10] Remove isAutoSelectArbitrators and hasMatchingLanguage check --- .../core/arbitration/ArbitratorManager.java | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java b/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java index dd2435fc8e..5ce57b393e 100644 --- a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java +++ b/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java @@ -230,30 +230,12 @@ public class ArbitratorManager { ); }); - if (preferences.isAutoSelectArbitrators()) { - arbitratorsObservableMap.values().stream() - .filter(user::hasMatchingLanguage) - .forEach(a -> { - user.addAcceptedArbitrator(a); - user.addAcceptedMediator(getMediator(a) - ); - }); - } else { - // if we don't have any arbitrator we set all matching - // we use a delay as we might get our matching arbitrator a bit delayed (first we get one we did not selected - // then we get our selected one - we don't want to activate the first in that case) - UserThread.runAfter(() -> { - if (user.getAcceptedArbitrators().isEmpty()) { - arbitratorsObservableMap.values().stream() - .filter(user::hasMatchingLanguage) - .forEach(a -> { - user.addAcceptedArbitrator(a); - user.addAcceptedMediator(getMediator(a) - ); - }); - } - }, 100, TimeUnit.MILLISECONDS); - } + // We keep the domain with storing the arbitrators in user as it might be still useful for mediators + arbitratorsObservableMap.values().forEach(a -> { + user.addAcceptedArbitrator(a); + user.addAcceptedMediator(getMediator(a) + ); + }); } // TODO we mirror arbitrator data for mediator as long we have not impl. it in the UI From 32bfe0eb8e1c65821cd5a31df54299f86fe8317c Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 2 Oct 2018 22:58:38 -0500 Subject: [PATCH 10/10] Set activation date, add logs --- core/src/main/java/bisq/core/arbitration/ArbitratorManager.java | 2 ++ .../java/bisq/core/offer/availability/ArbitratorSelection.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java b/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java index 5ce57b393e..f9809d6c48 100644 --- a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java +++ b/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java @@ -236,6 +236,8 @@ public class ArbitratorManager { user.addAcceptedMediator(getMediator(a) ); }); + + log.info("Available arbitrators: {}", arbitratorsObservableMap.keySet()); } // TODO we mirror arbitrator data for mediator as long we have not impl. it in the UI diff --git a/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java b/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java index e59d6bb271..54ee30b4e9 100644 --- a/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java +++ b/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java @@ -50,7 +50,7 @@ public class ArbitratorSelection { static { try { //TODO set activation data to 1 month after release - Date activationDate = new SimpleDateFormat("dd/MM/yyyy").parse("1/10/2018"); + Date activationDate = new SimpleDateFormat("dd/MM/yyyy").parse("20/11/2018"); isNewRuleActivated = new Date().after(activationDate); } catch (ParseException e) { e.printStackTrace();