Skip to content

Commit 9b946d8

Browse files
authored
Merge pull request ProvableHQ#2261 from AleoHQ/feat/synchronize-entry
Adds locks for speculate/finalize & on advancing to next block
2 parents 2e28b50 + e38ee4a commit 9b946d8

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

synthesizer/src/vm/finalize.rs

+10
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
159159
Vec<(Transaction<N>, String)>,
160160
Vec<FinalizeOperation<N>>,
161161
)> {
162+
// Acquire the atomic lock, which is needed to ensure this function is not called concurrently
163+
// with other `atomic_finalize!` macro calls, which will cause a `bail!` to be triggered erroneously.
164+
// Note: This lock must be held for the entire scope of the call to `atomic_finalize!`.
165+
let _atomic_lock = self.atomic_lock.lock();
166+
162167
let timer = timer!("VM::atomic_speculate");
163168

164169
// Retrieve the number of transactions.
@@ -448,6 +453,11 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
448453
solutions: Option<&CoinbaseSolution<N>>,
449454
transactions: &Transactions<N>,
450455
) -> Result<Vec<FinalizeOperation<N>>> {
456+
// Acquire the atomic lock, which is needed to ensure this function is not called concurrently
457+
// with other `atomic_finalize!` macro calls, which will cause a `bail!` to be triggered erroneously.
458+
// Note: This lock must be held for the entire scope of the call to `atomic_finalize!`.
459+
let _atomic_lock = self.atomic_lock.lock();
460+
451461
let timer = timer!("VM::atomic_finalize");
452462

453463
// Perform the finalize operation on the preset finalize mode.

synthesizer/src/vm/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use synthesizer_program::{FinalizeGlobalState, FinalizeOperation, FinalizeStoreT
6060

6161
use aleo_std::prelude::{finish, lap, timer};
6262
use indexmap::{IndexMap, IndexSet};
63-
use parking_lot::RwLock;
63+
use parking_lot::{Mutex, RwLock};
6464
use std::sync::Arc;
6565

6666
#[cfg(not(feature = "serial"))]
@@ -72,6 +72,10 @@ pub struct VM<N: Network, C: ConsensusStorage<N>> {
7272
process: Arc<RwLock<Process<N>>>,
7373
/// The VM store.
7474
store: ConsensusStore<N, C>,
75+
/// The lock to guarantee atomicity over calls to speculate and finalize.
76+
atomic_lock: Arc<Mutex<()>>,
77+
/// The lock for ensuring there is no concurrency when advancing blocks.
78+
block_lock: Arc<Mutex<()>>,
7579
}
7680

7781
impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
@@ -169,7 +173,12 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
169173
}
170174

171175
// Return the new VM.
172-
Ok(Self { process: Arc::new(RwLock::new(process)), store })
176+
Ok(Self {
177+
process: Arc::new(RwLock::new(process)),
178+
store,
179+
atomic_lock: Arc::new(Mutex::new(())),
180+
block_lock: Arc::new(Mutex::new(())),
181+
})
173182
}
174183

175184
/// Returns `true` if a program with the given program ID exists.
@@ -310,6 +319,10 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
310319
/// Adds the given block into the VM.
311320
#[inline]
312321
pub fn add_next_block(&self, block: &Block<N>) -> Result<()> {
322+
// Acquire the block lock, which is needed to ensure this function is not called concurrently.
323+
// Note: This lock must be held for the entire scope of this function.
324+
let _block_lock = self.block_lock.lock();
325+
313326
// Construct the finalize state.
314327
let state = FinalizeGlobalState::new::<N>(
315328
block.round(),

0 commit comments

Comments
 (0)