From 55c744512d005a4b82f1090cb8c73f9142980689 Mon Sep 17 00:00:00 2001
From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com>
Date: Thu, 23 May 2024 02:03:09 +0100
Subject: [PATCH 01/10] fix doc

---
 p2p/cuprate-p2p/src/lib.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/p2p/cuprate-p2p/src/lib.rs b/p2p/cuprate-p2p/src/lib.rs
index b694bc4c..20a35819 100644
--- a/p2p/cuprate-p2p/src/lib.rs
+++ b/p2p/cuprate-p2p/src/lib.rs
@@ -1,6 +1,6 @@
 //! Cuprate's P2P Crate.
 //!
-//! This crate contains a [`ClientPool`](client_pool::ClientPool) which holds connected peers on a single [`NetworkZone`](monero_p2p::NetworkZone).
+//! This crate contains a [`ClientPool`](client_pool::ClientPool) which holds connected peers on a single [`NetworkZone`].
 //!
 //! This crate also contains the different routing methods that control how messages should be sent, i.e. broadcast to all,
 //! or send to a single peer.

From 4876e159e7ba4714b426ec92bdb5e904270058f6 Mon Sep 17 00:00:00 2001
From: hinto-janai <hinto.janai@protonmail.com>
Date: Tue, 28 May 2024 21:18:30 -0400
Subject: [PATCH 02/10] repo: add skeleton directories, fix labels (#139)

* `database/` -> `storage/`, create skeleton `storage/` crates

* add skeleton root directories

* books: add skeleton

* ci: fix labeler.yml

* fix CONTRIBUTING.md

* fix workspace Cargo.toml

* fix `storage/`

* rename helper fs fn, `cuprate_database` -> `cuprate_blockchain`

* fix Cargo.toml

* cuprate-blockchain: revert find-and-replace

Since it has to be ported to the book anyway, there's not much
reason to update this and create review diffs.

* labeler.yml: remove `A-docs` from `books/` changes

Although books are documentation,
the `A-books` label already exists for this
---
 .github/labeler.yml                           | 38 +++++++++-
 .github/workflows/ci.yml                      |  2 +-
 CONTRIBUTING.md                               |  4 +-
 Cargo.lock                                    | 74 ++++++++++---------
 Cargo.toml                                    |  4 +-
 benches/README.md                             |  1 +
 binaries/README.md                            |  1 +
 books/README.md                               |  1 +
 books/architecture/README.md                  |  1 +
 books/protocol/README.md                      |  1 +
 helper/src/fs.rs                              | 40 +++++-----
 rpc/README.md                                 |  1 +
 storage/README.md                             |  5 ++
 .../cuprate-blockchain}/Cargo.toml            | 20 ++---
 .../cuprate-blockchain}/README.md             |  6 +-
 .../src/backend/heed/database.rs              |  0
 .../src/backend/heed/env.rs                   |  2 +-
 .../src/backend/heed/error.rs                 |  4 +-
 .../src/backend/heed/mod.rs                   |  0
 .../src/backend/heed/storable.rs              |  4 +-
 .../src/backend/heed/transaction.rs           |  0
 .../src/backend/heed/types.rs                 |  0
 .../cuprate-blockchain}/src/backend/mod.rs    |  0
 .../src/backend/redb/database.rs              |  0
 .../src/backend/redb/env.rs                   |  2 +-
 .../src/backend/redb/error.rs                 |  2 +-
 .../src/backend/redb/mod.rs                   |  0
 .../src/backend/redb/storable.rs              |  4 +-
 .../src/backend/redb/transaction.rs           |  0
 .../src/backend/redb/types.rs                 |  0
 .../cuprate-blockchain}/src/backend/tests.rs  |  2 +-
 .../cuprate-blockchain}/src/config/backend.rs |  2 +-
 .../cuprate-blockchain}/src/config/config.rs  | 20 ++---
 .../cuprate-blockchain}/src/config/mod.rs     |  4 +-
 .../src/config/reader_threads.rs              |  6 +-
 .../src/config/sync_mode.rs                   |  0
 .../cuprate-blockchain}/src/constants.rs      |  4 +-
 .../cuprate-blockchain}/src/database.rs       |  0
 .../cuprate-blockchain}/src/env.rs            |  0
 .../cuprate-blockchain}/src/error.rs          |  2 +-
 .../cuprate-blockchain}/src/free.rs           |  0
 .../cuprate-blockchain}/src/key.rs            |  2 +-
 .../cuprate-blockchain}/src/lib.rs            | 10 +--
 .../cuprate-blockchain}/src/ops/block.rs      |  0
 .../cuprate-blockchain}/src/ops/blockchain.rs |  0
 .../cuprate-blockchain}/src/ops/key_image.rs  |  0
 .../cuprate-blockchain}/src/ops/macros.rs     |  0
 .../cuprate-blockchain}/src/ops/mod.rs        |  2 +-
 .../cuprate-blockchain}/src/ops/output.rs     |  0
 .../cuprate-blockchain}/src/ops/property.rs   |  4 +-
 .../cuprate-blockchain}/src/ops/tx.rs         |  0
 .../cuprate-blockchain}/src/resize.rs         | 16 ++--
 .../cuprate-blockchain}/src/service/free.rs   |  2 +-
 .../cuprate-blockchain}/src/service/mod.rs    |  4 +-
 .../cuprate-blockchain}/src/service/read.rs   |  0
 .../cuprate-blockchain}/src/service/tests.rs  |  0
 .../cuprate-blockchain}/src/service/types.rs  |  0
 .../cuprate-blockchain}/src/service/write.rs  |  0
 .../cuprate-blockchain}/src/storable.rs       | 10 +--
 .../cuprate-blockchain}/src/table.rs          |  0
 .../cuprate-blockchain}/src/tables.rs         |  4 +-
 .../cuprate-blockchain}/src/tests.rs          |  2 +-
 .../cuprate-blockchain}/src/transaction.rs    |  0
 .../cuprate-blockchain}/src/types.rs          | 20 ++---
 .../src/unsafe_sendable.rs                    |  0
 storage/cuprate-txpool/Cargo.toml             |  6 ++
 storage/cuprate-txpool/src/lib.rs             |  1 +
 storage/database/Cargo.toml                   |  6 ++
 storage/database/src/lib.rs                   |  1 +
 zmq/README.md                                 |  1 +
 70 files changed, 209 insertions(+), 139 deletions(-)
 create mode 100644 benches/README.md
 create mode 100644 binaries/README.md
 create mode 100644 books/README.md
 create mode 100644 books/architecture/README.md
 create mode 100644 books/protocol/README.md
 create mode 100644 rpc/README.md
 create mode 100644 storage/README.md
 rename {database => storage/cuprate-blockchain}/Cargo.toml (78%)
 rename {database => storage/cuprate-blockchain}/README.md (99%)
 rename {database => storage/cuprate-blockchain}/src/backend/heed/database.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/heed/env.rs (99%)
 rename {database => storage/cuprate-blockchain}/src/backend/heed/error.rs (98%)
 rename {database => storage/cuprate-blockchain}/src/backend/heed/mod.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/heed/storable.rs (96%)
 rename {database => storage/cuprate-blockchain}/src/backend/heed/transaction.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/heed/types.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/mod.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/redb/database.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/redb/env.rs (99%)
 rename {database => storage/cuprate-blockchain}/src/backend/redb/error.rs (98%)
 rename {database => storage/cuprate-blockchain}/src/backend/redb/mod.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/redb/storable.rs (98%)
 rename {database => storage/cuprate-blockchain}/src/backend/redb/transaction.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/redb/types.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/backend/tests.rs (99%)
 rename {database => storage/cuprate-blockchain}/src/config/backend.rs (94%)
 rename {database => storage/cuprate-blockchain}/src/config/config.rs (91%)
 rename {database => storage/cuprate-blockchain}/src/config/mod.rs (92%)
 rename {database => storage/cuprate-blockchain}/src/config/reader_threads.rs (97%)
 rename {database => storage/cuprate-blockchain}/src/config/sync_mode.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/constants.rs (95%)
 rename {database => storage/cuprate-blockchain}/src/database.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/env.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/error.rs (98%)
 rename {database => storage/cuprate-blockchain}/src/free.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/key.rs (97%)
 rename {database => storage/cuprate-blockchain}/src/lib.rs (97%)
 rename {database => storage/cuprate-blockchain}/src/ops/block.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/ops/blockchain.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/ops/key_image.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/ops/macros.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/ops/mod.rs (99%)
 rename {database => storage/cuprate-blockchain}/src/ops/output.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/ops/property.rs (87%)
 rename {database => storage/cuprate-blockchain}/src/ops/tx.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/resize.rs (96%)
 rename {database => storage/cuprate-blockchain}/src/service/free.rs (94%)
 rename {database => storage/cuprate-blockchain}/src/service/mod.rs (96%)
 rename {database => storage/cuprate-blockchain}/src/service/read.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/service/tests.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/service/types.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/service/write.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/storable.rs (97%)
 rename {database => storage/cuprate-blockchain}/src/table.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/tables.rs (99%)
 rename {database => storage/cuprate-blockchain}/src/tests.rs (98%)
 rename {database => storage/cuprate-blockchain}/src/transaction.rs (100%)
 rename {database => storage/cuprate-blockchain}/src/types.rs (96%)
 rename {database => storage/cuprate-blockchain}/src/unsafe_sendable.rs (100%)
 create mode 100644 storage/cuprate-txpool/Cargo.toml
 create mode 100644 storage/cuprate-txpool/src/lib.rs
 create mode 100644 storage/database/Cargo.toml
 create mode 100644 storage/database/src/lib.rs
 create mode 100644 zmq/README.md

diff --git a/.github/labeler.yml b/.github/labeler.yml
index 1a71a240..6dea11cd 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -30,13 +30,31 @@ A-consensus: # This is the tag name
                                        # will cause the `github-actions` bot
                                        # to add the `A-consensus` tag.
 
+# Cuprate's books.
+A-books:
+- changed-files:
+  - any-glob-to-any-file: books/**
+
+A-book-architecture:
+- changed-files:
+  - any-glob-to-any-file: books/architecture/**
+
+A-book-protocol:
+- changed-files:
+  - any-glob-to-any-file: books/protocol/**
+
+# Crate (sub-)directories.
+A-binaries:
+- changed-files:
+  - any-glob-to-any-file: binaries/**
+
 A-cryptonight:
 - changed-files:
   - any-glob-to-any-file: cryptonight/**
 
-A-database:
+A-storage:
 - changed-files:
-  - any-glob-to-any-file: database/**
+  - any-glob-to-any-file: storage/**
 
 A-helper:
 - changed-files:
@@ -62,10 +80,24 @@ A-types:
 - changed-files:
   - any-glob-to-any-file: types/**
 
+A-rpc:
+- changed-files:
+  - any-glob-to-any-file: rpc/**
+
+A-zmq:
+- changed-files:
+  - any-glob-to-any-file: zmq/**
+
+# CI files.
 A-ci:
 - changed-files:
   - any-glob-to-any-file: .github/**
 
+# Misc
+A-benches:
+- changed-files:
+  - any-glob-to-any-file: benches/** # Benchmarks
+
 A-dependency:
 - changed-files:
   - any-glob-to-any-file: '**/Cargo.toml' # Any Cargo file in the entire repo
@@ -74,7 +106,9 @@ A-dependency:
 A-workspace:
 - changed-files:
   - any-glob-to-any-file: '*' # Any root file change
+  - any-glob-to-any-file: misc/**
 
 A-docs:
 - changed-files:
   - any-glob-to-any-file: '**/*.md' # Any file in the entire repo ending in `.md`
+  # `A-books` label is used for book documentation.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b45a5431..7cee92a7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -133,7 +133,7 @@ jobs:
     - name: Test
       run: |
         cargo test --all-features --workspace
-        cargo test --package cuprate-database --no-default-features --features redb --features service
+        cargo test --package cuprate-blockchain --no-default-features --features redb --features service
 
     # TODO: upload binaries with `actions/upload-artifact@v3`
     - name: Build
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 742ebaef..f27de2af 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -49,14 +49,13 @@ This section is primarily targeted at maintainers. Most contributors aren't able
 
 | Labels       | Description | Example |
 |--------------|-------------|---------|
-| [A-]         | The **area** of the project an issue relates to. | `A-database`, `A-rpc`, `A-docs`
+| [A-]         | The **area** of the project an issue relates to. | `A-storage`, `A-rpc`, `A-docs`
 | [C-]         | The **category** of an issue. | `C-cleanup`,  `C-optimization`
 | [D-]         | Issues for **diagnostics**. | `D-confusing`, `D-verbose`
 | [E-]         | The **experience** level necessary to fix an issue. | `E-easy`, `E-hard`
 | [I-]         | The **importance** of the issue. | `I-crash`, `I-memory`
 | [O-]         | The **operating system** or platform that the issue is specific to. | `O-windows`, `O-macos`, `O-linux`
 | [P-]         | The issue **priority**. These labels can be assigned by anyone that understand the issue and is able to prioritize it, and remove the [I-prioritize] label. | `P-high`, `P-low`
-| [wontfix]    | Indicates an issue will not be fixed. | |
 
 [A-]: https://github.com/Cuprate/cuprate/labels?q=A
 [C-]: https://github.com/Cuprate/cuprate/labels?q=C
@@ -65,4 +64,3 @@ This section is primarily targeted at maintainers. Most contributors aren't able
 [I-]: https://github.com/Cuprate/cuprate/labels?q=I
 [O-]: https://github.com/Cuprate/cuprate/labels?q=O
 [P-]: https://github.com/Cuprate/cuprate/labels?q=P
-[wontfix]: https://github.com/Cuprate/cuprate/labels?q=wontfix
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 6a081885..2855514f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -495,6 +495,39 @@ dependencies = [
  "thiserror",
 ]
 
+[[package]]
+name = "cuprate-blockchain"
+version = "0.0.0"
+dependencies = [
+ "bitflags 2.5.0",
+ "bytemuck",
+ "bytes",
+ "cfg-if",
+ "crossbeam",
+ "cuprate-helper",
+ "cuprate-test-utils",
+ "cuprate-types",
+ "curve25519-dalek",
+ "futures",
+ "heed",
+ "hex",
+ "hex-literal",
+ "monero-pruning",
+ "monero-serai",
+ "page_size",
+ "paste",
+ "pretty_assertions",
+ "rayon",
+ "redb",
+ "serde",
+ "tempfile",
+ "thiserror",
+ "thread_local",
+ "tokio",
+ "tokio-util",
+ "tower",
+]
+
 [[package]]
 name = "cuprate-consensus"
 version = "0.1.0"
@@ -528,39 +561,6 @@ dependencies = [
  "tracing-subscriber",
 ]
 
-[[package]]
-name = "cuprate-database"
-version = "0.0.0"
-dependencies = [
- "bitflags 2.5.0",
- "bytemuck",
- "bytes",
- "cfg-if",
- "crossbeam",
- "cuprate-helper",
- "cuprate-test-utils",
- "cuprate-types",
- "curve25519-dalek",
- "futures",
- "heed",
- "hex",
- "hex-literal",
- "monero-pruning",
- "monero-serai",
- "page_size",
- "paste",
- "pretty_assertions",
- "rayon",
- "redb",
- "serde",
- "tempfile",
- "thiserror",
- "thread_local",
- "tokio",
- "tokio-util",
- "tower",
-]
-
 [[package]]
 name = "cuprate-helper"
 version = "0.1.0"
@@ -628,6 +628,10 @@ dependencies = [
  "tokio-util",
 ]
 
+[[package]]
+name = "cuprate-txpool"
+version = "0.0.0"
+
 [[package]]
 name = "cuprate-types"
 version = "0.0.0"
@@ -713,6 +717,10 @@ dependencies = [
  "parking_lot_core",
 ]
 
+[[package]]
+name = "database"
+version = "0.0.0"
+
 [[package]]
 name = "diff"
 version = "0.1.13"
diff --git a/Cargo.toml b/Cargo.toml
index 987d93d3..c1ebaf20 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,7 +5,6 @@ members = [
 	"consensus",
 	"consensus/rules",
 	"cryptonight",
-	"database",
 	"helper",
 	"net/epee-encoding",
 	"net/fixed-bytes",
@@ -15,6 +14,9 @@ members = [
 	"p2p/dandelion",
 	"p2p/monero-p2p",
 	"p2p/address-book",
+	"storage/cuprate-blockchain",
+	"storage/cuprate-txpool",
+	"storage/database",
 	"pruning",
 	"test-utils",
 	"types",
diff --git a/benches/README.md b/benches/README.md
new file mode 100644
index 00000000..46409041
--- /dev/null
+++ b/benches/README.md
@@ -0,0 +1 @@
+# TODO
diff --git a/binaries/README.md b/binaries/README.md
new file mode 100644
index 00000000..46409041
--- /dev/null
+++ b/binaries/README.md
@@ -0,0 +1 @@
+# TODO
diff --git a/books/README.md b/books/README.md
new file mode 100644
index 00000000..46409041
--- /dev/null
+++ b/books/README.md
@@ -0,0 +1 @@
+# TODO
diff --git a/books/architecture/README.md b/books/architecture/README.md
new file mode 100644
index 00000000..46409041
--- /dev/null
+++ b/books/architecture/README.md
@@ -0,0 +1 @@
+# TODO
diff --git a/books/protocol/README.md b/books/protocol/README.md
new file mode 100644
index 00000000..46409041
--- /dev/null
+++ b/books/protocol/README.md
@@ -0,0 +1 @@
+# TODO
diff --git a/helper/src/fs.rs b/helper/src/fs.rs
index a6ece515..1efb20cb 100644
--- a/helper/src/fs.rs
+++ b/helper/src/fs.rs
@@ -68,7 +68,7 @@ pub const CUPRATE_DIR: &str = {
 /// - [`cuprate_cache_dir()`]
 /// - [`cuprate_config_dir()`]
 /// - [`cuprate_data_dir()`]
-/// - [`cuprate_database_dir()`]
+/// - [`cuprate_blockchain_dir()`]
 ///
 /// FIXME: Use `LazyLock` when stabilized.
 /// <https://github.com/rust-lang/rust/issues/109736>.
@@ -166,18 +166,18 @@ impl_path_oncelock_and_fn! {
     data_dir,
     "",
 
-    /// Cuprate's database directory.
+    /// Cuprate's blockchain directory.
     ///
-    /// This is the PATH used for any Cuprate database files.
+    /// This is the PATH used for any Cuprate blockchain files.
     ///
-    /// | OS      | PATH                                                         |
-    /// |---------|--------------------------------------------------------------|
-    /// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\database\`           |
-    /// | macOS   | `/Users/Alice/Library/Application Support/Cuprate/database/` |
-    /// | Linux   | `/home/alice/.local/share/cuprate/database/`                 |
-    cuprate_database_dir,
+    /// | OS      | PATH                                                           |
+    /// |---------|----------------------------------------------------------------|
+    /// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\blockchain\`           |
+    /// | macOS   | `/Users/Alice/Library/Application Support/Cuprate/blockchain/` |
+    /// | Linux   | `/home/alice/.local/share/cuprate/blockchain/`                 |
+    cuprate_blockchain_dir,
     data_dir,
-    "database",
+    "blockchain",
 }
 
 //---------------------------------------------------------------------------------------------------- Tests
@@ -195,7 +195,7 @@ mod test {
         assert!(cuprate_cache_dir().is_absolute());
         assert!(cuprate_config_dir().is_absolute());
         assert!(cuprate_data_dir().is_absolute());
-        assert!(cuprate_database_dir().is_absolute());
+        assert!(cuprate_blockchain_dir().is_absolute());
 
         if cfg!(target_os = "windows") {
             let dir = cuprate_cache_dir();
@@ -210,9 +210,9 @@ mod test {
             println!("cuprate_data_dir: {dir:?}");
             assert!(dir.ends_with(r"AppData\Roaming\Cuprate"));
 
-            let dir = cuprate_database_dir();
-            println!("cuprate_database_dir: {dir:?}");
-            assert!(dir.ends_with(r"AppData\Roaming\Cuprate\database"));
+            let dir = cuprate_blockchain_dir();
+            println!("cuprate_blockchain_dir: {dir:?}");
+            assert!(dir.ends_with(r"AppData\Roaming\Cuprate\blockchain"));
         } else if cfg!(target_os = "macos") {
             let dir = cuprate_cache_dir();
             println!("cuprate_cache_dir: {dir:?}");
@@ -226,9 +226,9 @@ mod test {
             println!("cuprate_data_dir: {dir:?}");
             assert!(dir.ends_with("Library/Application Support/Cuprate"));
 
-            let dir = cuprate_database_dir();
-            println!("cuprate_database_dir: {dir:?}");
-            assert!(dir.ends_with("Library/Application Support/Cuprate/database"));
+            let dir = cuprate_blockchain_dir();
+            println!("cuprate_blockchain_dir: {dir:?}");
+            assert!(dir.ends_with("Library/Application Support/Cuprate/blockchain"));
         } else {
             // Assumes Linux.
             let dir = cuprate_cache_dir();
@@ -243,9 +243,9 @@ mod test {
             println!("cuprate_data_dir: {dir:?}");
             assert!(dir.ends_with(".local/share/cuprate"));
 
-            let dir = cuprate_database_dir();
-            println!("cuprate_database_dir: {dir:?}");
-            assert!(dir.ends_with(".local/share/cuprate/database"));
+            let dir = cuprate_blockchain_dir();
+            println!("cuprate_blockchain_dir: {dir:?}");
+            assert!(dir.ends_with(".local/share/cuprate/blockchain"));
         }
     }
 }
diff --git a/rpc/README.md b/rpc/README.md
new file mode 100644
index 00000000..46409041
--- /dev/null
+++ b/rpc/README.md
@@ -0,0 +1 @@
+# TODO
diff --git a/storage/README.md b/storage/README.md
new file mode 100644
index 00000000..b04d8e78
--- /dev/null
+++ b/storage/README.md
@@ -0,0 +1,5 @@
+# storage
+
+TODO: This subdirectory used to be `database/` and is in the middle of being shifted around.
+
+The old `database/` design document is in `cuprate-blockchain/` which will eventually be ported Cuprate's architecture book.
diff --git a/database/Cargo.toml b/storage/cuprate-blockchain/Cargo.toml
similarity index 78%
rename from database/Cargo.toml
rename to storage/cuprate-blockchain/Cargo.toml
index 712dbb16..bd61d595 100644
--- a/database/Cargo.toml
+++ b/storage/cuprate-blockchain/Cargo.toml
@@ -1,12 +1,12 @@
 [package]
-name        = "cuprate-database"
+name        = "cuprate-blockchain"
 version     = "0.0.0"
 edition     = "2021"
-description = "Cuprate's database abstraction"
+description = "Cuprate's blockchain database"
 license     = "MIT"
 authors     = ["hinto-janai"]
-repository  = "https://github.com/Cuprate/cuprate/tree/main/database"
-keywords    = ["cuprate", "database"]
+repository  = "https://github.com/Cuprate/cuprate/tree/main/storage/cuprate-blockchain"
+keywords    = ["cuprate", "blockchain", "database"]
 
 [features]
 default   = ["heed", "redb", "service"]
@@ -25,10 +25,10 @@ cfg-if   = { workspace = true }
 # FIXME:
 # We only need the `thread` feature if `service` is enabled.
 # Figure out how to enable features of an already pulled in dependency conditionally.
-cuprate-helper   = { path = "../helper", features = ["fs", "thread", "map"] }
-cuprate-types    = { path = "../types", features = ["service"] }
+cuprate-helper   = { path = "../../helper", features = ["fs", "thread", "map"] }
+cuprate-types    = { path = "../../types", features = ["service"] }
 curve25519-dalek = { workspace = true }
-monero-pruning   = { path = "../pruning" }
+monero-pruning   = { path = "../../pruning" }
 monero-serai     = { workspace = true, features = ["std"] }
 paste            = { workspace = true }
 page_size        = { version = "0.6.0" } # Needed for database resizes, they must be a multiple of the OS page size.
@@ -50,10 +50,10 @@ serde = { workspace = true, optional = true }
 
 [dev-dependencies]
 bytemuck = { version = "1.14.3", features = ["must_cast", "derive", "min_const_generics", "extern_crate_alloc"] }
-cuprate-helper = { path = "../helper", features = ["thread"] }
-cuprate-test-utils = { path = "../test-utils" }
+cuprate-helper = { path = "../../helper", features = ["thread"] }
+cuprate-test-utils = { path = "../../test-utils" }
 page_size = { version = "0.6.0" }
 tempfile = { version = "3.10.0" }
 pretty_assertions = { workspace = true }
 hex = { workspace = true }
-hex-literal = { workspace = true }
\ No newline at end of file
+hex-literal = { workspace = true }
diff --git a/database/README.md b/storage/cuprate-blockchain/README.md
similarity index 99%
rename from database/README.md
rename to storage/cuprate-blockchain/README.md
index 293413ac..22f729f0 100644
--- a/database/README.md
+++ b/storage/cuprate-blockchain/README.md
@@ -1,5 +1,7 @@
 # Database
-Cuprate's database implementation.
+FIXME: This documentation must be updated and moved to the architecture book.
+
+Cuprate's blockchain implementation.
 
 - [1. Documentation](#1-documentation)
 - [2. File structure](#2-file-structure)
@@ -595,4 +597,4 @@ struct PreRctOutputId { amount: 1, amount_index: 1 }
 
 This means `cuprated`'s database will be slightly larger than `monerod`'s.
 
-The current method `cuprate_database` uses will be "good enough" until usage shows that it must be optimized as multimap tables are tricky to implement across all backends.
\ No newline at end of file
+The current method `cuprate_database` uses will be "good enough" until usage shows that it must be optimized as multimap tables are tricky to implement across all backends.
diff --git a/database/src/backend/heed/database.rs b/storage/cuprate-blockchain/src/backend/heed/database.rs
similarity index 100%
rename from database/src/backend/heed/database.rs
rename to storage/cuprate-blockchain/src/backend/heed/database.rs
diff --git a/database/src/backend/heed/env.rs b/storage/cuprate-blockchain/src/backend/heed/env.rs
similarity index 99%
rename from database/src/backend/heed/env.rs
rename to storage/cuprate-blockchain/src/backend/heed/env.rs
index 56064849..703af4a8 100644
--- a/database/src/backend/heed/env.rs
+++ b/storage/cuprate-blockchain/src/backend/heed/env.rs
@@ -27,7 +27,7 @@ use crate::{
 //---------------------------------------------------------------------------------------------------- Consts
 /// Panic message when there's a table missing.
 const PANIC_MSG_MISSING_TABLE: &str =
-    "cuprate_database::Env should uphold the invariant that all tables are already created";
+    "cuprate_blockchain::Env should uphold the invariant that all tables are already created";
 
 //---------------------------------------------------------------------------------------------------- ConcreteEnv
 /// A strongly typed, concrete database environment, backed by `heed`.
diff --git a/database/src/backend/heed/error.rs b/storage/cuprate-blockchain/src/backend/heed/error.rs
similarity index 98%
rename from database/src/backend/heed/error.rs
rename to storage/cuprate-blockchain/src/backend/heed/error.rs
index c47bd908..c809e51c 100644
--- a/database/src/backend/heed/error.rs
+++ b/storage/cuprate-blockchain/src/backend/heed/error.rs
@@ -1,4 +1,4 @@
-//! Conversion from `heed::Error` -> `cuprate_database`'s errors.
+//! Conversion from `heed::Error` -> `cuprate_blockchain`'s errors.
 
 //---------------------------------------------------------------------------------------------------- Use
 use crate::constants::DATABASE_CORRUPT_MSG;
@@ -85,7 +85,7 @@ impl From<heed::Error> for crate::RuntimeError {
                 E2::Corrupted | E2::PageNotFound => panic!("{mdb_error:#?}\n{DATABASE_CORRUPT_MSG}"),
 
                 // These errors should not occur, and if they do,
-                // the best thing `cuprate_database` can do for
+                // the best thing `cuprate_blockchain` can do for
                 // safety is to panic right here.
                 E2::Panic
                 | E2::PageFull
diff --git a/database/src/backend/heed/mod.rs b/storage/cuprate-blockchain/src/backend/heed/mod.rs
similarity index 100%
rename from database/src/backend/heed/mod.rs
rename to storage/cuprate-blockchain/src/backend/heed/mod.rs
diff --git a/database/src/backend/heed/storable.rs b/storage/cuprate-blockchain/src/backend/heed/storable.rs
similarity index 96%
rename from database/src/backend/heed/storable.rs
rename to storage/cuprate-blockchain/src/backend/heed/storable.rs
index 83442212..ebd8f6e6 100644
--- a/database/src/backend/heed/storable.rs
+++ b/storage/cuprate-blockchain/src/backend/heed/storable.rs
@@ -1,4 +1,4 @@
-//! `cuprate_database::Storable` <-> `heed` serde trait compatibility layer.
+//! `cuprate_blockchain::Storable` <-> `heed` serde trait compatibility layer.
 
 //---------------------------------------------------------------------------------------------------- Use
 use std::{borrow::Cow, marker::PhantomData};
@@ -9,7 +9,7 @@ use crate::storable::Storable;
 
 //---------------------------------------------------------------------------------------------------- StorableHeed
 /// The glue struct that implements `heed`'s (de)serialization
-/// traits on any type that implements `cuprate_database::Storable`.
+/// traits on any type that implements `cuprate_blockchain::Storable`.
 ///
 /// Never actually gets constructed, just used for trait bound translations.
 pub(super) struct StorableHeed<T>(PhantomData<T>)
diff --git a/database/src/backend/heed/transaction.rs b/storage/cuprate-blockchain/src/backend/heed/transaction.rs
similarity index 100%
rename from database/src/backend/heed/transaction.rs
rename to storage/cuprate-blockchain/src/backend/heed/transaction.rs
diff --git a/database/src/backend/heed/types.rs b/storage/cuprate-blockchain/src/backend/heed/types.rs
similarity index 100%
rename from database/src/backend/heed/types.rs
rename to storage/cuprate-blockchain/src/backend/heed/types.rs
diff --git a/database/src/backend/mod.rs b/storage/cuprate-blockchain/src/backend/mod.rs
similarity index 100%
rename from database/src/backend/mod.rs
rename to storage/cuprate-blockchain/src/backend/mod.rs
diff --git a/database/src/backend/redb/database.rs b/storage/cuprate-blockchain/src/backend/redb/database.rs
similarity index 100%
rename from database/src/backend/redb/database.rs
rename to storage/cuprate-blockchain/src/backend/redb/database.rs
diff --git a/database/src/backend/redb/env.rs b/storage/cuprate-blockchain/src/backend/redb/env.rs
similarity index 99%
rename from database/src/backend/redb/env.rs
rename to storage/cuprate-blockchain/src/backend/redb/env.rs
index e552d454..67e430f8 100644
--- a/database/src/backend/redb/env.rs
+++ b/storage/cuprate-blockchain/src/backend/redb/env.rs
@@ -22,7 +22,7 @@ pub struct ConcreteEnv {
     /// (and in current use).
     config: Config,
 
-    /// A cached, redb version of `cuprate_database::config::SyncMode`.
+    /// A cached, redb version of `cuprate_blockchain::config::SyncMode`.
     /// `redb` needs the sync mode to be set _per_ TX, so we
     /// will continue to use this value every `Env::tx_rw`.
     durability: redb::Durability,
diff --git a/database/src/backend/redb/error.rs b/storage/cuprate-blockchain/src/backend/redb/error.rs
similarity index 98%
rename from database/src/backend/redb/error.rs
rename to storage/cuprate-blockchain/src/backend/redb/error.rs
index 4d40dbd9..1cc1456b 100644
--- a/database/src/backend/redb/error.rs
+++ b/storage/cuprate-blockchain/src/backend/redb/error.rs
@@ -1,4 +1,4 @@
-//! Conversion from `redb`'s errors -> `cuprate_database`'s errors.
+//! Conversion from `redb`'s errors -> `cuprate_blockchain`'s errors.
 //!
 //! HACK: There's a lot of `_ =>` usage here because
 //! `redb`'s errors are `#[non_exhaustive]`...
diff --git a/database/src/backend/redb/mod.rs b/storage/cuprate-blockchain/src/backend/redb/mod.rs
similarity index 100%
rename from database/src/backend/redb/mod.rs
rename to storage/cuprate-blockchain/src/backend/redb/mod.rs
diff --git a/database/src/backend/redb/storable.rs b/storage/cuprate-blockchain/src/backend/redb/storable.rs
similarity index 98%
rename from database/src/backend/redb/storable.rs
rename to storage/cuprate-blockchain/src/backend/redb/storable.rs
index 6735fec0..efe77dc5 100644
--- a/database/src/backend/redb/storable.rs
+++ b/storage/cuprate-blockchain/src/backend/redb/storable.rs
@@ -1,4 +1,4 @@
-//! `cuprate_database::Storable` <-> `redb` serde trait compatibility layer.
+//! `cuprate_blockchain::Storable` <-> `redb` serde trait compatibility layer.
 
 //---------------------------------------------------------------------------------------------------- Use
 use std::{cmp::Ordering, fmt::Debug, marker::PhantomData};
@@ -9,7 +9,7 @@ use crate::{key::Key, storable::Storable};
 
 //---------------------------------------------------------------------------------------------------- StorableRedb
 /// The glue structs that implements `redb`'s (de)serialization
-/// traits on any type that implements `cuprate_database::Key`.
+/// traits on any type that implements `cuprate_blockchain::Key`.
 ///
 /// Never actually get constructed, just used for trait bound translations.
 #[derive(Debug)]
diff --git a/database/src/backend/redb/transaction.rs b/storage/cuprate-blockchain/src/backend/redb/transaction.rs
similarity index 100%
rename from database/src/backend/redb/transaction.rs
rename to storage/cuprate-blockchain/src/backend/redb/transaction.rs
diff --git a/database/src/backend/redb/types.rs b/storage/cuprate-blockchain/src/backend/redb/types.rs
similarity index 100%
rename from database/src/backend/redb/types.rs
rename to storage/cuprate-blockchain/src/backend/redb/types.rs
diff --git a/database/src/backend/tests.rs b/storage/cuprate-blockchain/src/backend/tests.rs
similarity index 99%
rename from database/src/backend/tests.rs
rename to storage/cuprate-blockchain/src/backend/tests.rs
index 03d06c69..3daec669 100644
--- a/database/src/backend/tests.rs
+++ b/storage/cuprate-blockchain/src/backend/tests.rs
@@ -1,4 +1,4 @@
-//! Tests for `cuprate_database`'s backends.
+//! Tests for `cuprate_blockchain`'s backends.
 //!
 //! These tests are fully trait-based, meaning there
 //! is no reference to `backend/`-specific types.
diff --git a/database/src/config/backend.rs b/storage/cuprate-blockchain/src/config/backend.rs
similarity index 94%
rename from database/src/config/backend.rs
rename to storage/cuprate-blockchain/src/config/backend.rs
index 4bbb12ca..ee72b3df 100644
--- a/database/src/config/backend.rs
+++ b/storage/cuprate-blockchain/src/config/backend.rs
@@ -10,7 +10,7 @@ use std::{
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
-use cuprate_helper::fs::cuprate_database_dir;
+use cuprate_helper::fs::cuprate_blockchain_dir;
 
 use crate::{
     config::{ReaderThreads, SyncMode},
diff --git a/database/src/config/config.rs b/storage/cuprate-blockchain/src/config/config.rs
similarity index 91%
rename from database/src/config/config.rs
rename to storage/cuprate-blockchain/src/config/config.rs
index d712cb69..9d932ab1 100644
--- a/database/src/config/config.rs
+++ b/storage/cuprate-blockchain/src/config/config.rs
@@ -9,7 +9,7 @@ use std::{
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
-use cuprate_helper::fs::cuprate_database_dir;
+use cuprate_helper::fs::cuprate_blockchain_dir;
 
 use crate::{
     config::{ReaderThreads, SyncMode},
@@ -55,7 +55,7 @@ impl ConfigBuilder {
     ///
     /// # Default values
     /// If [`ConfigBuilder::db_directory`] was not called,
-    /// the default [`cuprate_database_dir`] will be used.
+    /// the default [`cuprate_blockchain_dir`] will be used.
     ///
     /// For all other values, [`Default::default`] is used.
     pub fn build(self) -> Config {
@@ -63,7 +63,7 @@ impl ConfigBuilder {
         // in `helper::fs`. No need to do them here.
         let db_directory = self
             .db_directory
-            .unwrap_or_else(|| Cow::Borrowed(cuprate_database_dir()));
+            .unwrap_or_else(|| Cow::Borrowed(cuprate_blockchain_dir()));
 
         // Add the database filename to the directory.
         let db_file = {
@@ -137,7 +137,7 @@ impl ConfigBuilder {
 impl Default for ConfigBuilder {
     fn default() -> Self {
         Self {
-            db_directory: Some(Cow::Borrowed(cuprate_database_dir())),
+            db_directory: Some(Cow::Borrowed(cuprate_blockchain_dir())),
             sync_mode: Some(SyncMode::default()),
             reader_threads: Some(ReaderThreads::default()),
             resize_algorithm: Some(ResizeAlgorithm::default()),
@@ -163,7 +163,7 @@ pub struct Config {
     /// The directory used to store all database files.
     ///
     /// By default, if no value is provided in the [`Config`]
-    /// constructor functions, this will be [`cuprate_database_dir`].
+    /// constructor functions, this will be [`cuprate_blockchain_dir`].
     ///
     // SOMEDAY: we should also support `/etc/cuprated.conf`.
     // This could be represented with an `enum DbPath { Default, Custom, Etc, }`
@@ -190,20 +190,20 @@ pub struct Config {
 impl Config {
     /// Create a new [`Config`] with sane default settings.
     ///
-    /// The [`Config::db_directory`] will be [`cuprate_database_dir`].
+    /// The [`Config::db_directory`] will be [`cuprate_blockchain_dir`].
     ///
     /// All other values will be [`Default::default`].
     ///
     /// Same as [`Config::default`].
     ///
     /// ```rust
-    /// use cuprate_database::{config::*, resize::*, DATABASE_DATA_FILENAME};
+    /// use cuprate_blockchain::{config::*, resize::*, DATABASE_DATA_FILENAME};
     /// use cuprate_helper::fs::*;
     ///
     /// let config = Config::new();
     ///
-    /// assert_eq!(config.db_directory(), cuprate_database_dir());
-    /// assert!(config.db_file().starts_with(cuprate_database_dir()));
+    /// assert_eq!(config.db_directory(), cuprate_blockchain_dir());
+    /// assert!(config.db_file().starts_with(cuprate_blockchain_dir()));
     /// assert!(config.db_file().ends_with(DATABASE_DATA_FILENAME));
     /// assert_eq!(config.sync_mode, SyncMode::default());
     /// assert_eq!(config.reader_threads, ReaderThreads::default());
@@ -228,7 +228,7 @@ impl Default for Config {
     /// Same as [`Config::new`].
     ///
     /// ```rust
-    /// # use cuprate_database::config::*;
+    /// # use cuprate_blockchain::config::*;
     /// assert_eq!(Config::default(), Config::new());
     /// ```
     fn default() -> Self {
diff --git a/database/src/config/mod.rs b/storage/cuprate-blockchain/src/config/mod.rs
similarity index 92%
rename from database/src/config/mod.rs
rename to storage/cuprate-blockchain/src/config/mod.rs
index dfa4f674..141790b4 100644
--- a/database/src/config/mod.rs
+++ b/storage/cuprate-blockchain/src/config/mod.rs
@@ -12,7 +12,7 @@
 //!
 //! # Example
 //! ```rust
-//! use cuprate_database::{
+//! use cuprate_blockchain::{
 //!     Env,
 //!     config::{ConfigBuilder, ReaderThreads, SyncMode}
 //! };
@@ -31,7 +31,7 @@
 //!     .build();
 //!
 //! // Start a database `service` using this configuration.
-//! let (reader_handle, _) = cuprate_database::service::init(config.clone())?;
+//! let (reader_handle, _) = cuprate_blockchain::service::init(config.clone())?;
 //! // It's using the config we provided.
 //! assert_eq!(reader_handle.env().config(), &config);
 //! # Ok(()) }
diff --git a/database/src/config/reader_threads.rs b/storage/cuprate-blockchain/src/config/reader_threads.rs
similarity index 97%
rename from database/src/config/reader_threads.rs
rename to storage/cuprate-blockchain/src/config/reader_threads.rs
index 34b20a88..04216e3e 100644
--- a/database/src/config/reader_threads.rs
+++ b/storage/cuprate-blockchain/src/config/reader_threads.rs
@@ -49,7 +49,7 @@ pub enum ReaderThreads {
     /// as such, it is equal to [`ReaderThreads::OnePerThread`].
     ///
     /// ```rust
-    /// # use cuprate_database::config::*;
+    /// # use cuprate_blockchain::config::*;
     /// let reader_threads = ReaderThreads::from(0_usize);
     /// assert!(matches!(reader_threads, ReaderThreads::OnePerThread));
     /// ```
@@ -81,7 +81,7 @@ pub enum ReaderThreads {
     /// non-zero, but not 1 thread, the minimum value 1 will be returned.
     ///
     /// ```rust
-    /// # use cuprate_database::config::*;
+    /// # use cuprate_blockchain::config::*;
     /// assert_eq!(ReaderThreads::Percent(0.000000001).as_threads().get(), 1);
     /// ```
     Percent(f32),
@@ -97,7 +97,7 @@ impl ReaderThreads {
     ///
     /// # Example
     /// ```rust
-    /// use cuprate_database::config::ReaderThreads as Rt;
+    /// use cuprate_blockchain::config::ReaderThreads as Rt;
     ///
     /// let total_threads: std::num::NonZeroUsize =
     ///     cuprate_helper::thread::threads();
diff --git a/database/src/config/sync_mode.rs b/storage/cuprate-blockchain/src/config/sync_mode.rs
similarity index 100%
rename from database/src/config/sync_mode.rs
rename to storage/cuprate-blockchain/src/config/sync_mode.rs
diff --git a/database/src/constants.rs b/storage/cuprate-blockchain/src/constants.rs
similarity index 95%
rename from database/src/constants.rs
rename to storage/cuprate-blockchain/src/constants.rs
index 667e36cb..25837c23 100644
--- a/database/src/constants.rs
+++ b/storage/cuprate-blockchain/src/constants.rs
@@ -1,4 +1,4 @@
-//! General constants used throughout `cuprate-database`.
+//! General constants used throughout `cuprate-blockchain`.
 
 //---------------------------------------------------------------------------------------------------- Import
 use cfg_if::cfg_if;
@@ -8,7 +8,7 @@ use cfg_if::cfg_if;
 ///
 /// Returned by [`crate::ops::property::db_version`].
 ///
-/// This is incremented by 1 when `cuprate_database`'s
+/// This is incremented by 1 when `cuprate_blockchain`'s
 /// structure/schema/tables change.
 ///
 /// This is akin to `VERSION` in `monerod`:
diff --git a/database/src/database.rs b/storage/cuprate-blockchain/src/database.rs
similarity index 100%
rename from database/src/database.rs
rename to storage/cuprate-blockchain/src/database.rs
diff --git a/database/src/env.rs b/storage/cuprate-blockchain/src/env.rs
similarity index 100%
rename from database/src/env.rs
rename to storage/cuprate-blockchain/src/env.rs
diff --git a/database/src/error.rs b/storage/cuprate-blockchain/src/error.rs
similarity index 98%
rename from database/src/error.rs
rename to storage/cuprate-blockchain/src/error.rs
index e47634f6..6112d92f 100644
--- a/database/src/error.rs
+++ b/storage/cuprate-blockchain/src/error.rs
@@ -66,7 +66,7 @@ pub enum InitError {
 /// 2. (De)serialization
 /// 3. Shutdown errors
 ///
-/// as `cuprate_database` upholds the invariant that:
+/// as `cuprate_blockchain` upholds the invariant that:
 ///
 /// 1. All tables exist
 /// 2. (De)serialization never fails
diff --git a/database/src/free.rs b/storage/cuprate-blockchain/src/free.rs
similarity index 100%
rename from database/src/free.rs
rename to storage/cuprate-blockchain/src/free.rs
diff --git a/database/src/key.rs b/storage/cuprate-blockchain/src/key.rs
similarity index 97%
rename from database/src/key.rs
rename to storage/cuprate-blockchain/src/key.rs
index 13f7cede..daafc6bb 100644
--- a/database/src/key.rs
+++ b/storage/cuprate-blockchain/src/key.rs
@@ -23,7 +23,7 @@ pub trait Key: Storable + Sized {
     /// not a comparison of the key's value.
     ///
     /// ```rust
-    /// # use cuprate_database::*;
+    /// # use cuprate_blockchain::*;
     /// assert_eq!(
     ///     <u64 as Key>::compare([0].as_slice(), [1].as_slice()),
     ///     std::cmp::Ordering::Less,
diff --git a/database/src/lib.rs b/storage/cuprate-blockchain/src/lib.rs
similarity index 97%
rename from database/src/lib.rs
rename to storage/cuprate-blockchain/src/lib.rs
index f1d2b2eb..7e7970fe 100644
--- a/database/src/lib.rs
+++ b/storage/cuprate-blockchain/src/lib.rs
@@ -1,6 +1,6 @@
 //! Cuprate's database abstraction.
 //!
-//! This documentation is mostly for practical usage of `cuprate_database`.
+//! This documentation is mostly for practical usage of `cuprate_blockchain`.
 //!
 //! For a high-level overview,
 //! see [`database/README.md`](https://github.com/Cuprate/cuprate/blob/main/database/README.md).
@@ -13,7 +13,7 @@
 //!
 //! Each layer builds on-top of the previous.
 //!
-//! As a user of `cuprate_database`, consider using the higher-level [`service`] module,
+//! As a user of `cuprate_blockchain`, consider using the higher-level [`service`] module,
 //! or at the very least the [`ops`] module instead of interacting with the database traits directly.
 //!
 //! With that said, many database traits and internals (like [`DatabaseRo::get`]) are exposed.
@@ -82,7 +82,7 @@
 //! <!-- FIXME: tracing should be behind a feature flag -->
 //!
 //! # Invariants when not using `service`
-//! `cuprate_database` can be used without the `service` feature enabled but
+//! `cuprate_blockchain` can be used without the `service` feature enabled but
 //! there are some things that must be kept in mind when doing so.
 //!
 //! Failing to uphold these invariants may cause panics.
@@ -92,7 +92,7 @@
 //! 1. `LMDB` has [maximum key/value byte size](http://www.lmdb.tech/doc/group__internal.html#gac929399f5d93cef85f874b9e9b1d09e0) which must not be exceeded
 //!
 //! # Examples
-//! The below is an example of using `cuprate_database`'s
+//! The below is an example of using `cuprate_blockchain`'s
 //! lowest API, i.e. using the database directly.
 //!
 //! For examples of the higher-level APIs, see:
@@ -100,7 +100,7 @@
 //! - [`service`]
 //!
 //! ```rust
-//! use cuprate_database::{
+//! use cuprate_blockchain::{
 //!     ConcreteEnv,
 //!     config::ConfigBuilder,
 //!     Env, EnvInner,
diff --git a/database/src/ops/block.rs b/storage/cuprate-blockchain/src/ops/block.rs
similarity index 100%
rename from database/src/ops/block.rs
rename to storage/cuprate-blockchain/src/ops/block.rs
diff --git a/database/src/ops/blockchain.rs b/storage/cuprate-blockchain/src/ops/blockchain.rs
similarity index 100%
rename from database/src/ops/blockchain.rs
rename to storage/cuprate-blockchain/src/ops/blockchain.rs
diff --git a/database/src/ops/key_image.rs b/storage/cuprate-blockchain/src/ops/key_image.rs
similarity index 100%
rename from database/src/ops/key_image.rs
rename to storage/cuprate-blockchain/src/ops/key_image.rs
diff --git a/database/src/ops/macros.rs b/storage/cuprate-blockchain/src/ops/macros.rs
similarity index 100%
rename from database/src/ops/macros.rs
rename to storage/cuprate-blockchain/src/ops/macros.rs
diff --git a/database/src/ops/mod.rs b/storage/cuprate-blockchain/src/ops/mod.rs
similarity index 99%
rename from database/src/ops/mod.rs
rename to storage/cuprate-blockchain/src/ops/mod.rs
index 9f48bd65..a4f50dd0 100644
--- a/database/src/ops/mod.rs
+++ b/storage/cuprate-blockchain/src/ops/mod.rs
@@ -56,7 +56,7 @@
 //!
 //! use cuprate_test_utils::data::block_v16_tx0;
 //!
-//! use cuprate_database::{
+//! use cuprate_blockchain::{
 //!     ConcreteEnv,
 //!     config::ConfigBuilder,
 //!     Env, EnvInner,
diff --git a/database/src/ops/output.rs b/storage/cuprate-blockchain/src/ops/output.rs
similarity index 100%
rename from database/src/ops/output.rs
rename to storage/cuprate-blockchain/src/ops/output.rs
diff --git a/database/src/ops/property.rs b/storage/cuprate-blockchain/src/ops/property.rs
similarity index 87%
rename from database/src/ops/property.rs
rename to storage/cuprate-blockchain/src/ops/property.rs
index 279c3552..2e584d87 100644
--- a/database/src/ops/property.rs
+++ b/storage/cuprate-blockchain/src/ops/property.rs
@@ -13,7 +13,7 @@ use crate::{error::RuntimeError, ops::macros::doc_error};
 ///
 /// # Example
 /// ```rust
-/// # use cuprate_database::{*, tables::*, ops::block::*, ops::tx::*};
+/// # use cuprate_blockchain::{*, tables::*, ops::block::*, ops::tx::*};
 /// // SOMEDAY
 /// ```
 #[inline]
@@ -29,7 +29,7 @@ pub const fn get_blockchain_pruning_seed() -> Result<PruningSeed, RuntimeError>
 ///
 /// # Example
 /// ```rust
-/// # use cuprate_database::{*, tables::*, ops::block::*, ops::tx::*};
+/// # use cuprate_blockchain::{*, tables::*, ops::block::*, ops::tx::*};
 /// // SOMEDAY
 /// ```
 #[inline]
diff --git a/database/src/ops/tx.rs b/storage/cuprate-blockchain/src/ops/tx.rs
similarity index 100%
rename from database/src/ops/tx.rs
rename to storage/cuprate-blockchain/src/ops/tx.rs
diff --git a/database/src/resize.rs b/storage/cuprate-blockchain/src/resize.rs
similarity index 96%
rename from database/src/resize.rs
rename to storage/cuprate-blockchain/src/resize.rs
index 99d6d7e3..488325be 100644
--- a/database/src/resize.rs
+++ b/storage/cuprate-blockchain/src/resize.rs
@@ -50,7 +50,7 @@ impl ResizeAlgorithm {
     /// Returns [`Self::Monero`].
     ///
     /// ```rust
-    /// # use cuprate_database::resize::*;
+    /// # use cuprate_blockchain::resize::*;
     /// assert!(matches!(ResizeAlgorithm::new(), ResizeAlgorithm::Monero));
     /// ```
     #[inline]
@@ -75,7 +75,7 @@ impl Default for ResizeAlgorithm {
     /// Calls [`Self::new`].
     ///
     /// ```rust
-    /// # use cuprate_database::resize::*;
+    /// # use cuprate_blockchain::resize::*;
     /// assert_eq!(ResizeAlgorithm::new(), ResizeAlgorithm::default());
     /// ```
     #[inline]
@@ -113,7 +113,7 @@ pub fn page_size() -> NonZeroUsize {
 /// [^2]: `1_073_745_920`
 ///
 /// ```rust
-/// # use cuprate_database::resize::*;
+/// # use cuprate_blockchain::resize::*;
 /// // The value this function will increment by
 /// // (assuming page multiple of 4096).
 /// const N: usize = 1_073_741_824;
@@ -129,7 +129,7 @@ pub fn page_size() -> NonZeroUsize {
 /// This function will panic if adding onto `current_size_bytes` overflows [`usize::MAX`].
 ///
 /// ```rust,should_panic
-/// # use cuprate_database::resize::*;
+/// # use cuprate_blockchain::resize::*;
 /// // Ridiculous large numbers panic.
 /// monero(usize::MAX);
 /// ```
@@ -166,7 +166,7 @@ pub fn monero(current_size_bytes: usize) -> NonZeroUsize {
 /// and then round up to nearest OS page size.
 ///
 /// ```rust
-/// # use cuprate_database::resize::*;
+/// # use cuprate_blockchain::resize::*;
 /// let page_size: usize = page_size().get();
 ///
 /// // Anything below the page size will round up to the page size.
@@ -185,7 +185,7 @@ pub fn monero(current_size_bytes: usize) -> NonZeroUsize {
 /// This function will panic if adding onto `current_size_bytes` overflows [`usize::MAX`].
 ///
 /// ```rust,should_panic
-/// # use cuprate_database::resize::*;
+/// # use cuprate_blockchain::resize::*;
 /// // Ridiculous large numbers panic.
 /// fixed_bytes(1, usize::MAX);
 /// ```
@@ -221,7 +221,7 @@ pub fn fixed_bytes(current_size_bytes: usize, add_bytes: usize) -> NonZeroUsize
 /// (rounded up to the OS page size).
 ///
 /// ```rust
-/// # use cuprate_database::resize::*;
+/// # use cuprate_blockchain::resize::*;
 /// let page_size: usize = page_size().get();
 ///
 /// // Anything below the page size will round up to the page size.
@@ -247,7 +247,7 @@ pub fn fixed_bytes(current_size_bytes: usize, add_bytes: usize) -> NonZeroUsize
 /// is closer to [`usize::MAX`] than the OS page size.
 ///
 /// ```rust,should_panic
-/// # use cuprate_database::resize::*;
+/// # use cuprate_blockchain::resize::*;
 /// // Ridiculous large numbers panic.
 /// percent(usize::MAX, 1.001);
 /// ```
diff --git a/database/src/service/free.rs b/storage/cuprate-blockchain/src/service/free.rs
similarity index 94%
rename from database/src/service/free.rs
rename to storage/cuprate-blockchain/src/service/free.rs
index fb40a065..276ce6a8 100644
--- a/database/src/service/free.rs
+++ b/storage/cuprate-blockchain/src/service/free.rs
@@ -1,4 +1,4 @@
-//! General free functions used (related to `cuprate_database::service`).
+//! General free functions used (related to `cuprate_blockchain::service`).
 
 //---------------------------------------------------------------------------------------------------- Import
 use std::sync::Arc;
diff --git a/database/src/service/mod.rs b/storage/cuprate-blockchain/src/service/mod.rs
similarity index 96%
rename from database/src/service/mod.rs
rename to storage/cuprate-blockchain/src/service/mod.rs
index ca5c9e6f..a95276a7 100644
--- a/database/src/service/mod.rs
+++ b/storage/cuprate-blockchain/src/service/mod.rs
@@ -66,7 +66,7 @@
 //! use cuprate_types::service::{ReadRequest, WriteRequest, Response};
 //! use cuprate_test_utils::data::block_v16_tx0;
 //!
-//! use cuprate_database::{ConcreteEnv, config::ConfigBuilder, Env};
+//! use cuprate_blockchain::{ConcreteEnv, config::ConfigBuilder, Env};
 //!
 //! # #[tokio::main]
 //! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -77,7 +77,7 @@
 //!     .build();
 //!
 //! // Initialize the database thread-pool.
-//! let (mut read_handle, mut write_handle) = cuprate_database::service::init(config)?;
+//! let (mut read_handle, mut write_handle) = cuprate_blockchain::service::init(config)?;
 //!
 //! // Prepare a request to write block.
 //! let mut block = block_v16_tx0().clone();
diff --git a/database/src/service/read.rs b/storage/cuprate-blockchain/src/service/read.rs
similarity index 100%
rename from database/src/service/read.rs
rename to storage/cuprate-blockchain/src/service/read.rs
diff --git a/database/src/service/tests.rs b/storage/cuprate-blockchain/src/service/tests.rs
similarity index 100%
rename from database/src/service/tests.rs
rename to storage/cuprate-blockchain/src/service/tests.rs
diff --git a/database/src/service/types.rs b/storage/cuprate-blockchain/src/service/types.rs
similarity index 100%
rename from database/src/service/types.rs
rename to storage/cuprate-blockchain/src/service/types.rs
diff --git a/database/src/service/write.rs b/storage/cuprate-blockchain/src/service/write.rs
similarity index 100%
rename from database/src/service/write.rs
rename to storage/cuprate-blockchain/src/service/write.rs
diff --git a/database/src/storable.rs b/storage/cuprate-blockchain/src/storable.rs
similarity index 97%
rename from database/src/storable.rs
rename to storage/cuprate-blockchain/src/storable.rs
index f259523f..80d010c6 100644
--- a/database/src/storable.rs
+++ b/storage/cuprate-blockchain/src/storable.rs
@@ -29,7 +29,7 @@ use bytes::Bytes;
 /// See [`StorableVec`] & [`StorableBytes`] for storing slices of `T: Storable`.
 ///
 /// ```rust
-/// # use cuprate_database::*;
+/// # use cuprate_blockchain::*;
 /// # use std::borrow::*;
 /// let number: u64 = 0;
 ///
@@ -77,7 +77,7 @@ pub trait Storable: Debug {
     ///
     /// # Examples
     /// ```rust
-    /// # use cuprate_database::*;
+    /// # use cuprate_blockchain::*;
     /// assert_eq!(<()>::BYTE_LENGTH, Some(0));
     /// assert_eq!(u8::BYTE_LENGTH, Some(1));
     /// assert_eq!(u16::BYTE_LENGTH, Some(2));
@@ -99,7 +99,7 @@ pub trait Storable: Debug {
     ///
     /// # Blanket implementation
     /// The blanket implementation that covers all types used
-    /// by `cuprate_database` will simply bitwise copy `bytes`
+    /// by `cuprate_blockchain` will simply bitwise copy `bytes`
     /// into `Self`.
     ///
     /// The bytes do not have be correctly aligned.
@@ -136,7 +136,7 @@ where
 ///
 /// # Example
 /// ```rust
-/// # use cuprate_database::*;
+/// # use cuprate_blockchain::*;
 /// //---------------------------------------------------- u8
 /// let vec: StorableVec<u8> = StorableVec(vec![0,1]);
 ///
@@ -202,7 +202,7 @@ impl<T> Borrow<[T]> for StorableVec<T> {
 /// A [`Storable`] version of [`Bytes`].
 ///
 /// ```rust
-/// # use cuprate_database::*;
+/// # use cuprate_blockchain::*;
 /// # use bytes::Bytes;
 /// let bytes: StorableBytes = StorableBytes(Bytes::from_static(&[0,1]));
 ///
diff --git a/database/src/table.rs b/storage/cuprate-blockchain/src/table.rs
similarity index 100%
rename from database/src/table.rs
rename to storage/cuprate-blockchain/src/table.rs
diff --git a/database/src/tables.rs b/storage/cuprate-blockchain/src/tables.rs
similarity index 99%
rename from database/src/tables.rs
rename to storage/cuprate-blockchain/src/tables.rs
index 0056b0bd..3bdad943 100644
--- a/database/src/tables.rs
+++ b/storage/cuprate-blockchain/src/tables.rs
@@ -1,7 +1,7 @@
 //! Database tables.
 //!
 //! # Table marker structs
-//! This module contains all the table definitions used by `cuprate_database`.
+//! This module contains all the table definitions used by `cuprate_blockchain`.
 //!
 //! The zero-sized structs here represents the table type;
 //! they all are essentially marker types that implement [`Table`].
@@ -331,7 +331,7 @@ macro_rules! tables {
             ///
             /// ## Table Name
             /// ```rust
-            /// # use cuprate_database::{*,tables::*};
+            /// # use cuprate_blockchain::{*,tables::*};
             #[doc = concat!(
                 "assert_eq!(",
                 stringify!([<$table:camel>]),
diff --git a/database/src/tests.rs b/storage/cuprate-blockchain/src/tests.rs
similarity index 98%
rename from database/src/tests.rs
rename to storage/cuprate-blockchain/src/tests.rs
index ba5e8550..90a74137 100644
--- a/database/src/tests.rs
+++ b/storage/cuprate-blockchain/src/tests.rs
@@ -1,4 +1,4 @@
-//! Utilities for `cuprate_database` testing.
+//! Utilities for `cuprate_blockchain` testing.
 //!
 //! These types/fn's are only:
 //! - enabled on #[cfg(test)]
diff --git a/database/src/transaction.rs b/storage/cuprate-blockchain/src/transaction.rs
similarity index 100%
rename from database/src/transaction.rs
rename to storage/cuprate-blockchain/src/transaction.rs
diff --git a/database/src/types.rs b/storage/cuprate-blockchain/src/types.rs
similarity index 96%
rename from database/src/types.rs
rename to storage/cuprate-blockchain/src/types.rs
index 5d89d4c4..2bb9aa0e 100644
--- a/database/src/types.rs
+++ b/storage/cuprate-blockchain/src/types.rs
@@ -105,7 +105,7 @@ pub type UnlockTime = u64;
 ///
 /// ```rust
 /// # use std::borrow::*;
-/// # use cuprate_database::{*, types::*};
+/// # use cuprate_blockchain::{*, types::*};
 /// // Assert Storable is correct.
 /// let a = PreRctOutputId {
 ///     amount: 1,
@@ -118,7 +118,7 @@ pub type UnlockTime = u64;
 ///
 /// # Size & Alignment
 /// ```rust
-/// # use cuprate_database::types::*;
+/// # use cuprate_blockchain::types::*;
 /// # use std::mem::*;
 /// assert_eq!(size_of::<PreRctOutputId>(), 16);
 /// assert_eq!(align_of::<PreRctOutputId>(), 8);
@@ -148,7 +148,7 @@ pub struct PreRctOutputId {
 ///
 /// ```rust
 /// # use std::borrow::*;
-/// # use cuprate_database::{*, types::*};
+/// # use cuprate_blockchain::{*, types::*};
 /// // Assert Storable is correct.
 /// let a = BlockInfo {
 ///     timestamp: 1,
@@ -167,7 +167,7 @@ pub struct PreRctOutputId {
 ///
 /// # Size & Alignment
 /// ```rust
-/// # use cuprate_database::types::*;
+/// # use cuprate_blockchain::types::*;
 /// # use std::mem::*;
 /// assert_eq!(size_of::<BlockInfo>(), 88);
 /// assert_eq!(align_of::<BlockInfo>(), 8);
@@ -207,7 +207,7 @@ bitflags::bitflags! {
     ///
     /// ```rust
     /// # use std::borrow::*;
-    /// # use cuprate_database::{*, types::*};
+    /// # use cuprate_blockchain::{*, types::*};
     /// // Assert Storable is correct.
     /// let a = OutputFlags::NON_ZERO_UNLOCK_TIME;
     /// let b = Storable::as_bytes(&a);
@@ -217,7 +217,7 @@ bitflags::bitflags! {
     ///
     /// # Size & Alignment
     /// ```rust
-    /// # use cuprate_database::types::*;
+    /// # use cuprate_blockchain::types::*;
     /// # use std::mem::*;
     /// assert_eq!(size_of::<OutputFlags>(), 4);
     /// assert_eq!(align_of::<OutputFlags>(), 4);
@@ -236,7 +236,7 @@ bitflags::bitflags! {
 ///
 /// ```rust
 /// # use std::borrow::*;
-/// # use cuprate_database::{*, types::*};
+/// # use cuprate_blockchain::{*, types::*};
 /// // Assert Storable is correct.
 /// let a = Output {
 ///     key: [1; 32],
@@ -251,7 +251,7 @@ bitflags::bitflags! {
 ///
 /// # Size & Alignment
 /// ```rust
-/// # use cuprate_database::types::*;
+/// # use cuprate_blockchain::types::*;
 /// # use std::mem::*;
 /// assert_eq!(size_of::<Output>(), 48);
 /// assert_eq!(align_of::<Output>(), 8);
@@ -277,7 +277,7 @@ pub struct Output {
 ///
 /// ```rust
 /// # use std::borrow::*;
-/// # use cuprate_database::{*, types::*};
+/// # use cuprate_blockchain::{*, types::*};
 /// // Assert Storable is correct.
 /// let a = RctOutput {
 ///     key: [1; 32],
@@ -293,7 +293,7 @@ pub struct Output {
 ///
 /// # Size & Alignment
 /// ```rust
-/// # use cuprate_database::types::*;
+/// # use cuprate_blockchain::types::*;
 /// # use std::mem::*;
 /// assert_eq!(size_of::<RctOutput>(), 80);
 /// assert_eq!(align_of::<RctOutput>(), 8);
diff --git a/database/src/unsafe_sendable.rs b/storage/cuprate-blockchain/src/unsafe_sendable.rs
similarity index 100%
rename from database/src/unsafe_sendable.rs
rename to storage/cuprate-blockchain/src/unsafe_sendable.rs
diff --git a/storage/cuprate-txpool/Cargo.toml b/storage/cuprate-txpool/Cargo.toml
new file mode 100644
index 00000000..d08b2290
--- /dev/null
+++ b/storage/cuprate-txpool/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "cuprate-txpool"
+version = "0.0.0"
+edition = "2021"
+
+[dependencies]
diff --git a/storage/cuprate-txpool/src/lib.rs b/storage/cuprate-txpool/src/lib.rs
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/storage/cuprate-txpool/src/lib.rs
@@ -0,0 +1 @@
+
diff --git a/storage/database/Cargo.toml b/storage/database/Cargo.toml
new file mode 100644
index 00000000..b0351d12
--- /dev/null
+++ b/storage/database/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "database"
+version = "0.0.0"
+edition = "2021"
+
+[dependencies]
diff --git a/storage/database/src/lib.rs b/storage/database/src/lib.rs
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/storage/database/src/lib.rs
@@ -0,0 +1 @@
+
diff --git a/zmq/README.md b/zmq/README.md
new file mode 100644
index 00000000..46409041
--- /dev/null
+++ b/zmq/README.md
@@ -0,0 +1 @@
+# TODO

From d052fbedf1e8acce60f2a10733b7dd747077432c Mon Sep 17 00:00:00 2001
From: hinto-janai <hinto.janai@protonmail.com>
Date: Wed, 29 May 2024 13:34:32 -0400
Subject: [PATCH 03/10] repo: add issue templates (#137)

* add issue templates

* add `question.md`

* fix bug.md

* fix feature.md

* bug.md: fix spacing
---
 .github/ISSUE_TEMPLATE/bug.md        | 45 ++++++++++++++++++++++++++++
 .github/ISSUE_TEMPLATE/discussion.md | 18 +++++++++++
 .github/ISSUE_TEMPLATE/feature.md    | 21 +++++++++++++
 .github/ISSUE_TEMPLATE/proposal.md   | 24 +++++++++++++++
 .github/ISSUE_TEMPLATE/question.md   | 15 ++++++++++
 5 files changed, 123 insertions(+)
 create mode 100644 .github/ISSUE_TEMPLATE/bug.md
 create mode 100644 .github/ISSUE_TEMPLATE/discussion.md
 create mode 100644 .github/ISSUE_TEMPLATE/feature.md
 create mode 100644 .github/ISSUE_TEMPLATE/proposal.md
 create mode 100644 .github/ISSUE_TEMPLATE/question.md

diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md
new file mode 100644
index 00000000..404bd6ad
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug.md
@@ -0,0 +1,45 @@
+---
+name: 🐞 Bug report
+about: Create a bug report
+title: ''
+labels: ["C-bug"]
+assignees: ''
+
+---
+
+<!--
+Notes:
+- All these fields are optional, add as much or as little info as you like
+- Please search to see if an issue already exists for the bug you encountered
+-->
+
+## Environment
+Example:
+- OS: Windows 11
+- CPU: AMD Ryzen 5 5600X
+- Memory: 16GB
+- Storage: SSD 500GB
+- Cuprate: v1.0.0
+
+## Bug
+What is the bug?
+
+### Expected behavior
+What correct beahvior was expected to happen?
+
+## Steps to reproduce
+Example:
+1. In this environment...
+2. With this config...
+3. Run '...'
+4. See error...
+
+## Log
+If possible, add any related logs to help explain the bug.
+
+Note: please remove any sensitive information from the logs (e.g. IP address).
+
+## Screenshots
+If possible, add screenshots to help explain the bug.
+
+Note: please remove any sensitive information from the screenshot.
diff --git a/.github/ISSUE_TEMPLATE/discussion.md b/.github/ISSUE_TEMPLATE/discussion.md
new file mode 100644
index 00000000..60444617
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/discussion.md
@@ -0,0 +1,18 @@
+---
+name: ⏳ Discussion
+about: Start a discussion on a topic
+title: ''
+labels: ["C-discussion"]
+assignees: ''
+
+---
+
+<!--
+Note: Please search to see if an issue already exists for this discussion.
+-->
+
+## What
+What would you would like to discuss?
+
+## Why
+Why would you would like to discuss this?
diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md
new file mode 100644
index 00000000..dab48112
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature.md
@@ -0,0 +1,21 @@
+---
+name: ✨ Feature request
+about: Request a feature
+title: ''
+labels: ["C-request"]
+assignees: ''
+
+---
+
+<!--
+Note: Please search to see if an issue already exists for this request, or if the feature already exists.
+-->
+
+## Feature
+What is the feature you're requesting?
+
+## Why
+Why should your feature be added?
+
+## Additional context
+Add any other context or screenshots about the feature request.
diff --git a/.github/ISSUE_TEMPLATE/proposal.md b/.github/ISSUE_TEMPLATE/proposal.md
new file mode 100644
index 00000000..132b2b07
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/proposal.md
@@ -0,0 +1,24 @@
+---
+name: 📜 Proposal
+about: Propose an idea and request for comments
+title: ''
+labels: ["C-proposal"]
+assignees: ''
+
+---
+
+<!--
+Note: Please search to see if an issue already exists for this proposal.
+-->
+
+## What
+Describe your proposal.
+
+## Where
+Describe where your proposal will cause changes to.
+
+## Why
+Describe why the proposal is needed.
+
+## How
+Describe how the proposal could be implemented.
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
new file mode 100644
index 00000000..af426a2d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -0,0 +1,15 @@
+---
+name: ❓ Question
+about: Ask a question
+title: ''
+labels: ["C-question"]
+assignees: ''
+
+---
+
+<!--
+Note: Please search to see if an issue already exists for this question.
+-->
+
+## Question
+What question would you like to ask?

From c50d9642be99af829144dca3cb9f732c467d7d62 Mon Sep 17 00:00:00 2001
From: hinto-janai <hinto.janai@protonmail.com>
Date: Wed, 29 May 2024 15:00:29 -0400
Subject: [PATCH 04/10] storage: create Cargo.toml for `{database,
 cuprate-txpool}` (#140)

---
 storage/cuprate-txpool/Cargo.toml | 15 ++++++++++++---
 storage/database/Cargo.toml       | 15 ++++++++++++---
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/storage/cuprate-txpool/Cargo.toml b/storage/cuprate-txpool/Cargo.toml
index d08b2290..536d445a 100644
--- a/storage/cuprate-txpool/Cargo.toml
+++ b/storage/cuprate-txpool/Cargo.toml
@@ -1,6 +1,15 @@
 [package]
-name = "cuprate-txpool"
-version = "0.0.0"
-edition = "2021"
+name        = "cuprate-txpool"
+version     = "0.0.0"
+edition     = "2021"
+description = "Cuprate's transaction pool database"
+license     = "MIT"
+authors     = ["hinto-janai"]
+repository  = "https://github.com/Cuprate/cuprate/tree/main/storage/cuprate-txpool"
+keywords    = ["cuprate", "txpool", "transaction", "pool", "database"]
+
+[features]
 
 [dependencies]
+
+[dev-dependencies]
diff --git a/storage/database/Cargo.toml b/storage/database/Cargo.toml
index b0351d12..50bf0f7e 100644
--- a/storage/database/Cargo.toml
+++ b/storage/database/Cargo.toml
@@ -1,6 +1,15 @@
 [package]
-name = "database"
-version = "0.0.0"
-edition = "2021"
+name        = "database"
+version     = "0.0.0"
+edition     = "2021"
+description = "Cuprate's database abstraction"
+license     = "MIT"
+authors     = ["hinto-janai"]
+repository  = "https://github.com/Cuprate/cuprate/tree/main/storage/database"
+keywords    = ["cuprate", "database"]
+
+[features]
 
 [dependencies]
+
+[dev-dependencies]

From 384818f57f3868290e42a47b302052c48f8d10c1 Mon Sep 17 00:00:00 2001
From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com>
Date: Thu, 30 May 2024 01:25:55 +0100
Subject: [PATCH 05/10] dandelion_tower -> dandelion-tower

---
 Cargo.lock               | 2 +-
 p2p/dandelion/Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index c17cb7c9..1535ea4b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -687,7 +687,7 @@ dependencies = [
 ]
 
 [[package]]
-name = "dandelion_tower"
+name = "dandelion-tower"
 version = "0.1.0"
 dependencies = [
  "futures",
diff --git a/p2p/dandelion/Cargo.toml b/p2p/dandelion/Cargo.toml
index a8a04691..e5d7e340 100644
--- a/p2p/dandelion/Cargo.toml
+++ b/p2p/dandelion/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "dandelion_tower"
+name = "dandelion-tower"
 version = "0.1.0"
 edition = "2021"
 license = "MIT"

From a4ca12358903a68938b122709ee07ac27cb28845 Mon Sep 17 00:00:00 2001
From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com>
Date: Thu, 30 May 2024 01:27:27 +0100
Subject: [PATCH 06/10] fix async-buffer builds

---
 Cargo.lock                  | 10 ++++++++++
 Cargo.toml                  |  1 +
 p2p/async-buffer/src/lib.rs |  2 +-
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/Cargo.lock b/Cargo.lock
index 4750a614..b2ec7f03 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -98,6 +98,16 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "async-buffer"
+version = "0.1.0"
+dependencies = [
+ "futures",
+ "pin-project",
+ "thiserror",
+ "tokio",
+]
+
 [[package]]
 name = "async-lock"
 version = "3.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index c1ebaf20..b09bc3e4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,7 @@ members = [
 	"p2p/cuprate-p2p",
 	"p2p/dandelion",
 	"p2p/monero-p2p",
+	"p2p/async-buffer",
 	"p2p/address-book",
 	"storage/cuprate-blockchain",
 	"storage/cuprate-txpool",
diff --git a/p2p/async-buffer/src/lib.rs b/p2p/async-buffer/src/lib.rs
index ded8c6a9..0e2ced24 100644
--- a/p2p/async-buffer/src/lib.rs
+++ b/p2p/async-buffer/src/lib.rs
@@ -48,7 +48,7 @@ pub fn new_buffer<T>(max_item_weight: usize) -> (BufferAppender<T>, BufferStream
             queue: tx,
             sink_waker: sink_waker.clone(),
             capacity: capacity_atomic.clone(),
-            max_item_weight: capacity,
+            max_item_weight,
         },
         BufferStream {
             queue: rx,

From fd7225e6738869bcc9c1ef50e13977c044dbcd2e Mon Sep 17 00:00:00 2001
From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com>
Date: Thu, 30 May 2024 02:03:48 +0100
Subject: [PATCH 07/10] check if incoming peers are banned

---
 p2p/address-book/src/book.rs          |  3 +++
 p2p/cuprate-p2p/src/inbound_server.rs | 25 ++++++++++++++++++++-----
 p2p/cuprate-p2p/src/lib.rs            | 11 ++++++++---
 p2p/monero-p2p/src/services.rs        |  3 +++
 4 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/p2p/address-book/src/book.rs b/p2p/address-book/src/book.rs
index 3a49c6be..2f0617e9 100644
--- a/p2p/address-book/src/book.rs
+++ b/p2p/address-book/src/book.rs
@@ -409,6 +409,9 @@ impl<Z: NetworkZone> Service<AddressBookRequest<Z>> for AddressBook<Z> {
             AddressBookRequest::GetWhitePeers(len) => {
                 Ok(AddressBookResponse::Peers(self.get_white_peers(len)))
             }
+            AddressBookRequest::IsPeerBanned(addr) => Ok(AddressBookResponse::IsPeerBanned(
+                self.is_peer_banned(&addr),
+            )),
         };
 
         ready(response)
diff --git a/p2p/cuprate-p2p/src/inbound_server.rs b/p2p/cuprate-p2p/src/inbound_server.rs
index b56903a9..df15515e 100644
--- a/p2p/cuprate-p2p/src/inbound_server.rs
+++ b/p2p/cuprate-p2p/src/inbound_server.rs
@@ -12,9 +12,10 @@ use tokio::{
 use tower::{Service, ServiceExt};
 use tracing::{instrument, Instrument, Span};
 
+use monero_p2p::services::{AddressBookRequest, AddressBookResponse};
 use monero_p2p::{
     client::{Client, DoHandshakeRequest, HandshakeError, InternalPeerID},
-    ConnectionDirection, NetworkZone,
+    AddressBook, ConnectionDirection, NetworkZone,
 };
 
 use crate::{
@@ -25,9 +26,10 @@ use crate::{
 
 /// The inbound server.
 #[instrument(level = "warn", skip_all)]
-pub async fn inbound_server<N, HS>(
+pub async fn inbound_server<N, HS, A>(
     client_pool: Arc<ClientPool<N>>,
     mut handshaker: HS,
+    mut address_book: A,
     config: P2PConfig<N>,
 ) -> Result<(), tower::BoxError>
 where
@@ -36,15 +38,13 @@ where
         + Send
         + 'static,
     HS::Future: Send + 'static,
+    A: AddressBook<N>,
 {
     let Some(server_config) = config.server_config else {
         tracing::warn!("No inbound server config provided, not listening for inbound connections.");
         return Ok(());
     };
 
-    // TODO: take in the address book and check if incoming peers are banned before adding them to our
-    // connections.
-
     tracing::info!("Starting inbound connection server");
 
     let listener = N::incoming_connection_listener(server_config, config.p2p_port)
@@ -60,6 +60,21 @@ where
             continue;
         };
 
+        if let Some(addr) = &addr {
+            let AddressBookResponse::IsPeerBanned(banned) = address_book
+                .ready()
+                .await?
+                .call(AddressBookRequest::IsPeerBanned(*addr))
+                .await?
+            else {
+                panic!("Address book returned incorrect response!");
+            };
+
+            if banned {
+                continue;
+            }
+        }
+
         let addr = match addr {
             Some(addr) => InternalPeerID::KnownAddr(addr),
             None => InternalPeerID::Unknown(rand::random()),
diff --git a/p2p/cuprate-p2p/src/lib.rs b/p2p/cuprate-p2p/src/lib.rs
index 20a35819..500eeb09 100644
--- a/p2p/cuprate-p2p/src/lib.rs
+++ b/p2p/cuprate-p2p/src/lib.rs
@@ -56,7 +56,7 @@ where
         config.max_inbound_connections + config.outbound_connections,
     );
 
-    // Use the default config. Changing the defaults affects tx fluff times, which could effect D++ so for now don't allow changing
+    // Use the default config. Changing the defaults affects tx fluff times, which could affect D++ so for now don't allow changing
     // this.
     let (broadcast_svc, outbound_mkr, inbound_mkr) =
         broadcast::init_broadcast_channels(broadcast::BroadcastConfig::default());
@@ -105,8 +105,13 @@ where
             .instrument(Span::current()),
     );
     tokio::spawn(
-        inbound_server::inbound_server(client_pool.clone(), inbound_handshaker, config)
-            .instrument(Span::current()),
+        inbound_server::inbound_server(
+            client_pool.clone(),
+            inbound_handshaker,
+            address_book,
+            config,
+        )
+        .instrument(Span::current()),
     );
 
     Ok(NetworkInterface {
diff --git a/p2p/monero-p2p/src/services.rs b/p2p/monero-p2p/src/services.rs
index e86e2776..bf0d6ec3 100644
--- a/p2p/monero-p2p/src/services.rs
+++ b/p2p/monero-p2p/src/services.rs
@@ -119,10 +119,13 @@ pub enum AddressBookRequest<Z: NetworkZone> {
     TakeRandomPeer { height: Option<u64> },
     /// Gets the specified number of white peers, or less if we don't have enough.
     GetWhitePeers(usize),
+    /// Checks if the given peer is banned.
+    IsPeerBanned(Z::Addr),
 }
 
 pub enum AddressBookResponse<Z: NetworkZone> {
     Ok,
     Peer(ZoneSpecificPeerListEntryBase<Z::Addr>),
     Peers(Vec<ZoneSpecificPeerListEntryBase<Z::Addr>>),
+    IsPeerBanned(bool),
 }

From d84e8a48f86924dc18b97264c83ffa56012fa87b Mon Sep 17 00:00:00 2001
From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com>
Date: Thu, 30 May 2024 17:02:38 +0100
Subject: [PATCH 08/10] add interface methods

---
 p2p/cuprate-p2p/src/broadcast.rs              |  1 +
 p2p/cuprate-p2p/src/client_pool.rs            | 16 +------
 .../src/client_pool/disconnect_monitor.rs     |  4 +-
 p2p/cuprate-p2p/src/inbound_server.rs         |  2 +-
 p2p/cuprate-p2p/src/lib.rs                    | 47 +++++++++++++++----
 p2p/cuprate-p2p/src/sync_states.rs            |  8 ++--
 6 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/p2p/cuprate-p2p/src/broadcast.rs b/p2p/cuprate-p2p/src/broadcast.rs
index cc8a3fd6..b6e5e807 100644
--- a/p2p/cuprate-p2p/src/broadcast.rs
+++ b/p2p/cuprate-p2p/src/broadcast.rs
@@ -151,6 +151,7 @@ pub enum BroadcastRequest<N: NetworkZone> {
     },
 }
 
+#[derive(Clone)]
 pub struct BroadcastSvc<N: NetworkZone> {
     new_block_watch: watch::Sender<NewBlockInfo>,
     tx_broadcast_channel_outbound: broadcast::Sender<BroadcastTxInfo<N>>,
diff --git a/p2p/cuprate-p2p/src/client_pool.rs b/p2p/cuprate-p2p/src/client_pool.rs
index ed547dde..8b77f423 100644
--- a/p2p/cuprate-p2p/src/client_pool.rs
+++ b/p2p/cuprate-p2p/src/client_pool.rs
@@ -12,14 +12,14 @@
 //!
 use std::sync::Arc;
 
-use dashmap::{DashMap, DashSet};
+use dashmap::DashMap;
 use tokio::sync::mpsc;
 use tracing::{Instrument, Span};
 
 use monero_p2p::{
     client::{Client, InternalPeerID},
     handles::ConnectionHandle,
-    ConnectionDirection, NetworkZone,
+    NetworkZone,
 };
 
 pub(crate) mod disconnect_monitor;
@@ -33,11 +33,6 @@ pub use drop_guard_client::ClientPoolDropGuard;
 pub struct ClientPool<N: NetworkZone> {
     /// The connected [`Client`]s.
     clients: DashMap<InternalPeerID<N::Addr>, Client<N>>,
-    /// A set of outbound clients, as these allow accesses/mutation from different threads,
-    /// a peer ID in here does not mean the peer is necessarily in `clients` as it could have been removed
-    /// by another thread. However, if the peer is in both here and `clients` it is definitely
-    /// an outbound peer.
-    outbound_clients: DashSet<InternalPeerID<N::Addr>>,
     /// A channel to send new peer ids down to monitor for disconnect.
     new_connection_tx: mpsc::UnboundedSender<(ConnectionHandle, InternalPeerID<N::Addr>)>,
 }
@@ -49,7 +44,6 @@ impl<N: NetworkZone> ClientPool<N> {
 
         let pool = Arc::new(ClientPool {
             clients: DashMap::new(),
-            outbound_clients: DashSet::new(),
             new_connection_tx: tx,
         });
 
@@ -76,10 +70,6 @@ impl<N: NetworkZone> ClientPool<N> {
             return;
         }
 
-        if client.info.direction == ConnectionDirection::OutBound {
-            self.outbound_clients.insert(id);
-        }
-
         let res = self.clients.insert(id, client);
         assert!(res.is_none());
 
@@ -108,8 +98,6 @@ impl<N: NetworkZone> ClientPool<N> {
     ///
     /// [`None`] is returned if the client did not exist in the pool.
     fn remove_client(&self, peer: &InternalPeerID<N::Addr>) -> Option<Client<N>> {
-        self.outbound_clients.remove(peer);
-
         self.clients.remove(peer).map(|(_, client)| client)
     }
 
diff --git a/p2p/cuprate-p2p/src/client_pool/disconnect_monitor.rs b/p2p/cuprate-p2p/src/client_pool/disconnect_monitor.rs
index 977e46e8..e83fa325 100644
--- a/p2p/cuprate-p2p/src/client_pool/disconnect_monitor.rs
+++ b/p2p/cuprate-p2p/src/client_pool/disconnect_monitor.rs
@@ -24,8 +24,8 @@ pub async fn disconnect_monitor<N: NetworkZone>(
     mut new_connection_rx: mpsc::UnboundedReceiver<(ConnectionHandle, InternalPeerID<N::Addr>)>,
     client_pool: Arc<ClientPool<N>>,
 ) {
-    // We need to hold a weak reference otherwise the client pool and this would hold a reference to each
-    // other causing the pool to be leaked.
+    // We need to hold a weak reference otherwise the client pool and this would hold a reference to
+    // each other causing the pool to be leaked.
     let weak_client_pool = Arc::downgrade(&client_pool);
     drop(client_pool);
 
diff --git a/p2p/cuprate-p2p/src/inbound_server.rs b/p2p/cuprate-p2p/src/inbound_server.rs
index df15515e..0eb4772c 100644
--- a/p2p/cuprate-p2p/src/inbound_server.rs
+++ b/p2p/cuprate-p2p/src/inbound_server.rs
@@ -12,9 +12,9 @@ use tokio::{
 use tower::{Service, ServiceExt};
 use tracing::{instrument, Instrument, Span};
 
-use monero_p2p::services::{AddressBookRequest, AddressBookResponse};
 use monero_p2p::{
     client::{Client, DoHandshakeRequest, HandshakeError, InternalPeerID},
+    services::{AddressBookRequest, AddressBookResponse},
     AddressBook, ConnectionDirection, NetworkZone,
 };
 
diff --git a/p2p/cuprate-p2p/src/lib.rs b/p2p/cuprate-p2p/src/lib.rs
index 500eeb09..b244c57a 100644
--- a/p2p/cuprate-p2p/src/lib.rs
+++ b/p2p/cuprate-p2p/src/lib.rs
@@ -5,14 +5,20 @@
 //! This crate also contains the different routing methods that control how messages should be sent, i.e. broadcast to all,
 //! or send to a single peer.
 //!
-#![allow(dead_code)]
 
 use std::sync::Arc;
+
 use tokio::sync::{mpsc, watch};
-use tower::buffer::Buffer;
+use tokio_stream::wrappers::WatchStream;
+use tower::{buffer::Buffer, util::BoxCloneService, ServiceExt};
 use tracing::{instrument, Instrument, Span};
 
-use monero_p2p::{CoreSyncSvc, NetworkZone, PeerRequestHandler};
+use monero_p2p::{
+    client::Connector,
+    client::InternalPeerID,
+    services::{AddressBookRequest, AddressBookResponse},
+    CoreSyncSvc, NetworkZone, PeerRequestHandler,
+};
 
 mod broadcast;
 mod client_pool;
@@ -22,9 +28,10 @@ mod constants;
 mod inbound_server;
 mod sync_states;
 
-use crate::connection_maintainer::MakeConnectionRequest;
+pub use broadcast::{BroadcastRequest, BroadcastSvc};
+use client_pool::ClientPoolDropGuard;
 pub use config::P2PConfig;
-use monero_p2p::client::Connector;
+use connection_maintainer::MakeConnectionRequest;
 
 /// Initializes the P2P [`NetworkInterface`] for a specific [`NetworkZone`].
 ///
@@ -108,7 +115,7 @@ where
         inbound_server::inbound_server(
             client_pool.clone(),
             inbound_handshaker,
-            address_book,
+            address_book.clone(),
             config,
         )
         .instrument(Span::current()),
@@ -119,6 +126,7 @@ where
         broadcast_svc,
         top_block_watch,
         make_connection_tx,
+        address_book: address_book.boxed_clone(),
     })
 }
 
@@ -126,11 +134,34 @@ where
 pub struct NetworkInterface<N: NetworkZone> {
     /// A pool of free connected peers.
     pool: Arc<client_pool::ClientPool<N>>,
-    /// A [`Service`](tower::Service) that allows broadcasting to all connected peers.
-    broadcast_svc: broadcast::BroadcastSvc<N>,
+    /// A [`Service`] that allows broadcasting to all connected peers.
+    broadcast_svc: BroadcastSvc<N>,
     /// A [`watch`] channel that contains the highest seen cumulative difficulty and other info
     /// on that claimed chain.
     top_block_watch: watch::Receiver<sync_states::NewSyncInfo>,
     /// A channel to request extra connections.
+    #[allow(dead_code)] // will be used eventually
     make_connection_tx: mpsc::Sender<MakeConnectionRequest>,
+    /// The address book service.
+    address_book: BoxCloneService<AddressBookRequest<N>, AddressBookResponse<N>, tower::BoxError>,
+}
+
+impl<N: NetworkZone> NetworkInterface<N> {
+    pub fn broadcast_svc(&self) -> BroadcastSvc<N> {
+        self.broadcast_svc.clone()
+    }
+
+    pub fn top_sync_stream(&self) -> WatchStream<sync_states::NewSyncInfo> {
+        WatchStream::from_changes(self.top_block_watch.clone())
+    }
+
+    pub fn address_book(
+        &self,
+    ) -> BoxCloneService<AddressBookRequest<N>, AddressBookResponse<N>, tower::BoxError> {
+        self.address_book.clone()
+    }
+
+    pub fn borrow_client(&self, peer: &InternalPeerID<N::Addr>) -> Option<ClientPoolDropGuard<N>> {
+        self.pool.borrow_client(peer)
+    }
 }
diff --git a/p2p/cuprate-p2p/src/sync_states.rs b/p2p/cuprate-p2p/src/sync_states.rs
index 9b8b3bd2..2321692a 100644
--- a/p2p/cuprate-p2p/src/sync_states.rs
+++ b/p2p/cuprate-p2p/src/sync_states.rs
@@ -25,14 +25,14 @@ use monero_wire::CoreSyncData;
 use crate::{client_pool::disconnect_monitor::PeerDisconnectFut, constants::SHORT_BAN};
 
 /// The highest claimed sync info from our connected peers.
-#[derive(Debug)]
+#[derive(Debug, Copy, Clone)]
 pub struct NewSyncInfo {
     /// The peers chain height.
-    chain_height: u64,
+    pub chain_height: u64,
     /// The peers top block's hash.
-    top_hash: [u8; 32],
+    pub top_hash: [u8; 32],
     /// The peers cumulative difficulty.
-    cumulative_difficulty: u128,
+    pub cumulative_difficulty: u128,
 }
 
 /// A service that keeps track of our peers blockchains.

From cce4ef96dd86c9dd67bbc8709d5742e30b88b69a Mon Sep 17 00:00:00 2001
From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com>
Date: Thu, 30 May 2024 18:24:23 +0100
Subject: [PATCH 09/10] update docs

---
 p2p/cuprate-p2p/src/lib.rs | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/p2p/cuprate-p2p/src/lib.rs b/p2p/cuprate-p2p/src/lib.rs
index b244c57a..27ac0d0b 100644
--- a/p2p/cuprate-p2p/src/lib.rs
+++ b/p2p/cuprate-p2p/src/lib.rs
@@ -1,10 +1,7 @@
 //! Cuprate's P2P Crate.
 //!
-//! This crate contains a [`ClientPool`](client_pool::ClientPool) which holds connected peers on a single [`NetworkZone`].
-//!
-//! This crate also contains the different routing methods that control how messages should be sent, i.e. broadcast to all,
-//! or send to a single peer.
-//!
+//! This crate contains a [`NetworkInterface`] which allows interacting with the Monero P2P network on
+//! a certain [`NetworkZone`]
 
 use std::sync::Arc;
 
@@ -147,20 +144,25 @@ pub struct NetworkInterface<N: NetworkZone> {
 }
 
 impl<N: NetworkZone> NetworkInterface<N> {
+    /// Returns a service which allows broadcasting messages to all the connected peers in a specific [`NetworkZone`].
     pub fn broadcast_svc(&self) -> BroadcastSvc<N> {
         self.broadcast_svc.clone()
     }
 
+    /// Returns a stream which yields the highest seen sync state from a connected peer.
     pub fn top_sync_stream(&self) -> WatchStream<sync_states::NewSyncInfo> {
         WatchStream::from_changes(self.top_block_watch.clone())
     }
 
+    /// Returns the address book service.
     pub fn address_book(
         &self,
     ) -> BoxCloneService<AddressBookRequest<N>, AddressBookResponse<N>, tower::BoxError> {
         self.address_book.clone()
     }
 
+    /// Pulls a client from the client pool, returning it in a guard that will return it there when it's
+    /// dropped.
     pub fn borrow_client(&self, peer: &InternalPeerID<N::Addr>) -> Option<ClientPoolDropGuard<N>> {
         self.pool.borrow_client(peer)
     }

From cbcfbff8786f8bc8feb71a67290426103047d069 Mon Sep 17 00:00:00 2001
From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com>
Date: Thu, 30 May 2024 21:14:28 +0100
Subject: [PATCH 10/10] use a JoinSet for background network tasks

---
 p2p/cuprate-p2p/src/lib.rs | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/p2p/cuprate-p2p/src/lib.rs b/p2p/cuprate-p2p/src/lib.rs
index 27ac0d0b..52126225 100644
--- a/p2p/cuprate-p2p/src/lib.rs
+++ b/p2p/cuprate-p2p/src/lib.rs
@@ -2,10 +2,13 @@
 //!
 //! This crate contains a [`NetworkInterface`] which allows interacting with the Monero P2P network on
 //! a certain [`NetworkZone`]
-
 use std::sync::Arc;
 
-use tokio::sync::{mpsc, watch};
+use futures::FutureExt;
+use tokio::{
+    sync::{mpsc, watch},
+    task::JoinSet,
+};
 use tokio_stream::wrappers::WatchStream;
 use tower::{buffer::Buffer, util::BoxCloneService, ServiceExt};
 use tracing::{instrument, Instrument, Span};
@@ -68,7 +71,6 @@ where
     let mut basic_node_data = config.basic_node_data();
 
     if !N::CHECK_NODE_ID {
-        // TODO: make sure this is the value monerod sets for anon networks.
         basic_node_data.peer_id = 1;
     }
 
@@ -103,18 +105,27 @@ where
         outbound_connector,
     );
 
-    tokio::spawn(
+    let mut background_tasks = JoinSet::new();
+
+    background_tasks.spawn(
         outbound_connection_maintainer
             .run()
             .instrument(Span::current()),
     );
-    tokio::spawn(
+    background_tasks.spawn(
         inbound_server::inbound_server(
             client_pool.clone(),
             inbound_handshaker,
             address_book.clone(),
             config,
         )
+        .map(|res| {
+            if let Err(e) = res {
+                tracing::error!("Error in inbound connection listener: {e}")
+            }
+
+            tracing::info!("Inbound connection listener shutdown")
+        })
         .instrument(Span::current()),
     );
 
@@ -124,10 +135,12 @@ where
         top_block_watch,
         make_connection_tx,
         address_book: address_book.boxed_clone(),
+        _background_tasks: Arc::new(background_tasks),
     })
 }
 
 /// The interface to Monero's P2P network on a certain [`NetworkZone`].
+#[derive(Clone)]
 pub struct NetworkInterface<N: NetworkZone> {
     /// A pool of free connected peers.
     pool: Arc<client_pool::ClientPool<N>>,
@@ -141,6 +154,8 @@ pub struct NetworkInterface<N: NetworkZone> {
     make_connection_tx: mpsc::Sender<MakeConnectionRequest>,
     /// The address book service.
     address_book: BoxCloneService<AddressBookRequest<N>, AddressBookResponse<N>, tower::BoxError>,
+    /// Background tasks that will be aborted when this interface is dropped.
+    _background_tasks: Arc<JoinSet<()>>,
 }
 
 impl<N: NetworkZone> NetworkInterface<N> {