Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion chain/vm/src/host/context/tx_context_ref.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{ops::Deref, sync::Arc};
use std::{
ops::Deref,
sync::{Arc, Weak},
};

use crate::host::context::{TxContext, TxResult};

Expand Down Expand Up @@ -65,4 +68,9 @@ impl TxContextRef {
pub fn into_ref(self) -> Arc<TxContext> {
self.0
}

/// Creates a new [`Weak`] pointer to the [`TxContext`].
pub fn downgrade(&self) -> Weak<TxContext> {
Arc::downgrade(&self.0)
}
}
3 changes: 1 addition & 2 deletions framework/scenario/src/api/impl_vh/debug_api.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -32,7 +31,7 @@ impl VMHooksApiBackend for DebugApiBackend {
where
F: FnOnce(&mut dyn VMHooks) -> Result<R, VMHooksEarlyExit>,
{
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))
Expand Down
30 changes: 20 additions & 10 deletions framework/scenario/src/api/impl_vh/debug_handle_vh.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<TxContext>,
/// 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<TxContext>,
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) {
Expand All @@ -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 {
Expand All @@ -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,
}
}
Expand Down Expand Up @@ -73,7 +83,7 @@ impl PartialEq<RawHandle> for DebugHandle {

impl PartialEq<DebugHandle> 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
}
}

Expand Down
Loading