Skip to content

Commit 17c79f1

Browse files
committed
Merge #1253: Change defaults for fidelity bond settings.
044bef6 Change default fidelity bond exponent settings. (Adam Gibson)
2 parents 930c25f + 044bef6 commit 17c79f1

File tree

4 files changed

+34
-14
lines changed

4 files changed

+34
-14
lines changed

docs/fidelity-bonds.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ high enough (or if you think the sybil protection is too expensive then set the
4545
lower, as always its your choice as a taker in the market).
4646

4747
Takers will still choose makers equally (i.e. without taking into account fidelity bonds) with a
48-
small probability. By default this probability is 12.5%, so approximately 1-in-8 makers. This can
48+
small probability. By default this probability is currently 12.5%, so approximately 1-in-8 makers. This can
4949
be changed in the config file with the option `bondless_makers_allowance`.
5050

5151
The previous algorithm for choosing makers without regards to fidelity bonds can still be used by
@@ -179,12 +179,14 @@ JoinMarket itself.
179179
A fidelity bond is valuable as soon as the transaction creating it becomes confirmed. The
180180
simplified formula for a fidelity bond's value is:
181181

182-
bond_value = (locked_coins * (exp(interest_rate * locktime) - 1))^2
182+
bond_value = (locked_coins * (exp(interest_rate * locktime) - 1))^x
183+
184+
Here `x` is the 'exponent', a number larger than 1, for reasons we explain below.
183185

184186
A few important things to notice:
185-
* The bond value goes as the _square_ of sacrificed value. For example if your sacrificed value is
186-
5 BTC then the fidelity bond value is 25 (because 5 x 5 = 25). If instead you sacrificed 6 BTC the
187-
value is 36 (because 6 x 6 = 36). The point of this is to create an incentive for makers to lump
187+
* The bond value goes as the (locked_coins)^x of sacrificed value. For example if `x` is 1.3, the current default, and your sacrificed value is
188+
5 BTC then the fidelity bond value is \~ 8.1. If instead you sacrificed 6 BTC the
189+
value is \~ 10.3. The point of this is to create an incentive for makers to lump
188190
all their coins into just one bot rather than spreading it over many bots. It makes a sybil attack
189191
much more expensive.
190192
* The longer you lock for the greater the value. The value increases as the `interest_rate`, which
@@ -193,9 +195,9 @@ annum and because of tyranny-of-the-default takers are unlikely to change it. Th
193195
not too far from the "real" interest rate, and the system still works fine even if the real rate
194196
is something like 3% or 0.1%.
195197
* The above formula would suggest that if you lock 3 BTC for 10000 years you get a fidelity
196-
bond worth `1.7481837557171304e+131` (17 followed by 130 zeros). This does not happen because the
198+
bond worth `2.03e+85` (\~ 2 followed by 85 zeros). This does not happen because the
197199
sacrificed value is capped at the value of the burned coins. So in this example the fidelity bond
198-
value would be just 9 (equal to 3x3 or 3 squared). This feature is not included in the above
200+
value would be just \~ 4.17. This feature is not included in the above
199201
simplified equation.
200202
* After the locktime expires and the coins are free to move, the fidelity bond will continue to be
201203
valuable, but its value will exponentially drop following the interest rate. So it would be good
@@ -210,8 +212,8 @@ At any time you can use the orderbook watcher script to see your own fidelity bo
210212

211213
Consider also the [warning on the bitcoin wiki page on timelocks](https://en.bitcoin.it/wiki/Timelock#Far-future_locks).
212214

213-
I would recommend locking as many bitcoins as you are comfortable with for a period of between 6
214-
months and 2 years. Perhaps at the very start lock for only 1 month or 2 months(?) It's a
215+
I would recommend locking as many bitcoins as you are comfortable with for a period of between 3
216+
months and 1 years. Perhaps at the very start lock for only 1 month or 2 months(?) It's a
215217
marketplace and the rules are known to all, so ultimately you'll have to make your own decision.
216218

217219
### Can my yield-generator use multiple timelocked addresses or UTXO?

jmclient/jmclient/configure.py

+5
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,11 @@ def jm_single():
386386
# A real number, i.e. 1 = 100%, 0.125 = 1/8 = 1 in every 8 makers on average will be bondless
387387
bondless_makers_allowance = """ + _DEFAULT_BONDLESS_MAKERS_ALLOWANCE + """
388388
389+
# To (strongly) disincentivize Sybil behaviour, the value assessment of the bond
390+
# is based on the (time value of the bond)^x where x is the bond_value_exponent here,
391+
# where x > 1. It is a real number (so written as a decimal).
392+
bond_value_exponent = 1.3
393+
389394
##############################
390395
# THE FOLLOWING SETTINGS ARE REQUIRED TO DEFEND AGAINST SNOOPERS.
391396
# DON'T ALTER THEM UNLESS YOU UNDERSTAND THE IMPLICATIONS.

jmclient/jmclient/wallet.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2557,7 +2557,8 @@ def calculate_timelocked_fidelity_bond_value(cls, utxo_value, confirmation_time,
25572557
t = current_time / YEAR
25582558

25592559
a = max(0, min(1, exp(r*T) - 1) - min(1, exp(r*max(0, t-L)) - 1))
2560-
return utxo_value*utxo_value*a*a
2560+
exponent = float(jm_single().config.get("POLICY", "bond_value_exponent"))
2561+
return pow(utxo_value*a, exponent)
25612562

25622563
@classmethod
25632564
def get_validated_timelocked_fidelity_bond_utxo(cls, utxo, utxo_pubkey, locktime,

scripts/obwatch/ob-watcher.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import jmbitcoin as btc
5252
from jmdaemon.protocol import *
5353

54+
bond_exponent = None
55+
5456
#Initial state: allow only SW offer types
5557
sw0offers = list(filter(lambda x: x[0:3] == 'sw0', offername_list))
5658
swoffers = list(filter(lambda x: x[0:3] == 'swa' or x[0:3] == 'swr', offername_list))
@@ -115,15 +117,15 @@ def create_offerbook_table_heading(btc_unit, rel_unit):
115117
col.format('txfee', 'Miner Fee Contribution / ' + btc_unit),
116118
col.format('minsize', 'Minimum Size / ' + btc_unit),
117119
col.format('maxsize', 'Maximum Size / ' + btc_unit),
118-
col.format('bondvalue', 'Bond value / ' + btc_unit + '²')
120+
col.format('bondvalue', 'Bond value / ' + btc_unit + '<sup>' + bond_exponent + '</sup>')
119121
]) + ' </tr>'
120122
return tableheading
121123

122124
def create_bonds_table_heading(btc_unit):
123125
tableheading = ('<table class="tftable sortable" border="1"><tr>'
124126
+ '<th>Counterparty</th>'
125127
+ '<th>UTXO</th>'
126-
+ '<th>Bond value / ' + btc_unit + '&#xb2;</th>'
128+
+ '<th>Bond value / ' + btc_unit + '<sup>' + bond_exponent + '</sup></th>'
127129
+ '<th>Locktime</th>'
128130
+ '<th>Locked coins / ' + btc_unit + '</th>'
129131
+ '<th>Confirmation time</th>'
@@ -419,7 +421,8 @@ def create_sybil_resistance_page(self, btc_unit):
419421
+ "how much would a sybil attacker starting now have to sacrifice to succeed in their"
420422
+ " attack with 95% probability. Honest weight="
421423
+ satoshi_to_unit_power(honest_weight, 2*unit_to_power[btc_unit]) + " " + btc_unit
422-
+ "&#xb2;<br/>Also assumes that takers are not price-sensitive and that their max "
424+
+ "<sup>" + bond_exponent + "</sup><br/>Also assumes that takers "
425+
+ "are not price-sensitive and that their max "
423426
+ "coinjoin fee is configured high enough that they dont exclude any makers.")
424427
heading2 = "Sybil attacks from external enemies."
425428

@@ -459,7 +462,7 @@ def create_sybil_resistance_page(self, btc_unit):
459462
mainbody += ('<table class="tftable" border="1"><tr>'
460463
+ '<th>Maker count</th>'
461464
+ '<th>Success probability</th>'
462-
+ '<th>Foregone value / ' + btc_unit + '&#xb2;</th>'
465+
+ '<th>Foregone value / ' + btc_unit + '<sup>' + bond_exponent + '</sup></th>'
463466
+ '</tr>'
464467
)
465468

@@ -784,6 +787,7 @@ def get_dummy_nick():
784787
return nick
785788

786789
def main():
790+
global bond_exponent
787791
parser = OptionParser(
788792
usage='usage: %prog [options]',
789793
description='Runs a webservice which shows the orderbook.')
@@ -804,6 +808,14 @@ def main():
804808
default=62601)
805809
(options, args) = parser.parse_args()
806810
load_program_config(config_path=options.datadir)
811+
# needed to display notional units of FB valuation
812+
bond_exponent = jm_single().config.get("POLICY", "bond_value_exponent")
813+
try:
814+
float(bond_exponent)
815+
except ValueError:
816+
log.error("Invalid entry for bond_value_exponent, should be decimal "
817+
"number: {}".format(bond_exponent))
818+
sys.exit(EXIT_FAILURE)
807819
check_and_start_tor()
808820
hostport = (options.host, options.port)
809821
mcs = []

0 commit comments

Comments
 (0)