mirror of
https://github.com/JoinMarket-Org/joinmarket-clientserver.git
synced 2026-08-20 13:37:23 +02:00
Change default fidelity bond exponent settings.
Closes #1247. This consists of an inclusion of the bond value exponent into the config that the user can alter, and a change of that from 2 to default 1.3. Also updates the fidelity bond documentation to account for those changes, including the units used in ob-watcher, but not the calculation of fidelity bond attack resistance (which remains a TODO).
This commit is contained in:
parent
e7ff098887
commit
044bef6fff
4 changed files with 34 additions and 14 deletions
|
|
@ -45,7 +45,7 @@ high enough (or if you think the sybil protection is too expensive then set the
|
|||
lower, as always its your choice as a taker in the market).
|
||||
|
||||
Takers will still choose makers equally (i.e. without taking into account fidelity bonds) with a
|
||||
small probability. By default this probability is 12.5%, so approximately 1-in-8 makers. This can
|
||||
small probability. By default this probability is currently 12.5%, so approximately 1-in-8 makers. This can
|
||||
be changed in the config file with the option `bondless_makers_allowance`.
|
||||
|
||||
The previous algorithm for choosing makers without regards to fidelity bonds can still be used by
|
||||
|
|
@ -179,12 +179,14 @@ JoinMarket itself.
|
|||
A fidelity bond is valuable as soon as the transaction creating it becomes confirmed. The
|
||||
simplified formula for a fidelity bond's value is:
|
||||
|
||||
bond_value = (locked_coins * (exp(interest_rate * locktime) - 1))^2
|
||||
bond_value = (locked_coins * (exp(interest_rate * locktime) - 1))^x
|
||||
|
||||
Here `x` is the 'exponent', a number larger than 1, for reasons we explain below.
|
||||
|
||||
A few important things to notice:
|
||||
* The bond value goes as the _square_ of sacrificed value. For example if your sacrificed value is
|
||||
5 BTC then the fidelity bond value is 25 (because 5 x 5 = 25). If instead you sacrificed 6 BTC the
|
||||
value is 36 (because 6 x 6 = 36). The point of this is to create an incentive for makers to lump
|
||||
* 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
|
||||
5 BTC then the fidelity bond value is \~ 8.1. If instead you sacrificed 6 BTC the
|
||||
value is \~ 10.3. The point of this is to create an incentive for makers to lump
|
||||
all their coins into just one bot rather than spreading it over many bots. It makes a sybil attack
|
||||
much more expensive.
|
||||
* 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
|
|||
not too far from the "real" interest rate, and the system still works fine even if the real rate
|
||||
is something like 3% or 0.1%.
|
||||
* The above formula would suggest that if you lock 3 BTC for 10000 years you get a fidelity
|
||||
bond worth `1.7481837557171304e+131` (17 followed by 130 zeros). This does not happen because the
|
||||
bond worth `2.03e+85` (\~ 2 followed by 85 zeros). This does not happen because the
|
||||
sacrificed value is capped at the value of the burned coins. So in this example the fidelity bond
|
||||
value would be just 9 (equal to 3x3 or 3 squared). This feature is not included in the above
|
||||
value would be just \~ 4.17. This feature is not included in the above
|
||||
simplified equation.
|
||||
* After the locktime expires and the coins are free to move, the fidelity bond will continue to be
|
||||
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
|
|||
|
||||
Consider also the [warning on the bitcoin wiki page on timelocks](https://en.bitcoin.it/wiki/Timelock#Far-future_locks).
|
||||
|
||||
I would recommend locking as many bitcoins as you are comfortable with for a period of between 6
|
||||
months and 2 years. Perhaps at the very start lock for only 1 month or 2 months(?) It's a
|
||||
I would recommend locking as many bitcoins as you are comfortable with for a period of between 3
|
||||
months and 1 years. Perhaps at the very start lock for only 1 month or 2 months(?) It's a
|
||||
marketplace and the rules are known to all, so ultimately you'll have to make your own decision.
|
||||
|
||||
### Can my yield-generator use multiple timelocked addresses or UTXO?
|
||||
|
|
|
|||
|
|
@ -386,6 +386,11 @@ interest_rate = """ + _DEFAULT_INTEREST_RATE + """
|
|||
# A real number, i.e. 1 = 100%, 0.125 = 1/8 = 1 in every 8 makers on average will be bondless
|
||||
bondless_makers_allowance = """ + _DEFAULT_BONDLESS_MAKERS_ALLOWANCE + """
|
||||
|
||||
# To (strongly) disincentivize Sybil behaviour, the value assessment of the bond
|
||||
# is based on the (time value of the bond)^x where x is the bond_value_exponent here,
|
||||
# where x > 1. It is a real number (so written as a decimal).
|
||||
bond_value_exponent = 1.3
|
||||
|
||||
##############################
|
||||
# THE FOLLOWING SETTINGS ARE REQUIRED TO DEFEND AGAINST SNOOPERS.
|
||||
# DON'T ALTER THEM UNLESS YOU UNDERSTAND THE IMPLICATIONS.
|
||||
|
|
|
|||
|
|
@ -2557,7 +2557,8 @@ class FidelityBondMixin(object):
|
|||
t = current_time / YEAR
|
||||
|
||||
a = max(0, min(1, exp(r*T) - 1) - min(1, exp(r*max(0, t-L)) - 1))
|
||||
return utxo_value*utxo_value*a*a
|
||||
exponent = float(jm_single().config.get("POLICY", "bond_value_exponent"))
|
||||
return pow(utxo_value*a, exponent)
|
||||
|
||||
@classmethod
|
||||
def get_validated_timelocked_fidelity_bond_utxo(cls, utxo, utxo_pubkey, locktime,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ from jmdaemon import (OrderbookWatch, MessageChannelCollection,
|
|||
import jmbitcoin as btc
|
||||
from jmdaemon.protocol import *
|
||||
|
||||
bond_exponent = None
|
||||
|
||||
#Initial state: allow only SW offer types
|
||||
sw0offers = list(filter(lambda x: x[0:3] == 'sw0', offername_list))
|
||||
swoffers = list(filter(lambda x: x[0:3] == 'swa' or x[0:3] == 'swr', offername_list))
|
||||
|
|
@ -115,7 +117,7 @@ def create_offerbook_table_heading(btc_unit, rel_unit):
|
|||
col.format('txfee', 'Miner Fee Contribution / ' + btc_unit),
|
||||
col.format('minsize', 'Minimum Size / ' + btc_unit),
|
||||
col.format('maxsize', 'Maximum Size / ' + btc_unit),
|
||||
col.format('bondvalue', 'Bond value / ' + btc_unit + '²')
|
||||
col.format('bondvalue', 'Bond value / ' + btc_unit + '<sup>' + bond_exponent + '</sup>')
|
||||
]) + ' </tr>'
|
||||
return tableheading
|
||||
|
||||
|
|
@ -123,7 +125,7 @@ def create_bonds_table_heading(btc_unit):
|
|||
tableheading = ('<table class="tftable sortable" border="1"><tr>'
|
||||
+ '<th>Counterparty</th>'
|
||||
+ '<th>UTXO</th>'
|
||||
+ '<th>Bond value / ' + btc_unit + '²</th>'
|
||||
+ '<th>Bond value / ' + btc_unit + '<sup>' + bond_exponent + '</sup></th>'
|
||||
+ '<th>Locktime</th>'
|
||||
+ '<th>Locked coins / ' + btc_unit + '</th>'
|
||||
+ '<th>Confirmation time</th>'
|
||||
|
|
@ -419,7 +421,8 @@ class OrderbookPageRequestHeader(http.server.SimpleHTTPRequestHandler):
|
|||
+ "how much would a sybil attacker starting now have to sacrifice to succeed in their"
|
||||
+ " attack with 95% probability. Honest weight="
|
||||
+ satoshi_to_unit_power(honest_weight, 2*unit_to_power[btc_unit]) + " " + btc_unit
|
||||
+ "²<br/>Also assumes that takers are not price-sensitive and that their max "
|
||||
+ "<sup>" + bond_exponent + "</sup><br/>Also assumes that takers "
|
||||
+ "are not price-sensitive and that their max "
|
||||
+ "coinjoin fee is configured high enough that they dont exclude any makers.")
|
||||
heading2 = "Sybil attacks from external enemies."
|
||||
|
||||
|
|
@ -459,7 +462,7 @@ class OrderbookPageRequestHeader(http.server.SimpleHTTPRequestHandler):
|
|||
mainbody += ('<table class="tftable" border="1"><tr>'
|
||||
+ '<th>Maker count</th>'
|
||||
+ '<th>Success probability</th>'
|
||||
+ '<th>Foregone value / ' + btc_unit + '²</th>'
|
||||
+ '<th>Foregone value / ' + btc_unit + '<sup>' + bond_exponent + '</sup></th>'
|
||||
+ '</tr>'
|
||||
)
|
||||
|
||||
|
|
@ -784,6 +787,7 @@ def get_dummy_nick():
|
|||
return nick
|
||||
|
||||
def main():
|
||||
global bond_exponent
|
||||
parser = OptionParser(
|
||||
usage='usage: %prog [options]',
|
||||
description='Runs a webservice which shows the orderbook.')
|
||||
|
|
@ -804,6 +808,14 @@ def main():
|
|||
default=62601)
|
||||
(options, args) = parser.parse_args()
|
||||
load_program_config(config_path=options.datadir)
|
||||
# needed to display notional units of FB valuation
|
||||
bond_exponent = jm_single().config.get("POLICY", "bond_value_exponent")
|
||||
try:
|
||||
float(bond_exponent)
|
||||
except ValueError:
|
||||
log.error("Invalid entry for bond_value_exponent, should be decimal "
|
||||
"number: {}".format(bond_exponent))
|
||||
sys.exit(EXIT_FAILURE)
|
||||
check_and_start_tor()
|
||||
hostport = (options.host, options.port)
|
||||
mcs = []
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue