From efe04c668c5eb4dcc317a6a266534f625fa94118 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 7 Apr 2020 22:16:02 -0500 Subject: [PATCH] Add DonationAddressValidation static class --- .../core/trade/DonationAddressValidation.java | 94 +++++++++++++++++++ .../buyer/BuyerVerifiesDonationAddress.java | 49 +++------- 2 files changed, 106 insertions(+), 37 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/DonationAddressValidation.java diff --git a/core/src/main/java/bisq/core/trade/DonationAddressValidation.java b/core/src/main/java/bisq/core/trade/DonationAddressValidation.java new file mode 100644 index 0000000000..8d798409c4 --- /dev/null +++ b/core/src/main/java/bisq/core/trade/DonationAddressValidation.java @@ -0,0 +1,94 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade; + +import bisq.core.btc.wallet.BtcWalletService; +import bisq.core.dao.DaoFacade; +import bisq.core.dao.governance.param.Param; + +import org.bitcoinj.core.Address; +import org.bitcoinj.core.NetworkParameters; +import org.bitcoinj.core.Transaction; +import org.bitcoinj.core.TransactionOutput; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import static com.google.common.base.Preconditions.checkNotNull; + +@Slf4j +public class DonationAddressValidation { + + @Getter + public static class DonationAddressException extends Exception { + private final String addressAsString; + private final String recentDonationAddressString; + private final String defaultDonationAddressString; + + DonationAddressException(String addressAsString, + String recentDonationAddressString, + String defaultDonationAddressString) { + + this.addressAsString = addressAsString; + this.recentDonationAddressString = recentDonationAddressString; + this.defaultDonationAddressString = defaultDonationAddressString; + } + } + + public static class MissingDelayedPayoutTxException extends Exception { + public MissingDelayedPayoutTxException(String msg) { + super(msg); + } + } + + public static void validate(Transaction delayedPayoutTx, + DaoFacade daoFacade, + BtcWalletService btcWalletService) throws DonationAddressException, MissingDelayedPayoutTxException { + if (delayedPayoutTx == null) { + throw new MissingDelayedPayoutTxException("DelayedPayoutTx must not be null"); + } + + // Get most recent donation address. + // We do not support past DAO param addresses to avoid that those receive funds (no bond set up anymore). + // Users who have not synced the DAO cannot trade. + String recentDonationAddressString = daoFacade.getParamValue(Param.RECIPIENT_BTC_ADDRESS); + + // In case the seller has deactivated the DAO the default address will be used. + String defaultDonationAddressString = Param.RECIPIENT_BTC_ADDRESS.getDefaultValue(); + + TransactionOutput output = delayedPayoutTx.getOutput(0); + NetworkParameters params = btcWalletService.getParams(); + Address address = output.getAddressFromP2PKHScript(params); + if (address == null) { + // The donation address can be as well be a multisig address. + address = output.getAddressFromP2SH(params); + checkNotNull(address, "address must not be null"); + } + + String addressAsString = address.toString(); + boolean isValid = recentDonationAddressString.equals(addressAsString) || + defaultDonationAddressString.equals(addressAsString); + if (!isValid) { + log.warn("Donation address is invalid." + + "\nAddress used by BTC seller: " + addressAsString + + "\nRecent donation address:" + recentDonationAddressString + + "\nDefault donation address: " + defaultDonationAddressString); + throw new DonationAddressException(addressAsString, recentDonationAddressString, defaultDonationAddressString); + } + } +} diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesDonationAddress.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesDonationAddress.java index c9c19ae3d5..5e91dc39c5 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesDonationAddress.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesDonationAddress.java @@ -17,21 +17,14 @@ package bisq.core.trade.protocol.tasks.buyer; -import bisq.core.dao.governance.param.Param; +import bisq.core.trade.DonationAddressValidation; import bisq.core.trade.Trade; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.common.taskrunner.TaskRunner; -import org.bitcoinj.core.Address; -import org.bitcoinj.core.NetworkParameters; -import org.bitcoinj.core.Transaction; -import org.bitcoinj.core.TransactionOutput; - import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkNotNull; - @Slf4j public class BuyerVerifiesDonationAddress extends TradeTask { @SuppressWarnings({"unused"}) @@ -44,35 +37,17 @@ public class BuyerVerifiesDonationAddress extends TradeTask { try { runInterceptHook(); - Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx(), "preparedDelayedPayoutTx must not be null"); - - // Get most recent donation address. - // We do not support past DAO param addresses to avoid that those receive funds (no bond set up anymore). - // Users who have not synced the DAO cannot trade. - String recentDonationAddressString = processModel.getDaoFacade().getParamValue(Param.RECIPIENT_BTC_ADDRESS); - - // In case the seller has deactivated the DAO the default address will be used. - String defaultDonationAddressString = Param.RECIPIENT_BTC_ADDRESS.getDefaultValue(); - - TransactionOutput output = preparedDelayedPayoutTx.getOutput(0); - NetworkParameters params = processModel.getBtcWalletService().getParams(); - Address address = output.getAddressFromP2PKHScript(params); - if (address == null) { - // The donation address can be as well be a multisig address. - address = output.getAddressFromP2SH(params); - checkNotNull(address, "address must not be null"); - } - - String addressAsString = address.toString(); - if (recentDonationAddressString.equals(addressAsString) || - defaultDonationAddressString.equals(addressAsString)) { - complete(); - } else { - failed("Sellers donation address not recognized." + - "\nAddress used by BTC seller: " + addressAsString + - "\nRecent donation address:" + recentDonationAddressString + - "\nDefault donation address: " + defaultDonationAddressString); - } + DonationAddressValidation.validate(processModel.getPreparedDelayedPayoutTx(), + processModel.getDaoFacade(), + processModel.getBtcWalletService()); + complete(); + } catch (DonationAddressValidation.DonationAddressException e) { + failed("Sellers donation address is invalid." + + "\nAddress used by BTC seller: " + e.getAddressAsString() + + "\nRecent donation address:" + e.getRecentDonationAddressString() + + "\nDefault donation address: " + e.getDefaultDonationAddressString()); + } catch (DonationAddressValidation.MissingDelayedPayoutTxException e) { + failed(e.getMessage()); } catch (Throwable t) { failed(t); }