From 68fba89e9675945c52ac2698e44ae95e117df38a Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 15 Nov 2025 09:50:21 +0000 Subject: [PATCH] mmgen-xmrwallet: new `--compat` option --- mmgen/autosign.py | 1 + mmgen/cfg.py | 2 ++ mmgen/data/mmgen.cfg | 4 ++++ mmgen/help/help_notes.py | 8 ++++++++ mmgen/main_xmrwallet.py | 7 ++++++- mmgen/proto/xmr/params.py | 1 + mmgen/proto/xmr/tw/ctl.py | 19 +++++++++++++++++++ mmgen/tw/store.py | 3 ++- mmgen/xmrwallet/__init__.py | 12 +++++++++++- mmgen/xmrwallet/ops/create.py | 2 ++ setup.cfg | 1 + 11 files changed, 57 insertions(+), 3 deletions(-) create mode 100755 mmgen/proto/xmr/tw/ctl.py diff --git a/mmgen/autosign.py b/mmgen/autosign.py index d6cee88d..71517d36 100755 --- a/mmgen/autosign.py +++ b/mmgen/autosign.py @@ -801,6 +801,7 @@ class Autosign: 'autosign': True, 'autosign_mountpoint': str(self.mountpoint), 'offline': True, + 'compat': False, 'passwd_file': str(self.keyfile)}) return self._xmrwallet_cfg diff --git a/mmgen/cfg.py b/mmgen/cfg.py index 65d43fa7..a2c97932 100755 --- a/mmgen/cfg.py +++ b/mmgen/cfg.py @@ -239,6 +239,7 @@ class Config(Lockable): # Monero: monero_wallet_rpc_user = 'monero' monero_wallet_rpc_password = '' + xmrwallet_compat = False priority = 0 # test suite: @@ -308,6 +309,7 @@ class Config(Lockable): 'max_input_size', 'max_tx_file_size', 'mnemonic_entry_modes', + 'xmrwallet_compat', 'monero_wallet_rpc_password', 'monero_wallet_rpc_user', 'no_license', diff --git a/mmgen/data/mmgen.cfg b/mmgen/data/mmgen.cfg index f30dfcfa..d79faf25 100644 --- a/mmgen/data/mmgen.cfg +++ b/mmgen/data/mmgen.cfg @@ -152,6 +152,10 @@ # Set the Monero wallet RPC password to something secure: # monero_wallet_rpc_password passw0rd +# Configure mmgen-xmrwallet for compatibility with mmgen-tx{create,sign,send} +# family of commands (equivalent to mmgen-xmrwallet --compat option) +# xmrwallet_compat true + ####################################################################### ## The following options are probably of interest only to developers ## ####################################################################### diff --git a/mmgen/help/help_notes.py b/mmgen/help/help_notes.py index dac21470..5bfb0efa 100755 --- a/mmgen/help/help_notes.py +++ b/mmgen/help/help_notes.py @@ -51,6 +51,14 @@ class help_notes: from ..proto.btc.rpc.local import BitcoinRPCClient return BitcoinRPCClient.dfl_twname + def tw_dir(self): + from ..tw.ctl import TwCtl + twctl_cls = self.proto.base_proto_subclass(TwCtl, 'tw.ctl') + if hasattr(twctl_cls, 'get_tw_dir'): + return twctl_cls.get_tw_dir(self.cfg, self.proto) + else: + raise ValueError(f'protocol {self.proto.name} does not support tracking wallet with store') + def MasterShareIdx(self): from ..seedsplit import MasterShareIdx return MasterShareIdx diff --git a/mmgen/main_xmrwallet.py b/mmgen/main_xmrwallet.py index ca301b5e..f1b0bb6a 100755 --- a/mmgen/main_xmrwallet.py +++ b/mmgen/main_xmrwallet.py @@ -47,6 +47,10 @@ opts_data = { When this option is in effect, filename argu- ments must be omitted, as files are located automatically. +-c, --compat Adjust configuration for compatibility with + the mmgen-tx{{create,sign,send}} family of + commands. Currently equivalent to + ā€˜-w {tw_dir}’ -f, --priority=N Specify an integer priority ā€˜N’ for inclusion of a transaction in the blockchain (higher number means higher fee). Valid parameters: @@ -88,11 +92,12 @@ opts_data = { """ }, 'code': { - 'options': lambda cfg, s: s.format( + 'options': lambda cfg, help_notes, s: s.format( D = xmrwallet.uarg_info['daemon'].annot, R = xmrwallet.uarg_info['tx_relay_daemon'].annot, cfg = cfg, gc = gc, + tw_dir = help_notes('tw_dir'), tp = fmt_dict(xmrwallet.tx_priorities, fmt='equal_compact') ), 'notes': lambda help_mod, s: s.format( diff --git a/mmgen/proto/xmr/params.py b/mmgen/proto/xmr/params.py index 1467e52a..8c9d1002 100755 --- a/mmgen/proto/xmr/params.py +++ b/mmgen/proto/xmr/params.py @@ -25,6 +25,7 @@ class MoneroViewKey(HexStr): # https://github.com/monero-project/monero/blob/master/src/cryptonote_config.h class mainnet(CoinProtocol.RPC, CoinProtocol.DummyWIF, CoinProtocol.Base): + mod_clsname = 'Monero' network_names = _nw('mainnet', 'stagenet', None) base_proto = 'Monero' base_proto_coin = 'XMR' diff --git a/mmgen/proto/xmr/tw/ctl.py b/mmgen/proto/xmr/tw/ctl.py new file mode 100755 index 00000000..44350b47 --- /dev/null +++ b/mmgen/proto/xmr/tw/ctl.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# +# MMGen Wallet, a terminal-based cryptocurrency wallet +# Copyright (C)2013-2025 The MMGen Project +# Licensed under the GNU General Public License, Version 3: +# https://www.gnu.org/licenses +# Public project repositories: +# https://github.com/mmgen/mmgen-wallet +# https://gitlab.com/mmgen/mmgen-wallet + +""" +proto.xmr.tw.ctl: Monero tracking wallet control class +""" + +from ....tw.store import TwCtlWithStore + +class MoneroTwCtl(TwCtlWithStore): + + tw_subdir = 'tracking-wallets' diff --git a/mmgen/tw/store.py b/mmgen/tw/store.py index 5ef12261..1f19c6af 100755 --- a/mmgen/tw/store.py +++ b/mmgen/tw/store.py @@ -26,6 +26,7 @@ from .ctl import TwCtl, write_mode, label_addr_pair class TwCtlWithStore(TwCtl, metaclass=AsyncInit): caps = ('batch',) + tw_subdir = None tw_fn = 'tracking-wallet.json' aggressive_sync = False @@ -85,7 +86,7 @@ class TwCtlWithStore(TwCtl, metaclass=AsyncInit): cfg.data_dir_root, 'altcoins', proto.coin.lower(), - ('' if proto.network == 'mainnet' else proto.network)) + ('' if proto.network == 'mainnet' else proto.network)) / (cls.tw_subdir or '') def upgrade_wallet_maybe(self): pass diff --git a/mmgen/xmrwallet/__init__.py b/mmgen/xmrwallet/__init__.py index 0535e8c1..691656f2 100755 --- a/mmgen/xmrwallet/__init__.py +++ b/mmgen/xmrwallet/__init__.py @@ -17,7 +17,7 @@ from collections import namedtuple from ..proto.btc.common import b58a -from ..util import capfirst +from ..util import die, capfirst tx_priorities = { 1: 'low', @@ -113,4 +113,14 @@ def op_cls(op_name): return cls def op(op, cfg, infile, wallets, *, spec=None): + if cfg.compat if cfg.compat is not None else cfg.xmrwallet_compat: + if cfg.wallet_dir: + die(1, '--wallet-dir can not be specified in xmrwallet compatibility mode') + from ..tw.ctl import TwCtl + from ..cfg import Config + twctl_cls = cfg._proto.base_proto_subclass(TwCtl, 'tw.ctl') + cfg = Config({ + '_clone': cfg, + 'compat': True, + 'wallet_dir': twctl_cls.get_tw_dir(cfg, cfg._proto)}) return op_cls(op)(cfg, uargs(infile, wallets, spec)) diff --git a/mmgen/xmrwallet/ops/create.py b/mmgen/xmrwallet/ops/create.py index 6956e150..5aa4a4d2 100755 --- a/mmgen/xmrwallet/ops/create.py +++ b/mmgen/xmrwallet/ops/create.py @@ -28,6 +28,8 @@ class OpCreate(OpWallet): if self.cfg.restore_height != 'current': if int(self.cfg.restore_height or 0) < 0: die(1, f'{self.cfg.restore_height}: invalid value for --restore-height (less than zero)') + if self.cfg.compat: + self.cfg.wallet_dir.mkdir(parents=True, exist_ok=True) async def process_wallet(self, d, fn, last): msg_r('') # for pexpect diff --git a/setup.cfg b/setup.cfg index 4bce54b5..83564b39 100644 --- a/setup.cfg +++ b/setup.cfg @@ -104,6 +104,7 @@ packages = mmgen.proto.vm.tx mmgen.proto.xchain mmgen.proto.xmr + mmgen.proto.xmr.tw mmgen.proto.zec mmgen.rpc mmgen.rpc.backends