From 4ed86de63996e887cb3da159a13b1d61b54111c9 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Tue, 2 Mar 2021 17:34:50 +0000 Subject: [PATCH] rpc: add CallSigs classes, indirect RPC call (icall) method --- mmgen/daemon.py | 7 +++++++ mmgen/rpc.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/mmgen/daemon.py b/mmgen/daemon.py index 19117710..9a7475e0 100755 --- a/mmgen/daemon.py +++ b/mmgen/daemon.py @@ -297,6 +297,7 @@ class CoinDaemon(Daemon): network_ids = ('btc','btc_tn','btc_rt','bch','bch_tn','bch_rt','ltc','ltc_tn','ltc_rt','xmr','eth','etc') cd = namedtuple('daemon_data', [ + 'id', 'coin', 'cls_pfx', 'coind_name', @@ -311,6 +312,7 @@ class CoinDaemon(Daemon): daemon_ids = { 'btc': cd( + 'bitcoin_core', 'Bitcoin', 'Bitcoin', 'Bitcoin Core', 210000, '0.21.0', @@ -320,6 +322,7 @@ class CoinDaemon(Daemon): 'testnet3', 8332, 18332, 18444), 'bch': cd( + 'bitcoin_cash_node', 'BitcoinCashNode', 'Bitcoin', 'Bitcoin Cash Node', 22020000, '22.2.0', @@ -329,6 +332,7 @@ class CoinDaemon(Daemon): 'testnet3', 8442, 18442, 18553), # for BCH we use non-standard RPC ports 'ltc': cd( + 'litecoin_core', 'Litecoin', 'Bitcoin', 'Litecoin Core', 180100, '0.18.1', @@ -338,6 +342,7 @@ class CoinDaemon(Daemon): 'testnet4', 9332, 19332, 19444), 'xmr': cd( + 'monerod', 'Monero', 'Monero', 'Monero', 'N/A', 'N/A', @@ -347,6 +352,7 @@ class CoinDaemon(Daemon): None, 18081, None, None), 'eth': cd( + 'openethereum', 'Ethereum', 'Ethereum', 'OpenEthereum', 3000001, '3.0.1', @@ -356,6 +362,7 @@ class CoinDaemon(Daemon): None, 8545, 8545, 8545), 'etc': cd( + 'openethereum', 'Ethereum Classic', 'Ethereum', 'OpenEthereum', 3000001, '3.0.1', diff --git a/mmgen/rpc.py b/mmgen/rpc.py index 734121d8..27344959 100755 --- a/mmgen/rpc.py +++ b/mmgen/rpc.py @@ -193,6 +193,47 @@ class RPCBackends: from collections import namedtuple auth_data = namedtuple('rpc_auth_data',['user','passwd']) +class CallSigs: + + class Bitcoin: + + class bitcoin_core: + + @classmethod + def createwallet(cls,wallet_name,no_keys=True,passphrase='',load_on_startup=True): + """ + Quirk: when --datadir is specified (even if standard), wallet is created directly in + datadir, otherwise in datadir/wallets + """ + return ( + 'createwallet', + wallet_name, # 1. wallet_name + no_keys, # 2. disable_private_keys + no_keys, # 3. blank (no keys or seed) + passphrase, # 4. passphrase (empty string for non-encrypted) + False, # 5. avoid_reuse (track address reuse) + False, # 6. descriptors (native descriptor wallet) + load_on_startup # 7. load_on_startup + ) + + class litecoin_core(bitcoin_core): + + @classmethod + def createwallet(cls,wallet_name,no_keys=True,passphrase='',load_on_startup=True): + return ( + 'createwallet', + wallet_name, # 1. wallet_name + no_keys, # 2. disable_private_keys + no_keys, # 3. blank (no keys or seed) + ) + + class bitcoin_cash_node(litecoin_core): pass + + class Ethereum: + + class openethereum: pass + + class RPCClient(MMGenObject): auth_type = None @@ -307,6 +348,19 @@ class RPCClient(MMGenObject): return ret + # Icall family of methods - indirect RPC call using CallSigs mechanism: + # - 'timeout' and 'wallet' kwargs are passed to corresponding Call method + # - remaining kwargs are passed to CallSigs method + # - CallSigs method returns method and positional params for Call method + + def icall(self,method,**kwargs): + timeout = kwargs.pop('timeout',None) + wallet = kwargs.pop('wallet',None) + return self.call( + *getattr(self.call_sigs,method)(**kwargs), + timeout = timeout, + wallet = wallet ) + async def process_http_resp(self,coro,batch=False): text,status = await coro if status == 200: @@ -341,6 +395,7 @@ class BitcoinRPCClient(RPCClient,metaclass=aInitMeta): self.proto = proto self.daemon = daemon + self.call_sigs = getattr(getattr(CallSigs,proto.base_proto),daemon.id) super().__init__( host = 'localhost' if g.test_suite else (g.rpc_host or 'localhost'), @@ -530,6 +585,7 @@ class EthereumRPCClient(RPCClient,metaclass=aInitMeta): async def __ainit__(self,proto,daemon,backend,caller): self.proto = proto self.daemon = daemon + self.call_sigs = getattr(getattr(CallSigs,proto.base_proto),daemon.id) super().__init__( host = 'localhost' if g.test_suite else (g.rpc_host or 'localhost'),