11import { MAX_APPS_PER_KERNEL } from '@aztec/constants' ;
2+ import { uniqueBy } from '@aztec/foundation/collection' ;
23import { vkAsFieldsMegaHonk } from '@aztec/foundation/crypto/keys' ;
34import { Fr } from '@aztec/foundation/curves/bn254' ;
45import { type Logger , type LoggerBindings , createLogger } from '@aztec/foundation/log' ;
@@ -27,12 +28,14 @@ import {
2728 PrivateKernelTailCircuitPrivateInputs ,
2829 type PrivateKernelTailCircuitPublicInputs ,
2930 PrivateVerificationKeyHints ,
31+ type UpdatedClassIdHints ,
3032} from '@aztec/stdlib/kernel' ;
3133import { ChonkProof , ChonkProofWithPublicInputs } from '@aztec/stdlib/proofs' ;
3234import {
3335 type PrivateCallExecutionResult ,
3436 type PrivateExecutionResult ,
3537 TxRequest ,
38+ collectNested ,
3639 collectNoteHashNullifierCounterMap ,
3740 getFinalMinRevertibleSideEffectCounter ,
3841} from '@aztec/stdlib/tx' ;
@@ -120,6 +123,8 @@ export class PrivateKernelExecutionProver {
120123 // reusing the existing single-app `needsReset()` check.
121124 const planner = new BatchPlanner ( noteHashNullifierCounterMap , splitCounter , this . maxBatchSize ) ;
122125
126+ const updatedClassIdHintsMap = await this . prefetchUpdatedClassIdHints ( executionResult ) ;
127+
123128 while ( executionStack . length ) {
124129 if ( ! firstIteration ) {
125130 let resetBuilder = new PrivateKernelResetPrivateInputsBuilder (
@@ -156,7 +161,7 @@ export class PrivateKernelExecutionProver {
156161 const batchSize = planner . decideBatchSize ( output . publicInputs , executionStack ) ;
157162 const apps : PrivateCallData [ ] = [ ] ;
158163 for ( let i = 0 ; i < batchSize ; i ++ ) {
159- apps . push ( await this . consumeNextApp ( executionStack , executionSteps ) ) ;
164+ apps . push ( await this . consumeNextApp ( executionStack , executionSteps , updatedClassIdHintsMap ) ) ;
160165 }
161166
162167 output = await this . runBatchedKernel ( {
@@ -365,6 +370,7 @@ export class PrivateKernelExecutionProver {
365370 private async consumeNextApp (
366371 executionStack : PrivateCallExecutionResult [ ] ,
367372 executionSteps : PrivateExecutionStep [ ] ,
373+ updatedClassIdHintsMap : Map < string , UpdatedClassIdHints > ,
368374 ) : Promise < PrivateCallData > {
369375 const next = executionStack . pop ( ) ! ;
370376 executionStack . push ( ...[ ...next . nestedExecutionResults ] . reverse ( ) ) ;
@@ -385,10 +391,31 @@ export class PrivateKernelExecutionProver {
385391 } ,
386392 } ) ;
387393
388- return await this . createPrivateCallData ( next ) ;
394+ return await this . createPrivateCallData ( next , updatedClassIdHintsMap ) ;
395+ }
396+
397+ /** Prefetches updated class id hints for all unique contracts in the execution tree in parallel. */
398+ private async prefetchUpdatedClassIdHints (
399+ executionResult : PrivateExecutionResult ,
400+ ) : Promise < Map < string , UpdatedClassIdHints > > {
401+ const allAddresses = collectNested ( [ executionResult . entrypoint ] , exec => [
402+ exec . publicInputs . callContext . contractAddress ,
403+ ] ) ;
404+ const uniqueAddresses = uniqueBy ( allAddresses , a => a . toString ( ) ) ;
405+ return new Map < string , UpdatedClassIdHints > (
406+ await Promise . all (
407+ uniqueAddresses . map (
408+ async addr =>
409+ [ addr . toString ( ) , await this . oracle . getUpdatedClassIdHints ( addr ) ] as [ string , UpdatedClassIdHints ] ,
410+ ) ,
411+ ) ,
412+ ) ;
389413 }
390414
391- private async createPrivateCallData ( { publicInputs, vk : vkAsBuffer } : PrivateCallExecutionResult ) {
415+ private async createPrivateCallData (
416+ { publicInputs, vk : vkAsBuffer } : PrivateCallExecutionResult ,
417+ updatedClassIdHintsMap : Map < string , UpdatedClassIdHints > ,
418+ ) {
392419 const { contractAddress, functionSelector } = publicInputs . callContext ;
393420
394421 const vkAsFields = await vkAsFieldsMegaHonk ( vkAsBuffer ) ;
@@ -404,7 +431,7 @@ export class PrivateKernelExecutionProver {
404431 const { artifactHash : contractClassArtifactHash , publicBytecodeCommitment : contractClassPublicBytecodeCommitment } =
405432 await this . oracle . getContractClassIdPreimage ( currentContractClassId ) ;
406433
407- const updatedClassIdHints = await this . oracle . getUpdatedClassIdHints ( contractAddress ) ;
434+ const updatedClassIdHints = updatedClassIdHintsMap . get ( contractAddress . toString ( ) ) ! ;
408435
409436 return PrivateCallData . from ( {
410437 publicInputs,
0 commit comments