Skip to content

Commit

Permalink
Merge pull request #2261 from AleoHQ/feat/synchronize-entry
Browse files Browse the repository at this point in the history
Adds locks for speculate/finalize & on advancing to next block
  • Loading branch information
howardwu authored Dec 20, 2023
2 parents 2e28b50 + e38ee4a commit 9b946d8
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
10 changes: 10 additions & 0 deletions synthesizer/src/vm/finalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
Vec<(Transaction<N>, String)>,
Vec<FinalizeOperation<N>>,
)> {
// Acquire the atomic lock, which is needed to ensure this function is not called concurrently
// with other `atomic_finalize!` macro calls, which will cause a `bail!` to be triggered erroneously.
// Note: This lock must be held for the entire scope of the call to `atomic_finalize!`.
let _atomic_lock = self.atomic_lock.lock();

let timer = timer!("VM::atomic_speculate");

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

let timer = timer!("VM::atomic_finalize");

// Perform the finalize operation on the preset finalize mode.
Expand Down
17 changes: 15 additions & 2 deletions synthesizer/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use synthesizer_program::{FinalizeGlobalState, FinalizeOperation, FinalizeStoreT

use aleo_std::prelude::{finish, lap, timer};
use indexmap::{IndexMap, IndexSet};
use parking_lot::RwLock;
use parking_lot::{Mutex, RwLock};
use std::sync::Arc;

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

impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
Expand Down Expand Up @@ -169,7 +173,12 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
}

// Return the new VM.
Ok(Self { process: Arc::new(RwLock::new(process)), store })
Ok(Self {
process: Arc::new(RwLock::new(process)),
store,
atomic_lock: Arc::new(Mutex::new(())),
block_lock: Arc::new(Mutex::new(())),
})
}

/// Returns `true` if a program with the given program ID exists.
Expand Down Expand Up @@ -310,6 +319,10 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
/// Adds the given block into the VM.
#[inline]
pub fn add_next_block(&self, block: &Block<N>) -> Result<()> {
// Acquire the block lock, which is needed to ensure this function is not called concurrently.
// Note: This lock must be held for the entire scope of this function.
let _block_lock = self.block_lock.lock();

// Construct the finalize state.
let state = FinalizeGlobalState::new::<N>(
block.round(),
Expand Down

0 comments on commit 9b946d8

Please sign in to comment.