mmgen-xmrwallet: new resubmit operation

This commit is contained in:
The MMGen Project 2023-05-04 19:04:35 +00:00
commit 3b7a238259
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
6 changed files with 82 additions and 19 deletions

View file

@ -1 +1 @@
April 2023
May 2023

View file

@ -1 +1 @@
13.3.dev50
13.3.dev51

View file

@ -47,6 +47,8 @@ sweep - sweep funds in specified wallet:account to new address in same
relay - relay a transaction from a transaction file created using sweep
or transfer with the --no-relay option
submit - submit an autosigned transaction to a wallet and the network
resubmit - resubmit most recently submitted autosigned transaction (other
actions are required: see Exporting Outputs below)
txview - display detailed information about a transaction file or files
txlist - same as above, but display terse information in tabular format
dump - produce JSON dumps of wallet metadata (accounts, addresses and
@ -326,18 +328,20 @@ differences that apply to autosigning:
Exporting Outputs
Exporting outputs from a watch-only wallet is generally required in only
two cases:
three cases:
a) at the start of each signing session (after mmgen-autosign setup); and
a) at the start of each signing session (after mmgen-autosign setup);
b) after the wallet has received funds from an outside source or another
wallet.
wallet; and
c) after performing a resubmit operation.
You might also need to do it, however, if an offline wallet is unable to sign
a transaction due to missing outputs.
Export outputs from a wallet as follows:
Export outputs from a wallet as follows (note that the --rescan-blockchain
option is required only after a resubmit otherwise it should be omitted):
$ mmgen-xmrwallet --autosign export-outputs <wallet index>
$ mmgen-xmrwallet --autosign --rescan-blockchain export-outputs <wallet index>
At the start of a new signing session, you must export outputs from ALL
wallets you intend to transact with. This is necessary because the offline
@ -349,6 +353,11 @@ into the corresponding signing wallet(s) (and optionally redo any failed
transaction signing operation). The signing wallet(s) will also create
signed key images.
Following a resubmit, you must then import the signed key images into your
online wallet as follows:
$ mmgen-xmrwallet --autosign import-key-images
Replacing Existing Hot Wallets with Watch-Only Wallets

View file

@ -49,6 +49,7 @@ opts_data = {
'[opts] sweep [xmr_keyaddrfile] SWEEP_SPEC',
'[opts] submit [TX_file]',
'[opts] relay <TX_file>',
'[opts] resubmit',
'[opts] txview | txlist [TX_file] ...',
'[opts] export-outputs [wallets]',
'[opts] import-key-images [wallets]',
@ -112,7 +113,7 @@ if cmd_args and cfg.autosign and (
MoneroWalletOps.kafile_arg_ops
+ ('export-outputs','import-key-images','txview','txlist')
)
or len(cmd_args) == 1 and cmd_args[0] == 'submit'
or len(cmd_args) == 1 and cmd_args[0] in ('submit','resubmit')
):
cmd_args.insert(1,None)
@ -126,7 +127,7 @@ wallets = spec = None
if op.replace('-','_') not in MoneroWalletOps.ops:
die(1,f'{op!r}: unrecognized operation')
if op in ('relay','submit'):
if op in ('relay','submit','resubmit'):
if len(cmd_args) != 0:
cfg._opts.usage()
elif op in ('txview','txlist'):

View file

@ -446,6 +446,7 @@ class MoneroMMGenTX:
class Submitted(ColdSigned):
desc = 'submitted transaction'
ext = 'subtx'
silent_load = True
class View(Completed):
silent_load = True
@ -606,6 +607,7 @@ class MoneroWalletOps:
'label',
'sign',
'submit',
'resubmit',
'dump',
'restore',
'export_outputs',
@ -1266,6 +1268,10 @@ class MoneroWalletOps:
opts = ('rescan_blockchain',)
test_monerod = True
def check_uopts(self):
if self.cfg.rescan_blockchain and self.cfg.watch_only:
die(1,f'Operation {self.name!r} does not support --rescan-blockchain with watch-only wallets')
def __init__(self,cfg,uarg_tuple):
super().__init__(cfg,uarg_tuple)
@ -1748,6 +1754,25 @@ class MoneroWalletOps:
ask_overwrite = not self.cfg.autosign )
return new_tx
class resubmit(submit):
action = 'resubmitting transaction with'
def check_uopts(self):
if not self.cfg.autosign:
die(1,f'--autosign is required for this operation')
def get_tx(self):
asi = get_autosign_obj(self.cfg,'xmr')
files = [f for f in asi.xmr_tx_dir.iterdir() if f.name.endswith('.'+MoneroMMGenTX.Submitted.ext)]
txs = sorted(
(MoneroMMGenTX.Submitted( self.cfg, Path(fn) ) for fn in files),
key = lambda x: getattr(x.data,'submit_time',None) or x.data.create_time
)
if txs:
return txs[-1]
else:
self.die_no_tx( 'submitted', 0, asi.xmr_tx_dir )
class dump(wallet):
async def process_wallet(self,d,fn,last):
@ -1764,10 +1789,17 @@ class MoneroWalletOps:
class export_outputs(wallet):
action = 'exporting outputs from'
stem = 'process'
opts = ('rescan_blockchain',)
async def process_wallet(self,d,fn,last):
h = self.rpc(self,d)
h.open_wallet('source')
if self.cfg.rescan_blockchain:
gmsg_r(f'\n Rescanning blockchain...')
self.c.call('rescan_blockchain')
gmsg('done')
self.head_msg(d.idx,h.fn)
for ftype in ('Unsigned','Signed'):
old_fn = getattr(MoneroWalletOutputsFile,ftype).find_fn_from_wallet_fn(
@ -1803,7 +1835,7 @@ class MoneroWalletOps:
idata = res['num_imported']
bmsg('\n {} output{} imported'.format( idata, suf(idata) ))
data = m.data._asdict()
data.update(self.c.call('export_key_images')) # for testing: all = True
data.update(self.c.call('export_key_images', all=True))
m = MoneroWalletOutputsFile.SignedNew(
parent = self,
wallet_fn = m.get_wallet_fn(fn),

View file

@ -66,18 +66,23 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
('create_transfer_tx1', 'creating a transfer TX'),
('sign_transfer_tx1', 'signing the 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_key_images1', 'exporting signed key images from Alice’s offline wallets'),
('import_key_images1', 'importing signed key images into Alice’s online wallets'),
('sync_chkbal1', 'syncing Alice’s wallet #1'),
('create_transfer_tx2', 'creating a transfer TX (for relaying via proxy)'),
('sign_transfer_tx2', 'signing the transfer TX (for relaying via proxy)'),
('submit_transfer_tx2', 'submitting the transfer TX (relaying via proxy)'),
('sync_chkbal1', 'syncing Alice’s wallets and checking balance'),
('sync_chkbal2', 'syncing Alice’s wallets and checking balance'),
('dump_wallets', 'dumping Alice’s wallets'),
('delete_wallets', 'deleting Alice’s wallets'),
('restore_wallets', 'creating online (watch-only) wallets for Alice'),
('delete_dump_files', 'deleting Alice’s dump files'),
('export_outputs', 'exporting outputs from Alice’s watch-only wallets'),
('export_key_images', 'exporting signed key images from Alice’s offline wallets'),
('import_key_images', 'importing signed key images into Alice’s online wallets'),
('sync_chkbal2', 'syncing Alice’s wallets and checking balance'),
('export_outputs2', 'exporting outputs from Alice’s watch-only wallets'),
('export_key_images2', 'exporting signed key images from Alice’s offline 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'),
('check_tx_dirs', 'cleaning and checking signable file directories'),
)
@ -247,10 +252,14 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
bal_chk_func = bal_chk_func )
def sync_chkbal1(self):
return self._sync_chkbal( lambda n,b,ub: b == ub and 1 < b < 1.12 )
# 1.234567891234 - 0.124 = 1.110567891234 (minus fees)
def sync_chkbal2(self):
return self._sync_chkbal( lambda n,b,ub: b == ub and 0.8 < b < 0.86 )
# 1.234567891234 - 0.124 - 0.257 = 0.853567891234 (minus fees)
sync_chkbal2 = sync_chkbal1
sync_chkbal3 = sync_chkbal2
def _mine_chk(self,desc):
bal_type = {'locked':'b','unlocked':'ub'}[desc]
@ -262,6 +271,9 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
def submit_transfer_tx1(self):
return self._submit_transfer_tx( ext='sigtx' )
def resubmit_transfer_tx1(self):
return self._submit_transfer_tx( relay_parm=self.tx_relay_daemon_proxy_parm, op='resubmit', check_bal=False )
def submit_transfer_tx2(self):
return self._submit_transfer_tx( relay_parm=self.tx_relay_daemon_parm )
@ -288,14 +300,20 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
wallet_arg = wallet_arg,
add_opts = add_opts )
def export_outputs(self):
def export_outputs1(self):
return self._export_outputs('1',['--rescan-blockchain'])
def export_outputs2(self):
return self._export_outputs('1-2')
def _export_key_images(self,tx_count):
self.tx_count = tx_count
return self.do_sign(['--full-summary'],tx_name='Monero wallet outputs file')
def export_key_images(self):
def export_key_images1(self):
return self._export_key_images(1)
def export_key_images2(self):
return self._export_key_images(2)
def _import_key_images(self,wallet_arg):
@ -304,7 +322,10 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
desc = 'importing key images',
wallet_arg = wallet_arg )
def import_key_images(self):
def import_key_images1(self):
return self._import_key_images(None)
def import_key_images2(self):
return self._import_key_images(None)
def create_fake_tx_files(self):