diff --git a/Cargo.lock b/Cargo.lock index 1207e7cd..d9248e2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,6 +643,17 @@ dependencies = [ "zip", ] +[[package]] +name = "cuprate-types" +version = "0.0.0" +dependencies = [ + "borsh", + "cfg-if", + "curve25519-dalek", + "monero-serai", + "serde", +] + [[package]] name = "curve25519-dalek" version = "4.1.2" diff --git a/Cargo.toml b/Cargo.toml index 9e640e4a..cf51f5fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ members = [ "p2p/address-book", "pruning", "test-utils", + "types", ] [profile.release] @@ -39,6 +40,7 @@ opt-level = 3 async-trait = { version = "0.1.74", default-features = false } bitflags = { version = "2.4.2", default-features = false } borsh = { version = "1.2.1", default-features = false } +bytemuck = { version = "1.14.3", default-features = false } bytes = { version = "1.5.0", default-features = false } cfg-if = { version = "1.0.0", default-features = false } clap = { version = "4.4.7", default-features = false } @@ -87,7 +89,6 @@ proptest-derive = { version = "0.4.0" } # open = { version = "5.0.0" } # Open PATH/URL, probably for binaries | https://github.com/byron/open-rs # regex = { version = "1.10.2" } # Regular expressions | https://github.com/rust-lang/regex # ryu = { version = "1.0.15" } # Fast float to string formatting | https://github.com/dtolnay/ryu -# strum = { version = "0.25.0" } # Enum macros/traits | https://github.com/Peternator7/strum # Maybe one day. # disk = { version = "*" } # (De)serialization to/from disk with various file formats | https://github.com/hinto-janai/disk diff --git a/types/Cargo.toml b/types/Cargo.toml new file mode 100644 index 00000000..8e69e8fb --- /dev/null +++ b/types/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "cuprate-types" +version = "0.0.0" +edition = "2021" +description = "Cuprate data types" +license = "MIT" +authors = ["hinto-janai"] +repository = "https://github.com/Cuprate/cuprate/tree/main/types" +keywords = ["cuprate", "types"] + +[features] +default = ["service"] +service = [] + +[dependencies] +borsh = { workspace = true, optional = true } +cfg-if = { workspace = true } +curve25519-dalek = { workspace = true } +monero-serai = { workspace = true } +serde = { workspace = true, optional = true } + +[dev-dependencies] \ No newline at end of file diff --git a/types/README.md b/types/README.md new file mode 100644 index 00000000..bbe03c17 --- /dev/null +++ b/types/README.md @@ -0,0 +1,21 @@ +# `cuprate-types` +Various data types shared by Cuprate. + + +1. [File Structure](#file-structure) + - [`src/`](#src) + +--- + +# File Structure +A quick reference of the structure of the folders & files in `cuprate-types`. + +Note that `lib.rs/mod.rs` files are purely for re-exporting/visibility/lints, and contain no code. Each sub-directory has a corresponding `mod.rs`. + +## `src/` +The top-level `src/` files. + +| File | Purpose | +|---------------------|---------| +| `service.rs` | Types used in database requests; `enum {Request,Response}` +| `types.rs` | Various general types used by Cuprate diff --git a/types/src/lib.rs b/types/src/lib.rs new file mode 100644 index 00000000..ea96515c --- /dev/null +++ b/types/src/lib.rs @@ -0,0 +1,101 @@ +//! Cuprate shared data types. +//! +//! TODO + +//---------------------------------------------------------------------------------------------------- Lints +// Forbid lints. +// Our code, and code generated (e.g macros) cannot overrule these. +#![forbid( + // `unsafe` is allowed but it _must_ be + // commented with `SAFETY: reason`. + clippy::undocumented_unsafe_blocks, + + // Never. + unused_unsafe, + redundant_semicolons, + unused_allocation, + coherence_leak_check, + single_use_lifetimes, + while_true, + clippy::missing_docs_in_private_items, + + // Maybe can be put into `#[deny]`. + unconditional_recursion, + for_loops_over_fallibles, + unused_braces, + unused_doc_comments, + unused_labels, + keyword_idents, + non_ascii_idents, + variant_size_differences, + + // Probably can be put into `#[deny]`. + future_incompatible, + let_underscore, + break_with_label_and_loop, + duplicate_macro_attributes, + exported_private_dependencies, + large_assignments, + overlapping_range_endpoints, + semicolon_in_expressions_from_macros, + noop_method_call, + unreachable_pub, +)] +// Deny lints. +// Some of these are `#[allow]`'ed on a per-case basis. +#![deny( + clippy::all, + clippy::correctness, + clippy::suspicious, + clippy::style, + clippy::complexity, + clippy::perf, + clippy::pedantic, + clippy::nursery, + clippy::cargo, + unused_mut, + missing_docs, + deprecated, + unused_comparisons, + nonstandard_style +)] +#![allow(unreachable_code, unused_variables, dead_code, unused_imports)] // TODO: remove +#![allow( + // FIXME: this lint affects crates outside of + // `database/` for some reason, allow for now. + clippy::cargo_common_metadata, + + // FIXME: adding `#[must_use]` onto everything + // might just be more annoying than useful... + // although it is sometimes nice. + clippy::must_use_candidate, + + // TODO: should be removed after all `todo!()`'s are gone. + clippy::diverging_sub_expression, + + clippy::module_name_repetitions, + clippy::module_inception, + clippy::redundant_pub_crate, + clippy::option_if_let_else, +)] +// Allow some lints when running in debug mode. +#![cfg_attr(debug_assertions, allow(clippy::todo, clippy::multiple_crate_versions))] + +//---------------------------------------------------------------------------------------------------- Public API +// Import private modules, export public types. +// +// Documentation for each module is located in the respective file. + +mod types; +pub use types::{ + ExtendedBlockHeader, OutputOnChain, TransactionVerificationData, VerifiedBlockInformation, +}; + +//---------------------------------------------------------------------------------------------------- Feature-gated +cfg_if::cfg_if! { + if #[cfg(feature = "service")] { + pub mod service; + } +} + +//---------------------------------------------------------------------------------------------------- Private diff --git a/types/src/service.rs b/types/src/service.rs new file mode 100644 index 00000000..97344f64 --- /dev/null +++ b/types/src/service.rs @@ -0,0 +1,88 @@ +//! Database [`ReadRequest`]s, [`WriteRequest`]s, and [`Response`]s. + +//---------------------------------------------------------------------------------------------------- Import +use std::{ + collections::{HashMap, HashSet}, + ops::Range, +}; + +use monero_serai::{block::Block, transaction::Transaction}; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +use crate::types::{ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; + +//---------------------------------------------------------------------------------------------------- ReadRequest +/// A read request to the database. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +pub enum ReadRequest { + /// TODO + BlockExtendedHeader(u64), + /// TODO + BlockHash(u64), + /// TODO + BlockExtendedHeaderInRange(Range), + /// TODO + ChainHeight, + /// TODO + GeneratedCoins, + /// TODO + Outputs(HashMap>), + /// TODO + NumberOutputsWithAmount(Vec), + /// TODO + CheckKIsNotSpent(HashSet<[u8; 32]>), + /// TODO + BlockBatchInRange(Range), +} + +//---------------------------------------------------------------------------------------------------- WriteRequest +/// A write request to the database. +#[derive(Debug, Clone, PartialEq, Eq)] +// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +pub enum WriteRequest { + /// TODO + WriteBlock(VerifiedBlockInformation), +} + +//---------------------------------------------------------------------------------------------------- Response +/// A response from the database. +#[derive(Debug, Clone, PartialEq, Eq)] +// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +pub enum Response { + //------------------------------------------------------ Reads + /// TODO + BlockExtendedHeader(ExtendedBlockHeader), + /// TODO + BlockHash([u8; 32]), + /// TODO + BlockExtendedHeaderInRange(Vec), + /// TODO + ChainHeight(u64, [u8; 32]), + /// TODO + GeneratedCoins(u64), + /// TODO + Outputs(HashMap>), + /// TODO + NumberOutputsWithAmount(HashMap), + /// TODO + /// returns true if key images are spent + CheckKIsNotSpent(bool), + /// TODO + BlockBatchInRange(Vec<(Block, Vec)>), + + //------------------------------------------------------ Writes + /// TODO + WriteBlockOk, +} + +//---------------------------------------------------------------------------------------------------- Tests +#[cfg(test)] +mod test { + // use super::*; +} diff --git a/types/src/types.rs b/types/src/types.rs new file mode 100644 index 00000000..6532aec7 --- /dev/null +++ b/types/src/types.rs @@ -0,0 +1,103 @@ +//! TODO + +//---------------------------------------------------------------------------------------------------- Import +use std::sync::Arc; + +use curve25519_dalek::edwards::EdwardsPoint; +use monero_serai::{ + block::Block, + transaction::{Timelock, Transaction}, +}; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +//---------------------------------------------------------------------------------------------------- ExtendedBlockHeader +/// TODO +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +pub struct ExtendedBlockHeader { + /// TODO + /// This is a `cuprate_consensus::HardFork`. + pub version: u8, + /// TODO + /// This is a `cuprate_consensus::HardFork`. + pub vote: u8, + /// TODO + pub timestamp: u64, + /// TODO + pub cumulative_difficulty: u128, + /// TODO + pub block_weight: usize, + /// TODO + pub long_term_weight: usize, +} + +//---------------------------------------------------------------------------------------------------- TransactionVerificationData +/// TODO +#[derive(Clone, Debug, PartialEq, Eq)] +// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] // FIXME: monero_serai +// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +pub struct TransactionVerificationData { + /// TODO + pub tx: Transaction, + /// TODO + pub tx_blob: Vec, + /// TODO + pub tx_weight: usize, + /// TODO + pub fee: u64, + /// TODO + pub tx_hash: [u8; 32], +} + +//---------------------------------------------------------------------------------------------------- VerifiedBlockInformation +/// TODO +#[derive(Clone, Debug, PartialEq, Eq)] +// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] // FIXME: monero_serai +// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +pub struct VerifiedBlockInformation { + /// TODO + pub block: Block, + /// TODO + pub txs: Vec>, + /// TODO + pub block_hash: [u8; 32], + /// TODO + pub pow_hash: [u8; 32], + /// TODO + pub height: u64, + /// TODO + pub generated_coins: u64, + /// TODO + pub weight: usize, + /// TODO + pub long_term_weight: usize, + /// TODO + pub cumulative_difficulty: u128, +} + +//---------------------------------------------------------------------------------------------------- OutputOnChain +/// An already approved previous transaction output. +#[derive(Clone, Debug, PartialEq, Eq)] +// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] // FIXME: monero_serai +// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +pub struct OutputOnChain { + /// TODO + pub height: u64, + /// TODO + pub time_lock: Timelock, + /// TODO + pub key: Option, + /// TODO + pub commitment: EdwardsPoint, +} + +//---------------------------------------------------------------------------------------------------- Tests +#[cfg(test)] +mod test { + // use super::*; +}