Skip to content

chore: honk verifier opt + fix review#20547

Merged
Maddiaa0 merged 1 commit intonextfrom
md/honk-golf
Mar 20, 2026
Merged

chore: honk verifier opt + fix review#20547
Maddiaa0 merged 1 commit intonextfrom
md/honk-golf

Conversation

@Maddiaa0
Copy link
Copy Markdown
Member

@Maddiaa0 Maddiaa0 commented Feb 16, 2026

Overview

This has been submitted for audit already, so I've attempted to make the changes / optimizations as small as possible. I came across these while reading through it again for the zk verifier.

Commits are squashed to please CI - however ive pushed them to a mirror so they still exist within the repository

  • removing a scalar mul which was being multiplied by 1
  • LAGRANGE_FIRST is always (1,2), constant_term_acc is always multiplied by (1,2) so add the scalars together
  • the remaining are batching all inversions into the same modexp

This pr will be squashed - see md/honk-golf-all-commits for commit by commit break down

@Maddiaa0
Copy link
Copy Markdown
Member Author

@copilot can you remove the commit of barretenberg/sol/src/honk/instance/other.sol

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 17, 2026

@Maddiaa0 I've opened a new pull request, #20610, to work on those changes. Once the pull request is ready, I'll request review from you.

@Maddiaa0 Maddiaa0 changed the base branch from next to md/fix-verifier February 18, 2026 10:01
@Maddiaa0 Maddiaa0 marked this pull request as ready for review February 18, 2026 10:03
@Maddiaa0 Maddiaa0 requested a review from LHerskind February 18, 2026 10:03
for (int i = 0; i < BARYCENTRIC_DOMAIN_SIZE; ++i) {
print_fr(bary_pointer, "BARYCENTRIC_LAGRANGE_DENOMINATOR_" + std::to_string(i) + "_LOC");
bary_pointer += 32;
print_fr(pointer, "BARYCENTRIC_LAGRANGE_DENOMINATOR_" + std::to_string(i) + "_LOC");
Copy link
Copy Markdown
Member Author

@Maddiaa0 Maddiaa0 Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were starting from "scratch space", but I've leaned towards not re-using allocations due to memory having a trivial gas overhead

// INVERSIONS
print_header_centered("SHPLEMINI - RUNTIME MEMORY - INVERSIONS");

print_fr(pointer, "GEMINI_R_INV_LOC");
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stored in memory now as the inversion is performed before usage

out << "// LOG_N challenge pow minus u\n";
for (int i = 0; i < log_n; ++i) {
print_fr(pointer, "INVERTED_CHALLENEGE_POW_MINUS_U_" + std::to_string(i) + "_LOC");
print_fr(pointer, "INVERTED_CHALLENGE_POW_MINUS_U_" + std::to_string(i) + "_LOC");
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo fix


out << "\n";
print_fr(pointer, "LATER_SCRATCH_SPACE");
for (int i = 0; i < 8 * log_n; ++i) {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously these were located in LATER_SCRATCH_SPACE, i thought it would be better to explicitly provide their memory locations in the layout at the top of the file.

Hidden allocations could be a source of footguns when refactoring

Base automatically changed from md/fix-verifier to next February 19, 2026 15:22
Copy link
Copy Markdown
Contributor

@LHerskind LHerskind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using my 🥜 brain, but think there are a few unused bits than can be cut off. And then I am just curious about the first_lagrange really.

mulmod(mload(PUBLIC_INPUTS_DELTA_NUMERATOR_CHALLENGE), pi_delta_inv, p)
)
}

// Normalise as last loop will have incremented the offset
bary_centric_inverses_off := sub(bary_centric_inverses_off, 0x20)
for {} gt(bary_centric_inverses_off, SUM_U_CHALLENGE_14) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't this run for too long?

SUM_U_CHALLENGE_14 = 0x3cc0 and bary_centric_inversses_off = 0x4ce0, but the BARYCENTRIC_DENOMINATOR_INVERSES_0_0_LOC = 0x3de0 so it unds up looping more than planned and overwriting BARYCENTRIC_LAGRANGE_DENOMINATOR_7..0 (8 excess runs of the body). The accumulator and other values don't seem to be used afterwards, so it does not break currently, but just writing more than needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unbelievable catch, before this pr ( or maybe the last one ) barycentric_lagrange_denominator was in scratch space ( starting at 0x100 ). so this was correct, this pr updates such that the lagrange_denominators are stored in the slab with everything else. But does not update this pointer

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix is replacing SUM_U_CHALLENGE_14 with BARYCENTRIC_LAGRANGE_DENOMINATOR_7

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -4203,8 +4553,11 @@ contract BlakeOptHonkVerifier is IVerifier {
)

// Accumulator = accumulator + scalar[27] * vk[26]
// optimization - Lagrange first is always G - (1,2)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we absolutely sure that LAGRANGE_FIRST is always (1, 2)? Because then we should do that in both the optimized and base, to ensure that it is not different between the two variants and that will break together if it changes.

Copy link
Copy Markdown
Member Author

@Maddiaa0 Maddiaa0 Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it is - its enforced in the vk

let neg_inverted_denominator := mload(NEG_INVERTED_DENOM_0_LOC)
let shplonk_nu := mload(SHPLONK_NU_CHALLENGE)

unshifted_scalar := addmod(pos_inverted_denominator, mulmod(shplonk_nu, neg_inverted_denominator, p), p)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are onlysetting it here, we mightn ot need the separate let unshifted_scaler := 0 and then almost instantly setting it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah this was getting around a stack too deep

}
/// {{ UNROLL_SECTION_END ACCUMULATE_INVERSES }}

// Invert all elements (barycentric + PI delta + shplemini) as a single batch
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we apply similar checks as in Fr.sol to avoid trying to invert a 0 value? If there is one 0 we would end up fully making all the accumulator 0. It should be caught by other parts of the verification, but 🤷

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could, but if we invert a zero everything will blow up after

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure you read this value, seems to start at BATCH_SCALAR_1_LOC onwards.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep its now unused

uint256 internal constant BATCH_EVALUATION_ACCUMULATOR_INVERSION_13_LOC = 0x5f80;
uint256 internal constant BATCH_EVALUATION_ACCUMULATOR_INVERSION_14_LOC = 0x5fa0;

uint256 internal constant BATCHED_EVALUATION_LOC = 0x5fc0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you actually use this one. It looks like you store it in memory, but then you use the stack item batched_evaluation right after and not the memory variant.

@Maddiaa0 Maddiaa0 changed the title chore: lil bit of golfing on the ultra honk verifier chore: honk verifier opt + fix review Mar 10, 2026
Copy link
Copy Markdown
Contributor

@LHerskind LHerskind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor thing here.

Comment thread barretenberg/sol/src/honk/optimised/honk-optimized.sol.template Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we use this?


// --- Phase 2: Shplemini forward pass ---
// Compute shplemini denominators and accumulate into the running product.
// Pre-inversion values stored in staging area (0x6800+), NOT in
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The offset here looks stale now? Probably better to just refer to the constants by name or something?

Copy link
Copy Markdown
Member Author

Maddiaa0 commented Mar 20, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

## Overview

This has been submitted for audit already, so I've attempted to make the changes / optimizations as small as possible. I came across these while reading through it again for the zk verifier.

Commits are squashed to please CI - however ive pushed them to a mirror so they still exist within the repository
- removing a scalar mul which was being multiplied by 1
    - 699c7e2
- LAGRANGE_FIRST is always (1,2), constant_term_acc is always multiplied by (1,2) so add the scalars together
    - 6f2c350
- the remaining are batching all inversions into the same modexp
    - 05217b8
    - f1a5830

This pr will be squashed - see [md/honk-golf-all-commits](https://github.com/AztecProtocol/aztec-packages/tree/md/honk-golf-all-commits) for commit by commit break down

Co-authored-by: Alejo Amiras <alejo.amiras@gmail.com>
Co-authored-by: Alex Gherghisan <alexghr@users.noreply.github.com>
Co-authored-by: Ary Borenszweig <asterite@gmail.com>
Co-authored-by: Charlie Lye <5764343+charlielye@users.noreply.github.com>
Co-authored-by: David Banks <47112877+dbanks12@users.noreply.github.com>
Co-authored-by: Esau <esau@aztecprotocol.com>
Co-authored-by: Facundo <fcarreiro@users.noreply.github.com>
Co-authored-by: IlyasRidhuan <ilyasridhuan@gmail.com>
Co-authored-by: Jean M <132435771+jeanmon@users.noreply.github.com>
Co-authored-by: Jonathan Hao <jonathan@aztec-labs.com>
Co-authored-by: Jonathan Hao <jonathanpohsianghao@gmail.com>
Co-authored-by: Josh Crites <jc@joshcrites.com>
Co-authored-by: José Pedro Sousa <jose@aztecprotocol.com>
Co-authored-by: José Pedro Sousa <outgoing@zpedro.dev>
Co-authored-by: Khashayar Barooti <khashayar@aztecprotocol.com>
Co-authored-by: LHerskind <16536249+LHerskind@users.noreply.github.com>
Co-authored-by: Lasse Herskind <16536249+LHerskind@users.noreply.github.com>
Co-authored-by: Lucas Xia <lucasxia01@gmail.com>
Co-authored-by: MirandaWood <miranda@aztecprotocol.com>
Co-authored-by: Mitch <mitchell@aztecprotocol.com>
Co-authored-by: Mitchell Tracy <mitchellftracy@gmail.com>
Co-authored-by: Nicolás Venturo <nicolas.venturo@gmail.com>
Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com>
Co-authored-by: PhilWindle <philip.windle@gmail.com>
Co-authored-by: Raju Krishnamoorthy <krishnamoorthy@gmail.com>
Co-authored-by: Rumata888 <isennovskiy@gmail.com>
Co-authored-by: Santiago Palladino <santiago@aztec-labs.com>
Co-authored-by: Sarkoxed <sarkoxed2013@yandex.ru>
Co-authored-by: Savio <72797635+Savio-Sou@users.noreply.github.com>
Co-authored-by: StoneMac65 <StoneMac65@gmail.com>
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
Co-authored-by: benesjan <13470840+benesjan@users.noreply.github.com>
Co-authored-by: benesjan <janbenes1234@gmail.com>
Co-authored-by: critesjosh <18372439+critesjosh@users.noreply.github.com>
Co-authored-by: danielntmd <danielntmd@nethermind.io>
Co-authored-by: dbanks12 <david@aztec-labs.com>
Co-authored-by: fcarreiro <facundo@aztecprotocol.com>
Co-authored-by: federicobarbacovi <171914500+federicobarbacovi@users.noreply.github.com>
Co-authored-by: guipublic <47281315+guipublic@users.noreply.github.com>
Co-authored-by: iAmMichaelConnor <mike@aztecprotocol.com>
Co-authored-by: jeanmon <jean@aztec-labs.com>
Co-authored-by: jewelofchaos9 <jewelofchaos9@gmail.com>
Co-authored-by: josh crites <jc@joshcrites.com>
Co-authored-by: ledwards2225 <98505400+ledwards2225@users.noreply.github.com>
Co-authored-by: ledwards2225 <l.edwards.d@gmail.com>
Co-authored-by: lucasxia01 <lucasxia01@gmail.com>
Co-authored-by: ludamad <163993+ludamad@users.noreply.github.com>
Co-authored-by: ludamad <adam.domurad@gmail.com>
Co-authored-by: ludamad <domuradical@gmail.com>
Co-authored-by: mralj <nikola.mratinic@gmail.com>
Co-authored-by: nventuro <2530770+nventuro@users.noreply.github.com>
Co-authored-by: sergei iakovenko <105737703+iakovenkos@users.noreply.github.com>
Co-authored-by: sirasistant <sirasistant@gmail.com>
Co-authored-by: thunkar <gregojquiros@gmail.com>
@AztecBot AztecBot enabled auto-merge March 20, 2026 12:42
@AztecBot AztecBot added this pull request to the merge queue Mar 20, 2026
@ludamad ludamad added the claude-review Triggers an automated Claude code review label Mar 20, 2026
@AztecBot
Copy link
Copy Markdown
Collaborator

AztecBot commented Mar 20, 2026

Run #1 — completed (8m)
Live status

Reviewed #20547 — 8 files, no correctness issues found. The unified batch inversion, ecMul-by-1 removal, and LAGRANGE_FIRST scalar merge are all mathematically sound. Full analysis: https://gist.github.com/AztecBot/4b8b28b393bfbb91e2e285873ea7f1c0

Gist

@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Mar 20, 2026
@AztecBot AztecBot added claude-review-complete Claude code review has been completed and removed claude-review Triggers an automated Claude code review labels Mar 20, 2026
@Maddiaa0 Maddiaa0 added this pull request to the merge queue Mar 20, 2026
Merged via the queue into next with commit 762f1ee Mar 20, 2026
43 of 47 checks passed
@Maddiaa0 Maddiaa0 deleted the md/honk-golf branch March 20, 2026 13:52
saleel added a commit that referenced this pull request Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-no-squash claude-review-complete Claude code review has been completed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants