Skip to content

Commit 583b0dd

Browse files
committed
improve error handling on create dispute payout tx
1 parent 017d8d5 commit 583b0dd

File tree

2 files changed

+73
-62
lines changed

2 files changed

+73
-62
lines changed

core/src/main/java/haveno/core/support/dispute/DisputeManager.java

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -934,66 +934,66 @@ public MoneroTxWallet createDisputePayoutTx(Trade trade, Contract contract, Disp
934934
// sync and poll
935935
trade.syncAndPollWallet();
936936

937-
// create unsigned dispute payout tx if not already published
938-
if (!trade.isPayoutPublished()) {
937+
// check if payout tx already published
938+
String alreadyPublishedMsg = "Cannot create dispute payout tx because payout tx is already published for trade " + trade.getId();
939+
if (trade.isPayoutPublished()) throw new RuntimeException(alreadyPublishedMsg);
939940

940-
// create unsigned dispute payout tx
941-
if (updateState) log.info("Creating unsigned dispute payout tx for trade {}", trade.getId());
942-
try {
941+
// create unsigned dispute payout tx
942+
if (updateState) log.info("Creating unsigned dispute payout tx for trade {}", trade.getId());
943+
try {
943944

944-
// trade wallet must be synced
945-
if (trade.getWallet().isMultisigImportNeeded()) throw new RuntimeException("Arbitrator's wallet needs updated multisig hex to create payout tx which means a trader must have already broadcast the payout tx for trade " + trade.getId());
945+
// trade wallet must be synced
946+
if (trade.getWallet().isMultisigImportNeeded()) throw new RuntimeException("Arbitrator's wallet needs updated multisig hex to create payout tx which means a trader must have already broadcast the payout tx for trade " + trade.getId());
946947

947-
// check amounts
948-
if (disputeResult.getBuyerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Buyer payout cannot be negative");
949-
if (disputeResult.getSellerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Seller payout cannot be negative");
950-
if (disputeResult.getBuyerPayoutAmountBeforeCost().add(disputeResult.getSellerPayoutAmountBeforeCost()).compareTo(trade.getWallet().getUnlockedBalance()) > 0) {
951-
throw new RuntimeException("The payout amounts are more than the wallet's unlocked balance, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs " + disputeResult.getBuyerPayoutAmountBeforeCost() + " + " + disputeResult.getSellerPayoutAmountBeforeCost() + " = " + (disputeResult.getBuyerPayoutAmountBeforeCost().add(disputeResult.getSellerPayoutAmountBeforeCost())));
952-
}
948+
// check amounts
949+
if (disputeResult.getBuyerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Buyer payout cannot be negative");
950+
if (disputeResult.getSellerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Seller payout cannot be negative");
951+
if (disputeResult.getBuyerPayoutAmountBeforeCost().add(disputeResult.getSellerPayoutAmountBeforeCost()).compareTo(trade.getWallet().getUnlockedBalance()) > 0) {
952+
throw new RuntimeException("The payout amounts are more than the wallet's unlocked balance, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs " + disputeResult.getBuyerPayoutAmountBeforeCost() + " + " + disputeResult.getSellerPayoutAmountBeforeCost() + " = " + (disputeResult.getBuyerPayoutAmountBeforeCost().add(disputeResult.getSellerPayoutAmountBeforeCost())));
953+
}
953954

954-
// create dispute payout tx config
955-
MoneroTxConfig txConfig = new MoneroTxConfig().setAccountIndex(0);
956-
String buyerPayoutAddress = contract.isBuyerMakerAndSellerTaker() ? contract.getMakerPayoutAddressString() : contract.getTakerPayoutAddressString();
957-
String sellerPayoutAddress = contract.isBuyerMakerAndSellerTaker() ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString();
958-
txConfig.setPriority(XmrWalletService.PROTOCOL_FEE_PRIORITY);
959-
if (disputeResult.getBuyerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(buyerPayoutAddress, disputeResult.getBuyerPayoutAmountBeforeCost());
960-
if (disputeResult.getSellerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(sellerPayoutAddress, disputeResult.getSellerPayoutAmountBeforeCost());
961-
962-
// configure who pays mining fee
963-
BigInteger loserPayoutAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmountBeforeCost() : disputeResult.getBuyerPayoutAmountBeforeCost();
964-
if (loserPayoutAmount.equals(BigInteger.ZERO)) txConfig.setSubtractFeeFrom(0); // winner pays fee if loser gets 0
965-
else {
966-
switch (disputeResult.getSubtractFeeFrom()) {
967-
case BUYER_AND_SELLER:
968-
txConfig.setSubtractFeeFrom(0, 1);
969-
break;
970-
case BUYER_ONLY:
971-
txConfig.setSubtractFeeFrom(0);
972-
break;
973-
case SELLER_ONLY:
974-
txConfig.setSubtractFeeFrom(1);
975-
break;
976-
}
955+
// create dispute payout tx config
956+
MoneroTxConfig txConfig = new MoneroTxConfig().setAccountIndex(0);
957+
String buyerPayoutAddress = contract.isBuyerMakerAndSellerTaker() ? contract.getMakerPayoutAddressString() : contract.getTakerPayoutAddressString();
958+
String sellerPayoutAddress = contract.isBuyerMakerAndSellerTaker() ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString();
959+
txConfig.setPriority(XmrWalletService.PROTOCOL_FEE_PRIORITY);
960+
if (disputeResult.getBuyerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(buyerPayoutAddress, disputeResult.getBuyerPayoutAmountBeforeCost());
961+
if (disputeResult.getSellerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(sellerPayoutAddress, disputeResult.getSellerPayoutAmountBeforeCost());
962+
963+
// configure who pays mining fee
964+
BigInteger loserPayoutAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmountBeforeCost() : disputeResult.getBuyerPayoutAmountBeforeCost();
965+
if (loserPayoutAmount.equals(BigInteger.ZERO)) txConfig.setSubtractFeeFrom(0); // winner pays fee if loser gets 0
966+
else {
967+
switch (disputeResult.getSubtractFeeFrom()) {
968+
case BUYER_AND_SELLER:
969+
txConfig.setSubtractFeeFrom(0, 1);
970+
break;
971+
case BUYER_ONLY:
972+
txConfig.setSubtractFeeFrom(0);
973+
break;
974+
case SELLER_ONLY:
975+
txConfig.setSubtractFeeFrom(1);
976+
break;
977977
}
978+
}
978979

979-
// create dispute payout tx
980-
MoneroTxWallet payoutTx = trade.createDisputePayoutTx(txConfig);
981-
982-
// update trade state
983-
if (updateState) {
984-
trade.getProcessModel().setUnsignedPayoutTx(payoutTx);
985-
trade.updatePayout(payoutTx);
986-
if (trade.getBuyer().getUpdatedMultisigHex() != null) trade.getBuyer().setUnsignedPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex());
987-
if (trade.getSeller().getUpdatedMultisigHex() != null) trade.getSeller().setUnsignedPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex());
988-
}
989-
trade.requestPersistence();
990-
return payoutTx;
991-
} catch (Exception e) {
992-
trade.syncAndPollWallet();
993-
if (!trade.isPayoutPublished()) throw e;
980+
// create dispute payout tx
981+
MoneroTxWallet payoutTx = trade.createDisputePayoutTx(txConfig);
982+
983+
// update trade state
984+
if (updateState) {
985+
trade.getProcessModel().setUnsignedPayoutTx(payoutTx);
986+
trade.updatePayout(payoutTx);
987+
if (trade.getBuyer().getUpdatedMultisigHex() != null) trade.getBuyer().setUnsignedPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex());
988+
if (trade.getSeller().getUpdatedMultisigHex() != null) trade.getSeller().setUnsignedPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex());
994989
}
990+
trade.requestPersistence();
991+
return payoutTx;
992+
} catch (Exception e) {
993+
trade.syncAndPollWallet();
994+
if (trade.isPayoutPublished()) throw new RuntimeException(alreadyPublishedMsg);
995+
throw e;
995996
}
996-
return null; // can be null if already published or we don't have receiver's multisig hex
997997
}
998998

999999
private Tuple2<NodeAddress, PubKeyRing> getNodeAddressPubKeyRingTuple(Dispute dispute) {

desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -581,16 +581,27 @@ private void addButtons(Contract contract) {
581581
!trade.isPayoutPublished()) {
582582

583583
// create payout tx
584-
MoneroTxWallet payoutTx = arbitrationManager.createDisputePayoutTx(trade, dispute.getContract(), disputeResult, true);
585-
586-
// show confirmation
587-
showPayoutTxConfirmation(contract,
588-
payoutTx,
589-
() -> doClose(closeTicketButton, cancelButton),
590-
() -> {
591-
closeTicketButton.setDisable(false);
592-
cancelButton.setDisable(false);
593-
});
584+
try {
585+
MoneroTxWallet payoutTx = arbitrationManager.createDisputePayoutTx(trade, dispute.getContract(), disputeResult, true);
586+
587+
// show confirmation
588+
showPayoutTxConfirmation(contract,
589+
payoutTx,
590+
() -> doClose(closeTicketButton, cancelButton),
591+
() -> {
592+
closeTicketButton.setDisable(false);
593+
cancelButton.setDisable(false);
594+
});
595+
} catch (Exception ex) {
596+
if (trade.isPayoutPublished()) {
597+
doClose(closeTicketButton, cancelButton);
598+
} else {
599+
log.error("Error creating dispute payout tx for dispute: " + ex.getMessage(), ex);
600+
new Popup().error(ex.getMessage()).show();
601+
closeTicketButton.setDisable(false);
602+
cancelButton.setDisable(false);
603+
}
604+
}
594605
} else {
595606
doClose(closeTicketButton, cancelButton);
596607
}

0 commit comments

Comments
 (0)