Skip to content

perf(e2e): overlap and batch e2e setup transactions#24569

Open
spalladino wants to merge 2 commits into
spl/e2e-genesis-fund-sponsored-fpcfrom
spl/e2e-overlap-setup-txs
Open

perf(e2e): overlap and batch e2e setup transactions#24569
spalladino wants to merge 2 commits into
spl/e2e-genesis-fund-sponsored-fpcfrom
spl/e2e-overlap-setup-txs

Conversation

@spalladino

Copy link
Copy Markdown
Contributor

Stacked on #24564; retarget to merge-train/spartan-v5 after it merges.

Overlaps the serial setup-tx chains in the fees and cross-chain e2e harnesses so independent setup transactions share production slots instead of paying one slot each. Part of the round-4 e2e speedup effort.

Commits

  • perf(e2e): overlap fees harness setup txs — after FeesTest.setup deploys BananaCoin, the BananaFPC deploy, the SponsoredFPC registration (a PXE registration, no L2 tx), and Alice's banana mints each depend only on the token, so the fees suites (account_init, gas_estimation, private_payments) now run them under a Promise.all. The cross-chain harness (deployAndInitializeTokenAndBridgeContracts) deploys the L2 token and its bridge concurrently: the bridge takes the token address as a constructor arg, but that address is deterministic before the deploy tx mines (the deploy is now constructed with an explicit deployer, same address derivation as the previous send-time lock), and the bridge constructor only stores it without calling into the token.
  • perf(e2e): parallelize dual token mintsapplyFundAliceWithBananas sent the private and public mints back-to-back (measured 100% serial: tx:mint busyMs == totalMs == 23.9s on the base). They touch disjoint balances, so they are now sent concurrently. Each mint keeps its own tx:mint span, so the overlap shows up directly as busyMs < totalMs.

Dependency analysis

  • FPC deploy needs the token address (constructor arg) → runs after the token deploy, concurrent with the mints.
  • Mints need the token → concurrent with the FPC deploy, and the private/public mints are mutually independent.
  • SponsoredFPC setup is a wallet registration only → free to join the Promise.all.
  • TokenBridge's initializer stores {token, portal} in its own storage and never calls the token, so the bridge deploy does not need the token to be mined first.
  • perf(e2e): seed BananaFPC fee juice at genesis instead of bridging #24564 invariants preserved: BANANA_COIN_SALT/BANANA_FPC_SALT + deployer: alice are untouched, and the genesis-funded-address assertion in applyFPCSetup still runs (and passed locally).

Same-sender concurrency

Concurrent .send() calls from the same sender through the same TestWallet are safe: the PXE serializes simulateTx/proveTx through a SerialQueue (#putInJobQueue), so simulations never interleave and only the block-inclusion waits overlap. The setup txs pay fees from Alice's public fee-juice balance (PREEXISTING_FEE_JUICE) with random tx nonces, so there are no nullifier or note conflicts between the concurrent txs. Verified locally with full Promise.all of the send+wait calls; no NO_WAIT fallback or cross-sender split was needed.

Skipped: batching token class+instance publication (planned commit 2)

Not applicable on this base: DeployMethod.request() already merges class publication, instance publication, and the constructor call into a single execution payload sent as one tx (getPublicationExecutionPayload + getInitializationExecutionPayload → a single wallet.sendTx). Measured locally, deploy:token is a single ~12s (1 slot) occurrence, not two txs in separate blocks; the ~24s occurrences in the CI span data are inclusion latency at CI cadence, not a second tx. There is nothing to batch.

Local verification (12s slots; CI runs 24s slots so absolute savings roughly double there)

  • Base (account_init, spans on): 5/5 passed; beforeAll 83.5s = setup:auth-registry 32.0s + deploy:token 12.0s + tx:mint 23.9s (busyMs == totalMs, fully serial) + deploy:fpc 11.8s.
  • After (account_init, spans on): 5/5 passed; beforeAll 72.2s (−11.3s); tx:mint busyMs 24.0s < totalMs 36.0s (the overlap proof), deploy:fpc fully overlapped with the mint window. The serial token→mints→FPC tail compressed from 47.7s to ~36s; the remaining 32s is the auth-registry publish that perf(e2e): seed standard contracts at genesis #24568 removes.
  • gas_estimation: 3/3 passed; ideal overlap shape — tx:mint busyMs 11.8s vs totalMs 23.3s (both mints shared one slot), deploy:fpc 23.7s fully inside the mint window; beforeAll 71.6s.
  • private_payments: 8/8 passed; tx:mint busyMs 24.1s vs totalMs 36.0s; beforeAll 104.9s (includes the epoch-proving wait).
  • token_bridge (exercises the cross-chain harness overlap): 7/7 passed; deploy:token 12.1s and deploy:bridge 23.7s ran concurrently (union ≈ 23.7s). CI baseline for the same suite paid 24.1s + 24.0s fully serial (≈48s), so the overlap saves ~24s per harness creation at CI cadence.
  • l2_to_l1 (cross-chain path without the token bridge): 6/6 passed, regression check on the untouched path.
  • No intermittent failures across the five runs.

Expected effect

~2–4 min/run across the fees and cross-chain suite family once #24568 lands (which removes the auth-registry cost): roughly 2 slots saved per fees shard (mint pair + FPC overlap) and 1 slot per cross-chain harness creation. The tx:mint busyMs < totalMs gap is the direct proof metric; measured CI numbers to be appended after the fix-phase run.

The BananaFPC deploy, SponsoredFPC registration, and Alice's banana mints
each depend only on the BananaCoin deployed during FeesTest.setup, so the
fees suites now run them concurrently instead of paying one production slot
per step. Likewise the cross-chain harness deploys the L2 token and its
bridge concurrently: the bridge takes the token address as a constructor
arg, but that address is deterministic before the deploy tx mines, and the
bridge constructor does not call into the token.
applyFundAliceWithBananas sent Alice's private and public banana mints
back-to-back, paying one production slot each. The two mints touch disjoint
balances, so they are now sent concurrently and share a slot. Each mint
keeps its own tx:mint span, so the overlap shows up as busyMs < totalMs in
the timing data.
@spalladino spalladino added the ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure label Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant