Skip to content

leanvm_core: each table's sum from its join message, no Bus tables pass - #740

Open
nconsigny wants to merge 1 commit into
leanEthereum:mainfrom
nconsigny:pr/bus-sigma
Open

nconsigny wants to merge 1 commit into
leanEthereum:mainfrom
nconsigny:pr/bus-sigma

Conversation

@nconsigny

Copy link
Copy Markdown
Contributor

The table sumcheck needs each table's sum sigma_t against eq(zeta[..tau_t]) before its first round. Until now the bus computed it in a pass of its own ("Bus tables": eq_sums over every column of every table, plus the forms' column products), which reads every committed column once more than the sumcheck does (about 0.56 GB at aggregate --sphincs 500). Since eq factors, sigma_t = (1 + zeta_m) p(0) + zeta_m p(1) at m = tau_t - 1, where p(0), p(1) are the endpoints of the table's join-round message, and that message reads no challenge. So the sumcheck now takes the join message with both endpoints in Table::new, the join round sends the stored one, and the batch starts from the bus target the verifier derives. eq_sums, tables_and_prods_at, BusForm::sum_at and BusProof.sigmas are removed (net -60 lines).

Measured on base e5d75f8, Ryzen 9 9955HX3D (Zen 5), 16 threads (taskset -c 0-15), --repeat 3 --cooldown 1, medians of paired ABBA differences (branch - base) with [min, max], 6 pairs on rate-1/4 workloads, 3 elsewhere. S500/S480 = aggregate --sphincs 500/480, X1400 = aggregate --xmss 1400.

rate 1/4, S500 rate 1/4, S480
Bus tables + Prove constraints -9.4 ms [-20.8, -6.4] -11.9 ms [-29.6, -8.8]
Prove -0.8 ms [-37.3, +11.3] (-0.1%) -23.7 ms [-34.0, -8.0], 6/6 (-2.0%)
  • Rate 1/2 (3 pairs): Prove -20.0 ms at S500, -12.7 ms at S480.
  • X1400, rate 1/4: no slowdown (-10.5 ms by median pass).
  • Throughput at S500, rate 1/4: 391.4 -> 396.4 signatures/s (+1.3%).

Caveats:

  • The S500 Prove difference is within noise. The median of the absolute Prove times moved by -16.0 ms, but the paired median is -0.8 ms.
  • Spans come from one traced pass and vary by about +-10 ms run to run. Prove varies by about +-30 ms between passes.
  • One machine only. The box was not fully idle: about one core of foreign niced load.

The proof is byte for byte the same, and the verifier is unchanged:

  • The join message is the same field elements as before.
  • The sums equal the old ones, and the starting claim equals the old one on any proof that verifies.
  • No transcript write was added, removed or reordered.
  • Checked: leaf proofs of recursion --n 1 --sphincs-per-leaf 16 --leaf-log-inv-rate 2 have the base's sha256 (199,521 B). A reviewer checked three more leaf shapes. All 458 proofs of the benchmark runs verified.

Tests:

  • New, join_message_gives_the_table_sum: checks the derived sigma against sum_z eq(zeta[..tau], z) P(z), for tau in {0, 1, 3, 4, 5, 12}.
  • round_messages_match_naive_evaluation now checks both endpoints of the join message.
  • Two debug assertions: the tables' sums against the target (this replaces the per-side assertion that was removed), and a waiting table sending its stored message only on its join round. The leanvm_core tests pass with release debug assertions on.
  • Every test that proves and verifies covers the change. A sumcheck's honest messages are unique, so a different message would fail verification. As a check, sending the wrong endpoint of the stored message fails all three proving tests in leanvm_core/tests/verifiers.

Memory: no change in peak RSS. The join messages of shorter tables need their own eq tables, one per distinct height ((2^17 + 2^16) x 24 B, about 4.7 MB at S500). They are built and dropped before the first round.

The table sumcheck needs each table's sum sigma_t against eq(zeta[..tau_t])
before its first round, for the line a waiting table contributes. The bus
computed it in a pass of its own ("Bus tables": eq_sums over every column
of every table, plus the forms' column products), which read every
committed table column once more than the sumcheck does: 0.56 GB at
--sphincs 500.

eq factors, so sigma_t = (1 + zeta_m) p(0) + zeta_m p(1) at m = tau_t - 1,
for the endpoints p(b) of the table's join-round cofactor. That message
reads no challenge, only eq(zeta[..m]), which is what the batch's eq table
has shrunk to by then, so the sumcheck now takes it, with both endpoints,
before its first round (message_k returns [p(0), p(1), quadratic], the
upper rows' linear forms being the lower rows' plus those of lo + hi), and
the join round sends the stored one; a debug assertion checks that a table
that has not joined is asked only on that round. The batch's starting
claim is the bus's derived target, sum_s xi^(base+s) (V_s(zeta) less the
framework blocks), as on the verifier, and a debug assertion checks the
tables' sums against it; eq_sums, tables_and_prods_at, BusForm::sum_at and
BusProof.sigmas go.

The messages are the same field elements, and the target equals the old
claim on an honest witness, so the proof is byte for byte the same (leaf
proofs of `recursion --n 1 --sphincs-per-leaf 16 --leaf-log-inv-rate 2`
match the base's sha256). round_messages_match_naive_evaluation checks
both endpoints, and a new test checks the derived sum against
sum_z eq(zeta[..tau], z) P(z) from one row to 2^12; the release tests with
debug assertions on check the target.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant