Skip to content

Commit

Permalink
Fee rewards and P2PKH addr for guardnodes in Report script
Browse files Browse the repository at this point in the history
(Resolves #19)
  • Loading branch information
nkostoulas committed Jun 10, 2019
1 parent 52a5f14 commit 6cfb29f
Show file tree
Hide file tree
Showing 3 changed files with 280 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/target
**/*.rs.bk

# for python scripts
scripts/__pycache__/
190 changes: 190 additions & 0 deletions scripts/authproxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
"""
Copyright (c) 2011 Jeff Garzik
AuthServiceProxy has the following improvements over python-jsonrpc's
ServiceProxy class:
- HTTP connections persist for the life of the AuthServiceProxy object
(if server supports HTTP/1.1)
- sends protocol 'version', per JSON-RPC 1.1
- sends proper, incrementing 'id'
- sends Basic HTTP authentication headers
- parses all JSON numbers that look like floats as Decimal
- uses standard Python json lib
Previous copyright, from python-jsonrpc/jsonrpc/proxy.py:
Copyright (c) 2007 Jan-Klaas Kollhof
This file is part of jsonrpc.
jsonrpc is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this software; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""

try:
import http.client as httplib
except ImportError:
import httplib
import base64
import decimal
import json
import logging
import socket
try:
import urllib.parse as urlparse
except ImportError:
import urlparse

USER_AGENT = "AuthServiceProxy/0.1"

HTTP_TIMEOUT = 30

log = logging.getLogger("BitcoinRPC")

class JSONRPCException(Exception):
def __init__(self, rpc_error):
try:
errmsg = '%(message)s (%(code)i)' % rpc_error
except (KeyError, TypeError):
errmsg = ''
Exception.__init__(self, errmsg)
self.error = rpc_error


def EncodeDecimal(o):
if isinstance(o, decimal.Decimal):
return str(o)
raise TypeError(repr(o) + " is not JSON serializable")

class AuthServiceProxy(object):
__id_count = 0

# ensure_ascii: escape unicode as \uXXXX, passed to json.dumps
def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None, ensure_ascii=True):
self.__service_url = service_url
self._service_name = service_name
self.ensure_ascii = ensure_ascii # can be toggled on the fly by tests
self.__url = urlparse.urlparse(service_url)
if self.__url.port is None:
port = 80
else:
port = self.__url.port
(user, passwd) = (self.__url.username, self.__url.password)
try:
user = user.encode('utf8')
except AttributeError:
pass
try:
passwd = passwd.encode('utf8')
except AttributeError:
pass
authpair = user + b':' + passwd
self.__auth_header = b'Basic ' + base64.b64encode(authpair)

if connection:
# Callables re-use the connection of the original proxy
self.__conn = connection
elif self.__url.scheme == 'https':
self.__conn = httplib.HTTPSConnection(self.__url.hostname, port,
timeout=timeout)
else:
self.__conn = httplib.HTTPConnection(self.__url.hostname, port,
timeout=timeout)

def __getattr__(self, name):
if name.startswith('__') and name.endswith('__'):
# Python internal stuff
raise AttributeError
if self._service_name is not None:
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, **argsn):
AuthServiceProxy.__id_count += 1

log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self._service_name,
json.dumps(args, default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
if args and argsn:
raise ValueError('Cannot handle both named and positional arguments')
postdata = json.dumps({'version': '1.1',
'method': self._service_name,
'params': args or argsn,
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
response = self._request('POST', self.__url.path, postdata.encode('utf-8'))
if response['error'] is not None:
raise JSONRPCException(response['error'])
elif 'result' not in response:
raise JSONRPCException({
'code': -343, 'message': 'missing JSON-RPC result'})
else:
return response['result']

def _batch(self, rpc_call_list):
postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
log.debug("--> "+postdata)
return self._request('POST', self.__url.path, postdata.encode('utf-8'))

def _get_response(self):
try:
http_response = self.__conn.getresponse()
except socket.timeout as e:
raise JSONRPCException({
'code': -344,
'message': '%r RPC took longer than %f seconds. Consider '
'using larger timeout for calls that take '
'longer to return.' % (self._service_name,
self.__conn.timeout)})
if http_response is None:
raise JSONRPCException({
'code': -342, 'message': 'missing HTTP response from server'})

content_type = http_response.getheader('Content-Type')
if content_type != 'application/json':
raise JSONRPCException({
'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)})

responsedata = http_response.read().decode('utf8')
response = json.loads(responsedata, parse_float=decimal.Decimal)
if "error" in response and response["error"] is None:
log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
else:
log.debug("<-- "+responsedata)
return response
88 changes: 87 additions & 1 deletion scripts/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,81 @@
import requests
import json

############# PORTED FROM BITCOIN TEST-FRAMEWORK ##################
import authproxy
import hashlib
from binascii import hexlify, unhexlify

def connect(user, password, host, port):
return authproxy.AuthServiceProxy("http://%s:%s@%s:%s"%
(user, password, host, port))

def hash160(s):
return hashlib.new('ripemd160', sha256(s)).digest()

def sha256(s):
return hashlib.new('sha256', s).digest()

def hash256(byte_str):
sha256 = hashlib.sha256()
sha256.update(byte_str)
sha256d = hashlib.sha256()
sha256d.update(sha256.digest())
return sha256d.digest()[::-1]

def bytes_to_hex_str(byte_str):
return hexlify(byte_str).decode('ascii')

def hex_str_to_bytes(hex_str):
return unhexlify(hex_str.encode('ascii'))

chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def byte_to_base58(b, version):
result = ''
str = bytes_to_hex_str(b)
str = bytes_to_hex_str(chr(version).encode('latin-1')) + str
checksum = bytes_to_hex_str(hash256(hex_str_to_bytes(str)))
str += checksum[:8]
value = int('0x'+str,0)
while value > 0:
result = chars[value % 58] + result
value //= 58
while (str[:2] == '00'):
result = chars[0] + result
str = str[2:]
return result

def check_key(key):
if (type(key) is str):
key = hex_str_to_bytes(key) # Assuming this is hex string
if (type(key) is bytes and (len(key) == 33 or len(key) == 65)):
return key
assert(False)

def key_to_p2pkh(key, version):
key = check_key(key)
return byte_to_base58(hash160(key), version)
###################################################################

# Calculate fees from starting to ending height or
# print an error if connectivity to ocean client fails
def calculate_fees(rpc, start_height, end_height):
fee = 0
try:
for i in range(start_height, end_height + 1):
block = rpc.getblock(rpc.getblockhash(i))
coinbase_tx = rpc.getrawtransaction(block['tx'][0], True)
for out in coinbase_tx['vout']:
fee += out['value']
except Exception as e:
print("ERROR with rpc connectivity: {0}".format(e))
return fee

addr_prefix = 235
txid = "e5990b1d3bde028f40281df5f84d50272e74ca8f13d810d317b2022940423d15"
url = 'https://userApi:[email protected]:10006'
rpc = connect("ocean", "oceanpass", "localhost", "7043")

payload = '{{"jsonrpc": "2.0", "method": "getrequest", "params": {{"txid": "{}"}}, "id": 1}}'.format(txid)
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
Expand All @@ -16,11 +89,22 @@
print("Request details:\n{}".format(request))
print("")

print("Calculating total fees...")
fee = calculate_fees(rpc, request['start_blockheight'], request['end_blockheight'])
fee_percentage = request['fee_percentage']
fee_out = fee*fee_percentage/100
print("Fee: {0}".format(fee))
print("Paying out ({0}%): {1}".format(fee_percentage, fee_out))
print("")

print("Bids")
bids = {}
for bid in result["bids"]:
bids[bid['txid']] = bid['pubkey']
print(bid)
fee_per_guard = 0.0
if len(bids) > 0:
fee_per_guard = float(fee_out/len(bids))
print("")

payload = '{{"jsonrpc": "2.0", "method": "getrequestresponses", "params": {{"txid": "{}"}}, "id": 1}}'.format(txid)
Expand All @@ -44,4 +128,6 @@
performance = 0.0
if bid in resps:
performance = resps[bid]
print("bid: {0}\tpubkey: {1}\t performance: {2:.2f}%".format(bid, key, 100*performance))
print("Bid {0}\npubkey: {1}\naddress: {2}\nperformance: {3:.2f}%\nreward: {4}\n".\
format(bid, key, key_to_p2pkh(key, addr_prefix), 100*performance, fee_per_guard*performance))
print("End")

0 comments on commit 6cfb29f

Please sign in to comment.