From 0b79234f4896f389beb63c5d44468f76b07a5f9b Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 28 May 2022 19:41:43 +0000 Subject: [PATCH] rpc.py: improve host_path implementation --- mmgen/base_proto/bitcoin/rpc.py | 15 ++++++++------- mmgen/base_proto/ethereum/rpc.py | 3 +++ mmgen/base_proto/monero/rpc.py | 10 ++-------- mmgen/rpc.py | 32 +++++++++++++------------------- test/unit_tests_d/ut_rpc.py | 25 ++++++++++++++++++++++++- 5 files changed, 50 insertions(+), 35 deletions(-) diff --git a/mmgen/base_proto/bitcoin/rpc.py b/mmgen/base_proto/bitcoin/rpc.py index 00292fe8..a7d9caf4 100755 --- a/mmgen/base_proto/bitcoin/rpc.py +++ b/mmgen/base_proto/bitcoin/rpc.py @@ -77,6 +77,7 @@ class BitcoinRPCClient(RPCClient,metaclass=AsyncInit): auth_type = 'basic' has_auth_cookie = True + wallet_path = '/' async def __init__(self,proto,daemon,backend): @@ -150,6 +151,13 @@ class BitcoinRPCClient(RPCClient,metaclass=AsyncInit): if not self.chain == 'regtest': await self.check_tracking_wallet() + # for regtest, wallet path must remain '/' until Carol’s user wallet has been created + if g.regtest_user: + self.wallet_path = f'/wallet/{g.regtest_user}' + + def make_host_path(self,wallet): + return f'/wallet/{wallet}' if wallet else self.wallet_path + async def check_tracking_wallet(self,wallet_checked=[]): if not wallet_checked: wallets = await self.call('listwallets') @@ -196,13 +204,6 @@ class BitcoinRPCClient(RPCClient,metaclass=AsyncInit): fn = self.get_daemon_auth_cookie_fn() return get_lines_from_file(fn,'cookie',quiet=True)[0] if os.access(fn,os.R_OK) else '' - @staticmethod - def make_host_path(wallet): - return ( - '/wallet/{}'.format('bob' if g.bob else 'alice') if (g.bob or g.alice) else - '/wallet/{}'.format(wallet) if wallet else '/' - ) - def info(self,info_id): def segwit_is_active(): diff --git a/mmgen/base_proto/ethereum/rpc.py b/mmgen/base_proto/ethereum/rpc.py index 4ccaa63a..80087bd9 100755 --- a/mmgen/base_proto/ethereum/rpc.py +++ b/mmgen/base_proto/ethereum/rpc.py @@ -80,6 +80,9 @@ class EthereumRPCClient(RPCClient,metaclass=AsyncInit): self.chainID = Int(ci,16) self.chain = self.proto.chain_ids[self.chainID] + def make_host_path(self,wallet): + return '' + rpcmethods = ( 'eth_blockNumber', 'eth_call', diff --git a/mmgen/base_proto/monero/rpc.py b/mmgen/base_proto/monero/rpc.py index 296a97b4..818ecf66 100755 --- a/mmgen/base_proto/monero/rpc.py +++ b/mmgen/base_proto/monero/rpc.py @@ -18,7 +18,6 @@ class MoneroRPCClient(RPCClient): auth_type = None network_proto = 'https' - host_path = '/json_rpc' verify_server = False def __init__(self,host,port,user,passwd,test_connection=True,proxy=None,daemon=None): @@ -49,7 +48,7 @@ class MoneroRPCClient(RPCClient): return await self.process_http_resp(self.backend.run( payload = {'id': 0, 'jsonrpc': '2.0', 'method': method, 'params': kwargs }, timeout = 3600, # allow enough time to sync ≈1,000,000 blocks - wallet = None + host_path = '/json_rpc' )) rpcmethods = ( 'get_info', ) @@ -57,20 +56,15 @@ class MoneroRPCClient(RPCClient): class MoneroRPCClientRaw(MoneroRPCClient): json_rpc = False - host_path = '/' async def call(self,method,*params,**kwargs): assert params == (), f'{type(self).__name__}.call() accepts keyword arguments only' return await self.process_http_resp(self.backend.run( payload = kwargs, timeout = self.timeout, - wallet = method + host_path = f'/{method}' )) - @staticmethod - def make_host_path(arg): - return arg - async def do_stop_daemon(self,silent=False): return await self.call('stop_daemon') diff --git a/mmgen/rpc.py b/mmgen/rpc.py index 4c4f86a0..1e39f661 100755 --- a/mmgen/rpc.py +++ b/mmgen/rpc.py @@ -102,10 +102,9 @@ class RPCBackends: self.host = caller.host self.port = caller.port self.proxy = caller.proxy - self.url = caller.url + self.host_url = caller.host_url self.timeout = caller.timeout self.http_hdrs = caller.http_hdrs - self.make_host_path = caller.make_host_path self.name = type(self).__name__ class aiohttp(base): @@ -124,10 +123,10 @@ class RPCBackends: else: self.auth = None - async def run(self,payload,timeout,wallet): + async def run(self,payload,timeout,host_path): dmsg_rpc('\n RPC PAYLOAD data (aiohttp) ==>\n{}\n',payload) async with self.session.post( - url = self.url + self.make_host_path(wallet), + url = self.host_url + host_path, auth = self.auth, data = json.dumps(payload,cls=json_encoder), timeout = timeout or self.timeout, @@ -155,10 +154,10 @@ class RPCBackends: 'https': f'socks5h://{self.proxy}' }) - async def run(self,payload,timeout,wallet): + async def run(self,payload,timeout,host_path): dmsg_rpc('\n RPC PAYLOAD data (requests) ==>\n{}\n',payload) res = self.session.post( - url = self.url + self.make_host_path(wallet), + url = self.host_url + host_path, data = json.dumps(payload,cls=json_encoder), timeout = timeout or self.timeout, verify = False ) @@ -184,7 +183,7 @@ class RPCBackends: '', auth_str_b64 )) - async def run(self,payload,timeout,wallet): + async def run(self,payload,timeout,host_path): dmsg_rpc('\n RPC PAYLOAD data (httplib) ==>\n{}\n',payload) if timeout: @@ -196,7 +195,7 @@ class RPCBackends: try: s.request( method = 'POST', - url = self.make_host_path(wallet), + url = host_path, body = json.dumps(payload,cls=json_encoder), headers = self.http_hdrs ) r = s.getresponse() # => http.client.HTTPResponse instance @@ -234,7 +233,7 @@ class RPCBackends: self.exec_opts = list(gen_opts()) + ['--silent'] self.arg_max = 8192 # set way below system ARG_MAX, just to be safe - async def run(self,payload,timeout,wallet): + async def run(self,payload,timeout,host_path): data = json.dumps(payload,cls=json_encoder) if len(data) > self.arg_max: return self.httplib(payload,timeout=timeout) @@ -245,7 +244,7 @@ class RPCBackends: '--connect-timeout', str(timeout or self.timeout), '--write-out', '%{http_code}', '--data-binary', data - ] + self.exec_opts + [self.url + self.make_host_path(wallet)] + ] + self.exec_opts + [self.host_url + host_path] dmsg_rpc(' RPC curl exec data ==>\n{}\n',exec_cmd) @@ -262,7 +261,6 @@ class RPCClient(MMGenObject): auth_type = None has_auth_cookie = False network_proto = 'http' - host_path = '' proxy = None def __init__(self,host,port,test_connection=True): @@ -282,16 +280,12 @@ class RPCClient(MMGenObject): die( 'SocketError', f'Unable to connect to {host}:{port}' ) self.http_hdrs = { 'Content-Type': 'application/json' } - self.url = f'{self.network_proto}://{host}:{port}{self.host_path}' + self.host_url = f'{self.network_proto}://{host}:{port}' self.host = host self.port = port self.timeout = g.http_timeout self.auth = None - @staticmethod - def make_host_path(foo): - return '' - def set_backend(self,backend=None): bn = backend or opt.rpc_backend if bn == 'auto': @@ -336,7 +330,7 @@ class RPCClient(MMGenObject): return await self.process_http_resp(self.backend.run( payload = {'id': 1, 'jsonrpc': '2.0', 'method': method, 'params': params }, timeout = timeout, - wallet = wallet + host_path = self.make_host_path(wallet) )) async def batch_call(self,method,param_list,timeout=None,wallet=None): @@ -351,7 +345,7 @@ class RPCClient(MMGenObject): 'method': method, 'params': params } for n,params in enumerate(param_list,1) ], timeout = timeout, - wallet = wallet + host_path = self.make_host_path(wallet) ),batch=True) async def gathered_call(self,method,args_list,timeout=None,wallet=None): @@ -371,7 +365,7 @@ class RPCClient(MMGenObject): tasks = [self.process_http_resp(self.backend.run( payload = {'id': n, 'jsonrpc': '2.0', 'method': method, 'params': params }, timeout = timeout, - wallet = wallet + host_path = self.make_host_path(wallet) )) for n,(method,params) in enumerate(cmd_list[cur_pos:chunk_size+cur_pos],1)] ret.extend(await asyncio.gather(*tasks)) cur_pos += chunk_size diff --git a/test/unit_tests_d/ut_rpc.py b/test/unit_tests_d/ut_rpc.py index efcfe4e0..c54eb0a0 100755 --- a/test/unit_tests_d/ut_rpc.py +++ b/test/unit_tests_d/ut_rpc.py @@ -8,7 +8,7 @@ from mmgen.common import * from mmgen.protocol import init_proto from mmgen.rpc import rpc_init from mmgen.daemon import CoinDaemon -from mmgen.base_proto.monero.rpc import MoneroWalletRPCClient +from mmgen.base_proto.monero.rpc import MoneroRPCClient,MoneroRPCClientRaw,MoneroWalletRPCClient from mmgen.base_proto.monero.daemon import MoneroWalletDaemon def cfg_file_auth_test(proto,d): @@ -147,6 +147,26 @@ class unit_tests: def xmrwallet(self,name,ut): + async def test_monerod_rpc(md): + md_rpc = MoneroRPCClientRaw( + host = md.host, + port = md.rpc_port, + user = None, + passwd = None, + test_connection = False, + daemon = md, + ) + md_json_rpc = MoneroRPCClient( + host = md.host, + port = md.rpc_port, + user = None, + passwd = None, + test_connection = False, + daemon = md, + ) + await md_rpc.call('get_height') + await md_json_rpc.call('get_last_block_header') + async def run(): networks = init_proto('xmr').networks daemons = [( @@ -162,6 +182,9 @@ class unit_tests: if not opt.no_daemon_autostart: md.start() wd.start() + + await test_monerod_rpc(md) + c = MoneroWalletRPCClient(daemon=wd) fn = f'monero-{wd.network}-junk-wallet' qmsg(f'Creating {wd.network} wallet')