Skip to content

perf(l1): decrypt L1 deposits in parallel off the engine task - #1389

Closed
mattsse wants to merge 1 commit into
mainfrom
mattsse/perf-parallel-deposit-prepare
Closed

perf(l1): decrypt L1 deposits in parallel off the engine task#1389
mattsse wants to merge 1 commit into
mainfrom
mattsse/perf-parallel-deposit-prepare

Conversation

@mattsse

@mattsse mattsse commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

L1BlockDeposits::prepare ran the full ECIES pipeline (ECDH, Chaum-Pedersen proof, AES-GCM) inline for every encrypted deposit, and the leader awaits it from ZoneEngine::advance before block production starts. A block near the portal's cap of 230 deposits stalled the engine's tokio worker for the whole duration, and the key ring lock was taken and a SecretKey cloned per deposit.

Each deposit's result depends only on its key, its payload and the portal address, so keys are now resolved once per distinct index and the per-deposit work runs on rayon inside spawn_blocking, collected through an indexed pipeline so order and contents are unchanged. A missing key index fails with the same error, now before any crypto runs, and blocks without encrypted deposits stay inline. Per-deposit log lines may now interleave.

Timed with a throwaway harness over 230 encrypted deposits on a loaded 12-core machine, dev build with the crypto crates at opt-level 3: median wall time per call drops from roughly 200-225 ms to 32-37 ms, the minimum from 117 ms to 21 ms. For a single deposit the thread hop adds about 50 µs against roughly 260 µs of crypto it moves off the engine.

`L1BlockDeposits::prepare` was an async fn without an await that ran the
full ECIES pipeline — ECDH, Chaum-Pedersen proof and AES-GCM — for every
encrypted deposit inline. The leader awaits it from `ZoneEngine::advance`
before block production starts, so a block near the portal's cap of 230
deposits stalled the tokio worker driving the engine for the entire time.

Each deposit's result only depends on its decryption key, its own payload
and the portal address, so the secrets are now resolved once per distinct
key index up front and the per-deposit work runs on rayon inside
`spawn_blocking`, collected in order so the queued deposits and their
decryption data keep their exact positions. A missing key index still
fails with the same error, now before any crypto runs. Blocks without
encrypted deposits skip the thread hop and only ABI-encode inline.

Timed with a throwaway harness over 230 encrypted deposits on a loaded
12-core M-series machine, with the crypto crates built at opt-level 3:
median wall time per call drops from ~200-225 ms to ~32-37 ms, minimum
from ~117 ms to ~21 ms.

@mattsse mattsse left a comment

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.

not worth doing since we dont see a lot of deposits in the same block

@mattsse mattsse closed this Sep 3, 2026
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