Skip to content

feat: add Octobear curve and multiset hash on koalabear#832

Open
yelhousni wants to merge 34 commits into
masterfrom
feat/kb8
Open

feat: add Octobear curve and multiset hash on koalabear#832
yelhousni wants to merge 34 commits into
masterfrom
feat/kb8

Conversation

@yelhousni
Copy link
Copy Markdown
Collaborator

@yelhousni yelhousni commented Apr 15, 2026

Description

This PR adds support for the Octobear curve over the degree-8 extension of KoalaBear field and introduces a native multiset hash built on top of it, including a post-quantum vector extension. The target use case is circuit-friendly multiset hashing for computations defined over the KoalaBear field, in particular zkVM memory arguments that will later be verified inside SNARK circuits.

Concretely, this PR:

  • adds the new ecc.OCTOBEAR curve and the ecc/octobear package
  • reuses field/koalabear for the base field and adds shared E8 support in field/koalabear/extensions
  • adds the octobear curve arithmetic, scalar field, generator config, and tests
  • adds ecc/octobear/multiset-hash, implementing three flavors of multiset hash on octobear:
    • classical one-point ECMSH via the deterministic y-increment map (uint16 messages)
    • vector ECMSH with a linear domain separator (N=23 coordinates, T=128, M=2^18, uint32 messages)
    • vector ECMSH with a Poseidon2-sponge domain separator (N=23 coordinates, T=256, width-16 sponge, uint64 messages)
  • adds recursive cube-root support over the KoalaBear extension tower used by the Cardano solver
  • updates the generator/templates needed to support octobear while keeping the rest of the repository green

The one-point construction maps uint16 messages by searching y = 256*m + k for k < 256, solving the resulting depressed cubic over Fp^8, and accumulating mapped points on octobear. The final implementation uses recursive Cardano with binary Lucas sequences at every extension level.

The vector construction keeps N=23 independently domain-separated ECMSH accumulators. After Shor's algorithm computes discrete logarithms, a collision in the vector digest reduces to a bounded modular linear relation, i.e. a SIS-shaped problem with modulus r ≈ 2^248 and dimension N=23 (23·248 = 5704 bits, matching the Linea KoalaBear LtHash baseline). The linear separator is cheap but leaves a "probably" structurally regular post-Shor matrix; the Poseidon2 separator pays a sponge cost but yields a less structured matrix and is the preferred concrete derivation. Both variants preserve inverse-freeness (y_i < p/2) by construction.

Type of change

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How has this been tested?

The following checks pass locally:

  • go test ./field/koalabear/extensions ./ecc/octobear/...

Additional validation performed during development:

  • exhaustive Map(uint16) validation over all 65536 inputs of the one-point variant
  • per-coordinate inverse-free invariant (y_i < p/2) checked on sampled messages for both vector variants
  • homomorphic additivity (Hash(A ∪ B) == Hash(A) + Hash(B) componentwise) for both vector variants

How has this been benchmarked?

Benchmarks were run locally on a MacBook Pro class machine (darwin/arm64, Apple M5, 32GB RAM) with:

go test ./ecc/octobear/multiset-hash -bench . -run '^$'

Current results:

  • BenchmarkMap-10: 25440 ns/op
  • BenchmarkAccumulatorInsert-10: 6896592 ns/op (256 inserts of the one-point variant)
  • BenchmarkHash256-10: 6802114 ns/op (one-point hash over 256 messages)
  • BenchmarkMapLinear-10: 512971 ns/op (linear vector map for one message → 23 points)
  • BenchmarkMapPoseidon2-10: 570382 ns/op (Poseidon2 vector map for one message → 23 points)
  • BenchmarkHashLinear256-10: 157928583 ns/op (linear vector hash over 256 messages)
  • BenchmarkHashPoseidon2_256-10: 160487518 ns/op (Poseidon2 vector hash over 256 messages)

Checklist:

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • I did not modify files generated from templates
  • golangci-lint does not output errors locally
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Note

Medium Risk
Medium risk due to adding a large amount of new generated cryptographic field arithmetic (including arch-specific assembly) and extending the global ecc.ID/field mappings, which could affect downstream curve selection and serialization if misused.

Overview
Adds a new curve identifier OCTOBEAR to ecc.ID, wiring it into IDFromString, String(), and ScalarField/BaseField lookups, and updates the top-level ecc package docs accordingly.

Introduces a new ecc/octobear subtree: an fp package that aliases the existing field/koalabear base field, plus a full generated scalar-field implementation in fr (Element/Vector APIs, exp/sqrt/cbrt helpers, tests/benchmarks, and amd64/arm64 assembly + purego fallbacks).

Updates .golangci.yml to ignore octobear in misspell.

Reviewed by Cursor Bugbot for commit 8d7eba4. Bugbot is set up for automated code reviews on this repo. Configure here.

@yelhousni yelhousni marked this pull request as draft April 15, 2026 04:08
Comment thread ecc/bls12-377/marshal.go
@yelhousni yelhousni marked this pull request as ready for review April 21, 2026 22:17
@yelhousni yelhousni changed the title feat: add KB8 curve feat: add KB8 curve and multiset hash on koalabear Apr 21, 2026
@yelhousni yelhousni self-assigned this Apr 21, 2026
@yelhousni yelhousni added this to the v0.19.N milestone Apr 21, 2026
Comment thread ecc/octobear/fr/element.go
Comment thread internal/generator/main.go Outdated
Comment thread ecc/octobear/fp/fp.go
Comment thread ecc/kb8/multiset-hash/cardano.go Outdated
@gbotrel
Copy link
Copy Markdown
Collaborator

gbotrel commented May 7, 2026

Review pass from 2026-05-07.

Findings:

  • Blocking: staticcheck CI is correctly failing because the generated code is stale. The Actions log reports that go generate leaves the repository dirty, with a diff in ecc/kb8/fr/element.go (the generated exponentiation helpers differ from the committed file). Please run the generator and commit the resulting generated file before this PR is used as the dependency for gnark #1757.

Verification run locally:

  • go test ./field/koalabear/extensions ./ecc/kb8/...

@yelhousni yelhousni requested a review from ivokub May 7, 2026 18:48
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 913fcc2. Configure here.

Comment thread ecc/bn254/multiexp_glv.go Outdated
Comment thread ecc/bn254/multiexp_glv.go Outdated
The `1<<32-1` literal in MultiExpGLVWide's nbPoints guard overflows
the 32-bit int on GOARCH=386, breaking the CI `go test -json` step
that runs on ./ecc/bn254/... under 32-bit. The build failure emits
a JSON event with empty Package, which makes gotestfmt v2.5.0 panic
with "BUG: Empty package name encountered" and fails the test job.

Cast through uint64 and compare against math.MaxUint32 so the
constant compiles cleanly under both 32- and 64-bit int.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@ivokub ivokub left a comment

Choose a reason for hiding this comment

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

Sending first round of review. This is mostly about the code generation part.

I think for some implementation having hand-written files is fine, but in that case they should explicilty not have the "DO NOT EDIT" header, this breaks the automatic deletion logic. And I think we can still even now have more code-generation coverage and avoid switching in the generator function on concrete curves (and rather use attribute-base generation logic). Please see the inline comments.

I will do the curve implementation and multiset hash in another round. But it would be easier if we would have more code-generated parts (for the ECC even), so that I know everything matches the templates. What was the block change why files in ecc/kb8 had to be hand-written, not generated? Imo seems quite similar to other curves?

Comment thread internal/generator/field/template/extensions/e8.go.tmpl
Comment thread internal/generator/field/generator_extensions.go Outdated
Comment thread internal/generator/field/generator_field.go Outdated
Comment thread internal/generator/fieldwrapper/template/fp.go.tmpl
Comment thread internal/generator/config/curve.go Outdated
Comment thread internal/generator/main.go Outdated
Comment thread ecc/bn254/multiexp_glv.go Outdated
@yelhousni yelhousni changed the title feat: add KB8 curve and multiset hash on koalabear feat: add Octobear curve and multiset hash on koalabear May 21, 2026
@yelhousni yelhousni requested a review from ivokub May 21, 2026 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants