From 22b644f47ee2de8a962d00588579076e7a55455a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 22 Mar 2019 14:35:23 +0000 Subject: functional_tests: move RPC API to utils, it is not test specific --- utils/python-rpc/framework/daemon.py | 198 +++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 utils/python-rpc/framework/daemon.py (limited to 'utils/python-rpc/framework/daemon.py') diff --git a/utils/python-rpc/framework/daemon.py b/utils/python-rpc/framework/daemon.py new file mode 100644 index 000000000..11d5f5845 --- /dev/null +++ b/utils/python-rpc/framework/daemon.py @@ -0,0 +1,198 @@ +# Copyright (c) 2018 The Monero Project +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other +# materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be +# used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Daemon class to make rpc calls and store state.""" + +from .rpc import JSONRPC + +class Daemon(object): + + def __init__(self, protocol='http', host='127.0.0.1', port=0, idx=0): + self.rpc = JSONRPC('{protocol}://{host}:{port}'.format(protocol=protocol, host=host, port=port if port else 18180+idx)) + + def getblocktemplate(self, address): + getblocktemplate = { + 'method': 'getblocktemplate', + 'params': { + 'wallet_address': address, + 'reserve_size' : 1 + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(getblocktemplate) + + def send_raw_transaction(self, tx_as_hex, do_not_relay = False): + send_raw_transaction = { + 'tx_as_hex': tx_as_hex, + 'do_not_relay': do_not_relay, + } + return self.rpc.send_request("/send_raw_transaction", send_raw_transaction) + + def submitblock(self, block): + submitblock = { + 'method': 'submitblock', + 'params': [ block ], + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(submitblock) + + def getblock(self, height=0): + getblock = { + 'method': 'getblock', + 'params': { + 'height': height + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(getblock) + + def getlastblockheader(self): + getlastblockheader = { + 'method': 'getlastblockheader', + 'params': { + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(getlastblockheader) + + def getblockheaderbyhash(self, hash): + getblockheaderbyhash = { + 'method': 'getblockheaderbyhash', + 'params': { + 'hash': hash, + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(getblockheaderbyhash) + + def getblockheaderbyheight(self, height): + getblockheaderbyheight = { + 'method': 'getblockheaderbyheight', + 'params': { + 'height': height, + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(getblockheaderbyheight) + + def get_connections(self): + get_connections = { + 'method': 'get_connections', + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(get_connections) + + def get_info(self): + get_info = { + 'method': 'get_info', + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(get_info) + + def hard_fork_info(self): + hard_fork_info = { + 'method': 'hard_fork_info', + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(hard_fork_info) + + def generateblocks(self, address, blocks=1): + generateblocks = { + 'method': 'generateblocks', + 'params': { + 'amount_of_blocks' : blocks, + 'reserve_size' : 20, + 'wallet_address': address + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(generateblocks) + + def get_height(self): + get_height = { + 'method': 'get_height', + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_request("/get_height", get_height) + + def pop_blocks(self, nblocks = 1): + pop_blocks = { + 'nblocks' : nblocks, + } + return self.rpc.send_request("/pop_blocks", pop_blocks) + + def start_mining(self, miner_address, threads_count = 0, do_background_mining = False, ignore_battery = False): + start_mining = { + 'miner_address' : miner_address, + 'threads_count' : threads_count, + 'do_background_mining' : do_background_mining, + 'ignore_battery' : ignore_battery, + } + return self.rpc.send_request('/start_mining', start_mining) + + def stop_mining(self): + stop_mining = { + } + return self.rpc.send_request('/stop_mining', stop_mining) + + def mining_status(self): + mining_status = { + } + return self.rpc.send_request('/mining_status', mining_status) + + def get_transaction_pool(self): + get_transaction_pool = { + } + return self.rpc.send_request('/get_transaction_pool', get_transaction_pool) + + def get_transaction_pool_hashes(self): + get_transaction_pool_hashes = { + } + return self.rpc.send_request('/get_transaction_pool_hashes', get_transaction_pool_hashes) + + def flush_txpool(self, txids = []): + flush_txpool = { + 'method': 'flush_txpool', + 'params': { + 'txids': txids + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(flush_txpool) -- cgit v1.2.3 From c7bfdc356618fd1ccbe0f87fd5009e944cd12e50 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 22 Mar 2019 15:25:33 +0000 Subject: python-rpc: add console.py It allows one to connect to a running daemon or wallet, and use its RPC API from python. Usage: python -i console.py It will detect whether it's talking to a daemon or wallet and initialize itself accordingly. --- tests/functional_tests/functional_tests_rpc.py | 2 +- utils/python-rpc/console.py | 49 ++++++++++++++++++++++++++ utils/python-rpc/framework/daemon.py | 8 +++++ utils/python-rpc/framework/wallet.py | 8 +++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100755 utils/python-rpc/console.py (limited to 'utils/python-rpc/framework/daemon.py') diff --git a/tests/functional_tests/functional_tests_rpc.py b/tests/functional_tests/functional_tests_rpc.py index 606b19e45..f2fef7e95 100755 --- a/tests/functional_tests/functional_tests_rpc.py +++ b/tests/functional_tests/functional_tests_rpc.py @@ -60,7 +60,7 @@ try: PYTHONPATH = os.environ['PYTHONPATH'] if 'PYTHONPATH' in os.environ else '' if len(PYTHONPATH) > 0: PYTHONPATH += ':' - PYTHONPATH += '../../utils/python-rpc' + PYTHONPATH += srcdir + '/../../utils/python-rpc' os.environ['PYTHONPATH'] = PYTHONPATH for i in range(len(command_lines)): #print('Running: ' + str(command_lines[i])) diff --git a/utils/python-rpc/console.py b/utils/python-rpc/console.py new file mode 100755 index 000000000..ab0d9f27f --- /dev/null +++ b/utils/python-rpc/console.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +from __future__ import print_function +import sys +import subprocess +import socket +from framework import rpc +from framework import wallet +from framework import daemon + +USAGE = 'usage: python -i console.py ' +try: + port = int(sys.argv[1]) +except: + print(USAGE) + sys.exit(1) + +# check for open port +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.settimeout(1) +if s.connect_ex(('127.0.0.1', port)) != 0: + print('No wallet or daemon RPC on port ' + str(port)) + sys.exit(1) +s.close() + +# both wallet and daemon have a get_version JSON RPC +rpc = rpc.JSONRPC('{protocol}://{host}:{port}'.format(protocol='http', host='127.0.0.1', port=port)) +get_version = { + 'method': 'get_version', + 'jsonrpc': '2.0', + 'id': '0' +} +try: + res = rpc.send_json_rpc_request(get_version) +except Exception, e: + print('Failed to call version RPC: ' + str(e)) + sys.exit(1) + +if 'version' not in res: + print('Server is not a monero process') + sys.exit(1) + +if 'status' in res: + rpc = daemon.Daemon(port=port) +else: + rpc = wallet.Wallet(port=port) + +print('Connected to %s RPC on port %u' % ('daemon' if 'status' in res else 'wallet', port)) +print('The \'rpc\' object may now be used to use the API') diff --git a/utils/python-rpc/framework/daemon.py b/utils/python-rpc/framework/daemon.py index 11d5f5845..83c8eea67 100644 --- a/utils/python-rpc/framework/daemon.py +++ b/utils/python-rpc/framework/daemon.py @@ -196,3 +196,11 @@ class Daemon(object): 'id': '0' } return self.rpc.send_json_rpc_request(flush_txpool) + + def get_version(self): + get_version = { + 'method': 'get_version', + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(get_version) diff --git a/utils/python-rpc/framework/wallet.py b/utils/python-rpc/framework/wallet.py index e9f13667b..ea683b8c5 100644 --- a/utils/python-rpc/framework/wallet.py +++ b/utils/python-rpc/framework/wallet.py @@ -590,3 +590,11 @@ class Wallet(object): 'id': '0' } return self.rpc.send_json_rpc_request(verify) + + def get_version(self): + get_version = { + 'method': 'get_version', + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(get_version) -- cgit v1.2.3 From 32973434bd6aaba159b2bd805c3fc24fad7deb52 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 22 Mar 2019 16:25:07 +0000 Subject: python-rpc: add getblockheadersrange daemon RPC --- utils/python-rpc/framework/daemon.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'utils/python-rpc/framework/daemon.py') diff --git a/utils/python-rpc/framework/daemon.py b/utils/python-rpc/framework/daemon.py index 83c8eea67..f60fe62db 100644 --- a/utils/python-rpc/framework/daemon.py +++ b/utils/python-rpc/framework/daemon.py @@ -106,6 +106,19 @@ class Daemon(object): } return self.rpc.send_json_rpc_request(getblockheaderbyheight) + def getblockheadersrange(self, start_height, end_height, fill_pow_hash = False): + getblockheadersrange = { + 'method': 'getblockheadersrange', + 'params': { + 'start_height': start_height, + 'end_height': end_height, + 'fill_pow_hash': fill_pow_hash, + }, + 'jsonrpc': '2.0', + 'id': '0' + } + return self.rpc.send_json_rpc_request(getblockheadersrange) + def get_connections(self): get_connections = { 'method': 'get_connections', -- cgit v1.2.3