Skip to content

chore(foundation): faster toBufferBE via zero fast-path#23592

Merged
PhilWindle merged 1 commit into
merge-train/spartanfrom
fc/faster-tobufferBE
May 27, 2026
Merged

chore(foundation): faster toBufferBE via zero fast-path#23592
PhilWindle merged 1 commit into
merge-train/spartanfrom
fc/faster-tobufferBE

Conversation

@fcarreiro

Copy link
Copy Markdown
Contributor

Summary

Adds a zero fast-path to toBufferBE, the bigint→big-endian-buffer conversion underlying Fr.toBuffer(). Field elements serialized in protocol structs are overwhelmingly zero (kernel public inputs are mostly fixed-size zero-padding), so short-circuiting the zero case avoids a wasteful bigint → hex string → Buffer.from(hex) round-trip.

if (num === 0n) {
  return Buffer.alloc(width);
}

Why

Profiling Tx.toBuffer() showed it spends ~6.7ms almost entirely in per-field Fr.toBuffer() across ~3900 fields, and 96% of those fields are zero. The scalar conversion is already near-optimal otherwise — a 64-bit-words variant (writeBigUInt64BE×4) is actually slower on real (non-zero) field elements because V8's bigint shifts allocate.

Micro-benchmark of toBufferBE variants (width=32, correctness-checked against current):

variant 96%-zero (real) all-random (worst case)
current 452 ns 382 ns
64-bit words 215 ns 503 ns (slower)
zero fast-path 55 ns 387 ns (free)

The fast-path is ~8× on the real workload and costs one === 0n compare on the worst case.

Impact

End-to-end on mockTx(42):

before after
tx.toBuffer() total 6.66 ms 4.20 ms (−37%)
data.toBuffer() 4.34 ms 2.25 ms (−48%)

data.toBuffer() (the kernel public inputs) is the production-relevant figure: the mock serializes an uncompressed proof, whereas real txs carry a compressed proof that serializes as a single blob. The benefit applies to every Fr.toBuffer() / serialization path in the monorepo, not just txs.

The remaining cost is structural — a Buffer is allocated per field and then Buffer.concat'd across thousands of them. Eliminating that needs a single-preallocated-buffer serializer; this change is the safe, broadly-beneficial first step.

Testing

toBufferBE previously had no direct unit tests; added coverage for the zero path, big-endian left-padding, exact-width values, and the negative-input throw. The conversion is otherwise byte-identical to before.

@fcarreiro fcarreiro changed the title perf(foundation): faster toBufferBE via zero fast-path chore(foundation): faster toBufferBE via zero fast-path May 27, 2026
@PhilWindle PhilWindle merged commit dcf7354 into merge-train/spartan May 27, 2026
16 of 17 checks passed
@PhilWindle PhilWindle deleted the fc/faster-tobufferBE branch May 27, 2026 15:50
danielntmd pushed a commit to danielntmd/aztec-packages that referenced this pull request Jun 4, 2026
BEGIN_COMMIT_OVERRIDE
fix(archiver): skip descendants of invalid-attestations checkpoints
(AztecProtocol#23502)
chore: scale network validators (AztecProtocol#23579)
fix(ci): nightly 10 TPS bench GCP auth and checkout (AztecProtocol#23586)
chore: set eth node resource profile (AztecProtocol#23583)
fix: wait for checkpoint before sentinel assertions (AztecProtocol#23573)
fix: slash attestations for invalid checkpoint proposals (AztecProtocol#23506)
test: fix web3signer pipelining
`e2e_multi_validator_node_key_store.test.ts` (AztecProtocol#23568)
fix: cap CI devbox hostname (AztecProtocol#23591)
test: stabilize invalid checkpoint descendant e2e (AztecProtocol#23582)
test(e2e): stabilize invalidation slots in `proposer invalidates
multiple checkpoints` (AztecProtocol#23590)
test(e2e): stabilize invalid proposal slashing target slot in
`attested_invalid_proposal` (AztecProtocol#23589)
chore(foundation): faster toBufferBE via zero fast-path (AztecProtocol#23592)
fix: honour BB_BINARY_PATH (AztecProtocol#23570)
chore: bump reth and lighthouse (AztecProtocol#23588)
chore: add web3signer and postgres node selectors (AztecProtocol#23598)
fix: do not symlink .codex folders (AztecProtocol#23593)
chore: fix claude and codex symlinking tests (AztecProtocol#23599)
test(e2e): narrow down sentinel check in `multiple_validators_sentinel`
(AztecProtocol#23604)
test(e2e): fix `proposer invalidates multiple checkpoints` timeout
(AztecProtocol#23608)
fix: record zero-amount slashing offenses (AztecProtocol#23556)
fix: log slashing offense names (AztecProtocol#23565)
feat(p2p): tx validation cache (AztecProtocol#23585)
chore: add KEDA deployment module (AztecProtocol#23553)
chore: add KEDA prover agent autoscaling (AztecProtocol#23554)
chore: update destroy_bootnode.sh (AztecProtocol#23626)
chore: skip failing chonk_pinned_inputs.test in CI (AztecProtocol#23643)
chore(ci): tolerate public authwit P2P receipt flake (AztecProtocol#23648)
END_COMMIT_OVERRIDE
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.

2 participants