refactor(blst): use lodestar-z pubkey cache - #9728
Conversation
|
https://github.com/spiral-ladder/pubkey-cache-benchmarks This is a standalone personal repo benchmarking the original pk cache vs the new one, instructions to reproduce, results and more details in the README. TLDR: pubkey aggregation is about ~15% faster across different set sizes, lookups are slower (since lookups have to cross napi boundary) cc @twoeths you might be interested in this |
thanks for the statistic @spiral-ladder
|
Address review feedback from ChainSafe/lodestar#9728 (comment): - Aggregate sizes are now 1, 32, 128, and 512. Size 512 covers a full committee at 1M active validators (1M / 32 slots / 64 committees). - New indexed cases compare getOrThrow() + toBytes() with the native getPubkeyBytes() from lodestar-z d479f339, matching the BLS worker job path that consumes Uint8Array pubkeys. getPubkeyBytes had 26% lower latency than getOrThrow() + toBytes(). - Refresh README results from a new run on the same machine.
updated the benchmarks with new sample output. This uses:
|
Expose the cached 48-byte compressed pubkey bytes by validator index without materializing a PublicKey wrapper or serializing in JS. The BLS worker job path in Lodestar needs Uint8Array pubkeys, so this avoids the getOrThrow() + toBytes() round trip on the SingleAttestation gossip validation hot path. Refs ChainSafe/lodestar#9728 (comment)
There was a problem hiding this comment.
I was supposed to post this asyncAggregateWithRandomness() improvement but @wemeetagain already implemented it here
bing/blst-pk-cache...cayman/blst-pk-cache
i kinda think this might be small enough that we can make this part of this PR? I would be comfortable letting this soak for a few more days before next release if we change this |
|
I guess one caveat is this would be mostly replaced by the new branch that @wemeetagain is working on edit: lol u edited too |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## bing/blst-z #9728 +/- ##
===============================================
- Coverage 52.58% 52.58% -0.01%
===============================================
Files 848 848
Lines 59977 59975 -2
Branches 4418 4418
===============================================
- Hits 31540 31538 -2
Misses 28378 28378
Partials 59 59 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dab776d058
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| addPubkey(index: ValidatorIndex, pubkey: Uint8Array): void { | ||
| this.pubkeyCache.set(index, pubkey); | ||
| this.pubkeyCache.append(index, pubkey); |
There was a problem hiding this comment.
Preserve pubkeys for competing states
When two valid competing blocks extend the same pre-state with different deposits, each can assign a different pubkey to the same new validator index. The process-wide native cache is append-only and cannot remap an existing index, so after the first branch calls append, processing the second branch either fails or continues using the first branch's pubkey, causing valid signatures on the second branch to be rejected. The cache must support branch-specific mappings or avoid publishing unfinalized registry additions globally.
Useful? React with 👍 / 👎.
| const headroomEpochs = (90 * 24 * 60 * 60) / (config.SECONDS_PER_SLOT * SLOTS_PER_EPOCH); | ||
| const pubkeyCacheHeadroom = MAX_PENDING_DEPOSITS_PER_EPOCH * Math.ceil(headroomEpochs); | ||
| pubkeyCache.ensureCapacity(anchorState.validators.length + pubkeyCacheHeadroom); |
There was a problem hiding this comment.
Account for pre-Electra registry growth
For a node started before Electra, new validators can be added by up to MAX_DEPOSITS per slot, but this reservation assumes the post-Electra limit of MAX_PENDING_DEPOSITS_PER_EPOCH per epoch. At the maximum pre-Electra rate, the advertised 90-day headroom is exhausted in roughly 90 / SLOTS_PER_EPOCH days, after which append reallocates while BLS worker threads may be reading, despite the preceding comment identifying that operation as unsafe. Size the reservation according to the active fork or make growth synchronized.
AGENTS.md reference: AGENTS.md:L187-L197
Useful? React with 👍 / 👎.
asyncAggregateWithRandomness now resolves public keys from the native
pubkey cache by validator index, so same-message signature sets carry
{index, signature} and the per-attestation getOrThrow + PublicKey object
crossing on gossip validation disappears.
cb43ace to
dab776d
Compare
|
my claude force pushed while i was working on something oops |
Motivation
Replaces the pk cache implementation with calls to the native centralized cache.
Description
Reverts 'refactor: restore TS pubkey cache, use lodestar-z for BLS crypto only' (d614a9e) and adapts call sites to the refactored native pubkey cache API from ChainSafe/lodestar-z#522
Sample output
AI Assistance Disclosure
codex-gpt-sol was used to generate this code