@@ -74,6 +74,8 @@ use snarkvm_synthesizer_error::*;
7474use snarkvm_synthesizer_program:: {
7575 CallOperator ,
7676 Closure ,
77+ FinalizeGlobalState ,
78+ FinalizeStoreTrait ,
7779 Function ,
7880 Instruction ,
7981 Operand ,
@@ -257,6 +259,8 @@ pub struct Stack<N: Network> {
257259 register_types : Arc < RwLock < IndexMap < Identifier < N > , RegisterTypes < N > > > > ,
258260 /// The mapping of finalize names to their register types.
259261 finalize_types : Arc < RwLock < IndexMap < Identifier < N > , FinalizeTypes < N > > > > ,
262+ /// The mapping of view function names to their register types.
263+ view_types : Arc < RwLock < IndexMap < Identifier < N > , FinalizeTypes < N > > > > ,
260264 /// The universal SRS.
261265 universal_srs : UniversalSRS < N > ,
262266 /// The mapping of function name or record name to proving key.
@@ -319,15 +323,17 @@ impl<N: Network> Stack<N> {
319323
320324 /// Initializes and checks the register state and well-formedness of the stack, even if it has already been initialized.
321325 pub fn initialize_and_check ( & self , process : & Process < N > ) -> Result < ( ) > {
322- // Acquire the locks for the constructor, register, and finalize types.
326+ // Acquire the locks for the constructor, register, finalize, and view types.
323327 let mut constructor_types = self . constructor_types . write ( ) ;
324328 let mut register_types = self . register_types . write ( ) ;
325329 let mut finalize_types = self . finalize_types . write ( ) ;
330+ let mut view_types = self . view_types . write ( ) ;
326331
327- // Clear the existing constructor, closure, and function types.
332+ // Clear the existing constructor, closure, function, and view types.
328333 constructor_types. take ( ) ;
329334 register_types. clear ( ) ;
330335 finalize_types. clear ( ) ;
336+ view_types. clear ( ) ;
331337
332338 // Add all the imports into the stack.
333339 for import in self . program . imports ( ) . keys ( ) {
@@ -379,17 +385,21 @@ impl<N: Network> Stack<N> {
379385 }
380386 }
381387
382- // Type-check every view function. The result is not cached on the stack here;
383- // it is recomputed by the view evaluator. This is acceptable for the prototype
384- // and ensures that ill-typed views are rejected at deploy time .
388+ // Type-check every view function and cache the result. The cached types are read by
389+ // both the external view path (`evaluate_view_at_height`) and the in-block call path
390+ // when finalize calls a view, so we avoid recomputing them on every invocation .
385391 for view in self . program . views ( ) . values ( ) {
386- let _ = FinalizeTypes :: from_view ( self , view) ?;
392+ let name = view. name ( ) ;
393+ ensure ! ( !view_types. contains_key( name) , "View '{name}' already exists" ) ;
394+ let types = FinalizeTypes :: from_view ( self , view) ?;
395+ view_types. insert ( * name, types) ;
387396 }
388397
389398 // Drop the locks since the types have been initialized.
390399 drop ( constructor_types) ;
391400 drop ( register_types) ;
392401 drop ( finalize_types) ;
402+ drop ( view_types) ;
393403
394404 // Check that the functions are valid.
395405 for function in self . program . functions ( ) . values ( ) {
@@ -430,6 +440,15 @@ impl<N: Network> Stack<N> {
430440 }
431441 }
432442
443+ /// Returns the register types for the given view function name.
444+ #[ inline]
445+ pub fn get_view_types ( & self , name : & Identifier < N > ) -> Result < FinalizeTypes < N > > {
446+ match self . view_types . read ( ) . get ( name) {
447+ Some ( view_types) => Ok ( view_types. clone ( ) ) ,
448+ None => bail ! ( "View types for '{name}' do not exist" ) ,
449+ }
450+ }
451+
433452 /// Inserts the proving key if the program ID is 'credits.aleo'.
434453 fn try_insert_credits_function_proving_key ( & self , function_name : & Identifier < N > ) -> Result < ( ) > {
435454 // If the program is 'credits.aleo' and it does not exist yet, load the proving key directly.
0 commit comments