arbitrator sends same dispute payout tx to both peers on resolve w/ grpc

fix npe in trade.get*DepositTx()
This commit is contained in:
woodser 2023-02-22 13:06:22 -05:00
parent 55650c495b
commit ce579b78ca
5 changed files with 18 additions and 18 deletions

View file

@ -170,14 +170,17 @@ public class CoreDisputesService {
} }
applyPayoutAmountsToDisputeResult(payout, winningDispute, disputeResult, customWinnerAmount); applyPayoutAmountsToDisputeResult(payout, winningDispute, disputeResult, customWinnerAmount);
// close dispute ticket // create dispute payout tx
closeDisputeTicket(arbitrationManager, winningDispute, disputeResult, null, () -> { MoneroTxWallet disputePayoutTx = arbitrationManager.createDisputePayoutTx(trade, winningDispute.getContract(), disputeResult, false);
// close winning dispute ticket
closeDisputeTicket(arbitrationManager, winningDispute, disputeResult, disputePayoutTx, () -> {
arbitrationManager.requestPersistence(); arbitrationManager.requestPersistence();
}, (errMessage, err) -> { }, (errMessage, err) -> {
throw new IllegalStateException(errMessage, err); throw new IllegalStateException(errMessage, err);
}); });
// close peer's dispute ticket // close loser's dispute ticket
var peersDisputeOptional = arbitrationManager.getDisputesAsObservableList().stream() var peersDisputeOptional = arbitrationManager.getDisputesAsObservableList().stream()
.filter(d -> tradeId.equals(d.getTradeId()) && winningDispute.getTraderId() != d.getTraderId()) .filter(d -> tradeId.equals(d.getTradeId()) && winningDispute.getTraderId() != d.getTraderId())
.findFirst(); .findFirst();
@ -186,7 +189,7 @@ public class CoreDisputesService {
var peerDisputeResult = createDisputeResult(peerDispute, winner, reason, summaryNotes, closeDate); var peerDisputeResult = createDisputeResult(peerDispute, winner, reason, summaryNotes, closeDate);
peerDisputeResult.setBuyerPayoutAmount(disputeResult.getBuyerPayoutAmount()); peerDisputeResult.setBuyerPayoutAmount(disputeResult.getBuyerPayoutAmount());
peerDisputeResult.setSellerPayoutAmount(disputeResult.getSellerPayoutAmount()); peerDisputeResult.setSellerPayoutAmount(disputeResult.getSellerPayoutAmount());
closeDisputeTicket(arbitrationManager, peerDispute, peerDisputeResult, null, () -> { closeDisputeTicket(arbitrationManager, peerDispute, peerDisputeResult, disputePayoutTx, () -> {
arbitrationManager.requestPersistence(); arbitrationManager.requestPersistence();
}, (errMessage, err) -> { }, (errMessage, err) -> {
throw new IllegalStateException(errMessage, err); throw new IllegalStateException(errMessage, err);

View file

@ -708,7 +708,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
if (trade == null) throw new RuntimeException("Dispute trade " + dispute.getTradeId() + " does not exist"); if (trade == null) throw new RuntimeException("Dispute trade " + dispute.getTradeId() + " does not exist");
// create dispute payout tx if not given // create dispute payout tx if not given
if (payoutTx == null) payoutTx = createDisputePayoutTx(trade, dispute, disputeResult, false); // can be null if already published or we don't have receiver's multisig hex if (payoutTx == null) payoutTx = createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false); // can be null if already published or we don't have receiver's multisig hex
// persist result in dispute's chat message once // persist result in dispute's chat message once
boolean resending = disputeResult.getChatMessage() != null; boolean resending = disputeResult.getChatMessage() != null;
@ -814,15 +814,14 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
// Utils // Utils
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public MoneroTxWallet createDisputePayoutTx(Trade trade, Dispute dispute, DisputeResult disputeResult, boolean skipMultisigImport) { public MoneroTxWallet createDisputePayoutTx(Trade trade, Contract contract, DisputeResult disputeResult, boolean skipMultisigImport) {
// sync and save wallet // sync and save wallet
trade.syncWallet(); trade.syncWallet();
trade.saveWallet(); trade.saveWallet();
// create unsigned dispute payout tx if not already published and arbitrator has trader's updated multisig info // create unsigned dispute payout tx if not already published
TradePeer receiver = trade.getTradePeer(dispute.getTraderPubKeyRing()); if (!trade.isPayoutPublished()) {
if (!trade.isPayoutPublished() && receiver.getUpdatedMultisigHex() != null) {
MoneroWallet multisigWallet = trade.getWallet(); MoneroWallet multisigWallet = trade.getWallet();
// import multisig hex // import multisig hex
@ -840,10 +839,9 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
try { try {
// trade wallet must be synced // trade wallet must be synced
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 " + dispute.getTradeId()); 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());
// collect winner and loser payout address and amounts // collect winner and loser payout address and amounts
Contract contract = dispute.getContract();
String winnerPayoutAddress = disputeResult.getWinner() == Winner.BUYER ? String winnerPayoutAddress = disputeResult.getWinner() == Winner.BUYER ?
(contract.isBuyerMakerAndSellerTaker() ? contract.getMakerPayoutAddressString() : contract.getTakerPayoutAddressString()) : (contract.isBuyerMakerAndSellerTaker() ? contract.getMakerPayoutAddressString() : contract.getTakerPayoutAddressString()) :
(contract.isBuyerMakerAndSellerTaker() ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString()); (contract.isBuyerMakerAndSellerTaker() ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString());

View file

@ -292,7 +292,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
} }
} else { } else {
if (trade.isPayoutPublished()) log.info("Dispute payout tx already published for {} {}", trade.getClass().getSimpleName(), trade.getId()); if (trade.isPayoutPublished()) log.info("Dispute payout tx already published for {} {}", trade.getClass().getSimpleName(), trade.getId());
else if (disputeClosedMessage.getUnsignedPayoutTxHex() == null) log.info("{} did not receive unsigned dispute payout tx for trade {} because the arbitrator did not have their updated multisig info (can happen if trader went offline after trade started)", trade.getClass().getName(), trade.getId()); else if (disputeClosedMessage.getUnsignedPayoutTxHex() == null) log.info("{} did not receive unsigned dispute payout tx for trade {} because the arbitrator did not have their updated multisig info (can happen if trader went offline after trade started)", trade.getClass().getSimpleName(), trade.getId());
} }
// We use the chatMessage as we only persist those not the DisputeClosedMessage. // We use the chatMessage as we only persist those not the DisputeClosedMessage.
@ -430,7 +430,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
// TODO (monero-project): creating tx will require exchanging updated multisig hex if message needs reprocessed. provide weight with describe_transfer so fee can be estimated? // TODO (monero-project): creating tx will require exchanging updated multisig hex if message needs reprocessed. provide weight with describe_transfer so fee can be estimated?
MoneroTxWallet feeEstimateTx = null; MoneroTxWallet feeEstimateTx = null;
try { try {
feeEstimateTx = createDisputePayoutTx(trade, dispute, disputeResult, true); feeEstimateTx = createDisputePayoutTx(trade, dispute.getContract(), disputeResult, true);
} catch (Exception e) { } catch (Exception e) {
log.warn("Could not recreate dispute payout tx to verify fee: " + e.getMessage()); log.warn("Could not recreate dispute payout tx to verify fee: " + e.getMessage());
} }

View file

@ -1059,7 +1059,7 @@ public abstract class Trade implements Tradable, Model {
private MoneroTx getDepositTx(TradePeer trader) { private MoneroTx getDepositTx(TradePeer trader) {
String depositId = trader.getDepositTxHash(); String depositId = trader.getDepositTxHash();
try { try {
if (trader == null || !trader.getDepositTx().isConfirmed()) { if (trader.getDepositTx() == null || !trader.getDepositTx().isConfirmed()) {
trader.setDepositTx(getTxFromWalletOrDaemon(depositId)); trader.setDepositTx(getTxFromWalletOrDaemon(depositId));
} }
return trader.getDepositTx(); return trader.getDepositTx();
@ -1578,8 +1578,7 @@ public abstract class Trade implements Tradable, Model {
@Nullable @Nullable
public MoneroTxWallet getPayoutTx() { public MoneroTxWallet getPayoutTx() {
if (payoutTx == null) if (payoutTx == null) payoutTx = payoutTxId == null ? null : xmrWalletService.getWallet().getTx(payoutTxId);
payoutTx = payoutTxId != null ? xmrWalletService.getWallet().getTx(payoutTxId) : null;
return payoutTx; return payoutTx;
} }

View file

@ -590,8 +590,8 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
closeTicketButton.setOnAction(e -> { closeTicketButton.setOnAction(e -> {
// create payout tx // get or create payout tx
MoneroTxWallet payoutTx = arbitrationManager.createDisputePayoutTx(trade, dispute, disputeResult, false); MoneroTxWallet payoutTx = trade.isPayoutPublished() ? trade.getPayoutTx() : arbitrationManager.createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false);
// show confirmation // show confirmation
if (dispute.getSupportType() == SupportType.ARBITRATION && if (dispute.getSupportType() == SupportType.ARBITRATION &&