Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validate pending offer #1339

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/src/main/java/haveno/core/offer/Offer.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public Price getPrice() {
return null;
}
} else {
log.trace("We don't have a market price. " +
log.warn("We don't have a market price. " +
"That case could only happen if you don't have a price feed.");
return null;
}
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/haveno/core/offer/OpenOfferManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import haveno.core.offer.messages.SignOfferResponse;
import haveno.core.offer.placeoffer.PlaceOfferModel;
import haveno.core.offer.placeoffer.PlaceOfferProtocol;
import haveno.core.offer.placeoffer.tasks.ValidateOffer;
import haveno.core.provider.price.PriceFeedService;
import haveno.core.support.dispute.arbitration.arbitrator.Arbitrator;
import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
Expand Down Expand Up @@ -934,6 +935,14 @@ private void doProcessPendingOffer(List<OpenOffer> openOffers, OpenOffer openOff
return;
}

// validate offer
try {
ValidateOffer.validateOffer(openOffer.getOffer(), accountAgeWitnessService, user);
} catch (Exception e) {
errorMessageHandler.handleErrorMessage("Failed to validate offer: " + e.getMessage());
return;
}

// cancel offer if scheduled txs unavailable
if (openOffer.getScheduledTxHashes() != null) {
boolean scheduledTxsAvailable = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

import haveno.common.taskrunner.Task;
import haveno.common.taskrunner.TaskRunner;
import haveno.core.account.witness.AccountAgeWitnessService;
import haveno.core.offer.Offer;
import haveno.core.offer.placeoffer.PlaceOfferModel;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.messages.TradeMessage;
import haveno.core.user.User;
import org.bitcoinj.core.Coin;

import java.math.BigInteger;
Expand All @@ -41,55 +43,7 @@ protected void run() {
try {
runInterceptHook();

// Coins
checkBINotNullOrZero(offer.getAmount(), "Amount");
checkBINotNullOrZero(offer.getMinAmount(), "MinAmount");
//checkCoinNotNullOrZero(offer.getTxFee(), "txFee"); // TODO: remove from data model
checkBINotNullOrZero(offer.getMaxTradeLimit(), "MaxTradeLimit");
if (offer.getMakerFeePct() < 0) throw new IllegalArgumentException("Maker fee must be >= 0% but was " + offer.getMakerFeePct());
if (offer.getTakerFeePct() < 0) throw new IllegalArgumentException("Taker fee must be >= 0% but was " + offer.getTakerFeePct());
if (offer.getBuyerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Buyer security deposit percent must be positive but was " + offer.getBuyerSecurityDepositPct());
if (offer.getSellerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Seller security deposit percent must be positive but was " + offer.getSellerSecurityDepositPct());

// We remove those checks to be more flexible with future changes.
/*checkArgument(offer.getMakerFee().value >= FeeService.getMinMakerFee(offer.isCurrencyForMakerFeeBtc()).value,
"createOfferFee must not be less than FeeService.MIN_CREATE_OFFER_FEE_IN_BTC. " +
"MakerFee=" + offer.getMakerFee().toFriendlyString());*/
/*checkArgument(offer.getBuyerSecurityDeposit().value >= ProposalConsensus.getMinBuyerSecurityDeposit().value,
"buyerSecurityDeposit must not be less than ProposalConsensus.MIN_BUYER_SECURITY_DEPOSIT. " +
"buyerSecurityDeposit=" + offer.getBuyerSecurityDeposit().toFriendlyString());
checkArgument(offer.getBuyerSecurityDeposit().value <= ProposalConsensus.getMaxBuyerSecurityDeposit().value,
"buyerSecurityDeposit must not be larger than ProposalConsensus.MAX_BUYER_SECURITY_DEPOSIT. " +
"buyerSecurityDeposit=" + offer.getBuyerSecurityDeposit().toFriendlyString());
checkArgument(offer.getSellerSecurityDeposit().value == ProposalConsensus.getSellerSecurityDeposit().value,
"sellerSecurityDeposit must be equal to ProposalConsensus.SELLER_SECURITY_DEPOSIT. " +
"sellerSecurityDeposit=" + offer.getSellerSecurityDeposit().toFriendlyString());*/
/*checkArgument(offer.getMinAmount().compareTo(ProposalConsensus.getMinTradeAmount()) >= 0,
"MinAmount is less than " + ProposalConsensus.getMinTradeAmount().toFriendlyString());*/

long maxAmount = model.getAccountAgeWitnessService().getMyTradeLimit(model.getUser().getPaymentAccount(offer.getMakerPaymentAccountId()), offer.getCurrencyCode(), offer.getDirection());
checkArgument(offer.getAmount().longValueExact() <= maxAmount,
"Amount is larger than " + HavenoUtils.atomicUnitsToXmr(offer.getPaymentMethod().getMaxTradeLimit(offer.getCurrencyCode())) + " XMR");
checkArgument(offer.getAmount().compareTo(offer.getMinAmount()) >= 0, "MinAmount is larger than Amount");

checkNotNull(offer.getPrice(), "Price is null");
if (!offer.isUseMarketBasedPrice()) checkArgument(offer.getPrice().isPositive(),
"Price must be positive unless using market based price. price=" + offer.getPrice().toFriendlyString());

checkArgument(offer.getDate().getTime() > 0,
"Date must not be 0. date=" + offer.getDate().toString());

checkNotNull(offer.getCurrencyCode(), "Currency is null");
checkNotNull(offer.getDirection(), "Direction is null");
checkNotNull(offer.getId(), "Id is null");
checkNotNull(offer.getPubKeyRing(), "pubKeyRing is null");
checkNotNull(offer.getMinAmount(), "MinAmount is null");
checkNotNull(offer.getPrice(), "Price is null");
checkNotNull(offer.getVersionNr(), "VersionNr is null");
checkArgument(offer.getMaxTradePeriod() > 0,
"maxTradePeriod must be positive. maxTradePeriod=" + offer.getMaxTradePeriod());
// TODO check upper and lower bounds for fiat
// TODO check rest of new parameters
validateOffer(offer, model.getAccountAgeWitnessService(), model.getUser());

complete();
} catch (Exception e) {
Expand All @@ -100,42 +54,95 @@ protected void run() {
}
}

public static void checkBINotNullOrZero(BigInteger value, String name) {
public static void validateOffer(Offer offer, AccountAgeWitnessService accountAgeWitnessService, User user) {

// Coins
checkBINotNullOrZero(offer.getAmount(), "Amount");
checkBINotNullOrZero(offer.getMinAmount(), "MinAmount");
//checkCoinNotNullOrZero(offer.getTxFee(), "txFee"); // TODO: remove from data model
checkBINotNullOrZero(offer.getMaxTradeLimit(), "MaxTradeLimit");
if (offer.getMakerFeePct() < 0) throw new IllegalArgumentException("Maker fee must be >= 0% but was " + offer.getMakerFeePct());
if (offer.getTakerFeePct() < 0) throw new IllegalArgumentException("Taker fee must be >= 0% but was " + offer.getTakerFeePct());
if (offer.getBuyerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Buyer security deposit percent must be positive but was " + offer.getBuyerSecurityDepositPct());
if (offer.getSellerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Seller security deposit percent must be positive but was " + offer.getSellerSecurityDepositPct());

// We remove those checks to be more flexible with future changes.
/*checkArgument(offer.getMakerFee().value >= FeeService.getMinMakerFee(offer.isCurrencyForMakerFeeBtc()).value,
"createOfferFee must not be less than FeeService.MIN_CREATE_OFFER_FEE_IN_BTC. " +
"MakerFee=" + offer.getMakerFee().toFriendlyString());*/
/*checkArgument(offer.getBuyerSecurityDeposit().value >= ProposalConsensus.getMinBuyerSecurityDeposit().value,
"buyerSecurityDeposit must not be less than ProposalConsensus.MIN_BUYER_SECURITY_DEPOSIT. " +
"buyerSecurityDeposit=" + offer.getBuyerSecurityDeposit().toFriendlyString());
checkArgument(offer.getBuyerSecurityDeposit().value <= ProposalConsensus.getMaxBuyerSecurityDeposit().value,
"buyerSecurityDeposit must not be larger than ProposalConsensus.MAX_BUYER_SECURITY_DEPOSIT. " +
"buyerSecurityDeposit=" + offer.getBuyerSecurityDeposit().toFriendlyString());
checkArgument(offer.getSellerSecurityDeposit().value == ProposalConsensus.getSellerSecurityDeposit().value,
"sellerSecurityDeposit must be equal to ProposalConsensus.SELLER_SECURITY_DEPOSIT. " +
"sellerSecurityDeposit=" + offer.getSellerSecurityDeposit().toFriendlyString());*/
/*checkArgument(offer.getMinAmount().compareTo(ProposalConsensus.getMinTradeAmount()) >= 0,
"MinAmount is less than " + ProposalConsensus.getMinTradeAmount().toFriendlyString());*/

long maxAmount = accountAgeWitnessService.getMyTradeLimit(user.getPaymentAccount(offer.getMakerPaymentAccountId()), offer.getCurrencyCode(), offer.getDirection());
checkArgument(offer.getAmount().longValueExact() <= maxAmount,
"Amount is larger than " + HavenoUtils.atomicUnitsToXmr(offer.getPaymentMethod().getMaxTradeLimit(offer.getCurrencyCode())) + " XMR");
checkArgument(offer.getAmount().compareTo(offer.getMinAmount()) >= 0, "MinAmount is larger than Amount");

checkNotNull(offer.getPrice(), "Price is null");
if (!offer.isUseMarketBasedPrice()) checkArgument(offer.getPrice().isPositive(),
"Price must be positive unless using market based price. price=" + offer.getPrice().toFriendlyString());

checkArgument(offer.getDate().getTime() > 0,
"Date must not be 0. date=" + offer.getDate().toString());

checkNotNull(offer.getCurrencyCode(), "Currency is null");
checkNotNull(offer.getDirection(), "Direction is null");
checkNotNull(offer.getId(), "Id is null");
checkNotNull(offer.getPubKeyRing(), "pubKeyRing is null");
checkNotNull(offer.getMinAmount(), "MinAmount is null");
checkNotNull(offer.getPrice(), "Price is null");
checkNotNull(offer.getVersionNr(), "VersionNr is null");
checkArgument(offer.getMaxTradePeriod() > 0,
"maxTradePeriod must be positive. maxTradePeriod=" + offer.getMaxTradePeriod());
// TODO check upper and lower bounds for fiat
// TODO check rest of new parameters
}

private static void checkBINotNullOrZero(BigInteger value, String name) {
checkNotNull(value, name + " is null");
checkArgument(value.compareTo(BigInteger.ZERO) > 0,
name + " must be positive. " + name + "=" + value);
}

public static void checkCoinNotNullOrZero(Coin value, String name) {
private static void checkCoinNotNullOrZero(Coin value, String name) {
checkNotNull(value, name + " is null");
checkArgument(value.isPositive(),
name + " must be positive. " + name + "=" + value.toFriendlyString());
}

public static String nonEmptyStringOf(String value) {
private static String nonEmptyStringOf(String value) {
checkNotNull(value);
checkArgument(value.length() > 0);
return value;
}

public static long nonNegativeLongOf(long value) {
private static long nonNegativeLongOf(long value) {
checkArgument(value >= 0);
return value;
}

public static Coin nonZeroCoinOf(Coin value) {
private static Coin nonZeroCoinOf(Coin value) {
checkNotNull(value);
checkArgument(!value.isZero());
return value;
}

public static Coin positiveCoinOf(Coin value) {
private static Coin positiveCoinOf(Coin value) {
checkNotNull(value);
checkArgument(value.isPositive());
return value;
}

public static void checkTradeId(String tradeId, TradeMessage tradeMessage) {
private static void checkTradeId(String tradeId, TradeMessage tradeMessage) {
checkArgument(tradeId.equals(tradeMessage.getOfferId()));
}
}
Loading