mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-28 00:27:23 -04:00
fixes when cloned offers are taken at the same time
This commit is contained in:
parent
13e13d945d
commit
c7a3a9740f
6 changed files with 47 additions and 24 deletions
|
@ -2648,7 +2648,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setDepositTxs(txs);
|
setDepositTxs(txs);
|
||||||
if (getMaker().getDepositTx() == null || (getTaker().getDepositTx() == null && !hasBuyerAsTakerWithoutDeposit())) return; // skip if either deposit tx not seen
|
if (!isPublished(getMaker().getDepositTx()) || (!hasBuyerAsTakerWithoutDeposit() && !isPublished(getTaker().getDepositTx()))) return; // skip if deposit txs not published successfully
|
||||||
setStateDepositsSeen();
|
setStateDepositsSeen();
|
||||||
|
|
||||||
// set actual security deposits
|
// set actual security deposits
|
||||||
|
@ -2750,6 +2750,13 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isPublished(MoneroTx tx) {
|
||||||
|
if (tx == null) return false;
|
||||||
|
if (Boolean.TRUE.equals(tx.isFailed())) return false;
|
||||||
|
if (!Boolean.TRUE.equals(tx.inTxPool()) && !Boolean.TRUE.equals(tx.isConfirmed())) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void syncWalletIfBehind() {
|
private void syncWalletIfBehind() {
|
||||||
synchronized (walletLock) {
|
synchronized (walletLock) {
|
||||||
if (isWalletBehind()) {
|
if (isWalletBehind()) {
|
||||||
|
|
|
@ -460,9 +460,19 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||||
.using(new TradeTaskRunner(trade,
|
.using(new TradeTaskRunner(trade,
|
||||||
() -> {
|
() -> {
|
||||||
stopTimeout();
|
stopTimeout();
|
||||||
this.errorMessageHandler = null; // TODO: set this when trade state is >= DEPOSIT_PUBLISHED
|
|
||||||
handleTaskRunnerSuccess(sender, response);
|
// tasks may complete successfully but process an error
|
||||||
if (tradeResultHandler != null) tradeResultHandler.handleResult(trade); // trade is initialized
|
if (trade.getInitError() == null) {
|
||||||
|
this.errorMessageHandler = null; // TODO: set this when trade state is >= DEPOSIT_PUBLISHED
|
||||||
|
handleTaskRunnerSuccess(sender, response);
|
||||||
|
if (tradeResultHandler != null) tradeResultHandler.handleResult(trade); // trade is initialized
|
||||||
|
} else {
|
||||||
|
handleTaskRunnerSuccess(sender, response);
|
||||||
|
if (errorMessageHandler != null) errorMessageHandler.handleErrorMessage(trade.getInitError().getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tradeResultHandler = null;
|
||||||
|
this.errorMessageHandler = null;
|
||||||
},
|
},
|
||||||
errorMessage -> {
|
errorMessage -> {
|
||||||
handleTaskRunnerFault(sender, response, errorMessage);
|
handleTaskRunnerFault(sender, response, errorMessage);
|
||||||
|
|
|
@ -95,6 +95,18 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
// set peer's signature
|
// set peer's signature
|
||||||
sender.setContractSignature(signature);
|
sender.setContractSignature(signature);
|
||||||
|
|
||||||
|
// subscribe to trade state once to send responses with ack or nack
|
||||||
|
if (!hasBothContractSignatures()) {
|
||||||
|
trade.stateProperty().addListener((obs, oldState, newState) -> {
|
||||||
|
if (oldState == newState) return;
|
||||||
|
if (newState == Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED) {
|
||||||
|
sendDepositResponsesOnce(trade.getProcessModel().error == null ? "Arbitrator failed to publish deposit txs within timeout for trade " + trade.getId() : trade.getProcessModel().error.getMessage());
|
||||||
|
} else if (newState.ordinal() >= Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS.ordinal()) {
|
||||||
|
sendDepositResponsesOnce(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// collect expected values
|
// collect expected values
|
||||||
Offer offer = trade.getOffer();
|
Offer offer = trade.getOffer();
|
||||||
boolean isFromTaker = sender == trade.getTaker();
|
boolean isFromTaker = sender == trade.getTaker();
|
||||||
|
@ -138,7 +150,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
|
|
||||||
// relay deposit txs when both requests received
|
// relay deposit txs when both requests received
|
||||||
MoneroDaemon daemon = trade.getXmrWalletService().getDaemon();
|
MoneroDaemon daemon = trade.getXmrWalletService().getDaemon();
|
||||||
if (processModel.getMaker().getContractSignature() != null && processModel.getTaker().getContractSignature() != null) {
|
if (hasBothContractSignatures()) {
|
||||||
|
|
||||||
// check timeout and extend just before relaying
|
// check timeout and extend just before relaying
|
||||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out before relaying deposit txs for {} {}" + trade.getClass().getSimpleName() + " " + trade.getShortId());
|
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out before relaying deposit txs for {} {}" + trade.getClass().getSimpleName() + " " + trade.getShortId());
|
||||||
|
@ -182,22 +194,15 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// subscribe to trade state once to send responses with ack or nack
|
|
||||||
trade.stateProperty().addListener((obs, oldState, newState) -> {
|
|
||||||
if (oldState == newState) return;
|
|
||||||
if (newState == Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED) {
|
|
||||||
sendDepositResponsesOnce(trade.getProcessModel().error == null ? "Arbitrator failed to publish deposit txs within timeout for trade " + trade.getId() : trade.getProcessModel().error.getMessage());
|
|
||||||
} else if (newState.ordinal() >= Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS.ordinal()) {
|
|
||||||
sendDepositResponsesOnce(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (processModel.getMaker().getDepositTxHex() == null) log.info("Arbitrator waiting for deposit request from maker for trade " + trade.getId());
|
if (processModel.getMaker().getDepositTxHex() == null) log.info("Arbitrator waiting for deposit request from maker for trade " + trade.getId());
|
||||||
if (processModel.getTaker().getDepositTxHex() == null && !trade.hasBuyerAsTakerWithoutDeposit()) log.info("Arbitrator waiting for deposit request from taker for trade " + trade.getId());
|
if (processModel.getTaker().getDepositTxHex() == null && !trade.hasBuyerAsTakerWithoutDeposit()) log.info("Arbitrator waiting for deposit request from taker for trade " + trade.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasBothContractSignatures() {
|
||||||
|
return processModel.getMaker().getContractSignature() != null && processModel.getTaker().getContractSignature() != null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isTimedOut() {
|
private boolean isTimedOut() {
|
||||||
return !processModel.getTradeManager().hasOpenTrade(trade);
|
return !processModel.getTradeManager().hasOpenTrade(trade);
|
||||||
}
|
}
|
||||||
|
@ -210,7 +215,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
|
|
||||||
// log error
|
// log error
|
||||||
if (errorMessage != null) {
|
if (errorMessage != null) {
|
||||||
log.warn("Sending deposit responses with error={}", errorMessage, new Throwable("Stack trace"));
|
log.warn("Sending deposit responses for tradeId={}, error={}", trade.getId(), errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create deposit response
|
// create deposit response
|
||||||
|
@ -229,7 +234,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendDepositResponse(NodeAddress nodeAddress, PubKeyRing pubKeyRing, DepositResponse response) {
|
private void sendDepositResponse(NodeAddress nodeAddress, PubKeyRing pubKeyRing, DepositResponse response) {
|
||||||
log.info("Sending deposit response to trader={}; offerId={}, error={}", nodeAddress, trade.getId(), trade.getProcessModel().error);
|
log.info("Sending deposit response to trader={}; offerId={}, error={}", nodeAddress, trade.getId(), response.getErrorMessage());
|
||||||
processModel.getP2PService().sendEncryptedDirectMessage(nodeAddress, pubKeyRing, response, new SendDirectMessageListener() {
|
processModel.getP2PService().sendEncryptedDirectMessage(nodeAddress, pubKeyRing, response, new SendDirectMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onArrived() {
|
public void onArrived() {
|
||||||
|
|
|
@ -38,13 +38,14 @@ public class ProcessDepositResponse extends TradeTask {
|
||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
// throw if error
|
// handle error
|
||||||
DepositResponse message = (DepositResponse) processModel.getTradeMessage();
|
DepositResponse message = (DepositResponse) processModel.getTradeMessage();
|
||||||
if (message.getErrorMessage() != null) {
|
if (message.getErrorMessage() != null) {
|
||||||
log.warn("Unregistering trade {} {} because deposit response has error message={}", trade.getClass().getSimpleName(), trade.getShortId(), message.getErrorMessage());
|
log.warn("Deposit response for {} {} has error message={}", trade.getClass().getSimpleName(), trade.getShortId(), message.getErrorMessage());
|
||||||
trade.setStateIfValidTransitionTo(Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED);
|
trade.setStateIfValidTransitionTo(Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED);
|
||||||
processModel.getTradeManager().unregisterTrade(trade);
|
trade.setInitError(new RuntimeException(message.getErrorMessage()));
|
||||||
throw new RuntimeException(message.getErrorMessage());
|
complete();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// record security deposits
|
// record security deposits
|
||||||
|
|
|
@ -105,7 +105,6 @@ public abstract class XmrWalletBase {
|
||||||
// start polling wallet for progress
|
// start polling wallet for progress
|
||||||
syncProgressLatch = new CountDownLatch(1);
|
syncProgressLatch = new CountDownLatch(1);
|
||||||
syncProgressLooper = new TaskLooper(() -> {
|
syncProgressLooper = new TaskLooper(() -> {
|
||||||
if (wallet == null) return;
|
|
||||||
long height;
|
long height;
|
||||||
try {
|
try {
|
||||||
height = wallet.getHeight(); // can get read timeout while syncing
|
height = wallet.getHeight(); // can get read timeout while syncing
|
||||||
|
|
|
@ -346,7 +346,8 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
||||||
List<XmrAddressEntry> addressEntries = xmrWalletService.getAddressEntries();
|
List<XmrAddressEntry> addressEntries = xmrWalletService.getAddressEntries();
|
||||||
List<DepositListItem> items = new ArrayList<>();
|
List<DepositListItem> items = new ArrayList<>();
|
||||||
for (XmrAddressEntry addressEntry : addressEntries) {
|
for (XmrAddressEntry addressEntry : addressEntries) {
|
||||||
if (addressEntry.isTradePayout()) continue; // do not show trade payout addresses
|
DepositListItem item = new DepositListItem(addressEntry, xmrWalletService, formatter);
|
||||||
|
if (addressEntry.isTradePayout() && BigInteger.ZERO.equals(item.getBalanceAsBI())) continue; // do not show empty trade payout addresses
|
||||||
items.add(new DepositListItem(addressEntry, xmrWalletService, formatter));
|
items.add(new DepositListItem(addressEntry, xmrWalletService, formatter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue