set open offer's reserve tx fields once known and repost if invalid

This commit is contained in:
woodser 2023-12-14 10:52:12 -05:00
parent 2e13bc0051
commit dbd8db0e88
3 changed files with 44 additions and 36 deletions

View file

@ -1101,11 +1101,6 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(model, PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(model,
transaction -> { transaction -> {
// set reserve tx on open offer
openOffer.setReserveTxHash(model.getReserveTx().getHash());
openOffer.setReserveTxHex(model.getReserveTx().getFullHex());
openOffer.setReserveTxKey(model.getReserveTx().getKey());
// set offer state // set offer state
openOffer.setState(OpenOffer.State.AVAILABLE); openOffer.setState(OpenOffer.State.AVAILABLE);
openOffer.setScheduledTxHashes(null); openOffer.setScheduledTxHashes(null);
@ -1609,9 +1604,19 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
private void republishOffer(OpenOffer openOffer, @Nullable Runnable completeHandler) { private void republishOffer(OpenOffer openOffer, @Nullable Runnable completeHandler) {
// re-add to offer book if signature is valid // determine if offer is valid
boolean isValid = true;
Arbitrator arbitrator = user.getAcceptedArbitratorByAddress(openOffer.getOffer().getOfferPayload().getArbitratorSigner()); Arbitrator arbitrator = user.getAcceptedArbitratorByAddress(openOffer.getOffer().getOfferPayload().getArbitratorSigner());
boolean isValid = arbitrator != null && HavenoUtils.isArbitratorSignatureValid(openOffer.getOffer().getOfferPayload(), arbitrator); if (arbitrator == null || !HavenoUtils.isArbitratorSignatureValid(openOffer.getOffer().getOfferPayload(), arbitrator)) {
log.warn("Offer {} has invalid arbitrator signature, reposting", openOffer.getId());
isValid = false;
}
if (openOffer.getOffer().getOfferPayload().getReserveTxKeyImages() != null && (openOffer.getReserveTxHash() == null || openOffer.getReserveTxHash().isEmpty())) {
log.warn("Offer {} is missing reserve tx hash but has reserved key images, reposting", openOffer.getId());
isValid = false;
}
// if valid, re-add offer to book
if (isValid) { if (isValid) {
offerBookService.addOffer(openOffer.getOffer(), offerBookService.addOffer(openOffer.getOffer(),
() -> { () -> {
@ -1635,35 +1640,34 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
if (completeHandler != null) completeHandler.run(); if (completeHandler != null) completeHandler.run();
} }
}); });
return; } else {
// cancel and recreate offer
onCancelled(openOffer);
Offer updatedOffer = new Offer(openOffer.getOffer().getOfferPayload());
updatedOffer.setPriceFeedService(priceFeedService);
OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, openOffer.getTriggerPrice());
// repost offer
new Thread(() -> {
synchronized (processOffersLock) {
CountDownLatch latch = new CountDownLatch(1);
processUnpostedOffer(getOpenOffers(), updatedOpenOffer, (transaction) -> {
addOpenOffer(updatedOpenOffer);
requestPersistence();
latch.countDown();
if (completeHandler != null) completeHandler.run();
}, (errorMessage) -> {
log.warn("Error reposting offer {}: {}", updatedOpenOffer.getId(), errorMessage);
onCancelled(updatedOpenOffer);
updatedOffer.setErrorMessage(errorMessage);
latch.countDown();
if (completeHandler != null) completeHandler.run();
});
HavenoUtils.awaitLatch(latch);
}
}).start();
} }
// cancel and recreate offer
log.warn("Offer {} has invalid arbitrator signature, reposting", openOffer.getId());
onCancelled(openOffer);
Offer updatedOffer = new Offer(openOffer.getOffer().getOfferPayload());
updatedOffer.setPriceFeedService(priceFeedService);
OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, openOffer.getTriggerPrice());
// repost offer
new Thread(() -> {
synchronized (processOffersLock) {
CountDownLatch latch = new CountDownLatch(1);
processUnpostedOffer(getOpenOffers(), updatedOpenOffer, (transaction) -> {
addOpenOffer(updatedOpenOffer);
requestPersistence();
latch.countDown();
if (completeHandler != null) completeHandler.run();
}, (errorMessage) -> {
log.warn("Error reposting offer {} with invalid signature: {}", updatedOpenOffer.getId(), errorMessage);
onCancelled(updatedOpenOffer);
updatedOffer.setErrorMessage(errorMessage);
latch.countDown();
if (completeHandler != null) completeHandler.run();
});
HavenoUtils.awaitLatch(latch);
}
}).start();
} }
private void startPeriodicRepublishOffersTimer() { private void startPeriodicRepublishOffersTimer() {

View file

@ -70,6 +70,9 @@ public class MakerReserveOfferFunds extends Task<PlaceOfferModel> {
// save offer state // save offer state
model.setReserveTx(reserveTx); model.setReserveTx(reserveTx);
model.getOpenOffer().setReserveTxHash(reserveTx.getHash());
model.getOpenOffer().setReserveTxHex(reserveTx.getFullHex());
model.getOpenOffer().setReserveTxKey(reserveTx.getKey());
offer.getOfferPayload().setReserveTxKeyImages(reservedKeyImages); offer.getOfferPayload().setReserveTxKeyImages(reservedKeyImages);
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {

View file

@ -43,10 +43,11 @@ public class MakerSendInitTradeRequest extends TradeTask {
try { try {
runInterceptHook(); runInterceptHook();
// verify trade // verify trade state
InitTradeRequest makerRequest = (InitTradeRequest) processModel.getTradeMessage(); // arbitrator's InitTradeRequest to maker InitTradeRequest makerRequest = (InitTradeRequest) processModel.getTradeMessage(); // arbitrator's InitTradeRequest to maker
checkNotNull(makerRequest); checkNotNull(makerRequest);
checkTradeId(processModel.getOfferId(), makerRequest); checkTradeId(processModel.getOfferId(), makerRequest);
if (trade.getSelf().getReserveTxHash() == null || trade.getSelf().getReserveTxHash().isEmpty()) throw new IllegalStateException("Reserve tx id is not initialized: " + trade.getSelf().getReserveTxHash());
// create request to arbitrator // create request to arbitrator
Offer offer = processModel.getOffer(); Offer offer = processModel.getOffer();