@@ -104,7 +104,11 @@ impl<N: Network> Process<N> {
104104 lap ! ( timer, "Verify the number of transitions" ) ;
105105
106106 // Construct the call graph.
107- let call_graph = self . construct_call_graph ( execution) ?;
107+ // If the height is greater than or equal to `CONSENSUS_V3_HEIGHT`, then provide an empty call graph, as it is no longer used during finalization.
108+ let call_graph = match state. block_height ( ) < N :: CONSENSUS_V3_HEIGHT {
109+ true => self . construct_call_graph ( execution) ?,
110+ false => HashMap :: new ( ) ,
111+ } ;
108112
109113 atomic_batch_scope ! ( store, {
110114 // Finalize the root transition.
@@ -160,9 +164,11 @@ fn finalize_fee_transition<N: Network, P: FinalizeStorage<N>>(
160164 fee : & Fee < N > ,
161165) -> Result < Vec < FinalizeOperation < N > > > {
162166 // Construct the call graph.
163- let mut call_graph = HashMap :: new ( ) ;
164- // Insert the fee transition.
165- call_graph. insert ( * fee. transition_id ( ) , Vec :: new ( ) ) ;
167+ // If the height is greater than or equal to `CONSENSUS_V3_HEIGHT`, then provide an empty call graph, as it is no longer used during finalization.
168+ let call_graph = match state. block_height ( ) < N :: CONSENSUS_V3_HEIGHT {
169+ true => HashMap :: from ( [ ( * fee. transition_id ( ) , Vec :: new ( ) ) ] ) ,
170+ false => HashMap :: new ( ) ,
171+ } ;
166172
167173 // Finalize the transition.
168174 match finalize_transition ( state, store, stack, fee, call_graph) {
@@ -208,8 +214,12 @@ fn finalize_transition<N: Network, P: FinalizeStorage<N>>(
208214 // Initialize a stack of active finalize states.
209215 let mut states = Vec :: new ( ) ;
210216
217+ // Initialize a nonce for the finalize registers.
218+ // Note that this nonce must be unique for each sub-transition being finalized.
219+ let mut nonce = 0 ;
220+
211221 // Initialize the top-level finalize state.
212- states. push ( initialize_finalize_state ( state, future, stack, * transition. id ( ) ) ?) ;
222+ states. push ( initialize_finalize_state ( state, future, stack, * transition. id ( ) , nonce ) ?) ;
213223
214224 // While there are active finalize states, finalize them.
215225 ' outer: while let Some ( FinalizeState {
@@ -263,20 +273,31 @@ fn finalize_transition<N: Network, P: FinalizeStorage<N>>(
263273 await_. register( )
264274 ) ;
265275
266- // Get the current transition ID.
267- let transition_id = registers. transition_id ( ) ;
268- // Get the child transition ID.
269- let child_transition_id = match call_graph. get ( transition_id) {
270- Some ( transitions) => match transitions. get ( call_counter) {
271- Some ( transition_id) => * transition_id,
272- None => bail ! ( "Child transition ID not found." ) ,
273- } ,
274- None => bail ! ( "Transition ID '{transition_id}' not found in call graph" ) ,
276+ // Get the transition ID used to initialize the finalize registers.
277+ // If the block height is greater than or equal to `CONSENSUS_V3_HEIGHT`, then use the top-level transition ID.
278+ // Otherwise, query the call graph for the child transition ID corresponding to the future that is being awaited.
279+ let transition_id = match state. block_height ( ) < N :: CONSENSUS_V3_HEIGHT {
280+ true => {
281+ // Get the current transition ID.
282+ let transition_id = registers. transition_id ( ) ;
283+ // Get the child transition ID.
284+ match call_graph. get ( transition_id) {
285+ Some ( transitions) => match transitions. get ( call_counter) {
286+ Some ( transition_id) => * transition_id,
287+ None => bail ! ( "Child transition ID not found." ) ,
288+ } ,
289+ None => bail ! ( "Transition ID '{transition_id}' not found in call graph" ) ,
290+ }
291+ }
292+ false => * transition. id ( ) ,
275293 } ;
276294
295+ // Increment the nonce.
296+ nonce += 1 ;
297+
277298 // Set up the finalize state for the await.
278299 let callee_state =
279- match try_vm_runtime ! ( || setup_await( state, await_, stack, & registers, child_transition_id ) ) {
300+ match try_vm_runtime ! ( || setup_await( state, await_, stack, & registers, transition_id , nonce ) ) {
280301 Ok ( Ok ( callee_state) ) => callee_state,
281302 // If the evaluation fails, bail and return the error.
282303 Ok ( Err ( error) ) => bail ! ( "'finalize' failed to evaluate command ({command}): {error}" ) ,
@@ -357,6 +378,7 @@ fn initialize_finalize_state<'a, N: Network>(
357378 future : & Future < N > ,
358379 stack : & ' a Stack < N > ,
359380 transition_id : N :: TransitionID ,
381+ nonce : u64 ,
360382) -> Result < FinalizeState < ' a , N > > {
361383 // Get the finalize logic and the stack.
362384 let ( finalize, stack) = match stack. program_id ( ) == future. program_id ( ) {
@@ -381,6 +403,7 @@ fn initialize_finalize_state<'a, N: Network>(
381403 transition_id,
382404 * future. function_name ( ) ,
383405 stack. get_finalize_types ( future. function_name ( ) ) ?. clone ( ) ,
406+ nonce,
384407 ) ;
385408
386409 // Store the inputs.
@@ -402,14 +425,15 @@ fn setup_await<'a, N: Network>(
402425 stack : & ' a Stack < N > ,
403426 registers : & FinalizeRegisters < N > ,
404427 transition_id : N :: TransitionID ,
428+ nonce : u64 ,
405429) -> Result < FinalizeState < ' a , N > > {
406430 // Retrieve the input as a future.
407431 let future = match registers. load ( stack, & Operand :: Register ( await_. register ( ) . clone ( ) ) ) ? {
408432 Value :: Future ( future) => future,
409433 _ => bail ! ( "The input to 'await' is not a future" ) ,
410434 } ;
411435 // Initialize the state.
412- initialize_finalize_state ( state, & future, stack, transition_id)
436+ initialize_finalize_state ( state, & future, stack, transition_id, nonce )
413437}
414438
415439// A helper function that returns the index to branch to.
0 commit comments