From: CryptoManiac Date: Sun, 25 Jan 2015 21:08:42 +0000 (+0300) Subject: Improve Tor support X-Git-Tag: nvc-v0.5.3~132 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=24b2f2d42d10153c24ccef4a14ba57ad24aac183 Improve Tor support * Add list of seed nodes; * Implement Tor settings in the GUI client; * Disable DNS and IRC seeding, public IP discovery in -onlynet=tor mode; * Fix mapMultiArgs issue in SoftSetArg function. --- diff --git a/src/init.cpp b/src/init.cpp index 34cb698..b934e1c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -661,12 +661,21 @@ bool AppInit2() } // see Step 2: parameter interactions for more information about these - fNoListen = !GetBoolArg("-listen", true); - fDiscover = GetBoolArg("-discover", true); - fNameLookup = GetBoolArg("-dns", true); + if (!IsLimited(NET_IPV4) || !IsLimited(NET_IPV6)) + { + fNoListen = !GetBoolArg("-listen", true); + fDiscover = GetBoolArg("-discover", true); + fNameLookup = GetBoolArg("-dns", true); #ifdef USE_UPNP - fUseUPnP = GetBoolArg("-upnp", USE_UPNP); + fUseUPnP = GetBoolArg("-upnp", USE_UPNP); #endif + } else { + // Don't listen, discover addresses or search for nodes if IPv4 and IPv6 networking is disabled. + fNoListen = true; + fDiscover = fNameLookup = fUseUPnP = false; + SoftSetBoolArg("-irc", false); + SoftSetBoolArg("-dnsseed", false); + } bool fBound = false; if (!fNoListen) diff --git a/src/net.cpp b/src/net.cpp index 9e82413..9220122 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1172,6 +1172,22 @@ uint32_t pnSeed[] = 0x4d226805, }; +const char* pchTorSeed[] = +{ + "seedp4knqnoei57u.onion", + "seedr3hhlepyi7fd.onion", + "seed3uuomkclbiz4.onion", + "seedeh7qck3ouff5.onion", + "5rg3vq4jagckeckf.onion", + "seedt3sraf53ajiy.onion", + "seedg4qyccsg42oq.onion", + "novaqrtoywpg7jly.onion", + "seed3d5wolqbgrcb.onion", + "seed24u5dwph3qw4.onion", + "mj26ulzbs2oskgym.onion", + "eqon4usunavt76m7.onion", +}; + void DumpAddresses() { int64_t nStart = GetTimeMillis(); @@ -1316,7 +1332,7 @@ void ThreadOpenConnections2(void* parg) return; // Add seed nodes if IRC isn't working - if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet) + if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet) { std::vector vAdd; for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++) @@ -1335,6 +1351,20 @@ void ThreadOpenConnections2(void* parg) addrman.Add(vAdd, CNetAddr("127.0.0.1")); } + // Add Tor nodes if we have connection with onion router + if (mapArgs.count("-tor")) + { + std::vector vAdd; + for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++) + { + const int64_t nOneWeek = 7*24*60*60; + CAddress addr(CService(pchTorSeed[i], GetDefaultPort())); + addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; + vAdd.push_back(addr); + } + addrman.Add(vAdd, CNetAddr("dummyaddress.onion")); + } + // // Choose an address to connect to based on most recently seen // @@ -1855,12 +1885,17 @@ void StartNode(void* parg) printf("Error: NewThread(ThreadDNSAddressSeed) failed\n"); // Map ports with UPnP - if (fUseUPnP) + if (!fUseUPnP) + printf("UPNP port mapping is disabled\n"); + else MapPort(); // Get addresses from IRC and advertise ours - if (!NewThread(ThreadIRCSeed, NULL)) - printf("Error: NewThread(ThreadIRCSeed) failed\n"); + if (!GetBoolArg("-irc", true)) + printf("IRC seeding disabled\n"); + else + if (!NewThread(ThreadIRCSeed, NULL)) + printf("Error: NewThread(ThreadIRCSeed) failed\n"); // Send and receive from sockets, accept connections if (!NewThread(ThreadSocketHandler, NULL)) diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 73e4801..d5da8e3 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -23,7 +23,7 @@ QTabWidget::North - 0 + 1 @@ -233,6 +233,77 @@ + + + Connect through &Tor: + + + + + + + + + + 60 + 0 + + + + Tor IP: + + + + + + + + 130 + 16777215 + + + + + + + + Port: + + + + + + + + 55 + 16777215 + + + + + + + + Use Tor only + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + Qt::Vertical diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index c69ad82..671b18c 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -20,9 +20,11 @@ OptionsDialog::OptionsDialog(QWidget *parent) : model(0), mapper(0), fRestartWarningDisplayed_Proxy(false), + fRestartWarningDisplayed_Tor(false), fRestartWarningDisplayed_Lang(false), fRestartWarningDisplayed_URL(false), - fProxyIpValid(true) + fProxyIpValid(true), + fTorIpValid(true) { ui->setupUi(this); @@ -35,6 +37,11 @@ OptionsDialog::OptionsDialog(QWidget *parent) : ui->proxyPort->setEnabled(false); ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); + ui->torIp->setEnabled(false); + ui->torPort->setEnabled(false); + ui->torPort->setValidator(new QIntValidator(1, 65535, this)); + ui->TorOnly->setEnabled(false); + ui->socksVersion->setEnabled(false); ui->socksVersion->addItem("5", 5); ui->socksVersion->addItem("4", 4); @@ -45,7 +52,14 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool))); connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy())); + connect(ui->connectTor, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Tor())); + connect(ui->connectTor, SIGNAL(toggled(bool)), ui->torIp, SLOT(setEnabled(bool))); + connect(ui->connectTor, SIGNAL(toggled(bool)), ui->torPort, SLOT(setEnabled(bool))); + connect(ui->connectTor, SIGNAL(toggled(bool)), ui->TorOnly, SLOT(setEnabled(bool))); + connect(ui->TorOnly, SIGNAL(toggled(bool)), ui->connectSocks, SLOT(setDisabled(bool))); + ui->proxyIp->installEventFilter(this); + ui->torIp->installEventFilter(this); /* Window elements init */ #ifdef Q_OS_MAC @@ -100,6 +114,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton())); /* setup/change UI elements when proxy IP is invalid/valid */ connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool))); + /* setup/change UI elements when Tor IP is invalid/valid */ + connect(this, SIGNAL(torIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleTorIpValid(QValidatedLineEdit *, bool))); } OptionsDialog::~OptionsDialog() @@ -146,6 +162,11 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion); + mapper->addMapping(ui->connectTor, OptionsModel::TorUse); + mapper->addMapping(ui->torIp, OptionsModel::TorIP); + mapper->addMapping(ui->torPort, OptionsModel::TorPort); + mapper->addMapping(ui->TorOnly, OptionsModel::TorOnly); + /* Window */ #ifndef Q_OS_MAC mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray); @@ -173,7 +194,7 @@ void OptionsDialog::disableApplyButton() void OptionsDialog::enableSaveButtons() { /* prevent enabling of the save buttons when data modified, if there is an invalid proxy address present */ - if(fProxyIpValid) + if(fProxyIpValid && fTorIpValid) setSaveButtonState(true); } @@ -214,6 +235,15 @@ void OptionsDialog::showRestartWarning_Proxy() } } +void OptionsDialog::showRestartWarning_Tor() +{ + if(!fRestartWarningDisplayed_Proxy) + { + QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting NovaCoin."), QMessageBox::Ok); + fRestartWarningDisplayed_Tor = true; + } +} + void OptionsDialog::showRestartWarning_Lang() { if(!fRestartWarningDisplayed_Lang) @@ -261,6 +291,25 @@ void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState) } } +void OptionsDialog::handleTorIpValid(QValidatedLineEdit *object, bool fState) +{ + // this is used in a check before re-enabling the save buttons + fTorIpValid = fState; + + if(fTorIpValid) + { + enableSaveButtons(); + ui->statusLabel->clear(); + } + else + { + disableSaveButtons(); + object->setValid(fTorIpValid); + ui->statusLabel->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel->setText(tr("The supplied tor address is invalid.")); + } +} + bool OptionsDialog::eventFilter(QObject *object, QEvent *event) { if(event->type() == QEvent::FocusOut) @@ -271,6 +320,13 @@ bool OptionsDialog::eventFilter(QObject *object, QEvent *event) /* Check proxyIp for a valid IPv4/IPv6 address and emit the proxyIpValid signal */ emit proxyIpValid(ui->proxyIp, LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr)); } + + if(object == ui->torIp) + { + CService addr; + /* Check proxyIp for a valid IPv4/IPv6 address and emit the torIpValid signal */ + emit torIpValid(ui->torIp, LookupNumeric(ui->torIp->text().toStdString().c_str(), addr)); + } } return QDialog::eventFilter(object, event); } diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 5d75e06..c2a11df 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -41,22 +41,27 @@ private slots: void on_applyButton_clicked(); void showRestartWarning_Proxy(); + void showRestartWarning_Tor(); void showRestartWarning_Lang(); void showRestartWarning_URL(); void updateDisplayUnit(); void handleProxyIpValid(QValidatedLineEdit *object, bool fState); + void handleTorIpValid(QValidatedLineEdit *object, bool fState); signals: void proxyIpValid(QValidatedLineEdit *object, bool fValid); + void torIpValid(QValidatedLineEdit *object, bool fValid); private: Ui::OptionsDialog *ui; OptionsModel *model; MonitoredDataMapper *mapper; bool fRestartWarningDisplayed_Proxy; + bool fRestartWarningDisplayed_Tor; bool fRestartWarningDisplayed_Lang; bool fRestartWarningDisplayed_URL; bool fProxyIpValid; + bool fTorIpValid; }; #endif // OPTIONSDIALOG_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index d946352..07a2072 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -24,6 +24,7 @@ bool static ApplyProxySettings() } if (nSocksVersion && !addrProxy.IsValid()) return false; + if (!IsLimited(NET_IPV4)) SetProxy(NET_IPV4, addrProxy, nSocksVersion); if (nSocksVersion > 4) { @@ -31,8 +32,27 @@ bool static ApplyProxySettings() if (!IsLimited(NET_IPV6)) SetProxy(NET_IPV6, addrProxy, nSocksVersion); #endif - SetNameProxy(addrProxy, nSocksVersion); } + + SetNameProxy(addrProxy, nSocksVersion); + + return true; +} + +bool static ApplyTorSettings() +{ + QSettings settings; + CService addrTor(settings.value("addrTor", "127.0.0.1:9050").toString().toStdString()); + if (!settings.value("fUseTor", false).toBool()) { + addrTor = CService(); + return false; + } + if (!addrTor.IsValid()) + return false; + + SetProxy(NET_TOR, addrTor, 5); + SetReachable(NET_TOR); + return true; } @@ -60,10 +80,19 @@ void OptionsModel::Init() // command-line options to override the GUI settings: if (settings.contains("fUseUPnP")) SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool()); - if (settings.contains("addrProxy") && settings.value("fUseProxy").toBool()) - SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()); - if (settings.contains("nSocksVersion") && settings.value("fUseProxy").toBool()) - SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString()); + if ( !(settings.value("fTorOnly").toBool() && settings.contains("addrTor")) ) { + if (settings.contains("addrProxy") && settings.value("fUseProxy").toBool()) + SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()); + if (settings.contains("nSocksVersion") && settings.value("fUseProxy").toBool()) + SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString()); + } + + if (settings.contains("addrTor") && settings.value("fUseTor").toBool()) { + SoftSetArg("-tor", settings.value("addrTor").toString().toStdString()); + if (settings.value("fTorOnly").toBool()) + SoftSetArg("-onlynet", "tor"); + } + if (settings.contains("detachDB")) SoftSetBoolArg("-detachdb", settings.value("detachDB").toBool()); if (!language.isEmpty()) @@ -94,7 +123,7 @@ bool OptionsModel::Upgrade() } } QList boolOptions; - boolOptions << "bDisplayAddresses" << "fMinimizeToTray" << "fMinimizeOnClose" << "fUseProxy" << "fUseUPnP"; + boolOptions << "bDisplayAddresses" << "fMinimizeToTray" << "fMinimizeOnClose" << "fUseProxy" << "fUseTor" << "fTorOnly" << "fUseUPnP"; foreach(QString key, boolOptions) { bool value = false; @@ -106,24 +135,38 @@ bool OptionsModel::Upgrade() } try { - CAddress addrProxyAddress; + CAddress addrProxyAddress, addrTorAddress; if (walletdb.ReadSetting("addrProxy", addrProxyAddress)) { settings.setValue("addrProxy", addrProxyAddress.ToStringIPPort().c_str()); walletdb.EraseSetting("addrProxy"); } + + if (walletdb.ReadSetting("addrTor", addrTorAddress)) + { + settings.setValue("addrTor", addrTorAddress.ToStringIPPort().c_str()); + walletdb.EraseSetting("addrTor"); + } } catch (std::ios_base::failure &e) { // 0.6.0rc1 saved this as a CService, which causes failure when parsing as a CAddress - CService addrProxy; + CService addrProxy, addrTor; if (walletdb.ReadSetting("addrProxy", addrProxy)) { settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); walletdb.EraseSetting("addrProxy"); } + + if (walletdb.ReadSetting("addrTor", addrTor)) + { + settings.setValue("addrTor", addrTor.ToStringIPPort().c_str()); + walletdb.EraseSetting("addrTor"); + } } + ApplyProxySettings(); + ApplyTorSettings(); Init(); return true; @@ -168,6 +211,24 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const } case ProxySocksVersion: return settings.value("nSocksVersion", 5); + case TorUse: + return settings.value("fUseTor", false); + case TorIP: { + proxyType proxy; + if (GetProxy(NET_TOR, proxy)) + return QVariant(QString::fromStdString(proxy.first.ToStringIP())); + else + return QVariant(QString::fromStdString("127.0.0.1")); + } + case TorPort: { + proxyType proxy; + if (GetProxy(NET_TOR, proxy)) + return QVariant(proxy.first.GetPort()); + else + return QVariant(9050); + } + case TorOnly: + return settings.value("fTorOnly", false); case Fee: return QVariant(static_cast(nTransactionFee)); case DisplayUnit: @@ -248,6 +309,37 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in successful = ApplyProxySettings(); } break; + case TorUse: { + settings.setValue("fUseTor", value.toBool()); + ApplyTorSettings(); + } + break; + case TorIP: { + proxyType proxy; + proxy.first = CService("127.0.0.1", 9050); + GetProxy(NET_IPV4, proxy); + + CNetAddr addr(value.toString().toStdString()); + proxy.first.SetIP(addr); + settings.setValue("addrTor", proxy.first.ToStringIPPort().c_str()); + successful = ApplyTorSettings(); + } + break; + case TorPort: { + proxyType proxy; + proxy.first = CService("127.0.0.1", 9050); + GetProxy(NET_IPV4, proxy); + + proxy.first.SetPort(value.toInt()); + settings.setValue("addrTor", proxy.first.ToStringIPPort().c_str()); + successful = ApplyTorSettings(); + } + break; + case TorOnly: { + settings.setValue("fTorOnly", value.toBool()); + ApplyTorSettings(); + } + break; case Fee: nTransactionFee = value.toLongLong(); settings.setValue("nTransactionFee", static_cast(nTransactionFee)); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index e3f73b2..09197f7 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -25,6 +25,10 @@ public: ProxyIP, // QString ProxyPort, // int ProxySocksVersion, // int + TorUse, // bool + TorIP, // QString + TorPort, // int + TorOnly, // bool Fee, // qint64 DisplayUnit, // BitcoinUnits::Unit DisplayAddresses, // bool diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 1ce14cd..4b4448a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -56,7 +56,7 @@ Value getaddrmaninfo(const Array& params, bool fHelp) // Sort by the GetChance result backwardly sort(vAddr.begin(), vAddr.end(), addrManItemSort()); - string strFilterNetType = "ipv4"; + string strFilterNetType = ""; if (params.size() == 1) strFilterNetType = params[0].get_str(); @@ -71,9 +71,9 @@ Value getaddrmaninfo(const Array& params, bool fHelp) string strNetType; switch(addr.GetNetwork()) { -// case NET_TOR: -// strNetType = "tor"; -// break; + case NET_TOR: + strNetType = "tor"; + break; // case NET_I2P: // strNetType = "i2p"; // break; @@ -86,7 +86,7 @@ Value getaddrmaninfo(const Array& params, bool fHelp) } - if (strNetType != strFilterNetType) + if (strFilterNetType.size() != 0 && strNetType != strFilterNetType) continue; addrManItem.push_back(Pair("chance", addr.GetChance(GetTime()))); diff --git a/src/util.cpp b/src/util.cpp index be1339f..197e562 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -600,9 +600,11 @@ bool GetBoolArg(const std::string& strArg, bool fDefault) bool SoftSetArg(const std::string& strArg, const std::string& strValue) { - if (mapArgs.count(strArg)) + if (mapArgs.count(strArg) || mapMultiArgs.count(strArg)) return false; mapArgs[strArg] = strValue; + mapMultiArgs[strArg].push_back(strValue); + return true; }