Skip to content

Commit

Permalink
Auto merge of zcash#2176 - str4d:1593-libevent, r=bitcartel
Browse files Browse the repository at this point in the history
  • Loading branch information
zkbot committed Mar 25, 2017
2 parents 2bdb372 + 3da13e8 commit f9f4866
Show file tree
Hide file tree
Showing 34 changed files with 1,656 additions and 1,167 deletions.
14 changes: 14 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,12 @@ if test x$use_pkgconfig = xyes; then
[
PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)])
PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)])
if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then
PKG_CHECK_MODULES([EVENT], [libevent],, [AC_MSG_ERROR(libevent not found.)])
if test x$TARGET_OS != xwindows; then
PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads],, [AC_MSG_ERROR(libevent_pthreads not found.)])
fi
fi
if test "x$use_zmq" = "xyes"; then
PKG_CHECK_MODULES([ZMQ],[libzmq >= 4],
Expand All @@ -709,6 +715,14 @@ else
AC_CHECK_HEADER([openssl/ssl.h],, AC_MSG_ERROR(libssl headers missing),)
AC_CHECK_LIB([ssl], [main],SSL_LIBS=-lssl, AC_MSG_ERROR(libssl missing))

if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then
AC_CHECK_HEADER([event2/event.h],, AC_MSG_ERROR(libevent headers missing),)
AC_CHECK_LIB([event],[main],EVENT_LIBS=-levent,AC_MSG_ERROR(libevent missing))
if test x$TARGET_OS != xwindows; then
AC_CHECK_LIB([event_pthreads],[main],EVENT_PTHREADS_LIBS=-levent_pthreads,AC_MSG_ERROR(libevent_pthreads missing))
fi
fi

if test "x$use_zmq" = "xyes"; then
AC_CHECK_HEADER([zmq.h],
[AC_DEFINE([ENABLE_ZMQ],[1],[Define to 1 to enable ZMQ functions])],
Expand Down
2 changes: 1 addition & 1 deletion contrib/bitcoind.bash-completion
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ _zcashd() {
_get_comp_words_by_ref -n = cur prev words cword

case "$cur" in
-conf=*|-pid=*|-loadblock=*|-rpccookiefile=*|-wallet=*|-rpcsslcertificatechainfile=*|-rpcsslprivatekeyfile=*)
-conf=*|-pid=*|-loadblock=*|-rpccookiefile=*|-wallet=*)
cur="${cur#*=}"
_filedir
return 0
Expand Down
11 changes: 1 addition & 10 deletions contrib/debian/examples/zcash.conf
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@

# How many seconds zcash will wait for a complete RPC HTTP request.
# after the HTTP connection is established.
#rpctimeout=30
#rpcclienttimeout=30

# By default, only RPC connections from localhost are allowed.
# Specify as many rpcallowip= settings as you like to allow connections from other hosts,
Expand All @@ -95,15 +95,6 @@
# running on another host using this option:
#rpcconnect=127.0.0.1

# Use Secure Sockets Layer (also known as TLS or HTTPS) to communicate
# with Zcash -server or zcashd
#rpcssl=1

# OpenSSL settings used when rpcssl=1
#rpcsslciphers=TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH
#rpcsslcertificatechainfile=server.cert
#rpcsslprivatekeyfile=server.pem

# Transaction Fee

# Send transactions as zero-fee transactions if possible (default: 0)
Expand Down
31 changes: 31 additions & 0 deletions depends/packages/libevent.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package=libevent
$(package)_version=2.1.8
$(package)_download_path=https://github.com/libevent/libevent/archive/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_download_file=release-$($(package)_version)-stable.tar.gz
$(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d

define $(package)_preprocess_cmds
./autogen.sh
endef

define $(package)_set_vars
$(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress
$(package)_config_opts_release=--disable-debug-mode
$(package)_config_opts_linux=--with-pic
endef

define $(package)_config_cmds
$($(package)_autoconf)
endef

define $(package)_build_cmds
$(MAKE)
endef

define $(package)_stage_cmds
$(MAKE) DESTDIR=$($(package)_staging_dir) install
endef

define $(package)_postprocess_cmds
endef
2 changes: 1 addition & 1 deletion depends/packages/packages.mk
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
rust_packages := rust librustzcash
zcash_packages := libsnark libgmp libsodium
packages := boost openssl zeromq $(zcash_packages) googletest googlemock
packages := boost openssl libevent zeromq $(zcash_packages) googletest googlemock
native_packages := native_ccache

wallet_packages=bdb
Expand Down
6 changes: 0 additions & 6 deletions doc/man/zcash-cli.1
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,6 @@ Username for JSON\-RPC connections
\fB\-rpcpassword=\fR<pw>
.IP
Password for JSON\-RPC connections
.PP
SSL options: (see the Bitcoin Wiki for SSL setup instructions)
.HP
\fB\-rpcssl\fR
.IP
Use OpenSSL (https) for JSON\-RPC connections
.SH COPYRIGHT
Copyright (C) 2009-2017 The Bitcoin Core Developers
Copyright (C) 2015-2017 The Zcash Developers
Expand Down
19 changes: 0 additions & 19 deletions doc/man/zcashd.1
Original file line number Diff line number Diff line change
Expand Up @@ -422,25 +422,6 @@ multiple times
.IP
Set the number of threads to service RPC calls (default: 4)
.PP
RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)
.HP
\fB\-rpcssl\fR
.IP
Use OpenSSL (https) for JSON\-RPC connections
.HP
\fB\-rpcsslcertificatechainfile=\fR<file.cert>
.IP
Server certificate file (default: server.cert)
.HP
\fB\-rpcsslprivatekeyfile=\fR<file.pem>
.IP
Server private key (default: server.pem)
.HP
\fB\-rpcsslciphers=\fR<ciphers>
.IP
Acceptable ciphers (default:
TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH)
.PP
Metrics Options (only if \fB\-daemon\fR and \fB\-printtoconsole\fR are not set):
.HP
\fB\-showmetrics\fR
Expand Down
26 changes: 15 additions & 11 deletions qa/rpc-tests/httpbasics.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

class HTTPBasicsTest (BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir, extra_args=[['-rpckeepalive=1'], ['-rpckeepalive=0'], [], []])
return start_nodes(4, self.options.tmpdir)

def run_test(self):

Expand All @@ -38,9 +38,13 @@ def run_test(self):
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!

# TODO #1856: Re-enable support for persistent connections.
assert_equal(conn.sock!=None, False)
#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
Expand All @@ -51,9 +55,13 @@ def run_test(self):
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!

# TODO #1856: Re-enable support for persistent connections.
assert_equal(conn.sock!=None, False)
#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"
Expand All @@ -76,9 +84,8 @@ def run_test(self):
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
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is on
urlNode2 = urlparse.urlparse(self.nodes[2].url)
authpair = urlNode2.username + ':' + urlNode2.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
Expand All @@ -88,10 +95,7 @@ def run_test(self):
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)

# TODO #1856: Re-enable support for persistent connections.
assert_equal(conn.sock!=None, False)
conn.close()
assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default

if __name__ == '__main__':
HTTPBasicsTest ().main ()
42 changes: 26 additions & 16 deletions qa/rpc-tests/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,20 @@ def deser_uint256(f):
r += t << (i * 32)
return r

#allows simple http get calls with a request body
def http_get_call(host, port, path, requestdata = '', response_object = 0):
#allows simple http get calls
def http_get_call(host, port, path, response_object = 0):
conn = httplib.HTTPConnection(host, port)
conn.request('GET', path, requestdata)
conn.request('GET', path)

if response_object:
return conn.getresponse()

return conn.getresponse().read()

#allows simple http post calls with a request body
def http_post_call(host, port, path, requestdata = '', response_object = 0):
conn = httplib.HTTPConnection(host, port)
conn.request('POST', path, requestdata)

if response_object:
return conn.getresponse()
Expand Down Expand Up @@ -137,7 +147,7 @@ def run_test(self):
binaryRequest += binascii.unhexlify(vintx);
binaryRequest += pack("i", 0);

bin_response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest)
bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest)
output = StringIO.StringIO()
output.write(bin_response)
output.seek(0)
Expand Down Expand Up @@ -175,29 +185,29 @@ def run_test(self):

#do some invalid requests
json_request = '{"checkmempool'
response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True)
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True)
assert_equal(response.status, 500) #must be a 500 because we send a invalid json request

json_request = '{"checkmempool'
response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', json_request, True)
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', json_request, True)
assert_equal(response.status, 500) #must be a 500 because we send a invalid bin request

response = http_get_call(url.hostname, url.port, '/rest/getutxos/checkmempool'+self.FORMAT_SEPARATOR+'bin', '', True)
response = http_post_call(url.hostname, url.port, '/rest/getutxos/checkmempool'+self.FORMAT_SEPARATOR+'bin', '', True)
assert_equal(response.status, 500) #must be a 500 because we send a invalid bin request

#test limits
json_request = '/checkmempool/'
for x in range(0, 20):
json_request += txid+'-'+str(n)+'/'
json_request = json_request.rstrip("/")
response = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
assert_equal(response.status, 500) #must be a 500 because we exceeding the limits

json_request = '/checkmempool/'
for x in range(0, 15):
json_request += txid+'-'+str(n)+'/'
json_request = json_request.rstrip("/");
response = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
assert_equal(response.status, 200) #must be a 500 because we exceeding the limits

self.nodes[0].generate(1) #generate block to not affect upcoming tests
Expand All @@ -217,27 +227,27 @@ def run_test(self):
# this is 32 9-bit indices

# check binary format
response = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"bin", "", True)
response = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"bin", True)
assert_equal(response.status, 200)
assert_greater_than(int(response.getheader('content-length')), 177)
response_str = response.read()

# compare with block header
response_header = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"bin", "", True)
response_header = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"bin", True)
assert_equal(response_header.status, 200)
assert_equal(int(response_header.getheader('content-length')), 177)
response_header_str = response_header.read()
assert_equal(response_str[0:177], response_header_str)

# check block hex format
response_hex = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"hex", "", True)
response_hex = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"hex", True)
assert_equal(response_hex.status, 200)
assert_greater_than(int(response_hex.getheader('content-length')), 354)
response_hex_str = response_hex.read()
assert_equal(response_str.encode("hex")[0:354], response_hex_str[0:354])

# compare with hex block header
response_header_hex = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"hex", "", True)
response_header_hex = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"hex", True)
assert_equal(response_header_hex.status, 200)
assert_greater_than(int(response_header_hex.getheader('content-length')), 354)
response_header_hex_str = response_header_hex.read()
Expand All @@ -250,7 +260,7 @@ def run_test(self):
assert_equal(block_json_obj['hash'], bb_hash)

# compare with json block header
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", "", True)
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", True)
assert_equal(response_header_json.status, 200)
response_header_json_str = response_header_json.read()
json_obj = json.loads(response_header_json_str, parse_float=decimal.Decimal)
Expand All @@ -274,7 +284,7 @@ def run_test(self):
#see if we can get 5 headers in one response
self.nodes[1].generate(5)
self.sync_all()
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/5/'+bb_hash+self.FORMAT_SEPARATOR+"json", "", True)
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/5/'+bb_hash+self.FORMAT_SEPARATOR+"json", True)
assert_equal(response_header_json.status, 200)
response_header_json_str = response_header_json.read()
json_obj = json.loads(response_header_json_str)
Expand All @@ -287,7 +297,7 @@ def run_test(self):
assert_equal(json_obj['txid'], tx_hash)

# check hex format response
hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", "", True)
hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", True)
assert_equal(hex_string.status, 200)
assert_greater_than(int(response.getheader('content-length')), 10)

Expand Down
42 changes: 28 additions & 14 deletions qa/rpc-tests/test_framework/authproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,32 @@ def __getattr__(self, name):
name = "%s.%s" % (self.__service_name, name)
return AuthServiceProxy(self.__service_url, name, connection=self.__conn)

def _request(self, method, path, postdata):
'''
Do a HTTP request, with retry if we get disconnected (e.g. due to a timeout).
This is a workaround for https://bugs.python.org/issue3566 which is fixed in Python 3.5.
'''
headers = {'Host': self.__url.hostname,
'User-Agent': USER_AGENT,
'Authorization': self.__auth_header,
'Content-type': 'application/json'}
try:
self.__conn.request(method, path, postdata, headers)
return self._get_response()
except httplib.BadStatusLine as e:
if e.line == "''": # if connection was closed, try again
self.__conn.close()
self.__conn.request(method, path, postdata, headers)
return self._get_response()
else:
raise
except (BrokenPipeError,ConnectionResetError):
# Python 3.5+ raises BrokenPipeError instead of BadStatusLine when the connection was reset
# ConnectionResetError happens on FreeBSD with Python 3.4
self.__conn.close()
self.__conn.request(method, path, postdata, headers)
return self._get_response()

def __call__(self, *args):
AuthServiceProxy.__id_count += 1

Expand All @@ -115,13 +141,7 @@ def __call__(self, *args):
'method': self.__service_name,
'params': args,
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal)
self.__conn.request('POST', self.__url.path, postdata,
{'Host': self.__url.hostname,
'User-Agent': USER_AGENT,
'Authorization': self.__auth_header,
'Content-type': 'application/json'})

response = self._get_response()
response = self._request('POST', self.__url.path, postdata)
if response['error'] is not None:
raise JSONRPCException(response['error'])
elif 'result' not in response:
Expand All @@ -133,13 +153,7 @@ def __call__(self, *args):
def _batch(self, rpc_call_list):
postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal)
log.debug("--> "+postdata)
self.__conn.request('POST', self.__url.path, postdata,
{'Host': self.__url.hostname,
'User-Agent': USER_AGENT,
'Authorization': self.__auth_header,
'Content-type': 'application/json'})

return self._get_response()
return self._request('POST', self.__url.path, postdata)

def _get_response(self):
http_response = self.__conn.getresponse()
Expand Down
Loading

0 comments on commit f9f4866

Please sign in to comment.