ts_xmr_autosign: run signing process in separate thread

This commit is contained in:
The MMGen Project 2023-05-06 15:14:07 +00:00
commit 08319227c5
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
5 changed files with 80 additions and 35 deletions

View file

@ -215,7 +215,8 @@ class Autosign:
dfl_wallet_dir = '/dev/shm/autosign'
old_dfl_mountpoint = '/mnt/tx'
dev_disk_path = Path('/dev/disk/by-label/MMGEN_TX')
dfl_dev_disk_path = '/dev/disk/by-label/MMGEN_TX'
fake_dev_disk_path = '/tmp/mmgen-test-suite-dev.disk.by-label.MMGEN_TX'
old_dfl_mountpoint_errmsg = f"""
Mountpoint '{old_dfl_mountpoint}' is no longer supported!
@ -246,6 +247,9 @@ class Autosign:
cfg.mnemonic_fmt,
fmt_list( self.mn_fmts, fmt='no_spc' ) ))
self.dev_disk_path = Path(
self.fake_dev_disk_path if cfg.test_suite_xmr_autosign else
self.dfl_dev_disk_path )
self.mountpoint = Path(cfg.mountpoint or self.dfl_mountpoint)
self.wallet_dir = Path(cfg.wallet_dir or self.dfl_wallet_dir)
@ -488,6 +492,7 @@ class Autosign:
'coin': 'xmr',
'wallet_rpc_user': 'autosigner',
'wallet_rpc_password': 'my very secret password',
'wallet_rpc_port': 23232 if self.cfg.test_suite_xmr_autosign else None,
'wallet_dir': str(self.wallet_dir),
'autosign': True,
'autosign_mountpoint': str(self.mountpoint),
@ -571,26 +576,33 @@ class Autosign:
else: return True
async def do_loop(self):
n,prev_status = 0,False
if not self.cfg.stealth_led:
self.led.set('standby')
testing_xmr = self.cfg.test_suite_xmr_autosign
if testing_xmr:
msg('Waiting for fake device insertion')
n = 1 if testing_xmr else 0
prev_status = False
while True:
status = self.get_insert_status()
if status and not prev_status:
msg('Device insertion detected')
await self.do_sign()
if testing_xmr:
self.dev_disk_path.unlink(missing_ok=True)
prev_status = status
if not n % 10:
msg_r(f"\r{' '*17}\rWaiting")
await asyncio.sleep(1)
msg_r('.')
n += 1
if not testing_xmr:
msg_r('.')
n += 1
def at_exit(self,exit_val,message=None):
if message:
msg(message)
self.led.stop()
sys.exit(int(exit_val))
sys.exit(0 if self.cfg.test_suite_xmr_autosign else int(exit_val))
def init_exit_handler(self):

View file

@ -202,6 +202,7 @@ class Config(Lockable):
exec_wrapper = False
test_suite = False
test_suite_autosign_led_simulate = False
test_suite_xmr_autosign = False
test_suite_cfgtest = False
test_suite_deterministic = False
test_suite_pexpect = False
@ -283,6 +284,7 @@ class Config(Lockable):
'MMGEN_COLUMNS',
'MMGEN_TEST_SUITE',
'MMGEN_TEST_SUITE_AUTOSIGN_LED_SIMULATE',
'MMGEN_TEST_SUITE_XMR_AUTOSIGN',
'MMGEN_TEST_SUITE_CFGTEST',
'MMGEN_TEST_SUITE_DETERMINISTIC',
'MMGEN_TEST_SUITE_PEXPECT',

View file

@ -111,7 +111,9 @@ class MoneroWalletDaemon(RPCDaemon):
self.network = proto.network
self.wallet_dir = wallet_dir
self.rpc_port = getattr(self.rpc_ports,self.network) + (11 if test_suite else 0)
self.rpc_port = (
self.cfg.wallet_rpc_port or
getattr(self.rpc_ports,self.network) + (11 if test_suite else 0) )
if port_shift:
self.rpc_port += port_shift

View file

@ -80,6 +80,7 @@ class TestSuiteAutosignBase(TestSuiteBase):
tmpdir_nums = [18]
color = True
mountpoint_basename = 'mmgen_autosign'
no_insert_check = True
def __init__(self,trunner,cfgs,spawn):
@ -104,6 +105,7 @@ class TestSuiteAutosignBase(TestSuiteBase):
os.path.join(self.tmpdir,self.mountpoint_basename)
),
'wallet_dir': None if self.live else self.wallet_dir,
'test_suite_xmr_autosign': self.name == 'TestSuiteXMRAutosign',
})
)
self.mountpoint = self.asi.mountpoint
@ -126,8 +128,9 @@ class TestSuiteAutosignBase(TestSuiteBase):
self.opts.extend([
f'--mountpoint={self.mountpoint}',
f'--wallet-dir={self.wallet_dir}',
'--no-insert-check',
])
if self.no_insert_check:
self.opts.append('--no-insert-check')
self.tx_file_ops('set_count') # initialize tx_count here so we can resume anywhere

View file

@ -46,6 +46,7 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
simulate = False
bad_tx_count = 0
tx_relay_user = 'miner'
no_insert_check = False
cmd_group = (
('daemon_version', 'checking daemon version'),
@ -63,16 +64,14 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
('create_wallets_miner', 'creating Monero wallets for Miner'),
('mine_initial_coins', 'mining initial coins'),
('fund_alice', 'sending funds to Alice'),
('autosign_start_thread', 'starting autosign wait loop'),
('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_chkbal2', 'syncing Alice’s wallets and checking balance'),
('dump_wallets', 'dumping Alice’s wallets'),
@ -80,15 +79,17 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
('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_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'),
('autosign_kill_thread', 'stopping autosign wait loop'),
)
def __init__(self,trunner,cfgs,spawn):
os.environ['MMGEN_TEST_SUITE_XMR_AUTOSIGN'] = '1'
TestSuiteXMRWallet.__init__(self,trunner,cfgs,spawn)
TestSuiteAutosignBase.__init__(self,trunner,cfgs,spawn)
@ -109,6 +110,9 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
self.autosign_opts = [f'--autosign-mountpoint={self.mountpoint}'] # mmgen-xmrwallet opts
self.tx_count = 1
def __del__(self):
os.environ['MMGEN_TEST_SUITE_XMR_AUTOSIGN'] = ''
def create_tmp_wallets(self):
self.spawn('',msg_only=True)
data = self.users['alice']
@ -191,7 +195,11 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
def delete_dump_files(self):
return self._delete_files( '.dump' )
def insert_device(self):
self.asi.dev_disk_path.touch()
def autosign_setup(self):
self.insert_device()
Path(self.autosign_xmr_dir).mkdir(parents=True,exist_ok=True)
Path(self.autosign_xmr_dir,'old.vkeys').touch()
t = self.run_setup(
@ -202,6 +210,28 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
t.written_to_file('View keys')
return t
def autosign_start_thread(self):
self.asi.dev_disk_path.unlink(missing_ok=True)
def run():
t = self.spawn('mmgen-autosign', self.opts + ['wait'], direct_exec=True )
self.write_to_tmpfile('autosign_thread_pid',str(t.ep.pid))
import threading
threading.Thread( target=run, name='Autosign wait loop' ).start()
time.sleep(0.2)
return 'silent'
def autosign_kill_thread(self):
self.spawn('',msg_only=True)
pid = int(self.read_from_tmpfile('autosign_thread_pid'))
self.delete_tmpfile('autosign_thread_pid')
from signal import SIGTERM
imsg(purple(f'Killing autosign wait loop [PID {pid}]'))
try:
os.kill(pid,SIGTERM)
except:
imsg(yellow(f'{pid}: no such process'))
return 'ok'
def create_watchonly_wallets(self):
return self.create_wallets( 'alice', op='restore' )
@ -209,7 +239,10 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
return self.create_wallets( 'alice', op='restore' )
def _create_transfer_tx(self,amt):
return self.do_op('transfer','alice',f'1:0:{self.burn_addr},{amt}',no_relay=True,do_ret=True)
t = self.do_op('transfer','alice',f'1:0:{self.burn_addr},{amt}',no_relay=True,do_ret=True)
t.read() # required!
self.insert_device()
return t
def create_transfer_tx1(self):
return self._create_transfer_tx('0.124')
@ -219,16 +252,14 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
get_file_with_ext(self.asi.xmr_tx_dir,'sigtx',delete_all=True)
return self._create_transfer_tx('0.257')
def _sign_transfer_tx(self):
return self.do_sign(['--full-summary'],tx_name='Monero transaction')
def sign_transfer_tx1(self):
return self._sign_transfer_tx()
def sign_transfer_tx2(self):
return self._sign_transfer_tx()
def _xmr_autosign_op(self,op,desc=None,dtype=None,ext=None,wallet_arg=None,add_opts=[]):
def _xmr_autosign_op(self,op,desc=None,dtype=None,ext=None,wallet_arg=None,add_opts=[],wait_signed=False):
if wait_signed:
oqmsg_r(gray('[waiting for signing to complete]...'))
while True:
if not self.asi.dev_disk_path.exists():
break
time.sleep(0.2)
oqmsg(gray('OK'))
data = self.users['alice']
args = (
self.extra_opts
@ -283,7 +314,8 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
t = self._xmr_autosign_op(
op = op,
add_opts = [f'--tx-relay-daemon={relay_parm}'] if relay_parm else [],
ext = ext )
ext = ext,
wait_signed = op == 'submit' )
t.expect( f'{op.capitalize()} transaction? (y/N): ', 'y' )
t.written_to_file('Submitted transaction')
if check_bal:
@ -293,11 +325,14 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
return t
def _export_outputs(self,wallet_arg,add_opts=[]):
return self._xmr_autosign_op(
t = self._xmr_autosign_op(
op = 'export-outputs',
dtype = 'wallet outputs',
wallet_arg = wallet_arg,
add_opts = add_opts )
t.read() # required!
self.insert_device()
return t
def export_outputs1(self):
return self._export_outputs('1',['--rescan-blockchain'])
@ -305,20 +340,11 @@ class TestSuiteXMRAutosign(TestSuiteXMRWallet,TestSuiteAutosignBase):
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_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):
return self._xmr_autosign_op(
op = 'import-key-images',
wallet_arg = wallet_arg )
wallet_arg = wallet_arg,
wait_signed = True )
def import_key_images1(self):
return self._import_key_images(None)