diff --git a/.gitignore b/.gitignore index 75b5b82224f..a7382415e08 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ deploy .vscode .vim/* */.factorypath +node_modules/ +package.json +package-lock.json diff --git a/common/src/main/java/haveno/common/config/Config.java b/common/src/main/java/haveno/common/config/Config.java index 9147d535362..6c7bb38d164 100644 --- a/common/src/main/java/haveno/common/config/Config.java +++ b/common/src/main/java/haveno/common/config/Config.java @@ -116,6 +116,10 @@ public class Config { public static final String BTC_FEE_INFO = "bitcoinFeeInfo"; public static final String BYPASS_MEMPOOL_VALIDATION = "bypassMempoolValidation"; public static final String PASSWORD_REQUIRED = "passwordRequired"; + public static final String PUB_KEYS_LIST = "pubKeyList"; + public static final String DEV_PRIV_LIST = "devPrivilegeKeyList"; + public static final String MAKER_FEE = "makerFee"; + public static final String TAKER_FEE = "takerFee"; // Default values for certain options public static final int UNSPECIFIED_PORT = -1; @@ -203,6 +207,12 @@ public enum UseTorForXmr { public final boolean bypassMempoolValidation; public final boolean passwordRequired; + // Options supported only within the config file (unless i screw up the implementation) + public final List pubKeyList; + public final List devPrivilegeKeyList; + public final float makerFee; + public final float takerFee; + // Properties derived from options but not exposed as options themselves public final File torDir; public final File walletDir; @@ -612,8 +622,32 @@ public Config(String defaultAppName, File defaultUserDataDir, String... args) { .withRequiredArg() .ofType(boolean.class) .defaultsTo(false); + ArgumentAcceptingOptionSpec pubKeyListOpt = + parser.accepts(PUB_KEYS_LIST, + "List of public keys for the accepted splinter") + .withRequiredArg() + .ofType(String.class) + .withValuesSeparatedBy(',') + .describedAs("key[,...]"); + ArgumentAcceptingOptionSpec devPrivilegeKeyListOpt = + parser.accepts(DEV_PRIV_LIST, + "List of privileged dev keys for the accepted splinter") + .withRequiredArg() + .ofType(String.class) + .withValuesSeparatedBy(',') + .describedAs("key[,...]"); + ArgumentAcceptingOptionSpec makerFeeOpt = + parser.accepts(MAKER_FEE, "Maker fee for the accepted splinter") + .withRequiredArg() + .ofType(Float.class) + .defaultsTo(0.0015f); + ArgumentAcceptingOptionSpec takerFeeOpt = + parser.accepts(TAKER_FEE, "Taker fee for the accepted splinter") + .withRequiredArg() + .ofType(Float.class) + .defaultsTo(0.0075f); - try { +try { CompositeOptionSet options = new CompositeOptionSet(); // Parse command line options @@ -717,7 +751,10 @@ public Config(String defaultAppName, File defaultUserDataDir, String... args) { this.useAllProvidedNodes = options.valueOf(useAllProvidedNodesOpt); this.userAgent = options.valueOf(userAgentOpt); this.numConnectionsForBtc = options.valueOf(numConnectionsForBtcOpt); - + this.pubKeyList = options.valuesOf(pubKeyListOpt); + this.devPrivilegeKeyList = options.valuesOf(devPrivilegeKeyListOpt); + this.makerFee = options.valueOf(makerFeeOpt); + this.takerFee = options.valueOf(takerFeeOpt); this.apiPassword = options.valueOf(apiPasswordOpt); this.apiPort = options.valueOf(apiPortOpt); this.preventPeriodicShutdownAtSeedNode = options.valueOf(preventPeriodicShutdownAtSeedNodeOpt); diff --git a/core/src/main/java/haveno/core/alert/AlertManager.java b/core/src/main/java/haveno/core/alert/AlertManager.java index a54f45c489a..32e0e76c527 100644 --- a/core/src/main/java/haveno/core/alert/AlertManager.java +++ b/core/src/main/java/haveno/core/alert/AlertManager.java @@ -23,6 +23,7 @@ import haveno.common.app.DevEnv; import haveno.common.config.Config; import haveno.common.crypto.KeyRing; +import haveno.core.user.Preferences; import haveno.core.user.User; import haveno.network.p2p.P2PService; import haveno.network.p2p.storage.HashMapChangedListener; @@ -44,6 +45,7 @@ public class AlertManager { private static final Logger log = LoggerFactory.getLogger(AlertManager.class); + private final Preferences preferences; private final P2PService p2PService; private final KeyRing keyRing; private final User user; @@ -58,11 +60,13 @@ public class AlertManager { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public AlertManager(P2PService p2PService, + public AlertManager(Preferences preferences, + P2PService p2PService, KeyRing keyRing, User user, @Named(Config.IGNORE_DEV_MSG) boolean ignoreDevMsg, @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { + this.preferences = preferences; this.p2PService = p2PService; this.keyRing = keyRing; this.user = user; @@ -109,7 +113,7 @@ protected List getPubKeyList() { "026c581ad773d987e6bd10785ac7f7e0e64864aedeb8bce5af37046de812a37854", "025b058c9f2c60d839669dbfa5578cf5a8117d60e6b70e2f0946f8a691273c6a36"); case XMR_MAINNET: - return List.of(); + return preferences.getPubKeyList(); default: throw new RuntimeException("Unhandled base currency network: " + Config.baseCurrencyNetwork()); } diff --git a/core/src/main/java/haveno/core/alert/PrivateNotificationManager.java b/core/src/main/java/haveno/core/alert/PrivateNotificationManager.java index fd6abac5525..6769133b325 100644 --- a/core/src/main/java/haveno/core/alert/PrivateNotificationManager.java +++ b/core/src/main/java/haveno/core/alert/PrivateNotificationManager.java @@ -29,6 +29,7 @@ import haveno.common.crypto.KeyRing; import haveno.common.crypto.PubKeyRing; import haveno.common.proto.network.NetworkEnvelope; +import haveno.core.user.Preferences; import haveno.network.p2p.DecryptedMessageWithPubKey; import haveno.network.p2p.NodeAddress; import haveno.network.p2p.P2PService; @@ -59,6 +60,7 @@ public class PrivateNotificationManager implements MessageListener { private static final Logger log = LoggerFactory.getLogger(PrivateNotificationManager.class); + private final Preferences preferences; private final P2PService p2PService; private final MailboxMessageService mailboxMessageService; private final KeyRing keyRing; @@ -77,12 +79,14 @@ public class PrivateNotificationManager implements MessageListener { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public PrivateNotificationManager(P2PService p2PService, + public PrivateNotificationManager(Preferences preferences, + P2PService p2PService, NetworkNode networkNode, MailboxMessageService mailboxMessageService, KeyRing keyRing, @Named(Config.IGNORE_DEV_MSG) boolean ignoreDevMsg, @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { + this.preferences = preferences; this.p2PService = p2PService; this.networkNode = networkNode; this.mailboxMessageService = mailboxMessageService; @@ -108,7 +112,8 @@ protected List getPubKeyList() { "026c581ad773d987e6bd10785ac7f7e0e64864aedeb8bce5af37046de812a37854", "025b058c9f2c60d839669dbfa5578cf5a8117d60e6b70e2f0946f8a691273c6a36"); case XMR_MAINNET: - return List.of(); + return preferences.getPubKeyList(); + //preland: add pubkey info default: throw new RuntimeException("Unhandled base currency network: " + Config.baseCurrencyNetwork()); } diff --git a/core/src/main/java/haveno/core/app/HavenoSetup.java b/core/src/main/java/haveno/core/app/HavenoSetup.java index 67214fa2402..bf3c9274323 100644 --- a/core/src/main/java/haveno/core/app/HavenoSetup.java +++ b/core/src/main/java/haveno/core/app/HavenoSetup.java @@ -143,7 +143,7 @@ public class HavenoSetup { private final StringProperty topErrorMsg = new SimpleStringProperty(); @Setter @Nullable - private Consumer displayTacHandler; + private Consumer displayTacHandler, displaySplinterManagerHandler; @Setter @Nullable private Consumer chainFileLockedExceptionHandler, @@ -154,7 +154,7 @@ public class HavenoSetup { rejectedTxErrorMessageHandler; @Setter @Nullable - private Consumer displayTorNetworkSettingsHandler; + private Consumer displayTorNetworkSettingsHandler;//, displaySplinterManagerHandler; @Setter @Nullable private Runnable showFirstPopupIfResyncSPVRequestedHandler; @@ -307,10 +307,11 @@ public void start() { } persistHavenoVersion(); - maybeShowTac(this::step2); + maybeShowTac(this::showSplinterManager); } private void step2() { + //showSplinterManager(); readMapsFromResources(this::step3); checkForCorrectOSArchitecture(); checkOSXVersion(); @@ -341,6 +342,22 @@ private void step4() { // Sub tasks /////////////////////////////////////////////////////////////////////////////////////////// + private void showSplinterManager() { + //todo: fix the if statement after debugging is done + if (Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_MAINNET) { + if (displaySplinterManagerHandler != null){ + displaySplinterManagerHandler.accept(() -> { + log.info("wearehere.jpg"); + log.info(preferences.getPubKeyList().toString()); + step2(); + }); + log.info("bioz"); + } else {log.info("we aresoback.json");} + } else { + step2(); + } + //displaySplinterManagerHandler.accept(true); + } private void maybeShowTac(Runnable nextStep) { if (!preferences.isTacAcceptedV120() && !DevEnv.isDevMode()) { if (displayTacHandler != null) diff --git a/core/src/main/java/haveno/core/filter/FilterManager.java b/core/src/main/java/haveno/core/filter/FilterManager.java index cb7e0e9b218..1532b944539 100644 --- a/core/src/main/java/haveno/core/filter/FilterManager.java +++ b/core/src/main/java/haveno/core/filter/FilterManager.java @@ -86,7 +86,7 @@ public interface Listener { private final boolean ignoreDevMsg; private final ObjectProperty filterProperty = new SimpleObjectProperty<>(); private final List listeners = new CopyOnWriteArrayList<>(); - private final List publicKeys; + private List publicKeys; private ECKey filterSigningKey; private final Set invalidFilters = new HashSet<>(); private Consumer filterWarningHandler; @@ -115,11 +115,10 @@ public FilterManager(P2PService p2PService, this.ignoreDevMsg = ignoreDevMsg; publicKeys = useDevPrivilegeKeys ? - Collections.singletonList(DevEnv.DEV_PRIVILEGE_PUB_KEY) : - List.of("0358d47858acdc41910325fce266571540681ef83a0d6fedce312bef9810793a27", - "029340c3e7d4bb0f9e651b5f590b434fecb6175aeaa57145c7804ff05d210e534f", - "034dc7530bf66ffd9580aa98031ea9a18ac2d269f7c56c0e71eca06105b9ed69f9"); - + Collections.singletonList(DevEnv.DEV_PRIVILEGE_PUB_KEY) : preferences.getPubKeyList(); + // List.of("0358d47858acdc41910325fce266571540681ef83a0d6fedce312bef9810793a27", + // "029340c3e7d4bb0f9e651b5f590b434fecb6175aeaa57145c7804ff05d210e534f", + // "034dc7530bf66ffd9580aa98031ea9a18ac2d269f7c56c0e71eca06105b9ed69f9"); banFilter.setBannedNodePredicate(this::isNodeAddressBannedFromNetwork); } @@ -590,6 +589,11 @@ private boolean isFilterPublicKeyInList(Filter filter) { } private boolean isPublicKeyInList(String pubKeyAsHex) { + if(publicKeys.isEmpty()){ + publicKeys = preferences.getPubKeyList(); + //updatePrefs(); //todo: this could loop indefinitely; fix + } + boolean isPublicKeyInList = publicKeys.contains(pubKeyAsHex); if (!isPublicKeyInList) { log.info("pubKeyAsHex is not part of our pub key list (expected case for pre v1.3.9 filter). pubKeyAsHex={}, publicKeys={}", pubKeyAsHex, publicKeys); diff --git a/core/src/main/java/haveno/core/network/p2p/seed/DefaultSeedNodeRepository.java b/core/src/main/java/haveno/core/network/p2p/seed/DefaultSeedNodeRepository.java index c8d9c33d07c..79f10b53200 100644 --- a/core/src/main/java/haveno/core/network/p2p/seed/DefaultSeedNodeRepository.java +++ b/core/src/main/java/haveno/core/network/p2p/seed/DefaultSeedNodeRepository.java @@ -20,6 +20,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import haveno.common.config.Config; +import haveno.core.user.Preferences; import haveno.network.p2p.NodeAddress; import haveno.network.p2p.seed.SeedNodeRepository; import java.io.BufferedReader; @@ -44,10 +45,12 @@ public class DefaultSeedNodeRepository implements SeedNodeRepository { private static final String ENDING = ".seednodes"; private final Collection cache = new HashSet<>(); private final Config config; + private final Preferences preferences; @Inject - public DefaultSeedNodeRepository(Config config) { + public DefaultSeedNodeRepository(Config config, Preferences preferences) { this.config = config; + this.preferences = preferences; } private void reload() { @@ -59,6 +62,13 @@ private void reload() { return; } + //if not, see if there are seed nodes defined at initialization, and use those + if(!preferences.getSeedNodeList().isEmpty()) { + cache.clear(); + preferences.getSeedNodeList().forEach(s -> cache.add(new NodeAddress(s))); + + return; + } cache.clear(); List result = getSeedNodeAddressesFromPropertyFile(config.baseCurrencyNetwork.name().toLowerCase()); @@ -114,7 +124,11 @@ public Collection getSeedNodeAddresses() { return cache; } - + public void reloadFromPrefs() { + reload(); + log.info("ghastly."); + log.info(cache.toString()); + } @Override public boolean isSeedNode(NodeAddress nodeAddress) { if (cache.isEmpty()) diff --git a/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java b/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java index 4b4fc1011ed..c3a07a983ac 100644 --- a/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java +++ b/core/src/main/java/haveno/core/support/dispute/agent/DisputeAgentManager.java @@ -25,6 +25,7 @@ import haveno.common.handlers.ResultHandler; import haveno.common.util.Utilities; import haveno.core.filter.FilterManager; +import haveno.core.user.Preferences; import haveno.core.user.User; import haveno.network.p2p.BootstrapListener; import haveno.network.p2p.NodeAddress; @@ -63,7 +64,7 @@ public abstract class DisputeAgentManager { protected static final long RETRY_REPUBLISH_SEC = 5; protected static final long REPEATED_REPUBLISH_AT_STARTUP_SEC = 60; - protected final List publicKeys; + protected List publicKeys; /////////////////////////////////////////////////////////////////////////////////////////// // Instance fields @@ -76,16 +77,18 @@ public abstract class DisputeAgentManager { protected final ObservableMap observableMap = FXCollections.observableHashMap(); protected List persistedAcceptedDisputeAgents; protected Timer republishTimer, retryRepublishTimer; - + protected final Preferences preferences; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// - public DisputeAgentManager(KeyRing keyRing, + public DisputeAgentManager(Preferences preferences, + KeyRing keyRing, DisputeAgentService disputeAgentService, User user, FilterManager filterManager) { + this.preferences = preferences; this.keyRing = keyRing; this.disputeAgentService = disputeAgentService; this.user = user; @@ -162,6 +165,12 @@ public void onDataReceived() { updateMap(); } + public void updatePrefs() { + log.info("updateprefs"); + publicKeys = getPubKeyList(); + log.info(publicKeys.toString()); + updateMap(); + } public void shutDown() { stopRepublishTimer(); stopRetryRepublishTimer(); @@ -187,10 +196,13 @@ public void updateMap() { log.info("We got the DEV_PRIVILEGE_PUB_KEY in our list of publicKeys. RegistrationPubKey={}, nodeAddress={}", Utilities.bytesAsHexString(e.getRegistrationPubKey()), e.getNodeAddress().getFullAddress()); - else + else{ + log.info(DevEnv.DEV_PRIVILEGE_PUB_KEY); + log.info(pubKeyAsHex); log.warn("We got an disputeAgent which is not in our list of publicKeys. RegistrationPubKey={}, nodeAddress={}", Utilities.bytesAsHexString(e.getRegistrationPubKey()), e.getNodeAddress().getFullAddress()); + } } final boolean isSigValid = verifySignature(e.getPubKeyRing().getSignaturePubKey(), e.getRegistrationPubKey(), @@ -262,6 +274,10 @@ public ECKey getRegistrationKey(String privKeyBigIntString) { } public boolean isPublicKeyInList(String pubKeyAsHex) { + log.info(publicKeys.toString()); + if(publicKeys.isEmpty()){ + updatePrefs(); //todo: this could loop indefinitely; fix + } return publicKeys.contains(pubKeyAsHex); } diff --git a/core/src/main/java/haveno/core/support/dispute/arbitration/arbitrator/ArbitratorManager.java b/core/src/main/java/haveno/core/support/dispute/arbitration/arbitrator/ArbitratorManager.java index 30fe0be18f4..449faba977a 100644 --- a/core/src/main/java/haveno/core/support/dispute/arbitration/arbitrator/ArbitratorManager.java +++ b/core/src/main/java/haveno/core/support/dispute/arbitration/arbitrator/ArbitratorManager.java @@ -40,6 +40,7 @@ import haveno.common.crypto.KeyRing; import haveno.core.filter.FilterManager; import haveno.core.support.dispute.agent.DisputeAgentManager; +import haveno.core.user.Preferences; import haveno.core.user.User; import haveno.network.p2p.storage.payload.ProtectedStorageEntry; import java.util.List; @@ -50,11 +51,12 @@ public class ArbitratorManager extends DisputeAgentManager { @Inject - public ArbitratorManager(KeyRing keyRing, + public ArbitratorManager(Preferences preferences, + KeyRing keyRing, ArbitratorService arbitratorService, User user, FilterManager filterManager) { - super(keyRing, arbitratorService, user, filterManager); + super(preferences, keyRing, arbitratorService, user, filterManager); } @Override @@ -78,7 +80,11 @@ protected List getPubKeyList() { "02a1a458df5acf4ab08fdca748e28f33a955a30854c8c1a831ee733dca7f0d2fcd", "0374dd70f3fa6e47ec5ab97932e1cec6233e98e6ae3129036b17118650c44fd3de"); case XMR_MAINNET: - return List.of(); + // not letting you forget--you need to make this section crash + // either that or figure out what is calling this and get it to update after init + log.info("important thing"); + log.info(preferences.getPubKeyList().toString()); + return preferences.getPubKeyList(); default: throw new RuntimeException("Unhandled base currency network: " + Config.baseCurrencyNetwork()); } diff --git a/core/src/main/java/haveno/core/support/dispute/mediation/mediator/MediatorManager.java b/core/src/main/java/haveno/core/support/dispute/mediation/mediator/MediatorManager.java index 62ad2c01b09..dd4ba36df95 100644 --- a/core/src/main/java/haveno/core/support/dispute/mediation/mediator/MediatorManager.java +++ b/core/src/main/java/haveno/core/support/dispute/mediation/mediator/MediatorManager.java @@ -22,6 +22,7 @@ import haveno.common.crypto.KeyRing; import haveno.core.filter.FilterManager; import haveno.core.support.dispute.agent.DisputeAgentManager; +import haveno.core.user.Preferences; import haveno.core.user.User; import haveno.network.p2p.storage.payload.ProtectedStorageEntry; import java.util.List; @@ -30,11 +31,12 @@ public class MediatorManager extends DisputeAgentManager { @Inject - public MediatorManager(KeyRing keyRing, + public MediatorManager(Preferences preferences, + KeyRing keyRing, MediatorService mediatorService, User user, FilterManager filterManager) { - super(keyRing, mediatorService, user, filterManager); + super(preferences, keyRing, mediatorService, user, filterManager); } @Override diff --git a/core/src/main/java/haveno/core/support/dispute/refund/refundagent/RefundAgentManager.java b/core/src/main/java/haveno/core/support/dispute/refund/refundagent/RefundAgentManager.java index 3e31c38ac7b..3313b54f8b4 100644 --- a/core/src/main/java/haveno/core/support/dispute/refund/refundagent/RefundAgentManager.java +++ b/core/src/main/java/haveno/core/support/dispute/refund/refundagent/RefundAgentManager.java @@ -22,6 +22,7 @@ import haveno.common.crypto.KeyRing; import haveno.core.filter.FilterManager; import haveno.core.support.dispute.agent.DisputeAgentManager; +import haveno.core.user.Preferences; import haveno.core.user.User; import haveno.network.p2p.storage.payload.ProtectedStorageEntry; import java.util.List; @@ -32,11 +33,12 @@ public class RefundAgentManager extends DisputeAgentManager { @Inject - public RefundAgentManager(KeyRing keyRing, + public RefundAgentManager(Preferences preferences, + KeyRing keyRing, RefundAgentService refundAgentService, User user, FilterManager filterManager) { - super(keyRing, refundAgentService, user, filterManager); + super(preferences, keyRing, refundAgentService, user, filterManager); } @Override diff --git a/core/src/main/java/haveno/core/trade/HavenoUtils.java b/core/src/main/java/haveno/core/trade/HavenoUtils.java index 351d6bffee1..35830b6a341 100644 --- a/core/src/main/java/haveno/core/trade/HavenoUtils.java +++ b/core/src/main/java/haveno/core/trade/HavenoUtils.java @@ -65,7 +65,7 @@ */ @Slf4j public class HavenoUtils { - + //preland: UNSTATIC THIS!!! // configure release date private static final String RELEASE_DATE = "25-05-2024 00:00:00"; // optionally set to release date of the network in format dd-mm-yyyy to impose temporary limits, etc. e.g. "25-05-2024 00:00:00" public static final int RELEASE_LIMIT_DAYS = 60; // number of days to limit sell offers to max buy limit for new accounts @@ -309,7 +309,7 @@ public static boolean isSignatureValid(PubKeyRing pubKeyRing, byte[] message, by /** * Sign an offer. - * + * * @param offer is an unsigned offer to sign * @param keyRing is the arbitrator's key ring to sign with * @return the arbitrator's signature diff --git a/core/src/main/java/haveno/core/user/Preferences.java b/core/src/main/java/haveno/core/user/Preferences.java index 311bd3108b3..29157a4d3ed 100644 --- a/core/src/main/java/haveno/core/user/Preferences.java +++ b/core/src/main/java/haveno/core/user/Preferences.java @@ -133,6 +133,8 @@ public boolean isUseTorForXmr() { @Getter private final BooleanProperty useStandbyModeProperty = new SimpleBooleanProperty(prefPayload.isUseStandbyMode()); + private final List pubKeyList; + private final List seedNodeList; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @@ -145,7 +147,8 @@ public Preferences(PersistenceManager persistenceManager, this.persistenceManager = persistenceManager; this.config = config; this.xmrNodesFromOptions = xmrNodesFromOptions; - + this.pubKeyList = null; + this.seedNodeList = null; useAnimationsProperty.addListener((ov) -> { prefPayload.setUseAnimations(useAnimationsProperty.get()); GlobalSettings.setUseAnimations(prefPayload.isUseAnimations()); @@ -395,6 +398,10 @@ public void setTacAcceptedV120(boolean tacAccepted) { requestPersistence(); } + public void setPubKeyList(List pubKeyList) { + prefPayload.setPubKeyList(pubKeyList); + requestPersistence(); + } public void setBsqAverageTrimThreshold(double bsqAverageTrimThreshold) { prefPayload.setBsqAverageTrimThreshold(bsqAverageTrimThreshold); requestPersistence(); @@ -834,7 +841,12 @@ public List getDefaultTxBroadcastServices() { } } - + public List getPubKeyList() { + return prefPayload.getPubKeyList(); + } + public List getSeedNodeList() { + return prefPayload.getSeedNodeList(); + } /////////////////////////////////////////////////////////////////////////////////////////// // Private /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/haveno/core/user/PreferencesPayload.java b/core/src/main/java/haveno/core/user/PreferencesPayload.java index b0a2fd7d4a9..eb0bf21b754 100644 --- a/core/src/main/java/haveno/core/user/PreferencesPayload.java +++ b/core/src/main/java/haveno/core/user/PreferencesPayload.java @@ -131,6 +131,11 @@ public final class PreferencesPayload implements PersistableEnvelope { private boolean denyApiTaker; private boolean notifyOnPreRelease; + private List pubKeyList = new ArrayList<>(); + private List seedNodeList = new ArrayList<>(); + private float makerFee; + private float takerFee; + private XmrNodeSettings xmrNodeSettings = new XmrNodeSettings(); /////////////////////////////////////////////////////////////////////////////////////////// @@ -198,7 +203,11 @@ public Message toProtoMessage() { .setHideNonAccountPaymentMethods(hideNonAccountPaymentMethods) .setShowOffersMatchingMyAccounts(showOffersMatchingMyAccounts) .setDenyApiTaker(denyApiTaker) - .setNotifyOnPreRelease(notifyOnPreRelease); + .setNotifyOnPreRelease(notifyOnPreRelease) + .addAllPubKeyList(pubKeyList) + .addAllSeedNodeList(seedNodeList) + .setMakerFee(makerFee) + .setTakerFee(takerFee); Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory); Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((protobuf.TradeCurrency) e.toProtoMessage())); @@ -217,6 +226,7 @@ public Message toProtoMessage() { Optional.ofNullable(rpcUser).ifPresent(builder::setRpcUser); Optional.ofNullable(rpcPw).ifPresent(builder::setRpcPw); Optional.ofNullable(takeOfferSelectedPaymentAccountId).ifPresent(builder::setTakeOfferSelectedPaymentAccountId); + //Optional.ofNullable(pubKeyList).ifPresent(build::setPubKeyList); Optional.ofNullable(xmrNodeSettings).ifPresent(settings -> builder.setXmrNodeSettings(settings.toProtoMessage())); return protobuf.PersistableEnvelope.newBuilder().setPreferencesPayload(builder).build(); } @@ -298,6 +308,10 @@ public static PreferencesPayload fromProto(protobuf.PreferencesPayload proto, Co proto.getShowOffersMatchingMyAccounts(), proto.getDenyApiTaker(), proto.getNotifyOnPreRelease(), + proto.getPubKeyListList(), + proto.getSeedNodeListList(), + proto.getMakerFee(), + proto.getTakerFee(), XmrNodeSettings.fromProto(proto.getXmrNodeSettings()) ); } diff --git a/core/src/main/resources/xmr_mainnet.seednodes b/core/src/main/resources/xmr_mainnet.seednodes index 3f81fa04832..caa903a283f 100644 --- a/core/src/main/resources/xmr_mainnet.seednodes +++ b/core/src/main/resources/xmr_mainnet.seednodes @@ -1,2 +1,3 @@ # nodeaddress.onion:port [(@owner,@backup)] -placeholder.onion:8000 (@placeholder) \ No newline at end of file +placeholder.onion:8000 (@placeholder) +# preland: fix this diff --git a/desktop/src/main/java/haveno/desktop/main/MainViewModel.java b/desktop/src/main/java/haveno/desktop/main/MainViewModel.java index 4681431b707..a9f4bb9b5f9 100644 --- a/desktop/src/main/java/haveno/desktop/main/MainViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/MainViewModel.java @@ -61,6 +61,7 @@ import haveno.desktop.main.overlays.notifications.NotificationCenter; import haveno.desktop.main.overlays.popups.Popup; import haveno.desktop.main.overlays.windows.DisplayAlertMessageWindow; +import haveno.desktop.main.overlays.windows.SplinterManagerWindow; import haveno.desktop.main.overlays.windows.TacWindow; import haveno.desktop.main.overlays.windows.TorNetworkSettingsWindow; import haveno.desktop.main.overlays.windows.UpdateAmazonGiftCardAccountWindow; @@ -121,6 +122,7 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener private final WalletPasswordWindow walletPasswordWindow; private final NotificationCenter notificationCenter; private final TacWindow tacWindow; + private final SplinterManagerWindow splinterManagerWindow; @Getter private final PriceFeedService priceFeedService; private final Config config; @@ -165,6 +167,7 @@ public MainViewModel(HavenoSetup havenoSetup, WalletPasswordWindow walletPasswordWindow, NotificationCenter notificationCenter, TacWindow tacWindow, + SplinterManagerWindow splinterManagerWindow, PriceFeedService priceFeedService, Config config, AccountAgeWitnessService accountAgeWitnessService, @@ -188,6 +191,7 @@ public MainViewModel(HavenoSetup havenoSetup, this.walletPasswordWindow = walletPasswordWindow; this.notificationCenter = notificationCenter; this.tacWindow = tacWindow; + this.splinterManagerWindow = splinterManagerWindow; this.priceFeedService = priceFeedService; this.config = config; this.accountAgeWitnessService = accountAgeWitnessService; @@ -274,7 +278,7 @@ public void onSetupComplete() { UserThread.execute(() -> getShowAppScreen().set(true)); - // show welcome message + // show welcome message if (Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_STAGENET) { String key = "welcome.stagenet"; if (DontShowAgainLookup.showAgain(key)) { @@ -333,6 +337,17 @@ private void setupHandlers() { //noinspection FunctionalExpressionCanBeFolded tacWindow.onAction(acceptedHandler::run).show(); }, 1)); + /* havenoSetup.setDisplaySplinterManagerHandler(show -> { + if (show) { + splinterManagerWindow.show(); + } else if (splinterManagerWindow.isDisplayed()) { + splinterManagerWindow.hide(); + } + });*/ + havenoSetup.setDisplaySplinterManagerHandler(acceptedHandler -> UserThread.runAfter(() -> { + //noinspection FunctionalExpressionCanBeFolded + splinterManagerWindow.onAction(acceptedHandler::run).show(); + }, 1)); havenoSetup.setDisplayTorNetworkSettingsHandler(show -> { if (show) { @@ -550,7 +565,7 @@ private void updateXmrDaemonSyncProgress() { combinedSyncProgress.set(xmrDaemonSyncProgress.doubleValue()); }); } - + private void updateXmrWalletSyncProgress() { final DoubleProperty xmrWalletSyncProgress = havenoSetup.getXmrWalletSyncProgress(); UserThread.execute(() -> { diff --git a/desktop/src/main/java/haveno/desktop/main/overlays/Overlay.java b/desktop/src/main/java/haveno/desktop/main/overlays/Overlay.java index f937fb4add9..39a618012cb 100644 --- a/desktop/src/main/java/haveno/desktop/main/overlays/Overlay.java +++ b/desktop/src/main/java/haveno/desktop/main/overlays/Overlay.java @@ -1049,6 +1049,11 @@ protected void doClose() { closeHandlerOptional.ifPresent(Runnable::run); } + protected void doAction() { + //hide(); + actionHandlerOptional.ifPresent(Runnable::run); + } + protected void setTruncatedMessage() { if (message != null && message.length() > maxChar) truncatedMessage = StringUtils.abbreviate(message, maxChar); diff --git a/desktop/src/main/java/haveno/desktop/main/overlays/windows/SplinterManagerWindow.java b/desktop/src/main/java/haveno/desktop/main/overlays/windows/SplinterManagerWindow.java new file mode 100644 index 00000000000..495529d5476 --- /dev/null +++ b/desktop/src/main/java/haveno/desktop/main/overlays/windows/SplinterManagerWindow.java @@ -0,0 +1,485 @@ +/* + * 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 haveno.desktop.main.overlays.windows; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import haveno.common.UserThread; +import haveno.common.util.Tuple2; +import haveno.common.util.Tuple4; +import haveno.common.util.Utilities; +import haveno.core.app.TorSetup; +import haveno.core.locale.Res; +import haveno.core.network.p2p.seed.DefaultSeedNodeRepository; +import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager; +import haveno.core.user.Preferences; +import haveno.core.user.User; +import haveno.desktop.app.HavenoApp; +import haveno.desktop.components.AutoTooltipButton; +import haveno.desktop.components.BusyAnimation; +import haveno.desktop.components.TitledGroupBg; +import haveno.desktop.main.overlays.Overlay; +import haveno.desktop.main.overlays.popups.Popup; +import static haveno.desktop.util.FormBuilder.addButtonBusyAnimationLabelAfterGroup; +import static haveno.desktop.util.FormBuilder.addComboBox; +import static haveno.desktop.util.FormBuilder.addLabel; +import static haveno.desktop.util.FormBuilder.addRadioButton; +import static haveno.desktop.util.FormBuilder.addTitledGroupBg; +import static haveno.desktop.util.FormBuilder.addTopLabelTextArea; +import haveno.desktop.util.Layout; +import haveno.network.p2p.network.DefaultPluggableTransports; +import haveno.network.p2p.network.NetworkNode; +import haveno.network.p2p.peers.PeerManager; +import haveno.network.p2p.peers.getdata.RequestDataManager; +import haveno.network.p2p.peers.peerexchange.PeerExchangeManager; + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import javafx.collections.FXCollections; +import javafx.geometry.HPos; +import javafx.geometry.Insets; +import javafx.geometry.VPos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Label; +import javafx.scene.control.RadioButton; +import javafx.scene.control.TextArea; +import javafx.scene.control.ToggleGroup; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.util.StringConverter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Singleton +public class SplinterManagerWindow extends Overlay { + + public enum BridgeOption { + NONE, + PROVIDED, + CUSTOM + } + + public enum Transport { + OBFS_4, + OBFS_3, + MEEK_AMAZON, + MEEK_AZURE + } + + private final Preferences preferences; + // private final NetworkNode networkNode; + // private final TorSetup torSetup; + // private Label enterBridgeLabel; + private ComboBox transportTypeComboBox; + // private TextArea bridgeEntriesTextArea; + private TextArea pubKeyListEntriesTextArea; + private TextArea seedNodeListEntriesTextArea; + private TextArea makerFeeEntryTextArea; + private TextArea takerFeeEntryTextArea; + private BridgeOption selectedBridgeOption = BridgeOption.NONE; + private Transport selectedTorTransportOrdinal = Transport.OBFS_4; + private String customBridges = ""; + private String pubKeyList = ""; + private String seedNodeList = ""; + private String makerFee = ""; + private String takerFee = ""; + private DefaultSeedNodeRepository defaultSeedNodeRepository; + private PeerManager peerManager; + private PeerExchangeManager PeerExchangeManager; + private RequestDataManager requestDataManager; + private ArbitratorManager arbitratorManager; + //private User user; + @Inject + public SplinterManagerWindow(Preferences preferences, + DefaultSeedNodeRepository defaultSeedNodeRepository, PeerManager peerManager, PeerExchangeManager PeerExchangeManager, RequestDataManager requestDataManager, ArbitratorManager arbitratorManager, User user) { + this.preferences = preferences; + this.defaultSeedNodeRepository = defaultSeedNodeRepository; + this.peerManager = peerManager; + this.PeerExchangeManager = PeerExchangeManager; + this.requestDataManager = requestDataManager; + this.arbitratorManager = arbitratorManager; + //this.user = user; + type = Type.Attention; + + useShutDownButton(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////////////////////////////////////////////// + + public void show() { + if (!isDisplayed) { + if (headLine == null) + headLine = Res.get("wait this actually works?"); + + width = 1068; + rowIndex = 0; + createGridPane(); + gridPane.getColumnConstraints().get(0).setHalignment(HPos.LEFT); + + addThings(); + super.show(); + // display(); + } + } + @Override + protected void onShow() { + addMontent(); + applyStyles(); + display(); + } + + protected void addThings() { + closeButtonText(Res.get("shutdown text")); + onClose(HavenoApp.getShutDownHandler()); + actionButtonText(Res.get("launch haveno text")); + + /*closeButton = new AutoTooltipButton(closeButtonText == null ? Res.get("shutdown text") : closeButtonText); + closeButton.setOnAction(event -> HavenoApp.getShutDownHandler()); + + if (actionHandlerOptional.isPresent()) { + actionButton = new AutoTooltipButton(Res.get("launch haveno text")); + actionButton.setDefaultButton(true); + //TODO app wide focus + actionButton.requestFocus(); + //actionButton.setOnAction(event -> loadHavenoSplinter()); + // onAction(this::loadHavenoSplinter); + Button urlButton = new AutoTooltipButton(Res.get("torNetworkSettingWindow.openTorWebPage")); + urlButton.setOnAction(event -> { + try { + Utilities.openURI(URI.create("https://bridges.torproject.org/bridges")); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + Pane spacer = new Pane(); + HBox hBox = new HBox(); + hBox.setSpacing(10); + hBox.getChildren().addAll(spacer, urlButton, closeButton, actionButton); + HBox.setHgrow(spacer, Priority.ALWAYS); + + GridPane.setHalignment(hBox, HPos.RIGHT); + GridPane.setRowIndex(hBox, ++rowIndex); + GridPane.setColumnSpan(hBox, 2); + GridPane.setMargin(hBox, new Insets(buttonDistance, 0, 0, 0)); + gridPane.getChildren().add(hBox); + } else if (!hideCloseButton) { + closeButton.setDefaultButton(true); + GridPane.setHalignment(closeButton, HPos.RIGHT); + GridPane.setMargin(closeButton, new Insets(buttonDistance, 0, 0, 0)); + GridPane.setRowIndex(closeButton, rowIndex); + GridPane.setColumnIndex(closeButton, 1); + gridPane.getChildren().add(closeButton); + }*/ + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Protected + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + protected void setupKeyHandler(Scene scene) { + if (!hideCloseButton) { + scene.setOnKeyPressed(e -> { + if (e.getCode() == KeyCode.ESCAPE) { + e.consume(); + doClose(); + } else if (e.getCode() == KeyCode.ENTER) { + e.consume(); + doAction(); + // setBridgeAddressesByCustomBridges(); + } + }); + } + } + + @Override + protected void applyStyles() { + super.applyStyles(); + gridPane.setId("popup-grid-pane-bg"); + } + + private void addMontent() { + /*addTitledGroupBg(gridPane, ++rowIndex, 2, Res.get("torNetworkSettingWindow.deleteFiles.header")); + + Label deleteFilesLabel = addLabel(gridPane, rowIndex, Res.get("torNetworkSettingWindow.deleteFiles.info"), Layout.TWICE_FIRST_ROW_DISTANCE); + deleteFilesLabel.setWrapText(true); + GridPane.setColumnIndex(deleteFilesLabel, 0); + GridPane.setColumnSpan(deleteFilesLabel, 2); + GridPane.setHalignment(deleteFilesLabel, HPos.LEFT); + GridPane.setValignment(deleteFilesLabel, VPos.TOP); + + Tuple4 tuple = addButtonBusyAnimationLabelAfterGroup(gridPane, ++rowIndex, Res.get("torNetworkSettingWindow.deleteFiles.button")); + Button deleteFilesButton = tuple.first; + deleteFilesButton.getStyleClass().remove("action-button"); + deleteFilesButton.setOnAction(e -> { + tuple.second.play(); + tuple.third.setText(Res.get("torNetworkSettingWindow.deleteFiles.progress")); + gridPane.setMouseTransparent(true); + deleteFilesButton.setDisable(true); + cleanTorDir(() -> { + tuple.second.stop(); + tuple.third.setText(""); + new Popup().feedback(Res.get("torNetworkSettingWindow.deleteFiles.success")) + .useShutDownButton() + .hideCloseButton() + .show(); + }); + }); + + + final TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, ++rowIndex, 8, Res.get("torNetworkSettingWindow.bridges.header"), Layout.GROUP_DISTANCE); + titledGroupBg.getStyleClass().add("last"); + + Label bridgesLabel = addLabel(gridPane, rowIndex, Res.get("torNetworkSettingWindow.bridges.info"), Layout.TWICE_FIRST_ROW_AND_GROUP_DISTANCE); + bridgesLabel.setWrapText(true); + GridPane.setColumnIndex(bridgesLabel, 0); + GridPane.setColumnSpan(bridgesLabel, 2); + GridPane.setHalignment(bridgesLabel, HPos.LEFT); + GridPane.setValignment(bridgesLabel, VPos.TOP); + + ToggleGroup toggleGroup = new ToggleGroup(); + + // noBridges + RadioButton noBridgesRadioButton = addRadioButton(gridPane, ++rowIndex, toggleGroup, Res.get("torNetworkSettingWindow.noBridges")); + noBridgesRadioButton.setUserData(BridgeOption.NONE); + GridPane.setMargin(noBridgesRadioButton, new Insets(20, 0, 0, 0)); + + // providedBridges + RadioButton providedBridgesRadioButton = addRadioButton(gridPane, ++rowIndex, toggleGroup, Res.get("torNetworkSettingWindow.providedBridges")); + providedBridgesRadioButton.setUserData(BridgeOption.PROVIDED); + transportTypeComboBox = addComboBox(gridPane, ++rowIndex, Res.get("torNetworkSettingWindow.transportType")); + transportTypeComboBox.setItems(FXCollections.observableArrayList(Arrays.asList( + Transport.OBFS_4, + Transport.OBFS_3, + Transport.MEEK_AMAZON, + Transport.MEEK_AZURE))); + transportTypeComboBox.setConverter(new StringConverter<>() { + @Override + public String toString(Transport transport) { + switch (transport) { + case OBFS_3: + return Res.get("torNetworkSettingWindow.obfs3"); + case MEEK_AMAZON: + return Res.get("torNetworkSettingWindow.meekAmazon"); + case MEEK_AZURE: + return Res.get("torNetworkSettingWindow.meekAzure"); + default: + case OBFS_4: + return Res.get("torNetworkSettingWindow.obfs4"); + } + } + + @Override + public Transport fromString(String string) { + return null; + } + }); + + // customBridges + RadioButton customBridgesRadioButton = addRadioButton(gridPane, ++rowIndex, toggleGroup, Res.get("torNetworkSettingWindow.customBridges")); + customBridgesRadioButton.setUserData(BridgeOption.CUSTOM);*/ + + // final Tuple2 labelTextAreaTuple2 = addTopLabelTextArea(gridPane, ++rowIndex, Res.get("torNetworkSettingWindow.enterBridge"), Res.get("torNetworkSettingWindow.enterBridgePrompt")); + // enterBridgeLabel = labelTextAreaTuple2.first; + // bridgeEntriesTextArea = labelTextAreaTuple2.second; + // bridgeEntriesTextArea.setPrefHeight(60); + final Tuple2 labelTextAreaTuple = addTopLabelTextArea(gridPane, ++rowIndex, Res.get("pub label"), Res.get("pubkey promt")); + pubKeyListEntriesTextArea = labelTextAreaTuple.second; + pubKeyListEntriesTextArea.setPrefHeight(60); + + final Tuple2 labelTextAreaTuple2 = addTopLabelTextArea(gridPane, ++rowIndex, Res.get("seed label"), Res.get("seed prompt")); + seedNodeListEntriesTextArea = labelTextAreaTuple2.second; + seedNodeListEntriesTextArea.setPrefHeight(60); + + final Tuple2 labelTextAreaTuple3 = addTopLabelTextArea(gridPane, ++rowIndex, Res.get("maker fee label"), Res.get("maker fee prompt")); + makerFeeEntryTextArea= labelTextAreaTuple3.second; + makerFeeEntryTextArea.setPrefHeight(60); + + final Tuple2 labelTextAreaTuple4 = addTopLabelTextArea(gridPane, ++rowIndex, Res.get("taker fee label"), Res.get("taker fee prompt")); + takerFeeEntryTextArea= labelTextAreaTuple4.second; + takerFeeEntryTextArea.setPrefHeight(60); + + /*Label label2 = addLabel(gridPane, ++rowIndex, Res.get("torNetworkSettingWindow.restartInfo")); + label2.setWrapText(true); + GridPane.setColumnSpan(label2, 2); + GridPane.setHalignment(label2, HPos.LEFT); + GridPane.setValignment(label2, VPos.TOP); + GridPane.setMargin(label2, new Insets(10, 10, 20, 0)); + + // init persisted values + selectedBridgeOption = BridgeOption.values()[preferences.getBridgeOptionOrdinal()]; + switch (selectedBridgeOption) { + case PROVIDED: + toggleGroup.selectToggle(providedBridgesRadioButton); + break; + case CUSTOM: + toggleGroup.selectToggle(customBridgesRadioButton); + break; + default: + case NONE: + toggleGroup.selectToggle(noBridgesRadioButton); + break; + } + applyToggleSelection(); + + selectedTorTransportOrdinal = Transport.values()[preferences.getTorTransportOrdinal()]; + transportTypeComboBox.getSelectionModel().select(selectedTorTransportOrdinal); + + customBridges = preferences.getCustomBridges(); + // bridgeEntriesTextArea.setText(customBridges); + + toggleGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> { + selectedBridgeOption = (BridgeOption) newValue.getUserData(); + preferences.setBridgeOptionOrdinal(selectedBridgeOption.ordinal()); + applyToggleSelection(); + }); + transportTypeComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + selectedTorTransportOrdinal = newValue; + preferences.setTorTransportOrdinal(selectedTorTransportOrdinal.ordinal()); + setBridgeAddressesByTransport(); + }); + // bridgeEntriesTextArea.textProperty().addListener((observable, oldValue, newValue) -> { + // customBridges = newValue; + // preferences.setCustomBridges(customBridges); + // setBridgeAddressesByCustomBridges(); + // });*/ + pubKeyList = String.join(",", preferences.getPubKeyList()); + log.info(pubKeyList); + pubKeyListEntriesTextArea.setText(pubKeyList != null ? pubKeyList : "" ); + pubKeyListEntriesTextArea.textProperty().addListener((observable, oldValue, newValue) -> { + pubKeyList = newValue; + log.info(pubKeyList); + preferences.setPubKeyList(pubKeyList != null ? Arrays.asList(pubKeyList.split(",")) : null); + updatePubKeyList(); + }); + seedNodeList = String.join(",", preferences.getSeedNodeList()); + seedNodeListEntriesTextArea.setText(seedNodeList != null ? seedNodeList : "" ); + seedNodeListEntriesTextArea.textProperty().addListener((observable, oldValue, newValue) -> { + seedNodeList = newValue; + preferences.setSeedNodeList(seedNodeList != null ? Arrays.asList(seedNodeList.split(",")) : null); + updateSeedNodeList(); + }); + makerFee = Float.toString(preferences.getMakerFee()); + makerFeeEntryTextArea.setText(makerFee != null ? makerFee : "0.0015"); + makerFeeEntryTextArea.textProperty().addListener((observable, oldValue, newValue) -> { + makerFee = newValue; + preferences.setMakerFee(makerFee != null ? Float.parseFloat(makerFee) : null); + }); + takerFee = Float.toString(preferences.getTakerFee()); + takerFeeEntryTextArea.setText(takerFee != null ? takerFee : "0.0075"); + takerFeeEntryTextArea.textProperty().addListener((observable, oldValue, newValue) -> { + takerFee = newValue; + preferences.setTakerFee(takerFee != null ? Float.parseFloat(takerFee) : null); + }); + + } + private void updateSeedNodeList(){ + defaultSeedNodeRepository.reloadFromPrefs(); + peerManager.updateSeedNodes(); + PeerExchangeManager.updateSeedNodes(); + requestDataManager.updateSeedNodes(); + + } + private void updatePubKeyList(){ + arbitratorManager.updatePrefs(); + } + /*private void cleanTorDir(Runnable resultHandler) { + // We shut down Tor to be able to delete locked files (Windows locks files used by a process) + networkNode.shutDown(() -> { + // We give it a bit extra time to be sure that OS locks are removed + UserThread.runAfter(() -> { + torSetup.cleanupTorFiles(resultHandler, errorMessage -> new Popup().error(errorMessage).show()); + }, 3); + }); + } + + private void applyToggleSelection() { + switch (selectedBridgeOption) { + case PROVIDED: + transportTypeComboBox.setDisable(false); + // enterBridgeLabel.setDisable(true); + // bridgeEntriesTextArea.setDisable(true); + + setBridgeAddressesByTransport(); + break; + case CUSTOM: + // enterBridgeLabel.setDisable(false); + // bridgeEntriesTextArea.setDisable(false); + transportTypeComboBox.setDisable(true); + + setBridgeAddressesByCustomBridges(); + break; + default: + case NONE: + transportTypeComboBox.setDisable(true); + //enterBridgeLabel.setDisable(true); + //bridgeEntriesTextArea.setDisable(true); + + preferences.setBridgeAddresses(null); + break; + } + } + + private void setBridgeAddressesByTransport() { + switch (selectedTorTransportOrdinal) { + case OBFS_3: + preferences.setBridgeAddresses(DefaultPluggableTransports.OBFS_3); + break; + case MEEK_AMAZON: + preferences.setBridgeAddresses(DefaultPluggableTransports.MEEK_AMAZON); + break; + case MEEK_AZURE: + preferences.setBridgeAddresses(DefaultPluggableTransports.MEEK_AZURE); + break; + default: + case OBFS_4: + preferences.setBridgeAddresses(DefaultPluggableTransports.OBFS_4); + break; + } + } + + private void setBridgeAddressesByCustomBridges() { + preferences.setBridgeAddresses(customBridges != null ? Arrays.asList(customBridges.split("\\n")) : null); + }*/ + + /*private void loadHavenoSplinter() { + //log.info("hello peepes"); + //UserThread.runAfter(this::updateSplinterPreferences, 500, TimeUnit.MILLISECONDS); + + hide(); + } + private void updateSplinterPreferences() { + //pubkeys are comma separated + //pubKeyList = "google.com,fakesite.co,monero.gov"; + preferences.setPubKeyList(pubKeyList != null ? Arrays.asList(pubKeyList.split(",")) : null); + //log.info(preferences.getPubKeyList().toString()); + }*/ +} diff --git a/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java b/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java index b5bf10df7b0..f2ee7002da1 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/PeerManager.java @@ -99,7 +99,8 @@ public interface Listener { private final NetworkNode networkNode; private final ClockWatcher clockWatcher; - private final Set seedNodeAddresses; + private final SeedNodeRepository seedNodeRepository; + private Set seedNodeAddresses; private final PersistenceManager persistenceManager; private final ClockWatcher.Listener clockWatcherListener; private final List listeners = new CopyOnWriteArrayList<>(); @@ -138,7 +139,10 @@ public PeerManager(NetworkNode networkNode, ClockWatcher clockWatcher, PersistenceManager persistenceManager, @Named(Config.MAX_CONNECTIONS) int maxConnections) { + log.info("preland"); + log.info(seedNodeRepository.getSeedNodeAddresses().toString()); this.networkNode = networkNode; + this.seedNodeRepository = seedNodeRepository; this.seedNodeAddresses = new HashSet<>(seedNodeRepository.getSeedNodeAddresses()); this.clockWatcher = clockWatcher; this.persistenceManager = persistenceManager; @@ -185,6 +189,9 @@ public void shutDown() { } } + public void updateSeedNodes(){ + seedNodeAddresses = new HashSet<>(seedNodeRepository.getSeedNodeAddresses()); + } /////////////////////////////////////////////////////////////////////////////////////////// // PersistedDataHost implementation diff --git a/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java b/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java index 39277f6d584..22c015086de 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/getdata/RequestDataManager.java @@ -92,7 +92,8 @@ public interface ResponseListener { private final NetworkNode networkNode; private final P2PDataStorage dataStorage; private final PeerManager peerManager; - private final List seedNodeAddresses; + private final SeedNodeRepository seedNodeRepository; + private List seedNodeAddresses; private final List responseListeners = new CopyOnWriteArrayList<>(); // As we use Guice injection we cannot set the listener in our constructor but the P2PService calls the setListener @@ -125,6 +126,7 @@ public RequestDataManager(NetworkNode networkNode, this.networkNode.addConnectionListener(this); this.peerManager.addListener(this); + this.seedNodeRepository = seedNodeRepository; this.seedNodeAddresses = new ArrayList<>(seedNodeRepository.getSeedNodeAddresses()); // We shuffle only once so that we use the same seed nodes for preliminary and updated data requests. Collections.shuffle(seedNodeAddresses); @@ -150,6 +152,11 @@ public void shutDown() { closeAllHandlers(); } + public void updateSeedNodes(){ + seedNodeAddresses = new ArrayList<>(seedNodeRepository.getSeedNodeAddresses()); + //not rly sure what this does but it is done is the initialization :shrug: + Collections.shuffle(seedNodeAddresses); + } /////////////////////////////////////////////////////////////////////////////////////////// // API diff --git a/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java b/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java index a6a637fbff0..e1946cb647c 100644 --- a/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java +++ b/p2p/src/main/java/haveno/network/p2p/peers/peerexchange/PeerExchangeManager.java @@ -55,9 +55,11 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener, private final NetworkNode networkNode; private final PeerManager peerManager; - private final Set seedNodeAddresses; + private Set seedNodeAddresses; private final Map handlerMap = new HashMap<>(); + private final SeedNodeRepository seedNodeRepository; + private Timer retryTimer, periodicTimer; private boolean stopped; @@ -77,6 +79,7 @@ public PeerExchangeManager(NetworkNode networkNode, this.networkNode.addConnectionListener(this); this.peerManager.addListener(this); + this.seedNodeRepository = seedNodeRepository; this.seedNodeAddresses = new HashSet<>(seedNodeRepository.getSeedNodeAddresses()); } @@ -91,6 +94,9 @@ public void shutDown() { closeAllHandlers(); } + public void updateSeedNodes(){ + seedNodeAddresses = new HashSet<>(seedNodeRepository.getSeedNodeAddresses()); + } /////////////////////////////////////////////////////////////////////////////////////////// // API diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index 8e988bbe571..483f9602de7 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1733,11 +1733,15 @@ message PreferencesPayload { bool show_offers_matching_my_accounts = 55; bool deny_api_taker = 56; bool notify_on_pre_release = 57; - XmrNodeSettings xmr_node_settings = 58; - int32 clear_data_after_days = 59; - string buy_screen_crypto_currency_code = 60; - string sell_screen_crypto_currency_code = 61; - bool split_offer_output = 62; + repeated string pub_key_list = 58; + repeated string seed_node_list = 59; + float maker_fee = 60; + float taker_fee = 61; + XmrNodeSettings xmr_node_settings = 62; + int32 clear_data_after_days = 63; + string buy_screen_crypto_currency_code = 64; + string sell_screen_crypto_currency_code = 65; + bool split_offer_output = 66; } message AutoConfirmSettings {