From ca9cc0603bfd3277cd8cf68d67f49636657586ea Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Thu, 18 Sep 2025 22:07:55 +0300 Subject: [PATCH] DebugHandle Weak pointer to TxContext --- chain/vm/src/host/context/tx_context_ref.rs | 10 ++++++- .../scenario/src/api/impl_vh/debug_api.rs | 3 +- .../src/api/impl_vh/debug_handle_vh.rs | 30 ++++++++++++------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/chain/vm/src/host/context/tx_context_ref.rs b/chain/vm/src/host/context/tx_context_ref.rs index 1680198070..333b105452 100644 --- a/chain/vm/src/host/context/tx_context_ref.rs +++ b/chain/vm/src/host/context/tx_context_ref.rs @@ -1,4 +1,7 @@ -use std::{ops::Deref, sync::Arc}; +use std::{ + ops::Deref, + sync::{Arc, Weak}, +}; use crate::host::context::{TxContext, TxResult}; @@ -65,4 +68,9 @@ impl TxContextRef { pub fn into_ref(self) -> Arc { self.0 } + + /// Creates a new [`Weak`] pointer to the [`TxContext`]. + pub fn downgrade(&self) -> Weak { + Arc::downgrade(&self.0) + } } diff --git a/framework/scenario/src/api/impl_vh/debug_api.rs b/framework/scenario/src/api/impl_vh/debug_api.rs index 3076d6a24a..2babf9dbd1 100644 --- a/framework/scenario/src/api/impl_vh/debug_api.rs +++ b/framework/scenario/src/api/impl_vh/debug_api.rs @@ -1,6 +1,5 @@ use multiversx_chain_vm::{ executor::{VMHooks, VMHooksEarlyExit}, - host::context::TxContextRef, host::vm_hooks::{TxVMHooksContext, VMHooksDispatcher}, }; use multiversx_sc::{chain_core::types::ReturnCode, err_msg}; @@ -32,7 +31,7 @@ impl VMHooksApiBackend for DebugApiBackend { where F: FnOnce(&mut dyn VMHooks) -> Result, { - let tx_context_ref = TxContextRef(handle.context.clone()); + let tx_context_ref = handle.to_tx_context_ref(); let vh_context = TxVMHooksContext::new(tx_context_ref, ContractDebugInstanceState); let mut dispatcher = VMHooksDispatcher::new(vh_context); f(&mut dispatcher).unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err)) diff --git a/framework/scenario/src/api/impl_vh/debug_handle_vh.rs b/framework/scenario/src/api/impl_vh/debug_handle_vh.rs index 7f3da0d20f..193209708d 100644 --- a/framework/scenario/src/api/impl_vh/debug_handle_vh.rs +++ b/framework/scenario/src/api/impl_vh/debug_handle_vh.rs @@ -1,6 +1,6 @@ -use std::sync::Arc; +use std::sync::Weak; -use multiversx_chain_vm::host::context::TxContext; +use multiversx_chain_vm::host::context::{TxContext, TxContextRef}; use multiversx_sc::{ api::{HandleConstraints, RawHandle}, codec::TryStaticCast, @@ -10,22 +10,22 @@ use crate::executor::debug::ContractDebugStack; #[derive(Clone)] pub struct DebugHandle { - /// TODO: would be nice to be an actual TxContextRef, - /// but that requires changing the debugger scripts - pub(crate) context: Arc, + /// Only keep a weak reference to the context, to avoid stray handles keeping the context from being released. + /// Using the pointer after the context is released will panic. + pub(crate) context: Weak, raw_handle: RawHandle, } impl DebugHandle { pub fn is_on_current_context(&self) -> bool { - Arc::ptr_eq( + Weak::ptr_eq( &self.context, - &ContractDebugStack::static_peek().tx_context_ref.into_ref(), + &ContractDebugStack::static_peek().tx_context_ref.downgrade(), ) } pub fn is_on_same_context(&self, other: &DebugHandle) -> bool { - Arc::ptr_eq(&self.context, &other.context) + Weak::ptr_eq(&self.context, &other.context) } pub fn assert_current_context(&self) { @@ -34,6 +34,16 @@ impl DebugHandle { "Managed value not used in original context" ); } + + pub fn to_tx_context_ref(&self) -> TxContextRef { + let tx_context_arc = self.context.upgrade().unwrap_or_else(|| { + panic!( + "TxContext is no longer valid for handle {}", + self.raw_handle + ) + }); + TxContextRef::new(tx_context_arc) + } } impl core::fmt::Debug for DebugHandle { @@ -45,7 +55,7 @@ impl core::fmt::Debug for DebugHandle { impl HandleConstraints for DebugHandle { fn new(handle: multiversx_sc::api::RawHandle) -> Self { Self { - context: ContractDebugStack::static_peek().tx_context_ref.into_ref(), + context: ContractDebugStack::static_peek().tx_context_ref.downgrade(), raw_handle: handle, } } @@ -73,7 +83,7 @@ impl PartialEq for DebugHandle { impl PartialEq for DebugHandle { fn eq(&self, other: &DebugHandle) -> bool { - Arc::ptr_eq(&self.context, &other.context) && self.raw_handle == other.raw_handle + Weak::ptr_eq(&self.context, &other.context) && self.raw_handle == other.raw_handle } }