Skip to content

Ghost's next build: the four levers reopened by "fastest wins" #209

Description

@defenwycke

Ghost is defined as the fastest non-Core code we can get. That definition reopens levers previously closed on cost/benefit — each was rejected because the fidelity spend was not worth the gain, and under "fastest wins" that reasoning no longer applies.

Baseline to beat: GHOST = 1,198,904,653 cycles, 11.467x, straggler 1.407, 5 cards (docs/BUILDS.md).

Ghost sits at 4.05 of 5 cards. A straggler of 1.35 instead of 1.407 makes it four. That is a 4% packing improvement worth 20% of the fleet, and it is the cheapest item here.


1 · Ghost packer calibration — do this first

Worth a card. Cheapest thing on the list. Never been done.

Ghost has never had its cost model calibrated. Core's refit took its straggler 1.557 → 1.311; the same refit applied to Ghost made it worse — 1.407 → 1.884, and 1.996 with the field backend.

The likely cause: I rescaled Ghost's Schnorr constant by the old 13.77x ECDSA ratio, but the liftx hint removes pubkey decompression from both curves (taproot key-path spends call lift_x too), so that ratio should have narrowed. Keeping it over-prices Schnorr inputs.

Method: HAZYNC_CHUNKS=16 HAZYNC_PROFILE_EXEC=1 host chunk-profile, least-squares fit (ecdsa, schnorr, bytes, inputs) → cycles — and this time fit the two curves separately rather than rescaling a stale ratio. The constants are already runtime-overridable (HAZYNC_COST_EC_OP etc.).

Also unmeasured: GHOST's straggler at default constants. It is assumed 1.407 from the no-backend arm. That assumption is what says 5 cards rather than 4.

2 · MSM batch verification

Previously: rejected. Sized at 9.24x over a whole block but 4.3x at chunk scale after the checks it cannot remove — worth one card, 5 → 4, in exchange for removing libsecp from per-signature verification and a Fiat-Shamir soundness argument needing outside review.

Now: that card counts. The primitive is already in-tree, tested, off by default (prover/methods/guest/src/msm.rs). → docs/history/MSM_BATCH_VERIFY.md

⚠ Interacts with (1): both target the same card. Do the calibration first and re-size MSM against what remains.

3 · Wholesale bigint2

Previously: the middle path was chosen because wholesale "buys at most ONE card" for 15% more speed. Now: 15% is 15%.

⚠ Re-measure rather than trust the old figure — it was taken before the field backend, which changes what the non-ECDSA residual costs.

4 · G3 Schnorr and scalar-inverse re-measure

Both were sized before the liftx hint landed. The hint changes the ECDSA:Schnorr cost ratio (see 1), so their contributions have moved and neither has been re-measured in the current build.


Method

Each lever measured independently against the pinned GHOST baseline, in execute mode on CPU, with:

  • the journal digest byte-identical to 4fb3e3c5…4656d — a mismatch voids the arm
  • a two-sided binary symbol assertion before any number counts. Eight silent no-ops were caught this way in one session; every one would have reported a moved METHOD_ID and a clean digest while measuring nothing.
  • the straggler read from measured cycles, never predicted

Wall-clock on a GPU confirms at the end, not per lever.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions