Skip to content

perf(bindings): drop TS BLS comparison benches and report benchmarks on PRs - #552

Merged
wemeetagain merged 7 commits into
ChainSafe:mainfrom
5t4rg4z3r:bls-benchmarks-ci
Aug 19, 2026
Merged

perf(bindings): drop TS BLS comparison benches and report benchmarks on PRs#552
wemeetagain merged 7 commits into
ChainSafe:mainfrom
5t4rg4z3r:bls-benchmarks-ci

Conversation

@5t4rg4z3r

@5t4rg4z3r 5t4rg4z3r commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Motivation

This repository should not be concerned with blst-ts benchmarks. Measure this repo's own code + add a way to see it on PRs.

Description

bindings/perf/blst.test.ts benchmarked @chainsafe/blst next to the lodestar-z bindings, which pulled the old typescript BLS implementation into the dependency tree only to produce comparison numbers. That comparison now lives in spiral-ladder/lodestar-bls-benchmarks.

Todo

  • Store benchmark history in S3 instead of the Actions cache #551 - History uses --local in the Actions cache rather than S3, since this repository has no bucket or credentials. A pull request restores the entry written by the last push to main; only a push to main saves a new one, so pull requests cannot move the baseline.

Verification

  • pnpm benchmark with a shortened budget: 30/30 benchmarks pass.
  • pnpm lint: 10 warnings, all pre-existing in bindings/src/index.d.ts, none in changed files.
  • pnpm install re-run so pnpm-lock.yaml matches the dependency change; the lockfile diff is large for that reason.
  • The workflow itself was not executed locally. Its if guard skips forked pull requests, so it will not run on this pull request either; it needs a push to main or workflow_dispatch after merge.

This PR was written by an AI agent (stargazer), supervised by a human.

@spiral-ladder spiral-ladder left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

for proper benchmark reporting this seems blocked by #551 , otherwise lgtm

Comment thread .github/workflows/benchmark.yml Outdated
benchmark:
name: benchmark
runs-on: ubuntu-latest
# Forks and dependabot get a read-only token, so the result comment cannot be posted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please change this to match upstream lodestar's comment

@5t4rg4z3r 5t4rg4z3r Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 0c5dff3. The comment now matches upstream lodestar.

This reply was written by an AI agent (stargazer), supervised by a human.

@5t4rg4z3r

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Both points noted.

The workflow comment will be changed to match upstream lodestar's wording. That is queued and will go up as a follow-up commit on this branch.

On #551: understood, and I agree that is the right sequencing for durable reporting. That issue is open and waiting on a maintainer to provision the bucket and secrets; I cannot add them from outside. Once they exist, the workflow change is small and I am happy to open it. Until then this branch keeps the Actions cache provider so the comparison comment still works for the common case.

I have not run the workflow itself, here or anywhere. Its fork guard means it does not execute on this pull request, so its behaviour remains unverified by me and needs a push to main or a workflow_dispatch after merge.

This comment was written by an AI agent (stargazer), supervised by a human.

@GrapeBaBa

Copy link
Copy Markdown
Contributor

The sample output shows lodestar-z is worse than chainsafe blst https://github.com/spiral-ladder/lodestar-bls-benchmarks, is it out of date?

@5t4rg4z3r

5t4rg4z3r commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Correction: I focused on the package versions and raw benchmark rows, but I missed the key question: which paths matter to Lodestar. I checked upstream Lodestar. I found no production calls to aggregateVerify or the synchronous aggregateWithRandomness. Lodestar does use verifyMultipleAggregateSignatures, aggregatePublicKeys, aggregateSignatures, and asyncAggregateWithRandomness.

The slower unused paths therefore do not show a current Lodestar performance concern. @spiral-ladder’s reply gives the correct interpretation. My prior comment was misguided. Sorry for the noise.

This comment was written by an AI agent (stargazer), supervised by a human.

@spiral-ladder

Copy link
Copy Markdown
Member

@GrapeBaBa ignore stargazer's comment, he isn't very smart still 😅

i assume you're referring to aggregateVerify and aggregateWithRandomness - those paths are slower but they aren't used anywhere in upstream lodestar so i'm not too concerned tbh, probably still worth looking into why they're slower but low prior imo?

@GrapeBaBa

Copy link
Copy Markdown
Contributor

@GrapeBaBa ignore stargazer's comment, he isn't very smart still 😅

i assume you're referring to aggregateVerify and aggregateWithRandomness - those paths are slower but they aren't used anywhere in upstream lodestar so i'm not too concerned tbh, probably still worth looking into why they're slower but low prior imo?

I saw blst have some good results with different sets in each category

@spiral-ladder

Copy link
Copy Markdown
Member

@GrapeBaBa now that #562 is in, some of those benchmarks might be redundant (since we no longer) use them

@5t4rg4z3r can you confirm

@5t4rg4z3r

Copy link
Copy Markdown
Contributor Author

Confirmed, with one timing caveat: Lodestar-Z #562 is merged, but the Lodestar switch in #9820 is still open.

On #9820 head b4020c06:

  • aggregateWithRandomness and asyncAggregateWithRandomness have no references under packages/.
  • aggregateVerify remains only in BLS spec tests.
  • aggregatePublicKeys and aggregateSignatures still have production callers.
  • verifyMultipleAggregateSignatures remains in processDeposit.

For Lodestar-facing performance coverage, the aggregateVerify, aggregateWithRandomness, and asyncAggregateWithRandomness groups can be replaced with benchmarks for verifySignatureSets and verifySignatureSetsSameMessage. Current Lodestar unstable has not made that switch yet.

This comment was written by an AI agent (stargazer), supervised by a human.

@wemeetagain

Copy link
Copy Markdown
Member

@5t4rg4z3r fix the merge conflict here

@spiral-ladder

Copy link
Copy Markdown
Member

@wemeetagain i set it to only reply to me for now 😁

@5t4rg4z3r fix the merge conflict

@spiral-ladder

Copy link
Copy Markdown
Member

but we might want to get #551 sorted before merging this?

@5t4rg4z3r

Copy link
Copy Markdown
Contributor Author

Confirmed. GitHub currently reports this PR as CONFLICTING / DIRTY. Resolving the merge conflict is queued for an execution-capable run.

I agree that durable benchmark reporting should wait on #551. That issue is still open and has no maintainer response yet. It needs repository S3 secrets before I can replace the Actions-cache provider, so I will keep #552 blocked on it rather than treat the current cache workflow as merge-ready.

This comment was written by an AI agent (stargazer), supervised by a human.

@5t4rg4z3r

Copy link
Copy Markdown
Contributor Author

Resolved in 85f24fa4. GitHub now reports this PR as mergeable. The merge keeps the lodestar-z-only benchmark scope and removes the aggregateWithRandomness and asyncAggregateWithRandomness groups deleted from current main.

Verification: scoped Zig formatting passed, pnpm lint exited 0 with 10 pre-existing warnings, the BLS binding tests passed 143/143, and the focused benchmark passed 20/20. #551 remains the separate reporting blocker.

This comment was written by an AI agent (stargazer), supervised by a human.

@wemeetagain
wemeetagain merged commit c909c6f into ChainSafe:main Aug 19, 2026
31 of 32 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Lodestar Team Coordination Aug 19, 2026
@github-actions github-actions Bot mentioned this pull request Aug 19, 2026
wemeetagain pushed a commit that referenced this pull request Aug 19, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.0.0](v0.1.2...v1.0.0)
(2026-08-19)


### Features

* add `state.getBuildersLength()` binding
([#472](#472))
([be2b5ab](be2b5ab))
* **beacon-node:** add block state cache and checkpoint datastore
([#452](#452))
([2145faa](2145faa))
* bindings to `getExpectedWithdrawals` and native tweaks
([#350](#350))
([f47bc66](f47bc66))
* **bindings:** add pubkey cache syncPubkeys
([#537](#537))
([542779f](542779f))
* **bindings:** aggregate cached public keys by validator index
([#397](#397))
([2f90603](2f90603))
* **bindings:** align `BeaconStateView` with `IBeaconStateView`
([#347](#347))
([b8ec273](b8ec273))
* **bindings:** configurable pubkey cache growth step
([#481](#481))
([133ef24](133ef24))
* **bindings:** expose more APIs for STF
([#444](#444))
([7fe2609](7fe2609))
* **bls:** add small MSM for npoints < 32
([#393](#393))
([b430638](b430638))
* **blst:** use external buffers for blst operations
([#358](#358))
([78e4678](78e4678))
* **ci:** conditionally publish bindings with tag
([#355](#355))
([ea77919](ea77919))
* **clock:** add clock module for slot/epoch timing
([#354](#354))
([385b077](385b077))
* **fork_choice:** add Prometheus metrics module
([#309](#309))
([cbc9d8d](cbc9d8d))
* **forkchoice:** implement the forkchoice module
([#246](#246))
([7c62a9b](7c62a9b))
* getSyncCommitteesWitness
([#367](#367))
([ef77649](ef77649))
* implement `loadState` API and binding
([#165](#165))
([f903519](f903519)),
closes [#159](#159)
* **metrics:** metrics bindings
([#455](#455))
([dd41999](dd41999))
* migrate blst,pubkeys to use zapi js dsl
([#331](#331))
([fcd26ca](fcd26ca))
* **pubkeys:** add getPubkeyBytes binding
([#555](#555))
([4ca51cf](4ca51cf))
* publish ARM64 musl bindings
([#482](#482))
([ac764c9](ac764c9))
* **shuffle:** add swap-or-not shuffling module and binding
([#559](#559))
([c2db37c](c2db37c))
* split nextValue fn
([#464](#464))
([b47faeb](b47faeb))
* support getLatestWeakSubjectivityCheckpointEpoch
([#366](#366))
([dcf3883](dcf3883))
* update fulu deposit processing
([#442](#442))
([064335c](064335c))


### Bug Fixes

* avoid set ([#484](#484))
([2e25d97](2e25d97))
* better generation of rand scalar
([#388](#388))
([74dce77](74dce77))
* **bindings:** accept `dontTransferCache` in processSlots for backward
compatibility
([#460](#460))
([65df5af](65df5af))
* **bindings:** check signature infinity by default
([#509](#509))
([2f5f281](2f5f281))
* **bindings:** clean up failed async BLS work
([#527](#527))
([1111b00](1111b00))
* **bindings:** free metrics writer on scrape failure
([#529](#529))
([4c8d94a](4c8d94a))
* **bindings:** harden random aggregate scalars
([#528](#528))
([8e89a63](8e89a63))
* **bindings:** log level for missing fields
([#435](#435))
([08faf41](08faf41))
* **bindings:** misordering of print for cpu count
([#381](#381))
([752a972](752a972))
* **bindings:** populate epoch participation for test fixtures
([#436](#436))
([8dbdd2e](8dbdd2e))
* **bindings:** refcount Pool to fix teardown panic
([#352](#352))
([23b2f68](23b2f68))
* **bindings:** roll back partial N-API initialization
([#491](#491))
([31c5ebb](31c5ebb))
* **bindings:** size BLS thread pool by cgroup-aware CPU count
([#386](#386))
([3ae9522](3ae9522))
* **bindings:** validate class types before unwrap
([#514](#514))
([2fd2ad5](2fd2ad5))
* **bindings:** validate secret key hex length
([#517](#517))
([136e415](136e415))
* **bls:** align PublicKey.uncompress validation with
Signature.uncompress
([#508](#508))
([5a8dbe9](5a8dbe9))
* **bls:** bound randomized aggregation inputs
([#548](#548))
([779d0bf](779d0bf)),
closes [#542](#542)
* **bls:** clean up partial thread pool initialization
([#490](#490))
([d55e598](d55e598))
* **bls:** convert pippenger scratch bytes to element counts
([#513](#513))
([a12ca92](a12ca92))
* **bls:** enforce 32-byte signing roots
([#545](#545))
([72fd308](72fd308))
* **bls:** make batch cardinality structural
([#547](#547))
([a06d8b2](a06d8b2))
* **bls:** preserve aggregate outputs on failure
([#521](#521))
([e0b6dd1](e0b6dd1))
* **bls:** reject empty keygen salts
([#524](#524))
([d2a9c86](d2a9c86))
* **bls:** reject unknown BLST error codes
([#525](#525))
([9e4a6ad](9e4a6ad))
* **bls:** size pairing buffers for 32-bit targets
([#531](#531))
([dc64a27](dc64a27))
* **blst:** default signature infinity check to true if not provided
([#387](#387))
([021cdcb](021cdcb))
* **build:** remove `zig-out` from `files`
([#360](#360))
([c52af09](c52af09))
* **ci:** fix caching spec test version
([#439](#439))
([96885a1](96885a1))
* dangling state pointer in loadOtherState
([#450](#450))
([81cbd5f](81cbd5f))
* **epoch_cache:** compute missing `next_proposers`
([#447](#447))
([0088a29](0088a29))
* **epoch_cache:** populate decision roots in afterProcessEpoch
([#453](#453))
([4b70a5e](4b70a5e))
* export asyncAggregateWithRandomness through napi binding
([#371](#371))
([1d04c2b](1d04c2b))
* harden memory safety across PMT, SSZ tree views, and state transition
([#377](#377))
([d6f5897](d6f5897))
* improve atomic ordering in ThreadPool and NAPI init
([#310](#310))
([4b0a1cc](4b0a1cc))
* interface compatbility with NativeBeaconStateView
([#445](#445))
([89e13d1](89e13d1))
* missing deinits in loadOtherState
([#459](#459))
([094d278](094d278))
* missing state commits
([#454](#454))
([a432b55](a432b55))
* no-op when syncPubkeys run on a pk cache with shrinking validator set
([#432](#432))
([ed05a99](ed05a99))
* param order in BeaconBlockBody
([#348](#348))
([d8b9c06](d8b9c06))
* pendingConsolidations bindings
([#449](#449))
([b9c497e](b9c497e))
* **pmt,ssz:** harden chunked-leaf and zero-copy tree-view memory safety
([#400](#400))
([de50c53](de50c53))
* populate cache balances during rewards/penalties processing
([#474](#474))
([5bf23dc](5bf23dc))
* re-expose sizes
([#369](#369))
([64b81f3](64b81f3))
* remove `slashValidator` gating on active status
([#448](#448))
([d319a0d](d319a0d))
* **ssz:** drop redundant default-init pass in fixed-list decode
([#468](#468))
([0c757be](0c757be))
* **ssz:** publish child cache entries after lookup
([#565](#565))
([21e78c9](21e78c9))
* state transition binding exports
([#456](#456))
([895982c](895982c))
* **state-transition:** group-check signature sets
([#515](#515))
([42774e9](42774e9)),
closes [#502](#502)
* **state-transition:** isolate epoch step cache mutations
([#535](#535))
([a83741a](a83741a))
* **state-transition:** repair Pool.init call broken by
[#346](https://github.com/ChainSafe/lodestar-z/issues/346)×[#367](https://github.com/ChainSafe/lodestar-z/issues/367)
merge skew ([#394](#394))
([b42944f](b42944f))
* various fixes around config
([#433](#433))
([c4f082c](c4f082c))


### Performance Improvements

* **bindings:** drop TS BLS comparison benches and report benchmarks on
PRs ([#552](#552))
([c909c6f](c909c6f))
* **bls:** add cache-aware signature verifier
([#562](#562))
([063857e](063857e))
* **bls:** bypass worker queue for small batches
([#553](#553))
([3f8a6df](3f8a6df))
* **epoch:** replace AutoHashMap with array lookup in reward/penalty
caches ([#286](#286))
([e4e181b](e4e181b)),
closes [#243](#243)
* **pmt:** chunked-leaf packing for basic lists and container_struct
([#346](#346))
([ba156c4](ba156c4))


### Code Refactoring

* allocate `AsyncAggRandData` in one obj
([#384](#384))
([459750f](459750f))
* **bindings/pubkeys:** simplify allocation strategy for aggregate
([#518](#518))
([b82750f](b82750f))
* **bindings:** rename blst Lifecycle to State
([#516](#516))
([0a9c179](0a9c179))
* **bindings:** use zapi js.io() instead of local io module
([#469](#469))
([2b34cc0](2b34cc0))
* **bindings:** wake only required number of workers
([#383](#383))
([1db57f1](1db57f1))
* **bls:** allocations around VMAS
([#395](#395))
([dfda58c](dfda58c))
* **bls:** clean up bls
([#398](#398))
([e0f3b9b](e0f3b9b))
* **bls:** remove need for tracking results for
verifyMultipleAggregateSignatures
([#389](#389))
([6fe5c3f](6fe5c3f))
* **bls:** remove single-threaded fallback
([#390](#390))
([e057713](e057713))
* **clock:** single public Clock; internalize SlotClock
([#463](#463))
([fbab1fa](fbab1fa))
* make XXXDecisionRoot fns return `js.String`
([#342](#342))
([aef4420](aef4420))
* move shuffle into swap_or_not_shuffle module
([#558](#558))
([e56efb2](e56efb2))
* **pubkeys:** centralize the process-wide cache
([#522](#522))
([dc9669d](dc9669d))


### Miscellaneous Chores

* avoid slow tests in AGENTS.md
([#546](#546))
([c60f2a9](c60f2a9))
* bump zapi to include musl build
([#485](#485))
([0b488cc](0b488cc))
* **ci:** pin github actions with sha hashes
([#507](#507))
([167b8f5](167b8f5))
* deprecate unused blst APIs
([#575](#575))
([7b547fa](7b547fa))
* **deps:** bump zapi v2.1.0 -> v2.2.0
([#376](#376))
([0c240d8](0c240d8))
* **deps:** bump zbuild
([#403](#403))
([e2545de](e2545de))
* **deps:** compile blst with ReleaseFast
([#391](#391))
([753a896](753a896))
* **deps:** update zapi to 3.1.0
([#483](#483))
([f3e5827](f3e5827))
* **deps:** use zapi v2.1.0
([#372](#372))
([88f403a](88f403a))
* disable gemini auto code review
([#382](#382))
([63e42a4](63e42a4)),
closes [#380](#380)
* **docs:** add comments section in AGENTS.md
([#566](#566))
([0c09750](0c09750))
* move state clones out of benchmark run functions
([#324](#324))
([e4035de](e4035de))
* prepare 1.0.0 release
([#576](#576))
([20b657b](20b657b))
* release v0.1.2-rc.3
([#370](#370))
([e4fc551](e4fc551))
* **release:** 0.1.2-rc.2
([#365](#365))
([7046128](7046128))
* **release:** v0.1.2-rc.10
([#477](#477))
([9a4fad5](9a4fad5))
* **release:** v0.1.2-rc.4
([#373](#373))
([09468f1](09468f1))
* **release:** v0.1.2-rc.5
([#374](#374))
([f344efa](f344efa))
* **release:** v0.1.2-rc.6
([#375](#375))
([bdf5b67](bdf5b67))
* **release:** v0.1.2-rc.8
([#401](#401))
([06f91c2](06f91c2))
* **release:** v0.1.2-rc.9
([#404](#404))
([6024800](6024800))
* remove merge transition code
([#359](#359))
([09b175d](09b175d))
* remove stale epoch cache TODOs
([#534](#534))
([27a547a](27a547a))
* rename era shortHistoricalRoot to shortEraRoot
([#473](#473))
([c75a4d3](c75a4d3))
* **scripts:** build bindings with preset
([#434](#434))
([a1b5ef7](a1b5ef7))
* silence debug log when used in release builds
([#486](#486))
([c5377d7](c5377d7))
* support dev workflow
([#364](#364))
([fcb9a78](fcb9a78))
* update gloas types to align with the latest specs
([#431](#431))
([1f065b5](1f065b5))
* update spec test version to v1.7.0-alpha.11
([#451](#451))
([5875660](5875660))
* update spec-test-version: v1.6.0-beta.2 -> v1.7.0-alpha.10
([#441](#441))
([f932b1c](f932b1c))
* update zapi to 4.0.0
([#571](#571))
([de8e3fd](de8e3fd))


### Documentation

* document security threat model
([#557](#557))
([e678b87](e678b87))
* more comprehensive AGENTS.md
([#520](#520))
([c74b386](c74b386))
* **pkix:** document load provenance requirement
([#556](#556))
([37e0aa2](37e0aa2))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants