MacOSRamDisk: configure size in cfg file and at runtime

This commit is contained in:
The MMGen Project 2024-09-04 13:08:51 +00:00
commit 14f4839447
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
5 changed files with 54 additions and 4 deletions

View file

@ -18,9 +18,10 @@ from pathlib import Path
from subprocess import run, PIPE, DEVNULL
from .cfg import Config
from .util import msg, msg_r, ymsg, rmsg, gmsg, bmsg, die, suf, fmt, fmt_list
from .util import msg, msg_r, ymsg, rmsg, gmsg, bmsg, die, suf, fmt, fmt_list, is_int
from .color import yellow,red,orange,brown
from .wallet import Wallet,get_wallet_cls
from .addrlist import AddrIdxList
from .filename import find_file_in_dir
from .ui import keypress_confirm
@ -399,7 +400,7 @@ class Autosign:
self.ramdisk = MacOSRamDisk(
cfg,
self.macOS_ramdisk_name,
10,
self._get_macOS_ramdisk_size(),
path = self.shm_dir)
self.keyfile = self.mountpoint / 'autosign.key'
@ -611,6 +612,22 @@ class Autosign:
if not no_unmount:
self.do_umount()
def _get_macOS_ramdisk_size(self):
from .platform.darwin.util import MacOSRamDisk, warn_ramdisk_too_small
# allow 1MB for each Monero wallet
xmr_size = len(AddrIdxList(self.cfg.xmrwallets)) if self.cfg.xmrwallets else 0
calc_size = xmr_size + 1
usr_size = self.cfg.macos_ramdisk_size or self.cfg.macos_autosign_ramdisk_size
if is_int(usr_size):
usr_size = int(usr_size)
else:
die(1, f'{usr_size}: invalid user-specified macOS ramdisk size (not an integer)')
min_size = MacOSRamDisk.min_size
size = max(usr_size, calc_size, min_size)
if usr_size and usr_size < min_size:
warn_ramdisk_too_small(usr_size, min_size)
return size
def setup(self):
def remove_wallet_dir():

View file

@ -145,6 +145,7 @@ class Config(Lockable):
max_input_size = 1024 * 1024
min_urandchars = 10
max_urandchars = 80
macos_autosign_ramdisk_size = 10 # see MacOSRamDisk
# debug
debug = False
@ -255,6 +256,7 @@ class Config(Lockable):
'force_256_color',
'hash_preset',
'http_timeout',
'macos_autosign_ramdisk_size',
'max_input_size',
'max_tx_file_size',
'mnemonic_entry_modes',

View file

@ -84,6 +84,11 @@
# When change addresses are chosen manually the option is ignored:
# autochg_ignore_labels true
# Set the size in MB of the ramdisk used to store the temporary offline
# autosign wallet(s) on macOS machines. This option is of interest only for
# setups with unusually large Monero wallets:
# macos_autosign_ramdisk_size 10
############################
## Ignore daemon versions ##
############################

View file

@ -41,6 +41,11 @@ opts_data = {
-M, --mnemonic-fmt=F During setup, prompt for mnemonic seed phrase of format
'F' (choices: {mn_fmts}; default: {asi.dfl_mn_fmt!r})
-n, --no-summary Dont print a transaction summary
-r, --macos-ramdisk-size=S Set the size (in MB) of the ramdisk used to store
the offline signing wallet(s) on macOS machines. By
default, a runtime-calculated value will be used. This
option is of interest only for setups with unusually
large Monero wallets
-s, --stealth-led Stealth LED mode - signal busy and error only, and only
after successful authorization.
-S, --full-summary Print a full summary of each signed transaction after

View file

@ -16,6 +16,7 @@ from pathlib import Path
from subprocess import run, PIPE, DEVNULL
from ...obj import MMGenLabel
from ...util import oneshot_warning
def get_device_size(path_or_label):
import re
@ -27,6 +28,12 @@ def get_device_size(path_or_label):
assert m, f'{errmsg}:\n{res[0]}'
return int(m[1])
class warn_ramdisk_too_small(oneshot_warning):
message = 'requested ramdisk size ({}MB) too small, using {}MB instead'
color = 'yellow'
def __init__(self, usr_size, min_size):
oneshot_warning.__init__(self, div=usr_size, fmt_args=[usr_size, min_size])
class RamDiskLabel(MMGenLabel):
max_len = 24
desc = 'ramdisk label'
@ -34,8 +41,12 @@ class RamDiskLabel(MMGenLabel):
class MacOSRamDisk:
desc = 'ramdisk'
min_size = 10 # 10MB is the minimum supported by hdiutil
def __init__(self, cfg, label, size, path=None):
if size < self.min_size:
warn_ramdisk_too_small(size, self.min_size)
size = self.min_size
self.cfg = cfg
self.label = RamDiskLabel(label)
self.size = size # size in MiB
@ -45,16 +56,26 @@ class MacOSRamDisk:
def exists(self):
return self.path.is_mount()
def get_diskutil_size(self):
return get_device_size(self.label) // (2**20)
def create(self, quiet=False):
redir = DEVNULL if quiet else None
if self.exists():
self.cfg._util.qmsg('{} {} [{}] already exists'.format(self.desc, self.label.hl(), self.path))
return
diskutil_size = self.get_diskutil_size()
if diskutil_size != self.size:
self.cfg._util.qmsg(f'Existing ramdisk has incorrect size {diskutil_size}MB, deleting')
self.destroy()
else:
self.cfg._util.qmsg(f'{self.desc.capitalize()} {self.label.hl()} at path {self.path} already exists')
return
self.cfg._util.qmsg(f'Creating {self.desc} {self.label.hl()} of size {self.size}MB')
cp = run(['hdiutil', 'attach', '-nomount', f'ram://{2048 * self.size}'], stdout=PIPE, check=True)
self.dev_name = cp.stdout.decode().strip()
self.cfg._util.qmsg(f'Created {self.desc} {self.label.hl()} [{self.dev_name}]')
run(['diskutil', 'eraseVolume', 'APFS', self.label, self.dev_name], stdout=redir, check=True)
diskutil_size = self.get_diskutil_size()
assert diskutil_size == self.size, 'Reported ramdisk size {diskutil_size}MB is incorrect!'
if self.path != self.dfl_path:
run(['diskutil', 'umount', self.label], stdout=redir, check=True)
self.path.mkdir(parents=True, exist_ok=True)