Merge pull request #2355 from ManfredKarrer/dao-add-filter-flag-for-disable-dao

Dao add filter flag for disable dao
This commit is contained in:
Manfred Karrer 2019-02-04 00:17:08 +01:00 committed by GitHub
commit 3f4e641f19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 160 additions and 18 deletions

View File

@ -476,6 +476,7 @@ message Filter {
repeated string price_relay_nodes = 11;
bool prevent_public_btc_network = 12;
repeated string btc_nodes = 13;
bool disable_dao = 14;
}
// not used anymore from v0.6 on. But leave it for receiving TradeStatistics objects from older

View File

@ -23,6 +23,7 @@ import bisq.core.btc.exceptions.TransactionVerificationException;
import bisq.core.btc.exceptions.WalletException;
import bisq.core.btc.listeners.BsqBalanceListener;
import bisq.core.btc.setup.WalletsSetup;
import bisq.core.dao.DaoKillSwitch;
import bisq.core.dao.state.DaoStateListener;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.model.blockchain.Block;
@ -466,6 +467,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
public Transaction getPreparedSendTx(String receiverAddress, Coin receiverAmount)
throws AddressFormatException, InsufficientBsqException, WalletException, TransactionVerificationException {
DaoKillSwitch.assertDaoIsNotDisabled();
Transaction tx = new Transaction(params);
checkArgument(Restrictions.isAboveDust(receiverAmount),
"The amount is too low (dust limit).");
@ -497,6 +499,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
public Transaction getPreparedSendBtcTx(String receiverAddress, Coin receiverAmount)
throws AddressFormatException, InsufficientBsqException, WalletException, TransactionVerificationException {
DaoKillSwitch.assertDaoIsNotDisabled();
Transaction tx = new Transaction(params);
checkArgument(Restrictions.isAboveDust(receiverAmount),
"The amount is too low (dust limit).");
@ -535,6 +538,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
}
public Transaction getPreparedBurnFeeTx(Coin fee) throws InsufficientBsqException {
DaoKillSwitch.assertDaoIsNotDisabled();
final Transaction tx = new Transaction(params);
addInputsAndChangeOutputForTx(tx, fee, bsqCoinSelector);
// printTx("getPreparedFeeTx", tx);
@ -572,6 +576,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
// We create a tx with Bsq inputs for the fee, one output for the stake and optional one BSQ change output.
// As the fee amount will be missing in the output those BSQ fees are burned.
public Transaction getPreparedBlindVoteTx(Coin fee, Coin stake) throws InsufficientBsqException {
DaoKillSwitch.assertDaoIsNotDisabled();
Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, stake, getUnusedAddress()));
addInputsAndChangeOutputForTx(tx, fee.add(stake), bsqCoinSelector);
@ -585,6 +590,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
///////////////////////////////////////////////////////////////////////////////////////////
public Transaction getPreparedVoteRevealTx(TxOutput stakeTxOutput) {
DaoKillSwitch.assertDaoIsNotDisabled();
Transaction tx = new Transaction(params);
final Coin stake = Coin.valueOf(stakeTxOutput.getValue());
Transaction blindVoteTx = getTransaction(stakeTxOutput.getTxId());
@ -603,6 +609,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
///////////////////////////////////////////////////////////////////////////////////////////
public Transaction getPreparedLockupTx(Coin lockupAmount) throws AddressFormatException, InsufficientBsqException {
DaoKillSwitch.assertDaoIsNotDisabled();
Transaction tx = new Transaction(params);
checkArgument(Restrictions.isAboveDust(lockupAmount), "The amount is too low (dust limit).");
tx.addOutput(new TransactionOutput(params, tx, lockupAmount, getUnusedAddress()));
@ -616,6 +623,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
///////////////////////////////////////////////////////////////////////////////////////////
public Transaction getPreparedUnlockTx(TxOutput lockupTxOutput) throws AddressFormatException {
DaoKillSwitch.assertDaoIsNotDisabled();
Transaction tx = new Transaction(params);
// Unlocking means spending the full value of the locked txOutput to another txOutput with the same value
Coin amountToUnlock = Coin.valueOf(lockupTxOutput.getValue());

View File

@ -0,0 +1,62 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package bisq.core.dao;
import bisq.core.dao.exceptions.DaoDisabledException;
import bisq.core.filter.Filter;
import bisq.core.filter.FilterManager;
import javax.inject.Inject;
import lombok.Getter;
public class DaoKillSwitch implements DaoSetupService {
private static DaoKillSwitch INSTANCE;
private final FilterManager filterManager;
@Getter
private boolean daoDisabled;
@Inject
public DaoKillSwitch(FilterManager filterManager) {
this.filterManager = filterManager;
DaoKillSwitch.INSTANCE = this;
}
@Override
public void addListeners() {
filterManager.filterProperty().addListener((observable, oldValue, newValue) -> applyFilter(newValue));
}
@Override
public void start() {
applyFilter(filterManager.getFilter());
}
private void applyFilter(Filter filter) {
daoDisabled = filter != null && filter.isDisableDao();
}
public static void assertDaoIsNotDisabled() {
if (INSTANCE.isDaoDisabled()) {
throw new DaoDisabledException("The DAO features have been disabled by the Bisq developers. " +
"Please check out the Bisq Forum for further information.");
}
}
}

View File

@ -98,6 +98,7 @@ public class DaoModule extends AppModule {
protected void configure() {
bind(DaoSetup.class).in(Singleton.class);
bind(DaoFacade.class).in(Singleton.class);
bind(DaoKillSwitch.class).in(Singleton.class);
// Node, parser
bind(BsqNodeProvider.class).in(Singleton.class);

View File

@ -68,7 +68,8 @@ public class DaoSetup {
AssetService assetService,
ProofOfBurnService proofOfBurnService,
DaoFacade daoFacade,
ExportJsonFilesService exportJsonFilesService) {
ExportJsonFilesService exportJsonFilesService,
DaoKillSwitch daoKillSwitch) {
bsqNode = bsqNodeProvider.getBsqNode();
@ -90,6 +91,7 @@ public class DaoSetup {
daoSetupServices.add(proofOfBurnService);
daoSetupServices.add(daoFacade);
daoSetupServices.add(exportJsonFilesService);
daoSetupServices.add(daoKillSwitch);
daoSetupServices.add(bsqNodeProvider.getBsqNode());
}

View File

@ -0,0 +1,39 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package bisq.core.dao.exceptions;
public class DaoDisabledException extends RuntimeException {
public DaoDisabledException() {
}
public DaoDisabledException(String message) {
super(message);
}
public DaoDisabledException(String message, Throwable cause) {
super(message, cause);
}
public DaoDisabledException(Throwable cause) {
super(cause);
}
public DaoDisabledException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -32,6 +32,7 @@ import com.google.common.annotations.VisibleForTesting;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -85,6 +86,9 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
private Map<String, String> extraDataMap;
private PublicKey ownerPubKey;
// added in v0.9.4
private final boolean disableDao;
public Filter(List<String> bannedOfferIds,
List<String> bannedNodeAddress,
List<PaymentAccountFilter> bannedPaymentAccounts,
@ -94,7 +98,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
@Nullable List<String> seedNodes,
@Nullable List<String> priceRelayNodes,
boolean preventPublicBtcNetwork,
@Nullable List<String> btcNodes) {
@Nullable List<String> btcNodes,
boolean disableDao) {
this.bannedOfferIds = bannedOfferIds;
this.bannedNodeAddress = bannedNodeAddress;
this.bannedPaymentAccounts = bannedPaymentAccounts;
@ -105,6 +110,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
this.priceRelayNodes = priceRelayNodes;
this.preventPublicBtcNetwork = preventPublicBtcNetwork;
this.btcNodes = btcNodes;
this.disableDao = disableDao;
}
@ -123,6 +129,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
@Nullable List<String> priceRelayNodes,
boolean preventPublicBtcNetwork,
@Nullable List<String> btcNodes,
boolean disableDao,
String signatureAsBase64,
byte[] ownerPubKeyBytes,
@Nullable Map<String, String> extraDataMap) {
@ -135,7 +142,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
seedNodes,
priceRelayNodes,
preventPublicBtcNetwork,
btcNodes);
btcNodes,
disableDao);
this.signatureAsBase64 = signatureAsBase64;
this.ownerPubKeyBytes = ownerPubKeyBytes;
this.extraDataMap = extraDataMap;
@ -156,7 +164,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
.addAllBannedPaymentAccounts(paymentAccountFilterList)
.setSignatureAsBase64(signatureAsBase64)
.setOwnerPubKeyBytes(ByteString.copyFrom(ownerPubKeyBytes))
.setPreventPublicBtcNetwork(preventPublicBtcNetwork);
.setPreventPublicBtcNetwork(preventPublicBtcNetwork)
.setDisableDao(disableDao);
Optional.ofNullable(bannedCurrencies).ifPresent(builder::addAllBannedCurrencies);
Optional.ofNullable(bannedPaymentMethods).ifPresent(builder::addAllBannedPaymentMethods);
@ -170,18 +179,19 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
}
public static Filter fromProto(PB.Filter proto) {
return new Filter(proto.getBannedOfferIdsList().stream().collect(Collectors.toList()),
proto.getBannedNodeAddressList().stream().collect(Collectors.toList()),
return new Filter(new ArrayList<>(proto.getBannedOfferIdsList()),
new ArrayList<>(proto.getBannedNodeAddressList()),
proto.getBannedPaymentAccountsList().stream()
.map(PaymentAccountFilter::fromProto)
.collect(Collectors.toList()),
CollectionUtils.isEmpty(proto.getBannedCurrenciesList()) ? null : proto.getBannedCurrenciesList().stream().collect(Collectors.toList()),
CollectionUtils.isEmpty(proto.getBannedPaymentMethodsList()) ? null : proto.getBannedPaymentMethodsList().stream().collect(Collectors.toList()),
CollectionUtils.isEmpty(proto.getArbitratorsList()) ? null : proto.getArbitratorsList().stream().collect(Collectors.toList()),
CollectionUtils.isEmpty(proto.getSeedNodesList()) ? null : proto.getSeedNodesList().stream().collect(Collectors.toList()),
CollectionUtils.isEmpty(proto.getPriceRelayNodesList()) ? null : proto.getPriceRelayNodesList().stream().collect(Collectors.toList()),
CollectionUtils.isEmpty(proto.getBannedCurrenciesList()) ? null : new ArrayList<>(proto.getBannedCurrenciesList()),
CollectionUtils.isEmpty(proto.getBannedPaymentMethodsList()) ? null : new ArrayList<>(proto.getBannedPaymentMethodsList()),
CollectionUtils.isEmpty(proto.getArbitratorsList()) ? null : new ArrayList<>(proto.getArbitratorsList()),
CollectionUtils.isEmpty(proto.getSeedNodesList()) ? null : new ArrayList<>(proto.getSeedNodesList()),
CollectionUtils.isEmpty(proto.getPriceRelayNodesList()) ? null : new ArrayList<>(proto.getPriceRelayNodesList()),
proto.getPreventPublicBtcNetwork(),
CollectionUtils.isEmpty(proto.getBtcNodesList()) ? null : proto.getBtcNodesList().stream().collect(Collectors.toList()),
CollectionUtils.isEmpty(proto.getBtcNodesList()) ? null : new ArrayList<>(proto.getBtcNodesList()),
proto.getDisableDao(),
proto.getSignatureAsBase64(),
proto.getOwnerPubKeyBytes().toByteArray(),
CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap());

View File

@ -25,6 +25,7 @@ import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.TradeWalletService;
import bisq.core.btc.wallet.TxBroadcaster;
import bisq.core.btc.wallet.WalletService;
import bisq.core.dao.exceptions.DaoDisabledException;
import bisq.core.offer.Offer;
import bisq.core.offer.availability.ArbitratorSelection;
import bisq.core.offer.placeoffer.PlaceOfferModel;
@ -154,9 +155,16 @@ public class CreateMakerFeeTx extends Task<PlaceOfferModel> {
});
}
} catch (Throwable t) {
offer.setErrorMessage("An error occurred.\n" +
"Error message:\n"
+ t.getMessage());
if (t instanceof DaoDisabledException) {
offer.setErrorMessage("You cannot pay the trade fee in BSQ at the moment because the DAO features have been " +
"disabled due technical problems. Please use the BTC fee option until the issues are resolved. " +
"For more information please visit the Bisq Forum.");
} else {
offer.setErrorMessage("An error occurred.\n" +
"Error message:\n"
+ t.getMessage());
}
failed(t);
}
}

View File

@ -25,6 +25,7 @@ import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.TradeWalletService;
import bisq.core.btc.wallet.TxBroadcaster;
import bisq.core.btc.wallet.WalletService;
import bisq.core.dao.exceptions.DaoDisabledException;
import bisq.core.offer.availability.ArbitratorSelection;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
@ -147,7 +148,13 @@ public class CreateTakerFeeTx extends TradeTask {
});
}
} catch (Throwable t) {
failed(t);
if (t instanceof DaoDisabledException) {
failed("You cannot pay the trade fee in BSQ at the moment because the DAO features have been " +
"disabled due technical problems. Please use the BTC fee option until the issues are resolved. " +
"For more information please visit the Bisq Forum.");
} else {
failed(t);
}
}
}
}

View File

@ -1838,6 +1838,7 @@ filterWindow.seedNode=Filtered seed nodes (comma sep. onion addresses)
filterWindow.priceRelayNode=Filtered price relay nodes (comma sep. onion addresses)
filterWindow.btcNode=Filtered Bitcoin nodes (comma sep. addresses + port)
filterWindow.preventPublicBtcNetwork=Prevent usage of public Bitcoin network
filterWindow.disableDao=Disable DAO
filterWindow.add=Add filter
filterWindow.remove=Remove filter

View File

@ -43,7 +43,7 @@ public class UserPayloadModelVOTest {
vo.setDisplayedAlert(new Alert("message", true, "version", new byte[]{12, -64, 12}, "string", null));
vo.setDevelopersFilter(new Filter(Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(),
Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(),
false, Lists.newArrayList(), "string", new byte[]{10, 0, 0}, null));
false, Lists.newArrayList(), false, "string", new byte[]{10, 0, 0}, null));
vo.setRegisteredArbitrator(ArbitratorTest.getArbitratorMock());
vo.setRegisteredMediator(MediatorTest.getMediatorMock());
vo.setAcceptedArbitrators(Lists.newArrayList(ArbitratorTest.getArbitratorMock()));

View File

@ -140,6 +140,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
InputTextField priceRelayNodesInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.priceRelayNode"));
InputTextField btcNodesInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.btcNode"));
CheckBox preventPublicBtcNetworkCheckBox = addLabelCheckBox(gridPane, ++rowIndex, Res.get("filterWindow.preventPublicBtcNetwork"));
CheckBox disableDaoCheckBox = addLabelCheckBox(gridPane, ++rowIndex, Res.get("filterWindow.disableDao"));
final Filter filter = filterManager.getDevelopersFilter();
if (filter != null) {
@ -180,6 +181,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
preventPublicBtcNetworkCheckBox.setSelected(filter.isPreventPublicBtcNetwork());
disableDaoCheckBox.setSelected(filter.isDisableDao());
}
Button sendButton = new AutoTooltipButton(Res.get("filterWindow.add"));
sendButton.setOnAction(e -> {
@ -264,7 +266,8 @@ public class FilterWindow extends Overlay<FilterWindow> {
seedNodes,
priceRelayNodes,
preventPublicBtcNetworkCheckBox.isSelected(),
btcNodes),
btcNodes,
disableDaoCheckBox.isSelected()),
keyInputTextField.getText()))
hide();
else