Add full node mode and rpc data to settings

- Change FULL_DAO_NODE option from boolean to string to be able to detect not set values
- isFullDaoNode, rpcUser and rpcPw can be set in the UI. If prog ars are
available they will overwrite the UI data.
This commit is contained in:
Manfred Karrer 2018-10-19 23:43:07 -05:00
parent 75e0daefbf
commit 168a15b5a1
No known key found for this signature in database
GPG Key ID: 401250966A6B2C46
10 changed files with 193 additions and 31 deletions

View File

@ -1273,6 +1273,9 @@ message PreferencesPayload {
bool use_market_notifications = 43;
bool use_price_notifications = 44;
bool use_standby_mode = 45;
bool is_dao_full_node = 46;
string rpc_user = 47;
string rpc_pw = 48;
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -430,9 +430,8 @@ public abstract class BisqExecutable implements GracefulShutDownHandler {
parser.accepts(DaoOptionKeys.FULL_DAO_NODE,
description("If set to true the node requests the blockchain data via RPC requests from Bitcoin Core and " +
"provide the validated BSQ txs to the network. It requires that the other RPC properties are " +
"set as well.", false))
.withRequiredArg()
.ofType(boolean.class);
"set as well.", ""))
.withRequiredArg();
parser.accepts(DaoOptionKeys.GENESIS_TX_ID,
description("Genesis transaction ID when not using the hard coded one", ""))
.withRequiredArg();

View File

@ -17,14 +17,12 @@
package bisq.core.dao.node;
import bisq.core.dao.DaoOptionKeys;
import bisq.core.dao.node.full.FullNode;
import bisq.core.dao.node.lite.LiteNode;
import bisq.core.user.Preferences;
import com.google.inject.Inject;
import javax.inject.Named;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -39,7 +37,14 @@ public class BsqNodeProvider {
@Inject
public BsqNodeProvider(LiteNode bsqLiteNode,
FullNode bsqFullNode,
@Named(DaoOptionKeys.FULL_DAO_NODE) boolean fullDaoNode) {
bsqNode = fullDaoNode ? bsqFullNode : bsqLiteNode;
Preferences preferences) {
boolean rpcDataSet = preferences.getRpcUser() != null && !preferences.getRpcUser().isEmpty()
&& preferences.getRpcPw() != null && !preferences.getRpcPw().isEmpty();
boolean daoFullNode = preferences.isDaoFullNode();
if (daoFullNode && !rpcDataSet)
log.warn("daoFullNode is set but RPC user and pw are missing");
bsqNode = rpcDataSet && daoFullNode ? bsqFullNode : bsqLiteNode;
}
}

View File

@ -17,12 +17,14 @@
package bisq.core.dao.node.full;
import bisq.core.app.BisqEnvironment;
import bisq.core.dao.DaoOptionKeys;
import bisq.core.dao.state.blockchain.PubKeyScript;
import bisq.core.dao.state.blockchain.RawBlock;
import bisq.core.dao.state.blockchain.RawTx;
import bisq.core.dao.state.blockchain.RawTxOutput;
import bisq.core.dao.state.blockchain.TxInput;
import bisq.core.user.Preferences;
import bisq.common.UserThread;
import bisq.common.handlers.ResultHandler;
@ -90,15 +92,23 @@ public class RpcService {
@SuppressWarnings("WeakerAccess")
@Inject
public RpcService(@Named(DaoOptionKeys.RPC_USER) String rpcUser,
@Named(DaoOptionKeys.RPC_PASSWORD) String rpcPassword,
public RpcService(Preferences preferences,
@Named(DaoOptionKeys.RPC_PORT) String rpcPort,
@Named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT) String rpcBlockPort,
@Named(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) boolean dumpBlockchainData) {
this.rpcUser = rpcUser;
this.rpcPassword = rpcPassword;
this.rpcPort = rpcPort;
this.rpcBlockPort = rpcBlockPort;
this.rpcUser = preferences.getRpcUser();
this.rpcPassword = preferences.getRpcPw();
// mainnet is 8332, testnet 18332, regtest 18443
boolean isPortSet = rpcPort != null && !rpcPort.isEmpty();
boolean isMainnet = BisqEnvironment.getBaseCurrencyNetwork().isMainnet();
boolean isTestnet = BisqEnvironment.getBaseCurrencyNetwork().isTestnet();
this.rpcPort = isPortSet ? rpcPort :
isMainnet ? "8332" :
isTestnet ? "18332" :
"18443"; // regtest
this.rpcBlockPort = rpcBlockPort != null && !rpcBlockPort.isEmpty() ? rpcBlockPort : "5125";
this.dumpBlockchainData = dumpBlockchainData;
}

View File

@ -39,7 +39,8 @@ public class CoreNetworkCapabilities {
supportedCapabilities.add(Capabilities.Capability.BLIND_VOTE.ordinal());
supportedCapabilities.add(Capabilities.Capability.BSQ_BLOCK.ordinal());
if (bisqEnvironment.getProperty(DaoOptionKeys.FULL_DAO_NODE, Boolean.class, false))
String isFullDaoNode = bisqEnvironment.getProperty(DaoOptionKeys.FULL_DAO_NODE, String.class, "");
if (isFullDaoNode != null && !isFullDaoNode.isEmpty())
supportedCapabilities.add(Capabilities.Capability.DAO_FULL_NODE.ordinal());
}

View File

@ -23,6 +23,7 @@ import bisq.core.btc.BaseCurrencyNetwork;
import bisq.core.btc.BtcOptionKeys;
import bisq.core.btc.nodes.BtcNodes;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.dao.DaoOptionKeys;
import bisq.core.locale.Country;
import bisq.core.locale.CountryUtil;
import bisq.core.locale.CryptoCurrency;
@ -139,9 +140,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
private final Storage<PreferencesPayload> storage;
private final BisqEnvironment bisqEnvironment;
private final String btcNodesFromOptions;
private final String useTorFlagFromOptions;
private final String referralIdFromOptions;
private final String btcNodesFromOptions, useTorFlagFromOptions, referralIdFromOptions, fullDaoNodeFromOptions,
rpcUserFromOptions, rpcPasswordFromOptions;
@Getter
private final BooleanProperty useStandbyModeProperty = new SimpleBooleanProperty(prefPayload.isUseStandbyMode());
@ -157,13 +157,20 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
BisqEnvironment bisqEnvironment,
@Named(BtcOptionKeys.BTC_NODES) String btcNodesFromOptions,
@Named(BtcOptionKeys.USE_TOR_FOR_BTC) String useTorFlagFromOptions,
@Named(AppOptionKeys.REFERRAL_ID) String referralId) {
@Named(AppOptionKeys.REFERRAL_ID) String referralId,
@Named(DaoOptionKeys.FULL_DAO_NODE) String fullDaoNode,
@Named(DaoOptionKeys.RPC_USER) String rpcUser,
@Named(DaoOptionKeys.RPC_PASSWORD) String rpcPassword) {
this.storage = storage;
this.bisqEnvironment = bisqEnvironment;
this.btcNodesFromOptions = btcNodesFromOptions;
this.useTorFlagFromOptions = useTorFlagFromOptions;
this.referralIdFromOptions = referralId;
this.fullDaoNodeFromOptions = fullDaoNode;
this.rpcUserFromOptions = rpcUser;
this.rpcPasswordFromOptions = rpcPassword;
useAnimationsProperty.addListener((ov) -> {
prefPayload.setUseAnimations(useAnimationsProperty.get());
@ -206,7 +213,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
@Override
public void readPersisted() {
PreferencesPayload persisted = storage.initAndGetPersistedWithFileName("PreferencesPayload", 100);
final BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
TradeCurrency preferredTradeCurrency;
if (persisted != null) {
prefPayload = persisted;
@ -288,6 +295,15 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
if (referralIdFromOptions != null && !referralIdFromOptions.isEmpty())
setReferralId(referralIdFromOptions);
if (fullDaoNodeFromOptions != null && !fullDaoNodeFromOptions.isEmpty())
setDaoFullNode(fullDaoNodeFromOptions.toLowerCase().equals("true"));
if (rpcUserFromOptions != null && !rpcUserFromOptions.isEmpty())
setRpcUser(rpcUserFromOptions);
if (rpcPasswordFromOptions != null && !rpcPasswordFromOptions.isEmpty())
setRpcPw(rpcPasswordFromOptions);
// For users from old versions the 4 flags a false but we want to have it true by default
// PhoneKeyAndToken is also null so we can use that to enable the flags
if (prefPayload.getPhoneKeyAndToken() == null) {
@ -596,6 +612,22 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
this.useStandbyModeProperty.set(useStandbyMode);
}
public void setDaoFullNode(boolean value) {
prefPayload.setDaoFullNode(value);
persist();
}
public void setRpcUser(String value) {
prefPayload.setRpcUser(value);
persist();
}
public void setRpcPw(String value) {
prefPayload.setRpcPw(value);
persist();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
///////////////////////////////////////////////////////////////////////////////////////////
@ -796,5 +828,11 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
long getWithdrawalTxFeeInBytes();
void setUseStandbyMode(boolean useStandbyMode);
void setDaoFullNode(boolean value);
void setRpcUser(String value);
void setRpcPw(String value);
}
}

View File

@ -110,6 +110,11 @@ public final class PreferencesPayload implements PersistableEnvelope {
boolean useMarketNotifications = true;
boolean usePriceNotifications = true;
boolean useStandbyMode = false;
boolean isDaoFullNode = false;
@Nullable
String rpcUser;
@Nullable
String rpcPw;
///////////////////////////////////////////////////////////////////////////////////////////
@ -164,7 +169,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
.setUseTradeNotifications(useTradeNotifications)
.setUseMarketNotifications(useMarketNotifications)
.setUsePriceNotifications(usePriceNotifications)
.setUseStandbyMode(useStandbyMode);
.setUseStandbyMode(useStandbyMode)
.setIsDaoFullNode(isDaoFullNode);
Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory);
Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((PB.TradeCurrency) e.toProtoMessage()));
Optional.ofNullable(offerBookChartScreenCurrencyCode).ifPresent(builder::setOfferBookChartScreenCurrencyCode);
@ -177,6 +183,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
Optional.ofNullable(customBridges).ifPresent(builder::setCustomBridges);
Optional.ofNullable(referralId).ifPresent(builder::setReferralId);
Optional.ofNullable(phoneKeyAndToken).ifPresent(builder::setPhoneKeyAndToken);
Optional.ofNullable(rpcUser).ifPresent(builder::setRpcUser);
Optional.ofNullable(rpcPw).ifPresent(builder::setRpcPw);
return PB.PersistableEnvelope.newBuilder().setPreferencesPayload(builder).build();
}
@ -238,6 +246,9 @@ public final class PreferencesPayload implements PersistableEnvelope {
proto.getUseTradeNotifications(),
proto.getUseMarketNotifications(),
proto.getUsePriceNotifications(),
proto.getUseStandbyMode());
proto.getUseStandbyMode(),
proto.getIsDaoFullNode(),
proto.getRpcUser().isEmpty() ? null : proto.getRpcUser(),
proto.getRpcPw().isEmpty() ? null : proto.getRpcPw());
}
}

View File

@ -859,6 +859,13 @@ setting.preferences.daoOptions=DAO options
setting.preferences.dao.resync.label=Rebuild DAO state from genesis tx:
setting.preferences.dao.resync.button=Resync
setting.preferences.dao.resync.popup=After an application restart the BSQ consensus state will be rebuilt from the genesis transaction.
setting.preferences.dao.isDaoFullNode=Run Bisq as DAO full node
setting.preferences.dao.rpcUser=RPC username
setting.preferences.dao.rpcPw=RPC password
setting.preferences.dao.fullNodeInfo=For running Bisq as DAO full node you need to have Bitcoin Core locally running \
and configured with RPC and other requirements which are documented in ''{0}''.
setting.preferences.dao.fullNodeInfo.ok=Open docs page
setting.preferences.dao.fullNodeInfo.cancel=No, I stick with lite node mode
settings.net.btcHeader=Bitcoin network
settings.net.p2pHeader=P2P network

View File

@ -23,9 +23,11 @@ import bisq.desktop.common.view.FxmlView;
import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.InputTextField;
import bisq.desktop.components.PasswordTextField;
import bisq.desktop.components.TitledGroupBg;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.GUIUtil;
import bisq.desktop.util.ImageUtil;
import bisq.desktop.util.Layout;
@ -99,7 +101,12 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private CheckBox useAnimationsCheckBox, avoidStandbyModeCheckBox,
showOwnOffersInOfferBook, sortMarketCurrenciesNumericallyCheckBox, useCustomFeeCheckbox;
private int gridRow = 0;
private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, referralIdInputTextField;
private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, referralIdInputTextField, rpcUserTextField;
private CheckBox isDaoFullNodeCheckBox;
private PasswordTextField rpcPwTextField;
private TitledGroupBg daoOptionsTitledGroupBg;
private Label rpcUserLabel, rpcPwLabel;
private ChangeListener<Boolean> transactionFeeFocusedListener;
private final Preferences preferences;
private final FeeService feeService;
@ -124,11 +131,12 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private ObservableList<CryptoCurrency> allCryptoCurrencies;
private ObservableList<TradeCurrency> tradeCurrencies;
private InputTextField deviationInputTextField;
private ChangeListener<String> deviationListener, ignoreTradersListListener, referralIdListener;
private ChangeListener<String> deviationListener, ignoreTradersListListener, referralIdListener, rpcUserListener, rpcPwListener;
private ChangeListener<Boolean> deviationFocusedListener;
private ChangeListener<Boolean> useCustomFeeCheckboxListener;
private ChangeListener<Number> transactionFeeChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, initialisation
///////////////////////////////////////////////////////////////////////////////////////////
@ -501,12 +509,36 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
}
private void initializeDaoOptions() {
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 1, Res.get("setting.preferences.daoOptions"), Layout.GROUP_DISTANCE);
GridPane.setColumnSpan(titledGroupBg, 4);
daoOptionsTitledGroupBg = addTitledGroupBg(root, ++gridRow, 2, Res.get("setting.preferences.daoOptions"), Layout.GROUP_DISTANCE);
GridPane.setColumnSpan(daoOptionsTitledGroupBg, 4);
resyncDaoButton = addLabelButton(root, gridRow, Res.get("setting.preferences.dao.resync.label"),
Res.get("setting.preferences.dao.resync.button"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
isDaoFullNodeCheckBox = addLabelCheckBox(root, ++gridRow, Res.getWithCol("setting.preferences.dao.isDaoFullNode")).second;
Tuple2<Label, InputTextField> tuple = addLabelInputTextField(root, ++gridRow, Res.getWithCol("setting.preferences.dao.rpcUser"));
rpcUserLabel = tuple.first;
rpcUserLabel.setVisible(false);
rpcUserLabel.setManaged(false);
rpcUserTextField = tuple.second;
rpcUserTextField.setVisible(false);
rpcUserTextField.setManaged(false);
Tuple2<Label, PasswordTextField> tuple2 = addLabelPasswordTextField(root, ++gridRow, Res.getWithCol("setting.preferences.dao.rpcPw"));
rpcPwLabel = tuple2.first;
rpcPwLabel.setVisible(false);
rpcPwLabel.setManaged(false);
rpcPwTextField = tuple2.second;
rpcPwTextField.setVisible(false);
rpcPwTextField.setManaged(false);
rpcUserListener = (observable, oldValue, newValue) -> {
preferences.setRpcUser(rpcUserTextField.getText());
};
rpcPwListener = (observable, oldValue, newValue) -> {
preferences.setRpcPw(rpcPwTextField.getText());
};
}
///////////////////////////////////////////////////////////////////////////////////////////
// Activate
///////////////////////////////////////////////////////////////////////////////////////////
@ -695,12 +727,67 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
}
private void activateDaoPreferences() {
boolean daoFullNode = preferences.isDaoFullNode();
isDaoFullNodeCheckBox.setSelected(daoFullNode);
String rpcUser = preferences.getRpcUser();
String rpcPw = preferences.getRpcPw();
if (daoFullNode && (rpcUser == null || rpcUser.isEmpty() || rpcPw == null || rpcPw.isEmpty())) {
log.warn("You have full DAO node selected but have not provided the rpc username and password. We reset daoFullNode to false");
isDaoFullNodeCheckBox.setSelected(false);
}
rpcUserTextField.setText(rpcUser);
rpcPwTextField.setText(rpcPw);
updateDaoFields();
resyncDaoButton.setOnAction(e -> daoFacade.resyncDao(() -> {
new Popup<>().attention(Res.get("setting.preferences.dao.resync.popup"))
.useShutDownButton()
.hideCloseButton()
.show();
}));
isDaoFullNodeCheckBox.setOnAction(e -> {
String key = "daoFullModeInfoShown";
if (isDaoFullNodeCheckBox.isSelected() && preferences.showAgain(key)) {
String url = "https://bisq.network/docs/dao/full-node";
new Popup<>().backgroundInfo(Res.get("setting.preferences.dao.fullNodeInfo", url))
.onAction(() -> {
GUIUtil.openWebPage(url);
})
.actionButtonText(Res.get("setting.preferences.dao.fullNodeInfo.ok"))
.closeButtonText(Res.get("setting.preferences.dao.fullNodeInfo.cancel"))
.onClose(() -> UserThread.execute(() -> {
isDaoFullNodeCheckBox.setSelected(false);
updateDaoFields();
}))
.dontShowAgainId(key)
.width(800)
.show();
}
updateDaoFields();
});
rpcUserTextField.textProperty().addListener(rpcUserListener);
rpcPwTextField.textProperty().addListener(rpcPwListener);
}
private void updateDaoFields() {
boolean isDaoFullNode = isDaoFullNodeCheckBox.isSelected();
GridPane.setRowSpan(daoOptionsTitledGroupBg, isDaoFullNode ? 4 : 2);
rpcUserLabel.setVisible(isDaoFullNode);
rpcUserLabel.setManaged(isDaoFullNode);
rpcUserTextField.setVisible(isDaoFullNode);
rpcUserTextField.setManaged(isDaoFullNode);
rpcPwLabel.setVisible(isDaoFullNode);
rpcPwLabel.setManaged(isDaoFullNode);
rpcPwTextField.setVisible(isDaoFullNode);
rpcPwTextField.setManaged(isDaoFullNode);
preferences.setDaoFullNode(isDaoFullNode);
if (!isDaoFullNode) {
rpcPwTextField.clear();
rpcUserTextField.clear();
}
}
private void onSelectNetwork() {
@ -754,5 +841,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private void deactivateDaoPreferences() {
resyncDaoButton.setOnAction(null);
isDaoFullNodeCheckBox.setOnAction(null);
rpcUserTextField.textProperty().removeListener(rpcUserListener);
rpcPwTextField.textProperty().removeListener(rpcUserListener);
}
}

View File

@ -20,11 +20,9 @@ package bisq.seednode;
import bisq.core.app.misc.AppSetup;
import bisq.core.app.misc.AppSetupWithP2P;
import bisq.core.app.misc.AppSetupWithP2PAndDAO;
import bisq.core.dao.DaoOptionKeys;
import bisq.core.user.Preferences;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@ -39,8 +37,8 @@ public class SeedNode {
}
public void startApplication() {
Boolean fullDaoNode = injector.getInstance(Key.get(Boolean.class, Names.named(DaoOptionKeys.FULL_DAO_NODE)));
appSetup = fullDaoNode ? injector.getInstance(AppSetupWithP2PAndDAO.class) : injector.getInstance(AppSetupWithP2P.class);
boolean isDaoFullNode = injector.getInstance(Preferences.class).isDaoFullNode();
appSetup = isDaoFullNode ? injector.getInstance(AppSetupWithP2PAndDAO.class) : injector.getInstance(AppSetupWithP2P.class);
appSetup.start();
}
}