mirror of
https://github.com/boldsuck/haveno.git
synced 2025-01-03 14:49:25 +00:00
stability improvements
synchronize timeout timer fix concurrent modification exceptions use wallet lock when saving multisig wallets
This commit is contained in:
parent
9fda20f88b
commit
3314eac881
8 changed files with 42 additions and 19 deletions
|
@ -106,7 +106,7 @@ public class CoreOffersService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Offer getOffer(String id) {
|
Offer getOffer(String id) {
|
||||||
return offerBookService.getOffers().stream()
|
return new ArrayList<>(offerBookService.getOffers()).stream()
|
||||||
.filter(o -> o.getId().equals(id))
|
.filter(o -> o.getId().equals(id))
|
||||||
.filter(o -> !o.isMyOffer(keyRing))
|
.filter(o -> !o.isMyOffer(keyRing))
|
||||||
.filter(o -> {
|
.filter(o -> {
|
||||||
|
@ -120,7 +120,7 @@ public class CoreOffersService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Offer getMyOffer(String id) {
|
Offer getMyOffer(String id) {
|
||||||
return openOfferManager.getObservableList().stream()
|
return new ArrayList<>(openOfferManager.getObservableList()).stream()
|
||||||
.map(OpenOffer::getOffer)
|
.map(OpenOffer::getOffer)
|
||||||
.filter(o -> o.getId().equals(id))
|
.filter(o -> o.getId().equals(id))
|
||||||
.filter(o -> o.isMyOffer(keyRing))
|
.filter(o -> o.isMyOffer(keyRing))
|
||||||
|
@ -129,7 +129,7 @@ public class CoreOffersService {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Offer> getOffers(String direction, String currencyCode) {
|
List<Offer> getOffers(String direction, String currencyCode) {
|
||||||
List<Offer> offers = offerBookService.getOffers().stream()
|
List<Offer> offers = new ArrayList<>(offerBookService.getOffers()).stream()
|
||||||
.filter(o -> !o.isMyOffer(keyRing))
|
.filter(o -> !o.isMyOffer(keyRing))
|
||||||
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
|
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
|
||||||
.filter(o -> {
|
.filter(o -> {
|
||||||
|
@ -145,7 +145,7 @@ public class CoreOffersService {
|
||||||
List<Offer> getMyOffers(String direction, String currencyCode) {
|
List<Offer> getMyOffers(String direction, String currencyCode) {
|
||||||
|
|
||||||
// get my open offers
|
// get my open offers
|
||||||
List<Offer> offers = openOfferManager.getObservableList().stream()
|
List<Offer> offers = new ArrayList<>(openOfferManager.getObservableList()).stream()
|
||||||
.map(OpenOffer::getOffer)
|
.map(OpenOffer::getOffer)
|
||||||
.filter(o -> o.isMyOffer(keyRing))
|
.filter(o -> o.isMyOffer(keyRing))
|
||||||
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
|
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
|
||||||
|
|
|
@ -166,6 +166,10 @@ public class XmrWalletService {
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveWallet() {
|
||||||
|
saveWallet(getWallet());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isWalletReady() {
|
public boolean isWalletReady() {
|
||||||
try {
|
try {
|
||||||
return getWallet() != null;
|
return getWallet() != null;
|
||||||
|
@ -227,7 +231,21 @@ public class XmrWalletService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveWallet(MoneroWallet wallet) {
|
public void saveMultisigWallet(String tradeId) {
|
||||||
|
log.info("{}.saveMultisigWallet({})", getClass().getSimpleName(), tradeId);
|
||||||
|
initWalletLock(tradeId);
|
||||||
|
synchronized (walletLocks.get(tradeId)) {
|
||||||
|
String walletName = MONERO_MULTISIG_WALLET_PREFIX + tradeId;
|
||||||
|
if (!walletExists(walletName)) {
|
||||||
|
log.warn("Multisig wallet for trade {} does not exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!multisigWallets.containsKey(tradeId)) throw new RuntimeException("Multisig wallet to save was not previously opened for trade " + tradeId);
|
||||||
|
saveWallet(multisigWallets.get(tradeId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveWallet(MoneroWallet wallet) {
|
||||||
wallet.save();
|
wallet.save();
|
||||||
backupWallet(wallet.getPath());
|
backupWallet(wallet.getPath());
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,11 +610,11 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<OpenOffer> getOpenOfferById(String offerId) {
|
public Optional<OpenOffer> getOpenOfferById(String offerId) {
|
||||||
return openOffers.getObservableList().stream().filter(e -> e.getId().equals(offerId)).findFirst();
|
return new ArrayList<>(openOffers.getObservableList()).stream().filter(e -> e.getId().equals(offerId)).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<SignedOffer> getSignedOfferById(String offerId) {
|
public Optional<SignedOffer> getSignedOfferById(String offerId) {
|
||||||
return signedOffers.getObservableList().stream().filter(e -> e.getOfferId().equals(offerId)).findFirst();
|
return new ArrayList<>(signedOffers.getObservableList()).stream().filter(e -> e.getOfferId().equals(offerId)).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -931,7 +931,7 @@ public abstract class Trade implements Tradable, Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveWallet() {
|
public void saveWallet() {
|
||||||
xmrWalletService.saveWallet(getWallet());
|
xmrWalletService.saveMultisigWallet(getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteWallet() {
|
public void deleteWallet() {
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc
|
||||||
@Override
|
@Override
|
||||||
public void onTakeOffer(TradeResultHandler tradeResultHandler,
|
public void onTakeOffer(TradeResultHandler tradeResultHandler,
|
||||||
ErrorMessageHandler errorMessageHandler) {
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".onTakeOffer()");
|
System.out.println(getClass().getSimpleName() + ".onTakeOffer()");
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
synchronized (trade) {
|
synchronized (trade) {
|
||||||
latchTrade();
|
latchTrade();
|
||||||
|
|
|
@ -84,6 +84,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||||
protected final Trade trade;
|
protected final Trade trade;
|
||||||
protected CountDownLatch tradeLatch; // to synchronize on trade
|
protected CountDownLatch tradeLatch; // to synchronize on trade
|
||||||
private Timer timeoutTimer;
|
private Timer timeoutTimer;
|
||||||
|
private Object timeoutTimerLock = new Object();
|
||||||
protected TradeResultHandler tradeResultHandler;
|
protected TradeResultHandler tradeResultHandler;
|
||||||
protected ErrorMessageHandler errorMessageHandler;
|
protected ErrorMessageHandler errorMessageHandler;
|
||||||
|
|
||||||
|
@ -357,7 +358,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||||
latchTrade();
|
latchTrade();
|
||||||
Validator.checkTradeId(processModel.getOfferId(), response);
|
Validator.checkTradeId(processModel.getOfferId(), response);
|
||||||
processModel.setTradeMessage(response);
|
processModel.setTradeMessage(response);
|
||||||
expect(anyState(Trade.State.SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST, Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS, Trade.State.DEPOSIT_TXS_SEEN_IN_NETWORK)
|
expect(anyState(Trade.State.SENT_PUBLISH_DEPOSIT_TX_REQUEST, Trade.State.SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST, Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS, Trade.State.DEPOSIT_TXS_SEEN_IN_NETWORK)
|
||||||
.with(response)
|
.with(response)
|
||||||
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
||||||
.setup(tasks(
|
.setup(tasks(
|
||||||
|
@ -600,16 +601,20 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
protected synchronized void startTimeout(long timeoutSec) {
|
protected synchronized void startTimeout(long timeoutSec) {
|
||||||
stopTimeout();
|
synchronized (timeoutTimerLock) {
|
||||||
timeoutTimer = UserThread.runAfter(() -> {
|
stopTimeout();
|
||||||
handleError("Timeout reached. Protocol did not complete in " + timeoutSec + " sec. TradeID=" + trade.getId() + ", state=" + trade.stateProperty().get());
|
timeoutTimer = UserThread.runAfter(() -> {
|
||||||
}, timeoutSec);
|
handleError("Timeout reached. Protocol did not complete in " + timeoutSec + " sec. TradeID=" + trade.getId() + ", state=" + trade.stateProperty().get());
|
||||||
|
}, timeoutSec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void stopTimeout() {
|
protected synchronized void stopTimeout() {
|
||||||
if (timeoutTimer != null) {
|
synchronized (timeoutTimerLock) {
|
||||||
timeoutTimer.stop();
|
if (timeoutTimer != null) {
|
||||||
timeoutTimer = null;
|
timeoutTimer.stop();
|
||||||
|
timeoutTimer = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class MaybeSendSignContractRequest extends TradeTask {
|
||||||
private void completeAux() {
|
private void completeAux() {
|
||||||
trade.setState(State.CONTRACT_SIGNATURE_REQUESTED);
|
trade.setState(State.CONTRACT_SIGNATURE_REQUESTED);
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
processModel.getXmrWalletService().saveWallet(processModel.getXmrWalletService().getWallet());
|
processModel.getXmrWalletService().saveWallet();
|
||||||
complete();
|
complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
||||||
log.info("Importing exchanged multisig hex for trade {}", trade.getId());
|
log.info("Importing exchanged multisig hex for trade {}", trade.getId());
|
||||||
MoneroMultisigInitResult result = multisigWallet.exchangeMultisigKeys(Arrays.asList(peers[0].getExchangedMultisigHex(), peers[1].getExchangedMultisigHex()), xmrWalletService.getWalletPassword());
|
MoneroMultisigInitResult result = multisigWallet.exchangeMultisigKeys(Arrays.asList(peers[0].getExchangedMultisigHex(), peers[1].getExchangedMultisigHex()), xmrWalletService.getWalletPassword());
|
||||||
processModel.setMultisigAddress(result.getAddress());
|
processModel.setMultisigAddress(result.getAddress());
|
||||||
processModel.getProvider().getXmrWalletService().saveWallet(multisigWallet); // save multisig wallet once it's created
|
processModel.getProvider().getXmrWalletService().saveMultisigWallet(trade.getId()); // save multisig wallet once it's created
|
||||||
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_COMPLETED);
|
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue