Skip to content

Commit 2e3efbf

Browse files
committed
review: review security audit findings (GREVM-R2-001 ~ 008)
1 parent fd892cb commit 2e3efbf

4 files changed

Lines changed: 14 additions & 17 deletions

File tree

docs/security/2026-03-02-security-audit-round2-report.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ fn clear_destructed_entry(&self, account: Address) {
171171

172172
**Recommendation:** Maintain a secondary index `DashMap<Address, HashSet<LocationAndType>>` to enable O(1) lookup of entries by address, avoiding the full table scan. Alternatively, prefix-scan the DashMap only for the target address keys.
173173

174-
**Review Comments** reviewer: Xin GAO; state: ignored; comments:
174+
**Review Comments** reviewer: Xin GAO; state: ignored; comments: Resolved by `fallback_sequential`
175175

176176
---
177177

@@ -208,6 +208,8 @@ pub(crate) fn print(&self) {
208208

209209
Or use `tracing`'s lazy evaluation with `tracing::debug!(...)` and deferred formatting.
210210

211+
**Review Comments** reviewer: Xin GAO; state: ignored; comments: Only called in debug mode
212+
211213
---
212214

213215
## LOW Severity (3)
@@ -235,6 +237,8 @@ unsafe fn set(&self, index: usize, value: T) {
235237
}
236238
```
237239

240+
**Review Comments** reviewer: Xin GAO; state: ignored; comments:
241+
238242
---
239243

240244
### GREVM-R2-007: `IdentityHasher::write()` Panics with `unreachable!()`
@@ -267,6 +271,8 @@ fn write(&mut self, bytes: &[u8]) {
267271
}
268272
```
269273

274+
**Review Comments** reviewer: Xin GAO; state: ignored; comments:
275+
270276
---
271277

272278
### GREVM-R2-008: `parallel_apply_transitions_and_create_reverts` Clones Transitions via `get().cloned()`
@@ -295,6 +301,8 @@ fork_join_util(transitions_vec.len(), None, |start, end, _| {
295301
});
296302
```
297303

304+
**Review Comments** reviewer: Xin GAO; state: ignored; comments:
305+
298306
---
299307

300308
## INFO (2)

src/hint.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ impl RWSet {
8787
/// Struct to hold shared transaction states and provide methods for parsing
8888
/// and handling execution hints for parallel transaction execution.
8989
pub(crate) struct ParallelExecutionHints {
90-
/// SAFETY: Wrapped in `UnsafeCell` to allow disjoint parallel writes.
91-
/// Each thread in `fork_join_util` writes only to its own index range.
9290
rw_set: UnsafeCell<Vec<RWSet>>,
9391
txs: Arc<Vec<TxEnv>>,
9492
}
@@ -106,8 +104,6 @@ impl ParallelExecutionHints {
106104
let mut last_write_tx: HashMap<LocationAndType, TxId> = HashMap::new();
107105
let mut dependent_tx: Vec<Option<TxId>> = vec![None; num_txs];
108106
let mut affect_txs = vec![HashSet::new(); num_txs];
109-
// SAFETY: generate_dependency is called after parse_hints completes (fork_join is done),
110-
// so no concurrent access exists.
111107
let rw_set = unsafe { &*self.rw_set.get() };
112108
for (txid, rw_set) in rw_set.iter().enumerate() {
113109
for location in rw_set.read_set.iter() {
@@ -128,8 +124,6 @@ impl ParallelExecutionHints {
128124
let txs = self.txs.clone();
129125
// Utilize fork-join utility to process transactions in parallel
130126
fork_join_util(txs.len(), None, |start_tx, end_tx, _| {
131-
// SAFETY: Each thread writes to disjoint index ranges [start_tx..end_tx],
132-
// guaranteed by fork_join_util's partitioning.
133127
let hints = unsafe { &mut *self.rw_set.get() };
134128
for index in start_tx..end_tx {
135129
let tx_env = &txs[index];

src/scheduler.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ use std::{
4141
time::Instant,
4242
};
4343

44+
/// min number of txs to parallel execute.
45+
const MIN_PARALLEL_TXS: usize = 64;
46+
4447
pub(crate) type MVMemory = DashMap<LocationAndType, BTreeMap<TxId, MemoryEntry>>;
4548

4649
#[derive(Metrics)]
@@ -266,9 +269,6 @@ where
266269
env: BlockEnv,
267270
block_size: usize,
268271
txs: Arc<Vec<TxEnv>>,
269-
/// SAFETY: `UnsafeCell` allows the commit thread to mutate state while worker threads read.
270-
/// The commit thread has exclusive write access (serialized by finality ordering).
271-
/// Worker threads only read via `DatabaseRef` (DashMap-based, thread-safe).
272272
state: UnsafeCell<ParallelState<DB>>,
273273
results: Mutex<Vec<ExecutionResult>>,
274274
tx_states: Vec<Mutex<TxState>>,
@@ -445,16 +445,15 @@ where
445445
std::env::var("GREVM_CONCURRENT_LEVEL")
446446
.map_or(*CONCURRENT_LEVEL, |s| s.parse().unwrap_or(*CONCURRENT_LEVEL)),
447447
);
448-
if *FALLBACK_SEQUENTIAL {
448+
if *FALLBACK_SEQUENTIAL || self.block_size < MIN_PARALLEL_TXS {
449449
return self.fallback_sequential();
450450
}
451451
let commiter = Mutex::new(StateAsyncCommit::new(
452452
self.env.beneficiary,
453453
CommitGuard::new(&self.state),
454454
self.cfg.disable_nonce_check,
455455
));
456-
// SAFETY: Worker threads access `ParallelState` only through `DatabaseRef` (read-only,
457-
// DashMap-based, inherently thread-safe). The commit thread is the sole writer.
456+
458457
let state_ref = unsafe { &*self.state.get() };
459458
commiter.lock().init().map_err(|e| GrevmError { txid: 0, error: EVMError::Database(e) })?;
460459
thread::scope(|scope| {
@@ -571,9 +570,6 @@ where
571570
}
572571

573572
let mut sequential_results = Vec::with_capacity(self.block_size - num_commit);
574-
// SAFETY: fallback_sequential is called either before parallel execution starts
575-
// (when FALLBACK_SEQUENTIAL is true) or after post_execute (after thread::scope
576-
// has joined all threads), so no concurrent access exists.
577573
let mut commit_guard = CommitGuard::new(&self.state);
578574
let state_mut = commit_guard.state_mut();
579575
{

src/storage.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ impl ParallelBundleState for BundleState {
8686
let revert = transition.create_revert();
8787
if let Some(revert) = revert {
8888
state_size.fetch_add(present_bundle.size_hint(), Ordering::Relaxed);
89-
// SAFETY: fork_join_util guarantees each thread writes to disjoint indices.
9089
unsafe { bundle_state.set(pos, Some((address, present_bundle))) };
9190
if include_reverts {
9291
unsafe { reverts.set(pos, Some((address, revert))) };

0 commit comments

Comments
 (0)