@@ -17,7 +17,6 @@ import type { PXEConfig } from '@aztec/pxe/config';
1717import type { PXE } from '@aztec/pxe/server' ;
1818import { createPXE , getPXEConfig } from '@aztec/pxe/server' ;
1919import { AztecAddress } from '@aztec/stdlib/aztec-address' ;
20- import type { ContractClassIdPreimage , ContractClassWithId } from '@aztec/stdlib/contract' ;
2120import { deriveSigningKey } from '@aztec/stdlib/keys' ;
2221import { NoteDao } from '@aztec/stdlib/note' ;
2322import type { SimulationOverrides , TxExecutionRequest , TxProvingResult } from '@aztec/stdlib/tx' ;
@@ -31,13 +30,9 @@ import { printGasEstimates } from './options/fees.js';
3130
3231export class CLIWallet extends BaseWallet {
3332 private accountCache = new Map < string , Account > ( ) ;
34- /**
35- * Per-account-type cache of the stub class id and preimage. The Promise is stored (not the resolved
36- * value) so concurrent first-time callers dedupe on the same hashing + registration work. ECDSA
37- * variants all map to the same stub artifact but get their own cache slot, so we may hash + register
38- * the same artifact one extra time per variant on first miss; that cost is bounded and one-time.
39- */
40- #stubClasses = new Map < AccountType , Promise < ContractClassWithId & ContractClassIdPreimage > > ( ) ;
33+ // Stub class ids, populated on wallet startup
34+ // to avoid redundant work per simulation
35+ private stubClassIds = new Map < AccountType , Fr > ( ) ;
4136
4237 constructor (
4338 pxe : PXE ,
@@ -57,7 +52,27 @@ export class CLIWallet extends BaseWallet {
5752 ) : Promise < CLIWallet > {
5853 const pxeConfig = Object . assign ( getPXEConfig ( ) , overridePXEConfig ) ;
5954 const pxe = await createPXE ( node , pxeConfig ) ;
60- return new CLIWallet ( pxe , node , log , db ) ;
55+ const wallet = new CLIWallet ( pxe , node , log , db ) ;
56+ await wallet . initStubClasses ( ) ;
57+ return wallet ;
58+ }
59+
60+ /**
61+ * Hashes and registers the stub class for every supported account type with PXE, populating
62+ * stubClassIds. Called on wallet initialization.
63+ */
64+ private async initStubClasses ( ) : Promise < void > {
65+ const { id : schnorrClassId } = await getContractClassFromArtifact ( StubSchnorrAccountContractArtifact ) ;
66+ await this . pxe . registerContractClass ( StubSchnorrAccountContractArtifact ) ;
67+
68+ // ecdsa stubs share the same class id
69+ const { id : ecdsaClassId } = await getContractClassFromArtifact ( StubEcdsaAccountContractArtifact ) ;
70+ await this . pxe . registerContractClass ( StubEcdsaAccountContractArtifact ) ;
71+
72+ this . stubClassIds . set ( 'schnorr' , schnorrClassId ) ;
73+ this . stubClassIds . set ( 'ecdsasecp256k1' , ecdsaClassId ) ;
74+ this . stubClassIds . set ( 'ecdsasecp256r1' , ecdsaClassId ) ;
75+ this . stubClassIds . set ( 'ecdsasecp256r1ssh' , ecdsaClassId ) ;
6176 }
6277
6378 override async getAccounts ( ) : Promise < Aliased < AztecAddress > [ ] > {
@@ -208,29 +223,16 @@ export class CLIWallet extends BaseWallet {
208223 const { type } = await this . db ! . retrieveAccount ( address ) ;
209224 const stubAccount =
210225 type === 'schnorr' ? createStubSchnorrAccount ( originalAddress ) : createStubEcdsaAccount ( originalAddress ) ;
211- const { id : stubClassId } = await this . #getStubClass( type ) ;
226+ const stubClassId = this . stubClassIds . get ( type ) ;
227+ if ( ! stubClassId ) {
228+ throw new Error (
229+ `Stub class for account type '${ type } ' was not registered at wallet init. This is a bug — initStubClasses should cover every supported AccountType.` ,
230+ ) ;
231+ }
212232 const instance = { ...contractInstance , currentContractClassId : stubClassId } ;
213233 return { account : stubAccount , instance } ;
214234 }
215235
216- /**
217- * Lazily hashes and registers the stub class for the given account type, caching the result so
218- * subsequent simulations skip the artifact-hashing + registration round-trip.
219- */
220- #getStubClass( type : AccountType ) : Promise < ContractClassWithId & ContractClassIdPreimage > {
221- let cached = this . #stubClasses. get ( type ) ;
222- if ( ! cached ) {
223- cached = ( async ( ) => {
224- const artifact = type === 'schnorr' ? StubSchnorrAccountContractArtifact : StubEcdsaAccountContractArtifact ;
225- const stubClass = await getContractClassFromArtifact ( artifact ) ;
226- await this . pxe . registerContractClass ( artifact ) ;
227- return stubClass ;
228- } ) ( ) ;
229- this . #stubClasses. set ( type , cached ) ;
230- }
231- return cached ;
232- }
233-
234236 override async simulateTx (
235237 executionPayload : ExecutionPayload ,
236238 opts : SimulateOptions ,
0 commit comments