Skip to content

Commit b86b251

Browse files
committed
CIP????- Ouroboros Φalanx
1 parent 5ee672e commit b86b251

24 files changed

+5269
-0
lines changed

CIP-????/Readme.md

Lines changed: 1815 additions & 0 deletions
Large diffs are not rendered by default.

CIP-????/graph/NhandNa.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import matplotlib.pyplot as plt
2+
3+
# Adjusted data to ensure matching lengths
4+
s_a_values = [0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.25, 0.3, 0.33, 0.4, 0.45, 0.49, 0.5]
5+
N_a_values = [269, 434, 730, 1537, 2794, 5204, 6384, 7554, 8252, 9872, 11024, 11942, 12171]
6+
N_h_values = [19645, 19541, 18713, 17680, 15618, 14590, 13563, 12949, 11517, 10498, 9685, 9482, 9482]
7+
8+
# Plot
9+
plt.figure(figsize=(14, 6))
10+
11+
# Left plot: Max #Adversarial blocks
12+
plt.subplot(1, 2, 1)
13+
plt.plot([x * 100 for x in s_a_values], N_a_values, marker='o', label="N_a")
14+
plt.title("Nₐ s.t. Pr(Xₐ < Nₐ) = 1 - 2⁻¹²⁸")
15+
plt.xlabel("Adversarial stake sₐ (%)")
16+
plt.ylabel("Max #Adversarial blocks")
17+
plt.grid(True)
18+
plt.legend()
19+
20+
# Right plot: Min #Honest blocks
21+
plt.subplot(1, 2, 2)
22+
plt.plot([x * 100 for x in s_a_values], N_h_values, marker='o', color='orange', label="N_h")
23+
plt.title("Nₕ s.t. Pr(Xₕ > Nₕ) = 2⁻¹²⁸")
24+
plt.xlabel("Adversarial stake sₐ (%)")
25+
plt.ylabel("Min #Honest blocks")
26+
plt.grid(True)
27+
plt.legend()
28+
29+
plt.tight_layout()
30+
plt.show()

CIP-????/graph/extended_error_series_corrected.csv

Lines changed: 2501 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from matplotlib.patches import Patch
4+
5+
# Define the range for rho (Grinding Depth)
6+
rho = np.linspace(1, 256, 1000)
7+
f = 0.05
8+
cost_per_cpu_hour = 0.01
9+
w_O = 20 * (2 * rho - 1)
10+
w_O_hours = w_O / 3600
11+
epsilon = 1e-100 # Avoid log(0)
12+
13+
# Praos cost functions
14+
def ant_glance_praos(rho): return 5e-10 * 2**(rho - 2)
15+
def ant_patrol_praos(rho): return 5e-10 * 2**(rho - 1) + 2.16e-2 * 2**(rho - 1) / rho
16+
def owl_stare_praos(rho): return 5e-10 * 2**(rho - 2) + 5e-2 * 2**(rho - 1) / rho
17+
def owl_survey_praos(rho): return 5e-10 * 2**(rho - 2) + 7.16e-2 * 2**(rho - 1) / rho
18+
19+
# Phalanx cost function
20+
def phalanx_cost(rho, scale): return (scale * 2**(rho - 1)) / rho
21+
22+
# Compute log10(Cost) from CPU count
23+
def log_cost(n_cpu): return np.log10(np.maximum(n_cpu * cost_per_cpu_hour * w_O_hours, epsilon))
24+
25+
# Curves for Praos
26+
praos_curves = {
27+
'Ant Glance Praos': ('blue', log_cost(ant_glance_praos(rho))),
28+
'Ant Patrol Praos': ('orange', log_cost(ant_patrol_praos(rho))),
29+
'Owl Stare Praos': ('green', log_cost(owl_stare_praos(rho))),
30+
'Owl Survey Praos': ('red', log_cost(owl_survey_praos(rho))),
31+
}
32+
33+
# Curves for Phalanx configurations
34+
phalanx_curves = {
35+
'Phalanx$_{1/100}$': ('#6A5ACD', log_cost(phalanx_cost(rho, 2.16e2))),
36+
'Phalanx$_{1/10}$': ('#228B22', log_cost(phalanx_cost(rho, 2.16e3))),
37+
'Phalanx$_{max}$': ('#B22222', log_cost(phalanx_cost(rho, 2.16e4))),
38+
}
39+
40+
# Feasibility zones
41+
zones = [
42+
(-10, 4, 'green', 'Trivial'),
43+
(4, 6, 'yellow', 'Feasible'),
44+
(6, 9, '#FFA07A', 'Possible'),
45+
(9, 12, '#FF6347', 'Borderline Infeasible'),
46+
(12, 90, 'red', 'Infeasible')
47+
]
48+
49+
# Function to find crossing points and annotate
50+
def annotate_crossings(log_costs, color, threshold, position='above'):
51+
# Find indices where the curve crosses the threshold
52+
indices = np.where((log_costs[:-1] < threshold) & (log_costs[1:] >= threshold))[0]
53+
if len(indices) > 0:
54+
idx = indices[0]
55+
rho_val = rho[idx]
56+
plt.scatter(rho_val, threshold, color=color, marker='o', s=50, zorder=5)
57+
# Position above or below based on the curve
58+
if position == 'below':
59+
plt.annotate(f'{rho_val:.1f}',
60+
xy=(rho_val, threshold),
61+
xytext=(rho_val + 1.1, threshold - 0.4),
62+
fontsize=8, color=color)
63+
elif position == 'green':
64+
plt.annotate(f'{rho_val:.1f}',
65+
xy=(rho_val, threshold),
66+
xytext=(rho_val - 0.6, threshold - 0.9),
67+
fontsize=8, color=color)
68+
else:
69+
plt.annotate(f'{rho_val:.1f}',
70+
xy=(rho_val, threshold),
71+
xytext=(rho_val - 1, threshold + 0.3),
72+
fontsize=8, color=color)
73+
74+
75+
# # Annotate where curves cross threshold lines
76+
# def annotate_crossings(log_costs, color, threshold, position='above'):
77+
# indices = np.where((log_costs[:-1] < threshold) & (log_costs[1:] >= threshold))[0]
78+
# if len(indices) > 0:
79+
# idx = indices[0]
80+
# rho_val = rho[idx]
81+
# plt.scatter(rho_val, threshold, color=color, marker='o', s=50, zorder=5)
82+
# offset = {'above': (1, 0.5), 'below': (1.1, -0.4), 'green': (-0.6, -0.9)}.get(position, (1, 0.5))
83+
# plt.annotate(f'{rho_val:.1f}', xy=(rho_val, threshold),
84+
# xytext=(rho_val + offset[0], threshold + offset[1]),
85+
# fontsize=8, color=color)
86+
87+
# Unified curve list for annotation logic
88+
curves = [
89+
(praos_curves['Ant Glance Praos'][1], 'blue', 'above'),
90+
(praos_curves['Ant Patrol Praos'][1], 'orange', 'below'),
91+
(praos_curves['Owl Stare Praos'][1], 'green', 'green'),
92+
(praos_curves['Owl Survey Praos'][1], 'red', 'above'),
93+
(phalanx_curves['Phalanx$_{1/100}$'][1], '#6A5ACD', 'above'),
94+
(phalanx_curves['Phalanx$_{1/10}$'][1], '#228B22', 'above'),
95+
(phalanx_curves['Phalanx$_{max}$'][1], '#B22222', 'above')
96+
]
97+
98+
# Plotting
99+
plt.figure(figsize=(12, 7))
100+
101+
# Plot each Praos and Phalanx curve
102+
for label, (color, values) in praos_curves.items():
103+
plt.plot(rho, values, label=label, color=color, linewidth=2)
104+
for label, (color, values) in phalanx_curves.items():
105+
plt.plot(rho, values, label=label, color=color, linestyle='--', linewidth=2)
106+
107+
# Add feasibility zones
108+
for y0, y1, color, label in zones:
109+
plt.axhspan(y0, y1, color=color, alpha=0.1, label=label)
110+
111+
# Annotate crossings
112+
for threshold, _, _, _ in zones:
113+
for log_costs, color, position in curves:
114+
annotate_crossings(log_costs, color, threshold, position)
115+
116+
# Axis labels and title
117+
plt.xlabel(r'$\rho$ (Grinding Depth)', fontsize=14)
118+
plt.ylabel(r'$\log_{10}(\mathrm{Cost\ (USD)})$', fontsize=14)
119+
plt.title('Cost of Grinding Attacks Across Praos and Phalanx Scenarios', fontsize=16)
120+
plt.grid(True, linestyle='--', alpha=0.7)
121+
plt.xlim(0, 256)
122+
y_max = max(np.max(v[np.isfinite(v)]) for _, v in list(praos_curves.values()) + list(phalanx_curves.values())) + 5
123+
plt.ylim(-5, y_max)
124+
125+
# Custom legend
126+
legend_elements = [
127+
*[plt.Line2D([0], [0], color=color, lw=2, label=label) for label, (color, _) in praos_curves.items()],
128+
*[plt.Line2D([0], [0], color=color, lw=2, linestyle='--', label=label) for label, (color, _) in phalanx_curves.items()],
129+
*[Patch(facecolor=color, alpha=0.1, label=label) for _, _, color, label in zones]
130+
]
131+
plt.legend(handles=legend_elements, fontsize=10, loc='lower right',
132+
bbox_to_anchor=(1, 0), ncol=2, handletextpad=0.5, columnspacing=1.5)
133+
134+
# Final layout and save
135+
plt.subplots_adjust(left=0.1, right=0.95, top=0.9, bottom=0.2)
136+
137+
plt.show()
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from matplotlib.patches import Patch
4+
5+
# Range for rho (Grinding Depth)
6+
rho = np.linspace(1, 256, 1000)
7+
f = 0.05
8+
cost_per_cpu_hour = 0.01 # $0.01 per CPU-hour
9+
10+
# Time window for computation (w_O)
11+
w_O = 20 * (2 * rho - 1)
12+
w_O_hours = w_O / 3600
13+
14+
# PRAOS cost functions
15+
def ant_glance_praos(rho): return 5e-10 * 2**(rho - 2)
16+
def ant_patrol_praos(rho): return ant_glance_praos(rho) + 2.16e-2 * 2**(rho - 1) / rho
17+
def owl_stare_praos(rho): return ant_glance_praos(rho) + 5e-2 * 2**(rho - 1) / rho
18+
def owl_survey_praos(rho): return ant_glance_praos(rho) + 7.16e-2 * 2**(rho - 1) / rho
19+
20+
# PHALANX curves (generalized)
21+
def phalanx_curve(multiplier):
22+
return lambda rho: (multiplier * 2**(rho - 1)) / rho
23+
24+
phalanx_1_100 = phalanx_curve(2.16e2)
25+
phalanx_1_10 = phalanx_curve(2.16e3)
26+
phalanx_max = phalanx_curve(2.16e4)
27+
28+
# Convert to log10 cost
29+
def compute_log_cost(n_cpu):
30+
return np.log10(np.maximum(n_cpu * cost_per_cpu_hour * w_O_hours, 1e-100))
31+
32+
# Scenario definitions
33+
scenarios = {
34+
"Ant Glance Praos": compute_log_cost(ant_glance_praos(rho)),
35+
"Ant Patrol Praos": compute_log_cost(ant_patrol_praos(rho)),
36+
"Owl Stare Praos": compute_log_cost(owl_stare_praos(rho)),
37+
"Owl Survey Praos": compute_log_cost(owl_survey_praos(rho)),
38+
"Phalanx$_{1/100}$": compute_log_cost(phalanx_1_100(rho)),
39+
"Phalanx$_{1/10}$": compute_log_cost(phalanx_1_10(rho)),
40+
"Phalanx$_{max}$": compute_log_cost(phalanx_max(rho)),
41+
}
42+
43+
# Color map for plot lines
44+
color_map = {
45+
"Ant Glance Praos": "blue",
46+
"Ant Patrol Praos": "orange",
47+
"Owl Stare Praos": "green",
48+
"Owl Survey Praos": "red",
49+
"Phalanx$_{1/100}$": '#6A5ACD',
50+
"Phalanx$_{1/10}$": '#228B22',
51+
"Phalanx$_{max}$": "#B22222"
52+
}
53+
54+
# Feasibility zones
55+
zones = [
56+
(-10, 4, 'green', 'Trivial'),
57+
(4, 6, 'yellow', 'Feasible'),
58+
(6, 9, '#FFA07A', 'Possible'),
59+
(9, 12, '#FF6347', 'Borderline Infeasible'),
60+
(12, 90, 'red', 'Infeasible')
61+
]
62+
63+
# Plot
64+
plt.figure(figsize=(12, 7))
65+
66+
# Draw curves
67+
for label, log_cost in scenarios.items():
68+
style = "-" if "Praos" in label else "--"
69+
plt.plot(rho, log_cost, label=label, color=color_map[label], linestyle=style, linewidth=2)
70+
71+
# Draw feasibility zones
72+
for y0, y1, color_zone, label in zones:
73+
plt.axhspan(y0, y1, color=color_zone, alpha=0.1, label=label)
74+
75+
# Axis labels and title
76+
plt.xlabel(r'$\rho$ (Grinding Depth)', fontsize=14)
77+
plt.ylabel(r'$\log_{10}(\mathrm{Cost\ (USD)})$', fontsize=14)
78+
plt.title('Cost of Grinding Attacks: Praos vs Phalanx Configurations', fontsize=16)
79+
plt.grid(True, linestyle='--', alpha=0.7)
80+
plt.xlim(0, 256)
81+
y_max = max(np.max(v[np.isfinite(v)]) for v in scenarios.values()) + 5
82+
plt.ylim(-5, y_max)
83+
84+
# Delta annotations
85+
def draw_delta(rho_val, praos_label, phalanx_label, x_offset=3):
86+
idx = np.argmin(np.abs(rho - rho_val))
87+
delta = scenarios[phalanx_label][idx] - scenarios[praos_label][idx]
88+
mid = scenarios[phalanx_label][idx] - delta / 2
89+
plt.annotate('', xy=(rho_val, scenarios[phalanx_label][idx]),
90+
xytext=(rho_val, scenarios[praos_label][idx]),
91+
arrowprops=dict(arrowstyle='<->', color='black', lw=1))
92+
plt.text(rho_val + x_offset, mid, f'$\\Delta \\approx {delta:.1f}$', fontsize=12, color='black',
93+
bbox=dict(facecolor='white', alpha=0.8, edgecolor='none'), verticalalignment='center')
94+
95+
draw_delta(50, "Ant Glance Praos", "Phalanx$_{1/100}$")
96+
draw_delta(125, "Owl Survey Praos", "Phalanx$_{1/100}$")
97+
draw_delta(150, "Owl Survey Praos", "Phalanx$_{1/10}$")
98+
draw_delta(175, "Owl Survey Praos", "Phalanx$_{max}$")
99+
100+
# Legend
101+
legend_elements = [
102+
plt.Line2D([0], [0], color='blue', lw=2, label='Ant Glance Praos'),
103+
plt.Line2D([0], [0], color='orange', lw=2, label='Ant Patrol Praos'),
104+
plt.Line2D([0], [0], color='green', lw=2, label='Owl Stare Praos'),
105+
plt.Line2D([0], [0], color='red', lw=2, label='Owl Survey Praos'),
106+
plt.Line2D([0], [0], color='#6A5ACD', lw=2, linestyle='--', label='Phalanx$_{1/100}$'),
107+
plt.Line2D([0], [0], color='#228B22', lw=2, linestyle='--', label='Phalanx$_{1/10}$'),
108+
plt.Line2D([0], [0], color='#B22222', lw=2, linestyle='--', label='Phalanx$_{max}$'),
109+
*[Patch(facecolor=color, alpha=0.1, label=label) for _, _, color, label in zones]
110+
]
111+
plt.legend(handles=legend_elements, fontsize=10, loc='lower right', bbox_to_anchor=(1, 0), ncol=2)
112+
113+
plt.subplots_adjust(left=0.1, right=0.95, top=0.9, bottom=0.2)
114+
plt.show()
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from matplotlib.patches import Patch
4+
5+
# Define the range for rho (Grinding Depth)
6+
rho = np.linspace(1, 256, 1000)
7+
f = 0.05
8+
cost_per_cpu_hour = 0.01 # $0.01 per CPU-hour
9+
10+
# Compute w_O in seconds and hours
11+
w_O = 20 * (2 * rho - 1)
12+
w_O_hours = w_O / 3600
13+
14+
# N_CPU functions with corrected Phalanx_{1/100} expressions
15+
def ant_glance_praos(rho):
16+
return 5e-10 * 2**(rho - 2)
17+
18+
def ant_glance_phalanx(rho):
19+
return ant_glance_praos(rho) + 216 * 2**(rho - 1) / rho
20+
21+
def ant_patrol_praos(rho):
22+
return ant_glance_praos(rho) + 2.16e-2 * 2**(rho - 1) / rho
23+
24+
def ant_patrol_phalanx(rho):
25+
return ant_patrol_praos(rho) + 216 * 2**(rho - 1) / rho
26+
27+
def owl_stare_praos(rho):
28+
return ant_glance_praos(rho) + 5e-2 * 2**(rho - 1) / rho
29+
30+
def owl_stare_phalanx(rho):
31+
return owl_stare_praos(rho) + 216 * 2**(rho - 1) / rho
32+
33+
def owl_survey_praos(rho):
34+
return ant_glance_praos(rho) + 7.16e-2 * 2**(rho - 1) / rho
35+
36+
def owl_survey_phalanx(rho):
37+
return owl_survey_praos(rho) + 216 * 2**(rho - 1) / rho
38+
39+
# Compute N_CPU and costs
40+
def compute_log_cost(n_cpu):
41+
return np.log10(np.maximum(n_cpu * cost_per_cpu_hour * w_O_hours, 1e-100))
42+
43+
scenarios = {
44+
"Ant Glance Praos": compute_log_cost(ant_glance_praos(rho)),
45+
"Ant Glance Phalanx$_{1/100}$": compute_log_cost(ant_glance_phalanx(rho)),
46+
"Ant Patrol Praos": compute_log_cost(ant_patrol_praos(rho)),
47+
"Ant Patrol Phalanx$_{1/100}$": compute_log_cost(ant_patrol_phalanx(rho)),
48+
"Owl Stare Praos": compute_log_cost(owl_stare_praos(rho)),
49+
"Owl Stare Phalanx$_{1/100}$": compute_log_cost(owl_stare_phalanx(rho)),
50+
"Owl Survey Praos": compute_log_cost(owl_survey_praos(rho)),
51+
"Owl Survey Phalanx$_{1/100}$": compute_log_cost(owl_survey_phalanx(rho)),
52+
}
53+
54+
# Plot
55+
plt.figure(figsize=(12, 7))
56+
colors = {"Ant Glance": "blue", "Ant Patrol": "orange", "Owl Stare": "green", "Owl Survey": "red"}
57+
58+
for label, log_cost in scenarios.items():
59+
name = label.split()[0] + " " + label.split()[1]
60+
style = "--" if "Phalanx" in label else "-"
61+
plt.plot(rho, log_cost, label=label, color=colors[name], linestyle=style, linewidth=2)
62+
63+
# Feasibility zones
64+
zones = [
65+
(-10, 4, 'green', 'Trivial'),
66+
(4, 6, 'yellow', 'Feasible'),
67+
(6, 9, '#FFA07A', 'Possible'),
68+
(9, 12, '#FF6347', 'Borderline Infeasible'),
69+
(12, 90, 'red', 'Infeasible')
70+
]
71+
for y0, y1, color, label in zones:
72+
plt.axhspan(y0, y1, color=color, alpha=0.1, label=label)
73+
74+
# Labels and layout
75+
plt.xlabel('$\\rho$ (Grinding Depth)', fontsize=14)
76+
plt.ylabel('$\\log_{10}(\\text{Cost (USD)})$', fontsize=14)
77+
plt.title('Cost of Grinding Attacks: Praos vs Phalanx$_{1/100}$ Scenarios', fontsize=16)
78+
plt.grid(True, linestyle='--', alpha=0.7)
79+
plt.xlim(0, 256)
80+
y_max = max(np.max(v[np.isfinite(v)]) for v in scenarios.values()) + 5
81+
plt.ylim(-5, y_max)
82+
83+
# Delta annotations
84+
def draw_delta(rho_val, praos_label, phalanx_label, x_offset=3):
85+
idx = np.argmin(np.abs(rho - rho_val))
86+
delta = scenarios[phalanx_label][idx] - scenarios[praos_label][idx]
87+
mid = scenarios[phalanx_label][idx] - delta / 2
88+
plt.annotate('', xy=(rho_val, scenarios[phalanx_label][idx]),
89+
xytext=(rho_val, scenarios[praos_label][idx]),
90+
arrowprops=dict(arrowstyle='<->', color='black', lw=1))
91+
plt.text(rho_val + x_offset, mid, f'$\\Delta \\approx {delta:.1f}$', fontsize=12, color='black',
92+
bbox=dict(facecolor='white', alpha=0.8, edgecolor='none'), verticalalignment='center')
93+
94+
draw_delta(50,"Ant Glance Praos" , "Owl Survey Phalanx$_{1/100}$" )
95+
draw_delta(100, "Owl Survey Praos", "Owl Survey Phalanx$_{1/100}$" )
96+
97+
# Legend
98+
legend_elements = [
99+
plt.Line2D([0], [0], color='blue', lw=2, label='Ant Glance Praos'),
100+
plt.Line2D([0], [0], color='blue', lw=2, linestyle='--', label='Ant Glance Phalanx$_{1/100}$'),
101+
plt.Line2D([0], [0], color='orange', lw=2, label='Ant Patrol Praos'),
102+
plt.Line2D([0], [0], color='orange', lw=2, linestyle='--', label='Ant Patrol Phalanx$_{1/100}$'),
103+
plt.Line2D([0], [0], color='green', lw=2, label='Owl Stare Praos'),
104+
plt.Line2D([0], [0], color='green', lw=2, linestyle='--', label='Owl Stare Phalanx$_{1/100}$'),
105+
plt.Line2D([0], [0], color='red', lw=2, label='Owl Survey Praos'),
106+
plt.Line2D([0], [0], color='red', lw=2, linestyle='--', label='Owl Survey Phalanx$_{1/100}$'),
107+
*[Patch(facecolor=color, alpha=0.1, label=label) for _, _, color, label in zones]
108+
]
109+
plt.legend(handles=legend_elements, fontsize=10, loc='lower right',
110+
bbox_to_anchor=(1, 0), ncol=2, handletextpad=0.5, columnspacing=1.5)
111+
112+
plt.subplots_adjust(left=0.1, right=0.95, top=0.9, bottom=0.2)
113+
plt.show()

0 commit comments

Comments
 (0)