@@ -14,9 +14,9 @@ import { standardRepos } from "../lib/repoDefinitions";
1414import { shardManager } from "../lib/shardManager" ;
1515import invariant from "tiny-invariant" ;
1616import {
17- WasmPrecompileService ,
18- WasmPrecompileServiceLive ,
19- } from "./effect/WasmPrecompileService .js" ;
17+ StartupCacheService ,
18+ StartupCacheServiceLive ,
19+ } from "./effect/StartupCacheService .js" ;
2020
2121const logger = createLogger ( { name : "commandParsers" } ) ;
2222
@@ -149,34 +149,52 @@ export class LaunchCommandParser {
149149 }
150150
151151 /**
152- * Run WASM precompilation if enabled in launchSpec.
153- * This uses an Effect-based service that caches precompiled artifacts by binary hash.
152+ * Cache startup artifacts if enabled in launchSpec.
153+ * This uses an Effect-based service that caches artifacts by binary hash.
154+ *
155+ * When cacheStartupArtifacts is enabled, this generates:
156+ * 1. Precompiled WASM for the runtime
157+ * 2. Raw chain spec to skip genesis WASM compilation
158+ *
159+ * This reduces startup from ~3s to ~200ms (~10x improvement).
154160 */
155- async withWasmPrecompile ( ) : Promise < LaunchCommandParser > {
156- if ( ! this . launchSpec . precompileWasm ) {
161+ async withStartupCache ( ) : Promise < LaunchCommandParser > {
162+ if ( ! this . launchSpec . cacheStartupArtifacts ) {
157163 return this ;
158164 }
159165
160166 // Skip for Docker images
161167 if ( this . launchSpec . useDocker ) {
162- logger . warn ( "WASM precompilation is not supported for Docker images, skipping" ) ;
168+ logger . warn ( "Startup caching is not supported for Docker images, skipping" ) ;
163169 return this ;
164170 }
165171
166- // Extract chain argument from existing args
167- const chainArg = this . args . find ( ( arg ) => arg . includes ( "--chain" ) ) ;
172+ // Extract chain argument from existing args (e.g., "--chain=moonbase-dev")
173+ const chainArg = this . args . find ( ( arg ) => arg . startsWith ( "--chain" ) ) ;
174+ // Check if using --dev flag
175+ const hasDevFlag = this . args . includes ( "--dev" ) ;
176+ // Extract chain name from --chain=XXX or --chain XXX
177+ const existingChainName = chainArg ?. match ( / - - c h a i n [ = \s ] ? ( \S + ) / ) ?. [ 1 ] ;
168178
169- const cacheDir = this . launchSpec . wasmCacheDir || path . join ( process . cwd ( ) , "tmp" , "wasm-cache" ) ;
179+ // We can generate raw chain spec for both --dev mode and explicit --chain=XXX
180+ const canGenerateRawSpec = hasDevFlag || ! ! existingChainName ;
170181
171- const program = WasmPrecompileService . pipe (
182+ const cacheDir =
183+ this . launchSpec . startupCacheDir || path . join ( process . cwd ( ) , "tmp" , "startup-cache" ) ;
184+
185+ const program = StartupCacheService . pipe (
172186 Effect . flatMap ( ( service ) =>
173- service . getPrecompiledPath ( {
187+ service . getCachedArtifacts ( {
174188 binPath : this . launchSpec . binPath ,
175189 chainArg,
176190 cacheDir,
191+ // Generate raw chain spec for faster startup (works for both --dev and --chain=XXX)
192+ generateRawChainSpec : canGenerateRawSpec ,
193+ // Pass dev mode flag for proper chain name detection
194+ isDevMode : hasDevFlag ,
177195 } )
178196 ) ,
179- Effect . provide ( WasmPrecompileServiceLive )
197+ Effect . provide ( StartupCacheServiceLive )
180198 ) ;
181199
182200 try {
@@ -185,6 +203,28 @@ export class LaunchCommandParser {
185203 // Get the directory containing the precompiled wasm
186204 const precompiledDir = path . dirname ( result . precompiledPath ) ;
187205 this . overrideArg ( `--wasmtime-precompiled=${ precompiledDir } ` ) ;
206+
207+ // If we have a raw chain spec, use it for ~10x faster startup
208+ if ( result . rawChainSpecPath ) {
209+ if ( hasDevFlag ) {
210+ // Remove --dev flag and add equivalent flags
211+ this . args = this . args . filter ( ( arg ) => arg !== "--dev" ) ;
212+ this . overrideArg ( `--chain=${ result . rawChainSpecPath } ` ) ;
213+ // Add flags that --dev would normally set
214+ this . args . push ( "--alice" ) ;
215+ this . args . push ( "--force-authoring" ) ;
216+ this . overrideArg ( "--rpc-cors=all" ) ;
217+ // Use a deterministic node key for consistency
218+ this . overrideArg (
219+ "--node-key=0000000000000000000000000000000000000000000000000000000000000001"
220+ ) ;
221+ } else if ( existingChainName ) {
222+ // Replace original --chain=XXX with --chain=<raw-spec-path>
223+ this . overrideArg ( `--chain=${ result . rawChainSpecPath } ` ) ;
224+ }
225+ logger . debug ( `Using raw chain spec for ~10x faster startup: ${ result . rawChainSpecPath } ` ) ;
226+ }
227+
188228 logger . debug (
189229 result . fromCache
190230 ? `Using cached precompiled WASM: ${ result . precompiledPath } `
@@ -216,7 +256,7 @@ export class LaunchCommandParser {
216256 const parsed = await parser
217257 . withPorts ( )
218258 . then ( ( p ) => p . withDefaultForkConfig ( ) . withLaunchOverrides ( ) )
219- . then ( ( p ) => p . withWasmPrecompile ( ) ) ;
259+ . then ( ( p ) => p . withStartupCache ( ) ) ;
220260
221261 if ( options . verbose ) {
222262 parsed . print ( ) ;
0 commit comments