Browse Source

Merge #1035: Rename yield generator's txfee settings to txfee_contribution

c2729c0 fix typo (Kristaps Kaupe)
a542680 Rename yield generator's txfee settings to txfee_contribution (Kristaps Kaupe)
master
Adam Gibson 4 years ago
parent
commit
ebd04648a9
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 4
      docs/YIELDGENERATOR.md
  2. 4
      jmclient/jmclient/configure.py
  3. 43
      jmclient/jmclient/yieldgenerator.py
  4. 34
      jmclient/test/test_yieldgenerator.py
  5. 15
      scripts/yg-privacyenhanced.py
  6. 15
      test/ygrunner.py

4
docs/YIELDGENERATOR.md

@ -36,10 +36,10 @@ Open the configuration file `joinmarket.cfg` and edit the `[YIELDGENERATOR]` sec
cjfee_factor = 0.1 cjfee_factor = 0.1
# [satoshis, any integer] / the average transaction fee you're adding to coinjoin transactions # [satoshis, any integer] / the average transaction fee you're adding to coinjoin transactions
txfee = 100 txfee_contribution = 100
# [fraction, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200 # [fraction, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200
txfee_factor = 0.3 txfee_contribution_factor = 0.3
# [satoshis, any integer] / minimum size of your cj offer. Lower cj amounts will be disregarded # [satoshis, any integer] / minimum size of your cj offer. Lower cj amounts will be disregarded
minsize = 100000 minsize = 100000

4
jmclient/jmclient/configure.py

@ -410,10 +410,10 @@ cjfee_r = 0.00002
cjfee_factor = 0.1 cjfee_factor = 0.1
# [satoshis, any integer] / the average transaction fee you're adding to coinjoin transactions # [satoshis, any integer] / the average transaction fee you're adding to coinjoin transactions
txfee = 100 txfee_contribution = 100
# [fraction, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200 # [fraction, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200
txfee_factor = 0.3 txfee_contribution_factor = 0.3
# [satoshis, any integer] / minimum size of your cj offer. Lower cj amounts will be disregarded # [satoshis, any integer] / minimum size of your cj offer. Lower cj amounts will be disregarded
minsize = 100000 minsize = 100000

43
jmclient/jmclient/yieldgenerator.py

@ -83,10 +83,10 @@ class YieldGeneratorBasic(YieldGenerator):
thus is somewhat suboptimal in giving more information to spies. thus is somewhat suboptimal in giving more information to spies.
""" """
def __init__(self, wallet_service, offerconfig): def __init__(self, wallet_service, offerconfig):
#note the randomizing entries are ignored in this base class: # note the randomizing entries are ignored in this base class:
self.txfee_contribution, self.cjfee_a, self.cjfee_r, self.ordertype,\
self.txfee, self.cjfee_a, self.cjfee_r, self.ordertype, self.minsize, \ self.minsize, self.txfee_contribution_factor, self.cjfee_factor,\
self.txfee_factor, self.cjfee_factor, self.size_factor = offerconfig self.size_factor = offerconfig
super().__init__(wallet_service) super().__init__(wallet_service)
@ -103,16 +103,16 @@ class YieldGeneratorBasic(YieldGenerator):
f = self.cjfee_r f = self.cjfee_r
#minimum size bumped if necessary such that you always profit #minimum size bumped if necessary such that you always profit
#least 50% of the miner fee #least 50% of the miner fee
self.minsize = max(int(1.5 * self.txfee / float(self.cjfee_r)), self.minsize = max(int(1.5 * self.txfee_contribution /
self.minsize) float(self.cjfee_r)), self.minsize)
elif self.ordertype in ('absoffer', 'swabsoffer', 'sw0absoffer'): elif self.ordertype in ('absoffer', 'swabsoffer', 'sw0absoffer'):
f = str(self.txfee + self.cjfee_a) f = str(self.txfee_contribution + self.cjfee_a)
order = {'oid': 0, order = {'oid': 0,
'ordertype': self.ordertype, 'ordertype': self.ordertype,
'minsize': self.minsize, 'minsize': self.minsize,
'maxsize': mix_balance[max_mix] - max( 'maxsize': mix_balance[max_mix] - max(
jm_single().DUST_THRESHOLD, self.txfee), jm_single().DUST_THRESHOLD, self.txfee_contribution),
'txfee': self.txfee, 'txfee': self.txfee_contribution,
'cjfee': f} 'cjfee': f}
# sanity check # sanity check
@ -362,11 +362,11 @@ def ygmain(ygclass, nickserv_password='', gaplimit=6):
parser.add_option('-o', '--ordertype', action='store', type='string', parser.add_option('-o', '--ordertype', action='store', type='string',
dest='ordertype', default=None, dest='ordertype', default=None,
help='type of order; can be either reloffer or absoffer') help='type of order; can be either reloffer or absoffer')
parser.add_option('-t', '--txfee', action='store', type='int', parser.add_option('-t', '--txfee-contribution', action='store', type='int',
dest='txfee', default=None, dest='txfee_contribution', default=None,
help='the average transaction fee contribution you\'re adding to coinjoin transactions') help='the average transaction fee contribution you\'re adding to coinjoin transactions')
parser.add_option('-f', '--txfee-factor', action='store', type='float', parser.add_option('-f', '--txfee-contribution-factor', action='store', type='float',
dest='txfee_factor', default=None, dest='txfee_contribution_factor', default=None,
help='variance around the average transaction fee contribution, decimal fraction') help='variance around the average transaction fee contribution, decimal fraction')
parser.add_option('-a', '--cjfee-a', action='store', type='string', parser.add_option('-a', '--cjfee-a', action='store', type='string',
dest='cjfee_a', default=None, dest='cjfee_a', default=None,
@ -402,21 +402,22 @@ def ygmain(ygclass, nickserv_password='', gaplimit=6):
load_program_config(config_path=options["datadir"]) load_program_config(config_path=options["datadir"])
# As per previous note, override non-default command line settings: # As per previous note, override non-default command line settings:
for x in ["ordertype", "txfee", "txfee_factor", "cjfee_a", "cjfee_r", for x in ["ordertype", "txfee_contribution", "txfee_contribution_factor",
"cjfee_factor", "minsize", "size_factor"]: "cjfee_a", "cjfee_r", "cjfee_factor", "minsize", "size_factor"]:
if options[x] is None: if options[x] is None:
options[x] = jm_single().config.get("YIELDGENERATOR", x) options[x] = jm_single().config.get("YIELDGENERATOR", x)
wallet_name = args[0] wallet_name = args[0]
ordertype = options["ordertype"] ordertype = options["ordertype"]
txfee = int(options["txfee"]) txfee_contribution = int(options["txfee_contribution"])
txfee_factor = float(options["txfee_factor"]) txfee_contribution_factor = float(options["txfee_contribution_factor"])
cjfee_factor = float(options["cjfee_factor"]) cjfee_factor = float(options["cjfee_factor"])
size_factor = float(options["size_factor"]) size_factor = float(options["size_factor"])
if ordertype == 'reloffer': if ordertype == 'reloffer':
cjfee_r = options["cjfee_r"] cjfee_r = options["cjfee_r"]
# minimum size is such that you always net profit at least 20% # minimum size is such that you always net profit at least 20%
#of the miner fee #of the miner fee
minsize = max(int(1.2 * txfee / float(cjfee_r)), int(options["minsize"])) minsize = max(int(1.2 * txfee_contribution / float(cjfee_r)),
int(options["minsize"]))
cjfee_a = None cjfee_a = None
elif ordertype == 'absoffer': elif ordertype == 'absoffer':
cjfee_a = int(options["cjfee_a"]) cjfee_a = int(options["cjfee_a"])
@ -458,9 +459,9 @@ def ygmain(ygclass, nickserv_password='', gaplimit=6):
ordertype = prefix + ordertype ordertype = prefix + ordertype
jlog.debug("Set the offer type string to: " + ordertype) jlog.debug("Set the offer type string to: " + ordertype)
maker = ygclass(wallet_service, [txfee, cjfee_a, cjfee_r, maker = ygclass(wallet_service,
ordertype, minsize, txfee_factor, [txfee_contribution, cjfee_a, cjfee_r, ordertype, minsize,
cjfee_factor, size_factor]) txfee_contribution_factor, cjfee_factor, size_factor])
jlog.info('starting yield generator') jlog.info('starting yield generator')
clientfactory = JMClientProtocolFactory(maker, proto_type="MAKER") clientfactory = JMClientProtocolFactory(maker, proto_type="MAKER")
if jm_single().config.get("SNICKER", "enabled") == "true": if jm_single().config.get("SNICKER", "enabled") == "true":

34
jmclient/test/test_yieldgenerator.py

@ -42,14 +42,15 @@ class CustomUtxoWallet(SegwitLegacyWallet):
assert self.get_addr_mixdepth(u['address']) == expected assert self.get_addr_mixdepth(u['address']) == expected
def create_yg_basic(balances, txfee=0, cjfee_a=0, cjfee_r=0, def create_yg_basic(balances, txfee_contribution=0, cjfee_a=0, cjfee_r=0,
ordertype='swabsoffer', minsize=0): ordertype='swabsoffer', minsize=0):
"""Constructs a YieldGeneratorBasic instance with a fake wallet. The """Constructs a YieldGeneratorBasic instance with a fake wallet. The
wallet will have the given balances at mixdepths, and the offer params wallet will have the given balances at mixdepths, and the offer params
will be set as given here.""" will be set as given here."""
wallet = CustomUtxoWallet(balances) wallet = CustomUtxoWallet(balances)
offerconfig = (txfee, cjfee_a, cjfee_r, ordertype, minsize, None, None, None) offerconfig = (txfee_contribution, cjfee_a, cjfee_r, ordertype, minsize,
None, None, None)
yg = YieldGeneratorBasic(WalletService(wallet), offerconfig) yg = YieldGeneratorBasic(WalletService(wallet), offerconfig)
@ -71,8 +72,8 @@ class CreateMyOrdersTests(unittest.TestCase):
def test_abs_fee(self): def test_abs_fee(self):
jm_single().DUST_THRESHOLD = 10 jm_single().DUST_THRESHOLD = 10
yg = create_yg_basic([0, 2000000, 1000000], txfee=1000, cjfee_a=10, yg = create_yg_basic([0, 2000000, 1000000], txfee_contribution=1000,
ordertype='swabsoffer', minsize=100000) cjfee_a=10, ordertype='swabsoffer', minsize=100000)
self.assertEqual(yg.create_my_orders(), [ self.assertEqual(yg.create_my_orders(), [
{'oid': 0, {'oid': 0,
'ordertype': 'swabsoffer', 'ordertype': 'swabsoffer',
@ -84,8 +85,8 @@ class CreateMyOrdersTests(unittest.TestCase):
def test_rel_fee(self): def test_rel_fee(self):
jm_single().DUST_THRESHOLD = 10 jm_single().DUST_THRESHOLD = 10
yg = create_yg_basic([0, 2000000, 1000000], txfee=1000, cjfee_r=0.1, yg = create_yg_basic([0, 2000000, 1000000], txfee_contribution=1000,
ordertype='sw0reloffer', minsize=10) cjfee_r=0.1, ordertype='sw0reloffer', minsize=10)
self.assertEqual(yg.create_my_orders(), [ self.assertEqual(yg.create_my_orders(), [
{'oid': 0, {'oid': 0,
'ordertype': 'sw0reloffer', 'ordertype': 'sw0reloffer',
@ -97,8 +98,8 @@ class CreateMyOrdersTests(unittest.TestCase):
def test_dust_threshold(self): def test_dust_threshold(self):
jm_single().DUST_THRESHOLD = 1000 jm_single().DUST_THRESHOLD = 1000
yg = create_yg_basic([0, 2000000, 1000000], txfee=10, cjfee_a=10, yg = create_yg_basic([0, 2000000, 1000000], txfee_contribution=10,
ordertype='swabsoffer', minsize=100000) cjfee_a=10, ordertype='swabsoffer', minsize=100000)
self.assertEqual(yg.create_my_orders(), [ self.assertEqual(yg.create_my_orders(), [
{'oid': 0, {'oid': 0,
'ordertype': 'swabsoffer', 'ordertype': 'swabsoffer',
@ -110,8 +111,8 @@ class CreateMyOrdersTests(unittest.TestCase):
def test_minsize_above_maxsize(self): def test_minsize_above_maxsize(self):
jm_single().DUST_THRESHOLD = 10 jm_single().DUST_THRESHOLD = 10
yg = create_yg_basic([0, 20000, 10000], txfee=1000, cjfee_a=10, yg = create_yg_basic([0, 20000, 10000], txfee_contribution=1000,
ordertype='swabsoffer', minsize=100000) cjfee_a=10, ordertype='swabsoffer', minsize=100000)
self.assertEqual(yg.create_my_orders(), []) self.assertEqual(yg.create_my_orders(), [])
@ -121,13 +122,13 @@ class OidToOrderTests(unittest.TestCase):
def call_oid_to_order(self, yg, amount): def call_oid_to_order(self, yg, amount):
"""Calls oid_to_order on the given yg instance. It passes the """Calls oid_to_order on the given yg instance. It passes the
txfee and abs fee from yg as offer.""" txfee and abs fee from yg as offer."""
offer = {'txfee': yg.txfee, offer = {'txfee': yg.txfee_contribution,
'cjfee': str(yg.cjfee_a), 'cjfee': str(yg.cjfee_a),
'ordertype': 'swabsoffer'} 'ordertype': 'swabsoffer'}
return yg.oid_to_order(offer, amount) return yg.oid_to_order(offer, amount)
def test_not_enough_balance(self): def test_not_enough_balance(self):
yg = create_yg_basic([100], txfee=0, cjfee_a=10) yg = create_yg_basic([100], txfee_contribution=0, cjfee_a=10)
self.assertEqual(self.call_oid_to_order(yg, 1000), (None, None, None)) self.assertEqual(self.call_oid_to_order(yg, 1000), (None, None, None))
def test_chooses_single_utxo(self): def test_chooses_single_utxo(self):
@ -144,7 +145,8 @@ class OidToOrderTests(unittest.TestCase):
# right at the dust threshold. The wallet won't be able to find # right at the dust threshold. The wallet won't be able to find
# any extra inputs, though. # any extra inputs, though.
jm_single().DUST_THRESHOLD = 410 jm_single().DUST_THRESHOLD = 410
yg = create_yg_basic([10, 1000, 10], txfee=100, cjfee_a=10) yg = create_yg_basic([10, 1000, 10], txfee_contribution=100,
cjfee_a=10)
self.assertEqual(self.call_oid_to_order(yg, 500), (None, None, None)) self.assertEqual(self.call_oid_to_order(yg, 500), (None, None, None))
def test_extra_with_dust_threshold(self): def test_extra_with_dust_threshold(self):
@ -152,7 +154,8 @@ class OidToOrderTests(unittest.TestCase):
# need to include the extra_utxo from the wallet as well to get # need to include the extra_utxo from the wallet as well to get
# over the threshold. # over the threshold.
jm_single().DUST_THRESHOLD = 410 jm_single().DUST_THRESHOLD = 410
yg = create_yg_basic([10, 1000, 10], txfee=100, cjfee_a=10) yg = create_yg_basic([10, 1000, 10], txfee_contribution=100,
cjfee_a=10)
yg.wallet_service.wallet.add_utxo_at_mixdepth(1, 500) yg.wallet_service.wallet.add_utxo_at_mixdepth(1, 500)
utxos, cj_addr, change_addr = self.call_oid_to_order(yg, 500) utxos, cj_addr, change_addr = self.call_oid_to_order(yg, 500)
self.assertEqual(len(utxos), 2) self.assertEqual(len(utxos), 2)
@ -172,7 +175,8 @@ class OfferReannouncementTests(unittest.TestCase):
"""Constructs a fake yg instance that has an offer with the given """Constructs a fake yg instance that has an offer with the given
maxsize. Returns it together with the offer.""" maxsize. Returns it together with the offer."""
jm_single().DUST_THRESHOLD = 10 jm_single().DUST_THRESHOLD = 10
yg = create_yg_basic([100 + maxsize], txfee=100, ordertype='swabsoffer') yg = create_yg_basic([100 + maxsize], txfee_contribution=100,
ordertype='swabsoffer')
offers = yg.create_my_orders() offers = yg.create_my_orders()
self.assertEqual(len(offers), 1) self.assertEqual(len(offers), 1)
self.assertEqual(offers[0]['maxsize'], maxsize) self.assertEqual(offers[0]['maxsize'], maxsize)

15
scripts/yg-privacyenhanced.py

@ -53,21 +53,24 @@ class YieldGeneratorPrivacyEnhanced(YieldGeneratorBasic):
if self.ordertype in ['swreloffer', 'sw0reloffer']: if self.ordertype in ['swreloffer', 'sw0reloffer']:
f = self.cjfee_r f = self.cjfee_r
elif self.ordertype in ['swabsoffer', 'sw0absoffer']: elif self.ordertype in ['swabsoffer', 'sw0absoffer']:
f = str(self.txfee + self.cjfee_a) f = str(self.txfee_contribution + self.cjfee_a)
mix_balance = dict([(m, b) for m, b in iteritems(mix_balance) mix_balance = dict([(m, b) for m, b in iteritems(mix_balance)
if b > self.minsize]) if b > self.minsize])
if len(mix_balance) == 0: if len(mix_balance) == 0:
jlog.error('You do not have the minimum required amount of coins' jlog.error('You do not have the minimum required amount of coins'
' to be a maker: ' + str(self.minsize) + \ ' to be a maker: ' + str(self.minsize) + \
'\nTry setting txfee to zero and/or lowering the minsize.') '\nTry setting txfee_contribution to zero and/or '
'lowering the minsize.')
return [] return []
max_mix = max(mix_balance, key=mix_balance.get) max_mix = max(mix_balance, key=mix_balance.get)
# randomizing the different values # randomizing the different values
randomize_txfee = int(random.uniform(self.txfee * (1 - float(self.txfee_factor)), randomize_txfee = int(random.uniform(
self.txfee * (1 + float(self.txfee_factor)))) self.txfee_contribution * (1 - float(self.txfee_contribution_factor)),
randomize_minsize = int(random.uniform(self.minsize * (1 - float(self.size_factor)), self.txfee_contribution * (1 + float(self.txfee_contribution_factor))))
self.minsize * (1 + float(self.size_factor)))) randomize_minsize = int(random.uniform(
self.minsize * (1 - float(self.size_factor)),
self.minsize * (1 + float(self.size_factor))))
if randomize_minsize < jm_single().DUST_THRESHOLD: if randomize_minsize < jm_single().DUST_THRESHOLD:
jlog.warn("Minsize was randomized to below dust; resetting to dust " jlog.warn("Minsize was randomized to below dust; resetting to dust "
"threshold: " + amount_to_str(jm_single().DUST_THRESHOLD)) "threshold: " + amount_to_str(jm_single().DUST_THRESHOLD))

15
test/ygrunner.py

@ -134,19 +134,20 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, fb_indices,
# As per previous note, override non-default command line settings: # As per previous note, override non-default command line settings:
options = {} options = {}
for x in ["ordertype", "txfee", "txfee_factor", "cjfee_a", "cjfee_r", for x in ["ordertype", "txfee_contribution", "txfee_contribution_factor",
"cjfee_factor", "minsize", "size_factor"]: "cjfee_a", "cjfee_r", "cjfee_factor", "minsize", "size_factor"]:
options[x] = jm_single().config.get("YIELDGENERATOR", x) options[x] = jm_single().config.get("YIELDGENERATOR", x)
ordertype = options["ordertype"] ordertype = options["ordertype"]
txfee = int(options["txfee"]) txfee_contribution = int(options["txfee_contribution"])
txfee_factor = float(options["txfee_factor"]) txfee_contribution_factor = float(options["txfee_contribution_factor"])
cjfee_factor = float(options["cjfee_factor"]) cjfee_factor = float(options["cjfee_factor"])
size_factor = float(options["size_factor"]) size_factor = float(options["size_factor"])
if ordertype == 'reloffer': if ordertype == 'reloffer':
cjfee_r = options["cjfee_r"] cjfee_r = options["cjfee_r"]
# minimum size is such that you always net profit at least 20% # minimum size is such that you always net profit at least 20%
#of the miner fee #of the miner fee
minsize = max(int(1.2 * txfee / float(cjfee_r)), int(options["minsize"])) minsize = max(int(1.2 * txfee_contribution / float(cjfee_r)),
int(options["minsize"]))
cjfee_a = None cjfee_a = None
elif ordertype == 'absoffer': elif ordertype == 'absoffer':
cjfee_a = int(options["cjfee_a"]) cjfee_a = int(options["cjfee_a"])
@ -173,8 +174,8 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, fb_indices,
else: else:
ygclass = MaliciousYieldGenerator ygclass = MaliciousYieldGenerator
for i in range(num_ygs): for i in range(num_ygs):
cfg = [txfee, cjfee_a, cjfee_r, ordertype, minsize, txfee_factor, cfg = [txfee_contribution, cjfee_a, cjfee_r, ordertype, minsize,
cjfee_factor, size_factor] txfee_contribution_factor, cjfee_factor, size_factor]
wallet_service_yg = wallet_services[i]["wallet"] wallet_service_yg = wallet_services[i]["wallet"]
wallet_service_yg.startService() wallet_service_yg.startService()

Loading…
Cancel
Save