prefer overriding state if valid phase transition

This commit is contained in:
woodser 2025-11-21 18:00:12 -05:00
parent 8ef279522d
commit d607508eee
No known key found for this signature in database
GPG key ID: 55A10DD48ADEE5EF
11 changed files with 34 additions and 29 deletions

View file

@ -660,7 +660,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
if (trade.isArbitrator() && message.getPaymentSentMessage() != null) {
HavenoUtils.verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
trade.getBuyer().setUpdatedMultisigHex(message.getPaymentSentMessage().getUpdatedMultisigHex());
trade.advanceState(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
trade.setStateIfValidTransitionTo(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
}
// update opener's multisig hex

View file

@ -2275,12 +2275,6 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setStateIfValidTransitionTo(State newState) {
if (state.isValidTransitionTo(newState)) {
setState(newState);
}
}
public void addInitProgressStep() {
startProtocolTimeout();
initProgress = Math.min(1.0, (double) ++initStep / TOTAL_INIT_STEPS);
@ -2299,6 +2293,12 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
protocol.stopTimeout();
}
public void setStateIfValidTransitionTo(State newState) {
if (state.isValidTransitionTo(newState)) {
setState(newState);
}
}
public void setState(State state) {
// skip if no change
@ -2751,10 +2751,6 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
}
}
public boolean isPaymentSent() {
return getState().getPhase().ordinal() >= Phase.PAYMENT_SENT.ordinal() && getState() != State.BUYER_SEND_FAILED_PAYMENT_SENT_MSG;
}
public boolean hasPaymentSentMessage() {
return (isBuyer() ? getSeller() : getBuyer()).getPaymentSentMessage() != null; // buyer stores message to seller and arbitrator, peers store message from buyer
}
@ -2777,6 +2773,10 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
return getState().getPhase().ordinal() >= Phase.PAYMENT_SENT.ordinal();
}
public boolean isPaymentSent() {
return getState().getPhase().ordinal() >= Phase.PAYMENT_SENT.ordinal() && getState() != State.BUYER_SEND_FAILED_PAYMENT_SENT_MSG;
}
public boolean isPaymentMarkedReceived() {
return getState().getPhase().ordinal() >= Phase.PAYMENT_RECEIVED.ordinal();
}
@ -3813,7 +3813,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
}
private void setStateDepositsFinalized() {
if (!isPaymentSent() && !isDepositsFinalized()) advanceState(State.DEPOSIT_TXS_FINALIZED_IN_BLOCKCHAIN); // do not revert state if payment already sent
if (!isPaymentSent() && !isDepositsFinalized()) setStateIfValidTransitionTo(State.DEPOSIT_TXS_FINALIZED_IN_BLOCKCHAIN); // do not revert state if payment already sent
try {
maybeUpdateTradePeriod();
} catch (Exception e) {

View file

@ -127,7 +127,7 @@ public class BuyerProtocol extends DisputeProtocol {
// advance trade state
if (trade.isDepositsUnlocked() || trade.isDepositsFinalized() || trade.isPaymentSent()) {
trade.advanceState(Trade.State.BUYER_CONFIRMED_PAYMENT_SENT);
trade.setStateIfValidTransitionTo(Trade.State.BUYER_CONFIRMED_PAYMENT_SENT);
} else {
errorMessageHandler.handleErrorMessage("Cannot confirm payment sent for " + trade.getClass().getSimpleName() + " " + trade.getShortId() + " in state " + trade.getState());
return;

View file

@ -123,7 +123,7 @@ public class SellerProtocol extends DisputeProtocol {
// advance trade state
if (trade.isPaymentSent() || trade.isPaymentReceived()) {
trade.advanceState(Trade.State.SELLER_CONFIRMED_PAYMENT_RECEIPT);
trade.setStateIfValidTransitionTo(Trade.State.SELLER_CONFIRMED_PAYMENT_RECEIPT);
} else {
errorMessageHandler.handleErrorMessage("Cannot confirm payment received for " + trade.getClass().getSimpleName() + " " + trade.getShortId() + " in state " + trade.getState());
return;

View file

@ -620,7 +620,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
// the mailbox msg once wallet is ready and trade state set.
synchronized (trade.getLock()) {
if (!trade.isInitialized() || trade.isShutDownStarted()) return;
if (trade.getPhase().ordinal() >= Trade.Phase.PAYMENT_SENT.ordinal()) {
if (trade.getState().ordinal() >= Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal()) {
log.warn("Received another PaymentSentMessage which was already processed for {} {}, ACKing", trade.getClass().getSimpleName(), trade.getId());
handleTaskRunnerSuccess(trade.getBuyer().getNodeAddress(), message);
return;

View file

@ -39,7 +39,11 @@ public class BuyerSendPaymentSentMessageToSeller extends BuyerSendPaymentSentMes
@Override
protected void setStateSent() {
if (trade.getState().ordinal() < Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal()) trade.setStateIfValidTransitionTo(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
if (trade.getState().equals(Trade.State.BUYER_SEND_FAILED_PAYMENT_SENT_MSG)) {
trade.setState(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
} else {
trade.advanceState(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG); // do not revert previous send progress
}
super.setStateSent();
}

View file

@ -25,7 +25,6 @@ import haveno.core.trade.BuyerTrade;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.MakerTrade;
import haveno.core.trade.Trade;
import haveno.core.trade.Trade.State;
import haveno.core.trade.messages.SignContractRequest;
import haveno.core.trade.protocol.TradeProtocol;
import haveno.core.xmr.model.XmrAddressEntry;
@ -217,7 +216,7 @@ public class MaybeSendSignContractRequest extends TradeTask {
}
private void completeAux() {
trade.setState(State.CONTRACT_SIGNATURE_REQUESTED);
trade.setState(Trade.State.CONTRACT_SIGNATURE_REQUESTED);
trade.addInitProgressStep();
processModel.getTradeManager().requestPersistence();
complete();

View file

@ -40,7 +40,6 @@ import haveno.core.support.dispute.Dispute;
import haveno.core.trade.BuyerTrade;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade;
import haveno.core.trade.Trade.State;
import haveno.core.trade.messages.PaymentReceivedMessage;
import haveno.core.trade.messages.PaymentSentMessage;
import haveno.core.util.Validator;
@ -74,14 +73,14 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
trade.requestPersistence();
// ack and complete if already processed
if (trade.getState().ordinal() >= State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal() && trade.isPayoutPublished()) {
if (trade.getState().ordinal() >= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal() && trade.isPayoutPublished()) {
log.warn("Received another PaymentReceivedMessage which was already processed, ACKing");
complete();
return;
}
// set state to confirmed payment receipt before processing
trade.advanceState(State.SELLER_CONFIRMED_PAYMENT_RECEIPT);
trade.setStateIfValidTransitionTo(Trade.State.SELLER_CONFIRMED_PAYMENT_RECEIPT);
// cannot process until wallet sees deposits unlocked
if (!trade.isDepositsUnlocked()) {
@ -111,7 +110,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
}
// advance state, arbitrator auto completes when payout published
trade.advanceState(Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG);
trade.setStateIfValidTransitionTo(Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG);
// buyer republishes signed witness for resilience
SignedWitness signedWitness = message.getBuyerSignedWitness();

View file

@ -68,7 +68,7 @@ public class ProcessPaymentSentMessage extends TradeTask {
if (trade.isSeller()) trade.decryptPeerPaymentAccountPayload(message.getPaymentAccountKey());
// update state
trade.advanceState(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
trade.setStateIfValidTransitionTo(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
trade.requestPersistence();
complete();
} catch (Throwable t) {

View file

@ -29,7 +29,6 @@ import haveno.core.trade.ArbitratorTrade;
import haveno.core.trade.Contract;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade;
import haveno.core.trade.Trade.State;
import haveno.core.trade.messages.SignContractRequest;
import haveno.core.trade.messages.SignContractResponse;
import haveno.core.trade.protocol.TradePeer;
@ -162,7 +161,7 @@ public class ProcessSignContractRequest extends TradeTask {
private void completeAux() {
trade.addInitProgressStep();
trade.setState(State.CONTRACT_SIGNED);
trade.setState(Trade.State.CONTRACT_SIGNED);
processModel.getTradeManager().requestPersistence();
complete();
}

View file

@ -39,25 +39,29 @@ public class SellerSendPaymentReceivedMessageToBuyer extends SellerSendPaymentRe
@Override
protected void setStateSent() {
trade.advanceState(Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG);
if (trade.getState().equals(Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG)) {
trade.setState(Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG);
} else {
trade.advanceState(Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG); // do not revert previous send progress
}
super.setStateSent();
}
@Override
protected void setStateFault() {
trade.advanceState(Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG);
trade.setStateIfValidTransitionTo(Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG);
super.setStateFault();
}
@Override
protected void setStateStoredInMailbox() {
trade.advanceState(Trade.State.SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG);
trade.setStateIfValidTransitionTo(Trade.State.SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG);
super.setStateStoredInMailbox();
}
@Override
protected void setStateArrived() {
trade.advanceState(Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG);
trade.setStateIfValidTransitionTo(Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG);
super.setStateArrived();
}