mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-22 11:39:29 +00:00
add trade init steps and reset timeout
This commit is contained in:
parent
6fb846d783
commit
78ec06b851
18 changed files with 63 additions and 36 deletions
|
@ -1151,7 +1151,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
user,
|
||||
keyRing,
|
||||
filterManager,
|
||||
accountAgeWitnessService);
|
||||
accountAgeWitnessService,
|
||||
this);
|
||||
|
||||
// create protocol
|
||||
PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(model,
|
||||
|
|
|
@ -23,6 +23,7 @@ import haveno.core.account.witness.AccountAgeWitnessService;
|
|||
import haveno.core.filter.FilterManager;
|
||||
import haveno.core.offer.OfferBookService;
|
||||
import haveno.core.offer.OpenOffer;
|
||||
import haveno.core.offer.OpenOfferManager;
|
||||
import haveno.core.offer.messages.SignOfferResponse;
|
||||
import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
|
||||
import haveno.core.support.dispute.mediation.mediator.MediatorManager;
|
||||
|
@ -61,6 +62,8 @@ public class PlaceOfferModel implements Model {
|
|||
private final FilterManager filterManager;
|
||||
@Getter
|
||||
private final AccountAgeWitnessService accountAgeWitnessService;
|
||||
@Getter
|
||||
private final OpenOfferManager openOfferManager;
|
||||
|
||||
// Mutable
|
||||
@Setter
|
||||
|
@ -89,7 +92,8 @@ public class PlaceOfferModel implements Model {
|
|||
User user,
|
||||
KeyRing keyRing,
|
||||
FilterManager filterManager,
|
||||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
OpenOfferManager openOfferManager) {
|
||||
this.openOffer = openOffer;
|
||||
this.reservedFundsForOffer = reservedFundsForOffer;
|
||||
this.useSavingsWallet = useSavingsWallet;
|
||||
|
@ -105,6 +109,7 @@ public class PlaceOfferModel implements Model {
|
|||
this.keyRing = keyRing;
|
||||
this.filterManager = filterManager;
|
||||
this.accountAgeWitnessService = accountAgeWitnessService;
|
||||
this.openOfferManager = openOfferManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -58,6 +58,10 @@ public class MakerReserveOfferFunds extends Task<PlaceOfferModel> {
|
|||
MoneroTxWallet reserveTx = null;
|
||||
synchronized (XmrWalletService.WALLET_LOCK) {
|
||||
|
||||
// reset protocol timeout
|
||||
verifyOpen();
|
||||
model.getProtocol().startTimeoutTimer();
|
||||
|
||||
// collect relevant info
|
||||
BigInteger penaltyFee = HavenoUtils.multiply(offer.getAmount(), offer.getPenaltyFeePct());
|
||||
BigInteger makerFee = offer.getMaxMakerFee();
|
||||
|
@ -71,6 +75,7 @@ public class MakerReserveOfferFunds extends Task<PlaceOfferModel> {
|
|||
synchronized (HavenoUtils.getWalletFunctionLock()) {
|
||||
for (int i = 0; i < TradeProtocol.MAX_ATTEMPTS; i++) {
|
||||
try {
|
||||
//if (true) throw new RuntimeException("Pretend error");
|
||||
reserveTx = model.getXmrWalletService().createReserveTx(penaltyFee, makerFee, sendAmount, securityDeposit, returnAddress, openOffer.isReserveExactAmount(), preferredSubaddressIndex);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error creating reserve tx, attempt={}/{}, offerId={}, error={}", i + 1, TradeProtocol.MAX_ATTEMPTS, openOffer.getShortId(), e.getMessage());
|
||||
|
@ -78,10 +83,8 @@ public class MakerReserveOfferFunds extends Task<PlaceOfferModel> {
|
|||
HavenoUtils.waitFor(TradeProtocol.REPROCESS_DELAY_MS); // wait before retrying
|
||||
}
|
||||
|
||||
// check for error in case creating reserve tx exceeded timeout // TODO: better way?
|
||||
if (!model.getXmrWalletService().getAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).isPresent()) {
|
||||
throw new RuntimeException("An error has occurred posting offer " + offer.getId() + " causing its subaddress entry to be deleted");
|
||||
}
|
||||
// verify still open
|
||||
verifyOpen();
|
||||
if (reserveTx != null) break;
|
||||
}
|
||||
}
|
||||
|
@ -108,4 +111,12 @@ public class MakerReserveOfferFunds extends Task<PlaceOfferModel> {
|
|||
failed(t);
|
||||
}
|
||||
}
|
||||
|
||||
public void verifyOpen() {
|
||||
if (!isOpen()) throw new RuntimeException("Offer " + model.getOpenOffer().getOffer().getId() + " is no longer open");
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return model.getOpenOfferManager().getOpenOfferById(model.getOpenOffer().getId()).isPresent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -359,7 +359,7 @@ public abstract class Trade implements Tradable, Model {
|
|||
private long takeOfferDate;
|
||||
|
||||
// Initialization
|
||||
private static final int TOTAL_INIT_STEPS = 15; // total estimated steps
|
||||
private static final int TOTAL_INIT_STEPS = 23; // total estimated steps
|
||||
private int initStep = 0;
|
||||
@Getter
|
||||
private double initProgress = 0;
|
||||
|
@ -1537,10 +1537,15 @@ public abstract class Trade implements Tradable, Model {
|
|||
}
|
||||
|
||||
public void addInitProgressStep() {
|
||||
startProtocolTimeout();
|
||||
initProgress = Math.min(1.0, (double) ++initStep / TOTAL_INIT_STEPS);
|
||||
UserThread.execute(() -> initProgressProperty.set(initProgress));
|
||||
}
|
||||
|
||||
public void startProtocolTimeout() {
|
||||
getProtocol().startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
if (isInitialized) {
|
||||
// We don't want to log at startup the setState calls from all persisted trades
|
||||
|
|
|
@ -869,7 +869,6 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
|||
trade.getMaker().setPubKeyRing(trade.getOffer().getPubKeyRing());
|
||||
trade.getSelf().setPubKeyRing(model.getPubKeyRing());
|
||||
trade.getSelf().setPaymentAccountId(paymentAccountId);
|
||||
trade.addInitProgressStep();
|
||||
|
||||
// ensure trade is not already open
|
||||
Optional<Trade> tradeOptional = getOpenTrade(offer.getId());
|
||||
|
@ -880,6 +879,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
|||
addTrade(trade);
|
||||
|
||||
initTradeAndProtocol(trade, tradeProtocol);
|
||||
trade.addInitProgressStep();
|
||||
|
||||
// process with protocol
|
||||
((TakerProtocol) tradeProtocol).onTakeOffer(result -> {
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ArbitratorProtocol extends DisputeProtocol {
|
|||
ArbitratorSendInitTradeOrMultisigRequests.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
handleTaskRunnerSuccess(peer, message);
|
||||
},
|
||||
errorMessage -> {
|
||||
|
|
|
@ -74,7 +74,7 @@ public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol
|
|||
MakerSendInitTradeRequest.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
handleTaskRunnerSuccess(peer, message);
|
||||
},
|
||||
errorMessage -> {
|
||||
|
|
|
@ -79,7 +79,7 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol
|
|||
TakerSendInitTradeRequestToArbitrator.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
unlatchTrade();
|
||||
},
|
||||
errorMessage -> {
|
||||
|
|
|
@ -79,7 +79,7 @@ public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtoc
|
|||
MakerSendInitTradeRequest.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
handleTaskRunnerSuccess(peer, message);
|
||||
},
|
||||
errorMessage -> {
|
||||
|
|
|
@ -80,7 +80,7 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc
|
|||
TakerSendInitTradeRequestToArbitrator.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
unlatchTrade();
|
||||
},
|
||||
errorMessage -> {
|
||||
|
|
|
@ -299,6 +299,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
|
||||
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
||||
System.out.println(getClass().getSimpleName() + ".handleInitMultisigRequest()");
|
||||
trade.addInitProgressStep();
|
||||
ThreadUtils.execute(() -> {
|
||||
synchronized (trade) {
|
||||
|
||||
|
@ -320,7 +321,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
MaybeSendSignContractRequest.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
handleTaskRunnerSuccess(sender, request);
|
||||
},
|
||||
errorMessage -> {
|
||||
|
@ -335,6 +336,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
|
||||
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
||||
System.out.println(getClass().getSimpleName() + ".handleSignContractRequest() " + trade.getId());
|
||||
trade.addInitProgressStep();
|
||||
ThreadUtils.execute(() -> {
|
||||
synchronized (trade) {
|
||||
|
||||
|
@ -358,7 +360,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
ProcessSignContractRequest.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
handleTaskRunnerSuccess(sender, message);
|
||||
},
|
||||
errorMessage -> {
|
||||
|
@ -380,6 +382,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
|
||||
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
||||
System.out.println(getClass().getSimpleName() + ".handleSignContractResponse() " + trade.getId());
|
||||
trade.addInitProgressStep();
|
||||
ThreadUtils.execute(() -> {
|
||||
synchronized (trade) {
|
||||
|
||||
|
@ -403,7 +406,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
SendDepositRequest.class)
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
startTimeout(TRADE_STEP_TIMEOUT_SECONDS);
|
||||
startTimeout();
|
||||
handleTaskRunnerSuccess(sender, message);
|
||||
},
|
||||
errorMessage -> {
|
||||
|
@ -425,6 +428,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
|
||||
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||
System.out.println(getClass().getSimpleName() + ".handleDepositResponse()");
|
||||
trade.addInitProgressStep();
|
||||
ThreadUtils.execute(() -> {
|
||||
synchronized (trade) {
|
||||
Validator.checkTradeId(processModel.getOfferId(), response);
|
||||
|
@ -716,6 +720,10 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||
// Timeout
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public synchronized void startTimeout() {
|
||||
startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
public synchronized void startTimeout(long timeoutSec) {
|
||||
synchronized (timeoutTimerLock) {
|
||||
stopTimeout();
|
||||
|
|
|
@ -28,7 +28,6 @@ import haveno.core.trade.Trade;
|
|||
import haveno.core.trade.messages.DepositRequest;
|
||||
import haveno.core.trade.messages.DepositResponse;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
import haveno.core.trade.protocol.TradeProtocol;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import haveno.network.p2p.SendDirectMessageListener;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -104,7 +103,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
|||
|
||||
// extend timeout
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out while verifying deposit tx for {} {}" + trade.getClass().getSimpleName() + " " + trade.getShortId());
|
||||
trade.getProtocol().startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
||||
trade.startProtocolTimeout();
|
||||
|
||||
// set deposit info
|
||||
trader.setSecurityDeposit(securityDeposit.subtract(verifiedTx.getFee())); // subtract mining fee from security deposit
|
||||
|
|
|
@ -83,7 +83,8 @@ public class MaybeSendSignContractRequest extends TradeTask {
|
|||
synchronized (XmrWalletService.WALLET_LOCK) {
|
||||
|
||||
// check for timeout
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out while creating deposit tx, tradeId=" + trade.getShortId());
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out while getting lock to create deposit tx, tradeId=" + trade.getShortId());
|
||||
trade.startProtocolTimeout();
|
||||
|
||||
// collect relevant info
|
||||
Integer subaddressIndex = null;
|
||||
|
@ -126,7 +127,7 @@ public class MaybeSendSignContractRequest extends TradeTask {
|
|||
}
|
||||
|
||||
// reset protocol timeout
|
||||
trade.getProtocol().startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
||||
trade.addInitProgressStep();
|
||||
|
||||
// collect reserved key images
|
||||
List<String> reservedKeyImages = new ArrayList<String>();
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.math.BigInteger;
|
|||
import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.messages.DepositResponse;
|
||||
import haveno.core.trade.protocol.TradeProtocol;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
|
@ -47,16 +46,12 @@ public class ProcessDepositResponse extends TradeTask {
|
|||
throw new RuntimeException(message.getErrorMessage());
|
||||
}
|
||||
|
||||
// reset protocol timeout
|
||||
trade.getProtocol().startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
||||
|
||||
// record security deposits
|
||||
trade.getBuyer().setSecurityDeposit(BigInteger.valueOf(message.getBuyerSecurityDeposit()));
|
||||
trade.getSeller().setSecurityDeposit(BigInteger.valueOf(message.getSellerSecurityDeposit()));
|
||||
|
||||
// set success state
|
||||
trade.setStateIfValidTransitionTo(Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS);
|
||||
trade.addInitProgressStep();
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
|
||||
// update balances
|
||||
|
|
|
@ -81,7 +81,6 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
|||
// prepare multisig if applicable
|
||||
boolean updateParticipants = false;
|
||||
if (trade.getSelf().getPreparedMultisigHex() == null) {
|
||||
trade.addInitProgressStep();
|
||||
log.info("Preparing multisig wallet for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||
multisigWallet = trade.createWallet();
|
||||
trade.getSelf().setPreparedMultisigHex(multisigWallet.prepareMultisig());
|
||||
|
|
|
@ -89,7 +89,6 @@ public class SendDepositRequest extends TradeTask {
|
|||
// update trade state
|
||||
trade.setState(Trade.State.SENT_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
trade.addInitProgressStep();
|
||||
|
||||
// send request to arbitrator
|
||||
log.info("Sending {} to arbitrator {}; offerId={}; uid={}", request.getClass().getSimpleName(), trade.getArbitrator().getNodeAddress(), trade.getId(), request.getUid());
|
||||
|
@ -99,6 +98,7 @@ public class SendDepositRequest extends TradeTask {
|
|||
log.info("{} arrived: arbitrator={}; offerId={}; uid={}", request.getClass().getSimpleName(), trade.getArbitrator().getNodeAddress(), trade.getId(), request.getUid());
|
||||
trade.setStateIfValidTransitionTo(Trade.State.SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
trade.addInitProgressStep();
|
||||
complete();
|
||||
}
|
||||
@Override
|
||||
|
|
|
@ -49,7 +49,8 @@ public class TakerReserveTradeFunds extends TradeTask {
|
|||
synchronized (XmrWalletService.WALLET_LOCK) {
|
||||
|
||||
// check for timeout
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out while creating reserve tx, tradeId=" + trade.getShortId());
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out while getting lock to create reserve tx, tradeId=" + trade.getShortId());
|
||||
trade.startProtocolTimeout();
|
||||
|
||||
// collect relevant info
|
||||
BigInteger penaltyFee = HavenoUtils.multiply(trade.getAmount(), trade.getOffer().getPenaltyFeePct());
|
||||
|
@ -76,7 +77,7 @@ public class TakerReserveTradeFunds extends TradeTask {
|
|||
}
|
||||
|
||||
// reset protocol timeout
|
||||
trade.getProtocol().startTimeout(TradeProtocol.TRADE_STEP_TIMEOUT_SECONDS);
|
||||
trade.startProtocolTimeout();
|
||||
|
||||
// collect reserved key images
|
||||
List<String> reservedKeyImages = new ArrayList<String>();
|
||||
|
|
|
@ -372,12 +372,6 @@ public class XmrWalletService {
|
|||
return useNativeXmrWallet && MoneroUtils.isNativeLibraryLoaded();
|
||||
}
|
||||
|
||||
public MoneroSyncResult syncWallet() {
|
||||
MoneroSyncResult result = syncWallet(wallet);
|
||||
walletHeight.set(wallet.getHeight());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync the given wallet in a thread pool with other wallets.
|
||||
*/
|
||||
|
@ -1799,7 +1793,7 @@ public class XmrWalletService {
|
|||
// sync wallet if behind daemon
|
||||
if (walletHeight.get() < xmrConnectionService.getTargetHeight()) {
|
||||
synchronized (WALLET_LOCK) { // avoid long sync from blocking other operations
|
||||
syncWallet();
|
||||
syncMainWallet();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1833,6 +1827,14 @@ public class XmrWalletService {
|
|||
}
|
||||
}
|
||||
|
||||
private MoneroSyncResult syncMainWallet() {
|
||||
synchronized (WALLET_LOCK) {
|
||||
MoneroSyncResult result = syncWallet(wallet);
|
||||
walletHeight.set(wallet.getHeight());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWalletConnectedToDaemon() {
|
||||
synchronized (WALLET_LOCK) {
|
||||
try {
|
||||
|
|
Loading…
Reference in a new issue