Skip to content

Commit

Permalink
mmgen-txcreate: warn user if change address is a used address
Browse files Browse the repository at this point in the history
  • Loading branch information
mmgen committed Nov 16, 2022
1 parent 4b07f8f commit 68caeb3
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 8 deletions.
7 changes: 7 additions & 0 deletions mmgen/tw/addresses.py
Expand Up @@ -242,6 +242,13 @@ async def set_dates(self,addrs):
def dump_fn_pfx(self):
return 'listaddresses' + (f'-minconf-{self.minconf}' if self.minconf else '')

def is_used(self,coinaddr):
for e in self.data:
if e.addr == coinaddr:
return bool(e.recvd)
else: # addr not in tracking wallet
return None

class action(TwView.action):

def s_amt(self,parent):
Expand Down
21 changes: 20 additions & 1 deletion mmgen/tx/new.py
Expand Up @@ -15,7 +15,7 @@
from ..globalvars import *
from ..opts import opt
from .base import Base
from ..color import pink
from ..color import pink,yellow
from ..obj import get_obj,MMGenList
from ..util import msg,qmsg,fmt,die,suf,remove_dups,get_extension
from ..addr import is_mmgen_id,CoinAddr,is_coin_addr
Expand Down Expand Up @@ -235,6 +235,25 @@ async def get_outputs_from_cmdline(self,cmd_args):
self.add_mmaddrs_to_outputs(ad_w,ad_f)
self.check_dup_addrs('outputs')

chg_idx = self.get_chg_output_idx()
if chg_idx is not None:
await self.warn_chg_addr_used(self.outputs[chg_idx])

async def warn_chg_addr_used(self,chg):
from ..tw.addresses import TwAddresses
if (await TwAddresses(self.proto,get_data=True)).is_used(chg.addr):
from ..ui import keypress_confirm
if not keypress_confirm(
'{a} {b} {c}\n{d}'.format(
a = yellow(f'Requested change address'),
b = (chg.mmid or chg.addr).hl(),
c = yellow('is already used!'),
d = yellow('Address reuse harms your privacy and security. Continue anyway? (y/N): ')
),
complete_prompt = True,
default_yes = False ):
die(1,'Exiting at user request')

# inputs methods
def select_unspent(self,unspent):
prompt = 'Enter a range or space-separated list of outputs to spend: '
Expand Down
12 changes: 12 additions & 0 deletions test/overlay/fakemods/mmgen/tx/new.py
@@ -0,0 +1,12 @@
import os as overlay_fake_os
from .new_orig import *

if overlay_fake_os.getenv('MMGEN_BOGUS_UNSPENT_DATA'):

class overlay_fake_data:

async def warn_chg_addr_used(foo,us):
from ..util import ymsg
ymsg('Bogus unspent data: skipping change address is used check')

New.warn_chg_addr_used = overlay_fake_data.warn_chg_addr_used
20 changes: 14 additions & 6 deletions test/test_py_d/ts_regtest.py
Expand Up @@ -638,9 +638,13 @@ def bob_subwallet_fund(self):
sid1 = self._get_user_subsid('bob','29L')
sid2 = self._get_user_subsid('bob','127S')
chg_addr = self._user_sid('bob') + (':B:1',':L:1')[self.proto.coin=='BCH']
outputs_cl = [sid1+':C:2,0.29',sid2+':C:3,0.127',chg_addr]
inputs = ('3','1')[self.proto.coin=='BCH']
return self.user_txdo('bob',rtFee[1],outputs_cl,inputs,extra_args=['--subseeds=127'])
return self.user_txdo(
user = 'bob',
fee = rtFee[1],
outputs_cl = [sid1+':C:2,0.29',sid2+':C:3,0.127',chg_addr],
outputs_list = ('3','1')[self.proto.coin=='BCH'],
extra_args = ['--subseeds=127'],
used_chg_addr_resp = (None,'y')[self.proto.coin=='BCH'] )

def bob_twview2(self):
sid1 = self._get_user_subsid('bob','29L')
Expand Down Expand Up @@ -779,7 +783,8 @@ def user_txdo( self, user, fee, outputs_cl, outputs_list,
bad_locktime = False,
full_tx_view = False,
menu = ['M'],
skip_passphrase = False ):
skip_passphrase = False,
used_chg_addr_resp = None ):

t = self.spawn('mmgen-txdo',
['-d',self.tmpdir,'-B','--'+user] +
Expand All @@ -793,7 +798,9 @@ def user_txdo( self, user, fee, outputs_cl, outputs_list,
file_desc = 'Signed transaction',
interactive_fee = (tx_fee,'')[bool(fee)],
add_comment = tx_comment_jp,
view = 't',save=True)
view = 't',
save = True,
used_chg_addr_resp = used_chg_addr_resp )

if not skip_passphrase:
t.passphrase(dfl_wcls.desc,rt_pw)
Expand Down Expand Up @@ -848,7 +855,8 @@ def bob_send_maybe_rbf(self):
outputs_cl = self._create_tx_outputs('alice',(('L',1,',60'),('C',1,',40'))) # alice_sid:L:1, alice_sid:C:1
outputs_cl += [self._user_sid('bob')+':'+rtBobOp3]
return self.user_txdo('bob',rtFee[1],outputs_cl,'3',
extra_args=([],['--rbf'])[self.proto.cap('rbf')])
extra_args = ([],['--rbf'])[self.proto.cap('rbf')],
used_chg_addr_resp = 'y' )

def bob_send_non_mmgen(self):
outputs_cl = self._create_tx_outputs('alice',(
Expand Down
7 changes: 6 additions & 1 deletion test/test_py_d/ts_shared.py
Expand Up @@ -46,13 +46,18 @@ def txcreate_ui_common(self,t,
add_comment = '',
view = 't',
save = True,
tweaks = [] ):
tweaks = [],
used_chg_addr_resp = None ):

txdo = (caller or self.test_name)[:4] == 'txdo'

expect_pat = r'\[q\]uit view, .*?:.'
delete_pat = r'Enter account number .*:.'
confirm_pat = r'Is this what you want.*:.'

if used_chg_addr_resp is not None:
t.expect('reuse harms your privacy.*:.*',used_chg_addr_resp,regex=True)

pat = expect_pat
for choice in menu + ['q']:
t.expect(pat,choice,regex=True)
Expand Down

0 comments on commit 68caeb3

Please sign in to comment.