EIP-712 canonical-type collection re-parses whole build infos
Los mantenedores suelen responder en 2 días
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 48/100
- Tipo de issue
- Refactorización
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
- Área
- performance
Línea de trabajo
Empieza en packages/hardhat/src/internal/builtin-plugins/solidity-test/eip712/index.ts y luego lee ast-walker.ts, canonicalize.ts y edr-artifacts.ts para entender el solapamiento entre el análisis y la carga de artefactos. Ejecuta el escenario documentado del profiler de pnpm para establecer la línea base antes de evaluar el caching, la recopilación en tiempo de compilación o el análisis compartido. Se considera terminado cuando los tipos canónicos y el comportamiento de las pruebas sean idénticos, y el coste repetido de parseJsonBytes se haya eliminado o reducido según las mediciones del profiling.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Hardhat's JS-side EIP-712 pipeline (builtin-plugins/solidity-test/eip712/) prepares the eip712CanonicalTypes config field for EDR. Its own logic costs milliseconds, but it parses entire build-info outputs — the AST-bearing JSON for all compiled sources — to extract a handful of struct definitions.
Measured in the Hardhat 3 + EDR profiling campaign on aave-v4's hardhat test solidity run, the only benchmark suite configuring EIP-712 types:
- JS side: 1.35 s of
parseJsonBytesunder the collector — 1.21 s ≈ 37% of active JS ≈ 6% of wall - EDR side: ~1.1 s in its native EIP-712 collector on the same run
- Combined: ~2.3 s ≈ 12% of that 19 s test run
Three structural inefficiencies: the parse is a superset (full ASTs, bytecode and metadata materialised for a few struct definitions); the result is recomputed on every test run even though build infos are immutable per build id; and the artifact loader may read the same build infos in the same run. Cost is zero when unconfigured — collection short-circuits on an empty include.
Direction
In order of likely payoff: cache the collected canonical types by build id plus EIP-712 config (build infos are content-addressed, so invalidation is trivial and warm runs pay ~0); or collect at compile time, where the output JSON is already in memory, storing a small artifact that test runs load instead of walking ASTs; or, if parsing must stay on the test path, share the parsed build info with the artifact loader rather than parsing twice.
Note: this collector is being moved to Rust (EDR feat/eip712-collector-crate-and-inline-config), including compile-time collection — so the remaining JS-side scope here may reduce to caching and shared parsing.
Implementation plan
# Stop re-parsing whole build infos in the EIP-712 canonical-type collector
## Problem
[Profiling Hardhat 3 e2e scenarios](https://app.notion.com/p/nomicfoundation/Runtime-Profiling-2026-08-05-3b3578cdeaf5808eafdff4e22ba425d0?source=copy_link) measures the JS-side EIP-712 canonical-type collection on aave-v4's `hardhat test solidity` run at 1.35 s of `parseJsonBytes` self-time under `collectEip712CanonicalTypes` — 1.21 s ≈ 37% of active JS ≈ **6% of wall**. EDR spends a further ~1.1 s in its native EIP-712 collector on the same run, so EIP-712 preparation totals ~2.3 s ≈ **12% of that 19 s test run**.
The collector's own logic costs milliseconds; the cost is the parsing. It is zero in scenarios that configure no EIP-712 types, since collection short-circuits on an empty `include`.
## Root cause
`packages/hardhat/src/internal/builtin-plugins/solidity-test/eip712/index.ts` — `collectEip712CanonicalTypes` parses **entire build-info output files** (`SolidityBuildInfoOutput`, the AST-bearing JSON for every compiled source) with `parseJsonBytes`, walks each source's AST (`ast-walker.ts`) and canonicalises struct definitions (`canonicalize.ts`). Three structural inefficiencies:
1. **Superset parsing** — the document carries full ASTs, bytecode and metadata for every source, while the collector needs only struct definitions and user-defined value types from selected sources. `JSON.parse` is all-or-nothing, so everything is materialised. A `bytesIncludesUtf8String` pre-filter exists; check what it actually filters out here.
2. **Recomputed every run** — build-info outputs are immutable per build id, yet canonical types are re-collected on every `hardhat test solidity` invocation.
3. **Duplicate parsing** — the artifact loading path may read the same build info in the same run; check `edr-artifacts.ts` (`BuildInfoAndOutput`) for overlap.
## Task
1. Reproduce the baseline (see Verification), and add a temporary timing log around `collectEip712CanonicalTypes` for aave-v4.
2. Evaluate, in order of likely payoff:
- **Cache by build id**: persist the collected canonical types keyed by build id plus EIP-712 config, next to the build info or in the cache directory. Build infos are content-addressed, so invalidation is trivial, and warm test runs pay ~0.
- **Collect at compile time**: compute the canonical types once at the end of compilation, where the output JSON is already in memory, and store them as a small artifact — test runs then load a tiny file instead of walking ASTs. Weigh the cost for users who never run EIP-712 Solidity tests; the config gate can decide.
- **Cheaper extraction**, if parsing must stay on the test path: share the parsed build-info object with the artifact loader when both need it in one run, or extract only the `ast` subtrees of selected sources — worthwhile only if measurements justify the complexity.
3. Behaviour must be identical: same canonical type strings, same `include`/`exclude` semantics, same cross-file dependency inlining (non-selected sources still feed the dependency graph — see the doc comment in `index.ts`).
4. Extend the existing eip712 unit tests with cache-hit and invalidation cases if caching lands. Run `pnpm lint`, `pnpm build`, `pnpm test` in `packages/hardhat`.
## Verification (before/after)
Profile before and after with `pnpm profiler` (a bare `pnpm profiler` prints its usage; see `scripts/README.md`):
```bash
pnpm build
pnpm profiler --scenario ./end-to-end/aave-v4 \
--prepare "cold compile" --command "test solidity" \
--mode js --init --use-local
```
Expect: `parseJsonBytes` gone from the top functions of the `.cpuprofile` — on the second, cache-warm run if caching lands, or on every run if compile-time collection does. Test results must be identical, and so must the canonical types handed to EDR (assert against a baseline dump).
- Lenguaje dominante
- TypeScript
- Estrellas
- 110
- Forks
- 49
- Merge medio
- 2 d 19 h
- PR fusionados (30 d)
- 64
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de NomicFoundation/edr
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 76/100
NomicFoundation/edr#1383 · 3 comentarios ·
Los mantenedores suelen responder en 2 días
-
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
NomicFoundation/edr#1877 ·
Los mantenedores suelen responder en 2 días
-
OP deposit receipts with a zero deposit nonce decode as EIP-658 receiptsPosiblemente ocupada @aelmanaa la tomó hace 2 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 25/100
NomicFoundation/edr#1868 ·
Los mantenedores suelen responder en 2 días
-
Receipt RLP decoding fails for failed EIP-658 receiptsPosiblemente ocupada @aelmanaa la tomó hace 2 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 25/100
NomicFoundation/edr#1867 ·
Los mantenedores suelen responder en 2 días
-
`BlockHeader` RLP decoding and JSON serialization don't round-tripPosiblemente ocupada @aelmanaa la tomó hace 2 días. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 25/100
NomicFoundation/edr#1864 ·
Los mantenedores suelen responder en 2 días
Todos los issues de NomicFoundation/edr
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
kunchenguid/gh-axi#220 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 79/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día
-
prerender: wait for env-runner worker readiness before crawlingPosiblemente ocupada @sarankumar1325 la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día