mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-23 03:59:36 +00:00
fix invalid signature when sign offer re-requested after timeout
This commit is contained in:
parent
e12ec197bf
commit
88290c9dff
5 changed files with 63 additions and 50 deletions
|
@ -230,9 +230,12 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
offerBookService.addOfferBookChangedListener(new OfferBookChangedListener() {
|
offerBookService.addOfferBookChangedListener(new OfferBookChangedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAdded(Offer offer) {
|
public void onAdded(Offer offer) {
|
||||||
|
|
||||||
|
// cancel offer if reserved funds spent
|
||||||
Optional<OpenOffer> openOfferOptional = getOpenOfferById(offer.getId());
|
Optional<OpenOffer> openOfferOptional = getOpenOfferById(offer.getId());
|
||||||
if (openOfferOptional.isPresent() && openOfferOptional.get().getState() != OpenOffer.State.RESERVED && offer.isReservedFundsSpent()) {
|
if (openOfferOptional.isPresent() && openOfferOptional.get().getState() != OpenOffer.State.RESERVED && offer.isReservedFundsSpent()) {
|
||||||
closeOpenOffer(offer);
|
log.warn("Canceling open offer because reserved funds have been spent, offerId={}, state={}", offer.getId(), openOfferOptional.get().getState());
|
||||||
|
cancelOpenOffer(openOfferOptional.get(), null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -552,7 +555,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
if (openOffer.isCanceled()) latch.countDown();
|
if (openOffer.isCanceled()) latch.countDown();
|
||||||
else {
|
else {
|
||||||
log.warn("Error processing unposted offer {}: {}", openOffer.getId(), errorMessage);
|
log.warn("Error processing unposted offer {}: {}", openOffer.getId(), errorMessage);
|
||||||
doCancel(openOffer);
|
doCancelOffer(openOffer);
|
||||||
offer.setErrorMessage(errorMessage);
|
offer.setErrorMessage(errorMessage);
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||||
|
@ -622,19 +625,19 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
offerBookService.removeOffer(openOffer.getOffer().getOfferPayload(),
|
offerBookService.removeOffer(openOffer.getOffer().getOfferPayload(),
|
||||||
() -> {
|
() -> {
|
||||||
ThreadUtils.submitToPool(() -> { // TODO: this runs off thread and then shows popup when done. should show overlay spinner until done
|
ThreadUtils.submitToPool(() -> { // TODO: this runs off thread and then shows popup when done. should show overlay spinner until done
|
||||||
doCancel(openOffer);
|
doCancelOffer(openOffer);
|
||||||
resultHandler.handleResult();
|
if (resultHandler != null) resultHandler.handleResult();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
errorMessageHandler);
|
errorMessageHandler);
|
||||||
} else {
|
} else {
|
||||||
ThreadUtils.submitToPool(() -> {
|
ThreadUtils.submitToPool(() -> {
|
||||||
doCancel(openOffer);
|
doCancelOffer(openOffer);
|
||||||
resultHandler.handleResult();
|
if (resultHandler != null) resultHandler.handleResult();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorMessageHandler.handleErrorMessage("You can't remove an offer that is currently edited.");
|
if (errorMessageHandler != null) errorMessageHandler.handleErrorMessage("You can't remove an offer that is currently edited.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,7 +711,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove open offer which thaws its key images
|
// remove open offer which thaws its key images
|
||||||
private void doCancel(@NotNull OpenOffer openOffer) {
|
private void doCancelOffer(@NotNull OpenOffer openOffer) {
|
||||||
Offer offer = openOffer.getOffer();
|
Offer offer = openOffer.getOffer();
|
||||||
offer.setState(Offer.State.REMOVED);
|
offer.setState(Offer.State.REMOVED);
|
||||||
openOffer.setState(OpenOffer.State.CANCELED);
|
openOffer.setState(OpenOffer.State.CANCELED);
|
||||||
|
@ -874,7 +877,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
if (scheduledOffer.getNumProcessingAttempts() >= MAX_PROCESS_ATTEMPTS) {
|
if (scheduledOffer.getNumProcessingAttempts() >= MAX_PROCESS_ATTEMPTS) {
|
||||||
log.warn("Offer canceled after {} attempts, offerId={}, error={}", scheduledOffer.getNumProcessingAttempts(), scheduledOffer.getId(), errorMessage);
|
log.warn("Offer canceled after {} attempts, offerId={}, error={}", scheduledOffer.getNumProcessingAttempts(), scheduledOffer.getId(), errorMessage);
|
||||||
HavenoUtils.havenoSetup.getTopErrorMsg().set("Offer canceled after " + scheduledOffer.getNumProcessingAttempts() + " attempts. Please switch to a better Monero connection and try again.\n\nOffer ID: " + scheduledOffer.getId() + "\nError: " + errorMessage);
|
HavenoUtils.havenoSetup.getTopErrorMsg().set("Offer canceled after " + scheduledOffer.getNumProcessingAttempts() + " attempts. Please switch to a better Monero connection and try again.\n\nOffer ID: " + scheduledOffer.getId() + "\nError: " + errorMessage);
|
||||||
doCancel(scheduledOffer);
|
doCancelOffer(scheduledOffer);
|
||||||
}
|
}
|
||||||
errorMessages.add(errorMessage);
|
errorMessages.add(errorMessage);
|
||||||
}
|
}
|
||||||
|
@ -1754,7 +1757,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// cancel and recreate offer
|
// cancel and recreate offer
|
||||||
doCancel(openOffer);
|
doCancelOffer(openOffer);
|
||||||
Offer updatedOffer = new Offer(openOffer.getOffer().getOfferPayload());
|
Offer updatedOffer = new Offer(openOffer.getOffer().getOfferPayload());
|
||||||
updatedOffer.setPriceFeedService(priceFeedService);
|
updatedOffer.setPriceFeedService(priceFeedService);
|
||||||
OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, openOffer.getTriggerPrice());
|
OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, openOffer.getTriggerPrice());
|
||||||
|
@ -1770,7 +1773,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
}, (errorMessage) -> {
|
}, (errorMessage) -> {
|
||||||
if (!updatedOpenOffer.isCanceled()) {
|
if (!updatedOpenOffer.isCanceled()) {
|
||||||
log.warn("Error reposting offer {}: {}", updatedOpenOffer.getId(), errorMessage);
|
log.warn("Error reposting offer {}: {}", updatedOpenOffer.getId(), errorMessage);
|
||||||
doCancel(updatedOpenOffer);
|
doCancelOffer(updatedOpenOffer);
|
||||||
updatedOffer.setErrorMessage(errorMessage);
|
updatedOffer.setErrorMessage(errorMessage);
|
||||||
}
|
}
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
|
|
|
@ -94,11 +94,18 @@ public class PlaceOfferProtocol {
|
||||||
log.debug("handleSignOfferResponse() " + model.getOpenOffer().getOffer().getId());
|
log.debug("handleSignOfferResponse() " + model.getOpenOffer().getOffer().getId());
|
||||||
model.setSignOfferResponse(response);
|
model.setSignOfferResponse(response);
|
||||||
|
|
||||||
|
// ignore if unexpected signer
|
||||||
if (!model.getOpenOffer().getOffer().getOfferPayload().getArbitratorSigner().equals(sender)) {
|
if (!model.getOpenOffer().getOffer().getOfferPayload().getArbitratorSigner().equals(sender)) {
|
||||||
log.warn("Ignoring sign offer response from different sender");
|
log.warn("Ignoring sign offer response from different sender");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore if payloads have different timestamps
|
||||||
|
if (model.getOpenOffer().getOffer().getOfferPayload().getDate() != response.getSignedOfferPayload().getDate()) {
|
||||||
|
log.warn("Ignoring sign offer response from arbitrator for offer payload with different timestamp");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore if timer already stopped
|
// ignore if timer already stopped
|
||||||
if (timeoutTimer == null) {
|
if (timeoutTimer == null) {
|
||||||
log.warn("Ignoring sign offer response from arbitrator because timeout has expired for offer " + model.getOpenOffer().getOffer().getId());
|
log.warn("Ignoring sign offer response from arbitrator because timeout has expired for offer " + model.getOpenOffer().getOffer().getId());
|
||||||
|
|
|
@ -42,11 +42,14 @@ public class MakerProcessSignOfferResponse extends Task<PlaceOfferModel> {
|
||||||
|
|
||||||
// validate arbitrator signature
|
// validate arbitrator signature
|
||||||
if (!HavenoUtils.isArbitratorSignatureValid(model.getSignOfferResponse().getSignedOfferPayload(), arbitrator)) {
|
if (!HavenoUtils.isArbitratorSignatureValid(model.getSignOfferResponse().getSignedOfferPayload(), arbitrator)) {
|
||||||
throw new RuntimeException("Offer payload has invalid arbitrator signature");
|
throw new RuntimeException("Arbitrator's offer payload has invalid signature, offerId=" + offer.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// set arbitrator signature for maker's offer
|
// set arbitrator signature for maker's offer
|
||||||
offer.getOfferPayload().setArbitratorSignature(model.getSignOfferResponse().getSignedOfferPayload().getArbitratorSignature());
|
offer.getOfferPayload().setArbitratorSignature(model.getSignOfferResponse().getSignedOfferPayload().getArbitratorSignature());
|
||||||
|
if (!HavenoUtils.isArbitratorSignatureValid(offer.getOfferPayload(), arbitrator)) {
|
||||||
|
throw new RuntimeException("Maker's offer payload has invalid signature, offerId=" + offer.getId());
|
||||||
|
}
|
||||||
offer.setState(Offer.State.AVAILABLE);
|
offer.setState(Offer.State.AVAILABLE);
|
||||||
complete();
|
complete();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -364,7 +364,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||||
trade.onShutDownStarted();
|
trade.onShutDownStarted();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (e.getMessage() != null && e.getMessage().contains("Connection reset")) return; // expected if shut down with ctrl+c
|
if (e.getMessage() != null && e.getMessage().contains("Connection reset")) return; // expected if shut down with ctrl+c
|
||||||
log.warn("Error notifying {} {} that shut down started {}", getClass().getSimpleName(), trade.getId());
|
log.warn("Error notifying {} {} that shut down started {}", trade.getClass().getSimpleName(), trade.getId());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -221,7 +221,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
processModel.getP2PService().sendEncryptedDirectMessage(nodeAddress, pubKeyRing, response, new SendDirectMessageListener() {
|
processModel.getP2PService().sendEncryptedDirectMessage(nodeAddress, pubKeyRing, response, new SendDirectMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onArrived() {
|
public void onArrived() {
|
||||||
log.info("{} arrived: trading peer={}; offerId={}; uid={}", response.getClass().getSimpleName(), nodeAddress, trade.getId());
|
log.info("{} arrived: trading peer={}; offerId={}; uid={}", response.getClass().getSimpleName(), nodeAddress, trade.getId(), trade.getUid());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onFault(String errorMessage) {
|
public void onFault(String errorMessage) {
|
||||||
|
|
Loading…
Reference in a new issue