From eda0ab8c55549f7f625517ff1be6013f0c991591 Mon Sep 17 00:00:00 2001 From: Howard Wu <9260812+howardwu@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:48:35 -0800 Subject: [PATCH 1/3] Adds a block lock for advancing --- synthesizer/src/vm/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/synthesizer/src/vm/mod.rs b/synthesizer/src/vm/mod.rs index 2c2bb80abe..00e16a05b0 100644 --- a/synthesizer/src/vm/mod.rs +++ b/synthesizer/src/vm/mod.rs @@ -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"))] @@ -72,6 +72,8 @@ pub struct VM> { process: Arc>>, /// The VM store. store: ConsensusStore, + /// The lock for advancing blocks. + block_lock: Arc>, } impl> VM { @@ -169,7 +171,7 @@ impl> VM { } // Return the new VM. - Ok(Self { process: Arc::new(RwLock::new(process)), store }) + Ok(Self { process: Arc::new(RwLock::new(process)), store, block_lock: Arc::new(Mutex::new(())) }) } /// Returns `true` if a program with the given program ID exists. @@ -310,6 +312,10 @@ impl> VM { /// Adds the given block into the VM. #[inline] pub fn add_next_block(&self, block: &Block) -> 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::( block.round(), From 7cfadd9186534906eb3657b6f40f902917e59cd1 Mon Sep 17 00:00:00 2001 From: Howard Wu <9260812+howardwu@users.noreply.github.com> Date: Tue, 19 Dec 2023 17:04:45 -0800 Subject: [PATCH 2/3] Introduce an atomic lock over speculate and finalize --- synthesizer/src/vm/finalize.rs | 10 ++++++++++ synthesizer/src/vm/mod.rs | 10 +++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/synthesizer/src/vm/finalize.rs b/synthesizer/src/vm/finalize.rs index 2972d78ad1..8c9422d153 100644 --- a/synthesizer/src/vm/finalize.rs +++ b/synthesizer/src/vm/finalize.rs @@ -159,6 +159,11 @@ impl> VM { Vec<(Transaction, String)>, Vec>, )> { + // 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. @@ -448,6 +453,11 @@ impl> VM { solutions: Option<&CoinbaseSolution>, transactions: &Transactions, ) -> Result>> { + // 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. diff --git a/synthesizer/src/vm/mod.rs b/synthesizer/src/vm/mod.rs index 00e16a05b0..709b1e08e1 100644 --- a/synthesizer/src/vm/mod.rs +++ b/synthesizer/src/vm/mod.rs @@ -72,8 +72,8 @@ pub struct VM> { process: Arc>>, /// The VM store. store: ConsensusStore, - /// The lock for advancing blocks. - block_lock: Arc>, + /// The lock to guarantee atomicity over calls to speculate and finalize. + atomic_lock: Arc>, } impl> VM { @@ -171,7 +171,7 @@ impl> VM { } // Return the new VM. - Ok(Self { process: Arc::new(RwLock::new(process)), store, block_lock: Arc::new(Mutex::new(())) }) + Ok(Self { process: Arc::new(RwLock::new(process)), store, atomic_lock: Arc::new(Mutex::new(())) }) } /// Returns `true` if a program with the given program ID exists. @@ -312,10 +312,6 @@ impl> VM { /// Adds the given block into the VM. #[inline] pub fn add_next_block(&self, block: &Block) -> 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::( block.round(), From 6e05e7173eb07f16e952a806132dd948265b84dc Mon Sep 17 00:00:00 2001 From: Howard Wu <9260812+howardwu@users.noreply.github.com> Date: Tue, 19 Dec 2023 17:16:29 -0800 Subject: [PATCH 3/3] Adds block lock back in --- synthesizer/src/vm/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/synthesizer/src/vm/mod.rs b/synthesizer/src/vm/mod.rs index 709b1e08e1..a9e29d1594 100644 --- a/synthesizer/src/vm/mod.rs +++ b/synthesizer/src/vm/mod.rs @@ -74,6 +74,8 @@ pub struct VM> { store: ConsensusStore, /// The lock to guarantee atomicity over calls to speculate and finalize. atomic_lock: Arc>, + /// The lock for ensuring there is no concurrency when advancing blocks. + block_lock: Arc>, } impl> VM { @@ -171,7 +173,12 @@ impl> VM { } // Return the new VM. - Ok(Self { process: Arc::new(RwLock::new(process)), store, atomic_lock: Arc::new(Mutex::new(())) }) + 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. @@ -312,6 +319,10 @@ impl> VM { /// Adds the given block into the VM. #[inline] pub fn add_next_block(&self, block: &Block) -> 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::( block.round(),