Skip to content

Instantly share code, notes, and snippets.

@m0wer
Created January 5, 2026 10:27
Show Gist options
  • Select an option

  • Save m0wer/23d09c90b7a23070a3e4e340b26d6d14 to your computer and use it in GitHub Desktop.

Select an option

Save m0wer/23d09c90b7a23070a3e4e340b26d6d14 to your computer and use it in GitHub Desktop.
JoinMarket Fidelity Bond Exponent Analysis
"""
JoinMarket Fidelity Bond Exponent Analysis
Using real orderbook data to evaluate Sybil attack scenarios
"""
import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import List
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Real JoinMarket orderbook data (locked BTC amounts)
REAL_ORDERBOOK = [
30.05401340, 26.55225585, 21.65341699, 20.00996535, 8.08486780,
6.04915008, 5.39734023, 4.40845980, 4.09837043, 3.51949732,
3.00192447, 2.67220751, 2.04048986, 1.31983686, 1.00000000,
0.65404050, 0.63046190, 0.50120445, 0.42555395, 0.41538767,
0.29488531, 0.23975233, 0.20990883, 0.20575056, 0.19998701,
0.11764748, 0.09999856, 0.07502071, 0.06301196, 0.04999196,
0.04132994, 0.02607606, 0.01241268, 0.01106880, 0.00980906,
0.00946399, 0.00499853, 0.00355610, 0.00327513, 0.00129700,
0.00108267, 0.00070980, 0.00036572, 0.00029890
]
@dataclass
class AttackScenario:
name: str
honest_bonds: List[float]
attacker_coins: float
taker_peers: int
description: str
def bond_value(coins: float, exponent: float) -> float:
return coins**exponent
def simulate_selection(
honest_bonds: List[float],
attacker_bonds: List[float],
num_peers: int,
exponent: float,
iterations: int = 10000,
) -> dict:
"""Monte Carlo simulation of taker peer selection without replacement"""
full_successes = 0
attacker_peer_counts = []
for _ in range(iterations):
pool = [
{"value": bond_value(b, exponent), "honest": True} for b in honest_bonds
]
pool += [
{"value": bond_value(b, exponent), "honest": False} for b in attacker_bonds
]
attacker_selected = 0
for _ in range(min(num_peers, len(pool))):
total = sum(p["value"] for p in pool)
rand = np.random.random() * total
cumulative = 0
for i, peer in enumerate(pool):
cumulative += peer["value"]
if rand <= cumulative:
if not peer["honest"]:
attacker_selected += 1
pool.pop(i)
break
attacker_peer_counts.append(attacker_selected)
if attacker_selected == num_peers:
full_successes += 1
return {
"full_success_rate": (full_successes / iterations) * 100,
"avg_attacker_peers": np.mean(attacker_peer_counts),
"median_attacker_peers": np.median(attacker_peer_counts),
"attacker_majority_rate": (sum(1 for c in attacker_peer_counts if c > num_peers/2) / iterations) * 100
}
def analyze_attack_scenario(
scenario: AttackScenario, exponents: List[float]
) -> pd.DataFrame:
"""Analyze attack success across exponents for a scenario"""
results = []
for exp in exponents:
# Test a wide range of splitting strategies to find the true optimal
# According to AdamISZ: attacker should split into exactly N pieces where N = taker_peers
# But we test more to verify this empirically
max_splits = min(20, scenario.taker_peers * 3)
splits_to_test = list(range(1, max_splits + 1))
best_result = None
best_full_success = 0
best_split = None
for n_splits in splits_to_test:
attacker_splits = [scenario.attacker_coins / n_splits] * n_splits
result = simulate_selection(
scenario.honest_bonds, attacker_splits, scenario.taker_peers, exp, iterations=10000
)
if result["full_success_rate"] > best_full_success:
best_full_success = result["full_success_rate"]
best_result = result
best_split = n_splits
# Calculate metrics
large_maker_value = bond_value(10, exp)
small_maker_value = bond_value(1, exp)
centralization_ratio = large_maker_value / small_maker_value
consolidated = bond_value(10, exp)
split = 10 * bond_value(1, exp)
split_efficiency = (split / consolidated) * 100
if not best_result:
print(f"Warning: No results for exponent {exp} in scenario {scenario.name}")
continue
results.append({
"exponent": exp,
"full_sybil_rate": best_result["full_success_rate"],
"avg_attacker_peers": best_result["avg_attacker_peers"],
"majority_rate": best_result["attacker_majority_rate"],
"optimal_splits": best_split,
"centralization_ratio": centralization_ratio,
"split_efficiency": split_efficiency,
})
df = pd.DataFrame(results)
df["marginal_improvement"] = -df["full_sybil_rate"].diff().fillna(0)
return df
def create_comparison_plot(scenarios_results: dict) -> go.Figure:
"""Create comparison visualization across scenarios"""
fig = make_subplots(
rows=3, cols=1,
subplot_titles=(
"Full Sybil Attack Success Rate",
"Average Attacker-Controlled Peers",
"Split Efficiency vs Centralization Tradeoff"
),
specs=[[{"secondary_y": False}], [{"secondary_y": False}], [{"secondary_y": True}]],
vertical_spacing=0.10
)
colors = ['#ef4444', '#3b82f6', '#10b981', '#f59e0b', '#8b5cf6']
for i, (name, df) in enumerate(scenarios_results.items()):
# Full sybil success rate
fig.add_trace(
go.Scatter(
x=df["exponent"],
y=df["full_sybil_rate"],
mode="lines+markers",
name=name,
line=dict(color=colors[i % len(colors)], width=2),
legendgroup=name,
),
row=1, col=1
)
# Average attacker peers
fig.add_trace(
go.Scatter(
x=df["exponent"],
y=df["avg_attacker_peers"],
mode="lines+markers",
name=name,
line=dict(color=colors[i % len(colors)], width=2),
legendgroup=name,
showlegend=False,
),
row=2, col=1
)
# Use first scenario for efficiency/centralization (same for all)
first_df = list(scenarios_results.values())[0]
fig.add_trace(
go.Scatter(
x=first_df["exponent"],
y=first_df["split_efficiency"],
mode="lines+markers",
name="Split Efficiency",
line=dict(color="#ec4899", width=2, dash='dash'),
),
row=3, col=1, secondary_y=False
)
fig.add_trace(
go.Scatter(
x=first_df["exponent"],
y=first_df["centralization_ratio"],
mode="lines+markers",
name="Centralization",
line=dict(color="#8b5cf6", width=2),
),
row=3, col=1, secondary_y=True
)
fig.update_xaxes(title_text="Exponent", row=1, col=1)
fig.update_xaxes(title_text="Exponent", row=2, col=1)
fig.update_xaxes(title_text="Exponent", row=3, col=1)
fig.update_yaxes(title_text="Full Sybil Success (%)", row=1, col=1)
fig.update_yaxes(title_text="Avg Attacker Peers", row=2, col=1)
fig.update_yaxes(title_text="Split Efficiency (%)", row=3, col=1, secondary_y=False)
fig.update_yaxes(title_text="Income Ratio (10 BTC / 1 BTC)", row=3, col=1, secondary_y=True)
fig.update_layout(
height=1100,
title_text="Fidelity Bond Exponent Analysis: Real Orderbook Scenarios",
hovermode='x unified'
)
return fig
if __name__ == "__main__":
print("=" * 80)
print("REAL JOINMARKET ORDERBOOK ANALYSIS")
print("=" * 80)
print(f"\nCurrent orderbook: {len(REAL_ORDERBOOK)} makers")
print(f"Total locked: {sum(REAL_ORDERBOOK):.2f} BTC")
print(f"Top 5 makers: {sum(REAL_ORDERBOOK[:5]):.2f} BTC ({sum(REAL_ORDERBOOK[:5])/sum(REAL_ORDERBOOK)*100:.1f}%)")
print(f"Median locked: {sorted(REAL_ORDERBOOK)[len(REAL_ORDERBOOK)//2]:.4f} BTC")
# Define realistic attack scenarios
scenarios = {
"Small attacker (10 BTC, 2 peers)": AttackScenario(
name="Small attacker",
honest_bonds=REAL_ORDERBOOK.copy(),
attacker_coins=10.0,
taker_peers=2, # Small coinjoins
description="Modest attacker vs 2-peer selection"
),
"Medium attacker (25 BTC, 3 peers)": AttackScenario(
name="Medium attacker",
honest_bonds=REAL_ORDERBOOK.copy(),
attacker_coins=25.0,
taker_peers=3, # Medium coinjoins
description="Well-funded attacker vs 3-peer selection"
),
"Large attacker (50 BTC, 4 peers)": AttackScenario(
name="Large attacker",
honest_bonds=REAL_ORDERBOOK.copy(),
attacker_coins=50.0,
taker_peers=4, # Larger coinjoins
description="Major threat actor vs 4-peer selection"
),
"Insider (top maker, 2 peers)": AttackScenario(
name="Insider attack",
honest_bonds=REAL_ORDERBOOK[1:], # Remove top maker
attacker_coins=REAL_ORDERBOOK[0], # Top maker is attacker
taker_peers=2,
description="Top maker (30 BTC) turns malicious"
),
"Whale attacker (100 BTC, 5 peers)": AttackScenario(
name="Whale attacker",
honest_bonds=REAL_ORDERBOOK.copy(),
attacker_coins=100.0,
taker_peers=5,
description="Extreme threat: 100 BTC attacker"
),
}
exponents = [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 5.0, 10.0]
all_results = {}
for scenario_name, scenario in scenarios.items():
print(f"\n{'=' * 80}")
print(f"SCENARIO: {scenario_name}")
print(f"{'=' * 80}")
print(f"Description: {scenario.description}")
print(f"Attacker coins: {scenario.attacker_coins:.2f} BTC")
print(f"Honest makers: {len(scenario.honest_bonds)}")
print(f"Taker chooses: {scenario.taker_peers} peers")
print(f"\nAnalyzing...")
df = analyze_attack_scenario(scenario, exponents)
all_results[scenario_name] = df
print("\n" + df.to_string(index=False))
# Key insights - safely handle missing exponents
print(f"\nKEY RESULTS:")
for exp_val in [1.0, 1.3, 2.0, 3.0, 5.0, 10.0]:
exp_data = df[df["exponent"] == exp_val]
if not exp_data.empty:
exp_row = exp_data.iloc[0]
print(f" Exponent {exp_val}:")
print(f" Full Sybil: {exp_row['full_sybil_rate']:.2f}% | Avg peers: {exp_row['avg_attacker_peers']:.2f} | Majority: {exp_row['majority_rate']:.1f}%")
print(f" Optimal splits: {exp_row['optimal_splits']}")
print(f" Centralization: {exp_row['centralization_ratio']:.1f}x (10 BTC / 1 BTC maker income)")
exp_1_data = df[df["exponent"] == 1.0]
exp_2_data = df[df["exponent"] == 2.0]
# Compare tradeoffs between exponents
print(f"\nTRADEOFF ANALYSIS:")
comparisons = [(1.0, 1.3), (1.3, 2.0), (2.0, 3.0), (3.0, 5.0)]
for exp_a, exp_b in comparisons:
data_a = df[df["exponent"] == exp_a]
data_b = df[df["exponent"] == exp_b]
if not data_a.empty and not data_b.empty:
a = data_a.iloc[0]
b = data_b.iloc[0]
sybil_improvement = a['full_sybil_rate'] - b['full_sybil_rate']
if a['full_sybil_rate'] > 0:
sybil_improvement_pct = (sybil_improvement / a['full_sybil_rate']) * 100
else:
sybil_improvement_pct = 0
centralization_increase = b['centralization_ratio'] / a['centralization_ratio']
# Efficiency: how much Sybil resistance per unit of centralization
if centralization_increase > 1:
efficiency = sybil_improvement_pct / (centralization_increase - 1)
else:
efficiency = 0
print(f" {exp_a} → {exp_b}:")
print(f" Sybil resistance improves by {sybil_improvement:.3f}% ({sybil_improvement_pct:.1f}% relative)")
print(f" Centralization increases {centralization_increase:.1f}x")
print(f" Efficiency: {efficiency:.2f}% Sybil improvement per 1x centralization")
print("\n" + "=" * 80)
print("TRADEOFF ANALYSIS: Sybil Resistance vs Centralization")
print("=" * 80)
print("\nFor each scenario, we analyze: Is the Sybil resistance gain worth the centralization cost?")
for scenario_name, df in all_results.items():
print(f"\n{scenario_name}:")
# Compare key exponents
comparisons = [
(1.0, 1.3, "Linear to JoinMarket Current"),
(1.3, 2.0, "JoinMarket Current to Quadratic"),
(2.0, 3.0, "Quadratic to Cubic"),
]
for exp_a, exp_b, label in comparisons:
data_a = df[df["exponent"] == exp_a]
data_b = df[df["exponent"] == exp_b]
if data_a.empty or data_b.empty:
continue
a = data_a.iloc[0]
b = data_b.iloc[0]
# Calculate improvements and costs
sybil_improvement = a['full_sybil_rate'] - b['full_sybil_rate']
if a['full_sybil_rate'] > 0.01:
sybil_improvement_pct = (sybil_improvement / a['full_sybil_rate']) * 100
else:
sybil_improvement_pct = 0
centralization_ratio = b['centralization_ratio'] / a['centralization_ratio']
# Efficiency metric: Sybil improvement per unit centralization
if centralization_ratio > 1.01:
efficiency = sybil_improvement_pct / (centralization_ratio - 1)
else:
efficiency = 0
print(f" {label} ({exp_a} → {exp_b}):")
print(f" Sybil attack drops: {a['full_sybil_rate']:.3f}% → {b['full_sybil_rate']:.3f}% ({sybil_improvement_pct:.1f}% improvement)")
print(f" Centralization: {a['centralization_ratio']:.1f}x → {b['centralization_ratio']:.1f}x ({centralization_ratio:.1f}x worse)")
if efficiency > 0:
print(f" Tradeoff efficiency: {efficiency:.2f}% Sybil improvement per 1x centralization increase")
# Make a recommendation
if sybil_improvement < 0.05 and centralization_ratio > 2:
print(f" ⚠️ POOR TRADEOFF: Tiny Sybil gain ({sybil_improvement:.3f}%) for large centralization ({centralization_ratio:.1f}x)")
elif sybil_improvement > 1.0 and centralization_ratio < 3:
print(f" ✓ GOOD TRADEOFF: Significant Sybil improvement with moderate centralization")
elif efficiency > 50:
print(f" ✓ EFFICIENT: High Sybil improvement per unit centralization")
# Create visualization
fig = create_comparison_plot(all_results)
fig.write_html("exponent_analysis.html")
print("\nVisualization saved to: exponent_analysis.html")
@m0wer

m0wer commented Jan 5, 2026

Copy link
Copy Markdown
Author

The Exponent Choice

Experiment

Scenarios

The analysis tests five attack scenarios against real JoinMarket orderbook data (44 makers, 144.17 BTC total locked):

  1. Small attacker (10 BTC, 2 peers): A modest attacker with 10 BTC trying to compromise 2-peer coinjoins. Represents the minimum viable attack where the attacker has less capital than the top makers but still substantial resources.
  2. Medium attacker (25 BTC, 3 peers): A well-funded attacker with 25 BTC targeting 3-peer coinjoins. This amount is comparable to the top maker's bond, representing a realistic threat from a determined adversary.
  3. Large attacker (50 BTC, 4 peers): A major threat actor with 50 BTC attacking 4-peer coinjoins. This represents a sophisticated attacker with resources exceeding most individual makers.
  4. Insider (top maker, 2 peers): The current top maker (30 BTC) turns malicious. This scenario tests resistance against an already-trusted participant who decides to attack, which is particularly dangerous because they're already selected frequently.
  5. Whale attacker (100 BTC, 5 peers): An extreme scenario with 100 BTC targeting 5-peer coinjoins. This represents a nation-state level attack or well-funded adversary with resources comparable to the entire orderbook.

For each scenario, the script finds the optimal splitting strategy for the attacker (how to divide their coins across multiple maker identities) and measures the success rate of achieving a full Sybil attack (controlling all peers in the coinjoin).

Results

Script output
================================================================================
REAL JOINMARKET ORDERBOOK ANALYSIS
================================================================================

Current orderbook: 44 makers
Total locked: 144.17 BTC
Top 5 makers: 106.35 BTC (73.8%)
Median locked: 0.2398 BTC

================================================================================
SCENARIO: Small attacker (10 BTC, 2 peers)
================================================================================
Description: Modest attacker vs 2-peer selection
Attacker coins: 10.00 BTC
Honest makers: 44
Taker chooses: 2 peers

Analyzing...
Warning: No results for exponent 2.5 in scenario Small attacker
Warning: No results for exponent 3.0 in scenario Small attacker
Warning: No results for exponent 5.0 in scenario Small attacker
Warning: No results for exponent 10.0 in scenario Small attacker

 exponent  full_sybil_rate  avg_attacker_peers  majority_rate  optimal_splits  centralization_ratio  split_efficiency  marginal_improvement
      1.0             0.49              0.1458           0.49               6             10.000000        100.000000                 -0.00
      1.1             0.26              0.1136           0.26               6             12.589254         79.432823                  0.23
      1.2             0.23              0.0967           0.23               6             15.848932         63.095734                  0.03
      1.3             0.18              0.1060           0.18               2             19.952623         50.118723                  0.05
      1.4             0.11              0.0683           0.11               4             25.118864         39.810717                  0.07
      1.5             0.08              0.0601           0.08               4             31.622777         31.622777                  0.03
      1.6             0.07              0.0580           0.07               3             39.810717         25.118864                  0.01
      1.7             0.04              0.0383           0.04               5             50.118723         19.952623                  0.03
      1.8             0.02              0.0542           0.02               2             63.095734         15.848932                  0.02
      1.9             0.04              0.0330           0.04               3             79.432823         12.589254                 -0.02
      2.0             0.02              0.0289           0.02               3            100.000000         10.000000                  0.02

KEY RESULTS:
  Exponent 1.0:
    Full Sybil: 0.49% | Avg peers: 0.15 | Majority: 0.5%
    Optimal splits: 6.0
    Centralization: 10.0x (10 BTC / 1 BTC maker income)
  Exponent 1.3:
    Full Sybil: 0.18% | Avg peers: 0.11 | Majority: 0.2%
    Optimal splits: 2.0
    Centralization: 20.0x (10 BTC / 1 BTC maker income)
  Exponent 2.0:
    Full Sybil: 0.02% | Avg peers: 0.03 | Majority: 0.0%
    Optimal splits: 3.0
    Centralization: 100.0x (10 BTC / 1 BTC maker income)

TRADEOFF ANALYSIS:
  1.0 → 1.3:
    Sybil resistance improves by 0.310% (63.3% relative)
    Centralization increases 2.0x
    Efficiency: 63.57% Sybil improvement per 1x centralization
  1.3 → 2.0:
    Sybil resistance improves by 0.160% (88.9% relative)
    Centralization increases 5.0x
    Efficiency: 22.16% Sybil improvement per 1x centralization

================================================================================
SCENARIO: Medium attacker (25 BTC, 3 peers)
================================================================================
Description: Well-funded attacker vs 3-peer selection
Attacker coins: 25.00 BTC
Honest makers: 44
Taker chooses: 3 peers

Analyzing...
Warning: No results for exponent 2.5 in scenario Medium attacker
Warning: No results for exponent 3.0 in scenario Medium attacker
Warning: No results for exponent 5.0 in scenario Medium attacker
Warning: No results for exponent 10.0 in scenario Medium attacker

 exponent  full_sybil_rate  avg_attacker_peers  majority_rate  optimal_splits  centralization_ratio  split_efficiency  marginal_improvement
      1.0             0.22              0.4862           5.75               6             10.000000        100.000000                 -0.00
      1.1             0.26              0.4470           4.94               7             12.589254         79.432823                 -0.04
      1.2             0.11              0.4209           3.95               5             15.848932         63.095734                  0.15
      1.3             0.10              0.3676           3.23               6             19.952623         50.118723                  0.01
      1.4             0.06              0.3492           2.73               5             25.118864         39.810717                  0.04
      1.5             0.07              0.3171           2.37               5             31.622777         31.622777                 -0.01
      1.6             0.03              0.3715           2.81               3             39.810717         25.118864                  0.04
      1.7             0.05              0.3085           1.97               4             50.118723         19.952623                 -0.02
      1.8             0.04              0.2704           1.44               4             63.095734         15.848932                  0.01
      1.9             0.02              0.2442           1.14               4             79.432823         12.589254                  0.02
      2.0             0.02              0.1357           0.36               7            100.000000         10.000000                 -0.00

KEY RESULTS:
  Exponent 1.0:
    Full Sybil: 0.22% | Avg peers: 0.49 | Majority: 5.8%
    Optimal splits: 6.0
    Centralization: 10.0x (10 BTC / 1 BTC maker income)
  Exponent 1.3:
    Full Sybil: 0.10% | Avg peers: 0.37 | Majority: 3.2%
    Optimal splits: 6.0
    Centralization: 20.0x (10 BTC / 1 BTC maker income)
  Exponent 2.0:
    Full Sybil: 0.02% | Avg peers: 0.14 | Majority: 0.4%
    Optimal splits: 7.0
    Centralization: 100.0x (10 BTC / 1 BTC maker income)

TRADEOFF ANALYSIS:
  1.0 → 1.3:
    Sybil resistance improves by 0.120% (54.5% relative)
    Centralization increases 2.0x
    Efficiency: 54.81% Sybil improvement per 1x centralization
  1.3 → 2.0:
    Sybil resistance improves by 0.080% (80.0% relative)
    Centralization increases 5.0x
    Efficiency: 19.94% Sybil improvement per 1x centralization

================================================================================
SCENARIO: Large attacker (50 BTC, 4 peers)
================================================================================
Description: Major threat actor vs 4-peer selection
Attacker coins: 50.00 BTC
Honest makers: 44
Taker chooses: 4 peers

Analyzing...
Warning: No results for exponent 2.5 in scenario Large attacker
Warning: No results for exponent 3.0 in scenario Large attacker
Warning: No results for exponent 5.0 in scenario Large attacker
Warning: No results for exponent 10.0 in scenario Large attacker

 exponent  full_sybil_rate  avg_attacker_peers  majority_rate  optimal_splits  centralization_ratio  split_efficiency  marginal_improvement
      1.0             0.33              1.1245           4.97               8             10.000000        100.000000                 -0.00
      1.1             0.28              1.0617           4.33              12             12.589254         79.432823                  0.05
      1.2             0.17              1.0306           3.47               9             15.848932         63.095734                  0.11
      1.3             0.10              0.9709           2.95               8             19.952623         50.118723                  0.07
      1.4             0.10              0.9653           2.62               7             25.118864         39.810717                 -0.00
      1.5             0.06              0.9283           2.21               7             31.622777         31.622777                  0.04
      1.6             0.07              0.7016           0.96              12             39.810717         25.118864                 -0.01
      1.7             0.08              0.9664           1.97               5             50.118723         19.952623                 -0.01
      1.8             0.02              1.0169           1.83               4             63.095734         15.848932                  0.06
      1.9             0.01              0.9971           1.72               4             79.432823         12.589254                  0.01
      2.0             0.02              0.9772           1.46               4            100.000000         10.000000                 -0.01

KEY RESULTS:
  Exponent 1.0:
    Full Sybil: 0.33% | Avg peers: 1.12 | Majority: 5.0%
    Optimal splits: 8.0
    Centralization: 10.0x (10 BTC / 1 BTC maker income)
  Exponent 1.3:
    Full Sybil: 0.10% | Avg peers: 0.97 | Majority: 2.9%
    Optimal splits: 8.0
    Centralization: 20.0x (10 BTC / 1 BTC maker income)
  Exponent 2.0:
    Full Sybil: 0.02% | Avg peers: 0.98 | Majority: 1.5%
    Optimal splits: 4.0
    Centralization: 100.0x (10 BTC / 1 BTC maker income)

TRADEOFF ANALYSIS:
  1.0 → 1.3:
    Sybil resistance improves by 0.230% (69.7% relative)
    Centralization increases 2.0x
    Efficiency: 70.03% Sybil improvement per 1x centralization
  1.3 → 2.0:
    Sybil resistance improves by 0.080% (80.0% relative)
    Centralization increases 5.0x
    Efficiency: 19.94% Sybil improvement per 1x centralization

================================================================================
SCENARIO: Insider (top maker, 2 peers)
================================================================================
Description: Top maker (30 BTC) turns malicious
Attacker coins: 30.05 BTC
Honest makers: 43
Taker chooses: 2 peers

Analyzing...

 exponent  full_sybil_rate  avg_attacker_peers  majority_rate  optimal_splits  centralization_ratio  split_efficiency  marginal_improvement
      1.0             3.47              0.4215           3.47               6          1.000000e+01      1.000000e+02                 -0.00
      1.1             3.34              0.4157           3.34               6          1.258925e+01      7.943282e+01                  0.13
      1.2             2.79              0.4036           2.79               5          1.584893e+01      6.309573e+01                  0.55
      1.3             2.99              0.4195           2.99               3          1.995262e+01      5.011872e+01                 -0.20
      1.4             2.97              0.4573           2.97               2          2.511886e+01      3.981072e+01                  0.02
      1.5             2.55              0.4467           2.55               2          3.162278e+01      3.162278e+01                  0.42
      1.6             2.88              0.4585           2.88               2          3.981072e+01      2.511886e+01                 -0.33
      1.7             2.78              0.4503           2.78               2          5.011872e+01      1.995262e+01                  0.10
      1.8             2.51              0.4497           2.51               2          6.309573e+01      1.584893e+01                  0.27
      1.9             2.38              0.4428           2.38               2          7.943282e+01      1.258925e+01                  0.13
      2.0             2.31              0.4386           2.31               2          1.000000e+02      1.000000e+01                  0.07
      2.5             1.84              0.4018           1.84               2          3.162278e+02      3.162278e+00                  0.47
      3.0             1.35              0.3537           1.35               2          1.000000e+03      1.000000e+00                  0.49
      5.0             0.28              0.1870           0.28               2          1.000000e+05      1.000000e-02                  1.07
     10.0             0.01              0.0371           0.01               2          1.000000e+10      1.000000e-07                  0.27

KEY RESULTS:
  Exponent 1.0:
    Full Sybil: 3.47% | Avg peers: 0.42 | Majority: 3.5%
    Optimal splits: 6.0
    Centralization: 10.0x (10 BTC / 1 BTC maker income)
  Exponent 1.3:
    Full Sybil: 2.99% | Avg peers: 0.42 | Majority: 3.0%
    Optimal splits: 3.0
    Centralization: 20.0x (10 BTC / 1 BTC maker income)
  Exponent 2.0:
    Full Sybil: 2.31% | Avg peers: 0.44 | Majority: 2.3%
    Optimal splits: 2.0
    Centralization: 100.0x (10 BTC / 1 BTC maker income)
  Exponent 3.0:
    Full Sybil: 1.35% | Avg peers: 0.35 | Majority: 1.4%
    Optimal splits: 2.0
    Centralization: 1000.0x (10 BTC / 1 BTC maker income)
  Exponent 5.0:
    Full Sybil: 0.28% | Avg peers: 0.19 | Majority: 0.3%
    Optimal splits: 2.0
    Centralization: 100000.0x (10 BTC / 1 BTC maker income)
  Exponent 10.0:
    Full Sybil: 0.01% | Avg peers: 0.04 | Majority: 0.0%
    Optimal splits: 2.0
    Centralization: 10000000000.0x (10 BTC / 1 BTC maker income)

TRADEOFF ANALYSIS:
  1.0 → 1.3:
    Sybil resistance improves by 0.480% (13.8% relative)
    Centralization increases 2.0x
    Efficiency: 13.90% Sybil improvement per 1x centralization
  1.3 → 2.0:
    Sybil resistance improves by 0.680% (22.7% relative)
    Centralization increases 5.0x
    Efficiency: 5.67% Sybil improvement per 1x centralization
  2.0 → 3.0:
    Sybil resistance improves by 0.960% (41.6% relative)
    Centralization increases 10.0x
    Efficiency: 4.62% Sybil improvement per 1x centralization
  3.0 → 5.0:
    Sybil resistance improves by 1.070% (79.3% relative)
    Centralization increases 100.0x
    Efficiency: 0.80% Sybil improvement per 1x centralization

================================================================================
SCENARIO: Whale attacker (100 BTC, 5 peers)
================================================================================
Description: Extreme threat: 100 BTC attacker
Attacker coins: 100.00 BTC
Honest makers: 44
Taker chooses: 5 peers

Analyzing...
Warning: No results for exponent 5.0 in scenario Whale attacker
Warning: No results for exponent 10.0 in scenario Whale attacker

 exponent  full_sybil_rate  avg_attacker_peers  majority_rate  optimal_splits  centralization_ratio  split_efficiency  marginal_improvement
      1.0             0.72              2.1817          36.63              14             10.000000        100.000000                 -0.00
      1.1             0.59              2.1503          35.10              13             12.589254         79.432823                  0.13
      1.2             0.48              2.1195          34.01              11             15.848932         63.095734                  0.11
      1.3             0.40              2.1245          33.57               9             19.952623         50.118723                  0.08
      1.4             0.29              2.0710          31.20              10             25.118864         39.810717                  0.11
      1.5             0.29              2.2055          36.31               6             31.622777         31.622777                 -0.00
      1.6             0.23              2.1042          32.27               8             39.810717         25.118864                  0.06
      1.7             0.28              2.1436          32.98               7             50.118723         19.952623                 -0.05
      1.8             0.20              2.0498          28.77               8             63.095734         15.848932                  0.08
      1.9             0.20              2.0973          30.68               7             79.432823         12.589254                 -0.00
      2.0             0.16              2.1982          34.40               6            100.000000         10.000000                  0.04
      2.5             0.12              1.9684          22.98               7            316.227766          3.162278                  0.04
      3.0             0.06              2.2709          36.69               5           1000.000000          1.000000                  0.06

KEY RESULTS:
  Exponent 1.0:
    Full Sybil: 0.72% | Avg peers: 2.18 | Majority: 36.6%
    Optimal splits: 14.0
    Centralization: 10.0x (10 BTC / 1 BTC maker income)
  Exponent 1.3:
    Full Sybil: 0.40% | Avg peers: 2.12 | Majority: 33.6%
    Optimal splits: 9.0
    Centralization: 20.0x (10 BTC / 1 BTC maker income)
  Exponent 2.0:
    Full Sybil: 0.16% | Avg peers: 2.20 | Majority: 34.4%
    Optimal splits: 6.0
    Centralization: 100.0x (10 BTC / 1 BTC maker income)
  Exponent 3.0:
    Full Sybil: 0.06% | Avg peers: 2.27 | Majority: 36.7%
    Optimal splits: 5.0
    Centralization: 1000.0x (10 BTC / 1 BTC maker income)

TRADEOFF ANALYSIS:
  1.0 → 1.3:
    Sybil resistance improves by 0.320% (44.4% relative)
    Centralization increases 2.0x
    Efficiency: 44.66% Sybil improvement per 1x centralization
  1.3 → 2.0:
    Sybil resistance improves by 0.240% (60.0% relative)
    Centralization increases 5.0x
    Efficiency: 14.96% Sybil improvement per 1x centralization
  2.0 → 3.0:
    Sybil resistance improves by 0.100% (62.5% relative)
    Centralization increases 10.0x
    Efficiency: 6.94% Sybil improvement per 1x centralization

================================================================================
TRADEOFF ANALYSIS: Sybil Resistance vs Centralization
================================================================================

For each scenario, we analyze: Is the Sybil resistance gain worth the centralization cost?

Small attacker (10 BTC, 2 peers):
  Linear to JoinMarket Current (1.0 → 1.3):
    Sybil attack drops: 0.490% → 0.180% (63.3% improvement)
    Centralization: 10.0x → 20.0x (2.0x worse)
    Tradeoff efficiency: 63.57% Sybil improvement per 1x centralization increase
    ✓ EFFICIENT: High Sybil improvement per unit centralization
  JoinMarket Current to Quadratic (1.3 → 2.0):
    Sybil attack drops: 0.180% → 0.020% (88.9% improvement)
    Centralization: 20.0x → 100.0x (5.0x worse)
    Tradeoff efficiency: 22.16% Sybil improvement per 1x centralization increase

Medium attacker (25 BTC, 3 peers):
  Linear to JoinMarket Current (1.0 → 1.3):
    Sybil attack drops: 0.220% → 0.100% (54.5% improvement)
    Centralization: 10.0x → 20.0x (2.0x worse)
    Tradeoff efficiency: 54.81% Sybil improvement per 1x centralization increase
    ✓ EFFICIENT: High Sybil improvement per unit centralization
  JoinMarket Current to Quadratic (1.3 → 2.0):
    Sybil attack drops: 0.100% → 0.020% (80.0% improvement)
    Centralization: 20.0x → 100.0x (5.0x worse)
    Tradeoff efficiency: 19.94% Sybil improvement per 1x centralization increase

Large attacker (50 BTC, 4 peers):
  Linear to JoinMarket Current (1.0 → 1.3):
    Sybil attack drops: 0.330% → 0.100% (69.7% improvement)
    Centralization: 10.0x → 20.0x (2.0x worse)
    Tradeoff efficiency: 70.03% Sybil improvement per 1x centralization increase
    ✓ EFFICIENT: High Sybil improvement per unit centralization
  JoinMarket Current to Quadratic (1.3 → 2.0):
    Sybil attack drops: 0.100% → 0.020% (80.0% improvement)
    Centralization: 20.0x → 100.0x (5.0x worse)
    Tradeoff efficiency: 19.94% Sybil improvement per 1x centralization increase

Insider (top maker, 2 peers):
  Linear to JoinMarket Current (1.0 → 1.3):
    Sybil attack drops: 3.470% → 2.990% (13.8% improvement)
    Centralization: 10.0x → 20.0x (2.0x worse)
    Tradeoff efficiency: 13.90% Sybil improvement per 1x centralization increase
  JoinMarket Current to Quadratic (1.3 → 2.0):
    Sybil attack drops: 2.990% → 2.310% (22.7% improvement)
    Centralization: 20.0x → 100.0x (5.0x worse)
    Tradeoff efficiency: 5.67% Sybil improvement per 1x centralization increase
  Quadratic to Cubic (2.0 → 3.0):
    Sybil attack drops: 2.310% → 1.350% (41.6% improvement)
    Centralization: 100.0x → 1000.0x (10.0x worse)
    Tradeoff efficiency: 4.62% Sybil improvement per 1x centralization increase

Whale attacker (100 BTC, 5 peers):
  Linear to JoinMarket Current (1.0 → 1.3):
    Sybil attack drops: 0.720% → 0.400% (44.4% improvement)
    Centralization: 10.0x → 20.0x (2.0x worse)
    Tradeoff efficiency: 44.66% Sybil improvement per 1x centralization increase
  JoinMarket Current to Quadratic (1.3 → 2.0):
    Sybil attack drops: 0.400% → 0.160% (60.0% improvement)
    Centralization: 20.0x → 100.0x (5.0x worse)
    Tradeoff efficiency: 14.96% Sybil improvement per 1x centralization increase
  Quadratic to Cubic (2.0 → 3.0):
    Sybil attack drops: 0.160% → 0.060% (62.5% improvement)
    Centralization: 100.0x → 1000.0x (10.0x worse)
    Tradeoff efficiency: 6.94% Sybil improvement per 1x centralization increase

Charts

newplot

Representative Scenario Results

Medium attacker (25 BTC, 3 peers) - Most balanced scenario showing typical tradeoffs:

Exponent Sybil Success Centralization Efficiency Score
1.0 0.22% 10x baseline
1.3 0.10% 20x 54.8%
2.0 0.02% 100x 19.9%
3.0 - 1000x <5%

Efficiency Score = Sybil improvement % ÷ centralization increase factor
Key insight: Moving from 1.0→1.3 gives 54.8% efficiency (excellent), while 1.3→2.0 drops to 19.9% efficiency (2.7x worse), and going beyond 2.0 yields <5% efficiency (terrible tradeoff). The quadratic exponent (2.0) requires 5x more centralization than 1.3 for diminishing security returns.

Key findings across all scenarios

  1. SYBIL RESISTANCE:

    • All exponents provide very strong resistance (< 4% even for insider attacks)
    • Higher exponents do provide better resistance
    • But improvements are often marginal (< 0.5% absolute improvement)
    • Full Sybil attacks are very hard with the current orderbook even with very low peer count (usually 8-11 total participants are used)
  2. CENTRALIZATION PRESSURE:

    • x=1.0: 10x income advantage (10 BTC maker vs 1 BTC maker)
    • x=1.3: 20x income advantage
    • x=2.0: 100x income advantage
    • x=3.0: 1000x income advantage
    • x=5.0: 100,000x income advantage (!)
  3. THE CRITICAL QUESTION:
    Is a 0.1-1% improvement in Sybil resistance worth:

    • 10x more centralization pressure?
    • Making it nearly impossible for small makers to compete?
    • Creating 'winner-take-all' dynamics?
  4. RECOMMENDATION:
    Based on efficiency metrics, x=1.3 appears to offer the best balance:

    • Meaningful Sybil improvement over x=1.0
    • Moderate centralization (20x vs 100x for quadratic)
    • Still allows smaller makers to meaningfully participate
    • Going beyond 1.3 shows diminishing returns

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment