Skip to content
This repository was archived by the owner on Aug 14, 2023. It is now read-only.

Commit bd487a7

Browse files
authored
Easily detect uncommitted changes to the SVM global state (#422)
* uncommitted changes detection * Fix results and add doc test
1 parent f663b71 commit bd487a7

File tree

4 files changed

+48
-0
lines changed

4 files changed

+48
-0
lines changed

crates/runtime-ffi/src/api.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,38 @@ pub unsafe extern "C" fn svm_call(
477477
)
478478
}
479479

480+
/// Detects if the given runtime contains any uncommitted changes in memory; if
481+
/// it does, then it returns an error wrapped inside [`svm_result_t`].
482+
///
483+
/// # Examples
484+
///
485+
/// ```rust
486+
/// use svm_runtime_ffi::*;
487+
///
488+
/// let mut runtime = std::ptr::null_mut();
489+
///
490+
/// unsafe { svm_init(true, std::ptr::null(), 0); }
491+
///
492+
/// let res = unsafe { svm_runtime_create(&mut runtime) };
493+
/// assert!(res.is_ok());
494+
///
495+
/// let res = unsafe { svm_uncommitted_changes(runtime) };
496+
/// assert!(res.is_ok());
497+
/// ```
498+
///
499+
#[must_use]
500+
#[no_mangle]
501+
pub unsafe extern "C" fn svm_uncommitted_changes(runtime_ptr: *mut c_void) -> svm_result_t {
502+
catch_unwind_or_fail(|| {
503+
let runtime = get_runtime(runtime_ptr);
504+
if runtime.has_uncommitted_changes()? {
505+
svm_result_t::new_error(b"The SVM global state contains uncommitted changes.")
506+
} else {
507+
svm_result_t::OK
508+
}
509+
})
510+
}
511+
480512
/// Writes the current state root hash at `hash` and the current layer at `layer`.
481513
#[must_use]
482514
#[no_mangle]

crates/runtime/src/runtime/runtime.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,12 @@ impl Runtime {
687687
Ok(())
688688
}
689689

690+
/// Returns [`true`] iff the underlying [`GlobalState`] has changed since
691+
/// the last call to [`Runtime::commit`].
692+
pub fn has_uncommitted_changes(&self) -> Result<bool> {
693+
Ok(self.gs.has_uncommitted_changes())
694+
}
695+
690696
/// Given the address of an account, it attempts to read:
691697
///
692698
/// - balance;

crates/state/src/global_state.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ impl GlobalState {
9898
Ok(())
9999
}
100100

101+
/// Returns [`true`] iff there are any dirty changes in memory; [`false`]
102+
/// otherwise.
103+
pub fn has_uncommitted_changes(&self) -> bool {
104+
self.storage().has_uncommitted_changes()
105+
}
106+
101107
// GETTER/SETTER UTILITIES
102108
// -----------------------
103109

crates/state/src/storage.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ impl Storage {
122122
assert!(layer_id < self.next_layer.id);
123123
}
124124

125+
pub fn has_uncommitted_changes(&self) -> bool {
126+
!self.dirty_changes.is_empty()
127+
}
128+
125129
/// Fetches the value associated with the Blake3 hash of `key`. See
126130
/// [`Storage::get_by_hash`] for more information.
127131
///

0 commit comments

Comments
 (0)