Refactor dependency structure to enable adding dispute managers

If we would add DisputeManager to previous structure it would cause a
circular dependency error from guice. We change dependency structure so
that TradeManager does not know XmrTxProofService but XmrTxProofService
gets an instance of TradeManager. It makes code cleaner in total as well
as responsibility is better defined.

Next commit will contain the DisputeManager addition.
This commit is contained in:
chimp1984 2020-09-03 14:36:28 -05:00 committed by Christoph Atteneder
parent 688bef885a
commit 2da08a5620
No known key found for this signature in database
GPG key ID: CD5DC1C529CDFD3B
7 changed files with 83 additions and 98 deletions

View file

@ -26,6 +26,7 @@ import bisq.core.setup.CorePersistedDataHost;
import bisq.core.setup.CoreSetup;
import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import bisq.core.trade.TradeManager;
import bisq.core.trade.txproof.xmr.XmrTxProofService;
import bisq.network.p2p.P2PService;
@ -221,6 +222,7 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
try {
injector.getInstance(ArbitratorManager.class).shutDown();
injector.getInstance(TradeManager.class).shutDown();
injector.getInstance(XmrTxProofService.class).shutDown();
injector.getInstance(DaoSetup.class).shutDown();
injector.getInstance(AvoidStandbyModeService.class).shutDown();
injector.getInstance(OpenOfferManager.class).shutDown(() -> {

View file

@ -59,6 +59,7 @@ import bisq.core.support.traderchat.TraderChatManager;
import bisq.core.trade.TradeManager;
import bisq.core.trade.TradeTxException;
import bisq.core.trade.statistics.TradeStatisticsManager;
import bisq.core.trade.txproof.xmr.XmrTxProofService;
import bisq.core.user.Preferences;
import bisq.core.user.User;
import bisq.core.util.FormattingUtils;
@ -167,6 +168,7 @@ public class BisqSetup {
private final PrivateNotificationManager privateNotificationManager;
private final FilterManager filterManager;
private final TradeStatisticsManager tradeStatisticsManager;
private final XmrTxProofService xmrTxProofService;
private final ClockWatcher clockWatcher;
private final FeeService feeService;
private final DaoSetup daoSetup;
@ -263,6 +265,7 @@ public class BisqSetup {
PrivateNotificationManager privateNotificationManager,
FilterManager filterManager,
TradeStatisticsManager tradeStatisticsManager,
XmrTxProofService xmrTxProofService,
ClockWatcher clockWatcher,
FeeService feeService,
DaoSetup daoSetup,
@ -308,6 +311,7 @@ public class BisqSetup {
this.privateNotificationManager = privateNotificationManager;
this.filterManager = filterManager;
this.tradeStatisticsManager = tradeStatisticsManager;
this.xmrTxProofService = xmrTxProofService;
this.clockWatcher = clockWatcher;
this.feeService = feeService;
this.daoSetup = daoSetup;
@ -686,6 +690,7 @@ public class BisqSetup {
traderChatManager.onAllServicesInitialized();
tradeManager.onAllServicesInitialized();
xmrTxProofService.onAllServicesInitialized();
if (walletsSetup.downloadPercentageProperty().get() == 1) {
checkForLockedUpFunds();

View file

@ -46,8 +46,6 @@ import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.statistics.ReferralIdService;
import bisq.core.trade.statistics.TradeStatisticsManager;
import bisq.core.trade.txproof.AssetTxProofResult;
import bisq.core.trade.txproof.xmr.XmrTxProofService;
import bisq.core.user.User;
import bisq.core.util.Validator;
@ -59,7 +57,6 @@ import bisq.network.p2p.P2PService;
import bisq.network.p2p.SendMailboxMessageListener;
import bisq.common.ClockWatcher;
import bisq.common.UserThread;
import bisq.common.config.Config;
import bisq.common.crypto.KeyRing;
import bisq.common.handlers.ErrorMessageHandler;
@ -111,8 +108,6 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
public class TradeManager implements PersistedDataHost {
private static final Logger log = LoggerFactory.getLogger(TradeManager.class);
@ -132,7 +127,6 @@ public class TradeManager implements PersistedDataHost {
private final ReferralIdService referralIdService;
private final AccountAgeWitnessService accountAgeWitnessService;
@Getter
private final XmrTxProofService xmrTxProofService;
private final ArbitratorManager arbitratorManager;
private final MediatorManager mediatorManager;
private final RefundAgentManager refundAgentManager;
@ -174,7 +168,6 @@ public class TradeManager implements PersistedDataHost {
TradeStatisticsManager tradeStatisticsManager,
ReferralIdService referralIdService,
AccountAgeWitnessService accountAgeWitnessService,
XmrTxProofService xmrTxProofService,
ArbitratorManager arbitratorManager,
MediatorManager mediatorManager,
RefundAgentManager refundAgentManager,
@ -197,7 +190,6 @@ public class TradeManager implements PersistedDataHost {
this.tradeStatisticsManager = tradeStatisticsManager;
this.referralIdService = referralIdService;
this.accountAgeWitnessService = accountAgeWitnessService;
this.xmrTxProofService = xmrTxProofService;
this.arbitratorManager = arbitratorManager;
this.mediatorManager = mediatorManager;
this.refundAgentManager = refundAgentManager;
@ -286,7 +278,7 @@ public class TradeManager implements PersistedDataHost {
}
public void shutDown() {
xmrTxProofService.shutDown();
// Do nothing here
}
private void initPendingTrades() {
@ -329,13 +321,6 @@ public class TradeManager implements PersistedDataHost {
addTradeToFailedTradesList.add(trade);
}
}
if (trade.getState() == Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG) {
// This state can be only appear at a SellerTrade
checkArgument(trade instanceof SellerTrade, "Trade must be instance of SellerTrade");
// We delay a bit as at startup lots of stuff is happening
UserThread.runAfter(() -> maybeStartXmrTxProofServices((SellerTrade) trade), 1);
}
}
);
@ -360,29 +345,8 @@ public class TradeManager implements PersistedDataHost {
pendingTradesInitialized.set(true);
}
public void maybeStartXmrTxProofServices(SellerTrade sellerTrade) {
xmrTxProofService.maybeStartRequests(sellerTrade, tradableList.getList(),
assetTxProofResult -> {
if (assetTxProofResult == AssetTxProofResult.COMPLETED) {
log.info("###########################################################################################");
log.info("We auto-confirm trade {} as our all our services for the tx proof completed successfully", sellerTrade.getShortId());
log.info("###########################################################################################");
autoConfirmFiatPaymentReceived(sellerTrade);
}
},
(errorMessage, throwable) -> {
log.error(errorMessage);
});
}
private void autoConfirmFiatPaymentReceived(SellerTrade sellerTrade) {
onFiatPaymentReceived(sellerTrade,
() -> {
}, errorMessage -> {
});
}
public void onFiatPaymentReceived(SellerTrade sellerTrade,
public void onUserConfirmedFiatPaymentReceived(SellerTrade sellerTrade,
ResultHandler resultHandler,
ErrorMessageHandler errorMessageHandler) {
sellerTrade.onFiatPaymentReceived(resultHandler, errorMessageHandler);

View file

@ -17,7 +17,6 @@
package bisq.core.trade.protocol.tasks.seller;
import bisq.core.trade.SellerTrade;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage;
import bisq.core.trade.protocol.tasks.TradeTask;
@ -27,7 +26,6 @@ import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
@ -62,10 +60,6 @@ public class SellerProcessCounterCurrencyTransferStartedMessage extends TradeTas
trade.setCounterCurrencyExtraData(counterCurrencyExtraData);
}
checkArgument(trade instanceof SellerTrade, "Trade must be instance of SellerTrade");
// We return early in the service if its not XMR. We prefer to not have additional checks outside...
processModel.getTradeManager().maybeStartXmrTxProofServices((SellerTrade) trade);
processModel.removeMailboxMessageAfterProcessing(trade);
trade.setState(Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG);

View file

@ -17,18 +17,8 @@
package bisq.core.trade.txproof;
import bisq.core.trade.Trade;
import bisq.common.handlers.FaultHandler;
import java.util.List;
import java.util.function.Consumer;
public interface AssetTxProofService {
void maybeStartRequests(Trade trade,
List<Trade> activeTrades,
Consumer<AssetTxProofResult> resultHandler,
FaultHandler faultHandler);
void onAllServicesInitialized();
void shutDown();
}

View file

@ -23,6 +23,7 @@ import bisq.core.locale.Res;
import bisq.core.payment.payload.AssetsAccountPayload;
import bisq.core.trade.SellerTrade;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
import bisq.core.trade.closed.ClosedTradableManager;
import bisq.core.trade.failed.FailedTradesManager;
import bisq.core.trade.txproof.AssetTxProofHttpClient;
@ -34,16 +35,16 @@ import bisq.core.user.Preferences;
import bisq.network.p2p.P2PService;
import bisq.common.app.DevEnv;
import bisq.common.handlers.FaultHandler;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
@ -59,12 +60,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class XmrTxProofService implements AssetTxProofService {
private final FilterManager filterManager;
private final Preferences preferences;
private final TradeManager tradeManager;
private final ClosedTradableManager closedTradableManager;
private final FailedTradesManager failedTradesManager;
private final P2PService p2PService;
private final WalletsSetup walletsSetup;
private final AssetTxProofHttpClient httpClient;
private final Map<String, XmrTxProofRequestsPerTrade> servicesByTradeId = new HashMap<>();
private AutoConfirmSettings autoConfirmSettings;
///////////////////////////////////////////////////////////////////////////////////////////
@ -75,6 +78,7 @@ public class XmrTxProofService implements AssetTxProofService {
@Inject
public XmrTxProofService(FilterManager filterManager,
Preferences preferences,
TradeManager tradeManager,
ClosedTradableManager closedTradableManager,
FailedTradesManager failedTradesManager,
P2PService p2PService,
@ -82,11 +86,25 @@ public class XmrTxProofService implements AssetTxProofService {
AssetTxProofHttpClient httpClient) {
this.filterManager = filterManager;
this.preferences = preferences;
this.tradeManager = tradeManager;
this.closedTradableManager = closedTradableManager;
this.failedTradesManager = failedTradesManager;
this.p2PService = p2PService;
this.walletsSetup = walletsSetup;
this.httpClient = httpClient;
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onAllServicesInitialized() {
if (!preferences.findAutoConfirmSettings("XMR").isPresent()) {
log.error("AutoConfirmSettings is not present");
}
autoConfirmSettings = preferences.findAutoConfirmSettings("XMR").get();
filterManager.filterProperty().addListener((observable, oldValue, newValue) -> {
if (isAutoConfDisabledByFilter()) {
@ -96,22 +114,39 @@ public class XmrTxProofService implements AssetTxProofService {
shutDown();
}
});
ObservableList<Trade> tradableList = tradeManager.getTradableList();
tradableList.addListener((ListChangeListener<Trade>) c -> {
c.next();
if (c.wasAdded()) {
processTrades(c.getAddedSubList());
}
});
processTrades(tradableList);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void maybeStartRequests(Trade trade,
List<Trade> activeTrades,
Consumer<AssetTxProofResult> resultHandler,
FaultHandler faultHandler) {
if (!isXmrBuyer(trade)) {
return;
public void shutDown() {
servicesByTradeId.values().forEach(XmrTxProofRequestsPerTrade::terminate);
servicesByTradeId.clear();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void processTrades(List<? extends Trade> trades) {
trades.stream()
.filter(trade -> trade instanceof SellerTrade)
.map(trade -> (SellerTrade) trade)
.filter(this::isExpectedTradeState)
.filter(this::isXmrBuyer)
.filter(trade -> networkAndWalletReady())
.forEach(this::processTrade);
}
private void processTrade(SellerTrade trade) {
String txId = trade.getCounterCurrencyTxId();
String txHash = trade.getCounterCurrencyExtraData();
if (is32BitHexStringInValid(txId) || is32BitHexStringInValid(txHash)) {
@ -119,25 +154,13 @@ public class XmrTxProofService implements AssetTxProofService {
return;
}
if (!networkAndWalletReady()) {
return;
}
Optional<AutoConfirmSettings> optionalAutoConfirmSettings = preferences.findAutoConfirmSettings("XMR");
if (!optionalAutoConfirmSettings.isPresent()) {
// Not expected
log.error("autoConfirmSettings is not present");
return;
}
AutoConfirmSettings autoConfirmSettings = optionalAutoConfirmSettings.get();
if (isAutoConfDisabledByFilter()) {
trade.setAssetTxProofResult(AssetTxProofResult.FEATURE_DISABLED
.details(Res.get("portfolio.pending.autoConf.state.filterDisabledFeature")));
return;
}
if (wasTxKeyReUsed(trade, activeTrades)) {
if (wasTxKeyReUsed(trade, tradeManager.getTradableList())) {
trade.setAssetTxProofResult(AssetTxProofResult.INVALID_DATA
.details(Res.get("portfolio.pending.autoConf.state.xmr.txKeyReused")));
return;
@ -151,19 +174,22 @@ public class XmrTxProofService implements AssetTxProofService {
assetTxProofResult -> {
trade.setAssetTxProofResult(assetTxProofResult);
if (assetTxProofResult == AssetTxProofResult.COMPLETED) {
log.info("###########################################################################################");
log.info("We auto-confirm trade {} as our all our services for the tx proof completed successfully", trade.getShortId());
log.info("###########################################################################################");
trade.onFiatPaymentReceived(() -> {
}, errorMessage -> {
});
}
if (assetTxProofResult.isTerminal()) {
servicesByTradeId.remove(trade.getId());
}
resultHandler.accept(assetTxProofResult);
},
faultHandler);
}
@Override
public void shutDown() {
servicesByTradeId.values().forEach(XmrTxProofRequestsPerTrade::terminate);
servicesByTradeId.clear();
(errorMessage, throwable) -> {
log.error(errorMessage);
});
}
@ -171,6 +197,10 @@ public class XmrTxProofService implements AssetTxProofService {
// Validation
///////////////////////////////////////////////////////////////////////////////////////////
private boolean isExpectedTradeState(SellerTrade sellerTrade) {
return sellerTrade.getState() == Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG;
}
private boolean isXmrBuyer(Trade trade) {
if (!checkNotNull(trade.getOffer()).getCurrencyCode().equals("XMR")) {
return false;
@ -183,6 +213,12 @@ public class XmrTxProofService implements AssetTxProofService {
return checkNotNull(trade.getContract()).getSellerPaymentAccountPayload() instanceof AssetsAccountPayload;
}
private boolean networkAndWalletReady() {
return p2PService.isBootstrapped() &&
walletsSetup.isDownloadComplete() &&
walletsSetup.hasSufficientPeersForBroadcast();
}
private boolean is32BitHexStringInValid(String hexString) {
if (hexString == null || hexString.isEmpty() || !hexString.matches("[a-fA-F0-9]{64}")) {
log.warn("Invalid hexString: {}", hexString);
@ -192,12 +228,6 @@ public class XmrTxProofService implements AssetTxProofService {
return false;
}
private boolean networkAndWalletReady() {
return p2PService.isBootstrapped() &&
walletsSetup.isDownloadComplete() &&
walletsSetup.hasSufficientPeersForBroadcast();
}
private boolean isAutoConfDisabledByFilter() {
return filterManager.getFilter() != null &&
filterManager.getFilter().isDisableAutoConf();

View file

@ -194,7 +194,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
checkNotNull(getTrade(), "trade must not be null");
checkArgument(getTrade() instanceof SellerTrade, "Trade must be instance of SellerTrade");
tradeManager.onFiatPaymentReceived((SellerTrade) getTrade(), resultHandler, errorMessageHandler);
tradeManager.onUserConfirmedFiatPaymentReceived((SellerTrade) getTrade(), resultHandler, errorMessageHandler);
}
public void onWithdrawRequest(String toAddress,