mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-22 19:49:32 +00:00
fix not enough signers on process payout tx
This commit is contained in:
parent
60b91d3d23
commit
3e3f3085f8
7 changed files with 30 additions and 20 deletions
|
@ -199,7 +199,7 @@ public abstract class SupportManager {
|
||||||
if (dispute.isClosed()) dispute.reOpen();
|
if (dispute.isClosed()) dispute.reOpen();
|
||||||
trade.advanceDisputeState(Trade.DisputeState.DISPUTE_OPENED);
|
trade.advanceDisputeState(Trade.DisputeState.DISPUTE_OPENED);
|
||||||
} else if (dispute.isClosed()) {
|
} else if (dispute.isClosed()) {
|
||||||
trade.pollWalletNormallyForMs(30000); // sync to check for payout
|
trade.pollWalletNormallyForMs(60000); // sync to check for payout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -854,7 +854,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||||
// the state, as that is displayed to the user and we only persist that msg
|
// the state, as that is displayed to the user and we only persist that msg
|
||||||
disputeResult.getChatMessage().setArrived(true);
|
disputeResult.getChatMessage().setArrived(true);
|
||||||
trade.advanceDisputeState(Trade.DisputeState.ARBITRATOR_SAW_ARRIVED_DISPUTE_CLOSED_MSG);
|
trade.advanceDisputeState(Trade.DisputeState.ARBITRATOR_SAW_ARRIVED_DISPUTE_CLOSED_MSG);
|
||||||
trade.pollWalletNormallyForMs(30000);
|
trade.pollWalletNormallyForMs(60000);
|
||||||
requestPersistence(trade);
|
requestPersistence(trade);
|
||||||
resultHandler.handleResult();
|
resultHandler.handleResult();
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,7 +361,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
||||||
requestPersistence(trade);
|
requestPersistence(trade);
|
||||||
|
|
||||||
// nack bad message and do not reprocess
|
// nack bad message and do not reprocess
|
||||||
if (e instanceof IllegalArgumentException || e instanceof IllegalStateException) {
|
if (HavenoUtils.isIllegal(e)) {
|
||||||
trade.getArbitrator().setDisputeClosedMessage(null); // message is processed
|
trade.getArbitrator().setDisputeClosedMessage(null); // message is processed
|
||||||
trade.setDisputeState(Trade.DisputeState.DISPUTE_CLOSED);
|
trade.setDisputeState(Trade.DisputeState.DISPUTE_CLOSED);
|
||||||
String warningMsg = "Error processing dispute closed message: " + e.getMessage() + "\n\nOpen another dispute to try again (ctrl+o).";
|
String warningMsg = "Error processing dispute closed message: " + e.getMessage() + "\n\nOpen another dispute to try again (ctrl+o).";
|
||||||
|
|
|
@ -510,19 +510,27 @@ public class HavenoUtils {
|
||||||
havenoSetup.getTopErrorMsg().set(msg);
|
havenoSetup.getTopErrorMsg().set(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isConnectionRefused(Exception e) {
|
public static boolean isConnectionRefused(Throwable e) {
|
||||||
return e != null && e.getMessage().contains("Connection refused");
|
return e != null && e.getMessage().contains("Connection refused");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isReadTimeout(Exception e) {
|
public static boolean isReadTimeout(Throwable e) {
|
||||||
return e != null && e.getMessage().contains("Read timed out");
|
return e != null && e.getMessage().contains("Read timed out");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isUnresponsive(Exception e) {
|
public static boolean isUnresponsive(Throwable e) {
|
||||||
return isConnectionRefused(e) || isReadTimeout(e);
|
return isConnectionRefused(e) || isReadTimeout(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNotEnoughSigners(Exception e) {
|
public static boolean isNotEnoughSigners(Throwable e) {
|
||||||
return e != null && e.getMessage().contains("Not enough signers");
|
return e != null && e.getMessage().contains("Not enough signers");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isTransactionRejected(Throwable e) {
|
||||||
|
return e != null && e.getMessage().contains("was rejected");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isIllegal(Throwable e) {
|
||||||
|
return e instanceof IllegalArgumentException || e instanceof IllegalStateException;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1158,7 +1158,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
|
|
||||||
private void handleWalletError(Exception e, MoneroRpcConnection sourceConnection) {
|
private void handleWalletError(Exception e, MoneroRpcConnection sourceConnection) {
|
||||||
if (HavenoUtils.isUnresponsive(e)) forceCloseWallet(); // wallet can be stuck a while
|
if (HavenoUtils.isUnresponsive(e)) forceCloseWallet(); // wallet can be stuck a while
|
||||||
if (xmrConnectionService.isConnected()) requestSwitchToNextBestConnection(sourceConnection);
|
if (!HavenoUtils.isIllegal(e) && xmrConnectionService.isConnected()) requestSwitchToNextBestConnection(sourceConnection);
|
||||||
getWallet(); // re-open wallet
|
getWallet(); // re-open wallet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,7 +1278,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Failed to process payout tx, tradeId={}, attempt={}/{}, error={}", getShortId(), i + 1, TradeProtocol.MAX_ATTEMPTS, e.getMessage());
|
log.warn("Failed to process payout tx, tradeId={}, attempt={}/{}, error={}", getShortId(), i + 1, TradeProtocol.MAX_ATTEMPTS, e.getMessage(), e);
|
||||||
handleWalletError(e, sourceConnection);
|
handleWalletError(e, sourceConnection);
|
||||||
if (i == TradeProtocol.MAX_ATTEMPTS - 1) throw e;
|
if (i == TradeProtocol.MAX_ATTEMPTS - 1) throw e;
|
||||||
HavenoUtils.waitFor(TradeProtocol.REPROCESS_DELAY_MS); // wait before retrying
|
HavenoUtils.waitFor(TradeProtocol.REPROCESS_DELAY_MS); // wait before retrying
|
||||||
|
@ -1350,14 +1350,13 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
try {
|
try {
|
||||||
MoneroMultisigSignResult result = wallet.signMultisigTxHex(payoutTxHex);
|
MoneroMultisigSignResult result = wallet.signMultisigTxHex(payoutTxHex);
|
||||||
if (result.getSignedMultisigTxHex() == null) throw new IllegalArgumentException("Error signing payout tx, signed multisig hex is null");
|
if (result.getSignedMultisigTxHex() == null) throw new IllegalArgumentException("Error signing payout tx, signed multisig hex is null");
|
||||||
payoutTxHex = result.getSignedMultisigTxHex();
|
setPayoutTxHex(result.getSignedMultisigTxHex());
|
||||||
setPayoutTxHex(payoutTxHex);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// describe result
|
// describe result
|
||||||
describedTxSet = wallet.describeMultisigTxSet(payoutTxHex);
|
describedTxSet = wallet.describeMultisigTxSet(getPayoutTxHex());
|
||||||
payoutTx = describedTxSet.getTxs().get(0);
|
payoutTx = describedTxSet.getTxs().get(0);
|
||||||
updatePayout(payoutTx);
|
updatePayout(payoutTx);
|
||||||
|
|
||||||
|
@ -1377,14 +1376,16 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||||
requestPersistence();
|
requestPersistence();
|
||||||
|
|
||||||
// submit payout tx
|
// submit payout tx
|
||||||
if (publish) {
|
boolean doPublish = publish && !isPayoutPublished();
|
||||||
|
if (doPublish) {
|
||||||
try {
|
try {
|
||||||
wallet.submitMultisigTxHex(payoutTxHex);
|
wallet.submitMultisigTxHex(getPayoutTxHex());
|
||||||
setPayoutStatePublished();
|
setPayoutStatePublished();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (isPayoutPublished()) throw new IllegalStateException("Payout tx already published for " + getClass().getSimpleName() + " " + getShortId());
|
if (!isPayoutPublished()) {
|
||||||
if (HavenoUtils.isNotEnoughSigners(e)) throw new IllegalArgumentException(e);
|
if (HavenoUtils.isTransactionRejected(e) || HavenoUtils.isNotEnoughSigners(e)) throw new IllegalArgumentException(e);
|
||||||
throw new RuntimeException("Failed to submit payout tx for " + getClass().getSimpleName() + " " + getId(), e);
|
throw new RuntimeException("Failed to submit payout tx for " + getClass().getSimpleName() + " " + getId() + ", error=" + e.getMessage(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
|
||||||
// do not reprocess illegal argument
|
// do not reprocess illegal argument
|
||||||
if (t instanceof IllegalArgumentException) {
|
if (HavenoUtils.isIllegal(t)) {
|
||||||
trade.getSeller().setPaymentReceivedMessage(null); // do not reprocess
|
trade.getSeller().setPaymentReceivedMessage(null); // do not reprocess
|
||||||
trade.requestPersistence();
|
trade.requestPersistence();
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
||||||
boolean deferSignAndPublish = trade instanceof ArbitratorTrade && !isSigned && message.isDeferPublishPayout();
|
boolean deferSignAndPublish = trade instanceof ArbitratorTrade && !isSigned && message.isDeferPublishPayout();
|
||||||
if (deferSignAndPublish) {
|
if (deferSignAndPublish) {
|
||||||
log.info("Deferring signing and publishing payout tx for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
log.info("Deferring signing and publishing payout tx for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||||
|
trade.pollWalletNormallyForMs(60000);
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
if (trade.isPayoutPublished()) break;
|
if (trade.isPayoutPublished()) break;
|
||||||
HavenoUtils.waitFor(Trade.DEFER_PUBLISH_MS / 5);
|
HavenoUtils.waitFor(Trade.DEFER_PUBLISH_MS / 5);
|
||||||
|
|
|
@ -65,10 +65,10 @@ public class SellerPreparePaymentReceivedMessage extends TradeTask {
|
||||||
trade.processPayoutTx(trade.getPayoutTxHex(), false, true);
|
trade.processPayoutTx(trade.getPayoutTxHex(), false, true);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||||
log.warn("Illegal state or argument verifying, signing, and publishing payout tx for {} {}: {}. Creating new unsigned payout tx", trade.getClass().getSimpleName(), trade.getId(), e.getMessage());
|
log.warn("Illegal state or argument verifying, signing, and publishing payout tx for {} {}: {}. Creating new unsigned payout tx", trade.getClass().getSimpleName(), trade.getId(), e.getMessage(), e);
|
||||||
createUnsignedPayoutTx();
|
createUnsignedPayoutTx();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Error verifying, signing, and publishing payout tx for trade {}: {}", trade.getId(), e.getMessage());
|
log.warn("Error verifying, signing, and publishing payout tx for trade {}: {}", trade.getId(), e.getMessage(), e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue