Repository: mintlayer/mintlayer-core
Pull request #709 (2023-02-16 09:40:59)

Create VRF keys from custom Rng


Patch:
diff --git a/.github/scripts/codecheck.py b/.github/scripts/codecheck.py
index afa8ab625..c95b254a0 100755
--- a/.github/scripts/codecheck.py
+++ b/.github/scripts/codecheck.py
@@ -67,23 +67,6 @@ def check_crate_version_unique(crate_name):
 
     return len(versions) == 1
 
-# Ensure that the versions in the workspace's Cargo.toml are consistent
-def check_workspace_and_package_versions_equal():
-    print("==== Ensuring workspace and package versions are equal in the workspace's Cargo.toml")
-    root = toml.load('Cargo.toml')
-
-    workspace_version = root['package']['version']
-    package_version = root['workspace']['package']['version']
-
-    result = workspace_version == package_version
-
-    if not result:
-        print("Workspace vs package versions mismatch in Cargo.toml: '{}' != '{}'".format(workspace_version, package_version))
-        print()
-
-    return result
-
-
 # Check crate versions
 def check_crate_versions():
     print("==== Checking crate versions:")
@@ -99,7 +82,7 @@ def check_crate_versions():
 # Check license header in current project crates
 def check_local_licenses():
     print("==== Checking local license headers:")
-
+    
     # list of files exempted from license check
     exempted_files = [
         "./script/src/opcodes.rs",
@@ -109,14 +92,14 @@ def check_local_licenses():
         "./common/src/uint/impls.rs",
         "./common/src/uint/mod.rs"
         ]
-
+    
     template = re.compile('(?:' + r')\n(?:'.join(LICENSE_TEMPLATE) + ')')
 
     ok = True
     for path in rs_sources():
         if any(os.path.samefile(path, exempted) for exempted in exempted_files):
             continue
-
+        
         with open(path) as file:
             if not template.search(file.read()):
                 ok = False
@@ -128,16 +111,16 @@ def check_local_licenses():
 # check TODO(PR) and FIXME instances
 def check_todos():
     print("==== Checking TODO(PR) and FIXME instances:")
-
+    
     # list of files exempted from checks
     exempted_files = [
         ]
-
+    
     ok = True
     for path in rs_sources():
         if any(os.path.samefile(path, exempted) for exempted in exempted_files):
             continue
-
+        
         with open(path) as file:
             file_data = file.read()
             if 'TODO(PR)' in file_data or 'FIXME' in file_data:
@@ -153,7 +136,6 @@ def run_checks():
             disallow(JSONRPSEE_RE, exclude = ['rpc']),
             check_local_licenses(),
             check_crate_versions(),
-            check_workspace_and_package_versions_equal(),
             check_todos()
         ])
 
diff --git a/Cargo.lock b/Cargo.lock
index 0cd65caeb..77b5fb3e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -311,7 +311,6 @@ dependencies = [
  "chainstate-storage",
  "common",
  "crossbeam-channel",
- "crypto",
  "futures",
  "jsonrpsee",
  "logging",
diff --git a/Cargo.toml b/Cargo.toml
index 2e43b38ae..b04887e80 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -79,12 +79,6 @@ serialization = { path = "serialization"}
 storage = { path = "storage"}
 utxo = { path = "utxo"}
 
-[workspace.package]
-edition = "2021"
-rust-version = "1.67"
-version = "0.1.0"
-license = "MIT"
-
 [workspace.dependencies]
 async-trait = "0.1"
 futures = "0.3"
diff --git a/accounting/Cargo.toml b/accounting/Cargo.toml
index faeda215c..7578be75d 100644
--- a/accounting/Cargo.toml
+++ b/accounting/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "accounting"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+license = "MIT"
+version = "0.1.0"
+edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/blockprod/Cargo.toml b/blockprod/Cargo.toml
index 48500a3bd..5570c3252 100644
--- a/blockprod/Cargo.toml
+++ b/blockprod/Cargo.toml
@@ -1,16 +1,14 @@
 [package]
 name = "blockprod"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
 chainstate = { path = "../chainstate/" }
 common = { path = "../common/" }
-crypto = { path = "../crypto/" }
 mempool = { path = "../mempool/" }
 subsystem = { path = "../subsystem/" }
 logging = {path = '../logging'}
diff --git a/blockprod/src/detail/block_maker.rs b/blockprod/src/detail/block_maker.rs
index 386a79a11..c5d277fb5 100644
--- a/blockprod/src/detail/block_maker.rs
+++ b/blockprod/src/detail/block_maker.rs
@@ -38,7 +38,7 @@ pub enum BlockMakerControlCommand {
     Stop,
 }
 
-/// Slave to the [PerpetualBlockBuilder]. Every new block tip gets one Block Maker, and keeps running
+/// Slave to the [PerpetualBlockBuilder]. Every new block tip gets one BlockMaker, and keeps running
 /// until either it's successful in submitting a block, or there's a new tip in chainstate, deeming
 /// the effort pointless
 pub struct BlockMaker {
@@ -129,7 +129,7 @@ impl BlockMaker {
                 .log_err()?;
             if let Ok(_new_block_index) = block_submit_result {
                 log::info!(
-                "Success in submitting block {} at height {}. Exiting Block Maker at tip {} and height {}",
+                "Success in submitting block {} at height {}. Exiting block maker at tip {} and height {}",
                 block_id,
                 self.current_tip_height.next_height(),
                 self.current_tip_id,
@@ -157,16 +157,16 @@ impl BlockMaker {
                 BlockSubmitResult::Success => break,
             }
 
-            // attempt to receive new commands from the perpetual Block Builder
+            // attempt to receive new commands from the perpetual builder
             let new_info = match self.block_maker_rx.try_recv() {
                 Ok(cmd) => cmd,
                 Err(e) => match e {
                     // if there's nothing from the channel, then we can keep trying to build the block
                     crossbeam_channel::TryRecvError::Empty => continue,
-                    // if the channel is lost, that means the perpetual Block Builder is destroyed.
+                    // if the channel is lost, that means the perpetual builder is destroyed.
                     // No point in continuing since it seems that the node exited.
                     crossbeam_channel::TryRecvError::Disconnected => {
-                        log::error!("Block Maker control channel lost. Exiting Block Maker task on tip {} on best height {}", self.current_tip_id, self.current_tip_height);
+                        log::error!("Block maker control channel lost. Exiting maker task on tip {} on best height {}", self.current_tip_id, self.current_tip_height);
                         break;
                     }
                 },
diff --git a/blockprod/src/detail/builder.rs b/blockprod/src/detail/builder.rs
index cfe92306c..9295ba042 100644
--- a/blockprod/src/detail/builder.rs
+++ b/blockprod/src/detail/builder.rs
@@ -203,313 +203,14 @@ impl PerpetualBlockBuilder {
     }
 }
 
-/// On destruction, this struct sends a message to all Block Makers to stop to aid a graceful exit
+/// On destruction, this struct sends a message to all block makers to stop to aid a graceful exit
 struct BlockMakersDestroyer(crossbeam_channel::Sender<BlockMakerControlCommand>);
 
 impl Drop for BlockMakersDestroyer {
     fn drop(&mut self) {
         match self.0.send(BlockMakerControlCommand::Stop) {
             Ok(_) => (),
-            Err(err) => log::error!("Failed to stop all Block Makers: {}", err),
+            Err(err) => log::error!("Failed to stop all block makers: {}", err),
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::setup_blockprod_test;
-    use chainstate::BlockSource;
-    use crypto::random::make_pseudo_rng;
-    use std::thread;
-    use tokio::task::yield_now;
-    use tokio::time::{timeout, Duration};
-
-    use common::{
-        chain::block::{timestamp::BlockTimestamp, BlockReward, ConsensusData},
-        primitives::{Idable, H256},
-        time_getter::TimeGetter,
-    };
-
-    use super::*;
-
-    #[test]
-    fn new_tip() {
-        let (_manager, chain_config, chainstate, mempool) = setup_blockprod_test();
-
-        let (_tx_builder, rx_builder) = mpsc::unbounded_channel();
-
-        let mut block_builder = PerpetualBlockBuilder::new(
-            chain_config,
-            chainstate,
-            mempool,
-            Default::default(),
-            rx_builder,
-            true,
-        );
-
-        let block_id = Id::new(H256::random_using(&mut make_pseudo_rng()));
-
-        block_builder
-            .new_tip(block_id, BlockHeight::one())
-            .expect("Error sending new tip to Block Makers");
-
-        match block_builder
-            .block_maker_rx
-            .try_recv()
-            .expect("Error reading from Block Builder")
-        {
-            BlockMakerControlCommand::NewTip(new_block_id, new_block_height) => {
-                assert!(block_id == new_block_id, "Invalid Block ID received");
-                assert!(
-                    new_block_height == BlockHeight::one(),
-                    "Invalid block height received"
-                );
-            }
-            _ => panic!("Error reading new tip from Block Builder"),
-        }
-    }
-
-    #[test]
-    fn stop() {
-        let (_manager, chain_config, chainstate, mempool) = setup_blockprod_test();
-
-        let (_tx_builder, rx_builder) = mpsc::unbounded_channel();
-
-        let block_builder = PerpetualBlockBuilder::new(
-            chain_config,
-            chainstate,
-            mempool,
-            Default::default(),
-            rx_builder,
-            true,
-        );
-
-        block_builder.stop_all_block_makers().expect("Error stopping all Block Makers");
-
-        match block_builder
-            .block_maker_rx
-            .try_recv()
-            .expect("Error reading from Block Builder")
-        {
-            BlockMakerControlCommand::Stop => {}
-            _ => panic!("Invalid message received from Block Builder"),
-        }
-    }
-
-    #[tokio::test]
-    async fn run() {
-        let (manager, chain_config, chainstate, mempool) = setup_blockprod_test();
-
-        let (_tx_builder, rx_builder) = mpsc::unbounded_channel();
-
-        let mut block_builder = PerpetualBlockBuilder::new(
-            chain_config.clone(),
-            chainstate.clone(),
-            mempool.clone(),
-            Default::default(),
-            rx_builder,
-            true,
-        );
-
-        let block_maker_rx = block_builder.block_maker_rx.clone();
-
-        let block = Block::new(
-            vec![],
-            chain_config.genesis_block_id(),
-            BlockTimestamp::from_duration_since_epoch(TimeGetter::default().get_time()),
-            ConsensusData::None,
-            BlockReward::new(Vec::new()),
-        )
-        .expect("Error creating test block");
-
-        //
-        // Flag that the mempool saw the new tip event
-        //
-
-        let (tx, _rx) = crossbeam_channel::bounded(1);
-
-        mempool.call_async_mut({
-            let block_id = block.get_id();
-            move |this| {
-                this.subscribe_to_events(Arc::new(move |mempool_event| match mempool_event {
-                    MempoolEvent::NewTip(new_block_id, new_block_height) => {
-                        if block_id == new_block_id && new_block_height == BlockHeight::one() {
-                            tx.send(true).expect("Error sending new tip confirmation");
-                        }
-                    }
-                }))
-            }
-        });
-
-        //
-        // Flag that chainstate saw the new tip event
-        //
-
-        thread::spawn({
-            let block_id = block.get_id();
-            let shutdown = manager.make_shutdown_trigger();
-
-            move || {
-                match block_maker_rx.recv().expect("Error reading from Block Builder") {
-                    BlockMakerControlCommand::NewTip(new_block_id, new_block_height) => {
-                        assert!(block_id == new_block_id, "Invalid Block ID received");
-                        assert!(
-                            new_block_height == BlockHeight::one(),
-                            "Invalid block height received"
-                        );
-                    }
-                    _ => panic!("Error reading new tip from Block Builder"),
-                }
-
-                // TODO: the following assertion will fail until we turn on mempool broadcasts
-                //
-                // assert!(
-                //     rx.recv_timeout(Duration::from_millis(1000)).is_ok(),
-                //     "Mempool new tip timed out"
-                // );
-
-                shutdown.initiate();
-            }
-        });
-
-        tokio::spawn(async move {
-            // This will error due to run()'s recv() on disconnect when done
-            block_builder.run().await.err();
-        });
-
-        let get_subscriber_count = {
-            let chainstate = chainstate.clone();
-            move || chainstate.call_mut(|this| this.subscribers().len())
-        };
-
-        tokio::spawn(async move {
-            loop {
-                // One subscriber from this run()'s self.subscribe_to_chainstate_events()
-                // The other from mempool.run()'s self.subscribe_to_chainstate_events()
-                if get_subscriber_count().await.expect("Error getting subscriber count") == 2 {
-                    break;
-                }
-
-                yield_now().await;
-            }
-
-            chainstate.call_mut(|this| {
-                this.process_block(block, BlockSource::Local).expect("Error processing block")
-            });
-        });
-
-        manager.main().await;
-    }
-
-    #[tokio::test]
-    async fn subscribe_to_chainstate_events() {
-        let (manager, chain_config, chainstate, mempool) = setup_blockprod_test();
-
-        let (_tx_builder, rx_builder) = mpsc::unbounded_channel();
-
-        let block_builder = PerpetualBlockBuilder::new(
-            chain_config.clone(),
-            chainstate.clone(),
-            mempool,
-            Default::default(),
-            rx_builder,
-            true,
-        );
-
-        let shutdown = manager.make_shutdown_trigger();
-
-        tokio::spawn(async move {
-            let mut chainstate_rx = block_builder
-                .subscribe_to_chainstate_events()
-                .await
-                .expect("Error subscribing to chainstate events");
-
-            let block = Block::new(
-                vec![],
-                chain_config.genesis_block_id(),
-                BlockTimestamp::from_duration_since_epoch(TimeGetter::default().get_time()),
-                ConsensusData::None,
-                BlockReward::new(Vec::new()),
-            )
-            .expect("Error creating test block");
-
-            let block_id = block.get_id();
-
-            chainstate.call_mut(move |this| {
-                this.process_block(block, BlockSource::Local).expect("Error processing block");
-            });
-
-            let recv = timeout(Duration::from_millis(1000), chainstate_rx.recv());
-
-            tokio::select! {
-                msg = recv => match msg.expect("Chainstate timed out") {
-                    Some((new_block_id, _)) => {
-                        assert!(new_block_id == block_id, "Invalid Block Id received");
-                    }
-                    _ => panic!("Invalid message from chainstate"),
-                }
-            }
-
-            shutdown.initiate();
-        });
-
-        manager.main().await;
-    }
-
-    #[tokio::test]
-    async fn subscribe_to_mempool_events() {
-        let (manager, chain_config, chainstate, mempool) = setup_blockprod_test();
-
-        let (_tx_builder, rx_builder) = mpsc::unbounded_channel();
-
-        let block_builder = PerpetualBlockBuilder::new(
-            chain_config.clone(),
-            chainstate.clone(),
-            mempool,
-            Default::default(),
-            rx_builder,
-            true,
-        );
-
-        let shutdown = manager.make_shutdown_trigger();
-
-        tokio::spawn(async move {
-            let mut mempool_rx = block_builder
-                .subscribe_to_mempool_events()
-                .await
-                .expect("Error subscribing to chainstate events");
-
-            let block = Block::new(
-                vec![],
-                chain_config.genesis_block_id(),
-                BlockTimestamp::from_duration_since_epoch(TimeGetter::default().get_time()),
-                ConsensusData::None,
-                BlockReward::new(Vec::new()),
-            )
-            .expect("Error creating test block");
-
-            let _block_id = block.get_id();
-
-            chainstate.call_mut(move |this| {
-                this.process_block(block, BlockSource::Local).expect("Error processing block");
-            });
-
-            let _recv = timeout(Duration::from_millis(1000), mempool_rx.recv());
-
-            // TODO: the following assertion will fail until we turn on mempool broadcasts
-            //
-            // tokio::select! {
-            //     msg = recv => match msg.expect("Mempool timed out") {
-            //         Some((new_block_id, _)) => {
-            //             assert!(new_block_id == block_id, "Invalid Block Id received");
-            //         }
-            //         _ => panic!("Invalid message from mempool"),
-            //     }
-            // }
-
-            shutdown.initiate();
-        });
-
-        manager.main().await;
-    }
-}
diff --git a/blockprod/src/detail/mod.rs b/blockprod/src/detail/mod.rs
index 3f9e04c2b..e59d7e08a 100644
--- a/blockprod/src/detail/mod.rs
+++ b/blockprod/src/detail/mod.rs
@@ -83,7 +83,7 @@ mod tests {
     use crate::tests::setup_blockprod_test;
 
     #[tokio::test]
-    async fn stop() {
+    async fn test_stop() {
         let (_manager, chain_config, chainstate, mempool) = setup_blockprod_test();
 
         let (builder_tx, mut builder_rx) = mpsc::unbounded_channel();
@@ -95,22 +95,22 @@ mod tests {
             Default::default(),
             builder_tx,
         )
-        .expect("Error initializing Block Builder");
+        .expect("Error initializing Builder");
 
-        block_production.stop().expect("Error stopping Block Builder");
+        block_production.stop().expect("Error stopping Builder");
 
         let recv = timeout(Duration::from_millis(1000), builder_rx.recv());
 
         tokio::select! {
-            msg = recv => match msg.expect("Block Builder timed out").expect("Error reading from Block Builder") {
+            msg = recv => match msg.expect("Builder timed out").expect("Error reading from Builder") {
                 BlockBuilderControlCommand::Stop => {},
-                _ => panic!("Invalid message received from Block Builder"),
+                _ => panic!("Invalid message received from Builder"),
             }
         }
     }
 
     #[tokio::test]
-    async fn start() {
+    async fn test_start() {
         let (_manager, chain_config, chainstate, mempool) = setup_blockprod_test();
 
         let (builder_tx, mut builder_rx) = mpsc::unbounded_channel();
@@ -122,22 +122,22 @@ mod tests {
             Default::default(),
             builder_tx,
         )
-        .expect("Error initializing Block Builder");
+        .expect("Error initializing Builder");
 
-        block_production.start().expect("Error starting Block Builder");
+        block_production.start().expect("Error starting Builder");
 
         let recv = timeout(Duration::from_millis(1000), builder_rx.recv());
 
         tokio::select! {
-            msg = recv => match msg.expect("Block Builder timed out").expect("Error reading from Block Builder") {
+            msg = recv => match msg.expect("Builder timed out").expect("Error reading from Builder") {
                 BlockBuilderControlCommand::Start => {},
-                _ => panic!("Invalid message received from Block Builder"),
+                _ => panic!("Invalid message received from Builder"),
             }
         }
     }
 
     #[tokio::test]
-    async fn is_connected() {
+    async fn test_is_connected() {
         let (_manager, chain_config, chainstate, mempool) = setup_blockprod_test();
 
         let (builder_tx, _builder_rx) = mpsc::unbounded_channel();
@@ -149,11 +149,8 @@ mod tests {
             Default::default(),
             builder_tx,
         )
-        .expect("Error initializing Block Builder");
+        .expect("Error initializing Builder");
 
-        assert!(
-            block_production.is_connected(),
-            "Block Builder is not connected"
-        );
+        assert!(block_production.is_connected(), "Builder is not connected");
     }
 }
diff --git a/blockprod/src/interface/mod.rs b/blockprod/src/interface/mod.rs
index dcc3af6c3..ae6685c95 100644
--- a/blockprod/src/interface/mod.rs
+++ b/blockprod/src/interface/mod.rs
@@ -16,14 +16,14 @@
 use crate::BlockProductionError;
 
 pub trait BlockProductionInterface: Send {
-    /// When called, the Block Builder will start creating blocks at the next tip in chainstate
+    /// When called, the block builder will start creating blocks at the next tip in chainstate
     fn start(&self) -> Result<(), BlockProductionError>;
 
-    /// When called, the Block Builder will cancel all current attempts to create blocks
+    /// When called, the block builder will cancel all current attempts to create blocks
     /// and won't attempt to do it again for new tips in chainstate or mempool
     /// Call start() to enable again
     fn stop(&self) -> Result<(), BlockProductionError>;
 
-    /// Check if the Block Builder is currently connected
+    /// Check if the block builder is currently connected
     fn is_connected(&self) -> bool;
 }
diff --git a/blockprod/src/lib.rs b/blockprod/src/lib.rs
index e6bb4935b..68ac090d7 100644
--- a/blockprod/src/lib.rs
+++ b/blockprod/src/lib.rs
@@ -36,7 +36,7 @@ pub enum BlockProductionError {
     MempoolChannelClosed,
     #[error("Chainstate channel closed")]
     ChainstateChannelClosed,
-    #[error("Block Builder command channel closed")]
+    #[error("Block builder command channel closed")]
     BlockBuilderChannelClosed,
     #[error("Subsystem call error")]
     SubsystemCallError(#[from] CallError),
@@ -152,11 +152,11 @@ mod tests {
         tokio::spawn(async move {
             blockprod
                 .call(move |this| {
-                    assert!(this.is_connected(), "Block Builder is not connected");
+                    assert!(this.is_connected(), "Builder is not connected");
                     shutdown.initiate();
                 })
                 .await
-                .expect("Error initializing Block Builder");
+                .expect("Error initializing Builder");
         });
 
         manager.main().await;
diff --git a/chainstate/Cargo.toml b/chainstate/Cargo.toml
index 149245275..bb4fdfb2b 100644
--- a/chainstate/Cargo.toml
+++ b/chainstate/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
+edition = "2021"
+license = "MIT"
 name = "chainstate"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
 
 [dependencies]
 chainstate-storage = {path = './storage', features = ["mock"]}
diff --git a/chainstate/launcher/Cargo.toml b/chainstate/launcher/Cargo.toml
index 1f3a526d3..ed6167716 100644
--- a/chainstate/launcher/Cargo.toml
+++ b/chainstate/launcher/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "chainstate-launcher"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+license = "MIT"
+version = "0.1.0"
+edition = "2021"
 
 [dependencies]
 
diff --git a/chainstate/storage/Cargo.toml b/chainstate/storage/Cargo.toml
index fa88ae40f..0c06ec544 100644
--- a/chainstate/storage/Cargo.toml
+++ b/chainstate/storage/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "chainstate-storage"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/chainstate/tx-verifier/Cargo.toml b/chainstate/tx-verifier/Cargo.toml
index d9bf396f2..d58382ed2 100644
--- a/chainstate/tx-verifier/Cargo.toml
+++ b/chainstate/tx-verifier/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "tx-verifier"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/chainstate/tx-verifier/src/transaction_verifier/config.rs b/chainstate/tx-verifier/src/transaction_verifier/config.rs
index 6f0ac86aa..dfeb1bc12 100644
--- a/chainstate/tx-verifier/src/transaction_verifier/config.rs
+++ b/chainstate/tx-verifier/src/transaction_verifier/config.rs
@@ -24,7 +24,7 @@ impl TransactionVerifierConfig {
     }
 
     /// If transaction index is enabled, the function f is called, otherwise Ok(None) is returned
-    /// This function returns `Result<Option<T>, E>` instead of `Option<Result<T,E>>` for convenience,
+    /// This function returns Result<Option<T>, E> instead of Option<Result<T,E>> for convenience,
     /// since error handling should happen before knowing the result
     pub fn if_tx_index_enabled<F, T, E>(&self, f: F) -> Result<Option<T>, E>
     where
diff --git a/chainstate/types/Cargo.toml b/chainstate/types/Cargo.toml
index 793da81e4..27ce387be 100644
--- a/chainstate/types/Cargo.toml
+++ b/chainstate/types/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "chainstate-types"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/common/Cargo.toml b/common/Cargo.toml
index 4d5fc2e84..36306264e 100644
--- a/common/Cargo.toml
+++ b/common/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "common"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/consensus/Cargo.toml b/consensus/Cargo.toml
index fa5c12a3f..7ed2cd93b 100644
--- a/consensus/Cargo.toml
+++ b/consensus/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
+edition = "2021"
+license = "MIT"
 name = "consensus"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
 
 [dependencies]
 common = {path = '../common'}
diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml
index 500c889ba..63d02549e 100644
--- a/crypto/Cargo.toml
+++ b/crypto/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "crypto"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 authors = ["Samer Afach <samer.afach@mintlayer.org>", "Ben Marsh <benjamin.marsh@mintlayer.org>", "Enrico Rubboli <enrico.rubboli@mintlayer.org>"]
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/crypto/src/vrf/mod.rs b/crypto/src/vrf/mod.rs
index 735f71ea3..af3477268 100644
--- a/crypto/src/vrf/mod.rs
+++ b/crypto/src/vrf/mod.rs
@@ -16,7 +16,7 @@
 use merlin::Transcript;
 use serialization::{Decode, Encode};
 
-use crate::random::make_true_rng;
+use crate::random::{make_true_rng, CryptoRng, Rng};
 
 pub use self::primitives::VRFReturn;
 
@@ -64,11 +64,17 @@ pub(crate) enum VRFPublicKeyHolder {
 }
 
 impl VRFPrivateKey {
-    pub fn new(key_kind: VRFKeyKind) -> (VRFPrivateKey, VRFPublicKey) {
-        let mut rng = make_true_rng();
+    pub fn new_from_entropy(key_kind: VRFKeyKind) -> (VRFPrivateKey, VRFPublicKey) {
+        Self::new_from_rng(&mut make_true_rng(), key_kind)
+    }
+
+    pub fn new_from_rng(
+        rng: &mut (impl Rng + CryptoRng),
+        key_kind: VRFKeyKind,
+    ) -> (VRFPrivateKey, VRFPublicKey) {
         match key_kind {
             VRFKeyKind::Schnorrkel => {
-                let k = schnorrkel::SchnorrkelPrivateKey::new(&mut rng);
+                let k = schnorrkel::SchnorrkelPrivateKey::new(rng);
                 (
                     VRFPrivateKey {
                         key: VRFPrivateKeyHolder::Schnorrkel(k.0),
@@ -125,15 +131,21 @@ impl VRFPublicKey {
 #[cfg(test)]
 mod tests {
     use hex::FromHex;
+    use rstest::rstest;
     use serialization::DecodeAll;
+    use test_utils::random::make_seedable_rng;
+    use test_utils::random::Seed;
 
     use crate::vrf::transcript::{TranscriptAssembler, TranscriptComponent};
 
     use super::{transcript::WrappedTranscript, *};
 
-    #[test]
-    fn key_serialization() {
-        let (sk, pk) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+    #[rstest]
+    #[trace]
+    #[case(Seed::from_entropy())]
+    fn key_serialization(#[case] seed: Seed) {
+        let mut rng = make_seedable_rng(seed);
+        let (sk, pk) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         let encoded_sk = sk.encode();
         let encoded_pk = pk.encode();
@@ -178,11 +190,14 @@ mod tests {
             .finalize()
     }
 
-    #[test]
-    fn vrf_basic_usage() {
+    #[rstest]
+    #[trace]
+    #[case(Seed::from_entropy())]
+    fn vrf_basic_usage(#[case] seed: Seed) {
         let transcript = make_arbitrary_transcript();
 
-        let (sk, pk) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let mut rng = make_seedable_rng(seed);
+        let (sk, pk) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
         let vrf_data = sk.produce_vrf_data(transcript.clone().into());
 
         match &vrf_data {
@@ -204,11 +219,14 @@ mod tests {
             .expect("Valid VRF check failed");
     }
 
-    #[test]
-    fn basic_usage_schonorrkel_mutated_message() {
+    #[rstest]
+    #[trace]
+    #[case(Seed::from_entropy())]
+    fn basic_usage_schonorrkel_mutated_message(#[case] seed: Seed) {
         let transcript = make_arbitrary_transcript();
 
-        let (sk, pk) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let mut rng = make_seedable_rng(seed);
+        let (sk, pk) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
         let vrf_data = sk.produce_vrf_data(transcript.clone().into());
 
         match &vrf_data {
@@ -233,11 +251,14 @@ mod tests {
             .expect_err("Invalid VRF check succeeded");
     }
 
-    #[test]
-    fn basic_usage_schnorrkel_invalid_keys() {
+    #[rstest]
+    #[trace]
+    #[case(Seed::from_entropy())]
+    fn basic_usage_schnorrkel_invalid_keys(#[case] seed: Seed) {
         let transcript = make_arbitrary_transcript();
 
-        let (sk, pk) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let mut rng = make_seedable_rng(seed);
+        let (sk, pk) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
         let vrf_data = sk.produce_vrf_data(transcript.clone().into());
 
         match &vrf_data {
@@ -255,7 +276,7 @@ mod tests {
             }
         }
 
-        let (_sk2, pk2) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_sk2, pk2) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         pk2.verify_vrf_data(transcript.into(), &vrf_data)
             .expect_err("Invalid VRF check succeeded");
diff --git a/deny.toml b/deny.toml
index 6153f2629..35edf7ea7 100644
--- a/deny.toml
+++ b/deny.toml
@@ -46,4 +46,8 @@ unsound = "warn"
 yanked = "warn"
 notice = "warn"
 severity-threshold = "medium"
-ignore = []
+ignore = [
+    # time/chrono problems, have not been a problem in practice
+    "RUSTSEC-2020-0159",
+    "RUSTSEC-2020-0071",
+]
diff --git a/dns_server/Cargo.toml b/dns_server/Cargo.toml
index 1ae21d397..607c22327 100644
--- a/dns_server/Cargo.toml
+++ b/dns_server/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "dns_server"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/logging/Cargo.toml b/logging/Cargo.toml
index 735061217..5edd4b408 100644
--- a/logging/Cargo.toml
+++ b/logging/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "logging"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/mempool/Cargo.toml b/mempool/Cargo.toml
index 704b1731d..c0e98475f 100644
--- a/mempool/Cargo.toml
+++ b/mempool/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "mempool"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/mempool/src/pool/mod.rs b/mempool/src/pool/mod.rs
index d3cad8f3e..893fc64c4 100644
--- a/mempool/src/pool/mod.rs
+++ b/mempool/src/pool/mod.rs
@@ -698,9 +698,6 @@ where
     }
 
     pub fn new_tip_set(&mut self, block_id: Id<Block>, block_height: BlockHeight) {
-        // TODO: turn on mempool new tip broadcasts when ready
-        // self.events_controller.broadcast(MempoolEvent::NewTip(block_id, block_height));
-
         log::info!(
             "new tip with block_id {:?} and block_height {:?}",
             block_id,
diff --git a/node/Cargo.toml b/node/Cargo.toml
index d852854af..e93991aff 100644
--- a/node/Cargo.toml
+++ b/node/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "node"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml
index 141c4075f..c70e652f4 100644
--- a/p2p/Cargo.toml
+++ b/p2p/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "p2p"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [features]
 default = []
diff --git a/p2p/src/error.rs b/p2p/src/error.rs
index 95820a10f..e6a5faca5 100644
--- a/p2p/src/error.rs
+++ b/p2p/src/error.rs
@@ -31,7 +31,7 @@ pub enum ProtocolError {
     Unresponsive,
 }
 
-/// Peer state errors (Errors either for an individual peer or for the [`PeerManager`](crate::peer_manager::PeerManager))
+/// Peer state errors (Errors either for an individual peer or for the [`PeerManager`])
 #[derive(Error, Debug, PartialEq, Eq)]
 pub enum PeerError {
     #[error("Peer disconnected")]
diff --git a/p2p/src/peer_manager/mod.rs b/p2p/src/peer_manager/mod.rs
index 3cbb2cafa..40cf62a2a 100644
--- a/p2p/src/peer_manager/mod.rs
+++ b/p2p/src/peer_manager/mod.rs
@@ -845,7 +845,8 @@ where
     /// Runs the `PeerManager` event loop.
     ///
     /// The event loop has this main responsibilities:
-    /// - listening to and handling control events from [`crate::sync::BlockSyncManager`]/RPC
+    /// - listening to and handling control events from [`crate::sync::SyncManager`]/
+    /// [`crate::pubsub::PubSubMessageHandler`]/RPC
     /// - listening to network events
     /// - updating internal state
     /// - sending and checking ping requests
@@ -853,8 +854,7 @@ where
     /// After handling an event from one of the aforementioned sources, the event loop
     /// handles the error (if any) and runs the [`PeerManager::heartbeat()`] function
     /// to perform the peer manager maintenance. If the `PeerManager` doesn't receive any events,
-    /// [`PEER_MGR_HEARTBEAT_INTERVAL_MIN`] and [`PEER_MGR_HEARTBEAT_INTERVAL_MAX`] defines how
-    /// often the heartbeat function is called.
+    /// [`PEER_MGR_HEARTBEAT_INTERVAL`] defines how often the heartbeat function is called.
     /// This is done to prevent the `PeerManager` from stalling in case the network doesn't
     /// have any events.
     pub async fn run(&mut self) -> crate::Result<void::Void> {
diff --git a/pos_accounting/Cargo.toml b/pos_accounting/Cargo.toml
index 6fed8a3f9..088ddbf6b 100644
--- a/pos_accounting/Cargo.toml
+++ b/pos_accounting/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "pos_accounting"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+license = "MIT"
+version = "0.1.0"
+edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml
index 776e73688..68a853e71 100644
--- a/rpc/Cargo.toml
+++ b/rpc/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "rpc"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/script/Cargo.toml b/script/Cargo.toml
index 9869d2a73..dcba2c715 100644
--- a/script/Cargo.toml
+++ b/script/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "script"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 crypto = { path = '../crypto' }
diff --git a/serialization/Cargo.toml b/serialization/Cargo.toml
index 6668d4e7d..c914f26e9 100644
--- a/serialization/Cargo.toml
+++ b/serialization/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "serialization"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 serialization-core = { path = 'core' }
diff --git a/serialization/core/Cargo.toml b/serialization/core/Cargo.toml
index 53ba3ad57..ae6f3e283 100644
--- a/serialization/core/Cargo.toml
+++ b/serialization/core/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "serialization-core"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/serialization/tagged/Cargo.toml b/serialization/tagged/Cargo.toml
index 2a441f9eb..7b604bd63 100644
--- a/serialization/tagged/Cargo.toml
+++ b/serialization/tagged/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "serialization-tagged"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 serialization-core = { path = '../core' }
diff --git a/serialization/tagged/derive/Cargo.toml b/serialization/tagged/derive/Cargo.toml
index 1b2caafca..cf2da8c95 100644
--- a/serialization/tagged/derive/Cargo.toml
+++ b/serialization/tagged/derive/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "serialization-tagged-derive"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [lib]
 proc-macro = true
diff --git a/storage/Cargo.toml b/storage/Cargo.toml
index 3f1f4a34a..2ddea0c08 100644
--- a/storage/Cargo.toml
+++ b/storage/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "storage"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [features]
 default = [ 'inmemory' ]
diff --git a/storage/core/Cargo.toml b/storage/core/Cargo.toml
index f959a02ec..95f5f9059 100644
--- a/storage/core/Cargo.toml
+++ b/storage/core/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "storage-core"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 
diff --git a/storage/core/src/adaptor/locking/mod.rs b/storage/core/src/adaptor/locking/mod.rs
index 55019701d..1497e3a6a 100644
--- a/storage/core/src/adaptor/locking/mod.rs
+++ b/storage/core/src/adaptor/locking/mod.rs
@@ -20,7 +20,7 @@ mod prefix_iter_rw;
 
 use crate::{
     adaptor::{Construct, CoreOps},
-    backend::{self, ReadOps, WriteOps},
+    backend::{self, PrefixIter, ReadOps, WriteOps},
     Data, DbDesc, DbMapCount, DbMapId, DbMapsData,
 };
 
@@ -31,13 +31,19 @@ use utils::{const_value::ConstValue, sync};
 pub struct TxRo<'tx, T>(sync::RwLockReadGuard<'tx, T>);
 
 impl<'tx, T: ReadOps> ReadOps for TxRo<'tx, T> {
-    type PrefixIter<'i> = T::PrefixIter<'i> where Self: 'i;
-
     fn get(&self, map_id: DbMapId, key: &[u8]) -> crate::Result<Option<Cow<[u8]>>> {
         self.0.get(map_id, key)
     }
+}
+
+impl<'tx, 'i, T: PrefixIter<'i>> PrefixIter<'i> for TxRo<'tx, T> {
+    type Iterator = T::Iterator;
 
-    fn prefix_iter(&self, map_id: DbMapId, prefix: Data) -> crate::Result<Self::PrefixIter<'_>> {
+    fn prefix_iter<'m: 'i>(
+        &'m self,
+        map_id: DbMapId,
+        prefix: Data,
+    ) -> crate::Result<Self::Iterator> {
         self.0.prefix_iter(map_id, prefix)
     }
 }
@@ -61,16 +67,22 @@ impl<'tx, T> TxRw<'tx, T> {
 }
 
 impl<'tx, T: ReadOps> ReadOps for TxRw<'tx, T> {
-    type PrefixIter<'i> = prefix_iter_rw::Iter<'i, T> where Self: 'i;
-
     fn get(&self, map_id: DbMapId, key: &[u8]) -> crate::Result<Option<Cow<[u8]>>> {
         self.deltas[map_id].get(key).map_or_else(
             || self.db.get(map_id, key),
             |x| Ok(x.as_deref().map(|p| p.into())),
         )
     }
+}
 
-    fn prefix_iter(&self, map_id: DbMapId, prefix: Data) -> crate::Result<Self::PrefixIter<'_>> {
+impl<'tx, 'i, T: PrefixIter<'i>> PrefixIter<'i> for TxRw<'tx, T> {
+    type Iterator = prefix_iter_rw::Iter<'i, T>;
+
+    fn prefix_iter<'m: 'i>(
+        &'m self,
+        map_id: DbMapId,
+        prefix: Data,
+    ) -> crate::Result<Self::Iterator> {
         prefix_iter_rw::iter(self, map_id, prefix)
     }
 }
@@ -122,16 +134,18 @@ impl<T> utils::shallow_clone::ShallowClone for TransactionLockImpl<T> {
     }
 }
 
-impl<T: CoreOps + Sync + Send + 'static> backend::BackendImpl for TransactionLockImpl<T> {
-    type TxRo<'a> = TxRo<'a, T>;
-
-    type TxRw<'a> = TxRw<'a, T>;
+impl<'tx, T: 'tx + ReadOps> backend::TransactionalRo<'tx> for TransactionLockImpl<T> {
+    type TxRo = TxRo<'tx, T>;
 
-    fn transaction_ro(&self) -> crate::Result<Self::TxRo<'_>> {
+    fn transaction_ro<'st: 'tx>(&'st self) -> crate::Result<Self::TxRo> {
         Ok(TxRo(self.db.read().expect("lock to be alive")))
     }
+}
 
-    fn transaction_rw(&self, _size: Option<usize>) -> crate::Result<Self::TxRw<'_>> {
+impl<'tx, T: 'tx + ReadOps + WriteOps> backend::TransactionalRw<'tx> for TransactionLockImpl<T> {
+    type TxRw = TxRw<'tx, T>;
+
+    fn transaction_rw<'st: 'tx>(&'st self, _: Option<usize>) -> crate::Result<Self::TxRw> {
         Ok(TxRw {
             db: self.db.write().expect("lock to be alive"),
             deltas: DbMapsData::new(*self.num_maps, |_| BTreeMap::new()),
@@ -139,6 +153,8 @@ impl<T: CoreOps + Sync + Send + 'static> backend::BackendImpl for TransactionLoc
     }
 }
 
+impl<T: CoreOps + Sync + Send + 'static> backend::BackendImpl for TransactionLockImpl<T> {}
+
 /// Add lock-based transactions to given bare backend implementation.
 ///
 /// Given a type `T` implementing core database operations [CoreOps], this creates a full-featured
diff --git a/storage/core/src/adaptor/locking/prefix_iter_rw.rs b/storage/core/src/adaptor/locking/prefix_iter_rw.rs
index 8b1118761..04f0a5d41 100644
--- a/storage/core/src/adaptor/locking/prefix_iter_rw.rs
+++ b/storage/core/src/adaptor/locking/prefix_iter_rw.rs
@@ -15,9 +15,7 @@
 
 //! Internal functions and types used in the implementation of prefix iterator for RW transactions
 
-use crate::backend::ReadOps;
-
-use super::{Data, DbMapId, TxRw};
+use super::{Data, DbMapId, PrefixIter, TxRw};
 use itertools::EitherOrBoth;
 
 // The prefix iterator type for mutable transaction is a fairly complicated type. Here, we
@@ -26,7 +24,7 @@ type DataPair = (Data, Data);
 type DataPairRef<'a> = (&'a [u8], &'a Option<Data>);
 type KeyCompareFn = fn(&DataPair, &DataPairRef<'_>) -> std::cmp::Ordering;
 type ItemMergeFn = fn(itertools::EitherOrBoth<DataPair, DataPairRef<'_>>) -> Option<DataPair>;
-type DbIter<'i, T> = <T as ReadOps>::PrefixIter<'i>;
+type DbIter<'i, T> = <T as PrefixIter<'i>>::Iterator;
 type DeltaIter<'i> = crate::util::PrefixIter<'i, Option<Data>>;
 type JoinIter<'i, T> = itertools::MergeJoinBy<DbIter<'i, T>, DeltaIter<'i>, KeyCompareFn>;
 pub type Iter<'i, T> = std::iter::FilterMap<JoinIter<'i, T>, ItemMergeFn>;
@@ -50,7 +48,7 @@ fn merger(item: EitherOrBoth<DataPair, DataPairRef<'_>>) -> Option<(Data, Data)>
 }
 
 /// Create the iterator
-pub fn iter<'tx, 'i, 'm: 'i, T: ReadOps>(
+pub fn iter<'tx, 'i, 'm: 'i, T: PrefixIter<'i>>(
     tx: &'m TxRw<'tx, T>,
     map_id: DbMapId,
     prefix: Data,
diff --git a/storage/core/src/backend.rs b/storage/core/src/backend.rs
index 64082a4de..4cefe4531 100644
--- a/storage/core/src/backend.rs
+++ b/storage/core/src/backend.rs
@@ -21,18 +21,23 @@ use utils::shallow_clone::ShallowClone;
 
 pub use crate::{Data, DbDesc, DbMapId};
 
-/// Read-only database operations
-pub trait ReadOps {
-    /// The prefix iterator type
-    type PrefixIter<'i>: Iterator<Item = (Data, Data)> + 'i
-    where
-        Self: 'i;
+/// Types providing capability of iterating over keys with given prefix
+pub trait PrefixIter<'i> {
+    /// The iterator type
+    type Iterator: 'i + Iterator<Item = (Data, Data)>;
+
+    /// Get iterator over key-value pairs where the key has given prefix
+    fn prefix_iter<'m: 'i>(
+        &'m self,
+        map_id: DbMapId,
+        prefix: Data,
+    ) -> crate::Result<Self::Iterator>;
+}
 
+/// Read-only database operations
+pub trait ReadOps: for<'i> PrefixIter<'i> {
     /// Get value associated with given key.
     fn get(&self, map_id: DbMapId, key: &[u8]) -> crate::Result<Option<Cow<[u8]>>>;
-
-    /// Get iterator over key-value pairs where the key has given prefix
-    fn prefix_iter(&self, map_id: DbMapId, prefix: Data) -> crate::Result<Self::PrefixIter<'_>>;
 }
 
 /// Write database operation
@@ -57,19 +62,32 @@ pub trait TxRw: ReadOps + WriteOps {
     fn commit(self) -> crate::Result<()>;
 }
 
-/// Storage backend internal implementation type
-pub trait BackendImpl: 'static + Send + Sync + ShallowClone {
+/// Read-only transactional interface to the storage
+pub trait TransactionalRo<'tx> {
     /// Read-only transaction internal type
-    type TxRo<'a>: TxRo + 'a;
-
-    /// Start a read-write transaction
-    type TxRw<'a>: TxRw + 'a;
+    type TxRo: TxRo + 'tx;
 
     /// Start a read-only transaction
-    fn transaction_ro(&self) -> crate::Result<Self::TxRo<'_>>;
+    fn transaction_ro<'st: 'tx>(&'st self) -> crate::Result<Self::TxRo>;
+}
+
+/// Read-write transactional interface to the storage
+pub trait TransactionalRw<'tx> {
+    /// Start a read-write transaction
+    type TxRw: TxRw + 'tx;
 
     /// Start a read-write transaction
-    fn transaction_rw(&self, size: Option<usize>) -> crate::Result<Self::TxRw<'_>>;
+    fn transaction_rw<'st: 'tx>(&'st self, size: Option<usize>) -> crate::Result<Self::TxRw>;
+}
+
+/// Storage backend internal implementation type
+pub trait BackendImpl
+where
+    Self: 'static + Send + Sync,
+    Self: for<'tx> TransactionalRo<'tx>,
+    Self: for<'tx> TransactionalRw<'tx>,
+    Self: ShallowClone,
+{
 }
 
 /// Storage backend type. Used to set up storage.
diff --git a/storage/inmemory/Cargo.toml b/storage/inmemory/Cargo.toml
index ffd949890..cf7490a6a 100644
--- a/storage/inmemory/Cargo.toml
+++ b/storage/inmemory/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "storage-inmemory"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 
diff --git a/storage/inmemory/src/lib.rs b/storage/inmemory/src/lib.rs
index 265923db6..547f6b5c0 100644
--- a/storage/inmemory/src/lib.rs
+++ b/storage/inmemory/src/lib.rs
@@ -32,17 +32,19 @@ impl<'i> Iterator for PrefixIter<'i> {
 pub struct StorageMaps(DbMapsData<Map>);
 
 impl backend::ReadOps for StorageMaps {
-    type PrefixIter<'i> = PrefixIter<'i>;
-
     fn get(&self, map_id: DbMapId, key: &[u8]) -> storage_core::Result<Option<Cow<[u8]>>> {
         Ok(self.0[map_id].get(key).map(|p| p.into()))
     }
+}
+
+impl<'i> backend::PrefixIter<'i> for StorageMaps {
+    type Iterator = PrefixIter<'i>;
 
-    fn prefix_iter(
-        &self,
+    fn prefix_iter<'m: 'i>(
+        &'m self,
         map_id: DbMapId,
         prefix: Data,
-    ) -> storage_core::Result<Self::PrefixIter<'_>> {
+    ) -> storage_core::Result<Self::Iterator> {
         Ok(PrefixIter(util::PrefixIter::new(&self.0[map_id], prefix)))
     }
 }
diff --git a/storage/lmdb/Cargo.toml b/storage/lmdb/Cargo.toml
index f9e560105..6acf5552b 100644
--- a/storage/lmdb/Cargo.toml
+++ b/storage/lmdb/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "storage-lmdb"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 logging = { path = '../../logging' }
diff --git a/storage/lmdb/src/lib.rs b/storage/lmdb/src/lib.rs
index b9ba24546..2326b5848 100644
--- a/storage/lmdb/src/lib.rs
+++ b/storage/lmdb/src/lib.rs
@@ -24,7 +24,10 @@ use std::{borrow::Cow, path::PathBuf};
 use initial_map_size::InitialMapSize;
 use lmdb::Cursor;
 use resize_callback::MapResizeCallback;
-use storage_core::{backend, Data, DbDesc, DbMapDesc, DbMapId, DbMapsData};
+use storage_core::{
+    backend::{self, TransactionalRo, TransactionalRw},
+    Data, DbDesc, DbMapDesc, DbMapId, DbMapsData,
+};
 use utils::const_value::ConstValue;
 use utils::sync::Arc;
 
@@ -63,20 +66,14 @@ pub struct DbTx<'m, Tx> {
 type DbTxRo<'a> = DbTx<'a, lmdb::RoTransaction<'a>>;
 type DbTxRw<'a> = DbTx<'a, lmdb::RwTransaction<'a>>;
 
-impl<Tx: lmdb::Transaction> backend::ReadOps for DbTx<'_, Tx> {
-    type PrefixIter<'i> = PrefixIter<'i, lmdb::RoCursor<'i>> where Self: 'i;
+impl<'s, 'i, Tx: lmdb::Transaction> backend::PrefixIter<'i> for DbTx<'s, Tx> {
+    type Iterator = PrefixIter<'i, lmdb::RoCursor<'i>>;
 
-    fn get(&self, map_id: DbMapId, key: &[u8]) -> storage_core::Result<Option<Cow<[u8]>>> {
-        self.tx
-            .get(self.backend.dbs[map_id], &key)
-            .map_or_else(error::process_with_none, |x| Ok(Some(x.into())))
-    }
-
-    fn prefix_iter(
-        &self,
+    fn prefix_iter<'t: 'i>(
+        &'t self,
         map_id: DbMapId,
         prefix: Data,
-    ) -> storage_core::Result<Self::PrefixIter<'_>> {
+    ) -> storage_core::Result<Self::Iterator> {
         let cursor = self
             .tx
             .open_ro_cursor(self.backend.dbs[map_id])
@@ -90,6 +87,14 @@ impl<Tx: lmdb::Transaction> backend::ReadOps for DbTx<'_, Tx> {
     }
 }
 
+impl<Tx: lmdb::Transaction> backend::ReadOps for DbTx<'_, Tx> {
+    fn get(&self, map_id: DbMapId, key: &[u8]) -> storage_core::Result<Option<Cow<[u8]>>> {
+        self.tx
+            .get(self.backend.dbs[map_id], &key)
+            .map_or_else(error::process_with_none, |x| Ok(Some(x.into())))
+    }
+}
+
 impl backend::WriteOps for DbTx<'_, lmdb::RwTransaction<'_>> {
     fn put(&mut self, map_id: DbMapId, key: Data, val: Data) -> storage_core::Result<()> {
         let db = self.backend.dbs[map_id];
@@ -182,6 +187,26 @@ impl LmdbImpl {
     }
 }
 
+impl<'tx> TransactionalRo<'tx> for LmdbImpl {
+    type TxRo = DbTxRo<'tx>;
+
+    fn transaction_ro<'st: 'tx>(&'st self) -> storage_core::Result<Self::TxRo> {
+        self.start_transaction(lmdb::Environment::begin_ro_txn)
+    }
+}
+
+impl<'tx> TransactionalRw<'tx> for LmdbImpl {
+    type TxRw = DbTxRw<'tx>;
+
+    fn transaction_rw<'st: 'tx>(
+        &'st self,
+        size: Option<usize>,
+    ) -> storage_core::Result<Self::TxRw> {
+        self.resize_if_resize_scheduled();
+        self.start_transaction(|env| lmdb::Environment::begin_rw_txn(env, size))
+    }
+}
+
 impl utils::shallow_clone::ShallowClone for LmdbImpl {
     fn shallow_clone(&self) -> Self {
         Self {
@@ -191,20 +216,7 @@ impl utils::shallow_clone::ShallowClone for LmdbImpl {
         }
     }
 }
-impl backend::BackendImpl for LmdbImpl {
-    type TxRo<'a> = DbTxRo<'a>;
-
-    type TxRw<'a> = DbTxRw<'a>;
-
-    fn transaction_ro(&self) -> storage_core::Result<Self::TxRo<'_>> {
-        self.start_transaction(lmdb::Environment::begin_ro_txn)
-    }
-
-    fn transaction_rw(&self, size: Option<usize>) -> storage_core::Result<Self::TxRw<'_>> {
-        self.resize_if_resize_scheduled();
-        self.start_transaction(|env| lmdb::Environment::begin_rw_txn(env, size))
-    }
-}
+impl backend::BackendImpl for LmdbImpl {}
 
 pub struct Lmdb {
     path: PathBuf,
diff --git a/storage/sqlite/Cargo.toml b/storage/sqlite/Cargo.toml
index 8a43d6c62..cf1757c5d 100644
--- a/storage/sqlite/Cargo.toml
+++ b/storage/sqlite/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "storage-sqlite"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 logging = { path = '../../logging' }
diff --git a/storage/sqlite/src/lib.rs b/storage/sqlite/src/lib.rs
index 4d687b09e..bfa19da7a 100644
--- a/storage/sqlite/src/lib.rs
+++ b/storage/sqlite/src/lib.rs
@@ -26,7 +26,10 @@ use std::sync::{Mutex, MutexGuard};
 
 use crate::queries::SqliteQueries;
 use error::process_sqlite_error;
-use storage_core::{backend, Data, DbDesc, DbMapId};
+use storage_core::{
+    backend::{self, TransactionalRo, TransactionalRw},
+    Data, DbDesc, DbMapId,
+};
 use utils::shallow_clone::ShallowClone;
 use utils::sync::Arc;
 
@@ -97,29 +100,14 @@ impl Drop for DbTx<'_> {
     }
 }
 
-impl backend::ReadOps for DbTx<'_> {
-    type PrefixIter<'i> = PrefixIter where Self: 'i;
-
-    fn get(&self, map_id: DbMapId, key: &[u8]) -> storage_core::Result<Option<Cow<[u8]>>> {
-        let mut stmt = self
-            .connection
-            .prepare_cached(self.queries[map_id].get_query.as_str())
-            .map_err(process_sqlite_error)?;
+impl<'s, 'i> backend::PrefixIter<'i> for DbTx<'s> {
+    type Iterator = PrefixIter;
 
-        let params = (key,);
-        let res = stmt
-            .query_row(params, |row| row.get::<usize, Vec<u8>>(0))
-            .optional()
-            .map_err(process_sqlite_error)?;
-        let res = res.map(|v| v.into());
-        Ok(res)
-    }
-
-    fn prefix_iter(
-        &self,
+    fn prefix_iter<'t: 'i>(
+        &'t self,
         map_id: DbMapId,
         prefix: Data,
-    ) -> storage_core::Result<Self::PrefixIter<'_>> {
+    ) -> storage_core::Result<Self::Iterator> {
         // TODO check if prefix.is_empty()
         // TODO Perform the filtering in the SQL query itself
         let mut stmt = self
@@ -144,6 +132,23 @@ impl backend::ReadOps for DbTx<'_> {
     }
 }
 
+impl backend::ReadOps for DbTx<'_> {
+    fn get(&self, map_id: DbMapId, key: &[u8]) -> storage_core::Result<Option<Cow<[u8]>>> {
+        let mut stmt = self
+            .connection
+            .prepare_cached(self.queries[map_id].get_query.as_str())
+            .map_err(process_sqlite_error)?;
+
+        let params = (key,);
+        let res = stmt
+            .query_row(params, |row| row.get::<usize, Vec<u8>>(0))
+            .optional()
+            .map_err(process_sqlite_error)?;
+        let res = res.map(|v| v.into());
+        Ok(res)
+    }
+}
+
 impl backend::WriteOps for DbTx<'_> {
     fn put(&mut self, map_id: DbMapId, key: Data, val: Data) -> storage_core::Result<()> {
         let mut stmt = self
@@ -197,26 +202,33 @@ impl SqliteImpl {
     }
 }
 
-impl ShallowClone for SqliteImpl {
-    fn shallow_clone(&self) -> Self {
-        Self(self.0.shallow_clone())
+impl<'tx> TransactionalRo<'tx> for SqliteImpl {
+    type TxRo = DbTx<'tx>;
+
+    fn transaction_ro<'st: 'tx>(&'st self) -> storage_core::Result<Self::TxRo> {
+        self.start_transaction()
     }
 }
 
-impl backend::BackendImpl for SqliteImpl {
-    type TxRo<'a> = DbTx<'a>;
-
-    type TxRw<'a> = DbTx<'a>;
+impl<'tx> TransactionalRw<'tx> for SqliteImpl {
+    type TxRw = DbTx<'tx>;
 
-    fn transaction_ro(&self) -> storage_core::Result<Self::TxRo<'_>> {
+    fn transaction_rw<'st: 'tx>(
+        &'st self,
+        _size: Option<usize>,
+    ) -> storage_core::Result<Self::TxRw> {
         self.start_transaction()
     }
+}
 
-    fn transaction_rw(&self, _size: Option<usize>) -> storage_core::Result<Self::TxRw<'_>> {
-        self.start_transaction()
+impl ShallowClone for SqliteImpl {
+    fn shallow_clone(&self) -> Self {
+        Self(self.0.shallow_clone())
     }
 }
 
+impl backend::BackendImpl for SqliteImpl {}
+
 #[derive(Eq, PartialEq, Clone, Debug)]
 enum SqliteStorageMode {
     InMemory,
diff --git a/storage/src/database/internal.rs b/storage/src/database/internal.rs
index 52989a11d..84282b117 100644
--- a/storage/src/database/internal.rs
+++ b/storage/src/database/internal.rs
@@ -20,7 +20,7 @@ use std::borrow::Cow;
 use crate::schema;
 use serialization::{encoded::Encoded, EncodeLike};
 use storage_core::{
-    backend::{self, ReadOps},
+    backend::{self, PrefixIter, ReadOps},
     Backend, DbMapId,
 };
 
@@ -31,11 +31,11 @@ pub trait TxImpl {
 }
 
 impl<'tx, B: Backend, Sch> TxImpl for super::TransactionRo<'tx, B, Sch> {
-    type Impl = <B::Impl as backend::BackendImpl>::TxRo<'tx>;
+    type Impl = <B::Impl as backend::TransactionalRo<'tx>>::TxRo;
 }
 
 impl<'tx, B: Backend, Sch> TxImpl for super::TransactionRw<'tx, B, Sch> {
-    type Impl = <B::Impl as backend::BackendImpl>::TxRw<'tx>;
+    type Impl = <B::Impl as backend::TransactionalRw<'tx>>::TxRw;
 }
 
 /// Get a value from the database backend as a SCALE-encoded object
@@ -59,11 +59,11 @@ impl<DbMap: schema::DbMap, I: Iterator<Item = (DbMap::Key, Encoded<Vec<u8>, DbMa
 {
 }
 
-pub fn prefix_iter<DbMap: schema::DbMap, Tx: ReadOps>(
-    dbtx: &Tx,
+pub fn prefix_iter<'tx, DbMap: schema::DbMap, Tx: PrefixIter<'tx>>(
+    dbtx: &'tx Tx,
     map_id: DbMapId,
     prefix: Vec<u8>,
-) -> crate::Result<impl '_ + EntryIterator<DbMap>> {
+) -> crate::Result<impl 'tx + EntryIterator<DbMap>> {
     dbtx.prefix_iter(map_id, prefix).map(|iter| {
         iter.map(|(k, v)| {
             (
diff --git a/storage/src/database/mod.rs b/storage/src/database/mod.rs
index 42a08b4bf..c36eec459 100644
--- a/storage/src/database/mod.rs
+++ b/storage/src/database/mod.rs
@@ -71,15 +71,18 @@ impl<B: Backend, Sch: Schema> Storage<B, Sch> {
     }
 
     /// Start a read-only transaction
-    pub fn transaction_ro(&self) -> crate::Result<TransactionRo<'_, B, Sch>> {
-        let dbtx = backend::BackendImpl::transaction_ro(&self.backend)?;
+    pub fn transaction_ro<'tx, 'st: 'tx>(&'st self) -> crate::Result<TransactionRo<'tx, B, Sch>> {
+        let dbtx = backend::TransactionalRo::transaction_ro(&self.backend)?;
         let _schema = std::marker::PhantomData;
         Ok(TransactionRo { dbtx, _schema })
     }
 
     /// Start a read-write transaction
-    pub fn transaction_rw(&self, size: Option<usize>) -> crate::Result<TransactionRw<'_, B, Sch>> {
-        let dbtx = backend::BackendImpl::transaction_rw(&self.backend, size)?;
+    pub fn transaction_rw<'tx, 'st: 'tx>(
+        &'st self,
+        size: Option<usize>,
+    ) -> crate::Result<TransactionRw<'tx, B, Sch>> {
+        let dbtx = backend::TransactionalRw::transaction_rw(&self.backend, size)?;
         let _schema = std::marker::PhantomData;
         Ok(TransactionRw { dbtx, _schema })
     }
diff --git a/storage/src/database/raw.rs b/storage/src/database/raw.rs
index 4bf36148e..babe6b01b 100644
--- a/storage/src/database/raw.rs
+++ b/storage/src/database/raw.rs
@@ -20,7 +20,7 @@ use crate::{
     Backend, Storage,
 };
 use std::collections::BTreeMap;
-use storage_core::backend::ReadOps;
+use storage_core::backend::PrefixIter;
 
 pub use storage_core::Data;
 
diff --git a/subsystem/Cargo.toml b/subsystem/Cargo.toml
index f740d72cd..77372acaf 100644
--- a/subsystem/Cargo.toml
+++ b/subsystem/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "subsystem"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [features]
 default = [ "time" ]
diff --git a/utils/Cargo.toml b/utils/Cargo.toml
index f16dc830b..4368cf703 100644
--- a/utils/Cargo.toml
+++ b/utils/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "utils"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 logging = {path = '../logging'}
diff --git a/utils/typename-derive/Cargo.toml b/utils/typename-derive/Cargo.toml
index d25e084d3..c2912104b 100644
--- a/utils/typename-derive/Cargo.toml
+++ b/utils/typename-derive/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "typename-derive"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [lib]
 proc-macro = true
diff --git a/utils/typename/Cargo.toml b/utils/typename/Cargo.toml
index d99675e92..9f4c9e36d 100644
--- a/utils/typename/Cargo.toml
+++ b/utils/typename/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "typename"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
-typename-derive = { path = "../typename-derive" }
+typename-derive = { path = "../typename-derive" }
\ No newline at end of file
diff --git a/utxo/Cargo.toml b/utxo/Cargo.toml
index afa619fd7..534a74679 100644
--- a/utxo/Cargo.toml
+++ b/utxo/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "utxo"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml
index 06582c32f..906348409 100644
--- a/wallet/Cargo.toml
+++ b/wallet/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "wallet"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/wallet/storage/Cargo.toml b/wallet/storage/Cargo.toml
index 5661edea7..26d3ab801 100644
--- a/wallet/storage/Cargo.toml
+++ b/wallet/storage/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "wallet-storage"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
@@ -19,4 +18,4 @@ test-utils = {path = '../../test-utils'}
 utils = { path = '../../utils' }
 crypto = { path = '../../crypto' }
 
-rstest = "0.16"
+rstest = "0.16"
\ No newline at end of file


Test patch:
diff --git a/chainstate/test-framework/Cargo.toml b/chainstate/test-framework/Cargo.toml
index f9419959a..197468a59 100644
--- a/chainstate/test-framework/Cargo.toml
+++ b/chainstate/test-framework/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "chainstate-test-framework"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/chainstate/test-suite/Cargo.toml b/chainstate/test-suite/Cargo.toml
index 66ce7ac6b..95715736f 100644
--- a/chainstate/test-suite/Cargo.toml
+++ b/chainstate/test-suite/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "chainstate-test-suite"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/chainstate/test-suite/src/tests/chainstate_accounting_storage_tests.rs b/chainstate/test-suite/src/tests/chainstate_accounting_storage_tests.rs
index cf92e9dce..a901b37eb 100644
--- a/chainstate/test-suite/src/tests/chainstate_accounting_storage_tests.rs
+++ b/chainstate/test-suite/src/tests/chainstate_accounting_storage_tests.rs
@@ -31,13 +31,14 @@ use common::{
 };
 use crypto::{
     key::{KeyKind, PrivateKey, PublicKey},
+    random::CryptoRng,
     vrf::{VRFKeyKind, VRFPrivateKey},
 };
 use pos_accounting::PoolData;
 use utxo::UtxosStorageRead;
 
 fn make_tx_with_stake_pool_from_genesis(
-    rng: &mut impl Rng,
+    rng: &mut (impl Rng + CryptoRng),
     tf: &mut TestFramework,
     amount_to_stake: Amount,
     pub_key: &PublicKey,
@@ -47,7 +48,7 @@ fn make_tx_with_stake_pool_from_genesis(
 }
 
 fn make_tx_with_stake_pool_from_tx(
-    rng: &mut impl Rng,
+    rng: &mut (impl Rng + CryptoRng),
     tx_id: Id<Transaction>,
     amount_to_stake: Amount,
     pub_key: &PublicKey,
@@ -57,12 +58,12 @@ fn make_tx_with_stake_pool_from_tx(
 }
 
 fn make_tx_with_stake_pool(
-    rng: &mut impl Rng,
+    rng: &mut (impl Rng + CryptoRng),
     outpoint_id: OutPointSourceId,
     amount_to_stake: Amount,
     pub_key: &PublicKey,
 ) -> (SignedTransaction, PoolId) {
-    let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+    let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(rng, VRFKeyKind::Schnorrkel);
     let tx_output = TxOutput::new(
         OutputValue::Coin(amount_to_stake),
         OutputPurpose::StakePool(Box::new(StakePoolData::new(
diff --git a/chainstate/test-suite/src/tests/pos_accounting_reorg.rs b/chainstate/test-suite/src/tests/pos_accounting_reorg.rs
index aef26fe08..9ab079bc1 100644
--- a/chainstate/test-suite/src/tests/pos_accounting_reorg.rs
+++ b/chainstate/test-suite/src/tests/pos_accounting_reorg.rs
@@ -72,7 +72,7 @@ fn stake_pool_reorg(#[case] seed: Seed) {
 
             // prepare tx_a
             let (_, pub_key_a) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-            let (_, vrf_pub_key_a) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+            let (_, vrf_pub_key_a) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
             let tx_a = TransactionBuilder::new()
                 .add_input(
                     TxInput::new(OutPointSourceId::BlockReward(genesis_id.into()), 0),
@@ -109,7 +109,7 @@ fn stake_pool_reorg(#[case] seed: Seed) {
 
             // prepare tx_c
             let (_, pub_key_c) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-            let (_, vrf_pub_key_c) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+            let (_, vrf_pub_key_c) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
             let tx_c = TransactionBuilder::new()
                 .add_input(
                     TxInput::new(
diff --git a/chainstate/test-suite/src/tests/pos_processing_tests.rs b/chainstate/test-suite/src/tests/pos_processing_tests.rs
index 7b9c7c1ca..8abc74cfa 100644
--- a/chainstate/test-suite/src/tests/pos_processing_tests.rs
+++ b/chainstate/test-suite/src/tests/pos_processing_tests.rs
@@ -51,7 +51,7 @@ fn create_chain_with_stake_pool(
 ) -> (OutPoint, PoolId, VRFPrivateKey) {
     let genesis_id = tf.genesis().get_id();
     let (_, pub_key) = PrivateKey::new_from_rng(rng, KeyKind::RistrettoSchnorr);
-    let (vrf_sk, vrf_pk) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+    let (vrf_sk, vrf_pk) = VRFPrivateKey::new_from_rng(rng, VRFKeyKind::Schnorrkel);
     let tx = TransactionBuilder::new()
         .add_input(
             TxInput::new(OutPointSourceId::BlockReward(genesis_id.into()), 0),
@@ -167,7 +167,7 @@ fn pos_invalid_kernel_input(#[case] seed: Seed) {
     let mut tf = TestFramework::builder(&mut rng).with_chain_config(chain_config).build();
 
     let genesis_id = tf.genesis().get_id();
-    let (vrf_sk, _) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+    let (vrf_sk, _) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
     let pool_id = pos_accounting::make_pool_id(&OutPoint::new(
         OutPointSourceId::BlockReward(genesis_id.into()),
         0,
@@ -320,7 +320,7 @@ fn pos_invalid_vrf(#[case] seed: Seed) {
 
     {
         // invalid vrf private key
-        let (vrf_sk_2, _) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (vrf_sk_2, _) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
         let vrf_data = vrf_sk_2.produce_vrf_data(valid_vrf_transcript.into());
         let pos_data = PoSData::new(
             vec![stake_pool_outpoint.clone().into()],
diff --git a/chainstate/test-suite/src/tests/processing_tests.rs b/chainstate/test-suite/src/tests/processing_tests.rs
index 9d7703b55..35c477b4f 100644
--- a/chainstate/test-suite/src/tests/processing_tests.rs
+++ b/chainstate/test-suite/src/tests/processing_tests.rs
@@ -203,7 +203,7 @@ fn invalid_block_reward_types(#[case] seed: Seed) {
 
         // Case 7: reward is a stake lock
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
         let block = tf
             .make_block_builder()
             .with_reward(vec![TxOutput::new(
diff --git a/chainstate/test-suite/src/tests/stake_pool_tests.rs b/chainstate/test-suite/src/tests/stake_pool_tests.rs
index edec80917..58d59ea06 100644
--- a/chainstate/test-suite/src/tests/stake_pool_tests.rs
+++ b/chainstate/test-suite/src/tests/stake_pool_tests.rs
@@ -41,7 +41,7 @@ fn stake_pool_basic(#[case] seed: Seed) {
         let mut tf = TestFramework::builder(&mut rng).build();
 
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         let tx = TransactionBuilder::new()
             .add_input(
@@ -81,7 +81,7 @@ fn stake_pool_and_spend_coin_same_tx(#[case] seed: Seed) {
         let mut tf = TestFramework::builder(&mut rng).build();
 
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         let tx = TransactionBuilder::new()
             .add_input(
@@ -125,7 +125,7 @@ fn stake_pool_and_issue_tokens_same_tx(#[case] seed: Seed) {
         let mut tf = TestFramework::builder(&mut rng).build();
 
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         let tx = TransactionBuilder::new()
             .add_input(
@@ -200,7 +200,7 @@ fn stake_pool_and_transfer_tokens_same_tx(#[case] seed: Seed) {
         let token_id = common::chain::tokens::token_id(tx0.transaction()).unwrap();
 
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         // stake pool with coin input and transfer tokens with token input
         let tx1 = TransactionBuilder::new()
@@ -284,7 +284,7 @@ fn stake_pool_with_tokens_as_input_value(#[case] seed: Seed) {
         let token_id = common::chain::tokens::token_id(tx0.transaction()).unwrap();
 
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         // use token input to stake pool with tokens
         let tx1 = TransactionBuilder::new()
@@ -330,7 +330,7 @@ fn stake_pool_twice(#[case] seed: Seed) {
         let mut tf = TestFramework::builder(&mut rng).build();
 
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         let tx = TransactionBuilder::new()
             .add_input(
@@ -397,7 +397,7 @@ fn stake_pool_overspend(#[case] seed: Seed) {
         let genesis_overspend_amount = (genesis_output_amount + Amount::from_atoms(1)).unwrap();
 
         let (_, pub_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::RistrettoSchnorr);
-        let (_, vrf_pub_key) = VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+        let (_, vrf_pub_key) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
 
         let tx = TransactionBuilder::new()
             .add_input(
diff --git a/p2p/backend-test-suite/Cargo.toml b/p2p/backend-test-suite/Cargo.toml
index 93c86a4b6..22c8e8927 100644
--- a/p2p/backend-test-suite/Cargo.toml
+++ b/p2p/backend-test-suite/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "p2p-backend-test-suite"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 common = { path = "../../common" }
diff --git a/p2p/p2p-test-utils/Cargo.toml b/p2p/p2p-test-utils/Cargo.toml
index acbbf0e12..6b9b73daa 100644
--- a/p2p/p2p-test-utils/Cargo.toml
+++ b/p2p/p2p-test-utils/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "p2p-test-utils"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 chainstate-storage = { path = "../../chainstate/storage" }
diff --git a/storage/backend-test-suite/Cargo.toml b/storage/backend-test-suite/Cargo.toml
index 26b04fe39..e34e4c55f 100644
--- a/storage/backend-test-suite/Cargo.toml
+++ b/storage/backend-test-suite/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "storage-backend-test-suite"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 [dependencies]
 storage-core = { path = "../core" }
diff --git a/storage/backend-test-suite/src/model.rs b/storage/backend-test-suite/src/model.rs
index b60756cea..c234935ce 100644
--- a/storage/backend-test-suite/src/model.rs
+++ b/storage/backend-test-suite/src/model.rs
@@ -79,8 +79,8 @@ impl Model {
     }
 
     /// New model obtained by dumping a database in a transaction. May contain uncommitted changes.
-    pub fn from_tx<Tx: backend::ReadOps>(tx: &Tx, map_id: DbMapId) -> Self {
-        Model(backend::ReadOps::prefix_iter(tx, map_id, Data::new()).unwrap().collect())
+    pub fn from_tx<Tx: for<'tx> backend::PrefixIter<'tx>>(tx: &Tx, map_id: DbMapId) -> Self {
+        Model(backend::PrefixIter::prefix_iter(tx, map_id, Data::new()).unwrap().collect())
     }
 
     /// Get the inner map
diff --git a/storage/backend-test-suite/src/prelude.rs b/storage/backend-test-suite/src/prelude.rs
index 8bed68b05..8fbd06346 100644
--- a/storage/backend-test-suite/src/prelude.rs
+++ b/storage/backend-test-suite/src/prelude.rs
@@ -16,7 +16,9 @@
 // Re-export a bunch of often used items
 pub use crate::model::{ApplyActions, Model, WriteAction};
 pub use storage_core::{
-    backend::{Backend, BackendImpl, Data, ReadOps, TxRo, TxRw, WriteOps},
+    backend::{
+        Backend, Data, PrefixIter, ReadOps, TransactionalRo, TransactionalRw, TxRo, TxRw, WriteOps,
+    },
     DbDesc, DbMapCount, DbMapDesc, DbMapId, DbMapsData,
 };
 pub use utils::{sync, thread};
diff --git a/storage/lmdb/src/resize_tests.rs b/storage/lmdb/src/resize_tests.rs
index 4d3ad0169..55346c82b 100644
--- a/storage/lmdb/src/resize_tests.rs
+++ b/storage/lmdb/src/resize_tests.rs
@@ -17,7 +17,10 @@ use std::{collections::BTreeMap, sync::Mutex};
 
 use memsize::MemSize;
 use rstest::rstest;
-use storage_core::backend::{Backend, BackendImpl, ReadOps, TxRw, WriteOps};
+use storage_core::{
+    backend::{ReadOps, TxRw, WriteOps},
+    Backend,
+};
 use tempdir::TempDir;
 use test_utils::random::make_seedable_rng;
 use test_utils::random::{CryptoRng, Rng, Seed};
diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml
index 2d9e9cfb5..8093aae82 100644
--- a/test-utils/Cargo.toml
+++ b/test-utils/Cargo.toml
@@ -1,9 +1,8 @@
 [package]
 name = "test-utils"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/test/Cargo.toml b/test/Cargo.toml
index e2efb32a2..4c8bb6872 100644
--- a/test/Cargo.toml
+++ b/test/Cargo.toml
@@ -1,10 +1,9 @@
 [package]
 name = "mintlayer-test"
-license.workspace = true
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
+version = "0.1.0"
+edition = "2021"
 homepage = "https://github.com/mintlayer/mintlayer-core/issues"
+license = "MIT"
 
 [dependencies]
 node = { path = "../node" }
diff --git a/utxo/src/tests/mod.rs b/utxo/src/tests/mod.rs
index 071d6ec49..fa92e4b78 100644
--- a/utxo/src/tests/mod.rs
+++ b/utxo/src/tests/mod.rs
@@ -658,7 +658,7 @@ fn check_pos_reward_spend_undo_spend(#[case] seed: Seed) {
     let inputs = vec![TxInput::new(outpoint.tx_id(), outpoint.output_index())];
     let outputs = create_tx_outputs(&mut rng, 1);
 
-    let (sk, _pk) = crypto::vrf::VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+    let (sk, _pk) = crypto::vrf::VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
     let vrf_data = sk.produce_vrf_data(TranscriptAssembler::new(b"abc").finalize().into());
     let pool_id = make_pool_id(&mut rng);
 
@@ -756,7 +756,7 @@ fn check_missing_reward_undo(#[case] seed: Seed) {
     let inputs = vec![TxInput::new(outpoint.tx_id(), outpoint.output_index())];
     let outputs = create_tx_outputs(&mut rng, 1);
 
-    let (sk, _pk) = crypto::vrf::VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+    let (sk, _pk) = crypto::vrf::VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
     let vrf_data = sk.produce_vrf_data(TranscriptAssembler::new(b"abc").finalize().into());
     let pool_id = make_pool_id(&mut rng);
 
@@ -810,7 +810,7 @@ fn check_burn_output_in_block_reward(#[case] seed: Seed) {
         OutputPurpose::Burn,
     )];
 
-    let (sk, _pk) = crypto::vrf::VRFPrivateKey::new(VRFKeyKind::Schnorrkel);
+    let (sk, _pk) = crypto::vrf::VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);
     let vrf_data = sk.produce_vrf_data(TranscriptAssembler::new(b"abc").finalize().into());
     let pool_id = make_pool_id(&mut rng);