Merge branch 'main' into network-init

This commit is contained in:
Boog900 2024-05-30 01:25:59 +01:00
commit a53279a8c6
No known key found for this signature in database
GPG key ID: 42AB1287CB0041C2
83 changed files with 745 additions and 169 deletions

45
.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View file

@ -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.

18
.github/ISSUE_TEMPLATE/discussion.md vendored Normal file
View file

@ -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?

21
.github/ISSUE_TEMPLATE/feature.md vendored Normal file
View file

@ -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.

24
.github/ISSUE_TEMPLATE/proposal.md vendored Normal file
View file

@ -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.

15
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View file

@ -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?

114
.github/labeler.yml vendored Normal file
View file

@ -0,0 +1,114 @@
# This file consists of rules determining which labels the
# `github-actions` bot should automatically label an issue/PR with.
# The CI that actually applies labels is in `.github/workflows/labeler.yml`.
#
# The main one used is the "if a file changed" rule.
# The format for this rule is:
#
# ```
# $LABEL_NAME:
# - changed-files:
# - any-glob-to-any-file: $PATH
# ```
#
# where $PATH can be:
# $DIRECTORY/*
# which means any file changed 1 level deep inside that directory or:
# $DIRECTORY/**
# which means any file changed within that directory or:
# $DIRECTORY/$FILE_NAME
# which means a specific file path or:
# $DIRECTORY/*.$FILE_EXTENSION
# which means any file 1 level deep in that directory with a certain file extension.
#
# For a detailed guide, see: <https://github.com/actions/labeler>.
#
# For a real example:
A-consensus: # This is the tag name
- changed-files: # Any changed file...
- any-glob-to-any-file: consensus/** # ...within the `consensus/` directory
# 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-storage:
- changed-files:
- any-glob-to-any-file: storage/**
A-helper:
- changed-files:
- any-glob-to-any-file: helper/**
A-net:
- changed-files:
- any-glob-to-any-file: net/**
A-p2p:
- changed-files:
- any-glob-to-any-file: p2p/**
A-pruning:
- changed-files:
- any-glob-to-any-file: pruning/**
A-test-utils:
- changed-files:
- any-glob-to-any-file: test-utils/**
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
- any-glob-to-any-file: '**/Cargo.lock'
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.

View file

@ -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

25
.github/workflows/labeler.yml vendored Normal file
View file

@ -0,0 +1,25 @@
# This action automatically applies GitHub labels
# based on the rules in the `.github/labeler.yml` file.
#
# For more info:
# - <https://github.com/actions/labeler>
# - <https://github.com/tokio-rs/tokio/blob/6c42d286b343f498ce29de2aab9358a0aedb081c/.github/workflows/labeler.yml>
name: "Labeler"
on:
- pull_request_target
permissions:
contents: read
jobs:
labeler:
permissions:
contents: read # for actions/labeler to determine modified files
pull-requests: write # for actions/labeler to add labels to PRs
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
sync-labels: true

View file

@ -38,3 +38,29 @@ After that, ensure all lints, tests, and builds are successful by running:
- Sort imports as core, std, third-party, Cuprate crates, current crate.
- Follow the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines)
- Break the above rules when it makes sense
## Keeping track of issues and PRs
The Cuprate GitHub repository has a lot of issues and PRs to keep track of. Cuprate makes use of generic labels and labels grouped by a prefixes to help with this.
Some labels will be [automatically added/removed](https://github.com/Cuprate/cuprate/tree/main/.github/labeler.yml) if certain file paths have been changed in a PR.
The following section explains the meaning of various labels used.
This section is primarily targeted at maintainers. Most contributors aren't able to set these labels.
| Labels | Description | Example |
|--------------|-------------|---------|
| [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`
[A-]: https://github.com/Cuprate/cuprate/labels?q=A
[C-]: https://github.com/Cuprate/cuprate/labels?q=C
[D-]: https://github.com/Cuprate/cuprate/labels?q=D
[E-]: https://github.com/Cuprate/cuprate/labels?q=E
[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

74
Cargo.lock generated
View file

@ -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"
@ -629,6 +629,10 @@ dependencies = [
"tokio-util",
]
[[package]]
name = "cuprate-txpool"
version = "0.0.0"
[[package]]
name = "cuprate-types"
version = "0.0.0"
@ -714,6 +718,10 @@ dependencies = [
"parking_lot_core",
]
[[package]]
name = "database"
version = "0.0.0"
[[package]]
name = "diff"
version = "0.1.13"

View file

@ -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",

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Boog900
Copyright (c) 2023-2024 Cuprate Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View file

@ -1,6 +1,5 @@
Cuprate crates are licensed under one of two licenses, either MIT or AGPL-3.0,
depending on the crate in question. Each crate declares their license in their
`Cargo.toml` and includes a `LICENSE` file detailing its status. Additionally,
a full copy of the AGPL-3.0 License is included in the root of this repository
as a reference text. This copy should be provided with any distribution of a
crate licensed under the AGPL-3.0, as per its terms.
`Cargo.toml`. Additionally, a full copy of both licenses are included in the
root of this repository for reference. These copies should be provided with
any distribution of a crate, as per the respective license's terms.

1
benches/README.md Normal file
View file

@ -0,0 +1 @@
# TODO

1
binaries/README.md Normal file
View file

@ -0,0 +1 @@
# TODO

1
books/README.md Normal file
View file

@ -0,0 +1 @@
# TODO

View file

@ -0,0 +1 @@
# TODO

1
books/protocol/README.md Normal file
View file

@ -0,0 +1 @@
# TODO

View file

@ -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>.
@ -78,17 +78,16 @@ macro_rules! impl_path_oncelock_and_fn {
$(#[$attr:meta])* // Documentation and any `derive`'s.
$fn:ident, // Name of the corresponding access function.
$dirs_fn:ident, // Name of the `dirs` function to use, the PATH prefix.
$once_lock:ident, // Name of the `OnceLock`.
$sub_dirs:literal // Any sub-directories to add onto the PATH.
),* $(,)?) => {$(
/// Local `OnceLock` containing the Path.
static $once_lock: OnceLock<PathBuf> = OnceLock::new();
// Create the `OnceLock` if needed, append
// the Cuprate directory string and return.
$(#[$attr])*
pub fn $fn() -> &'static Path {
$once_lock.get_or_init(|| {
/// Local `OnceLock` containing the Path.
static ONCE_LOCK: OnceLock<PathBuf> = OnceLock::new();
ONCE_LOCK.get_or_init(|| {
// There's nothing we can do but panic if
// we cannot acquire critical system directories.
//
@ -139,7 +138,6 @@ impl_path_oncelock_and_fn! {
/// | Linux | `/home/alice/.cache/cuprate/` |
cuprate_cache_dir,
cache_dir,
__CUPRATE_CACHE_DIR,
"",
/// Cuprate's config directory.
@ -153,7 +151,6 @@ impl_path_oncelock_and_fn! {
/// | Linux | `/home/alice/.config/cuprate/` |
cuprate_config_dir,
config_dir,
__CUPRATE_CONFIG_DIR,
"",
/// Cuprate's data directory.
@ -167,22 +164,20 @@ impl_path_oncelock_and_fn! {
/// | Linux | `/home/alice/.local/share/cuprate/` |
cuprate_data_dir,
data_dir,
__CUPRATE_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,
__CUPRATE_DATABASE_DIR,
"database",
"blockchain",
}
//---------------------------------------------------------------------------------------------------- Tests
@ -200,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();
@ -215,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:?}");
@ -231,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();
@ -248,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"));
}
}
}

View file

@ -1,9 +0,0 @@
MIT license
Copyright (C) 2023 Cuprate Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,9 +0,0 @@
MIT license
Copyright (C) 2023 Cuprate Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,14 @@
[package]
name = "async-buffer"
version = "0.1.0"
edition = "2021"
license = "MIT"
authors = ["Boog900"]
[dependencies]
thiserror = { workspace = true }
futures = { workspace = true, features = ["std"] }
pin-project = { workspace = true }
[dev-dependencies]
tokio = { workspace = true, features = ["full"] }

205
p2p/async-buffer/src/lib.rs Normal file
View file

@ -0,0 +1,205 @@
//! Async Buffer
//!
//! A bounded SPSC, FIFO, async buffer that supports arbitrary weights for values.
//!
//! Weight is used to bound the channel, on creation you specify a max weight and for each value you
//! specify a weight.
use std::{
cmp::min,
future::Future,
pin::Pin,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
task::{Context, Poll},
};
use futures::{
channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender},
ready,
task::AtomicWaker,
Stream, StreamExt,
};
#[derive(thiserror::Error, Debug, Copy, Clone, Eq, PartialEq)]
pub enum BufferError {
#[error("The buffer did not have enough capacity.")]
NotEnoughCapacity,
#[error("The other end of the buffer disconnected.")]
Disconnected,
}
/// Initializes a new buffer with the provided capacity.
///
/// The capacity inputted is not the max number of items, it is the max combined weight of all items
/// in the buffer.
///
/// It should be noted that if there are no items in the buffer then a single item of any capacity is accepted.
/// i.e. if the capacity is 5 and there are no items in the buffer then any item even if it's weight is >5 will be
/// accepted.
pub fn new_buffer<T>(max_item_weight: usize) -> (BufferAppender<T>, BufferStream<T>) {
let (tx, rx) = unbounded();
let sink_waker = Arc::new(AtomicWaker::new());
let capacity_atomic = Arc::new(AtomicUsize::new(max_item_weight));
(
BufferAppender {
queue: tx,
sink_waker: sink_waker.clone(),
capacity: capacity_atomic.clone(),
max_item_weight: capacity,
},
BufferStream {
queue: rx,
sink_waker,
capacity: capacity_atomic,
},
)
}
/// The stream side of the buffer.
pub struct BufferStream<T> {
/// The internal queue of items.
queue: UnboundedReceiver<(T, usize)>,
/// The waker for the [`BufferAppender`]
sink_waker: Arc<AtomicWaker>,
/// The current capacity of the buffer.
capacity: Arc<AtomicUsize>,
}
impl<T> Stream for BufferStream<T> {
type Item = T;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let Some((item, size)) = ready!(self.queue.poll_next_unpin(cx)) else {
return Poll::Ready(None);
};
// add the capacity back to the buffer.
self.capacity.fetch_add(size, Ordering::AcqRel);
// wake the sink.
self.sink_waker.wake();
Poll::Ready(Some(item))
}
}
/// The appender/sink side of the buffer.
pub struct BufferAppender<T> {
/// The internal queue of items.
queue: UnboundedSender<(T, usize)>,
/// Our waker.
sink_waker: Arc<AtomicWaker>,
/// The current capacity of the buffer.
capacity: Arc<AtomicUsize>,
/// The max weight of an item, equal to the total allowed weight of the buffer.
max_item_weight: usize,
}
impl<T> BufferAppender<T> {
/// Returns a future that resolves when the channel has enough capacity for
/// a single message of `size_needed`.
///
/// It should be noted that if there are no items in the buffer then a single item of any capacity is accepted.
/// i.e. if the capacity is 5 and there are no items in the buffer then any item even if it's weight is >5 will be
/// accepted.
pub fn ready(&mut self, size_needed: usize) -> BufferSinkReady<'_, T> {
let size_needed = min(self.max_item_weight, size_needed);
BufferSinkReady {
sink: self,
size_needed,
}
}
/// Attempts to add an item to the buffer.
///
/// # Errors
/// Returns an error if there is not enough capacity or the [`BufferStream`] was dropped.
pub fn try_send(&mut self, item: T, size_needed: usize) -> Result<(), BufferError> {
let size_needed = min(self.max_item_weight, size_needed);
if self.capacity.load(Ordering::Acquire) < size_needed {
return Err(BufferError::NotEnoughCapacity);
}
let prev_size = self.capacity.fetch_sub(size_needed, Ordering::AcqRel);
// make sure we haven't wrapped the capacity around.
assert!(prev_size >= size_needed);
self.queue
.unbounded_send((item, size_needed))
.map_err(|_| BufferError::Disconnected)?;
Ok(())
}
/// Waits for capacity in the buffer and then sends the item.
pub fn send(&mut self, item: T, size_needed: usize) -> BufferSinkSend<'_, T> {
BufferSinkSend {
ready: self.ready(size_needed),
item: Some(item),
}
}
}
/// A [`Future`] for adding an item to the buffer.
#[pin_project::pin_project]
pub struct BufferSinkSend<'a, T> {
/// A future that resolves when the channel has capacity.
#[pin]
ready: BufferSinkReady<'a, T>,
/// The item to send.
///
/// This is [`take`](Option::take)n and added to the buffer when there is enough capacity.
item: Option<T>,
}
impl<'a, T> Future for BufferSinkSend<'a, T> {
type Output = Result<(), BufferError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
let size_needed = this.ready.size_needed;
this.ready.as_mut().poll(cx).map(|_| {
this.ready
.sink
.try_send(this.item.take().unwrap(), size_needed)
})
}
}
/// A [`Future`] for waiting for capacity in the buffer.
pub struct BufferSinkReady<'a, T> {
/// The sink side of the buffer.
sink: &'a mut BufferAppender<T>,
/// The capacity needed.
///
/// This future will wait forever if this is higher than the total availability of the buffer.
size_needed: usize,
}
impl<'a, T> Future for BufferSinkReady<'a, T> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// Check before setting the waker just in case it has capacity now,
if self.sink.capacity.load(Ordering::Acquire) >= self.size_needed {
return Poll::Ready(());
}
// set the waker
self.sink.sink_waker.register(cx.waker());
// check the capacity again to avoid a race condition that would result in lost notifications.
if self.sink.capacity.load(Ordering::Acquire) >= self.size_needed {
Poll::Ready(())
} else {
Poll::Pending
}
}
}

View file

@ -0,0 +1,37 @@
use futures::{FutureExt, StreamExt};
use async_buffer::new_buffer;
#[tokio::test]
async fn async_buffer_send_rec() {
let (mut tx, mut rx) = new_buffer(1000);
tx.send(4, 5).await.unwrap();
tx.send(8, 5).await.unwrap();
assert_eq!(rx.next().await.unwrap(), 4);
assert_eq!(rx.next().await.unwrap(), 8);
}
#[tokio::test]
async fn capacity_reached() {
let (mut tx, mut rx) = new_buffer(1000);
tx.send(4, 1000).await.unwrap();
assert!(tx.ready(1).now_or_never().is_none());
let fut = tx.ready(1);
rx.next().await;
assert!(fut.now_or_never().is_some());
}
#[tokio::test]
async fn single_item_over_capacity() {
let (mut tx, mut rx) = new_buffer(1000);
tx.send(4, 1_000_000).await.unwrap();
assert_eq!(rx.next().await.unwrap(), 4);
}

1
rpc/README.md Normal file
View file

@ -0,0 +1 @@
# TODO

5
storage/README.md Normal file
View file

@ -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.

View file

@ -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 }
hex-literal = { workspace = true }

View file

@ -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.
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.

View file

@ -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`.

View file

@ -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

View file

@ -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>)

View file

@ -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,

View file

@ -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]`...

View file

@ -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)]

View file

@ -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.

View file

@ -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},

View file

@ -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 {

View file

@ -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(()) }

View file

@ -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();

View file

@ -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`:

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -56,7 +56,7 @@
//!
//! use cuprate_test_utils::data::block_v16_tx0;
//!
//! use cuprate_database::{
//! use cuprate_blockchain::{
//! ConcreteEnv,
//! config::ConfigBuilder,
//! Env, EnvInner,

View file

@ -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]

View file

@ -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]
@ -85,8 +85,6 @@ impl Default for ResizeAlgorithm {
}
//---------------------------------------------------------------------------------------------------- Free functions
/// Cached result of [`page_size()`].
static PAGE_SIZE: OnceLock<NonZeroUsize> = OnceLock::new();
/// This function retrieves the systems memory page size.
///
/// It is just [`page_size::get`](https://docs.rs/page_size) internally.
@ -97,6 +95,8 @@ static PAGE_SIZE: OnceLock<NonZeroUsize> = OnceLock::new();
/// This function will panic if the OS returns of page size of `0` (impossible?).
#[inline]
pub fn page_size() -> NonZeroUsize {
/// Cached result of [`page_size()`].
static PAGE_SIZE: OnceLock<NonZeroUsize> = OnceLock::new();
*PAGE_SIZE
.get_or_init(|| NonZeroUsize::new(page_size::get()).expect("page_size::get() returned 0"))
}
@ -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);
/// ```

View file

@ -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;

View file

@ -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();

View file

@ -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]));
///

View file

@ -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>]),

View file

@ -1,4 +1,4 @@
//! Utilities for `cuprate_database` testing.
//! Utilities for `cuprate_blockchain` testing.
//!
//! These types/fn's are only:
//! - enabled on #[cfg(test)]

View file

@ -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);

View file

@ -0,0 +1,15 @@
[package]
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]

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,15 @@
[package]
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]

View file

@ -0,0 +1 @@

1
zmq/README.md Normal file
View file

@ -0,0 +1 @@
# TODO