Browse Source

Merge pull request #4327

a339a37 error out, when we detect -socks argument (Philip Kaufmann)
0127a9b remove SOCKS4 support from core and GUI (Philip Kaufmann)
0.10
Wladimir J. van der Laan 10 years ago
parent
commit
4252f2928b
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 20
      src/init.cpp
  2. 116
      src/netbase.cpp
  3. 6
      src/netbase.h
  4. 20
      src/qt/forms/optionsdialog.ui
  5. 8
      src/qt/optionsdialog.cpp
  6. 24
      src/qt/optionsmodel.cpp
  7. 8
      src/qt/paymentserver.cpp
  8. 2
      src/rpcmisc.cpp
  9. 2
      src/rpcnet.cpp

20
src/init.cpp

@ -239,9 +239,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n"; strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n";
strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n"; strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n";
strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n"; strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n";
strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS proxy") + "\n"; strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS5 proxy") + "\n";
strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n"; strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n";
strUsage += " -socks=<n> " + _("Select SOCKS version for -proxy (4 or 5, default: 5)") + "\n";
strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n"; strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n";
#ifdef USE_UPNP #ifdef USE_UPNP
#if USE_UPNP #if USE_UPNP
@ -567,6 +566,9 @@ bool AppInit2(boost::thread_group& threadGroup)
// Check for -debugnet (deprecated) // Check for -debugnet (deprecated)
if (GetBoolArg("-debugnet", false)) if (GetBoolArg("-debugnet", false))
InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net")); InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net"));
// Check for -socks - as this is a privacy risk to continue, exit here
if (mapArgs.count("-socks"))
return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
// Check for -tor - as this is a privacy risk to continue, exit here // Check for -tor - as this is a privacy risk to continue, exit here
if (GetBoolArg("-tor", false)) if (GetBoolArg("-tor", false))
return InitError(_("Error: Unsupported argument -tor found, use -onion.")); return InitError(_("Error: Unsupported argument -tor found, use -onion."));
@ -746,10 +748,6 @@ bool AppInit2(boost::thread_group& threadGroup)
RegisterNodeSignals(GetNodeSignals()); RegisterNodeSignals(GetNodeSignals());
int nSocksVersion = GetArg("-socks", 5);
if (nSocksVersion != 4 && nSocksVersion != 5)
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
if (mapArgs.count("-onlynet")) { if (mapArgs.count("-onlynet")) {
std::set<enum Network> nets; std::set<enum Network> nets;
BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) {
@ -773,12 +771,10 @@ bool AppInit2(boost::thread_group& threadGroup)
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"]));
if (!IsLimited(NET_IPV4)) if (!IsLimited(NET_IPV4))
SetProxy(NET_IPV4, addrProxy, nSocksVersion); SetProxy(NET_IPV4, addrProxy);
if (nSocksVersion > 4) {
if (!IsLimited(NET_IPV6)) if (!IsLimited(NET_IPV6))
SetProxy(NET_IPV6, addrProxy, nSocksVersion); SetProxy(NET_IPV6, addrProxy);
SetNameProxy(addrProxy, nSocksVersion); SetNameProxy(addrProxy);
}
fProxy = true; fProxy = true;
} }
@ -792,7 +788,7 @@ bool AppInit2(boost::thread_group& threadGroup)
addrOnion = CService(mapArgs["-onion"], 9050); addrOnion = CService(mapArgs["-onion"], 9050);
if (!addrOnion.IsValid()) if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"])); return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"]));
SetProxy(NET_TOR, addrOnion, 5); SetProxy(NET_TOR, addrOnion);
SetReachable(NET_TOR); SetReachable(NET_TOR);
} }

116
src/netbase.cpp

@ -37,7 +37,7 @@ using namespace std;
// Settings // Settings
static proxyType proxyInfo[NET_MAX]; static proxyType proxyInfo[NET_MAX];
static proxyType nameproxyInfo; static CService nameProxy;
static CCriticalSection cs_proxyInfos; static CCriticalSection cs_proxyInfos;
int nConnectTimeout = 5000; int nConnectTimeout = 5000;
bool fNameLookup = false; bool fNameLookup = false;
@ -214,50 +214,6 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
return Lookup(pszName, addr, portDefault, false); return Lookup(pszName, addr, portDefault, false);
} }
bool static Socks4(const CService &addrDest, SOCKET& hSocket)
{
LogPrintf("SOCKS4 connecting %s\n", addrDest.ToString());
if (!addrDest.IsIPv4())
{
closesocket(hSocket);
return error("Proxy destination is not IPv4");
}
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET)
{
closesocket(hSocket);
return error("Cannot get proxy destination address");
}
memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
char* pszSocks4 = pszSocks4IP;
int nSize = sizeof(pszSocks4IP);
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
if (ret != nSize)
{
closesocket(hSocket);
return error("Error sending to proxy");
}
char pchRet[8];
if (recv(hSocket, pchRet, 8, 0) != 8)
{
closesocket(hSocket);
return error("Error reading proxy response");
}
if (pchRet[1] != 0x5a)
{
closesocket(hSocket);
if (pchRet[1] != 0x5b)
LogPrintf("ERROR: Proxy returned error %d\n", pchRet[1]);
return false;
}
LogPrintf("SOCKS4 connected %s\n", addrDest.ToString());
return true;
}
bool static Socks5(string strDest, int port, SOCKET& hSocket) bool static Socks5(string strDest, int port, SOCKET& hSocket)
{ {
LogPrintf("SOCKS5 connecting %s\n", strDest); LogPrintf("SOCKS5 connecting %s\n", strDest);
@ -468,53 +424,49 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
return true; return true;
} }
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) { bool SetProxy(enum Network net, CService addrProxy) {
assert(net >= 0 && net < NET_MAX); assert(net >= 0 && net < NET_MAX);
if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5) if (!addrProxy.IsValid())
return false;
if (nSocksVersion != 0 && !addrProxy.IsValid())
return false; return false;
LOCK(cs_proxyInfos); LOCK(cs_proxyInfos);
proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion); proxyInfo[net] = addrProxy;
return true; return true;
} }
bool GetProxy(enum Network net, proxyType &proxyInfoOut) { bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
assert(net >= 0 && net < NET_MAX); assert(net >= 0 && net < NET_MAX);
LOCK(cs_proxyInfos); LOCK(cs_proxyInfos);
if (!proxyInfo[net].second) if (!proxyInfo[net].IsValid())
return false; return false;
proxyInfoOut = proxyInfo[net]; proxyInfoOut = proxyInfo[net];
return true; return true;
} }
bool SetNameProxy(CService addrProxy, int nSocksVersion) { bool SetNameProxy(CService addrProxy) {
if (nSocksVersion != 0 && nSocksVersion != 5) if (!addrProxy.IsValid())
return false;
if (nSocksVersion != 0 && !addrProxy.IsValid())
return false; return false;
LOCK(cs_proxyInfos); LOCK(cs_proxyInfos);
nameproxyInfo = std::make_pair(addrProxy, nSocksVersion); nameProxy = addrProxy;
return true; return true;
} }
bool GetNameProxy(proxyType &nameproxyInfoOut) { bool GetNameProxy(CService &nameProxyOut) {
LOCK(cs_proxyInfos); LOCK(cs_proxyInfos);
if (!nameproxyInfo.second) if(!nameProxy.IsValid())
return false; return false;
nameproxyInfoOut = nameproxyInfo; nameProxyOut = nameProxy;
return true; return true;
} }
bool HaveNameProxy() { bool HaveNameProxy() {
LOCK(cs_proxyInfos); LOCK(cs_proxyInfos);
return nameproxyInfo.second != 0; return nameProxy.IsValid();
} }
bool IsProxy(const CNetAddr &addr) { bool IsProxy(const CNetAddr &addr) {
LOCK(cs_proxyInfos); LOCK(cs_proxyInfos);
for (int i = 0; i < NET_MAX; i++) { for (int i = 0; i < NET_MAX; i++) {
if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first)) if (addr == (CNetAddr)proxyInfo[i])
return true; return true;
} }
return false; return false;
@ -523,31 +475,18 @@ bool IsProxy(const CNetAddr &addr) {
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
{ {
proxyType proxy; proxyType proxy;
// no proxy needed (none set for target network)
// no proxy needed
if (!GetProxy(addrDest.GetNetwork(), proxy)) if (!GetProxy(addrDest.GetNetwork(), proxy))
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
SOCKET hSocket = INVALID_SOCKET; SOCKET hSocket = INVALID_SOCKET;
// first connect to proxy server // first connect to proxy server
if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout)) if (!ConnectSocketDirectly(proxy, hSocket, nTimeout))
return false; return false;
// do socks negotiation // do socks negotiation
switch (proxy.second) {
case 4:
if (!Socks4(addrDest, hSocket))
return false;
break;
case 5:
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
return false; return false;
break;
default:
closesocket(hSocket);
return false;
}
hSocketRet = hSocket; hSocketRet = hSocket;
return true; return true;
@ -561,30 +500,25 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
SOCKET hSocket = INVALID_SOCKET; SOCKET hSocket = INVALID_SOCKET;
proxyType nameproxy; CService nameProxy;
GetNameProxy(nameproxy); GetNameProxy(nameProxy);
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port); CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port);
if (addrResolved.IsValid()) { if (addrResolved.IsValid()) {
addr = addrResolved; addr = addrResolved;
return ConnectSocket(addr, hSocketRet, nTimeout); return ConnectSocket(addr, hSocketRet, nTimeout);
} }
addr = CService("0.0.0.0:0"); addr = CService("0.0.0.0:0");
if (!nameproxy.second)
return false;
if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout))
return false;
switch(nameproxy.second) { if (!HaveNameProxy())
default:
case 4:
closesocket(hSocket);
return false; return false;
case 5: // first connect to name proxy server
if (!Socks5(strDest, port, hSocket)) if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout))
return false;
// do socks negotiation
if (!Socks5(strDest, (unsigned short)port, hSocket))
return false; return false;
break;
}
hSocketRet = hSocket; hSocketRet = hSocket;
return true; return true;

6
src/netbase.h

@ -161,14 +161,14 @@ class CService : public CNetAddr
) )
}; };
typedef std::pair<CService, int> proxyType; typedef CService proxyType;
enum Network ParseNetwork(std::string net); enum Network ParseNetwork(std::string net);
void SplitHostPort(std::string in, int &portOut, std::string &hostOut); void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5); bool SetProxy(enum Network net, CService addrProxy);
bool GetProxy(enum Network net, proxyType &proxyInfoOut); bool GetProxy(enum Network net, proxyType &proxyInfoOut);
bool IsProxy(const CNetAddr &addr); bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5); bool SetNameProxy(CService addrProxy);
bool HaveNameProxy(); bool HaveNameProxy();
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true); bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);

20
src/qt/forms/optionsdialog.ui

@ -328,26 +328,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="socksVersionLabel">
<property name="text">
<string>SOCKS &amp;Version:</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="buddy">
<cstring>socksVersion</cstring>
</property>
</widget>
</item>
<item>
<widget class="QValueComboBox" name="socksVersion">
<property name="toolTip">
<string>SOCKS version of the proxy (e.g. 5)</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_1_Network"> <spacer name="horizontalSpacer_1_Network">
<property name="orientation"> <property name="orientation">

8
src/qt/optionsdialog.cpp

@ -52,15 +52,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
ui->proxyPort->setEnabled(false); ui->proxyPort->setEnabled(false);
ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));
/** SOCKS version is only selectable for default proxy and is always 5 for IPv6 and Tor */
ui->socksVersion->setEnabled(false);
ui->socksVersion->addItem("5", 5);
ui->socksVersion->addItem("4", 4);
ui->socksVersion->setCurrentIndex(0);
connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool))); connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool)));
connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool))); connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool)));
connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool)));
ui->proxyIp->installEventFilter(this); ui->proxyIp->installEventFilter(this);
@ -182,7 +175,6 @@ void OptionsDialog::setMapper()
mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse); mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP); mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);
mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion);
/* Window */ /* Window */
#ifndef Q_OS_MAC #ifndef Q_OS_MAC

24
src/qt/optionsmodel.cpp

@ -122,11 +122,6 @@ void OptionsModel::Init()
// Only try to set -proxy, if user has enabled fUseProxy // Only try to set -proxy, if user has enabled fUseProxy
if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString())) if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()))
addOverriddenOption("-proxy"); addOverriddenOption("-proxy");
if (!settings.contains("nSocksVersion"))
settings.setValue("nSocksVersion", 5);
// Only try to set -socks, if user has enabled fUseProxy
if (settings.value("fUseProxy").toBool() && !SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString()))
addOverriddenOption("-socks");
// Display // Display
if (!settings.contains("language")) if (!settings.contains("language"))
@ -188,8 +183,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
return strlIpPort.at(1); return strlIpPort.at(1);
} }
case ProxySocksVersion:
return settings.value("nSocksVersion", 5);
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
case Fee: { case Fee: {
@ -284,13 +277,6 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
} }
} }
break; break;
case ProxySocksVersion: {
if (settings.value("nSocksVersion") != value) {
settings.setValue("nSocksVersion", value.toInt());
setRestartRequired(true);
}
}
break;
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
case Fee: { // core option - can be changed on-the-fly case Fee: { // core option - can be changed on-the-fly
// Todo: Add is valid check and warn via message, if not // Todo: Add is valid check and warn via message, if not
@ -378,20 +364,16 @@ bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
// GUI settings can be overridden with -proxy. // GUI settings can be overridden with -proxy.
proxyType curProxy; proxyType curProxy;
if (GetProxy(NET_IPV4, curProxy)) { if (GetProxy(NET_IPV4, curProxy)) {
if (curProxy.second == 5) {
proxy.setType(QNetworkProxy::Socks5Proxy); proxy.setType(QNetworkProxy::Socks5Proxy);
proxy.setHostName(QString::fromStdString(curProxy.first.ToStringIP())); proxy.setHostName(QString::fromStdString(curProxy.ToStringIP()));
proxy.setPort(curProxy.first.GetPort()); proxy.setPort(curProxy.GetPort());
return true; return true;
} }
else
return false;
}
else else
proxy.setType(QNetworkProxy::NoProxy); proxy.setType(QNetworkProxy::NoProxy);
return true; return false;
} }
void OptionsModel::setRestartRequired(bool fRequired) void OptionsModel::setRestartRequired(bool fRequired)

8
src/qt/paymentserver.cpp

@ -341,20 +341,14 @@ void PaymentServer::initNetManager()
QNetworkProxy proxy; QNetworkProxy proxy;
// Query active proxy (fails if no SOCKS5 proxy) // Query active SOCKS5 proxy
if (optionsModel->getProxySettings(proxy)) { if (optionsModel->getProxySettings(proxy)) {
if (proxy.type() == QNetworkProxy::Socks5Proxy) {
netManager->setProxy(proxy); netManager->setProxy(proxy);
qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port(); qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
} }
else else
qDebug() << "PaymentServer::initNetManager : No active proxy server found."; qDebug() << "PaymentServer::initNetManager : No active proxy server found.";
}
else
emit message(tr("Net manager warning"),
tr("Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy."),
CClientUIInterface::MSG_WARNING);
connect(netManager, SIGNAL(finished(QNetworkReply*)), connect(netManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(netRequestFinished(QNetworkReply*))); this, SLOT(netRequestFinished(QNetworkReply*)));

2
src/rpcmisc.cpp

@ -72,7 +72,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("timeoffset", GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", Params().NetworkID() == CBaseChainParams::TESTNET)); obj.push_back(Pair("testnet", Params().NetworkID() == CBaseChainParams::TESTNET));
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET

2
src/rpcnet.cpp

@ -371,7 +371,7 @@ Value getnetworkinfo(const Array& params, bool fHelp)
obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("timeoffset", GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
Array localAddresses; Array localAddresses;
{ {

Loading…
Cancel
Save