From f6380d0d20edb5df2a5bf1350a6c72b15a964ef1 Mon Sep 17 00:00:00 2001 From: The CI Date: Fri, 6 Dec 2024 12:51:04 +0100 Subject: [PATCH] Improve the open_encrypted documentation --- heed/src/databases/encrypted_database.rs | 2 + heed/src/envs/encrypted_env.rs | 2 + heed/src/envs/env_open_options.rs | 57 ++++++++++++++++++++---- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/heed/src/databases/encrypted_database.rs b/heed/src/databases/encrypted_database.rs index 9450b746..7f8d5b57 100644 --- a/heed/src/databases/encrypted_database.rs +++ b/heed/src/databases/encrypted_database.rs @@ -6,6 +6,8 @@ use types::LazyDecode; use crate::envs::DefaultComparator; use crate::iteration_method::MoveOnCurrentKeyDuplicates; +#[allow(unused)] // for cargo auto doc links +use crate::mdb::ffi; use crate::mdb::lmdb_flags::DatabaseFlags; use crate::*; diff --git a/heed/src/envs/encrypted_env.rs b/heed/src/envs/encrypted_env.rs index cfadf764..bb30bbcc 100644 --- a/heed/src/envs/encrypted_env.rs +++ b/heed/src/envs/encrypted_env.rs @@ -10,6 +10,8 @@ use super::{Env, EnvClosingEvent, EnvInfo, FlagSetMode}; use crate::databases::{EncryptedDatabase, EncryptedDatabaseOpenOptions}; use crate::mdb::ffi::{self}; use crate::{CompactionOption, EnvFlags, Result, RoTxn, RwTxn, Unspecified}; +#[allow(unused)] // fro cargo auto doc links +use crate::{Database, EnvOpenOptions}; /// An environment handle constructed by using [`EnvOpenOptions::open_encrypted`]. #[derive(Clone)] diff --git a/heed/src/envs/env_open_options.rs b/heed/src/envs/env_open_options.rs index 406f9935..057afa46 100644 --- a/heed/src/envs/env_open_options.rs +++ b/heed/src/envs/env_open_options.rs @@ -160,12 +160,38 @@ impl EnvOpenOptions { ) } - /// Creates a blank new set of options ready for configuration and specifies that - /// the [`Env`] will be encrypted-at-rest using the `E` algorithm with the given `key`. + /// Open an encrypted-at-rest environment that will be located at the specified path. /// - /// You can find more compatible algorithms on [the RustCrypto/AEADs page](https://github.com/RustCrypto/AEADs#crates). + /// # Safety + /// LMDB is backed by a memory map [^1] which comes with some safety precautions. + /// + /// Memory map constructors are marked `unsafe` because of the potential + /// for Undefined Behavior (UB) using the map if the underlying file is + /// subsequently modified, in or out of process. + /// + /// LMDB itself has a locking system that solves this problem, + /// but it will not save you from making mistakes yourself. + /// + /// These are some things to take note of: + /// + /// - Avoid long-lived transactions, they will cause the database to grow quickly [^2] + /// - Avoid aborting your process with an active transaction [^3] + /// - Do not use LMDB on remote filesystems, even between processes on the same host [^4] + /// - You must manage concurrent accesses yourself if using [`EnvFlags::NO_LOCK`] [^5] + /// - Anything that causes LMDB's lock file to be broken will cause synchronization issues and may introduce UB [^6] + /// + /// `heed` itself upholds some safety invariants, including but not limited to: + /// - Calling [`EnvOpenOptions::open`] twice in the same process, at the same time is OK [^7] + /// + /// For more details, it is highly recommended to read LMDB's official documentation. [^8] + /// + /// # Basic Example /// - /// Note that you cannot use any type of encryption algorithm as LMDB exposes a nonce of 16 bytes. + /// Creates and open a database. The [`Env`] is encrypted-at-rest using the `E` algorithm with the + /// given `key`. You can find more compatible algorithms on + /// [the RustCrypto/AEADs page](https://github.com/RustCrypto/AEADs#crates). + /// + /// Note that you cannot use **any** type of encryption algorithm as LMDB exposes a nonce of 16 bytes. /// Heed makes sure to truncate it if necessary. /// /// As an example, XChaCha20 requires a 20 bytes long nonce. However, XChaCha20 is used to protect @@ -173,8 +199,6 @@ impl EnvOpenOptions { /// weak RNGs. There is no need to use this kind of algorithm in LMDB since LMDB nonces aren't /// random and are guaranteed to be unique. /// - /// ## Basic Example - /// /// ``` /// use std::fs; /// use std::path::Path; @@ -217,7 +241,14 @@ impl EnvOpenOptions { /// # Ok(()) } /// ``` /// - /// ## Example Showing limitations + /// # Example Showing limitations + /// + /// At the end of this example file you can see that we can not longer use the `val1` + /// variable as we performed a read in the database just after fetching it and keeping + /// a reference to it. + /// + /// That's the main limitation of LMDB with the encryption-at-rest feature: entries cannot + /// be kept for too long as they are kept in a cycling buffer when decrypting them on the fly. /// /// ```compile_fail,E0499 /// use std::fs; @@ -261,10 +292,20 @@ impl EnvOpenOptions { /// let val1 = db.get(&mut rtxn, key1)?; /// let val2 = db.get(&mut rtxn, key2)?; /// - /// // This example won't compile because val1 cannot be used for too long. + /// // This example won't compile because val1 cannot be used + /// // after we performed another read in the database (val2). /// let _force_keep = val1; /// # Ok(()) } /// ``` + /// + /// [^1]: + /// [^2]: + /// [^3]: + /// [^4]: + /// [^5]: + /// [^6]: + /// [^7]: + /// [^8]: #[cfg(master3)] pub unsafe fn open_encrypted(&self, key: Key, path: P) -> Result where