Browse Source

Remove mixdepthsrc from options, more tests

master
Adam Gibson 3 years ago
parent
commit
d0bf888971
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 12
      jmclient/jmclient/cli_options.py
  2. 25
      jmclient/jmclient/schedule.py
  3. 9
      jmclient/test/test_schedule.py
  4. 33
      scripts/tumbler.py

12
jmclient/jmclient/cli_options.py

@ -275,14 +275,6 @@ def get_tumbler_parser():
' be configured to ask for more address mid-run, giving the user'
' a chance to click `Generate New Deposit Address` on whatever service'
' they are using.')
parser.add_option(
'-m',
'--mixdepthsource',
type='int',
dest='mixdepthsrc',
help=
'Mixing depth to start tumble process from. default=0.',
default=0)
parser.add_option('--restart',
action='store_true',
dest='restart',
@ -398,9 +390,7 @@ def get_tumbler_parser():
type='int',
dest='amtmixdepths',
help='number of mixdepths ever used in wallet, '
'only to be used if mixdepths higher than '
'mixdepthsrc + number of mixdepths to tumble '
'have been used.',
'will soon be deprecated.',
default=-1)
parser.add_option(
'--rounding-chance',

25
jmclient/jmclient/schedule.py

@ -17,6 +17,12 @@ from .support import rand_exp_array, rand_norm_array, rand_weighted_choice
NO_ROUNDING = 16 #max btc significant figures not including LN
class ScheduleGenerationError(Exception):
pass
class ScheduleGenerationErrorNoFunds(ScheduleGenerationError):
pass
def get_schedule(filename):
with open(filename, "rb") as f:
schedule = []
@ -84,15 +90,11 @@ def get_amount_fractions(count):
def get_tumble_schedule(options, destaddrs, mixdepth_balance_dict,
max_mixdepth_in_wallet=4):
"""for the general intent and design of the tumbler algo, see the docs in
joinmarket-org/joinmarket.
Alterations:
Donation removed for now.
"""
Default final setting for "amount_fraction" is zero, for each mixdepth.
This is because we now use a general "schedule" syntax for both tumbler and
any other taker algo; it interprets floats as fractions and integers as satoshis,
and zero as sweep (as before).
This is a modified version of tumbler.py/generate_tumbler_tx()
Args:
* options - as specified in scripts/tumbler.py and taken from cli_options.py
* destaddrs - a list of valid address strings for the destination of funds
@ -136,7 +138,10 @@ def get_tumble_schedule(options, destaddrs, mixdepth_balance_dict,
'rounding': NO_ROUNDING
}
tx_list.append(tx)
lowest_nonempty_mixdepth = min([x for x, y in nonempty_mixdepths.items() if y == 1])
try:
lowest_nonempty_mixdepth = min([x for x, y in nonempty_mixdepths.items() if y == 1])
except ValueError:
raise ScheduleGenerationErrorNoFunds
### stage 2 coinjoins, which create a number of random-amount coinjoins from each mixdepth
for m, txcount in enumerate(txcounts):
if options['mixdepthcount'] - options['addrcount'] <= m and m < \
@ -163,8 +168,8 @@ def get_tumble_schedule(options, destaddrs, mixdepth_balance_dict,
rounding = rand_weighted_choice(len(weight_prob), weight_prob) + 1
tx = {'amount_fraction': amount_fraction,
'wait': round(wait, 2),
'srcmixdepth': (lowest_nonempty_mixdepth + m + options[
'mixdepthsrc']) % (max_mixdepth_in_wallet + 1),
'srcmixdepth': (lowest_nonempty_mixdepth + m) % (
max_mixdepth_in_wallet + 1),
'makercount': makercount,
'destination': 'INTERNAL',
'rounding': rounding
@ -176,8 +181,8 @@ def get_tumble_schedule(options, destaddrs, mixdepth_balance_dict,
addrask = options['addrcount'] - len(destaddrs)
external_dest_addrs = ['addrask'] * addrask + destaddrs[::-1]
for mix_offset in range(options['addrcount']):
srcmix = (lowest_nonempty_mixdepth + options['mixdepthsrc']
+ options['mixdepthcount'] - mix_offset - 1) % (max_mixdepth_in_wallet + 1)
srcmix = (lowest_nonempty_mixdepth + options['mixdepthcount']
- mix_offset - 1) % (max_mixdepth_in_wallet + 1)
for tx in reversed(tx_list):
if tx['srcmixdepth'] == srcmix:
tx['destination'] = external_dest_addrs[mix_offset]

9
jmclient/test/test_schedule.py

@ -54,7 +54,6 @@ class Options(object):
def get_options():
options = Options()
options.mixdepthsrc = 0
options.mixdepthcount = 4
options.txcountparams = (18, 3)
options.minmakercount = 2
@ -90,6 +89,13 @@ def get_options():
"mifCWfmygxKhsP3qM3HZi3ZjBEJu7m39h8",
"mnTn9KVQQT9zy9R4E2ZGzWPK4EfcEcV9Y5"], (3,2), 8,
{2:1, 3: 1}),
#slightly larger version
(["mzzAYbtPpANxpNVGCVBAhZYzrxyZtoix7i",
"mifCWfmygxKhsP3qM3HZi3ZjBEJu7m39h8",
"mnTn9KVQQT9zy9R4E2ZGzWPK4EfcEcV9Y5",
"bcrt1qcnv26w889eum5sekz5h8we45rxnr4sj5k08phv",
"bcrt1qgs0t239gj2kqgnsrvetvsv2qdva8y3j74cta4d"], (4,3), 8,
{0:2, 1: 1, 3: 1, 4: 1}),
])
def test_tumble_schedule(destaddrs, txcparams, mixdepthcount, mixdepthbal):
# note that these tests are currently only leaving the default
@ -97,6 +103,7 @@ def test_tumble_schedule(destaddrs, txcparams, mixdepthcount, mixdepthbal):
# and will fail if this is changed:
wallet_total_mixdepths = 5
options = get_options()
options['addrcount'] = len(destaddrs)
options['mixdepthcount'] = mixdepthcount
options['txcountparams'] = txcparams
schedule = get_tumble_schedule(options, destaddrs, mixdepthbal)

33
scripts/tumbler.py

@ -12,6 +12,8 @@ from jmclient import Taker, load_program_config, get_schedule,\
get_tumble_log, tumbler_taker_finished_update, check_regtest, \
tumbler_filter_orders_callback, validate_address, get_tumbler_parser, \
get_max_cj_fee_values
from jmclient.wallet_utils import DEFAULT_MIXDEPTH
from jmclient.schedule import ScheduleGenerationErrorNoFunds
from jmbase.support import get_log, jmprint, EXIT_SUCCESS, \
EXIT_FAILURE, EXIT_ARGERROR
@ -38,11 +40,17 @@ def main():
#Load the wallet
wallet_name = args[0]
max_mix_depth = options['mixdepthsrc'] + options['mixdepthcount']
if options['amtmixdepths'] > max_mix_depth:
# as of #1324 the concept of a max_mix_depth distinct from
# the normal wallet value (4) no longer applies, since the
# tumbler cycles; but we keep the `amtmixdepths` option for now,
# deprecating it later.
if options['amtmixdepths'] > DEFAULT_MIXDEPTH:
max_mix_depth = options['amtmixdepths']
else:
max_mix_depth = DEFAULT_MIXDEPTH
wallet_path = get_wallet_path(wallet_name, None)
wallet = open_test_wallet_maybe(wallet_path, wallet_name, max_mix_depth, wallet_password_stdin=options_org.wallet_password_stdin)
wallet = open_test_wallet_maybe(wallet_path, wallet_name, max_mix_depth,
wallet_password_stdin=options_org.wallet_password_stdin)
wallet_service = WalletService(wallet)
if wallet_service.rpc_error:
sys.exit(EXIT_FAILURE)
@ -109,8 +117,12 @@ def main():
tumble_log.info("TUMBLE RESTARTING")
else:
#Create a new schedule from scratch
schedule = get_tumble_schedule(options, destaddrs,
wallet.get_balance_by_mixdepth(), wallet_service.mixdepth)
try:
schedule = get_tumble_schedule(options, destaddrs,
wallet.get_balance_by_mixdepth(), wallet_service.mixdepth)
except ScheduleGenerationErrorNoFunds:
jmprint("No funds in wallet to tumble.", "error")
sys.exit(EXIT_FAILURE)
tumble_log.info("TUMBLE STARTING")
with open(os.path.join(logsdir, options['schedulefile']), "wb") as f:
f.write(schedule_to_text(schedule))
@ -133,10 +145,15 @@ def main():
involved_parties = len(schedule) # own participation in each CJ
for item in schedule:
involved_parties += item[2] # number of total tumble counterparties
# calculating total coins that will be included in the tumble;
# in almost all cases all coins (unfrozen) in wallet will be tumbled,
# though it's technically possible with a very small mixdepthcount, to start
# at say m0, and only go through to 2 or 3, such that coins in 4 are untouched
# in phase 2 (after having been swept in phase 1).
used_mixdepths = set()
[used_mixdepths.add(x[0]) for x in schedule]
total_tumble_amount = int(0)
max_mix_to_tumble = min(options['mixdepthsrc']+options['mixdepthcount'], \
max_mix_depth)
for i in range(options['mixdepthsrc'], max_mix_to_tumble):
for i in used_mixdepths:
total_tumble_amount += wallet_service.get_balance_by_mixdepth()[i]
if total_tumble_amount == 0:
raise ValueError("No confirmed coins in the selected mixdepth(s). Quitting")

Loading…
Cancel
Save