mirror of
https://github.com/logos-blockchain/research.git
synced 2026-08-10 21:23:12 +00:00
Measure the W = 12 pairing instead of asserting it
The report had twice recommended pairing the parent-anchored window with W = 12, argued from the shape of the mechanism -- a parent gap running one to two block-intervals longer consumes that much window -- but never measured. Swept under the adversary that exposed the cost in the first place (the capstone's geometry, 30 % uncle suppression, U = 2, k = 2160, 12 replicates): uncle W=10 (today's recipe) : D-hat 0.9916 p_ref 0.933 parent W=10 : D-hat 0.9851 p_ref 0.913 parent W=12 (proposed pair) : D-hat 0.9908 p_ref 0.924 Parent-anchored at W = 12 lands within +0.0008 of today's recipe -- parity inside one standard error -- so the anchor's cost under a suppressing adversary is bought back exactly by the two extra block-intervals the longer parent gap consumes. p_ref recovers more slowly (matching only at W = 15) but stays far above the ~0.3 the soft rule needs, so it does not bind the recommendation. The operative conclusion, now supported: adopt the anchor change and W = 12 TOGETHER, or neither. At W = 10 the anchor costs 0.0065 under this adversary, which is the one regime where it is not free. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
de618d7ea8
commit
c4577e7062
@ -815,6 +815,18 @@ The floor rises by one to two block-intervals, which is what the ~one-block-inte
|
||||
|
||||
**The uncle cap rule is unchanged.** Sizing `U` is the other half of the recipe, and it is not affected: the smallest cap reaching the 0.98 bar is identical under both anchors at every load tested (`configs/window-uncles-anchor.yaml`, `W` = 10 held slack) — `U` = 1 at `ρ` = 0.27 and 0.47, `U` = 2 at 0.87, and neither anchor clears at `ρ` = 1.27, which is past the operating point the recipe permits anyway. `U = ⌈ρ⌉ + 1` therefore carries over verbatim. At that recommended cap the residual cost is small and stays inside the design regime: `−0.003` at `ρ` = 0.47 and 0.87, growing to `−0.009` only at `ρ` = 1.27. The anchor's cost lives in the window, not in the cap.
|
||||
|
||||
**`W = 12` restores it — measured, not inferred.** The pairing this section recommends was first argued from the shape of the mechanism; sweeping the window under the adversary that exposed the cost settles it (`configs/pref-window-anchor.yaml`, the capstone's geometry, 30 % suppression, 12 replicates):
|
||||
|
||||
| `W` | uncle-anchored: `D̂/D` / `p_ref` | parent-anchored: `D̂/D` / `p_ref` |
|
||||
|---|---|---|
|
||||
| 8 | 0.9852 / 0.917 | 0.9724 / 0.877 |
|
||||
| **10** (today) | **0.9916 / 0.933** | 0.9851 / 0.913 |
|
||||
| **12** (proposed pair) | 0.9965 / 0.942 | **0.9908 / 0.924** |
|
||||
| 15 | 0.9921 / 0.912 | 0.9946 / 0.943 |
|
||||
| 20 | 0.9971 / 0.945 | 0.9958 / 0.944 |
|
||||
|
||||
Parent-anchored at `W` = 12 lands within **+0.0008** of today's uncle-anchored `W` = 10 — parity inside one standard error — so the anchor's cost under a suppressing adversary is bought back exactly by the two extra block-intervals the longer parent gap consumes. `p_ref` recovers more slowly (0.924 against 0.933, matching only at `W` = 15), but it is far above the `≳ 0.3` the soft rule needs either way, so it does not bind the recommendation. **Adopt the anchor change and `W = 12` together, or neither**: at `W` = 10 the anchor costs 0.0065 under this adversary, which is the one regime where the change is not free.
|
||||
|
||||
**One further observation, and it sharpens the case.** At `δ_max` = 16 the *honest* uncle-anchored arm already reaches **315 slots** — past its own `w_u` = 300. Under the current rule `w_u` is not a bound on how far back validation reaches even with no adversary present; under the parent rule the same cell is 296. The parameter only becomes a state-retention bound once it is anchored to the parent.
|
||||
|
||||

|
||||
@ -965,7 +977,7 @@ The deltas this report recommends, in one place. This is a parameter-selection r
|
||||
| on-chain `f` precision | 10⁻³ (`f_p = 0.033`) | **10⁻⁶** (`0.033333`) | removes the residual ≈ 1 % `f/f_p` offset ([§2.2](#s2-2)) |
|
||||
| uncle window `W` | `W` = 10 block-intervals, so `w_u = W/f` = 300 slots, bounded `1 ≤ W ≤ ⌊0.6k⌋` | **10/f = 300 slots** (confirms the default), widen to 450–600 near `ρ ≈ 1` | the floor is ≥ 7/f, set by block *spacing* rather than network delay — which supplies what the spec's rationale leaves out. The spec justifies the *upper* bound (a candidate within `w_u` is still in the proposer's block tree, and referencing blocks stay in the same epoch as the window they count) and asserts of the value itself only that this window "comfortably captures the forks worth referencing"; it states no lower bound, and 300 slots is only a ~1.5× margin over the measured one. The `⌊0.6k⌋` ceiling is 1296 slots at k = 2160, so the 450–600 widening recommended near `ρ ≈ 1` — where W = 600 recovers ≈ 0.99 against ≈ 0.96 at W = 300 (N = 1 000) — is well inside what the spec already permits, and needs no spec change ([§3.4](#s3-4)) |
|
||||
| uncle cap `U` | `MAX_UNCLES` = 4 | **`⌈ρ⌉ + 1`** = 2 at the Blend target — well inside the spec's cap of 4 | the load-plus-margin rule ([§3.3](#s3-3)); 4 leaves headroom for heavier loads |
|
||||
| uncle reference window anchor | the **uncle's** slot: `0 < sl_A − sl_U ≤ w_u` | **the uncle's PARENT's slot**: `sl_A − sl_parent(U) ≤ w_u` | the current rule bounds which block may be referenced but not how far back verifying it reaches, so a 30 % coalition forces counted references against state ~76 800 slots old (~21 h, 256× the window). The parent anchor is strictly tighter — it implies the uncle bound rather than adding to it — caps the reach at `w_u`, and costs no honest recovery at the recommended cap. It does raise the [§3.4](#s3-4) window floor by one to two block-intervals (the parent gap runs that much longer), so a deployment adopting it should size `W` against the parent gap — `W = 12` restores the margin `W = 10` has today, well inside the spec's `⌊0.6·k⌋` bound ([§6.12](#s6-12)) |
|
||||
| uncle reference window anchor | the **uncle's** slot: `0 < sl_A − sl_U ≤ w_u` | **the uncle's PARENT's slot**: `sl_A − sl_parent(U) ≤ w_u` | the current rule bounds which block may be referenced but not how far back verifying it reaches, so a 30 % coalition forces counted references against state ~76 800 slots old (~21 h, 256× the window). The parent anchor is strictly tighter — it implies the uncle bound rather than adding to it — caps the reach at `w_u`, and costs no honest recovery at the recommended cap. It does raise the [§3.4](#s3-4) window floor by one to two block-intervals (the parent gap runs that much longer), so a deployment adopting it should size `W` against the parent gap — `W = 12` restores the margin `W = 10` has today — measured to parity within one standard error — well inside the spec's `⌊0.6·k⌋` bound ([§6.12](#s6-12)) |
|
||||
| peering degree | (operator choice) | **≥ 6, scaled with N** | keeps `ρ` and reorg depth bounded at scale ([§3.7](#s3-7), [§6.10](#s6-10)) |
|
||||
| uncle rewards | none (spec: uncle grants no block reward) | **soft inclusion, `w_u + w_n < 1`** | fork-safe fairness + anti-hiding ([§6.7](#s6-7)–[§6.8](#s6-8)) |
|
||||
| operating point | set by the Blend privacy budget | **`ρ = f·D_vis < 1`** | accuracy, weak grinding, shallow reorgs — one rule ([§6.3](#s6-3), [§6.10](#s6-10)) |
|
||||
@ -1024,7 +1036,7 @@ Sweep studies are committed configs, run with `make <name>` (writes a dated `run
|
||||
| **uncle cap under a private chain** (`U` × `W` × `α` against the SM1 engine adversary, plus the structural/queue decomposition of the honest orphans) | `scripts/selfish_uncle_margin.py` (`adversary_strategy: selfish`); `runs/selfish_uncle_margin{,_decomp}.parquet` | [§6.8](#s6-8) |
|
||||
| **profit/deflation frontier** (how far a *paid* adversary can deflate `D̂`; the deflation-optimal MDP) | `scripts/deflation_frontier.py` (`selfish_mdp.deflation_frontier`, `.deflation_optimal_stats`); fig37 | [§6.6](#s6-6) |
|
||||
| **uncle- vs parent-anchored reference window** (honest recovery cost, and an adversary's reach into historical state) | `scripts/uncle_parent_window.py` (`uncle_window_anchor`, `adversary_strategy: deep_parent`); `runs/uncle_parent_window{,_effort}.parquet`; fig38 | [§6.12](#s6-12) |
|
||||
| **the sizing rules re-measured under both anchors** (the `W` floor at `U` = 1; the `U` rule at `W` = 10) | `configs/absorption-window-anchor.yaml`, `configs/window-uncles-anchor.yaml` | [§3.4](#s3-4), [§6.12](#s6-12) |
|
||||
| **the sizing rules re-measured under both anchors** (the `W` floor at `U` = 1; the `U` rule at `W` = 10; the `W` pairing under a suppression adversary) | `configs/absorption-window-anchor.yaml`, `configs/window-uncles-anchor.yaml`, `configs/pref-window-anchor.yaml` | [§3.4](#s3-4), [§6.8](#s6-8), [§6.12](#s6-12) |
|
||||
| **the deployed operating point** (`δ_max` = 4 from the spec's Blend profile; the three `f`-precision arms) | `scripts/spec_point.py` (`f_precision`); `runs/spec_point.parquet` | [§2.2](#s2-2), [§8.5](#s8-5), [Appendix A](#sA) |
|
||||
| **per-recipient delay variance** (jitter 0–8 slots × `U`, both referencing models, exact oracle) | `scripts/spec_jitter.py`, `configs/spec-point-jitter.yaml`; `runs/spec_jitter.parquet` | [§6.1](#s6-1), [§8.3](#s8-3) item 15 |
|
||||
| **the spec point at scale and by window** (`N` = 5000; `W_abs` sweep at `δ_max` = 4) | `configs/spec-point-n5000.yaml` (run twice, `--old`), `configs/spec-point-window.yaml` | [§3.4](#s3-4), [§8.5](#s8-5) |
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
# Does widening W restore what the parent anchor costs under a suppression adversary? (§6.8, §6.12)
|
||||
#
|
||||
# The capstone found the one place the anchor change actually bites: honest recovery is
|
||||
# unaffected, but under a 30 % uncle-suppression coalition the parent-anchored rule drops to
|
||||
# D_hat = 0.974 with p_ref = 0.875, against 0.994 / 0.936 for the spec's rule. The two effects
|
||||
# compound — a tighter effective window leaves an orphan fewer chances to be referenced before
|
||||
# its PARENT ages out, and a suppressing adversary removes some of those chances by declining to
|
||||
# reference from its own blocks.
|
||||
#
|
||||
# The report now recommends pairing the anchor change with W = 12 to restore the margin. That
|
||||
# recommendation has been asserted from the shape of the mechanism and not yet measured, which is
|
||||
# what this config is for: sweep W across both anchors, with and without the adversary, and read
|
||||
# off whether a wider window buys back p_ref and the estimate.
|
||||
#
|
||||
# Geometry is the capstone's, so the answer lands on the recommended configuration rather than a
|
||||
# probe point: delta_max = 8 (rho ~ 0.47), U = 2 = ceil(rho)+1, degree 6, k = 2160.
|
||||
# Latency is in SLOTS (1 slot = 1 s).
|
||||
n_nodes: [1000] # network size
|
||||
stake_dist: [pareto] # heavy-tailed (realistic) stake distribution
|
||||
topology: [blend] # Blend mixnet — the deployment transport
|
||||
degree: [6] # peering degree of the d-regular graph
|
||||
link_latency_mean: [0.5] # natural geographic transport (sub-slot)
|
||||
link_latency_dist: [geo] # real-world geographic band mixture
|
||||
blend_hops: [3] # the spec's Blend cascade length
|
||||
blend_delay_max: [8.0] # the capstone's operating point, rho ~ 0.47
|
||||
window_absorption: [8, 10, 12, 15, 20] # W in block-intervals; 10 = today, 12 = proposed
|
||||
uncle_window_anchor: [uncle, parent] # spec rule vs the §6.12 proposal
|
||||
max_uncles: [2] # the recommended cap U = ceil(rho)+1
|
||||
uncle_strategy: [oldest] # spec Uncle Selection
|
||||
init_dest: [common] # per-node initial D_est from agreement
|
||||
replicates: 12
|
||||
base: # per-run settings shared by every cell
|
||||
k: 2160 # true security parameter
|
||||
epochs: 20 # equilibrium within ~2 epochs; burn 50%
|
||||
f: 0.03333333333333333 # slot activation coefficient (1/30)
|
||||
genesis_d_factor: 0.5 # start near true stake (cheap epoch 0)
|
||||
early_stop: true
|
||||
adversary_frac: 0.3 # the capstone's suppression coalition
|
||||
adversary_strategy: suppress # references no uncles from its own blocks
|
||||
Loading…
x
Reference in New Issue
Block a user