aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/gitian-downloader/cdecker-key.pgpbin0 -> 2230 bytes
-rw-r--r--depends/packages/boost.mk3
-rw-r--r--depends/packages/native_comparisontool.mk6
-rw-r--r--depends/patches/boost/gcc_5_no_cxx11.patch37
-rw-r--r--doc/build-osx.md25
-rwxr-xr-xqa/pull-tester/rpc-tests.sh1
-rwxr-xr-xqa/rpc-tests/httpbasics.py34
-rwxr-xr-xqa/rpc-tests/nodehandling.py69
-rwxr-xr-xqa/rpc-tests/proxy_test.py62
-rw-r--r--src/addrman.cpp8
-rw-r--r--src/addrman.h2
-rw-r--r--src/init.cpp41
-rw-r--r--src/net.cpp68
-rw-r--r--src/net.h11
-rw-r--r--src/netbase.cpp5
-rw-r--r--src/netbase.h1
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/rpcclient.cpp2
-rw-r--r--src/rpcnet.cpp128
-rw-r--r--src/rpcprotocol.h2
-rw-r--r--src/rpcserver.cpp4
-rw-r--r--src/rpcserver.h4
-rw-r--r--src/scheduler.cpp4
-rw-r--r--src/test/rpc_tests.cpp83
-rw-r--r--src/wallet/db.cpp12
-rw-r--r--src/wallet/db.h4
26 files changed, 515 insertions, 103 deletions
diff --git a/contrib/gitian-downloader/cdecker-key.pgp b/contrib/gitian-downloader/cdecker-key.pgp
new file mode 100644
index 0000000000..928a74b315
--- /dev/null
+++ b/contrib/gitian-downloader/cdecker-key.pgp
Binary files differ
diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk
index f50828c546..e7aa48ddf8 100644
--- a/depends/packages/boost.mk
+++ b/depends/packages/boost.mk
@@ -3,7 +3,7 @@ $(package)_version=1_55_0
$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.55.0
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
$(package)_sha256_hash=fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52
-$(package)_patches=darwin_boost_atomic-1.patch darwin_boost_atomic-2.patch
+$(package)_patches=darwin_boost_atomic-1.patch darwin_boost_atomic-2.patch gcc_5_no_cxx11.patch
define $(package)_set_vars
$(package)_config_opts_release=variant=release
@@ -28,6 +28,7 @@ endef
define $(package)_preprocess_cmds
patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-1.patch && \
patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-2.patch && \
+ patch -p2 < $($(package)_patch_dir)/gcc_5_no_cxx11.patch && \
echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$(boost_archiver_$(host_os))\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam
endef
diff --git a/depends/packages/native_comparisontool.mk b/depends/packages/native_comparisontool.mk
index d1b86dc2de..2a8a19b0a2 100644
--- a/depends/packages/native_comparisontool.mk
+++ b/depends/packages/native_comparisontool.mk
@@ -1,8 +1,8 @@
package=native_comparisontool
-$(package)_version=0f7b5d8
-$(package)_download_path=https://github.com/TheBlueMatt/test-scripts/raw/38b490a2599d422b12d5ce8f165792f63fd8f54f
+$(package)_version=be0eef7
+$(package)_download_path=https://github.com/theuni/bitcoind-comparisontool/raw/master
$(package)_file_name=pull-tests-$($(package)_version).jar
-$(package)_sha256_hash=ecd43b988a8b673b483e4f69f931596360a5e90fc415c75c4c259faa690df198
+$(package)_sha256_hash=46c2efa25e717751e1ef380d428761b1e37b43d6d1e92ac761b15ee92703e560
$(package)_install_dirname=BitcoindComparisonTool_jar
$(package)_install_filename=BitcoindComparisonTool.jar
diff --git a/depends/patches/boost/gcc_5_no_cxx11.patch b/depends/patches/boost/gcc_5_no_cxx11.patch
new file mode 100644
index 0000000000..04514c593a
--- /dev/null
+++ b/depends/patches/boost/gcc_5_no_cxx11.patch
@@ -0,0 +1,37 @@
+From eec808554936ae068b23df07ab54d4dc6302a695 Mon Sep 17 00:00:00 2001
+From: jzmaddock <jzmaddock@gmail.com>
+Date: Sat, 23 Aug 2014 09:38:02 +0100
+Subject: [PATCH] Fix BOOST_NO_CXX11_VARIADIC_TEMPLATES definition - the
+ feature was introduced in GCC 4.4.
+
+---
+ include/boost/config/compiler/gcc.hpp | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+diff --git a/include/boost/config/compiler/gcc.hpp b/include/boost/config/compiler/gcc.hpp
+index f37159d..97d8a18 100644
+--- a/include/boost/config/compiler/gcc.hpp
++++ b/include/boost/config/compiler/gcc.hpp
+@@ -154,14 +154,6 @@
+ # define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
+ # define BOOST_NO_CXX11_RVALUE_REFERENCES
+ # define BOOST_NO_CXX11_STATIC_ASSERT
+-
+-// Variadic templates compiler:
+-// http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html
+-# if defined(__VARIADIC_TEMPLATES) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4) && defined(__GXX_EXPERIMENTAL_CXX0X__))
+-# define BOOST_HAS_VARIADIC_TMPL
+-# else
+-# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+-# endif
+ #endif
+
+ // C++0x features in 4.4.n and later
+@@ -176,6 +168,7 @@
+ # define BOOST_NO_CXX11_DELETED_FUNCTIONS
+ # define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
+ # define BOOST_NO_CXX11_INLINE_NAMESPACES
++# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ #endif
+
+ #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 913e72519f..dc319dd1c4 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -32,33 +32,10 @@ Instructions: Homebrew
#### Install dependencies using Homebrew
- brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt5
+ brew install autoconf automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf qt5
NOTE: Building with Qt4 is still supported, however, could result in a broken UI. As such, building with Qt5 is recommended.
-#### Installing berkeley-db4 using Homebrew
-
-The homebrew package for berkeley-db4 has been broken for some time. It will install without Java though.
-
-Running this command takes you into brew's interactive mode, which allows you to configure, make, and install by hand:
-```
-$ brew install https://raw.github.com/homebrew/homebrew/master/Library/Formula/berkeley-db4.rb -–without-java
-```
-
-The rest of these commands are run inside brew interactive mode:
-```
-/private/tmp/berkeley-db4-UGpd0O/db-4.8.30 $ cd ..
-/private/tmp/berkeley-db4-UGpd0O $ db-4.8.30/dist/configure --prefix=/usr/local/Cellar/berkeley-db4/4.8.30 --mandir=/usr/local/Cellar/berkeley-db4/4.8.30/share/man --enable-cxx
-/private/tmp/berkeley-db4-UGpd0O $ make
-/private/tmp/berkeley-db4-UGpd0O $ make install
-/private/tmp/berkeley-db4-UGpd0O $ exit
-```
-
-After exiting, you'll get a warning that the install is keg-only, which means it wasn't symlinked to `/usr/local`. You don't need it to link it to build bitcoin, but if you want to, here's how:
-
- $ brew link --force berkeley-db4
-
-
### Building `bitcoind`
1. Clone the github tree to get the source code and go into the directory.
diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh
index 9b318650e9..426d81fa90 100755
--- a/qa/pull-tester/rpc-tests.sh
+++ b/qa/pull-tester/rpc-tests.sh
@@ -32,6 +32,7 @@ testScripts=(
'merkle_blocks.py'
'signrawtransactions.py'
'walletbackup.py'
+ 'nodehandling.py'
);
testScriptsExt=(
'bipdersig-p2p.py'
diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py
index 64ba49df64..8ccb821286 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -4,7 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-# Test REST interface
+# Test rpc http basics
#
from test_framework.test_framework import BitcoinTestFramework
@@ -20,83 +20,83 @@ try:
except ImportError:
import urlparse
-class HTTPBasicsTest (BitcoinTestFramework):
+class HTTPBasicsTest (BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir, extra_args=[['-rpckeepalive=1'], ['-rpckeepalive=0'], [], []])
- def run_test(self):
-
+ def run_test(self):
+
#################################################
# lowlevel check for http persistent connection #
#################################################
url = urlparse.urlparse(self.nodes[0].url)
authpair = url.username + ':' + url.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
-
+
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
-
+
#send 2nd request without closing connection
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
out2 = conn.getresponse().read();
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
conn.close()
-
+
#same should be if we add keep-alive because this should be the std. behaviour
headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection": "keep-alive"}
-
+
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
-
+
#send 2nd request without closing connection
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
out2 = conn.getresponse().read();
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
conn.close()
-
+
#now do the same with "Connection: close"
headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection":"close"}
-
+
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
- assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
-
+ assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
+
#node1 (2nd node) is running with disabled keep-alive option
urlNode1 = urlparse.urlparse(self.nodes[1].url)
authpair = urlNode1.username + ':' + urlNode1.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
-
+
conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #connection must be closed because keep-alive was set to false
-
+
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is off
urlNode2 = urlparse.urlparse(self.nodes[2].url)
authpair = urlNode2.username + ':' + urlNode2.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
-
+
conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default
-
+
if __name__ == '__main__':
HTTPBasicsTest ().main ()
diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py
new file mode 100755
index 0000000000..9a77bd97e8
--- /dev/null
+++ b/qa/rpc-tests/nodehandling.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test node handling
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+import base64
+
+try:
+ import http.client as httplib
+except ImportError:
+ import httplib
+try:
+ import urllib.parse as urlparse
+except ImportError:
+ import urlparse
+
+class NodeHandlingTest (BitcoinTestFramework):
+ def run_test(self):
+ ###########################
+ # setban/listbanned tests #
+ ###########################
+ assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point
+ self.nodes[2].setban("127.0.0.1", "add")
+ time.sleep(3) #wait till the nodes are disconected
+ assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point
+ assert_equal(len(self.nodes[2].listbanned()), 1)
+ self.nodes[2].clearbanned()
+ assert_equal(len(self.nodes[2].listbanned()), 0)
+ self.nodes[2].setban("127.0.0.0/24", "add")
+ assert_equal(len(self.nodes[2].listbanned()), 1)
+ try:
+ self.nodes[2].setban("127.0.0.1", "add") #throws exception because 127.0.0.1 is within range 127.0.0.0/24
+ except:
+ pass
+ assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24
+ try:
+ self.nodes[2].setban("127.0.0.1", "remove")
+ except:
+ pass
+ assert_equal(len(self.nodes[2].listbanned()), 1)
+ self.nodes[2].setban("127.0.0.0/24", "remove")
+ assert_equal(len(self.nodes[2].listbanned()), 0)
+ self.nodes[2].clearbanned()
+ assert_equal(len(self.nodes[2].listbanned()), 0)
+
+ ###########################
+ # RPC disconnectnode test #
+ ###########################
+ url = urlparse.urlparse(self.nodes[1].url)
+ self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
+ time.sleep(2) #disconnecting a node needs a little bit of time
+ for node in self.nodes[0].getpeerinfo():
+ assert(node['addr'] != url.hostname+":"+str(p2p_port(1)))
+
+ connect_nodes_bi(self.nodes,0,1) #reconnect the node
+ found = False
+ for node in self.nodes[0].getpeerinfo():
+ if node['addr'] == url.hostname+":"+str(p2p_port(1)):
+ found = True
+ assert(found)
+
+if __name__ == '__main__':
+ NodeHandlingTest ().main ()
diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py
index 9a9b2f5300..3623c16162 100755
--- a/qa/rpc-tests/proxy_test.py
+++ b/qa/rpc-tests/proxy_test.py
@@ -68,10 +68,10 @@ class ProxyTest(BitcoinTestFramework):
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
- ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0']
+ ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
])
- def node_test(self, node, proxies, auth):
+ def node_test(self, node, proxies, auth, test_onion=True):
rv = []
# Test: outgoing IPv4 connection through node
node.addnode("15.61.23.23:1234", "onetry")
@@ -99,17 +99,18 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(cmd.password, None)
rv.append(cmd)
- # Test: outgoing onion connection through node
- node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
- cmd = proxies[2].queue.get()
- assert(isinstance(cmd, Socks5Command))
- assert_equal(cmd.atyp, AddressType.DOMAINNAME)
- assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
- assert_equal(cmd.port, 8333)
- if not auth:
- assert_equal(cmd.username, None)
- assert_equal(cmd.password, None)
- rv.append(cmd)
+ if test_onion:
+ # Test: outgoing onion connection through node
+ node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
+ cmd = proxies[2].queue.get()
+ assert(isinstance(cmd, Socks5Command))
+ assert_equal(cmd.atyp, AddressType.DOMAINNAME)
+ assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
+ assert_equal(cmd.port, 8333)
+ if not auth:
+ assert_equal(cmd.username, None)
+ assert_equal(cmd.password, None)
+ rv.append(cmd)
# Test: outgoing DNS name connection through node
node.addnode("node.noumenon:8333", "onetry")
@@ -139,8 +140,41 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(len(credentials), 4)
# proxy on IPv6 localhost
- self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False)
+ self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
+
+ def networks_dict(d):
+ r = {}
+ for x in d['networks']:
+ r[x['name']] = x
+ return r
+
+ # test RPC getnetworkinfo
+ n0 = networks_dict(self.nodes[0].getnetworkinfo())
+ for net in ['ipv4','ipv6','onion']:
+ assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr))
+ assert_equal(n0[net]['proxy_randomize_credentials'], True)
+ assert_equal(n0['onion']['reachable'], True)
+
+ n1 = networks_dict(self.nodes[1].getnetworkinfo())
+ for net in ['ipv4','ipv6']:
+ assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr))
+ assert_equal(n1[net]['proxy_randomize_credentials'], False)
+ assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
+ assert_equal(n1['onion']['proxy_randomize_credentials'], False)
+ assert_equal(n1['onion']['reachable'], True)
+ n2 = networks_dict(self.nodes[2].getnetworkinfo())
+ for net in ['ipv4','ipv6','onion']:
+ assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr))
+ assert_equal(n2[net]['proxy_randomize_credentials'], True)
+ assert_equal(n2['onion']['reachable'], True)
+
+ n3 = networks_dict(self.nodes[3].getnetworkinfo())
+ for net in ['ipv4','ipv6']:
+ assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
+ assert_equal(n3[net]['proxy_randomize_credentials'], False)
+ assert_equal(n3['onion']['reachable'], False)
+
if __name__ == '__main__':
ProxyTest().main()
diff --git a/src/addrman.cpp b/src/addrman.cpp
index c41ee3f9fc..b605f4351d 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -8,8 +8,6 @@
#include "serialize.h"
#include "streams.h"
-using namespace std;
-
int CAddrInfo::GetTriedBucket(const uint256& nKey) const
{
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetHash().GetCheapHash();
@@ -68,7 +66,7 @@ double CAddrInfo::GetChance(int64_t nNow) const
fChance *= 0.01;
// deprioritize 66% after each failed attempt, but at most 1/28th to avoid the search taking forever or overly penalizing outages.
- fChance *= pow(0.66, min(nAttempts, 8));
+ fChance *= pow(0.66, std::min(nAttempts, 8));
return fChance;
}
@@ -258,7 +256,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP
bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty))
- pinfo->nTime = max((int64_t)0, addr.nTime - nTimePenalty);
+ pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty);
// add services
pinfo->nServices |= addr.nServices;
@@ -283,7 +281,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP
return false;
} else {
pinfo = Create(addr, source, &nId);
- pinfo->nTime = max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
+ pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
nNew++;
fNew = true;
}
diff --git a/src/addrman.h b/src/addrman.h
index 373b0f39f3..2623d89809 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -458,7 +458,7 @@ public:
}
//! Return the number of (unique) addresses in all tables.
- int size()
+ size_t size() const
{
return vRandom.size();
}
diff --git a/src/init.cpp b/src/init.cpp
index 76def363e4..bcdd1f2f3d 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -987,31 +987,36 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
}
- proxyType addrProxy;
- bool fProxy = false;
- if (mapArgs.count("-proxy")) {
- addrProxy = proxyType(CService(mapArgs["-proxy"], 9050), GetBoolArg("-proxyrandomize", true));
+ bool proxyRandomize = GetBoolArg("-proxyrandomize", true);
+ // -proxy sets a proxy for all outgoing network traffic
+ // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
+ std::string proxyArg = GetArg("-proxy", "");
+ if (proxyArg != "" && proxyArg != "0") {
+ proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize);
if (!addrProxy.IsValid())
- return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"]));
+ return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg));
SetProxy(NET_IPV4, addrProxy);
SetProxy(NET_IPV6, addrProxy);
+ SetProxy(NET_TOR, addrProxy);
SetNameProxy(addrProxy);
- fProxy = true;
+ SetReachable(NET_TOR); // by default, -proxy sets onion as reachable, unless -noonion later
}
- // -onion can override normal proxy, -noonion disables connecting to .onion entirely
- if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") &&
- (fProxy || mapArgs.count("-onion"))) {
- proxyType addrOnion;
- if (!mapArgs.count("-onion"))
- addrOnion = addrProxy;
- else
- addrOnion = proxyType(CService(mapArgs["-onion"], 9050), GetBoolArg("-proxyrandomize", true));
- if (!addrOnion.IsValid())
- return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"]));
- SetProxy(NET_TOR, addrOnion);
- SetReachable(NET_TOR);
+ // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
+ // -noonion (or -onion=0) disables connecting to .onion entirely
+ // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)
+ std::string onionArg = GetArg("-onion", "");
+ if (onionArg != "") {
+ if (onionArg == "0") { // Handle -noonion/-onion=0
+ SetReachable(NET_TOR, false); // set onions as unreachable
+ } else {
+ proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize);
+ if (!addrOnion.IsValid())
+ return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg));
+ SetProxy(NET_TOR, addrOnion);
+ SetReachable(NET_TOR);
+ }
}
// see Step 2: parameter interactions for more information about these
diff --git a/src/net.cpp b/src/net.cpp
index 42ac0e50ea..0511256e55 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -332,6 +332,15 @@ CNode* FindNode(const CNetAddr& ip)
return NULL;
}
+CNode* FindNode(const CSubNet& subNet)
+{
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ if (subNet.Match((CNetAddr)pnode->addr))
+ return (pnode);
+ return NULL;
+}
+
CNode* FindNode(const std::string& addrName)
{
LOCK(cs_vNodes);
@@ -434,11 +443,12 @@ void CNode::PushVersion()
-std::map<CNetAddr, int64_t> CNode::setBanned;
+std::map<CSubNet, int64_t> CNode::setBanned;
CCriticalSection CNode::cs_setBanned;
void CNode::ClearBanned()
{
+ LOCK(cs_setBanned);
setBanned.clear();
}
@@ -447,7 +457,24 @@ bool CNode::IsBanned(CNetAddr ip)
bool fResult = false;
{
LOCK(cs_setBanned);
- std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
+ for (std::map<CSubNet, int64_t>::iterator it = setBanned.begin(); it != setBanned.end(); it++)
+ {
+ CSubNet subNet = (*it).first;
+ int64_t t = (*it).second;
+
+ if(subNet.Match(ip) && GetTime() < t)
+ fResult = true;
+ }
+ }
+ return fResult;
+}
+
+bool CNode::IsBanned(CSubNet subnet)
+{
+ bool fResult = false;
+ {
+ LOCK(cs_setBanned);
+ std::map<CSubNet, int64_t>::iterator i = setBanned.find(subnet);
if (i != setBanned.end())
{
int64_t t = (*i).second;
@@ -458,14 +485,37 @@ bool CNode::IsBanned(CNetAddr ip)
return fResult;
}
-bool CNode::Ban(const CNetAddr &addr) {
+void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset, bool sinceUnixEpoch) {
+ CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128"));
+ Ban(subNet, bantimeoffset, sinceUnixEpoch);
+}
+
+void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset, bool sinceUnixEpoch) {
int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
- {
- LOCK(cs_setBanned);
- if (setBanned[addr] < banTime)
- setBanned[addr] = banTime;
- }
- return true;
+ if (bantimeoffset > 0)
+ banTime = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
+
+ LOCK(cs_setBanned);
+ if (setBanned[subNet] < banTime)
+ setBanned[subNet] = banTime;
+}
+
+bool CNode::Unban(const CNetAddr &addr) {
+ CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128"));
+ return Unban(subNet);
+}
+
+bool CNode::Unban(const CSubNet &subNet) {
+ LOCK(cs_setBanned);
+ if (setBanned.erase(subNet))
+ return true;
+ return false;
+}
+
+void CNode::GetBanned(std::map<CSubNet, int64_t> &banMap)
+{
+ LOCK(cs_setBanned);
+ banMap = setBanned; //create a thread safe copy
}
diff --git a/src/net.h b/src/net.h
index 938f2376f7..69e4c592a9 100644
--- a/src/net.h
+++ b/src/net.h
@@ -66,6 +66,7 @@ unsigned int SendBufferSize();
void AddOneShot(const std::string& strDest);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
+CNode* FindNode(const CSubNet& subNet);
CNode* FindNode(const std::string& addrName);
CNode* FindNode(const CService& ip);
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL);
@@ -284,7 +285,7 @@ protected:
// Denial-of-service detection/prevention
// Key is IP address, value is banned-until-time
- static std::map<CNetAddr, int64_t> setBanned;
+ static std::map<CSubNet, int64_t> setBanned;
static CCriticalSection cs_setBanned;
// Whitelisted ranges. Any node connecting from these is automatically
@@ -606,7 +607,13 @@ public:
// new code.
static void ClearBanned(); // needed for unit testing
static bool IsBanned(CNetAddr ip);
- static bool Ban(const CNetAddr &ip);
+ static bool IsBanned(CSubNet subnet);
+ static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
+ static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
+ static bool Unban(const CNetAddr &ip);
+ static bool Unban(const CSubNet &ip);
+ static void GetBanned(std::map<CSubNet, int64_t> &banmap);
+
void copyStats(CNodeStats &stats);
static bool IsWhitelistedRange(const CNetAddr &ip);
diff --git a/src/netbase.cpp b/src/netbase.cpp
index e3cb4e706f..adac5c2d07 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -1330,6 +1330,11 @@ bool operator!=(const CSubNet& a, const CSubNet& b)
return !(a==b);
}
+bool operator<(const CSubNet& a, const CSubNet& b)
+{
+ return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
+}
+
#ifdef WIN32
std::string NetworkErrorString(int err)
{
diff --git a/src/netbase.h b/src/netbase.h
index 1f2957116e..27f0eac2a2 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -125,6 +125,7 @@ class CSubNet
friend bool operator==(const CSubNet& a, const CSubNet& b);
friend bool operator!=(const CSubNet& a, const CSubNet& b);
+ friend bool operator<(const CSubNet& a, const CSubNet& b);
};
/** A combination of a network address (CNetAddr) and a (TCP) port */
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 681617bd81..f828ce2534 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -687,7 +687,7 @@ void RPCConsole::disconnectSelectedNode()
QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address);
// Find the node, disconnect it and clear the selected node
if (CNode *bannedNode = FindNode(strNode.toStdString())) {
- bannedNode->CloseSocketDisconnect();
+ bannedNode->fDisconnect = true;
clearSelectedNode();
}
}
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index f254da5de0..1d94e4f61b 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -93,6 +93,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "estimatepriority", 0 },
{ "prioritisetransaction", 1 },
{ "prioritisetransaction", 2 },
+ { "setban", 2 },
+ { "setban", 3 },
};
class CRPCConvertTable
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index c4e038eebb..1572b16687 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -214,6 +214,28 @@ UniValue addnode(const UniValue& params, bool fHelp)
return NullUniValue;
}
+UniValue disconnectnode(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "disconnectnode \"node\" \n"
+ "\nImmediately disconnects from the specified node.\n"
+ "\nArguments:\n"
+ "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
+ "\nExamples:\n"
+ + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
+ + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
+ );
+
+ CNode* pNode = FindNode(params[0].get_str());
+ if (pNode == NULL)
+ throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
+
+ pNode->fDisconnect = true;
+
+ return NullUniValue;
+}
+
UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
@@ -443,3 +465,109 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("warnings", GetWarnings("statusbar")));
return obj;
}
+
+UniValue setban(const UniValue& params, bool fHelp)
+{
+ string strCommand;
+ if (params.size() >= 2)
+ strCommand = params[1].get_str();
+ if (fHelp || params.size() < 2 ||
+ (strCommand != "add" && strCommand != "remove"))
+ throw runtime_error(
+ "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n"
+ "\nAttempts add or remove a IP/Subnet from the banned list.\n"
+ "\nArguments:\n"
+ "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n"
+ "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n"
+ "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n"
+ "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
+ "\nExamples:\n"
+ + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
+ + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
+ + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400")
+ );
+
+ CSubNet subNet;
+ CNetAddr netAddr;
+ bool isSubnet = false;
+
+ if (params[0].get_str().find("/") != string::npos)
+ isSubnet = true;
+
+ if (!isSubnet)
+ netAddr = CNetAddr(params[0].get_str());
+ else
+ subNet = CSubNet(params[0].get_str());
+
+ if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
+ throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
+
+ if (strCommand == "add")
+ {
+ if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr))
+ throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
+
+ int64_t banTime = 0; //use standard bantime if not specified
+ if (params.size() >= 3 && !params[2].isNull())
+ banTime = params[2].get_int64();
+
+ bool absolute = false;
+ if (params.size() == 4 && params[3].isTrue())
+ absolute = true;
+
+ isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute);
+
+ //disconnect possible nodes
+ while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr)))
+ bannedNode->fDisconnect = true;
+ }
+ else if(strCommand == "remove")
+ {
+ if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
+ throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
+ }
+
+ return NullUniValue;
+}
+
+UniValue listbanned(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "listbanned\n"
+ "\nList all banned IPs/Subnets.\n"
+ "\nExamples:\n"
+ + HelpExampleCli("listbanned", "")
+ + HelpExampleRpc("listbanned", "")
+ );
+
+ std::map<CSubNet, int64_t> banMap;
+ CNode::GetBanned(banMap);
+
+ UniValue bannedAddresses(UniValue::VARR);
+ for (std::map<CSubNet, int64_t>::iterator it = banMap.begin(); it != banMap.end(); it++)
+ {
+ UniValue rec(UniValue::VOBJ);
+ rec.push_back(Pair("address", (*it).first.ToString()));
+ rec.push_back(Pair("banned_untill", (*it).second));
+ bannedAddresses.push_back(rec);
+ }
+
+ return bannedAddresses;
+}
+
+UniValue clearbanned(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "clearbanned\n"
+ "\nClear all banned IPs.\n"
+ "\nExamples:\n"
+ + HelpExampleCli("clearbanned", "")
+ + HelpExampleRpc("clearbanned", "")
+ );
+
+ CNode::ClearBanned();
+
+ return NullUniValue;
+}
diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h
index b9fa091955..ccd2439c9f 100644
--- a/src/rpcprotocol.h
+++ b/src/rpcprotocol.h
@@ -63,6 +63,8 @@ enum RPCErrorCode
RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //! Still downloading initial blocks
RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added
RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before
+ RPC_CLIENT_NODE_NOT_CONNECTED = -29, //! Node to disconnect not found in connected nodes
+ RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //! Invalid IP/Subnet
//! Wallet errors
RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.)
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 3894dd08bb..6d089c6738 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -273,11 +273,15 @@ static const CRPCCommand vRPCCommands[] =
/* P2P networking */
{ "network", "getnetworkinfo", &getnetworkinfo, true },
{ "network", "addnode", &addnode, true },
+ { "network", "disconnectnode", &disconnectnode, true },
{ "network", "getaddednodeinfo", &getaddednodeinfo, true },
{ "network", "getconnectioncount", &getconnectioncount, true },
{ "network", "getnettotals", &getnettotals, true },
{ "network", "getpeerinfo", &getpeerinfo, true },
{ "network", "ping", &ping, true },
+ { "network", "setban", &setban, true },
+ { "network", "listbanned", &listbanned, true },
+ { "network", "clearbanned", &clearbanned, true },
/* Block chain and UTXO */
{ "blockchain", "getblockchaininfo", &getblockchaininfo, true },
diff --git a/src/rpcserver.h b/src/rpcserver.h
index 7b462a8b79..d08ae72f5c 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -151,8 +151,12 @@ extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rp
extern UniValue getpeerinfo(const UniValue& params, bool fHelp);
extern UniValue ping(const UniValue& params, bool fHelp);
extern UniValue addnode(const UniValue& params, bool fHelp);
+extern UniValue disconnectnode(const UniValue& params, bool fHelp);
extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp);
extern UniValue getnettotals(const UniValue& params, bool fHelp);
+extern UniValue setban(const UniValue& params, bool fHelp);
+extern UniValue listbanned(const UniValue& params, bool fHelp);
+extern UniValue clearbanned(const UniValue& params, bool fHelp);
extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue importprivkey(const UniValue& params, bool fHelp);
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index c42eb7244d..d5bb588b71 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -50,8 +50,10 @@ void CScheduler::serviceQueue()
// Keep waiting until timeout
}
#else
+ // Some boost versions have a conflicting overload of wait_until that returns void.
+ // Explicitly use a template here to avoid hitting that overload.
while (!shouldStop() && !taskQueue.empty() &&
- newTaskScheduled.wait_until(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
+ newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
// Keep waiting until timeout
}
#endif
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 08f988fdbf..c38df0ecf3 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -177,4 +177,87 @@ BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr)
BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::ffff:127.0.0.1")).ToString(), "127.0.0.1");
}
+BOOST_AUTO_TEST_CASE(rpc_ban)
+{
+ BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
+
+ UniValue r;
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0 add")));
+ BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.0:8334")), runtime_error); //portnumber for setban not allowed
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ UniValue ar = r.get_array();
+ UniValue o1 = ar[0].get_obj();
+ UniValue adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.255");
+ BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0 remove")));;
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ BOOST_CHECK_EQUAL(ar.size(), 0);
+
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 1607731200 true")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ UniValue banned_until = find_value(o1, "banned_untill");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
+ BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check
+
+ BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
+
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 200")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ banned_until = find_value(o1, "banned_untill");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0");
+ int64_t now = GetTime();
+ BOOST_CHECK(banned_until.get_int64() > now);
+ BOOST_CHECK(banned_until.get_int64()-now <= 200);
+
+ // must throw an exception because 127.0.0.1 is in already banned suubnet range
+ BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.1 add")), runtime_error);
+
+ BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0/24 remove")));;
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ BOOST_CHECK_EQUAL(ar.size(), 0);
+
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/255.255.0.0 add")));
+ BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.1.1 add")), runtime_error);
+
+ BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ BOOST_CHECK_EQUAL(ar.size(), 0);
+
+
+ BOOST_CHECK_THROW(r = CallRPC(string("setban test add")), runtime_error); //invalid IP
+
+ //IPv6 tests
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+
+ BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:db8::/30 add")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/ffff:fffc:0:0:0:0:0:0");
+
+ BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 53cfcf0961..e5bc653c33 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -43,7 +43,7 @@ void CDBEnv::EnvShutdown()
if (ret != 0)
LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
if (!fMockDb)
- DbEnv(0).remove(path.string().c_str(), 0);
+ DbEnv(0).remove(strPath.c_str(), 0);
}
void CDBEnv::Reset()
@@ -78,10 +78,10 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn)
boost::this_thread::interruption_point();
- path = pathIn;
- boost::filesystem::path pathLogDir = path / "database";
+ strPath = pathIn.string();
+ boost::filesystem::path pathLogDir = pathIn / "database";
TryCreateDirectory(pathLogDir);
- boost::filesystem::path pathErrorFile = path / "db.log";
+ boost::filesystem::path pathErrorFile = pathIn / "db.log";
LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());
unsigned int nEnvFlags = 0;
@@ -98,7 +98,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn)
dbenv->set_flags(DB_AUTO_COMMIT, 1);
dbenv->set_flags(DB_TXN_WRITE_NOSYNC, 1);
dbenv->log_set_config(DB_LOG_AUTO_REMOVE, 1);
- int ret = dbenv->open(path.string().c_str(),
+ int ret = dbenv->open(strPath.c_str(),
DB_CREATE |
DB_INIT_LOCK |
DB_INIT_LOG |
@@ -455,7 +455,7 @@ void CDBEnv::Flush(bool fShutdown)
dbenv->log_archive(&listp, DB_ARCH_REMOVE);
Close();
if (!fMockDb)
- boost::filesystem::remove_all(path / "database");
+ boost::filesystem::remove_all(boost::filesystem::path(strPath) / "database");
}
}
}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 2df6f6e5a9..64071caa3a 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -27,7 +27,9 @@ class CDBEnv
private:
bool fDbEnvInit;
bool fMockDb;
- boost::filesystem::path path;
+ // Don't change into boost::filesystem::path, as that can result in
+ // shutdown problems/crashes caused by a static initialized internal pointer.
+ std::string strPath;
void EnvShutdown();