Add transaction broadcasting

This commit is contained in:
Michał Sałaban 2018-01-15 04:12:53 +01:00
parent 900bcdc2ed
commit f8bb84c458
5 changed files with 83 additions and 3 deletions

View File

@ -17,7 +17,7 @@ _log = logging.getLogger(__name__)
class JSONRPCDaemon(object):
def __init__(self, protocol='http', host='127.0.0.1', port=18081, path='/json_rpc'):
self.url = '{protocol}://{host}:{port}/json_rpc'.format(
self.url = '{protocol}://{host}:{port}'.format(
protocol=protocol,
host=host,
port=port)
@ -27,13 +27,37 @@ class JSONRPCDaemon(object):
info = self.raw_jsonrpc_request('get_info')
return info
def send_transaction(self, blob):
res = self.raw_request('/sendrawtransaction', {'tx_as_hex': blob})
if res['status'] == 'OK':
return res
raise exceptions.TransactionBroadcastError(
"{status}: {reason}".format(**res),
details=res)
def raw_request(self, path, data):
hdr = {'Content-Type': 'application/json'}
_log.debug(u"Request: {path}\nData: {data}".format(
path=path,
data=pprint.pformat(data)))
rsp = requests.post(self.url + path, headers=hdr, data=json.dumps(data))
if rsp.status_code != 200:
raise RPCError("Invalid HTTP status {code} for path {path}.".format(
code=rsp.status_code,
path=path))
result = rsp.json()
_ppresult = pprint.pformat(result)
_log.debug(u"Result:\n{result}".format(result=_ppresult))
return result
def raw_jsonrpc_request(self, method, params=None):
hdr = {'Content-Type': 'application/json'}
data = {'jsonrpc': '2.0', 'id': 0, 'method': method, 'params': params or {}}
_log.debug(u"Method: {method}\nParams:\n{params}".format(
method=method,
params=pprint.pformat(params)))
rsp = requests.post(self.url, headers=hdr, data=json.dumps(data))
rsp = requests.post(self.url + '/json_rpc', headers=hdr, data=json.dumps(data))
if rsp.status_code != 200:
raise RPCError("Invalid HTTP status {code} for method {method}.".format(
code=rsp.status_code,

View File

@ -4,3 +4,6 @@ class Daemon(object):
def get_info(self):
return self._backend.get_info()
def send_transaction(self, blob):
return self._backend.send_transaction(blob)

View File

@ -24,3 +24,9 @@ class AmountIsZero(AccountException):
class TransactionNotPossible(AccountException):
pass
class TransactionBroadcastError(BackendException):
def __init__(self, message, details=None):
self.details = details
super(TransactionBroadcastError, self).__init__(message)

47
utils/pushtx.py Normal file
View File

@ -0,0 +1,47 @@
import argparse
import logging
import operator
import re
import sys
from monero.backends.jsonrpc import JSONRPCDaemon
from monero import Daemon
from monero import exceptions
def url_data(url):
gs = re.compile(
r'^(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$'
).match(url).groupdict()
return dict(filter(operator.itemgetter(1), gs.items()))
argsparser = argparse.ArgumentParser(description="Push transaction to network")
argsparser.add_argument('daemon_rpc_url', nargs='?', type=url_data, default='127.0.0.1:18081',
help="Daemon RPC URL [host[:port]]")
argsparser.add_argument('-v', dest='verbosity', action='count', default=0,
help="Verbosity (repeat to increase; -v for INFO, -vv for DEBUG")
argsparser.add_argument('-i', dest='tx_filenames', nargs='+', default=None,
help="Files with transaction data. Will read from stdin if not given.")
args = argsparser.parse_args()
level = logging.WARNING
if args.verbosity == 1:
level = logging.INFO
elif args.verbosity > 1:
level = logging.DEBUG
logging.basicConfig(level=level, format="%(asctime)-15s %(message)s")
if args.tx_filenames:
blobs = [(f, open(f, 'r').read()) for f in args.tx_filenames]
else:
blobs = [('transaction', sys.stdin.read())]
d = Daemon(JSONRPCDaemon(**args.daemon_rpc_url))
for name, blob in blobs:
logging.debug("Sending {}".format(name))
try:
res = d.send_transaction(blob)
except exceptions.TransactionBroadcastError as e:
print("{} not sent, reason: {}".format(name, e.details['reason']))
logging.debug(e.details)
continue
if res['not_relayed']:
print("{} not relayed".format(name))
else:
print("{} successfully sent".format(name))

View File

@ -62,6 +62,6 @@ for tx in txfrs:
if args.outdir:
outname = os.path.join(args.outdir, tx.hash + '.tx')
outfile = open(outname, 'wb')
outfile.write(tx.blob)
outfile.write(tx.blob.encode())
outfile.close()
print(u"Transaction saved to {}".format(outname))