Merge branch 'main' into db

This commit is contained in:
hinto.janai 2024-06-17 16:42:41 -04:00
commit 0b6bd2c3c0
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
12 changed files with 652 additions and 118 deletions

View file

@ -18,7 +18,7 @@ jobs:
steps: steps:
- name: Cache - name: Cache
uses: actions/cache@v3.2.3 uses: actions/cache@v4
with: with:
path: | path: |
~/.cargo ~/.cargo

View file

@ -83,7 +83,7 @@ jobs:
components: clippy components: clippy
- name: Cache - name: Cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: target path: target
key: ${{ matrix.os }} key: ${{ matrix.os }}

View file

@ -18,7 +18,7 @@ jobs:
steps: steps:
- name: Cache - name: Cache
uses: actions/cache@v3.2.3 uses: actions/cache@v4
with: with:
path: | path: |
~/.cargo ~/.cargo

View file

@ -1,45 +1,115 @@
# Contributing to Cuprate ## Contributing to Cuprate
Thank you for wanting to help out!
## Introduction Cuprate is in the stage where things are likely to change quickly, so it's recommended
you ask questions in our public [Matrix room](https://matrix.to/#/#cuprate:monero.social).
Thank you for wanting to help out! Cuprate is in the stage where things are likely to change quickly, so it's recommend - [1. Submitting a pull request](#1-submitting-a-pull-request)
you join our [Matrix room](https://matrix.to/#/#cuprate:monero.social). - [1.1 Rust toolchain](#11-rust-toolchain)
- [1.2 Draft PR](#12-draft-pr)
- [1.3 Passing CI](#13-passing-ci)
- [1.4 Ready for review](#14-ready-for-review)
- [2. Crate names](#2-crate-names)
- [3. Coding guidelines](#3-coding-guidelines)
- [4. Keeping track of issues and PRs](#4-keeping-track-of-issues-and-prs)
- [5. Documentation](#5-documentation)
- [6. Books](#6-books)
- [6.1 Architecture book](#61-architecture-book)
- [6.2 Protocol book](#62-protocol-book)
- [6.3 User book](#63-user-book)
## Making a PR ## 1. Submitting a pull request
Once you have found something you would like to work on by:
- Looking at the [open issues](https://github.com/Cuprate/cuprate/issues)
- Looking at issues with the [`A-help-wanted`](https://github.com/Cuprate/cuprate/issues?q=is%3Aissue+is%3Aopen+label%3AE-help-wanted) label
- or joining Cuprate's [Matrix room](https://matrix.to/#/#cuprate:monero.social) and asking
Once you have found something you would like to work on by either looking at the open issues or joining Cuprate's [Matrix room](https://matrix.to/#/#cuprate:monero.social) it is recommended to make your interest on working on that thing known so people don't duplicate work.
and asking it's recommended to make your interest on working on that thing known so people don't duplicate work.
When you are at a stage where you would like feedback you can open a draft PR, keep in mind that feedback may take time especially if the change is large. Before starting, consider reading/using Cuprate's:
Once your PR is at the stage where you feel it's ready to go, open it for review. - [`Documentation`](#5-documentation) (practical `cargo` docs)
- [`Books`](#6-books) (Cuprate's architecture and protocol)
## Passing CI These may answer some questions you have, or may confirm an issue you would like to fix.
The first 3 steps to CI are formatting, typo, and documentation checking.
Check if your changes are formatted, typo-free, and documented correctly by running: _Note: Cuprate is currently a work-in-progress; documentation will be changing/unfinished._
- `cargo fmt --all --check`
- `typos` ### 1.1 Rust toolchain
- `RUSTDOCFLAGS='-D warnings' cargo doc --workspace --all-features` Cuprate is written in [Rust](https://rust-lang.org).
If you are editing code, you will need Rust's toolchain and package manager,
[`cargo`](https://doc.rust-lang.org/cargo/index.html), to develop and submit PRs effectively.
Get started with Rust here: <https://www.rust-lang.org/learn/get-started>.
### 1.2 Draft PR
Consider opening a draft PR until you have passed all CI.
This is also the stage where you can ask for feedback from others. Keep in mind that feedback may take time especially if the change is large.
### 1.3 Passing CI
Each commit pushed in a PR will trigger our [lovely, yet pedantic CI](https://github.com/Cuprate/cuprate/blob/main/.github/workflows/ci.yml).
It currently:
- Checks code formatting
- Checks documentation
- Looks for typos
- Runs [`clippy`](https://github.com/rust-lang/rust-clippy) (and fails on warnings)
- Runs all tests
- Builds all targets
- Automatically add approriate [labels](#4-keeping-track-of-issues-and-prs) to your PR
Before pushing your code, please run the following at the root of the repository:
| Command | Does what |
|-------------------|-----------|
| `cargo fmt --all` | Formats code
| `typos -w` | Fixes typos
`typos` can be installed with `cargo` from: https://github.com/crate-ci/typos. `typos` can be installed with `cargo` from: https://github.com/crate-ci/typos.
After that, ensure all lints, tests, and builds are successful by running: After that, ensure all other CI passes by running:
- `cargo clippy --workspace --all-features --all-targets -- -D warnings` | Command | Does what |
- `cargo fmt --all` |------------------------------------------------------------------------|-----------|
- `cargo test --all-features --workspace` | `RUSTDOCFLAGS='-D warnings' cargo doc --workspace --all-features` | Checks documentation is OK
- `cargo build --all-features --all-targets --workspace` | `cargo clippy --workspace --all-features --all-targets -- -D warnings` | Checks clippy lints are satisfied
| `cargo test --all-features --workspace` | Runs all tests
| `cargo build --all-features --all-targets --workspace` | Builds all code
## Coding guidelines **Note: in order for some tests to work, you will need to place a [`monerod`](https://www.getmonero.org/downloads/) binary at the root of the repository.**
### 1.4 Ready for review
Once your PR has passed all CI and is ready to go, open it for review. Others will leave their thoughts and may ask for changes to be made.
Finally, if everything looks good, we will merge your code! Thank you for contributing!
## 2. Crate names
All of Cuprate's crates (libraries) are prefixed with `cuprate-`. All directories containing crates however, are not.
For example:
| Crate Directory | Crate Name |
|--------------------|--------------------|
| `storage/database` | `cuprate-database` |
| `net/levin` | `cuprate-levin` |
| `net/wire` | `cuprate-wire` |
## 3. Coding guidelines
This is a list of rules that are not mandated by any automation, but contributors generally follow.
You should keep these in mind when submitting code:
- Separate and sort imports as core, std, third-party, Cuprate crates, current crate
- Follow the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines)
- `// Comment like this.` and not `//like this` - `// Comment like this.` and not `//like this`
- Use `TODO` instead of `FIXME` - Use `TODO` instead of `FIXME`
- Avoid `unsafe` - Avoid `unsafe`
- 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 And the most important rule:
- Break any and all of the above rules when it makes sense
## 4. 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. 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. 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.
@ -65,7 +135,45 @@ This section is primarily targeted at maintainers. Most contributors aren't able
[O-]: https://github.com/Cuprate/cuprate/labels?q=O [O-]: https://github.com/Cuprate/cuprate/labels?q=O
[P-]: https://github.com/Cuprate/cuprate/labels?q=P [P-]: https://github.com/Cuprate/cuprate/labels?q=P
## Books ## 5. Documentation
Cuprate's crates (libraries) have inline documentation.
These can be built and viewed using the `cargo` tool. For example, to build and view a specific crate's documentation, run the following command at the repository's root:
```bash
cargo doc --open --package $CRATE
```
`$CRATE` can be any package listed in the [root `Cargo.toml`](https://github.com/Cuprate/cuprate/tree/main/Cargo.toml)'s workspace members list, for example, `cuprate-blockchain`.
You can also build all documentation at once:
```bash
cargo doc
```
and view by using a web-browser to open the `index.html` file within the build directory: `target/doc/$CRATE/index.html`, for example, `target/doc/cuprate_blockchain/index.html`.
## 6. Books
Cuprate has various documentation books whose source files live in [`books/`](https://github.com/Cuprate/cuprate/tree/main/books). Cuprate has various documentation books whose source files live in [`books/`](https://github.com/Cuprate/cuprate/tree/main/books).
Please contribute if you found a mistake! The files are mostly [markdown](https://wikipedia.org/wiki/Markdown) files and can be easily edited. See the `books/` directory for more information. Please contribute if you found a mistake! The files are mostly [markdown](https://wikipedia.org/wiki/Markdown) files and can be easily edited. See the `books/` directory for more information.
These books are also good resources to understand how Cuprate and Monero work.
### 6.1 Architecture book
This book documents Cuprate's architecture and implementation.
- <https://architecture.cuprate.org>
- <https://github.com/Cuprate/architecture-book>
- <https://github.com/Cuprate/cuprate/tree/main/books/architecture>
### 6.2 Protocol book
This book documents the Monero protocol.
- <https://monero-book.cuprate.org>
- <https://github.com/Cuprate/monero-book>
- <https://github.com/Cuprate/cuprate/tree/main/books/protocol>
### 6.3 User book
This book is a user-guide for using Cuprate.
- <https://user.cuprate.org>
- <https://github.com/Cuprate/user-book>
- <https://github.com/Cuprate/cuprate/tree/main/books/user>

331
Cargo.lock generated
View file

@ -118,9 +118,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.72" version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cc", "cc",
@ -317,9 +317,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.6" version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -327,9 +327,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.6" version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"clap_lex", "clap_lex",
@ -589,11 +589,15 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"cuprate-blockchain", "cuprate-blockchain",
"cuprate-consensus",
"cuprate-consensus-rules",
"cuprate-types", "cuprate-types",
"hex", "hex",
"hex-literal", "hex-literal",
"monero-serai",
"rayon", "rayon",
"sha3", "sha3",
"thiserror",
"tokio", "tokio",
"tokio-test", "tokio-test",
"tower", "tower",
@ -808,6 +812,17 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "displaydoc"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]] [[package]]
name = "doxygen-rs" name = "doxygen-rs"
version = "0.4.2" version = "0.4.2"
@ -1179,12 +1194,12 @@ dependencies = [
[[package]] [[package]]
name = "http-body-util" name = "http-body-util"
version = "0.1.1" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-util",
"http", "http",
"http-body", "http-body",
"pin-project-lite", "pin-project-lite",
@ -1192,9 +1207,9 @@ dependencies = [
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.8.0" version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545"
[[package]] [[package]]
name = "hyper" name = "hyper"
@ -1277,13 +1292,133 @@ dependencies = [
] ]
[[package]] [[package]]
name = "idna" name = "icu_collections"
version = "0.5.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
dependencies = [ dependencies = [
"unicode-bidi", "displaydoc",
"unicode-normalization", "yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_locid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
dependencies = [
"displaydoc",
"litemap",
"tinystr",
"writeable",
"zerovec",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
[[package]]
name = "icu_properties"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
[[package]]
name = "icu_provider"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]]
name = "idna"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
dependencies = [
"icu_normalizer",
"icu_properties",
"smallvec",
"utf8_iter",
] ]
[[package]] [[package]]
@ -1389,6 +1524,12 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "litemap"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
[[package]] [[package]]
name = "lmdb-master-sys" name = "lmdb-master-sys"
version = "0.2.1" version = "0.2.1"
@ -1620,9 +1761,9 @@ dependencies = [
[[package]] [[package]]
name = "object" name = "object"
version = "0.35.0" version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -1995,9 +2136,9 @@ dependencies = [
[[package]] [[package]]
name = "redb" name = "redb"
version = "2.1.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed7508e692a49b6b2290b56540384ccae9b1fb4d77065640b165835b56ffe3bb" checksum = "a6dd20d3cdeb9c7d2366a0b16b93b35b75aec15309fbeb7ce477138c9f68c8c0"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -2044,9 +2185,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.3" version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]] [[package]]
name = "ring" name = "ring"
@ -2093,9 +2234,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.23.9" version = "0.23.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a218f0f6d05669de4eabfb24f31ce802035c952429d037507b4a4a39f0e60c5b" checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"ring", "ring",
@ -2345,6 +2486,12 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "std-shims" name = "std-shims"
version = "0.1.1" version = "0.1.1"
@ -2403,6 +2550,17 @@ dependencies = [
"crossbeam-queue", "crossbeam-queue",
] ]
[[package]]
name = "synstructure"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]] [[package]]
name = "tap" name = "tap"
version = "1.0.1" version = "1.0.1"
@ -2461,20 +2619,15 @@ dependencies = [
] ]
[[package]] [[package]]
name = "tinyvec" name = "tinystr"
version = "1.6.0" version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
dependencies = [ dependencies = [
"tinyvec_macros", "displaydoc",
"zerovec",
] ]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.38.0" version = "1.38.0"
@ -2684,27 +2837,12 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"
@ -2713,15 +2851,27 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna",
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "valuable" name = "valuable"
version = "0.1.0" version = "0.1.0"
@ -3044,6 +3194,18 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "write16"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]] [[package]]
name = "wyz" name = "wyz"
version = "0.5.1" version = "0.5.1"
@ -3059,6 +3221,30 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "yoke"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
"synstructure",
]
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.34" version = "0.7.34"
@ -3079,6 +3265,27 @@ dependencies = [
"syn 2.0.66", "syn 2.0.66",
] ]
[[package]]
name = "zerofrom"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
"synstructure",
]
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.8.1" version = "1.8.1"
@ -3098,3 +3305,25 @@ dependencies = [
"quote", "quote",
"syn 2.0.66", "syn 2.0.66",
] ]
[[package]]
name = "zerovec"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c"
dependencies = [
"yoke",
"zerofrom",
"zerovec-derive",
]
[[package]]
name = "zerovec-derive"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]

View file

@ -1,16 +1,58 @@
![Cuprate](misc/logo/wordmark/CuprateWordmark.svg) <div align="center">
<img src="misc/logo/wordmark/CuprateWordmark.svg" width="50%"/>
An alternative Monero node implementation.
---- _(work-in-progress)_
> An up and coming Rust Monero node.
[![Matrix](https://img.shields.io/badge/Matrix-Cuprate-white?logo=matrix&labelColor=grey&logoColor=white)](https://matrix.to/#/#cuprate:monero.social) [![CI](https://github.com/Cuprate/cuprate/actions/workflows/ci.yml/badge.svg)](https://github.com/Cuprate/cuprate/actions/workflows/ci.yml) [![Matrix](https://img.shields.io/badge/Matrix-Cuprate-white?logo=matrix&labelColor=grey&logoColor=white)](https://matrix.to/#/#cuprate:monero.social) [![CI](https://github.com/Cuprate/cuprate/actions/workflows/ci.yml/badge.svg)](https://github.com/Cuprate/cuprate/actions/workflows/ci.yml)
Cuprate will be an alternative Monero node written from the ground up in Rust. It </div>
will be able to independently validate Monero consensus rules providing a layer of
security and redundancy for the Monero network.
Cuprate will help to protect the network from implementation bugs that could ## Contents
cause a variety of issues, plus because it's written in a memory safe language Cuprate - [About](#about)
will be less likely to suffer from memory safety issues compared to monerod. - [Documentation](#documentation)
- [Contributing](#contributing)
- [Security](#security)
- [License](#license)
<!--
TODO: add these sections someday.
- [Status](#status) // when we're near v1.0.0
- [Getting help](#getting-help) // issue tracker, user book, matrix channels, etc
- [Build](#build)
- [Windows](#windows)
- [macOS](#macOS)
- [Linux](#Linux)
-->
## About
Cuprate is an effort to create an alternative [Monero](https://getmonero.org) node implementation in [Rust](http://rust-lang.org).
It will be able to independently validate Monero consensus rules, providing a layer of security and redundancy for the Monero network.
<!-- TODO: add some details about what Cuprate is and is not, goals, status -->
## Documentation
_Cuprate is currently a work-in-progress; documentation will be changing/unfinished._
Cuprate maintains various documentation books:
| Book | Description |
|-----------------------------------------------------------------|------------------------------------------------------------|
| [Cuprate's architecture book](https://architecture.cuprate.org) | Documents Cuprate's internal architecture & implementation |
| [Cuprate's protocol book](https://monero-book.cuprate.org) | Documents the Monero protocol |
| [Cuprate's user book](https://user.cuprate.org) | Practical user-guide for using `cuprated` |
For crate (library) documentation, see the `Documentation` section in [`CONTRIBUTING.md`](CONTRIBUTING.md).
## Contributing
See [`CONTRIBUTING.md`](CONTRIBUTING.md).
## Security
Cuprate has a responsible vulnerability disclosure policy, see [`SECURITY.md`](SECURITY.md).
## License
The `binaries/` directory is licensed under AGPL-3.0, everything else is licensed under MIT.
See [`LICENSE`](LICENSE) for more details.

View file

@ -1,11 +1,15 @@
# Security Policy # Security Policy
## Supported Versions ## Reporting a vulnerability
If you have discovered a vulnerability within Cuprate, please do not open a GitHub issue or announce it publicly.
We only support the latest version available as it follows monero specifications and older client is therefore prohibited by the network. Please contact us directly by email using our PGP keys in the [`gpg_keys/`](misc/gpg_keys/) directory or via an encrypted Matrix channel.
## Reporting a Vulnerability Thanks for being quiet.
If you ever discover a vulnerability, please do not open a github issue. Contact us by mail directly using our pgp keys under the gpg_keys folder in the repository. We're also available on Matrix. ## Contact
You can also alert us using the *Report a Vulnerability* feature of Github. Thanks for being quiet. We'll always disclose the vulnerability after patching it and encourage everyone to fetch the Please disclose vulnerabilities to one of the trusted maintainers below:
security update.
| Trusted maintainer | PGP key | Email address | Matrix ID |
|--------------------|---------|---------------|-----------|
| [Boog900](https://github.com/Boog900) | [`boog900.asc`](misc/gpg_keys/boog900.asc) | `boog900@tutanota.com` | `@boog900:monero.social`

View file

@ -11,11 +11,15 @@ path = "src/create.rs"
[dependencies] [dependencies]
clap = { workspace = true, features = ["derive", "std"] } clap = { workspace = true, features = ["derive", "std"] }
cuprate-blockchain = { path = "../../storage/blockchain" } cuprate-blockchain = { path = "../../storage/blockchain" }
cuprate-consensus = { path = ".." }
cuprate-consensus-rules = { path = "../rules" }
cuprate-types = { path = "../../types" } cuprate-types = { path = "../../types" }
hex.workspace = true hex.workspace = true
hex-literal.workspace = true hex-literal.workspace = true
monero-serai.workspace = true
rayon.workspace = true rayon.workspace = true
sha3 = "0.10.8" sha3 = "0.10.8"
thiserror.workspace = true
tokio = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] }
tower.workspace = true tower.workspace = true

View file

@ -1,5 +1,6 @@
use std::{ use std::{
cmp, cmp,
collections::HashMap,
future::Future, future::Future,
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
@ -7,9 +8,21 @@ use std::{
#[allow(unused_imports)] #[allow(unused_imports)]
use hex_literal::hex; use hex_literal::hex;
use tower::Service; use monero_serai::{
block::Block,
transaction::{Input, Transaction},
};
use tower::{Service, ServiceExt};
use cuprate_consensus::{
context::{BlockChainContextRequest, BlockChainContextResponse},
transactions::TransactionVerificationData,
};
use cuprate_consensus_rules::{miner_tx::MinerTxError, ConsensusError};
use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation};
use crate::{hash_of_hashes, BlockId, HashOfHashes}; use crate::{hash_of_hashes, BlockId, HashOfHashes};
#[cfg(not(test))] #[cfg(not(test))]
static HASHES_OF_HASHES: &[HashOfHashes] = &include!("./data/hashes_of_hashes"); static HASHES_OF_HASHES: &[HashOfHashes] = &include!("./data/hashes_of_hashes");
@ -31,13 +44,6 @@ fn max_height() -> u64 {
(HASHES_OF_HASHES.len() * BATCH_SIZE) as u64 (HASHES_OF_HASHES.len() * BATCH_SIZE) as u64
} }
pub enum FastSyncRequest {
ValidateHashes {
start_height: u64,
block_ids: Vec<BlockId>,
},
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct ValidBlockId(BlockId); pub struct ValidBlockId(BlockId);
@ -45,31 +51,79 @@ fn valid_block_ids(block_ids: &[BlockId]) -> Vec<ValidBlockId> {
block_ids.iter().map(|b| ValidBlockId(*b)).collect() block_ids.iter().map(|b| ValidBlockId(*b)).collect()
} }
#[allow(clippy::large_enum_variant)]
pub enum FastSyncRequest {
ValidateHashes {
start_height: u64,
block_ids: Vec<BlockId>,
},
ValidateBlock {
block: Block,
txs: HashMap<[u8; 32], Transaction>,
token: ValidBlockId,
},
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum FastSyncResponse { pub enum FastSyncResponse {
ValidateHashes { ValidateHashes {
validated_hashes: Vec<ValidBlockId>, validated_hashes: Vec<ValidBlockId>,
unknown_hashes: Vec<BlockId>, unknown_hashes: Vec<BlockId>,
}, },
ValidateBlock(VerifiedBlockInformation),
} }
#[derive(Debug, PartialEq)] #[derive(thiserror::Error, Debug, PartialEq)]
pub enum FastSyncError { pub enum FastSyncError {
InvalidStartHeight, // start_height not a multiple of BATCH_SIZE #[error("Block does not match its expected hash")]
Mismatch, // hash does not match BlockHashMismatch,
NothingToDo, // no complete batch to check
OutOfRange, // start_height too high #[error("Start height must be a multiple of the batch size")]
InvalidStartHeight,
#[error("Hash of hashes mismatch")]
Mismatch,
#[error("Given range too small for fast sync (less than one batch)")]
NothingToDo,
#[error("Start height too high for fast sync")]
OutOfRange,
#[error("Block does not have the expected height entry")]
BlockHeightMismatch,
#[error("Block does not contain the expected transaction list")]
TxsIncludedWithBlockIncorrect,
#[error(transparent)]
Consensus(#[from] ConsensusError),
#[error(transparent)]
MinerTx(#[from] MinerTxError),
#[error("Database error: {0}")]
DbErr(String),
}
impl From<tower::BoxError> for FastSyncError {
fn from(error: tower::BoxError) -> Self {
Self::DbErr(error.to_string())
}
} }
#[allow(dead_code)]
pub struct FastSyncService<C> { pub struct FastSyncService<C> {
context_svc: C, context_svc: C,
} }
impl<C> FastSyncService<C> impl<C> FastSyncService<C>
where where
C: Service<FastSyncRequest, Response = FastSyncResponse, Error = FastSyncError> C: Service<
+ Clone BlockChainContextRequest,
Response = BlockChainContextResponse,
Error = tower::BoxError,
> + Clone
+ Send + Send
+ 'static, + 'static,
{ {
@ -81,8 +135,11 @@ where
impl<C> Service<FastSyncRequest> for FastSyncService<C> impl<C> Service<FastSyncRequest> for FastSyncService<C>
where where
C: Service<FastSyncRequest, Response = FastSyncResponse, Error = FastSyncError> C: Service<
+ Clone BlockChainContextRequest,
Response = BlockChainContextResponse,
Error = tower::BoxError,
> + Clone
+ Send + Send
+ 'static, + 'static,
C::Future: Send + 'static, C::Future: Send + 'static,
@ -97,12 +154,17 @@ where
} }
fn call(&mut self, req: FastSyncRequest) -> Self::Future { fn call(&mut self, req: FastSyncRequest) -> Self::Future {
let context_svc = self.context_svc.clone();
Box::pin(async move { Box::pin(async move {
match req { match req {
FastSyncRequest::ValidateHashes { FastSyncRequest::ValidateHashes {
start_height, start_height,
block_ids, block_ids,
} => validate_hashes(start_height, &block_ids).await, } => validate_hashes(start_height, &block_ids).await,
FastSyncRequest::ValidateBlock { block, txs, token } => {
validate_block(context_svc, block, txs, token).await
}
} }
}) })
} }
@ -149,6 +211,91 @@ async fn validate_hashes(
}) })
} }
async fn validate_block<C>(
mut context_svc: C,
block: Block,
mut txs: HashMap<[u8; 32], Transaction>,
token: ValidBlockId,
) -> Result<FastSyncResponse, FastSyncError>
where
C: Service<
BlockChainContextRequest,
Response = BlockChainContextResponse,
Error = tower::BoxError,
> + Send
+ 'static,
C::Future: Send + 'static,
{
let BlockChainContextResponse::Context(checked_context) = context_svc
.ready()
.await?
.call(BlockChainContextRequest::GetContext)
.await?
else {
panic!("Context service returned wrong response!");
};
let block_chain_ctx = checked_context.unchecked_blockchain_context().clone();
let block_hash = block.hash();
if block_hash != token.0 {
return Err(FastSyncError::BlockHashMismatch);
}
let block_blob = block.serialize();
let Some(Input::Gen(height)) = block.miner_tx.prefix.inputs.first() else {
return Err(FastSyncError::MinerTx(MinerTxError::InputNotOfTypeGen));
};
if *height != block_chain_ctx.chain_height {
return Err(FastSyncError::BlockHeightMismatch);
}
let mut verified_txs = Vec::with_capacity(txs.len());
for tx in &block.txs {
let tx = txs
.remove(tx)
.ok_or(FastSyncError::TxsIncludedWithBlockIncorrect)?;
let data = TransactionVerificationData::new(tx)?;
verified_txs.push(VerifiedTransactionInformation {
tx_blob: data.tx_blob,
tx_weight: data.tx_weight,
fee: data.fee,
tx_hash: data.tx_hash,
tx: data.tx,
});
}
let total_fees = verified_txs.iter().map(|tx| tx.fee).sum::<u64>();
let total_outputs = block
.miner_tx
.prefix
.outputs
.iter()
.map(|output| output.amount.unwrap_or(0))
.sum::<u64>();
let generated_coins = total_outputs - total_fees;
let weight =
block.miner_tx.weight() + verified_txs.iter().map(|tx| tx.tx_weight).sum::<usize>();
Ok(FastSyncResponse::ValidateBlock(VerifiedBlockInformation {
block_blob,
txs: verified_txs,
block_hash,
pow_hash: [0u8; 32],
height: *height,
generated_coins,
weight,
long_term_weight: block_chain_ctx.next_block_long_term_weight(weight),
cumulative_difficulty: block_chain_ctx.cumulative_difficulty
+ block_chain_ctx.next_difficulty,
block,
}))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -120,6 +120,7 @@ allow = [
# Font licenses. # Font licenses.
"Unicode-DFS-2016", # https://spdx.org/licenses/Unicode-DFS-2016.html "Unicode-DFS-2016", # https://spdx.org/licenses/Unicode-DFS-2016.html
"Unicode-3.0", # https://spdx.org/licenses/Unicode-3.0.html
# "LicenseRef-UFL-1.0", # https://tldrlegal.com/license/ubuntu-font-license,-1.0 # "LicenseRef-UFL-1.0", # https://tldrlegal.com/license/ubuntu-font-license,-1.0
# "OFL-1.1", # https://spdx.org/licenses/OFL-1.1.html # "OFL-1.1", # https://spdx.org/licenses/OFL-1.1.html
] ]

View file

@ -182,20 +182,20 @@ macro_rules! impl_u {
$( $(
impl From<$u> for Id { impl From<$u> for Id {
fn from(u: $u) -> Self { fn from(u: $u) -> Self {
Self::Num(u as u64) Self::Num(u64::from(u))
} }
} }
impl From<&$u> for Id { impl From<&$u> for Id {
fn from(u: &$u) -> Self { fn from(u: &$u) -> Self {
Self::Num(*u as u64) Self::Num(u64::from(*u))
} }
} }
impl From<Option<$u>> for Id { impl From<Option<$u>> for Id {
fn from(u: Option<$u>) -> Self { fn from(u: Option<$u>) -> Self {
match u { match u {
Some(u) => Self::Num(u as u64), Some(u) => Self::Num(u64::from(u)),
None => Self::Null, None => Self::Null,
} }
} }

View file

@ -1,6 +1,5 @@
//! Tests and utilities. //! Tests and utilities.
#![cfg(test)]
#![allow( #![allow(
clippy::unreadable_literal, clippy::unreadable_literal,
clippy::manual_string_new, clippy::manual_string_new,