mmgen-xmrwallet: new export-outputs-sign operation

This commit is contained in:
The MMGen Project 2024-03-03 09:59:01 +00:00
commit c96908ee36
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
5 changed files with 47 additions and 26 deletions

View file

@ -39,6 +39,7 @@ class Signable:
clean_all = False
multiple_ok = True
action_desc = 'signed'
def __init__(self,parent):
self.parent = parent
@ -266,7 +267,6 @@ class Signable:
dir_name = 'xmr_outputs_dir'
clean_all = True
summary_footer = '\n'
action_desc = 'imported and signed'
async def sign(self,f):
from .xmrwallet import MoneroWalletOps,xmrwallet_uargs
@ -278,8 +278,12 @@ class Signable:
wallets = str(wallet_idx),
spec = None ),
)
obj = await m.main( f, wallet_idx, restart_daemon=self.need_daemon_restart(m,wallet_idx) )
obj.write()
obj = await m.main(f, wallet_idx, restart_daemon=self.need_daemon_restart(m,wallet_idx))
if obj.data.sign:
obj.write()
self.action_desc = 'imported and signed'
else:
self.action_desc = 'imported'
return obj
class message(base):

View file

@ -63,6 +63,8 @@ restore - same as ‘create’, but additionally restore wallet metadata from
the corresponding JSON dump files created with dump
export-outputs - export outputs of watch-only wallets for import into
their corresponding offline wallets
export-outputs-sign - same as above, plus request offline wallet to create
signed key images for import by import-key-images
import-key-images - import key images signed by offline wallets into their
corresponding watch-only wallets
@ -357,12 +359,14 @@ Then insert the removable device on the offline machine. This will import
the outputs into the corresponding signing wallet(s) (and optionally redo any
failed transaction signing operation).
Following a resubmit, add the --rescan-blockchain option:
Following a resubmit, use the export-outputs-sign operation instead, and
add the --rescan-blockchain option:
$ mmgen-xmrwallet --autosign --rescan-blockchain export-outputs <wallet index>
$ mmgen-xmrwallet --autosign --rescan-blockchain export-outputs-sign <wallet index>
Insert the removable device on your online machine and import the signed key
images into your online wallet as follows:
Here the offline signing wallet(s) will also create signed key images. Insert
the removable device on your online machine and import the signed key images
into your online wallet as follows:
$ mmgen-xmrwallet --autosign import-key-images
@ -421,7 +425,7 @@ in again and resume where you left off.
Once your watch-only wallets are synced, you need to export their outputs:
$ mmgen-xmrwallet --autosign export-outputs
$ mmgen-xmrwallet --autosign export-outputs-sign
Now insert the removable device on the offline machine and wait until the LED
stops flashing (or safe to extract). The wallet outputs are now imported

View file

@ -48,7 +48,7 @@ opts_data = {
'[opts] relay <TX_file>',
'[opts] resubmit | abort (for use with --autosign only)',
'[opts] txview | txlist [TX_file] ...',
'[opts] export-outputs | import-key-images [wallets]',
'[opts] export-outputs | export-outputs-sign | import-key-images [wallets]',
],
'options': """
-h, --help Print this help message
@ -107,7 +107,7 @@ cmd_args = cfg._args
if cmd_args and cfg.autosign and (
cmd_args[0] in (
MoneroWalletOps.kafile_arg_ops
+ ('export-outputs','import-key-images','txview','txlist')
+ ('export-outputs', 'export-outputs-sign', 'import-key-images', 'txview', 'txlist')
)
or len(cmd_args) == 1 and cmd_args[0] in ('submit', 'resubmit', 'abort')
):
@ -133,7 +133,7 @@ elif op in ('new','transfer','sweep','label'):
if len(cmd_args) != 1:
cfg._opts.usage()
spec = cmd_args[0]
elif op in ('export-outputs','import-key-images'):
elif op in ('export-outputs', 'export-outputs-sign', 'import-key-images'):
if not cfg.autosign: # --autosign only for now - TODO
die(f'--autosign must be used with command {op!r}')
if len(cmd_args) > 1:

View file

@ -486,6 +486,7 @@ class MoneroWalletOutputsFile:
'wallet_index',
'outputs_data_hex',
'signed_key_images',
'sign',
])
def __init__(self,cfg):
@ -527,7 +528,7 @@ class MoneroWalletOutputsFile:
class New(Base):
ext = 'raw'
def __init__( self, parent, wallet_fn, data, wallet_idx=None ):
def __init__(self, parent, wallet_fn, data, wallet_idx=None, sign=False):
super().__init__(parent.cfg)
self.wallet_fn = wallet_fn
init_data = dict.fromkeys(self.data_tuple._fields)
@ -535,6 +536,8 @@ class MoneroWalletOutputsFile:
'seed_id': parent.kal.al_id.sid,
'wallet_index': wallet_idx or parent.get_idx_from_fn(wallet_fn),
})
if sign:
init_data['sign'] = sign
init_data.update({k:v for k,v in data.items() if k in init_data})
self.data = self.data_tuple(**init_data)
@ -1882,6 +1885,7 @@ class MoneroWalletOps:
action = 'exporting outputs from'
stem = 'process'
opts = ('rescan_blockchain',)
sign = False
async def process_wallet(self,d,fn,last):
h = self.rpc(self,d)
@ -1904,10 +1908,14 @@ class MoneroWalletOps:
parent = self,
wallet_fn = fn,
data = self.c.call('export_outputs', all=True),
sign = self.sign,
)
m.write()
return True
class export_outputs_sign(export_outputs):
sign = True
class import_outputs(wallet):
action = 'importing wallet outputs into'
start_daemon = False
@ -1927,14 +1935,15 @@ class MoneroWalletOps:
outputs_data_hex = m.data.outputs_data_hex )
idata = res['num_imported']
bmsg(f'\n {idata} output{suf(idata)} imported')
data = m.data._asdict()
data.update(self.c.call('export_key_images', all=True))
m = MoneroWalletOutputsFile.SignedNew(
parent = self,
wallet_fn = m.get_wallet_fn(fn),
data = data )
idata = m.data.signed_key_images or []
bmsg(f' {len(idata)} key image{suf(idata)} signed')
if m.data.sign:
data = m.data._asdict()
data.update(self.c.call('export_key_images', all=True))
m = MoneroWalletOutputsFile.SignedNew(
parent = self,
wallet_fn = m.get_wallet_fn(fn),
data = data)
idata = m.data.signed_key_images or []
bmsg(f' {len(idata)} key image{suf(idata)} signed')
return m
class import_key_images(wallet):

View file

@ -67,10 +67,11 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignThreaded):
('fund_alice1', 'sending funds to Alice (wallet #1)'),
('fund_alice2', 'sending funds to Alice (wallet #2)'),
('autosign_start_thread', 'starting autosign wait loop'),
('export_outputs1', 'exporting outputs from Alice’s watch-only wallet #1'),
('create_transfer_tx1', 'creating a transfer TX'),
('submit_transfer_tx1', 'submitting the transfer TX'),
('resubmit_transfer_tx1', 'resubmitting the transfer TX'),
('export_outputs1', 'exporting outputs from Alice’s watch-only wallet #1'),
('export_outputs2', 'exporting outputs from Alice’s watch-only wallet #1'),
('import_key_images1', 'importing signed key images into Alice’s online wallets'),
('sync_chkbal1', 'syncing Alice’s wallet #1'),
('abort_tx1', 'aborting the current transaction (error)'),
@ -83,7 +84,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignThreaded):
('delete_wallets', 'deleting Alice’s wallets'),
('restore_wallets', 'creating online (watch-only) wallets for Alice'),
('delete_dump_files', 'deleting Alice’s dump files'),
('export_outputs2', 'exporting outputs from Alice’s watch-only wallets'),
('export_outputs3', 'exporting outputs from Alice’s watch-only wallets'),
('import_key_images2', 'importing signed key images into Alice’s online wallets'),
('sync_chkbal3', 'syncing Alice’s wallets and checking balance'),
('txlist', 'listing Alice’s submitted transactions'),
@ -353,10 +354,10 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignThreaded):
else:
return t
def _export_outputs(self,wallet_arg,add_opts=[]):
def _export_outputs(self, wallet_arg, op, add_opts=[]):
self.insert_device_online()
t = self._xmr_autosign_op(
op = 'export-outputs',
op = op,
wallet_arg = wallet_arg,
add_opts = add_opts)
t.written_to_file('Wallet outputs')
@ -364,10 +365,13 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignThreaded):
return t
def export_outputs1(self):
return self._export_outputs('1',['--rescan-blockchain'])
return self._export_outputs('1', op='export-outputs')
def export_outputs2(self):
return self._export_outputs('1-2')
return self._export_outputs('1', op='export-outputs-sign', add_opts=['--rescan-blockchain'])
def export_outputs3(self):
return self._export_outputs('1-2', op='export-outputs-sign')
def _import_key_images(self,wallet_arg):
self.insert_device_online()