diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml deleted file mode 100644 index 84b1995b..00000000 --- a/.github/workflows/audit.yml +++ /dev/null @@ -1,34 +0,0 @@ -# This runs `cargo audit` on all dependencies (only if Cargo deps changed) - -name: Audit - -on: - push: - paths: - - '**/Cargo.toml' - - '**/Cargo.lock' - workflow_dispatch: - -env: - CARGO_TERM_COLOR: always - -jobs: - audit: - - runs-on: ubuntu-latest - - steps: - - name: Cache - uses: actions/cache@v4 - with: - path: | - ~/.cargo - target - key: audit - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Install dependencies - run: cargo install cargo-audit --locked - - name: Audit - run: cargo audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c2271d5..367e8e14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -133,7 +133,12 @@ jobs: - name: Test run: | cargo test --all-features --workspace - cargo test --package cuprate-blockchain --no-default-features --features redb --features service + cargo test --package cuprate-blockchain --no-default-features --features redb + + - name: Hack Check + run: | + cargo install cargo-hack --locked + cargo hack --workspace check --feature-powerset --no-dev-deps # TODO: upload binaries with `actions/upload-artifact@v3` - name: Build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b66a58e..2d990601 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -120,12 +120,15 @@ Before pushing your code, please run the following at the root of the repository After that, ensure all other CI passes by running: -| Command | Does what | -|------------------------------------------------------------------------|-----------| -| `RUSTDOCFLAGS='-D warnings' cargo doc --workspace --all-features` | Checks documentation is OK -| `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 +| Command | Does what | +|------------------------------------------------------------------------|-------------------------------------------------------------------------| +| `RUSTDOCFLAGS='-D warnings' cargo doc --workspace --all-features` | Checks documentation is OK | +| `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 | +| `cargo hack --workspace check --feature-powerset --no-dev-deps` | Uses `cargo hack` to check our crates build with different features set | + +`cargo hack` can be installed with `cargo` from: https://github.com/taiki-e/cargo-hack. **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.** diff --git a/Cargo.lock b/Cargo.lock index 3d4aa692..9e07de02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -46,15 +46,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" [[package]] name = "arrayref" @@ -70,9 +70,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -81,24 +81,24 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -109,15 +109,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -141,7 +141,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tower 0.4.13", + "tower 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -162,7 +162,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", @@ -292,7 +292,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.77", + "syn", "syn_derive", ] @@ -304,22 +304,22 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -330,18 +330,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.1.21" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -372,9 +372,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -382,9 +382,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstyle", "clap_lex", @@ -392,14 +392,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -559,7 +559,7 @@ dependencies = [ "thiserror", "tokio", "tokio-util", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "tracing", ] @@ -599,7 +599,7 @@ dependencies = [ "tempfile", "thread_local", "tokio", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", ] [[package]] @@ -625,7 +625,7 @@ dependencies = [ "thread_local", "tokio", "tokio-test", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "tracing", ] @@ -645,7 +645,7 @@ dependencies = [ "thread_local", "tokio", "tokio-util", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "tracing", ] @@ -702,7 +702,7 @@ dependencies = [ "thiserror", "tokio", "tokio-util", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "tracing", ] @@ -732,7 +732,7 @@ dependencies = [ "futures", "rayon", "serde", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", ] [[package]] @@ -765,7 +765,7 @@ dependencies = [ "sha3", "thiserror", "tokio", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", ] [[package]] @@ -852,10 +852,18 @@ dependencies = [ "tokio-stream", "tokio-test", "tokio-util", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "tracing", ] +[[package]] +name = "cuprate-p2p-bucket" +version = "0.1.0" +dependencies = [ + "arrayvec", + "rand", +] + [[package]] name = "cuprate-p2p-core" version = "0.1.0" @@ -866,6 +874,7 @@ dependencies = [ "cuprate-helper", "cuprate-pruning", "cuprate-test-utils", + "cuprate-types", "cuprate-wire", "futures", "hex", @@ -875,7 +884,7 @@ dependencies = [ "tokio-stream", "tokio-test", "tokio-util", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "tracing", ] @@ -904,7 +913,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "ureq", ] @@ -966,7 +975,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", ] [[package]] @@ -1027,6 +1036,7 @@ dependencies = [ "cuprate-consensus", "cuprate-consensus-context", "cuprate-consensus-rules", + "cuprate-constants", "cuprate-cryptonight", "cuprate-dandelion-tower", "cuprate-database", @@ -1068,7 +1078,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "tower 0.5.1", + "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", "tracing", "tracing-subscriber", ] @@ -1099,7 +1109,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -1120,12 +1130,13 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.3" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", - "hashbrown", + "crossbeam-utils", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -1238,9 +1249,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -1282,9 +1293,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1296,9 +1307,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1306,44 +1317,44 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1380,9 +1391,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "groestl" @@ -1432,6 +1443,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "heck" version = "0.5.0" @@ -1533,9 +1550,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1545,9 +1562,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1584,9 +1601,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1597,7 +1614,6 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower 0.4.13", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", ] @@ -1637,12 +1653,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", ] [[package]] @@ -1664,9 +1680,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1688,15 +1704,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -1983,18 +1999,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl-probe" @@ -2089,7 +2105,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -2103,29 +2119,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2186,9 +2202,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2215,13 +2231,13 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" +checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -2326,18 +2342,18 @@ dependencies = [ [[package]] name = "redb" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4760ad04a88ef77075ba86ba9ea79b919e6bab29c1764c5747237cd6eaedcaa" +checksum = "84b1de48a7cf7ba193e81e078d17ee2b786236eed1d3f7c60f8a09545efc4925" dependencies = [ "libc", ] [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -2370,14 +2386,14 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" @@ -2411,9 +2427,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags 2.6.0", "errno", @@ -2424,9 +2440,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ "log", "once_cell", @@ -2452,19 +2468,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -2479,9 +2494,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rusty-fork" @@ -2503,9 +2518,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -2531,9 +2546,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -2553,9 +2568,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] @@ -2571,20 +2586,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -2724,7 +2739,7 @@ name = "std-shims" version = "0.1.1" source = "git+https://github.com/Cuprate/serai.git?rev=d5205ce#d5205ce2319e09414eb91d12cf38e83a08165f79" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", "spin", ] @@ -2747,7 +2762,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn", ] [[package]] @@ -2758,20 +2773,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c" dependencies = [ "proc-macro2", "quote", @@ -2787,7 +2791,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -2819,9 +2823,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -2832,22 +2836,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -2883,9 +2887,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -2907,7 +2911,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -2969,9 +2973,9 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "toml_datetime", @@ -2980,14 +2984,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tokio", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3052,7 +3056,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -3110,9 +3114,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -3208,9 +3212,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -3219,24 +3223,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3244,28 +3248,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "webpki-roots" -version = "0.26.5" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -3332,7 +3336,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -3343,7 +3347,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -3515,9 +3519,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -3555,7 +3559,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] [[package]] @@ -3575,5 +3579,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index c324e8d5..0f460e8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ members = [ "net/wire", "p2p/p2p", "p2p/p2p-core", + "p2p/bucket", "p2p/dandelion-tower", "p2p/async-buffer", "p2p/address-book", @@ -51,83 +52,84 @@ opt-level = 3 [workspace.dependencies] # Cuprate members -cuprate-fast-sync = { path = "consensus/fast-sync" ,default-features = false} -cuprate-consensus-rules = { path = "consensus/rules" ,default-features = false} -cuprate-constants = { path = "constants" ,default-features = false} -cuprate-consensus = { path = "consensus" ,default-features = false} -cuprate-consensus-context = { path = "consensus/context" ,default-features = false} -cuprate-cryptonight = { path = "cryptonight" ,default-features = false} -cuprate-helper = { path = "helper" ,default-features = false} -cuprate-epee-encoding = { path = "net/epee-encoding" ,default-features = false} -cuprate-fixed-bytes = { path = "net/fixed-bytes" ,default-features = false} -cuprate-levin = { path = "net/levin" ,default-features = false} -cuprate-wire = { path = "net/wire" ,default-features = false} -cuprate-p2p = { path = "p2p/p2p" ,default-features = false} -cuprate-p2p-core = { path = "p2p/p2p-core" ,default-features = false} -cuprate-dandelion-tower = { path = "p2p/dandelion-tower" ,default-features = false} -cuprate-async-buffer = { path = "p2p/async-buffer" ,default-features = false} -cuprate-address-book = { path = "p2p/address-book" ,default-features = false} -cuprate-blockchain = { path = "storage/blockchain" ,default-features = false} -cuprate-database = { path = "storage/database" ,default-features = false} -cuprate-database-service = { path = "storage/service" ,default-features = false} -cuprate-txpool = { path = "storage/txpool" ,default-features = false} -cuprate-pruning = { path = "pruning" ,default-features = false} -cuprate-test-utils = { path = "test-utils" ,default-features = false} -cuprate-types = { path = "types" ,default-features = false} -cuprate-json-rpc = { path = "rpc/json-rpc" ,default-features = false} -cuprate-rpc-types = { path = "rpc/types" ,default-features = false} -cuprate-rpc-interface = { path = "rpc/interface" ,default-features = false} +cuprate-fast-sync = { path = "consensus/fast-sync", default-features = false } +cuprate-consensus-rules = { path = "consensus/rules", default-features = false } +cuprate-constants = { path = "constants", default-features = false } +cuprate-consensus = { path = "consensus", default-features = false } +cuprate-consensus-context = { path = "consensus/context", default-features = false } +cuprate-cryptonight = { path = "cryptonight", default-features = false } +cuprate-helper = { path = "helper", default-features = false } +cuprate-epee-encoding = { path = "net/epee-encoding", default-features = false } +cuprate-fixed-bytes = { path = "net/fixed-bytes", default-features = false } +cuprate-levin = { path = "net/levin", default-features = false } +cuprate-wire = { path = "net/wire", default-features = false } +cuprate-p2p = { path = "p2p/p2p", default-features = false } +cuprate-p2p-core = { path = "p2p/p2p-core", default-features = false } +cuprate-p2p-bucket = { path = "p2p/p2p-bucket", default-features = false } +cuprate-dandelion-tower = { path = "p2p/dandelion-tower", default-features = false } +cuprate-async-buffer = { path = "p2p/async-buffer", default-features = false } +cuprate-address-book = { path = "p2p/address-book", default-features = false } +cuprate-blockchain = { path = "storage/blockchain", default-features = false } +cuprate-database = { path = "storage/database", default-features = false } +cuprate-database-service = { path = "storage/service", default-features = false } +cuprate-txpool = { path = "storage/txpool", default-features = false } +cuprate-pruning = { path = "pruning", default-features = false } +cuprate-test-utils = { path = "test-utils", default-features = false } +cuprate-types = { path = "types", default-features = false } +cuprate-json-rpc = { path = "rpc/json-rpc", default-features = false } +cuprate-rpc-types = { path = "rpc/types", default-features = false } +cuprate-rpc-interface = { path = "rpc/interface", default-features = false } # External dependencies -anyhow = { version = "1.0.89", default-features = false } -async-trait = { version = "0.1.82", default-features = false } -bitflags = { version = "2.6.0", default-features = false } +anyhow = { version = "1", default-features = false } +arrayvec = { version = "0.7", default-features = false } +async-trait = { version = "0.1", default-features = false } +bitflags = { version = "2", default-features = false } blake3 = { version = "1", default-features = false } -borsh = { version = "1.5.1", default-features = false } -bytemuck = { version = "1.18.0", default-features = false } -bytes = { version = "1.7.2", default-features = false } -cfg-if = { version = "1.0.0", default-features = false } -clap = { version = "4.5.17", default-features = false } -chrono = { version = "0.4.38", default-features = false } -crypto-bigint = { version = "0.5.5", default-features = false } -crossbeam = { version = "0.8.4", default-features = false } -const_format = { version = "0.2.33", default-features = false } -curve25519-dalek = { version = "4.1.3", default-features = false } -dashmap = { version = "5.5.3", default-features = false } -dirs = { version = "5.0.1", default-features = false } -futures = { version = "0.3.30", default-features = false } -hex = { version = "0.4.3", default-features = false } +borsh = { version = "1", default-features = false } +bytemuck = { version = "1", default-features = false } +bytes = { version = "1", default-features = false } +cfg-if = { version = "1", default-features = false } +clap = { version = "4", default-features = false } +chrono = { version = "0.4", default-features = false } +crypto-bigint = { version = "0.5", default-features = false } +crossbeam = { version = "0.8", default-features = false } +const_format = { version = "0.2", default-features = false } +curve25519-dalek = { version = "4", default-features = false } +dashmap = { version = "6", default-features = false } +dirs = { version = "5", default-features = false } +futures = { version = "0.3", default-features = false } +hex = { version = "0.4", default-features = false } hex-literal = { version = "0.4", default-features = false } -indexmap = { version = "2.5.0", default-features = false } +indexmap = { version = "2", default-features = false } monero-serai = { git = "https://github.com/Cuprate/serai.git", rev = "d5205ce", default-features = false } -paste = { version = "1.0.15", default-features = false } -pin-project = { version = "1.1.5", default-features = false } +paste = { version = "1", default-features = false } +pin-project = { version = "1", default-features = false } randomx-rs = { git = "https://github.com/Cuprate/randomx-rs.git", rev = "0028464", default-features = false } -rand = { version = "0.8.5", default-features = false } -rand_distr = { version = "0.4.3", default-features = false } -rayon = { version = "1.10.0", default-features = false } -serde_bytes = { version = "0.11.15", default-features = false } -serde_json = { version = "1.0.128", default-features = false } -serde = { version = "1.0.210", default-features = false } -sha3 = { version = "0.10.8", default-features = false } -strum = { version = "0.26.3", default-features = false } -thiserror = { version = "1.0.63", default-features = false } -thread_local = { version = "1.1.8", default-features = false } -tokio-util = { version = "0.7.12", default-features = false } -tokio-stream = { version = "0.1.16", default-features = false } -tokio = { version = "1.40.0", default-features = false } +rand = { version = "0.8", default-features = false } +rand_distr = { version = "0.4", default-features = false } +rayon = { version = "1", default-features = false } +serde_bytes = { version = "0.11", default-features = false } +serde_json = { version = "1", default-features = false } +serde = { version = "1", default-features = false } +strum = { version = "0.26", default-features = false } +thiserror = { version = "1", default-features = false } +thread_local = { version = "1", default-features = false } +tokio-util = { version = "0.7", default-features = false } +tokio-stream = { version = "0.1", default-features = false } +tokio = { version = "1", default-features = false } tower = { git = "https://github.com/Cuprate/tower.git", rev = "6c7faf0", default-features = false } # -tracing-subscriber = { version = "0.3.18", default-features = false } -tracing = { version = "0.1.40", default-features = false } +tracing-subscriber = { version = "0.3", default-features = false } +tracing = { version = "0.1", default-features = false } ## workspace.dev-dependencies monero-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "d5205ce" } monero-simple-request-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "d5205ce" } tempfile = { version = "3" } -pretty_assertions = { version = "1.4.1" } +pretty_assertions = { version = "1" } proptest = { version = "1" } -proptest-derive = { version = "0.4.0" } -tokio-test = { version = "0.4.4" } +proptest-derive = { version = "0.5" } +tokio-test = { version = "0.4" } ## TODO: ## Potential dependencies. diff --git a/binaries/cuprated/Cargo.toml b/binaries/cuprated/Cargo.toml index 880c2054..9ebdd780 100644 --- a/binaries/cuprated/Cargo.toml +++ b/binaries/cuprated/Cargo.toml @@ -9,31 +9,32 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/binaries/cuprated" [dependencies] # TODO: after v1.0.0, remove unneeded dependencies. -cuprate-consensus = { workspace = true } -cuprate-fast-sync = { workspace = true } +cuprate-consensus = { workspace = true } +cuprate-fast-sync = { workspace = true } cuprate-consensus-context = { workspace = true } -cuprate-consensus-rules = { workspace = true } -cuprate-cryptonight = { workspace = true } -cuprate-helper = { workspace = true } -cuprate-epee-encoding = { workspace = true } -cuprate-fixed-bytes = { workspace = true } -cuprate-levin = { workspace = true } -cuprate-wire = { workspace = true } -cuprate-p2p = { workspace = true } -cuprate-p2p-core = { workspace = true } -cuprate-dandelion-tower = { workspace = true, features = ["txpool"] } -cuprate-async-buffer = { workspace = true } -cuprate-address-book = { workspace = true } -cuprate-blockchain = { workspace = true, features = ["service"] } -cuprate-database-service = { workspace = true } -cuprate-txpool = { workspace = true } -cuprate-database = { workspace = true } -cuprate-pruning = { workspace = true } -cuprate-test-utils = { workspace = true } -cuprate-types = { workspace = true } -cuprate-json-rpc = { workspace = true } -cuprate-rpc-interface = { workspace = true } -cuprate-rpc-types = { workspace = true } +cuprate-consensus-rules = { workspace = true } +cuprate-constants = { workspace = true } +cuprate-cryptonight = { workspace = true } +cuprate-helper = { workspace = true } +cuprate-epee-encoding = { workspace = true } +cuprate-fixed-bytes = { workspace = true } +cuprate-levin = { workspace = true } +cuprate-wire = { workspace = true } +cuprate-p2p = { workspace = true } +cuprate-p2p-core = { workspace = true } +cuprate-dandelion-tower = { workspace = true, features = ["txpool"] } +cuprate-async-buffer = { workspace = true } +cuprate-address-book = { workspace = true } +cuprate-blockchain = { workspace = true } +cuprate-database-service = { workspace = true } +cuprate-txpool = { workspace = true } +cuprate-database = { workspace = true } +cuprate-pruning = { workspace = true } +cuprate-test-utils = { workspace = true } +cuprate-types = { workspace = true } +cuprate-json-rpc = { workspace = true } +cuprate-rpc-interface = { workspace = true } +cuprate-rpc-types = { workspace = true } # TODO: after v1.0.0, remove unneeded dependencies. anyhow = { workspace = true } diff --git a/binaries/cuprated/src/main.rs b/binaries/cuprated/src/main.rs index d3fe1f56..d5c832e2 100644 --- a/binaries/cuprated/src/main.rs +++ b/binaries/cuprated/src/main.rs @@ -9,6 +9,10 @@ unused_variables, clippy::needless_pass_by_value, clippy::unused_async, + clippy::diverging_sub_expression, + unused_mut, + clippy::let_unit_value, + clippy::needless_pass_by_ref_mut, reason = "TODO: remove after v1.0.0" )] diff --git a/binaries/cuprated/src/rpc.rs b/binaries/cuprated/src/rpc.rs index fe8e5f21..255d90d5 100644 --- a/binaries/cuprated/src/rpc.rs +++ b/binaries/cuprated/src/rpc.rs @@ -3,6 +3,7 @@ //! Will contain the code to initiate the RPC and a request handler. mod bin; +mod constants; mod handler; mod json; mod other; diff --git a/binaries/cuprated/src/rpc/constants.rs b/binaries/cuprated/src/rpc/constants.rs new file mode 100644 index 00000000..1236269d --- /dev/null +++ b/binaries/cuprated/src/rpc/constants.rs @@ -0,0 +1,5 @@ +//! Constants used within RPC. + +/// The string message used in RPC response fields for when +/// `cuprated` does not support a field that `monerod` has. +pub(super) const FIELD_NOT_SUPPORTED: &str = "`cuprated` does not support this field."; diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index af2e3f2c..1f73403b 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -8,6 +8,8 @@ use monero_serai::block::Block; use tower::Service; use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle}; +use cuprate_consensus::BlockChainContextService; +use cuprate_pruning::PruningSeed; use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ bin::{BinRequest, BinResponse}, @@ -15,6 +17,7 @@ use cuprate_rpc_types::{ other::{OtherRequest, OtherResponse}, }; use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle}; +use cuprate_types::{AddAuxPow, AuxPow, HardFork}; use crate::rpc::{bin, json, other}; @@ -54,6 +57,32 @@ pub enum BlockchainManagerRequest { /// The height of the next block in the chain. TargetHeight, + + /// Generate new blocks. + /// + /// This request is only for regtest, see RPC's `generateblocks`. + GenerateBlocks { + /// Number of the blocks to be generated. + amount_of_blocks: u64, + /// The previous block's hash. + prev_block: [u8; 32], + /// The starting value for the nonce. + starting_nonce: u32, + /// The address that will receive the coinbase reward. + wallet_address: String, + }, + + // // TODO: the below requests actually belong to the block downloader/syncer: + // // + // /// Get [`Span`] data. + // /// + // /// This is data that describes an active downloading process, + // /// if we are fully synced, this will return an empty [`Vec`]. + // Spans, + + // + /// Get the next [`PruningSeed`] needed for a pruned sync. + NextNeededPruningSeed, } /// TODO: use real type when public. @@ -69,6 +98,9 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::PopBlocks`] PopBlocks { new_height: usize }, + /// Response to [`BlockchainManagerRequest::Prune`] + Prune(PruningSeed), + /// Response to [`BlockchainManagerRequest::Pruned`] Pruned(bool), @@ -83,6 +115,19 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::TargetHeight`] TargetHeight { height: usize }, + + /// Response to [`BlockchainManagerRequest::GenerateBlocks`] + GenerateBlocks { + /// Hashes of the blocks generated. + blocks: Vec<[u8; 32]>, + /// The new top height. (TODO: is this correct?) + height: usize, + }, + + // /// Response to [`BlockchainManagerRequest::Spans`]. + // Spans(Vec>), + /// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`]. + NextNeededPruningSeed(PruningSeed), } /// TODO: use real type when public. @@ -102,6 +147,9 @@ pub struct CupratedRpcHandler { /// Read handle to the blockchain database. pub blockchain_read: BlockchainReadHandle, + /// Handle to the blockchain context service. + pub blockchain_context: BlockChainContextService, + /// Handle to the blockchain manager. pub blockchain_manager: BlockchainManagerHandle, @@ -117,6 +165,7 @@ impl CupratedRpcHandler { pub const fn new( restricted: bool, blockchain_read: BlockchainReadHandle, + blockchain_context: BlockChainContextService, blockchain_manager: BlockchainManagerHandle, txpool_read: TxpoolReadHandle, txpool_manager: std::convert::Infallible, @@ -124,6 +173,7 @@ impl CupratedRpcHandler { Self { restricted, blockchain_read, + blockchain_context, blockchain_manager, txpool_read, txpool_manager, diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 2aa58e84..6760a6c2 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -2,26 +2,33 @@ use std::convert::Infallible; -use anyhow::Error; +use anyhow::{anyhow, Error}; use tower::ServiceExt; use cuprate_helper::cast::usize_to_u64; use cuprate_p2p_core::{ services::{AddressBookRequest, AddressBookResponse}, + types::{BanState, ConnectionId}, AddressBook, NetworkZone, }; +use cuprate_pruning::PruningSeed; +use cuprate_rpc_types::misc::{ConnectionInfo, Span}; + +use crate::rpc::constants::FIELD_NOT_SUPPORTED; + +// FIXME: use `anyhow::Error` over `tower::BoxError` in address book. /// [`AddressBookRequest::PeerlistSize`] -pub(super) async fn peerlist_size( +pub(crate) async fn peerlist_size( address_book: &mut impl AddressBook, ) -> Result<(u64, u64), Error> { let AddressBookResponse::PeerlistSize { white, grey } = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::PeerlistSize) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -29,17 +36,74 @@ pub(super) async fn peerlist_size( Ok((usize_to_u64(white), usize_to_u64(grey))) } +/// [`AddressBookRequest::ConnectionInfo`] +pub(crate) async fn connection_info( + address_book: &mut impl AddressBook, +) -> Result, Error> { + let AddressBookResponse::ConnectionInfo(vec) = address_book + .ready() + .await + .map_err(|e| anyhow!(e))? + .call(AddressBookRequest::ConnectionInfo) + .await + .map_err(|e| anyhow!(e))? + else { + unreachable!(); + }; + + // FIXME: impl this map somewhere instead of inline. + let vec = vec + .into_iter() + .map(|info| { + let (ip, port) = match info.socket_addr { + Some(socket) => (socket.ip().to_string(), socket.port().to_string()), + None => (String::new(), String::new()), + }; + + ConnectionInfo { + address: info.address.to_string(), + address_type: info.address_type, + avg_download: info.avg_download, + avg_upload: info.avg_upload, + connection_id: String::from(ConnectionId::DEFAULT_STR), + current_download: info.current_download, + current_upload: info.current_upload, + height: info.height, + host: info.host, + incoming: info.incoming, + ip, + live_time: info.live_time, + localhost: info.localhost, + local_ip: info.local_ip, + peer_id: hex::encode(info.peer_id.to_ne_bytes()), + port, + pruning_seed: info.pruning_seed.compress(), + recv_count: info.recv_count, + recv_idle_time: info.recv_idle_time, + rpc_credits_per_hash: info.rpc_credits_per_hash, + rpc_port: info.rpc_port, + send_count: info.send_count, + send_idle_time: info.send_idle_time, + state: info.state, + support_flags: info.support_flags, + } + }) + .collect(); + + Ok(vec) +} + /// [`AddressBookRequest::ConnectionCount`] -pub(super) async fn connection_count( +pub(crate) async fn connection_count( address_book: &mut impl AddressBook, ) -> Result<(u64, u64), Error> { let AddressBookResponse::ConnectionCount { incoming, outgoing } = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::ConnectionCount) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -48,17 +112,17 @@ pub(super) async fn connection_count( } /// [`AddressBookRequest::SetBan`] -pub(super) async fn set_ban( +pub(crate) async fn set_ban( address_book: &mut impl AddressBook, - peer: cuprate_p2p_core::ban::SetBan, + set_ban: cuprate_p2p_core::types::SetBan, ) -> Result<(), Error> { let AddressBookResponse::Ok = address_book .ready() .await - .expect("TODO") - .call(AddressBookRequest::SetBan(peer)) + .map_err(|e| anyhow!(e))? + .call(AddressBookRequest::SetBan(set_ban)) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -67,17 +131,17 @@ pub(super) async fn set_ban( } /// [`AddressBookRequest::GetBan`] -pub(super) async fn get_ban( +pub(crate) async fn get_ban( address_book: &mut impl AddressBook, peer: Z::Addr, ) -> Result, Error> { let AddressBookResponse::GetBan { unban_instant } = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::GetBan(peer)) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -86,19 +150,19 @@ pub(super) async fn get_ban( } /// [`AddressBookRequest::GetBans`] -pub(super) async fn get_bans( +pub(crate) async fn get_bans( address_book: &mut impl AddressBook, -) -> Result<(), Error> { +) -> Result>, Error> { let AddressBookResponse::GetBans(bans) = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::GetBans) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; - Ok(todo!()) + Ok(bans) } diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs index 8af80e50..97c7f48b 100644 --- a/binaries/cuprated/src/rpc/request/blockchain.rs +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -1,24 +1,61 @@ //! Functions for [`BlockchainReadRequest`]. use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeMap, HashMap, HashSet}, ops::Range, }; use anyhow::Error; -use cuprate_blockchain::service::BlockchainReadHandle; +use monero_serai::block::Block; use tower::{Service, ServiceExt}; +use cuprate_blockchain::{service::BlockchainReadHandle, types::AltChainInfo}; use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, - Chain, CoinbaseTxSum, ExtendedBlockHeader, MinerData, OutputHistogramEntry, - OutputHistogramInput, OutputOnChain, + Chain, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, HardFork, MinerData, + OutputHistogramEntry, OutputHistogramInput, OutputOnChain, }; +/// [`BlockchainReadRequest::Block`]. +pub(crate) async fn block( + blockchain_read: &mut BlockchainReadHandle, + height: u64, +) -> Result { + let BlockchainResponse::Block(block) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::Block { + height: u64_to_usize(height), + }) + .await? + else { + unreachable!(); + }; + + Ok(block) +} + +/// [`BlockchainReadRequest::BlockByHash`]. +pub(crate) async fn block_by_hash( + blockchain_read: &mut BlockchainReadHandle, + hash: [u8; 32], +) -> Result { + let BlockchainResponse::Block(block) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::BlockByHash(hash)) + .await? + else { + unreachable!(); + }; + + Ok(block) +} + /// [`BlockchainReadRequest::BlockExtendedHeader`]. -pub(super) async fn block_extended_header( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn block_extended_header( + blockchain_read: &mut BlockchainReadHandle, height: u64, ) -> Result { let BlockchainResponse::BlockExtendedHeader(header) = blockchain_read @@ -36,8 +73,8 @@ pub(super) async fn block_extended_header( } /// [`BlockchainReadRequest::BlockHash`]. -pub(super) async fn block_hash( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn block_hash( + blockchain_read: &mut BlockchainReadHandle, height: u64, chain: Chain, ) -> Result<[u8; 32], Error> { @@ -57,8 +94,8 @@ pub(super) async fn block_hash( } /// [`BlockchainReadRequest::FindBlock`]. -pub(super) async fn find_block( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn find_block( + blockchain_read: &mut BlockchainReadHandle, block_hash: [u8; 32], ) -> Result, Error> { let BlockchainResponse::FindBlock(option) = blockchain_read @@ -74,8 +111,8 @@ pub(super) async fn find_block( } /// [`BlockchainReadRequest::FilterUnknownHashes`]. -pub(super) async fn filter_unknown_hashes( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn filter_unknown_hashes( + blockchain_read: &mut BlockchainReadHandle, block_hashes: HashSet<[u8; 32]>, ) -> Result, Error> { let BlockchainResponse::FilterUnknownHashes(output) = blockchain_read @@ -91,8 +128,8 @@ pub(super) async fn filter_unknown_hashes( } /// [`BlockchainReadRequest::BlockExtendedHeaderInRange`] -pub(super) async fn block_extended_header_in_range( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn block_extended_header_in_range( + blockchain_read: &mut BlockchainReadHandle, range: Range, chain: Chain, ) -> Result, Error> { @@ -111,8 +148,8 @@ pub(super) async fn block_extended_header_in_range( } /// [`BlockchainReadRequest::ChainHeight`]. -pub(super) async fn chain_height( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn chain_height( + blockchain_read: &mut BlockchainReadHandle, ) -> Result<(u64, [u8; 32]), Error> { let BlockchainResponse::ChainHeight(height, hash) = blockchain_read .ready() @@ -127,8 +164,8 @@ pub(super) async fn chain_height( } /// [`BlockchainReadRequest::GeneratedCoins`]. -pub(super) async fn generated_coins( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn generated_coins( + blockchain_read: &mut BlockchainReadHandle, block_height: u64, ) -> Result { let BlockchainResponse::GeneratedCoins(generated_coins) = blockchain_read @@ -146,8 +183,8 @@ pub(super) async fn generated_coins( } /// [`BlockchainReadRequest::Outputs`] -pub(super) async fn outputs( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn outputs( + blockchain_read: &mut BlockchainReadHandle, outputs: HashMap>, ) -> Result>, Error> { let BlockchainResponse::Outputs(outputs) = blockchain_read @@ -163,8 +200,8 @@ pub(super) async fn outputs( } /// [`BlockchainReadRequest::NumberOutputsWithAmount`] -pub(super) async fn number_outputs_with_amount( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn number_outputs_with_amount( + blockchain_read: &mut BlockchainReadHandle, output_amounts: Vec, ) -> Result, Error> { let BlockchainResponse::NumberOutputsWithAmount(map) = blockchain_read @@ -182,8 +219,8 @@ pub(super) async fn number_outputs_with_amount( } /// [`BlockchainReadRequest::KeyImagesSpent`] -pub(super) async fn key_images_spent( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn key_images_spent( + blockchain_read: &mut BlockchainReadHandle, key_images: HashSet<[u8; 32]>, ) -> Result { let BlockchainResponse::KeyImagesSpent(is_spent) = blockchain_read @@ -199,8 +236,8 @@ pub(super) async fn key_images_spent( } /// [`BlockchainReadRequest::CompactChainHistory`] -pub(super) async fn compact_chain_history( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn compact_chain_history( + blockchain_read: &mut BlockchainReadHandle, ) -> Result<(Vec<[u8; 32]>, u128), Error> { let BlockchainResponse::CompactChainHistory { block_ids, @@ -218,8 +255,8 @@ pub(super) async fn compact_chain_history( } /// [`BlockchainReadRequest::FindFirstUnknown`] -pub(super) async fn find_first_unknown( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn find_first_unknown( + blockchain_read: &mut BlockchainReadHandle, hashes: Vec<[u8; 32]>, ) -> Result, Error> { let BlockchainResponse::FindFirstUnknown(resp) = blockchain_read @@ -235,8 +272,8 @@ pub(super) async fn find_first_unknown( } /// [`BlockchainReadRequest::TotalTxCount`] -pub(super) async fn total_tx_count( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn total_tx_count( + blockchain_read: &mut BlockchainReadHandle, ) -> Result { let BlockchainResponse::TotalTxCount(tx_count) = blockchain_read .ready() @@ -251,8 +288,8 @@ pub(super) async fn total_tx_count( } /// [`BlockchainReadRequest::DatabaseSize`] -pub(super) async fn database_size( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn database_size( + blockchain_read: &mut BlockchainReadHandle, ) -> Result<(u64, u64), Error> { let BlockchainResponse::DatabaseSize { database_size, @@ -270,8 +307,8 @@ pub(super) async fn database_size( } /// [`BlockchainReadRequest::OutputHistogram`] -pub(super) async fn output_histogram( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn output_histogram( + blockchain_read: &mut BlockchainReadHandle, input: OutputHistogramInput, ) -> Result, Error> { let BlockchainResponse::OutputHistogram(histogram) = blockchain_read @@ -287,8 +324,8 @@ pub(super) async fn output_histogram( } /// [`BlockchainReadRequest::CoinbaseTxSum`] -pub(super) async fn coinbase_tx_sum( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn coinbase_tx_sum( + blockchain_read: &mut BlockchainReadHandle, height: u64, count: u64, ) -> Result { @@ -306,3 +343,35 @@ pub(super) async fn coinbase_tx_sum( Ok(sum) } + +/// [`BlockchainReadRequest::AltChains`] +pub(crate) async fn alt_chains( + blockchain_read: &mut BlockchainReadHandle, +) -> Result, Error> { + let BlockchainResponse::AltChains(vec) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::AltChains) + .await? + else { + unreachable!(); + }; + + Ok(vec) +} + +/// [`BlockchainReadRequest::AltChainCount`] +pub(crate) async fn alt_chain_count( + blockchain_read: &mut BlockchainReadHandle, +) -> Result { + let BlockchainResponse::AltChainCount(count) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::AltChainCount) + .await? + else { + unreachable!(); + }; + + Ok(usize_to_u64(count)) +} diff --git a/binaries/cuprated/src/rpc/request/blockchain_context.rs b/binaries/cuprated/src/rpc/request/blockchain_context.rs index 2b14d467..c6f0f225 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_context.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_context.rs @@ -2,27 +2,30 @@ use std::convert::Infallible; -use anyhow::Error; +use anyhow::{anyhow, Error}; +use monero_serai::block::Block; use tower::{Service, ServiceExt}; use cuprate_consensus_context::{ BlockChainContext, BlockChainContextRequest, BlockChainContextResponse, BlockChainContextService, }; +use cuprate_helper::cast::u64_to_usize; use cuprate_types::{FeeEstimate, HardFork, HardForkInfo}; +// FIXME: use `anyhow::Error` over `tower::BoxError` in blockchain context. + /// [`BlockChainContextRequest::Context`]. -pub(super) async fn context( - service: &mut BlockChainContextService, - height: u64, +pub(crate) async fn context( + blockchain_context: &mut BlockChainContextService, ) -> Result { - let BlockChainContextResponse::Context(context) = service + let BlockChainContextResponse::Context(context) = blockchain_context .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(BlockChainContextRequest::Context) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -31,17 +34,17 @@ pub(super) async fn context( } /// [`BlockChainContextRequest::HardForkInfo`]. -pub(super) async fn hard_fork_info( - service: &mut BlockChainContextService, +pub(crate) async fn hard_fork_info( + blockchain_context: &mut BlockChainContextService, hard_fork: HardFork, ) -> Result { - let BlockChainContextResponse::HardForkInfo(hf_info) = service + let BlockChainContextResponse::HardForkInfo(hf_info) = blockchain_context .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(BlockChainContextRequest::HardForkInfo(hard_fork)) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -50,20 +53,47 @@ pub(super) async fn hard_fork_info( } /// [`BlockChainContextRequest::FeeEstimate`]. -pub(super) async fn fee_estimate( - service: &mut BlockChainContextService, +pub(crate) async fn fee_estimate( + blockchain_context: &mut BlockChainContextService, grace_blocks: u64, ) -> Result { - let BlockChainContextResponse::FeeEstimate(fee) = service + let BlockChainContextResponse::FeeEstimate(fee) = blockchain_context .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(BlockChainContextRequest::FeeEstimate { grace_blocks }) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; Ok(fee) } + +/// [`BlockChainContextRequest::CalculatePow`] +pub(crate) async fn calculate_pow( + blockchain_context: &mut BlockChainContextService, + hardfork: HardFork, + height: u64, + block: Box, + seed_hash: [u8; 32], +) -> Result<[u8; 32], Error> { + let BlockChainContextResponse::CalculatePow(hash) = blockchain_context + .ready() + .await + .map_err(|e| anyhow!(e))? + .call(BlockChainContextRequest::CalculatePow { + hardfork, + height: u64_to_usize(height), + block, + seed_hash, + }) + .await + .map_err(|e| anyhow!(e))? + else { + unreachable!(); + }; + + Ok(hash) +} diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 4dc91c82..18b75deb 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -5,13 +5,18 @@ use monero_serai::block::Block; use tower::{Service, ServiceExt}; use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; +use cuprate_p2p_core::{types::ConnectionId, NetworkZone}; +use cuprate_pruning::PruningSeed; +use cuprate_rpc_types::misc::Span; +use cuprate_types::{AddAuxPow, AuxPow, HardFork}; -use crate::rpc::handler::{ - BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse, +use crate::rpc::{ + constants::FIELD_NOT_SUPPORTED, + handler::{BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse}, }; /// [`BlockchainManagerRequest::PopBlocks`] -pub(super) async fn pop_blocks( +pub(crate) async fn pop_blocks( blockchain_manager: &mut BlockchainManagerHandle, amount: u64, ) -> Result { @@ -30,8 +35,10 @@ pub(super) async fn pop_blocks( } /// [`BlockchainManagerRequest::Prune`] -pub(super) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> { - let BlockchainManagerResponse::Ok = blockchain_manager +pub(crate) async fn prune( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::Prune(seed) = blockchain_manager .ready() .await? .call(BlockchainManagerRequest::Prune) @@ -40,11 +47,11 @@ pub(super) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> R unreachable!(); }; - Ok(()) + Ok(seed) } /// [`BlockchainManagerRequest::Pruned`] -pub(super) async fn pruned( +pub(crate) async fn pruned( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Pruned(pruned) = blockchain_manager @@ -60,7 +67,7 @@ pub(super) async fn pruned( } /// [`BlockchainManagerRequest::RelayBlock`] -pub(super) async fn relay_block( +pub(crate) async fn relay_block( blockchain_manager: &mut BlockchainManagerHandle, block: Block, ) -> Result<(), Error> { @@ -77,7 +84,7 @@ pub(super) async fn relay_block( } /// [`BlockchainManagerRequest::Syncing`] -pub(super) async fn syncing( +pub(crate) async fn syncing( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Syncing(syncing) = blockchain_manager @@ -93,7 +100,7 @@ pub(super) async fn syncing( } /// [`BlockchainManagerRequest::Synced`] -pub(super) async fn synced( +pub(crate) async fn synced( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Synced(syncing) = blockchain_manager @@ -109,7 +116,7 @@ pub(super) async fn synced( } /// [`BlockchainManagerRequest::Target`] -pub(super) async fn target( +pub(crate) async fn target( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Target(target) = blockchain_manager @@ -125,7 +132,7 @@ pub(super) async fn target( } /// [`BlockchainManagerRequest::TargetHeight`] -pub(super) async fn target_height( +pub(crate) async fn target_height( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::TargetHeight { height } = blockchain_manager @@ -139,3 +146,76 @@ pub(super) async fn target_height( Ok(usize_to_u64(height)) } + +/// [`BlockchainManagerRequest::GenerateBlocks`] +pub(crate) async fn generate_blocks( + blockchain_manager: &mut BlockchainManagerHandle, + amount_of_blocks: u64, + prev_block: [u8; 32], + starting_nonce: u32, + wallet_address: String, +) -> Result<(Vec<[u8; 32]>, u64), Error> { + let BlockchainManagerResponse::GenerateBlocks { blocks, height } = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::GenerateBlocks { + amount_of_blocks, + prev_block, + starting_nonce, + wallet_address, + }) + .await? + else { + unreachable!(); + }; + + Ok((blocks, usize_to_u64(height))) +} + +// [`BlockchainManagerRequest::Spans`] +pub(crate) async fn spans( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result, Error> { + // let BlockchainManagerResponse::Spans(vec) = blockchain_manager + // .ready() + // .await? + // .call(BlockchainManagerRequest::Spans) + // .await? + // else { + // unreachable!(); + // }; + + let vec: Vec> = todo!(); + + // FIXME: impl this map somewhere instead of inline. + let vec = vec + .into_iter() + .map(|span| Span { + connection_id: String::from(ConnectionId::DEFAULT_STR), + nblocks: span.nblocks, + rate: span.rate, + remote_address: span.remote_address.to_string(), + size: span.size, + speed: span.speed, + start_block_height: span.start_block_height, + }) + .collect(); + + Ok(vec) +} + +/// [`BlockchainManagerRequest::NextNeededPruningSeed`] +pub(crate) async fn next_needed_pruning_seed( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::NextNeededPruningSeed(seed) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::NextNeededPruningSeed) + .await? + else { + unreachable!(); + }; + + Ok(seed) +} diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs index a36778eb..eadbb23d 100644 --- a/binaries/cuprated/src/rpc/request/txpool.rs +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -2,7 +2,7 @@ use std::convert::Infallible; -use anyhow::Error; +use anyhow::{anyhow, Error}; use tower::{Service, ServiceExt}; use cuprate_helper::cast::usize_to_u64; @@ -14,15 +14,17 @@ use cuprate_txpool::{ TxEntry, }; +// FIXME: use `anyhow::Error` over `tower::BoxError` in txpool. + /// [`TxpoolReadRequest::Backlog`] -pub(super) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result, Error> { +pub(crate) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result, Error> { let TxpoolReadResponse::Backlog(tx_entries) = txpool_read .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(TxpoolReadRequest::Backlog) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -31,14 +33,19 @@ pub(super) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result Result { +pub(crate) async fn size( + txpool_read: &mut TxpoolReadHandle, + include_sensitive_txs: bool, +) -> Result { let TxpoolReadResponse::Size(size) = txpool_read .ready() .await - .expect("TODO") - .call(TxpoolReadRequest::Size) + .map_err(|e| anyhow!(e))? + .call(TxpoolReadRequest::Size { + include_sensitive_txs, + }) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -47,9 +54,17 @@ pub(super) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result, +) -> Result<(), Error> { + todo!(); + Ok(()) +} + +/// TODO +pub(crate) async fn relay( + txpool_manager: &mut Infallible, tx_hashes: Vec<[u8; 32]>, ) -> Result<(), Error> { todo!(); diff --git a/books/architecture/src/appendix/crates.md b/books/architecture/src/appendix/crates.md index fe8f1f05..ac2780e1 100644 --- a/books/architecture/src/appendix/crates.md +++ b/books/architecture/src/appendix/crates.md @@ -35,6 +35,7 @@ cargo doc --open --package cuprate-blockchain | [`cuprate-async-buffer`](https://doc.cuprate.org/cuprate_async_buffer) | [`p2p/async-buffer/`](https://github.com/Cuprate/cuprate/tree/main/p2p/async-buffer) | A bounded SPSC, FIFO, asynchronous buffer that supports arbitrary weights for values | [`cuprate-dandelion-tower`](https://doc.cuprate.org/cuprate_dandelion_tower) | [`p2p/dandelion-tower/`](https://github.com/Cuprate/cuprate/tree/main/p2p/dandelion-tower) | TODO | [`cuprate-p2p`](https://doc.cuprate.org/cuprate_p2p) | [`p2p/p2p/`](https://github.com/Cuprate/cuprate/tree/main/p2p/p2p) | TODO +| [`cuprate-p2p-bucket`](https://doc.cuprate.org/cuprate_p2p_bucket) | [`p2p/bucket/`](https://github.com/Cuprate/cuprate/tree/main/p2p/bucket) | A collection data structure discriminating its items into "buckets" of limited size. | [`cuprate-p2p-core`](https://doc.cuprate.org/cuprate_p2p_core) | [`p2p/p2p-core/`](https://github.com/Cuprate/cuprate/tree/main/p2p/p2p-core) | TODO ## Storage diff --git a/consensus/context/src/lib.rs b/consensus/context/src/lib.rs index 198d5a1d..acc4d23d 100644 --- a/consensus/context/src/lib.rs +++ b/consensus/context/src/lib.rs @@ -18,6 +18,7 @@ use std::{ }; use futures::{channel::oneshot, FutureExt}; +use monero_serai::block::Block; use tokio::sync::mpsc; use tokio_util::sync::PollSender; use tower::Service; @@ -267,6 +268,21 @@ pub enum BlockChainContextRequest { grace_blocks: u64, }, + /// Calculate proof-of-work for this block. + CalculatePow { + /// The hardfork of the protocol at this block height. + hardfork: HardFork, + /// The height of the block. + height: usize, + /// The block data. + /// + /// This is boxed because [`Block`] causes this enum to be 1200 bytes, + /// where the 2nd variant is only 96 bytes. + block: Box, + /// The seed hash for the proof-of-work. + seed_hash: [u8; 32], + }, + /// Clear the alt chain context caches. ClearAltCache, @@ -364,6 +380,9 @@ pub enum BlockChainContextResponse { /// Response to [`BlockChainContextRequest::FeeEstimate`] FeeEstimate(FeeEstimate), + /// Response to [`BlockChainContextRequest::CalculatePow`] + CalculatePow([u8; 32]), + /// Response to [`BlockChainContextRequest::AltChains`] /// /// If the inner [`Vec::is_empty`], there were no alternate chains. diff --git a/consensus/context/src/task.rs b/consensus/context/src/task.rs index 65cfea99..b0759952 100644 --- a/consensus/context/src/task.rs +++ b/consensus/context/src/task.rs @@ -324,7 +324,8 @@ impl ContextTask { } BlockChainContextRequest::HardForkInfo(_) | BlockChainContextRequest::FeeEstimate { .. } - | BlockChainContextRequest::AltChains => { + | BlockChainContextRequest::AltChains + | BlockChainContextRequest::CalculatePow { .. } => { todo!("finish https://github.com/Cuprate/cuprate/pull/297") } }) diff --git a/consensus/src/tests/mock_db.rs b/consensus/src/tests/mock_db.rs index 5ca53d84..bf005d2f 100644 --- a/consensus/src/tests/mock_db.rs +++ b/consensus/src/tests/mock_db.rs @@ -1,5 +1,3 @@ -#![expect(non_local_definitions, reason = "proptest macro")] - use std::{ future::Future, pin::Pin, diff --git a/deny.toml b/deny.toml index f469d062..e54d1161 100644 --- a/deny.toml +++ b/deny.toml @@ -81,6 +81,9 @@ ignore = [ #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish #{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" }, + + # TODO: check this is sorted before a beta release. + { id = "RUSTSEC-2024-0370", reason = "unmaintained crate, not necessarily vulnerable yet." } ] # If this is true, then cargo deny will use the git executable to fetch advisory database. # If this is false, then it uses a built-in git library. @@ -110,6 +113,7 @@ allow = [ "Apache-2.0", # https://tldrlegal.com/license/apache-license-2.0-(apache-2.0) "MPL-2.0", # https://www.mozilla.org/en-US/MPL/2.0/FAQ/ "BSL-1.0", # https://tldrlegal.com/license/boost-software-license-1.0-explained + "Zlib", # https://spdx.org/licenses/Zlib.html # OpenSSL 3.0+ uses Apache-2.0 # OpenSSL 1.x.x uses https://www.openssl.org/source/license-openssl-ssleay.txt diff --git a/helper/Cargo.toml b/helper/Cargo.toml index ad78a448..1b3158f1 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -17,7 +17,7 @@ asynch = ["dep:futures", "dep:rayon"] cast = [] constants = [] crypto = ["dep:curve25519-dalek", "dep:monero-serai", "std"] -fs = ["dep:dirs"] +fs = ["dep:dirs", "std"] num = [] map = ["cast", "dep:monero-serai", "dep:cuprate-constants"] time = ["dep:chrono", "std"] diff --git a/helper/src/cast.rs b/helper/src/cast.rs index 99b7f53e..5628d7d6 100644 --- a/helper/src/cast.rs +++ b/helper/src/cast.rs @@ -18,7 +18,6 @@ // // //============================ SAFETY: DO NOT REMOVE ===========================// -//---------------------------------------------------------------------------------------------------- Free functions /// Cast [`u64`] to [`usize`]. #[inline(always)] pub const fn u64_to_usize(u: u64) -> usize { diff --git a/helper/src/lib.rs b/helper/src/lib.rs index 47d47a23..9bd64fa1 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -11,7 +11,7 @@ pub mod atomic; #[cfg(feature = "cast")] pub mod cast; -#[cfg(feature = "fs")] +#[cfg(all(feature = "fs", feature = "std"))] pub mod fs; pub mod network; diff --git a/net/epee-encoding/src/container_as_blob.rs b/net/epee-encoding/src/container_as_blob.rs index 83078c2c..363e157b 100644 --- a/net/epee-encoding/src/container_as_blob.rs +++ b/net/epee-encoding/src/container_as_blob.rs @@ -1,3 +1,5 @@ +use alloc::{string::ToString, vec, vec::Vec}; + use bytes::{Buf, BufMut, Bytes, BytesMut}; use ref_cast::RefCast; diff --git a/net/epee-encoding/src/error.rs b/net/epee-encoding/src/error.rs index 756cd136..7206189a 100644 --- a/net/epee-encoding/src/error.rs +++ b/net/epee-encoding/src/error.rs @@ -1,3 +1,4 @@ +use alloc::string::{String, ToString}; use core::{ fmt::{Debug, Formatter}, num::TryFromIntError, diff --git a/net/epee-encoding/src/lib.rs b/net/epee-encoding/src/lib.rs index d55a5460..a6ff1b04 100644 --- a/net/epee-encoding/src/lib.rs +++ b/net/epee-encoding/src/lib.rs @@ -64,6 +64,7 @@ use hex as _; extern crate alloc; +use alloc::string::ToString; use core::str::from_utf8 as str_from_utf8; use bytes::{Buf, BufMut, Bytes, BytesMut}; diff --git a/net/epee-encoding/src/value.rs b/net/epee-encoding/src/value.rs index 816203e5..4762c96a 100644 --- a/net/epee-encoding/src/value.rs +++ b/net/epee-encoding/src/value.rs @@ -1,7 +1,7 @@ //! This module contains a [`EpeeValue`] trait and //! impls for some possible base epee values. -use alloc::{string::String, vec::Vec}; +use alloc::{string::String, vec, vec::Vec}; use core::fmt::Debug; use bytes::{Buf, BufMut, Bytes, BytesMut}; diff --git a/net/wire/src/network_address.rs b/net/wire/src/network_address.rs index ad599b70..3e15c467 100644 --- a/net/wire/src/network_address.rs +++ b/net/wire/src/network_address.rs @@ -17,10 +17,12 @@ //! Monero network. Core Monero has 4 main addresses: IPv4, IPv6, Tor, //! I2p. Currently this module only has IPv(4/6). //! -use bytes::BufMut; -use cuprate_epee_encoding::EpeeObject; use std::{hash::Hash, net, net::SocketAddr}; +use bytes::BufMut; + +use cuprate_epee_encoding::EpeeObject; + mod epee_builder; use epee_builder::*; diff --git a/net/wire/src/network_address/epee_builder.rs b/net/wire/src/network_address/epee_builder.rs index c1d17423..bd481a5e 100644 --- a/net/wire/src/network_address/epee_builder.rs +++ b/net/wire/src/network_address/epee_builder.rs @@ -1,9 +1,10 @@ -use bytes::Buf; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; -use cuprate_epee_encoding::{epee_object, EpeeObjectBuilder}; +use bytes::Buf; use thiserror::Error; +use cuprate_epee_encoding::{epee_object, EpeeObjectBuilder}; + use crate::NetworkAddress; #[derive(Default)] @@ -77,7 +78,7 @@ impl From for TaggedNetworkAddress { SocketAddr::V4(addr) => Self { ty: Some(1), addr: Some(AllFieldsNetworkAddress { - m_ip: Some(u32::from_be_bytes(addr.ip().octets())), + m_ip: Some(u32::from_le_bytes(addr.ip().octets())), m_port: Some(addr.port()), addr: None, }), @@ -112,7 +113,10 @@ epee_object!( impl AllFieldsNetworkAddress { fn try_into_network_address(self, ty: u8) -> Option { Some(match ty { - 1 => NetworkAddress::from(SocketAddrV4::new(Ipv4Addr::from(self.m_ip?), self.m_port?)), + 1 => NetworkAddress::from(SocketAddrV4::new( + Ipv4Addr::from(self.m_ip?.to_le_bytes()), + self.m_port?, + )), 2 => NetworkAddress::from(SocketAddrV6::new( Ipv6Addr::from(self.addr?), self.m_port?, diff --git a/p2p/address-book/Cargo.toml b/p2p/address-book/Cargo.toml index 9cbba717..a88819f7 100644 --- a/p2p/address-book/Cargo.toml +++ b/p2p/address-book/Cargo.toml @@ -9,7 +9,7 @@ authors = ["Boog900"] [dependencies] cuprate-constants = { workspace = true } cuprate-pruning = { workspace = true } -cuprate-p2p-core = { workspace = true } +cuprate-p2p-core = { workspace = true, features = ["borsh"] } tower = { workspace = true, features = ["util"] } tokio = { workspace = true, features = ["time", "fs", "rt"]} diff --git a/p2p/address-book/src/book.rs b/p2p/address-book/src/book.rs index 907d6911..3e5269f5 100644 --- a/p2p/address-book/src/book.rs +++ b/p2p/address-book/src/book.rs @@ -423,7 +423,8 @@ impl Service> for AddressBook { AddressBookRequest::PeerlistSize | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) - | AddressBookRequest::GetBans => { + | AddressBookRequest::GetBans + | AddressBookRequest::ConnectionInfo => { todo!("finish https://github.com/Cuprate/cuprate/pull/297") } }; diff --git a/p2p/bucket/Cargo.toml b/p2p/bucket/Cargo.toml new file mode 100644 index 00000000..1a53e85a --- /dev/null +++ b/p2p/bucket/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cuprate-p2p-bucket" +version = "0.1.0" +edition = "2021" +license = "MIT" +authors = ["SyntheticBird"] + +[dependencies] +arrayvec = { workspace = true } +rand = { workspace = true, features = ["std", "std_rng"]} + +[lints] +workspace = true diff --git a/p2p/bucket/src/lib.rs b/p2p/bucket/src/lib.rs new file mode 100644 index 00000000..0f73eea2 --- /dev/null +++ b/p2p/bucket/src/lib.rs @@ -0,0 +1,172 @@ +//! Bucket data structure +//! +//! A collection data structure that discriminates its unique items and place them into "buckets". +//! +//! The item must implement the [`Bucketable`] trait that defines how to create the discriminant +//! from the item type. The data structure will internally contain any item into "buckets" or vectors +//! of sized capacity `N` that regroup all the stored items with this specific discriminant. +//! +//! A practical example of this data structure is for storing `N` amount of IP discriminated by their subnets. +//! You can store in each "buckets" corresponding to a `/16` subnet up to `N` IPs of that subnet. +//! +//! # Example +//! +//! ``` +//! use cuprate_p2p_bucket::Bucket; +//! use std::net::Ipv4Addr; +//! +//! // Create a new bucket that can store at most 2 IPs in a particular `/16` subnet. +//! let mut bucket = Bucket::<2,Ipv4Addr>::new(); +//! +//! // Fulfill the `96.96.0.0/16` bucket. +//! bucket.push("96.96.0.1".parse().unwrap()); +//! bucket.push("96.96.0.2".parse().unwrap()); +//! assert_eq!(2, bucket.len()); +//! assert_eq!(2, bucket.len_bucket(&[96_u8,96_u8]).unwrap()); +//! +//! // Push a new IP from another subnet +//! bucket.push("127.0.0.1".parse().unwrap()); +//! assert_eq!(3, bucket.len()); +//! assert_eq!(2, bucket.len_bucket(&[96_u8,96_u8]).unwrap()); +//! assert_eq!(1, bucket.len_bucket(&[127_u8,0_u8]).unwrap()); +//! +//! // Attempting to push a new IP within `96.96.0.0/16` bucket will return the IP back +//! // as this subnet is already full. +//! let pushed = bucket.push("96.96.0.3".parse().unwrap()); +//! assert!(pushed.is_some()); +//! assert_eq!(2, bucket.len_bucket(&[96_u8,96_u8]).unwrap()); +//! +//! ``` + +use arrayvec::{ArrayVec, CapacityError}; +use rand::random; + +use std::{collections::BTreeMap, net::Ipv4Addr}; + +/// A discriminant that can be computed from the type. +pub trait Bucketable: Sized + Eq + Clone { + /// The type of the discriminant being used in the Binary tree. + type Discriminant: Ord + AsRef<[u8]>; + + /// Method that can compute the discriminant from the item. + fn discriminant(&self) -> Self::Discriminant; +} + +/// A collection data structure discriminating its unique items +/// with a specified method. Limiting the amount of items stored +/// with that discriminant to the const `N`. +pub struct Bucket { + /// The storage of the bucket + storage: BTreeMap>, +} + +impl Bucket { + /// Create a new Bucket + pub const fn new() -> Self { + Self { + storage: BTreeMap::new(), + } + } + + /// Push a new element into the Bucket + /// + /// Will internally create a new vector for each new discriminant being + /// generated from an item. + /// + /// This function WILL NOT push the element if it already exists. + /// + /// Return `None` if the item has been pushed or ignored. `Some(I)` if + /// the vector is full. + /// + /// # Example + /// + /// ``` + /// use cuprate_p2p_bucket::Bucket; + /// use std::net::Ipv4Addr; + /// + /// let mut bucket = Bucket::<8,Ipv4Addr>::new(); + /// + /// // Push a first IP address. + /// bucket.push("127.0.0.1".parse().unwrap()); + /// assert_eq!(1, bucket.len()); + /// + /// // Push the same IP address a second time. + /// bucket.push("127.0.0.1".parse().unwrap()); + /// assert_eq!(1, bucket.len()); + /// ``` + pub fn push(&mut self, item: I) -> Option { + let discriminant = item.discriminant(); + + if let Some(vec) = self.storage.get_mut(&discriminant) { + // Push the item if it doesn't exist. + if !vec.contains(&item) { + return vec.try_push(item).err().map(CapacityError::element); + } + } else { + // Initialize the vector if not found. + let mut vec = ArrayVec::::new(); + vec.push(item); + self.storage.insert(discriminant, vec); + } + + None + } + + /// Will attempt to remove an item from the bucket. + pub fn remove(&mut self, item: &I) -> Option { + self.storage.get_mut(&item.discriminant()).and_then(|vec| { + vec.iter() + .enumerate() + .find_map(|(i, v)| (item == v).then_some(i)) + .map(|index| vec.swap_remove(index)) + }) + } + + /// Return the number of item stored within the storage + pub fn len(&self) -> usize { + self.storage.values().map(ArrayVec::len).sum() + } + + /// Return the number of item stored with a specific discriminant. + /// + /// This method returns None if the bucket with this discriminant + /// doesn't exist. + pub fn len_bucket(&self, discriminant: &I::Discriminant) -> Option { + self.storage.get(discriminant).map(ArrayVec::len) + } + + /// Return `true` if the storage contains no items + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Return a reference to an item chosen at random. + /// + /// Repeated use of this function will provide a normal distribution of + /// items based on their discriminants. + pub fn get_random(&mut self) -> Option<&I> { + // Get the total amount of discriminants to explore. + let len = self.storage.len(); + + // Get a random bucket. + let (_, vec) = self.storage.iter().nth(random::() / len).unwrap(); + + // Return a reference chose at random. + vec.get(random::() / vec.len()) + } +} + +impl Default for Bucket { + fn default() -> Self { + Self::new() + } +} + +impl Bucketable for Ipv4Addr { + /// We are discriminating by `/16` subnets. + type Discriminant = [u8; 2]; + + fn discriminant(&self) -> Self::Discriminant { + [self.octets()[0], self.octets()[1]] + } +} diff --git a/p2p/p2p-core/Cargo.toml b/p2p/p2p-core/Cargo.toml index 0a6aaf38..bc6c8335 100644 --- a/p2p/p2p-core/Cargo.toml +++ b/p2p/p2p-core/Cargo.toml @@ -10,9 +10,10 @@ default = ["borsh"] borsh = ["dep:borsh", "cuprate-pruning/borsh"] [dependencies] -cuprate-helper = { workspace = true, features = ["asynch"], default-features = false } -cuprate-wire = { workspace = true, features = ["tracing"] } +cuprate-helper = { workspace = true, features = ["asynch"], default-features = false } +cuprate-wire = { workspace = true, features = ["tracing"] } cuprate-pruning = { workspace = true } +cuprate-types = { workspace = true } tokio = { workspace = true, features = ["net", "sync", "macros", "time", "rt", "rt-multi-thread"]} tokio-util = { workspace = true, features = ["codec"] } diff --git a/p2p/p2p-core/src/ban.rs b/p2p/p2p-core/src/ban.rs deleted file mode 100644 index 76fd3ebf..00000000 --- a/p2p/p2p-core/src/ban.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Data structures related to bans. - -use std::time::{Duration, Instant}; - -use crate::NetZoneAddress; - -/// Data within [`crate::services::AddressBookRequest::SetBan`]. -pub struct SetBan { - /// Address of the peer. - pub address: A, - /// - If [`Some`], how long this peer should be banned for - /// - If [`None`], the peer will be unbanned - pub ban: Option, -} - -/// Data within [`crate::services::AddressBookResponse::GetBans`]. -pub struct BanState { - /// Address of the peer. - pub address: A, - /// - If [`Some`], the peer is banned until this [`Instant`] - /// - If [`None`], the peer is not currently banned - pub unban_instant: Option, -} diff --git a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs index 8bb966db..48b3daf5 100644 --- a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs +++ b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs @@ -111,7 +111,8 @@ impl Service> for DummyAddressBook { AddressBookRequest::PeerlistSize | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) - | AddressBookRequest::GetBans => { + | AddressBookRequest::GetBans + | AddressBookRequest::ConnectionInfo => { todo!("finish https://github.com/Cuprate/cuprate/pull/297") } })) diff --git a/p2p/p2p-core/src/lib.rs b/p2p/p2p-core/src/lib.rs index 5b93b59c..26e10686 100644 --- a/p2p/p2p-core/src/lib.rs +++ b/p2p/p2p-core/src/lib.rs @@ -75,7 +75,6 @@ use cuprate_wire::{ NetworkAddress, }; -pub mod ban; pub mod client; mod constants; pub mod error; @@ -83,6 +82,7 @@ pub mod handles; mod network_zones; pub mod protocol; pub mod services; +pub mod types; pub use error::*; pub use network_zones::{ClearNet, ClearNetServerCfg}; diff --git a/p2p/p2p-core/src/services.rs b/p2p/p2p-core/src/services.rs index 495b7192..6d1089ce 100644 --- a/p2p/p2p-core/src/services.rs +++ b/p2p/p2p-core/src/services.rs @@ -4,9 +4,9 @@ use cuprate_pruning::{PruningError, PruningSeed}; use cuprate_wire::{CoreSyncData, PeerListEntryBase}; use crate::{ - ban::{BanState, SetBan}, client::InternalPeerID, handles::ConnectionHandle, + types::{BanState, ConnectionInfo, SetBan}, NetZoneAddress, NetworkAddressIncorrectZone, NetworkZone, }; @@ -118,6 +118,9 @@ pub enum AddressBookRequest { /// Get the amount of white & grey peers. PeerlistSize, + /// Get information on all connections. + ConnectionInfo, + /// Get the amount of incoming & outgoing connections. ConnectionCount, @@ -152,6 +155,9 @@ pub enum AddressBookResponse { /// Response to [`AddressBookRequest::PeerlistSize`]. PeerlistSize { white: usize, grey: usize }, + /// Response to [`AddressBookRequest::ConnectionInfo`]. + ConnectionInfo(Vec>), + /// Response to [`AddressBookRequest::ConnectionCount`]. ConnectionCount { incoming: usize, outgoing: usize }, diff --git a/p2p/p2p-core/src/types.rs b/p2p/p2p-core/src/types.rs new file mode 100644 index 00000000..ca560555 --- /dev/null +++ b/p2p/p2p-core/src/types.rs @@ -0,0 +1,96 @@ +//! General data structures. + +use std::time::{Duration, Instant}; + +use cuprate_pruning::PruningSeed; +use cuprate_types::{AddressType, ConnectionState}; + +use crate::NetZoneAddress; + +/// Data within [`crate::services::AddressBookRequest::SetBan`]. +pub struct SetBan { + /// Address of the peer. + pub address: A, + /// - If [`Some`], how long this peer should be banned for + /// - If [`None`], the peer will be unbanned + pub ban: Option, +} + +/// Data within [`crate::services::AddressBookResponse::GetBans`]. +pub struct BanState { + /// Address of the peer. + pub address: A, + /// - If [`Some`], the peer is banned until this [`Instant`] + /// - If [`None`], the peer is not currently banned + pub unban_instant: Option, +} + +/// Data within [`crate::services::AddressBookResponse::ConnectionInfo`]. +pub struct ConnectionInfo { + // The following fields are mostly the same as `monerod`. + pub address: A, + pub address_type: AddressType, + pub avg_download: u64, + pub avg_upload: u64, + pub current_download: u64, + pub current_upload: u64, + pub height: u64, + /// Either a domain or an IP without the port. + pub host: String, + pub incoming: bool, + pub live_time: u64, + pub localhost: bool, + pub local_ip: bool, + pub peer_id: u64, + pub pruning_seed: PruningSeed, + pub recv_count: u64, + pub recv_idle_time: u64, + pub rpc_credits_per_hash: u32, + pub rpc_port: u16, + pub send_count: u64, + pub send_idle_time: u64, + pub state: ConnectionState, + pub support_flags: u32, + + // The following fields are slightly different than `monerod`. + + // + /// [`None`] if Tor/i2p or unknown. + pub socket_addr: Option, + + /// This field does not exist for `cuprated`'s RPC, this is just a marker type: + /// - + /// - + /// + /// [`ConnectionId::DEFAULT_STR`] is used when mapping to the RPC type. + pub connection_id: ConnectionId, +} + +/// Marker type for `monerod`'s connection ID. +/// +/// `connection_id` is a 128-bit `uuid` in `monerod`. +/// `cuprated` does not support this field so it returns +/// the default value in the RPC interface, an all 0-bit UUID. +/// +/// This default value in string form is [`ConnectionId::DEFAULT_STR`]. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ConnectionId; + +impl ConnectionId { + /// [`str`] representation of a default connection ID. + pub const DEFAULT_STR: &str = "00000000000000000000000000000000"; +} + +/// Used in RPC's `sync_info`. +/// +// TODO: fix docs after +// Data within [`crate::services::AddressBookResponse::Spans`]. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Span { + pub nblocks: u64, + pub rate: u32, + pub remote_address: A, + pub size: u64, + pub speed: u32, + pub start_block_height: u64, +} diff --git a/pruning/Cargo.toml b/pruning/Cargo.toml index 6fcc74e2..4b03551d 100644 --- a/pruning/Cargo.toml +++ b/pruning/Cargo.toml @@ -10,7 +10,7 @@ default = [] borsh = ["dep:borsh"] [dependencies] -cuprate-constants = { workspace = true } +cuprate-constants = { workspace = true, features = ["block"] } thiserror = { workspace = true } diff --git a/rpc/interface/Cargo.toml b/rpc/interface/Cargo.toml index ef62d349..c5d4db70 100644 --- a/rpc/interface/Cargo.toml +++ b/rpc/interface/Cargo.toml @@ -10,20 +10,20 @@ keywords = ["cuprate", "rpc", "interface"] [features] default = ["dummy", "serde"] -dummy = [] +dummy = ["dep:cuprate-helper", "dep:futures"] [dependencies] cuprate-epee-encoding = { workspace = true, default-features = false } cuprate-json-rpc = { workspace = true, default-features = false } cuprate-rpc-types = { workspace = true, features = ["serde", "epee"], default-features = false } -cuprate-helper = { workspace = true, features = ["asynch"], default-features = false } +cuprate-helper = { workspace = true, features = ["asynch"], default-features = false, optional = true } anyhow = { workspace = true } axum = { version = "0.7.5", features = ["json"], default-features = false } serde = { workspace = true, optional = true } -tower = { workspace = true } +tower = { workspace = true, features = ["util"] } paste = { workspace = true } -futures = { workspace = true } +futures = { workspace = true, optional = true } [dev-dependencies] cuprate-test-utils = { workspace = true } diff --git a/rpc/types/Cargo.toml b/rpc/types/Cargo.toml index e9ca5296..6d8797b2 100644 --- a/rpc/types/Cargo.toml +++ b/rpc/types/Cargo.toml @@ -10,16 +10,16 @@ keywords = ["cuprate", "rpc", "types", "monero"] [features] default = ["serde", "epee"] -serde = ["dep:serde", "cuprate-fixed-bytes/serde"] -epee = ["dep:cuprate-epee-encoding"] +serde = ["dep:serde", "cuprate-fixed-bytes/serde", "cuprate-types/serde"] +epee = ["dep:cuprate-epee-encoding", "cuprate-types/epee"] [dependencies] cuprate-epee-encoding = { workspace = true, optional = true } cuprate-fixed-bytes = { workspace = true } -cuprate-types = { workspace = true, default-features = false, features = ["epee", "serde"] } +cuprate-types = { workspace = true, default-features = false } -paste = { workspace = true } -serde = { workspace = true, optional = true } +paste = { workspace = true } +serde = { workspace = true, optional = true } [dev-dependencies] cuprate-test-utils = { workspace = true } diff --git a/rpc/types/src/base.rs b/rpc/types/src/base.rs index c131e41e..89eafc5b 100644 --- a/rpc/types/src/base.rs +++ b/rpc/types/src/base.rs @@ -58,61 +58,37 @@ pub struct ResponseBase { } impl ResponseBase { - /// `const` version of [`Default::default`]. - /// - /// ```rust - /// use cuprate_rpc_types::{misc::*, base::*}; - /// - /// let new = ResponseBase::new(); - /// assert_eq!(new, ResponseBase { - /// status: Status::Ok, - /// untrusted: false, - /// }); - /// ``` - pub const fn new() -> Self { - Self { - status: Status::Ok, - untrusted: false, - } - } - - /// Returns OK and trusted [`Self`]. + /// [`Status::Ok`] and trusted [`Self`]. /// /// This is the most common version of [`Self`]. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok = ResponseBase::ok(); - /// assert_eq!(ok, ResponseBase { + /// assert_eq!(ResponseBase::OK, ResponseBase { /// status: Status::Ok, /// untrusted: false, /// }); /// ``` - pub const fn ok() -> Self { - Self { - status: Status::Ok, - untrusted: false, - } - } + pub const OK: Self = Self { + status: Status::Ok, + untrusted: false, + }; - /// Same as [`Self::ok`] but with [`Self::untrusted`] set to `true`. + /// Same as [`Self::OK`] but with [`Self::untrusted`] set to `true`. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok_untrusted = ResponseBase::ok_untrusted(); - /// assert_eq!(ok_untrusted, ResponseBase { + /// assert_eq!(ResponseBase::OK_UNTRUSTED, ResponseBase { /// status: Status::Ok, /// untrusted: true, /// }); /// ``` - pub const fn ok_untrusted() -> Self { - Self { - status: Status::Ok, - untrusted: true, - } - } + pub const OK_UNTRUSTED: Self = Self { + status: Status::Ok, + untrusted: true, + }; } #[cfg(feature = "epee")] @@ -148,9 +124,9 @@ impl AccessResponseBase { /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let new = AccessResponseBase::new(ResponseBase::ok()); + /// let new = AccessResponseBase::new(ResponseBase::OK); /// assert_eq!(new, AccessResponseBase { - /// response_base: ResponseBase::ok(), + /// response_base: ResponseBase::OK, /// credits: 0, /// top_hash: "".into(), /// }); @@ -163,47 +139,41 @@ impl AccessResponseBase { } } - /// Returns OK and trusted [`Self`]. + /// [`Status::Ok`] and trusted [`Self`]. /// /// This is the most common version of [`Self`]. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok = AccessResponseBase::ok(); - /// assert_eq!(ok, AccessResponseBase { - /// response_base: ResponseBase::ok(), + /// assert_eq!(AccessResponseBase::OK, AccessResponseBase { + /// response_base: ResponseBase::OK, /// credits: 0, /// top_hash: "".into(), /// }); /// ``` - pub const fn ok() -> Self { - Self { - response_base: ResponseBase::ok(), - credits: 0, - top_hash: String::new(), - } - } + pub const OK: Self = Self { + response_base: ResponseBase::OK, + credits: 0, + top_hash: String::new(), + }; - /// Same as [`Self::ok`] but with `untrusted` set to `true`. + /// Same as [`Self::OK`] but with `untrusted` set to `true`. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok_untrusted = AccessResponseBase::ok_untrusted(); - /// assert_eq!(ok_untrusted, AccessResponseBase { - /// response_base: ResponseBase::ok_untrusted(), + /// assert_eq!(AccessResponseBase::OK_UNTRUSTED, AccessResponseBase { + /// response_base: ResponseBase::OK_UNTRUSTED, /// credits: 0, /// top_hash: "".into(), /// }); /// ``` - pub const fn ok_untrusted() -> Self { - Self { - response_base: ResponseBase::ok_untrusted(), - credits: 0, - top_hash: String::new(), - } - } + pub const OK_UNTRUSTED: Self = Self { + response_base: ResponseBase::OK_UNTRUSTED, + credits: 0, + top_hash: String::new(), + }; } #[cfg(feature = "epee")] diff --git a/rpc/types/src/bin.rs b/rpc/types/src/bin.rs index a68d3e10..7b941918 100644 --- a/rpc/types/src/bin.rs +++ b/rpc/types/src/bin.rs @@ -20,12 +20,16 @@ use cuprate_types::BlockCompleteEntry; use crate::{ base::AccessResponseBase, - defaults::{default_false, default_zero}, macros::{define_request, define_request_and_response, define_request_and_response_doc}, - misc::{BlockOutputIndices, GetOutputsOut, OutKeyBin, PoolInfoExtent, PoolTxInfo, Status}, + misc::{BlockOutputIndices, GetOutputsOut, OutKeyBin, PoolTxInfo, Status}, rpc_call::RpcCallValue, }; +#[cfg(any(feature = "epee", feature = "serde"))] +use crate::defaults::{default_false, default_zero}; +#[cfg(feature = "epee")] +use crate::misc::PoolInfoExtent; + //---------------------------------------------------------------------------------------------------- Definitions define_request_and_response! { get_blocks_by_heightbin, diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index fd9ffa32..cb55e64a 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -8,10 +8,6 @@ use serde::{Deserialize, Serialize}; use crate::{ base::{AccessResponseBase, ResponseBase}, - defaults::{ - default_false, default_height, default_one, default_string, default_true, default_vec, - default_zero, - }, macros::define_request_and_response, misc::{ AuxPow, BlockHeader, ChainInfo, ConnectionInfo, Distribution, GetBan, @@ -21,6 +17,12 @@ use crate::{ rpc_call::RpcCallValue, }; +#[cfg(any(feature = "epee", feature = "serde"))] +use crate::defaults::{ + default_false, default_height, default_one, default_string, default_true, default_vec, + default_zero, +}; + //---------------------------------------------------------------------------------------------------- Macro /// Adds a (de)serialization doc-test to a type in `json.rs`. /// @@ -184,7 +186,7 @@ define_request_and_response! { // . #[doc = serde_doc_test!( GET_BLOCK_TEMPLATE_RESPONSE => GetBlockTemplateResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, blockhashing_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a00000000e0c20372be23d356347091025c5b5e8f2abf83ab618378565cce2b703491523401".into(), blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), difficulty_top64: 0, @@ -240,7 +242,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_COUNT_RESPONSE => GetBlockCountResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, count: 3195019, } )] @@ -332,7 +334,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GENERATE_BLOCKS_RESPONSE => GenerateBlocksResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, blocks: vec!["49b712db7760e3728586f8434ee8bc8d7b3d410dac6bb6e98bf5845c83b917e4".into()], height: 9783, } @@ -357,7 +359,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_LAST_BLOCK_HEADER_RESPONSE => GetLastBlockHeaderResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_header: BlockHeader { block_size: 200419, block_weight: 200419, @@ -409,7 +411,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_HEADER_BY_HASH_RESPONSE => GetBlockHeaderByHashResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_headers: vec![], block_header: BlockHeader { block_size: 210, @@ -464,7 +466,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_HEADER_BY_HEIGHT_RESPONSE => GetBlockHeaderByHeightResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_header: BlockHeader { block_size: 210, block_weight: 210, @@ -519,7 +521,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_HEADERS_RANGE_RESPONSE => GetBlockHeadersRangeResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, headers: vec![ BlockHeader { block_size: 301413, @@ -601,7 +603,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_RESPONSE => GetBlockResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, blob: "1010c58bab9b06b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7807e07f502cef8a70101ff92f8a7010180e0a596bb1103d7cbf826b665d7a532c316982dc8dbc24f285cbc18bbcc27c7164cd9b3277a85d034019f629d8b36bd16a2bfce3ea80c31dc4d8762c67165aec21845494e32b7582fe00211000000297a787a000000000000000000000000".into(), block_header: BlockHeader { block_size: 106, @@ -654,11 +656,11 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_CONNECTIONS_RESPONSE => GetConnectionsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, connections: vec![ ConnectionInfo { address: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083".into(), - address_type: 4, + address_type: cuprate_types::AddressType::Tor, avg_download: 0, avg_upload: 0, connection_id: "22ef856d0f1d44cc95e84fecfd065fe2".into(), @@ -680,12 +682,12 @@ define_request_and_response! { rpc_port: 0, send_count: 3406572, send_idle_time: 30, - state: "normal".into(), + state: cuprate_types::ConnectionState::Normal, support_flags: 0 }, ConnectionInfo { address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(), - address_type: 4, + address_type: cuprate_types::AddressType::Tor, avg_download: 0, avg_upload: 0, connection_id: "c7734e15936f485a86d2b0534f87e499".into(), @@ -707,7 +709,7 @@ define_request_and_response! { rpc_port: 0, send_count: 3370566, send_idle_time: 120, - state: "normal".into(), + state: cuprate_types::ConnectionState::Normal, support_flags: 0 } ], @@ -728,7 +730,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_INFO_RESPONSE => GetInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, adjusted_time: 1721245289, alt_blocks_count: 16, block_size_limit: 600000, @@ -831,7 +833,7 @@ define_request_and_response! { #[doc = serde_doc_test!( HARD_FORK_INFO_RESPONSE => HardForkInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, earliest_height: 2689608, enabled: true, state: 0, @@ -877,7 +879,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_BANS_RESPONSE => SetBansResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -892,7 +894,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BANS_RESPONSE => GetBansResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, bans: vec![ GetBan { host: "104.248.206.131".into(), @@ -994,7 +996,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_OUTPUT_HISTOGRAM_RESPONSE => GetOutputHistogramResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, histogram: vec![HistogramEntry { amount: 20000000000, recent_instances: 0, @@ -1028,7 +1030,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_COINBASE_TX_SUM_RESPONSE => GetCoinbaseTxSumResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, emission_amount: 9387854817320, emission_amount_top64: 0, fee_amount: 83981380000, @@ -1057,7 +1059,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_VERSION_RESPONSE => GetVersionResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, current_height: 3195051, hard_forks: vec![ HardforkEntry { @@ -1143,12 +1145,16 @@ define_request_and_response! { get_fee_estimate, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2250..=2277, - GetFeeEstimate (empty), - Request {}, + + GetFeeEstimate, + + Request { + grace_blocks: u64 = default_zero::(), "default_zero", + }, #[doc = serde_doc_test!( GET_FEE_ESTIMATE_RESPONSE => GetFeeEstimateResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, fee: 20000, fees: vec![20000,80000,320000,4000000], quantization_mask: 10000, @@ -1170,7 +1176,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_ALTERNATE_CHAINS_RESPONSE => GetAlternateChainsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, chains: vec![ ChainInfo { block_hash: "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into(), @@ -1238,7 +1244,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SYNC_INFO_RESPONSE => SyncInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, height: 3195157, next_needed_pruning_seed: 0, overview: "[]".into(), @@ -1247,7 +1253,7 @@ define_request_and_response! { SyncInfoPeer { info: ConnectionInfo { address: "142.93.128.65:44986".into(), - address_type: 1, + address_type: cuprate_types::AddressType::Ipv4, avg_download: 1, avg_upload: 1, connection_id: "a5803c4c2dac49e7b201dccdef54c862".into(), @@ -1269,14 +1275,14 @@ define_request_and_response! { rpc_port: 18089, send_count: 32235, send_idle_time: 6, - state: "normal".into(), + state: cuprate_types::ConnectionState::Normal, support_flags: 1 } }, SyncInfoPeer { info: ConnectionInfo { address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(), - address_type: 4, + address_type: cuprate_types::AddressType::Tor, avg_download: 0, avg_upload: 0, connection_id: "277f7c821bc546878c8bd29977e780f5".into(), @@ -1298,7 +1304,7 @@ define_request_and_response! { rpc_port: 0, send_count: 99120, send_idle_time: 15, - state: "normal".into(), + state: cuprate_types::ConnectionState::Normal, support_flags: 0 } } @@ -1328,7 +1334,7 @@ define_request_and_response! { // TODO: enable test after binary string impl. // #[doc = serde_doc_test!( // GET_TRANSACTION_POOL_BACKLOG_RESPONSE => GetTransactionPoolBacklogResponse { - // base: ResponseBase::ok(), + // base: ResponseBase::OK, // backlog: "...Binary...".into(), // } // )] @@ -1370,7 +1376,7 @@ define_request_and_response! { // TODO: enable test after binary string impl. // #[doc = serde_doc_test!( // GET_OUTPUT_DISTRIBUTION_RESPONSE => GetOutputDistributionResponse { - // base: AccessResponseBase::ok(), + // base: AccessResponseBase::OK, // distributions: vec![Distribution::Uncompressed(DistributionUncompressed { // start_height: 1462078, // base: 0, @@ -1394,7 +1400,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_MINER_DATA_RESPONSE => GetMinerDataResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, already_generated_coins: 18186022843595960691, difficulty: "0x48afae42de".into(), height: 2731375, @@ -1447,7 +1453,7 @@ define_request_and_response! { #[doc = serde_doc_test!( PRUNE_BLOCKCHAIN_RESPONSE => PruneBlockchainResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, pruned: true, pruning_seed: 387, } @@ -1513,7 +1519,7 @@ define_request_and_response! { #[doc = serde_doc_test!( FLUSH_CACHE_RESPONSE => FlushCacheResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -1542,7 +1548,7 @@ define_request_and_response! { #[doc = serde_doc_test!( ADD_AUX_POW_RESPONSE => AddAuxPowResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, aux_pow: vec![AuxPow { hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(), id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(), diff --git a/rpc/types/src/lib.rs b/rpc/types/src/lib.rs index be1069ec..403a3ea3 100644 --- a/rpc/types/src/lib.rs +++ b/rpc/types/src/lib.rs @@ -6,6 +6,7 @@ )] mod constants; +#[cfg(any(feature = "serde", feature = "epee"))] mod defaults; mod free; mod macros; diff --git a/rpc/types/src/misc/distribution.rs b/rpc/types/src/misc/distribution.rs index faac7ad7..e920d129 100644 --- a/rpc/types/src/misc/distribution.rs +++ b/rpc/types/src/misc/distribution.rs @@ -20,8 +20,8 @@ use cuprate_epee_encoding::{ "rpc/core_rpc_server_commands_defs.h", 45..=55 )] -#[cfg(feature = "epee")] -fn compress_integer_array(_: &[u64]) -> error::Result> { +#[cfg(any(feature = "epee", feature = "serde"))] +fn compress_integer_array(_: &[u64]) -> Vec { todo!() } @@ -33,6 +33,7 @@ fn compress_integer_array(_: &[u64]) -> error::Result> { "rpc/core_rpc_server_commands_defs.h", 57..=72 )] +#[cfg(any(feature = "epee", feature = "serde"))] fn decompress_integer_array(_: &[u8]) -> Vec { todo!() } @@ -135,12 +136,7 @@ fn serialize_distribution_as_compressed_data(v: &Vec, s: S) -> Result compressed_data.serialize(s), - Err(_) => Err(serde::ser::Error::custom( - "error compressing distribution array", - )), - } + compress_integer_array(v).serialize(s) } /// Deserializer function for [`DistributionCompressedBinary::distribution`]. @@ -256,7 +252,7 @@ impl EpeeObject for Distribution { distribution, amount, }) => { - let compressed_data = compress_integer_array(&distribution)?; + let compressed_data = compress_integer_array(&distribution); start_height.write(w)?; base.write(w)?; diff --git a/rpc/types/src/misc/misc.rs b/rpc/types/src/misc/misc.rs index 842997bc..8f7467ba 100644 --- a/rpc/types/src/misc/misc.rs +++ b/rpc/types/src/misc/misc.rs @@ -11,10 +11,10 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "epee")] use cuprate_epee_encoding::epee_object; -use crate::{ - defaults::{default_string, default_zero}, - macros::monero_definition_link, -}; +use crate::macros::monero_definition_link; + +#[cfg(any(feature = "epee", feature = "serde"))] +use crate::defaults::default_zero; //---------------------------------------------------------------------------------------------------- Macros /// This macro (local to this file) defines all the misc types. @@ -110,7 +110,7 @@ define_struct_and_impl_epee! { /// Used in [`crate::json::GetConnectionsResponse`]. ConnectionInfo { address: String, - address_type: u8, + address_type: cuprate_types::AddressType, avg_download: u64, avg_upload: u64, connection_id: String, @@ -135,7 +135,7 @@ define_struct_and_impl_epee! { // Exists in the original definition, but isn't // used or (de)serialized for RPC purposes. // ssl: bool, - state: String, + state: cuprate_types::ConnectionState, support_flags: u32, } } @@ -148,7 +148,7 @@ define_struct_and_impl_epee! { )] /// Used in [`crate::json::SetBansRequest`]. SetBan { - #[cfg_attr(feature = "serde", serde(default = "default_string"))] + #[cfg_attr(feature = "serde", serde(default = "crate::defaults::default_string"))] host: String, #[cfg_attr(feature = "serde", serde(default = "default_zero"))] ip: u32, diff --git a/rpc/types/src/other.rs b/rpc/types/src/other.rs index e7f3394c..3694041c 100644 --- a/rpc/types/src/other.rs +++ b/rpc/types/src/other.rs @@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize}; use crate::{ base::{AccessResponseBase, ResponseBase}, - defaults::{default_false, default_string, default_true, default_vec, default_zero}, macros::define_request_and_response, misc::{ GetOutputsOut, OutKey, Peer, PublicNode, SpentKeyImageInfo, Status, TxEntry, TxInfo, @@ -17,6 +16,9 @@ use crate::{ RpcCallValue, }; +#[cfg(any(feature = "serde", feature = "epee"))] +use crate::defaults::{default_false, default_string, default_true, default_vec, default_zero}; + //---------------------------------------------------------------------------------------------------- Macro /// Adds a (de)serialization doc-test to a type in `other.rs`. /// @@ -102,7 +104,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_HEIGHT_RESPONSE => GetHeightResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, hash: "68bb1a1cff8e2a44c3221e8e1aff80bc6ca45d06fa8eff4d2a3a7ac31d4efe3f".into(), height: 3195160, } @@ -157,7 +159,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_ALT_BLOCKS_HASHES_RESPONSE => GetAltBlocksHashesResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, blks_hashes: vec!["8ee10db35b1baf943f201b303890a29e7d45437bd76c2bd4df0d2f2ee34be109".into()], } )] @@ -187,7 +189,7 @@ define_request_and_response! { #[doc = serde_doc_test!( IS_KEY_IMAGE_SPENT_RESPONSE => IsKeyImageSpentResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, spent_status: vec![1, 1], } )] @@ -283,7 +285,7 @@ define_request_and_response! { #[doc = serde_doc_test!( START_MINING_RESPONSE => StartMiningResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -298,7 +300,7 @@ define_request_and_response! { #[doc = serde_doc_test!( STOP_MINING_RESPONSE => StopMiningResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -313,7 +315,7 @@ define_request_and_response! { #[doc = serde_doc_test!( MINING_STATUS_RESPONSE => MiningStatusResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, active: false, address: "".into(), bg_idle_threshold: 0, @@ -359,7 +361,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SAVE_BC_RESPONSE => SaveBcResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -385,7 +387,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_PEER_LIST_RESPONSE => GetPeerListResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, gray_list: vec![ Peer { host: "161.97.193.0".into(), @@ -467,7 +469,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LOG_HASH_RATE_RESPONSE => SetLogHashRateResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -492,7 +494,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LOG_LEVEL_RESPONSE => SetLogLevelResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -516,7 +518,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LOG_CATEGORIES_RESPONSE => SetLogCategoriesResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, categories: "*:INFO".into(), } )] @@ -582,7 +584,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_TRANSACTION_POOL_STATS_RESPONSE => GetTransactionPoolStatsResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, pool_stats: TxpoolStats { bytes_max: 11843, bytes_med: 2219, @@ -644,7 +646,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_LIMIT_RESPONSE => GetLimitResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, limit_down: 1280000, limit_up: 1280000, } @@ -676,7 +678,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LIMIT_RESPONSE => SetLimitResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, limit_down: 1024, limit_up: 128, } @@ -707,7 +709,7 @@ define_request_and_response! { #[doc = serde_doc_test!( OUT_PEERS_RESPONSE => OutPeersResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, out_peers: 3232235535, } )] @@ -740,7 +742,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_NET_STATS_RESPONSE => GetNetStatsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, start_time: 1721251858, total_bytes_in: 16283817214, total_bytes_out: 34225244079, @@ -779,7 +781,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_OUTS_RESPONSE => GetOutsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, outs: vec![ OutKey { height: 51941, @@ -823,7 +825,7 @@ define_request_and_response! { #[doc = serde_doc_test!( UPDATE_RESPONSE => UpdateResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, auto_uri: "".into(), hash: "".into(), path: "".into(), @@ -860,7 +862,7 @@ define_request_and_response! { #[doc = serde_doc_test!( POP_BLOCKS_RESPONSE => PopBlocksResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, height: 76482, } )] @@ -879,7 +881,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_TRANSACTION_POOL_HASHES_RESPONSE => GetTransactionPoolHashesResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, tx_hashes: vec![ "aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03".into(), "794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11".into(), @@ -929,7 +931,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_PUBLIC_NODES_RESPONSE => GetPublicNodesResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, gray: vec![], white: vec![ PublicNode { diff --git a/storage/blockchain/Cargo.toml b/storage/blockchain/Cargo.toml index 84991303..2e72143a 100644 --- a/storage/blockchain/Cargo.toml +++ b/storage/blockchain/Cargo.toml @@ -9,32 +9,31 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/storage/cuprate-bloc keywords = ["cuprate", "blockchain", "database"] [features] -default = ["heed", "service"] +default = ["heed"] # default = ["redb", "service"] # default = ["redb-memory", "service"] heed = ["cuprate-database/heed"] redb = ["cuprate-database/redb"] redb-memory = ["cuprate-database/redb-memory"] -service = ["dep:thread_local", "dep:rayon", "cuprate-helper/thread"] +serde = ["dep:serde", "cuprate-database/serde", "cuprate-database-service/serde"] [dependencies] cuprate-database = { workspace = true } cuprate-database-service = { workspace = true } -cuprate-helper = { workspace = true, features = ["fs", "map", "crypto"] } +cuprate-helper = { workspace = true, features = ["fs", "map", "crypto", "tx", "thread"] } cuprate-types = { workspace = true, features = ["blockchain"] } cuprate-pruning = { workspace = true } bitflags = { workspace = true, features = ["std", "serde", "bytemuck"] } bytemuck = { workspace = true, features = ["must_cast", "derive", "min_const_generics", "extern_crate_alloc"] } curve25519-dalek = { workspace = true } -rand = { workspace = true } +rand = { workspace = true, features = ["std", "std_rng"] } monero-serai = { workspace = true, features = ["std"] } serde = { workspace = true, optional = true } -# `service` feature. tower = { workspace = true } -thread_local = { workspace = true, optional = true } -rayon = { workspace = true, optional = true } +thread_local = { workspace = true } +rayon = { workspace = true } bytes = "1.7.2" [dev-dependencies] diff --git a/storage/blockchain/README.md b/storage/blockchain/README.md index 48005469..3f97a3d6 100644 --- a/storage/blockchain/README.md +++ b/storage/blockchain/README.md @@ -32,9 +32,6 @@ use cuprate_blockchain::{ This ensures the types/traits used from `cuprate_database` are the same ones used by `cuprate_blockchain` internally. # Feature flags -The `service` module requires the `service` feature to be enabled. -See the module for more documentation. - Different database backends are enabled by the feature flags: - `heed` (LMDB) - `redb` @@ -45,7 +42,7 @@ The default is `heed`. # Invariants when not using `service` -`cuprate_blockchain` can be used without the `service` feature enabled but +`cuprate_blockchain` can be used without the `service` module but there are some things that must be kept in mind when doing so. Failing to uphold these invariants may cause panics. diff --git a/storage/blockchain/src/lib.rs b/storage/blockchain/src/lib.rs index f66cd99b..7db8cc6e 100644 --- a/storage/blockchain/src/lib.rs +++ b/storage/blockchain/src/lib.rs @@ -29,16 +29,12 @@ pub use free::open; pub mod config; pub mod ops; +pub mod service; pub mod tables; pub mod types; -//---------------------------------------------------------------------------------------------------- Feature-gated -#[cfg(feature = "service")] -pub mod service; - //---------------------------------------------------------------------------------------------------- Private #[cfg(test)] pub(crate) mod tests; -#[cfg(feature = "service")] // only needed in `service` for now pub(crate) mod unsafe_sendable; diff --git a/storage/blockchain/src/service/mod.rs b/storage/blockchain/src/service/mod.rs index 53bf1dfa..c5eb80c2 100644 --- a/storage/blockchain/src/service/mod.rs +++ b/storage/blockchain/src/service/mod.rs @@ -10,8 +10,6 @@ //! //! The system is managed by this crate, and only requires [`init`] by the user. //! -//! This module must be enabled with the `service` feature. -//! //! ## Handles //! The 2 handles to the database are: //! - [`BlockchainReadHandle`] diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index f8642db2..01fc92d0 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -129,6 +129,8 @@ fn map_request( R::DatabaseSize => database_size(env), R::OutputHistogram(input) => output_histogram(env, input), R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count), + R::AltChains => alt_chains(env), + R::AltChainCount => alt_chain_count(env), } /* SOMEDAY: post-request handling, run some code for each request? */ @@ -771,3 +773,13 @@ fn output_histogram(env: &ConcreteEnv, input: OutputHistogramInput) -> ResponseR fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResult { Ok(BlockchainResponse::CoinbaseTxSum(todo!())) } + +/// [`BlockchainReadRequest::AltChains`] +fn alt_chains(env: &ConcreteEnv) -> ResponseResult { + Ok(BlockchainResponse::AltChains(todo!())) +} + +/// [`BlockchainReadRequest::AltChainCount`] +fn alt_chain_count(env: &ConcreteEnv) -> ResponseResult { + Ok(BlockchainResponse::AltChainCount(todo!())) +} diff --git a/storage/database/Cargo.toml b/storage/database/Cargo.toml index 7a2f4ae1..feeaf876 100644 --- a/storage/database/Cargo.toml +++ b/storage/database/Cargo.toml @@ -9,10 +9,10 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/storage/database" keywords = ["cuprate", "database"] [features] -# default = ["heed"] +default = ["heed"] # default = ["redb"] # default = ["redb-memory"] -heed = ["dep:heed"] +heed = [] redb = ["dep:redb"] redb-memory = ["redb"] @@ -25,7 +25,7 @@ paste = { workspace = true } thiserror = { workspace = true } # Optional features. -heed = { version = "0.20.5", features = ["read-txn-no-tls"], optional = true } +heed = { version = "0.20.5", features = ["read-txn-no-tls"] } redb = { version = "2.1.3", optional = true } serde = { workspace = true, optional = true } diff --git a/storage/database/src/backend/mod.rs b/storage/database/src/backend/mod.rs index 11ae40b8..ebe12d86 100644 --- a/storage/database/src/backend/mod.rs +++ b/storage/database/src/backend/mod.rs @@ -4,6 +4,8 @@ cfg_if::cfg_if! { // If both backends are enabled, fallback to `heed`. // This is useful when using `--all-features`. if #[cfg(all(feature = "redb", not(feature = "heed")))] { + use heed as _; + mod redb; pub use redb::ConcreteEnv; } else { diff --git a/storage/service/Cargo.toml b/storage/service/Cargo.toml index fa6971c5..ebdb13e8 100644 --- a/storage/service/Cargo.toml +++ b/storage/service/Cargo.toml @@ -8,14 +8,20 @@ authors = ["Boog900"] repository = "https://github.com/Cuprate/cuprate/tree/main/storage/service" keywords = ["cuprate", "service", "database"] +[features] +default = ["heed"] +heed = ["cuprate-database/heed"] +redb = ["cuprate-database/redb"] +redb-memorey = ["cuprate-database/redb-memory"] + [dependencies] cuprate-database = { workspace = true } -cuprate-helper = { workspace = true, features = ["fs", "thread", "map"] } +cuprate-helper = { workspace = true, features = ["fs", "thread", "map", "asynch"] } serde = { workspace = true, optional = true } rayon = { workspace = true } tower = { workspace = true } -futures = { workspace = true } +futures = { workspace = true, features = ["std"] } crossbeam = { workspace = true, features = ["std"] } [lints] diff --git a/storage/txpool/Cargo.toml b/storage/txpool/Cargo.toml index c3011663..c9082655 100644 --- a/storage/txpool/Cargo.toml +++ b/storage/txpool/Cargo.toml @@ -9,18 +9,17 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/storage/txpool" keywords = ["cuprate", "txpool", "transaction", "pool", "database"] [features] -default = ["heed", "service"] +default = ["heed"] # default = ["redb", "service"] # default = ["redb-memory", "service"] heed = ["cuprate-database/heed"] redb = ["cuprate-database/redb"] redb-memory = ["cuprate-database/redb-memory"] -service = ["dep:tower", "dep:rayon", "dep:cuprate-database-service"] serde = ["dep:serde", "cuprate-database/serde", "cuprate-database-service/serde"] [dependencies] cuprate-database = { workspace = true, features = ["heed"] } -cuprate-database-service = { workspace = true, optional = true } +cuprate-database-service = { workspace = true } cuprate-types = { workspace = true } cuprate-helper = { workspace = true, default-features = false, features = ["constants"] } @@ -28,11 +27,11 @@ monero-serai = { workspace = true, features = ["std"] } bytemuck = { workspace = true, features = ["must_cast", "derive", "min_const_generics", "extern_crate_alloc"] } bitflags = { workspace = true, features = ["std", "serde", "bytemuck"] } thiserror = { workspace = true } -hex = { workspace = true } +hex = { workspace = true, features = ["std"] } blake3 = { workspace = true, features = ["std"] } -tower = { workspace = true, optional = true } -rayon = { workspace = true, optional = true } +tower = { workspace = true } +rayon = { workspace = true } serde = { workspace = true, optional = true } diff --git a/storage/txpool/README.md b/storage/txpool/README.md index 80d3b25b..d14f445b 100644 --- a/storage/txpool/README.md +++ b/storage/txpool/README.md @@ -37,10 +37,6 @@ use cuprate_txpool::{ This ensures the types/traits used from `cuprate_database` are the same ones used by `cuprate_txpool` internally. # Feature flags - -The `service` module requires the `service` feature to be enabled. -See the module for more documentation. - Different database backends are enabled by the feature flags: - `heed` (LMDB) diff --git a/storage/txpool/src/lib.rs b/storage/txpool/src/lib.rs index 8a57c726..53e53ecf 100644 --- a/storage/txpool/src/lib.rs +++ b/storage/txpool/src/lib.rs @@ -4,10 +4,12 @@ clippy::significant_drop_tightening )] +// Used in docs: . +use tower as _; + pub mod config; mod free; pub mod ops; -#[cfg(feature = "service")] pub mod service; pub mod tables; mod tx; @@ -20,8 +22,6 @@ pub use tx::TxEntry; //re-exports pub use cuprate_database; -// TODO: remove when used. -use tower as _; #[cfg(test)] mod test { use cuprate_test_utils as _; diff --git a/storage/txpool/src/service.rs b/storage/txpool/src/service.rs index 91a7060c..a82de5bf 100644 --- a/storage/txpool/src/service.rs +++ b/storage/txpool/src/service.rs @@ -10,8 +10,6 @@ //! //! The system is managed by this crate, and only requires [`init`] by the user. //! -//! This module must be enabled with the `service` feature. -//! //! ## Handles //! The 2 handles to the database are: //! - [`TxpoolReadHandle`] @@ -42,7 +40,7 @@ //! To interact with the database (whether reading or writing data), //! a `Request` can be sent using one of the above handles. //! -//! Both the handles implement `tower::Service`, so they can be [`tower::Service::call`]ed. +//! Both the handles implement [`tower::Service`], so they can be [`tower::Service::call`]ed. //! //! An `async`hronous channel will be returned from the call. //! This channel can be `.await`ed upon to (eventually) receive diff --git a/storage/txpool/src/service/interface.rs b/storage/txpool/src/service/interface.rs index 5cd518f5..a27c6309 100644 --- a/storage/txpool/src/service/interface.rs +++ b/storage/txpool/src/service/interface.rs @@ -35,7 +35,11 @@ pub enum TxpoolReadRequest { Backlog, /// Get the number of transactions in the pool. - Size, + Size { + /// If this is [`true`], the size returned will + /// include private transactions in the pool. + include_sensitive_txs: bool, + }, } //---------------------------------------------------------------------------------------------------- TxpoolReadResponse @@ -66,7 +70,7 @@ pub enum TxpoolReadResponse { /// Response to [`TxpoolReadRequest::Backlog`]. /// - /// The inner `Vec` contains information on all + /// The inner [`Vec`] contains information on all /// the transactions currently in the pool. Backlog(Vec), diff --git a/storage/txpool/src/service/read.rs b/storage/txpool/src/service/read.rs index 257fe8ea..0de1e7d0 100644 --- a/storage/txpool/src/service/read.rs +++ b/storage/txpool/src/service/read.rs @@ -71,7 +71,9 @@ fn map_request( } TxpoolReadRequest::TxsForBlock(txs_needed) => txs_for_block(env, txs_needed), TxpoolReadRequest::Backlog => backlog(env), - TxpoolReadRequest::Size => size(env), + TxpoolReadRequest::Size { + include_sensitive_txs, + } => size(env, include_sensitive_txs), } } @@ -201,6 +203,6 @@ fn backlog(env: &ConcreteEnv) -> ReadResponseResult { /// [`TxpoolReadRequest::Size`]. #[inline] -fn size(env: &ConcreteEnv) -> ReadResponseResult { +fn size(env: &ConcreteEnv, include_sensitive_txs: bool) -> ReadResponseResult { Ok(TxpoolReadResponse::Size(todo!())) } diff --git a/storage/txpool/src/tx.rs b/storage/txpool/src/tx.rs index 6425326a..29afae8c 100644 --- a/storage/txpool/src/tx.rs +++ b/storage/txpool/src/tx.rs @@ -5,6 +5,8 @@ /// Used in [`TxpoolReadResponse::Backlog`](crate::service::interface::TxpoolReadResponse::Backlog). #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct TxEntry { + /// The transaction's ID (hash). + pub id: [u8; 32], /// The transaction's weight. pub weight: u64, /// The transaction's fee. diff --git a/types/Cargo.toml b/types/Cargo.toml index 29887bdb..e1ffb196 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -12,21 +12,23 @@ keywords = ["cuprate", "types"] default = ["blockchain", "epee", "serde", "json", "hex"] blockchain = [] epee = ["dep:cuprate-epee-encoding"] -serde = ["dep:serde"] +serde = ["dep:serde", "hex"] proptest = ["dep:proptest", "dep:proptest-derive"] json = ["hex", "dep:cuprate-helper"] -hex = ["dep:hex"] +# We sadly have no choice but to enable serde here as otherwise we will get warnings from the `hex` dep being unused. +# This isn't too bad as `HexBytes` only makes sense with serde anyway. +hex = ["serde", "dep:hex"] [dependencies] cuprate-epee-encoding = { workspace = true, optional = true, features = ["std"] } cuprate-helper = { workspace = true, optional = true, features = ["cast"] } -cuprate-fixed-bytes = { workspace = true } +cuprate-fixed-bytes = { workspace = true, features = ["std", "serde"] } bytes = { workspace = true } curve25519-dalek = { workspace = true } monero-serai = { workspace = true } hex = { workspace = true, features = ["serde", "alloc"], optional = true } -serde = { workspace = true, features = ["derive"], optional = true } +serde = { workspace = true, features = ["std", "derive"], optional = true } strum = { workspace = true, features = ["derive"] } thiserror = { workspace = true } diff --git a/types/src/address_type.rs b/types/src/address_type.rs new file mode 100644 index 00000000..743902da --- /dev/null +++ b/types/src/address_type.rs @@ -0,0 +1,147 @@ +//! Types of network addresses; used in P2P. + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "epee")] +use cuprate_epee_encoding::{ + error, + macros::bytes::{Buf, BufMut}, + EpeeValue, Marker, +}; + +use strum::{ + AsRefStr, Display, EnumCount, EnumIs, EnumString, FromRepr, IntoStaticStr, VariantArray, +}; + +/// An enumeration of address types. +/// +/// Used in `cuprate_p2p` and `cuprate_types` +/// +/// Original definition: +/// - +/// +/// # Serde +/// This type's `serde` implementation (de)serializes from a [`u8`]. +/// +/// ```rust +/// use cuprate_types::AddressType as A; +/// use serde_json::{to_string, from_str}; +/// +/// assert_eq!(from_str::(&"0").unwrap(), A::Invalid); +/// assert_eq!(from_str::(&"1").unwrap(), A::Ipv4); +/// assert_eq!(from_str::(&"2").unwrap(), A::Ipv6); +/// assert_eq!(from_str::(&"3").unwrap(), A::I2p); +/// assert_eq!(from_str::(&"4").unwrap(), A::Tor); +/// +/// assert_eq!(to_string(&A::Invalid).unwrap(), "0"); +/// assert_eq!(to_string(&A::Ipv4).unwrap(), "1"); +/// assert_eq!(to_string(&A::Ipv6).unwrap(), "2"); +/// assert_eq!(to_string(&A::I2p).unwrap(), "3"); +/// assert_eq!(to_string(&A::Tor).unwrap(), "4"); +/// ``` +#[derive( + Copy, + Clone, + Default, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + AsRefStr, + Display, + EnumCount, + EnumIs, + EnumString, + FromRepr, + IntoStaticStr, + VariantArray, +)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(untagged, try_from = "u8", into = "u8"))] +#[repr(u8)] +pub enum AddressType { + #[default] + Invalid, + Ipv4, + Ipv6, + I2p, + Tor, +} + +impl AddressType { + /// Convert [`Self`] to a [`u8`]. + /// + /// ```rust + /// use cuprate_types::AddressType as A; + /// + /// assert_eq!(A::Invalid.to_u8(), 0); + /// assert_eq!(A::Ipv4.to_u8(), 1); + /// assert_eq!(A::Ipv6.to_u8(), 2); + /// assert_eq!(A::I2p.to_u8(), 3); + /// assert_eq!(A::Tor.to_u8(), 4); + /// ``` + pub const fn to_u8(self) -> u8 { + self as u8 + } + + /// Convert a [`u8`] to a [`Self`]. + /// + /// # Errors + /// This returns [`None`] if `u > 4`. + /// + /// ```rust + /// use cuprate_types::AddressType as A; + /// + /// assert_eq!(A::from_u8(0), Some(A::Invalid)); + /// assert_eq!(A::from_u8(1), Some(A::Ipv4)); + /// assert_eq!(A::from_u8(2), Some(A::Ipv6)); + /// assert_eq!(A::from_u8(3), Some(A::I2p)); + /// assert_eq!(A::from_u8(4), Some(A::Tor)); + /// assert_eq!(A::from_u8(5), None); + /// ``` + pub const fn from_u8(u: u8) -> Option { + Some(match u { + 0 => Self::Invalid, + 1 => Self::Ipv4, + 2 => Self::Ipv6, + 3 => Self::I2p, + 4 => Self::Tor, + _ => return None, + }) + } +} + +impl From for u8 { + fn from(value: AddressType) -> Self { + value.to_u8() + } +} + +impl TryFrom for AddressType { + type Error = u8; + fn try_from(value: u8) -> Result { + match Self::from_u8(value) { + Some(s) => Ok(s), + None => Err(value), + } + } +} + +#[cfg(feature = "epee")] +impl EpeeValue for AddressType { + const MARKER: Marker = u8::MARKER; + + fn read(r: &mut B, marker: &Marker) -> error::Result { + let u = u8::read(r, marker)?; + Self::from_u8(u).ok_or(error::Error::Format("u8 was greater than 4")) + } + + fn write(self, w: &mut B) -> error::Result<()> { + let u = self.to_u8(); + u8::write(u, w)?; + Ok(()) + } +} diff --git a/types/src/block_complete_entry.rs b/types/src/block_complete_entry.rs index 77ed82dd..af5fa883 100644 --- a/types/src/block_complete_entry.rs +++ b/types/src/block_complete_entry.rs @@ -136,7 +136,7 @@ impl TransactionBlobs { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct PrunedTxBlobEntry { /// The transaction. - pub tx: Bytes, + pub blob: Bytes, /// The prunable transaction hash. pub prunable_hash: ByteArray<32>, } @@ -144,7 +144,7 @@ pub struct PrunedTxBlobEntry { #[cfg(feature = "epee")] epee_object!( PrunedTxBlobEntry, - tx: Bytes, + blob: Bytes, prunable_hash: ByteArray<32>, ); diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index f908d894..b5da7cb7 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -13,7 +13,7 @@ use monero_serai::block::Block; use crate::{ types::{ Chain, ExtendedBlockHeader, MissingTxsInBlock, OutputOnChain, VerifiedBlockInformation, - }, + }, ChainInfo, AltBlockInformation, BlockCompleteEntry, ChainId, CoinbaseTxSum, OutputHistogramEntry, OutputHistogramInput, }; @@ -132,9 +132,7 @@ pub enum BlockchainReadRequest { AltBlocksInChain(ChainId), /// Get a [`Block`] by its height. - Block { - height: usize, - }, + Block { height: usize }, /// Get a [`Block`] by its hash. BlockByHash([u8; 32]), @@ -154,10 +152,13 @@ pub enum BlockchainReadRequest { /// `N` last blocks starting at particular height. /// /// TODO: document fields after impl. - CoinbaseTxSum { - height: usize, - count: u64, - }, + CoinbaseTxSum { height: usize, count: u64 }, + + /// Get information on all alternative chains. + AltChains, + + /// Get the amount of alternative chains that exist. + AltChainCount, } //---------------------------------------------------------------------------------------------------- WriteRequest @@ -329,6 +330,12 @@ pub enum BlockchainResponse { /// Response to [`BlockchainReadRequest::CoinbaseTxSum`]. CoinbaseTxSum(CoinbaseTxSum), + /// Response to [`BlockchainReadRequest::AltChains`]. + AltChains(Vec), + + /// Response to [`BlockchainReadRequest::AltChainCount`]. + AltChainCount(usize), + //------------------------------------------------------ Writes /// A generic Ok response to indicate a request was successfully handled. /// diff --git a/types/src/connection_state.rs b/types/src/connection_state.rs new file mode 100644 index 00000000..69b8ed64 --- /dev/null +++ b/types/src/connection_state.rs @@ -0,0 +1,148 @@ +//! [`ConnectionState`]. + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "epee")] +use cuprate_epee_encoding::{ + error, + macros::bytes::{Buf, BufMut}, + EpeeValue, Marker, +}; + +use strum::{ + AsRefStr, Display, EnumCount, EnumIs, EnumString, FromRepr, IntoStaticStr, VariantArray, +}; + +/// An enumeration of P2P connection states. +/// +/// Used in `cuprate_p2p` and `cuprate_rpc_types`. +/// +/// Original definition: +/// - +/// +/// # Serde +/// This type's `serde` implementation depends on `snake_case`. +/// +/// ```rust +/// use cuprate_types::ConnectionState as C; +/// use serde_json::to_string; +/// +/// assert_eq!(to_string(&C::BeforeHandshake).unwrap(), r#""before_handshake""#); +/// assert_eq!(to_string(&C::Synchronizing).unwrap(), r#""synchronizing""#); +/// assert_eq!(to_string(&C::Standby).unwrap(), r#""standby""#); +/// assert_eq!(to_string(&C::Idle).unwrap(), r#""idle""#); +/// assert_eq!(to_string(&C::Normal).unwrap(), r#""normal""#); +/// +/// assert_eq!(C::BeforeHandshake.to_string(), "before_handshake"); +/// assert_eq!(C::Synchronizing.to_string(), "synchronizing"); +/// assert_eq!(C::Standby.to_string(), "standby"); +/// assert_eq!(C::Idle.to_string(), "idle"); +/// assert_eq!(C::Normal.to_string(), "normal"); +/// ``` +#[derive( + Copy, + Clone, + Default, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + AsRefStr, + Display, + EnumCount, + EnumIs, + EnumString, + FromRepr, + IntoStaticStr, + VariantArray, +)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] // cuprate-rpc-types depends on snake_case +#[strum(serialize_all = "snake_case")] +#[repr(u8)] +pub enum ConnectionState { + BeforeHandshake, + Synchronizing, + Standby, + Idle, + #[default] + Normal, +} + +impl ConnectionState { + /// Convert [`Self`] to a [`u8`]. + /// + /// ```rust + /// use cuprate_types::ConnectionState as C; + /// + /// assert_eq!(C::BeforeHandshake.to_u8(), 0); + /// assert_eq!(C::Synchronizing.to_u8(), 1); + /// assert_eq!(C::Standby.to_u8(), 2); + /// assert_eq!(C::Idle.to_u8(), 3); + /// assert_eq!(C::Normal.to_u8(), 4); + /// ``` + pub const fn to_u8(self) -> u8 { + self as u8 + } + + /// Convert a [`u8`] to a [`Self`]. + /// + /// # Errors + /// This returns [`None`] if `u > 4`. + /// + /// ```rust + /// use cuprate_types::ConnectionState as C; + /// + /// assert_eq!(C::from_u8(0), Some(C::BeforeHandshake)); + /// assert_eq!(C::from_u8(1), Some(C::Synchronizing)); + /// assert_eq!(C::from_u8(2), Some(C::Standby)); + /// assert_eq!(C::from_u8(3), Some(C::Idle)); + /// assert_eq!(C::from_u8(4), Some(C::Normal)); + /// assert_eq!(C::from_u8(5), None); + /// ``` + pub const fn from_u8(u: u8) -> Option { + Some(match u { + 0 => Self::BeforeHandshake, + 1 => Self::Synchronizing, + 2 => Self::Standby, + 3 => Self::Idle, + 4 => Self::Normal, + _ => return None, + }) + } +} + +impl From for u8 { + fn from(value: ConnectionState) -> Self { + value.to_u8() + } +} + +impl TryFrom for ConnectionState { + type Error = u8; + fn try_from(value: u8) -> Result { + match Self::from_u8(value) { + Some(s) => Ok(s), + None => Err(value), + } + } +} + +#[cfg(feature = "epee")] +impl EpeeValue for ConnectionState { + const MARKER: Marker = u8::MARKER; + + fn read(r: &mut B, marker: &Marker) -> error::Result { + let u = u8::read(r, marker)?; + Self::from_u8(u).ok_or(error::Error::Format("u8 was greater than 4")) + } + + fn write(self, w: &mut B) -> error::Result<()> { + let u = self.to_u8(); + u8::write(u, w)?; + Ok(()) + } +} diff --git a/types/src/hex.rs b/types/src/hex.rs index 34da09d8..de4fc816 100644 --- a/types/src/hex.rs +++ b/types/src/hex.rs @@ -22,6 +22,7 @@ pub struct HexBytes( #[cfg_attr(feature = "serde", serde(with = "hex::serde"))] pub [u8; N], ); +#[cfg(feature = "serde")] impl<'de, const N: usize> Deserialize<'de> for HexBytes where [u8; N]: hex::FromHex, diff --git a/types/src/json/block.rs b/types/src/json/block.rs index 1397f6fd..88f134d5 100644 --- a/types/src/json/block.rs +++ b/types/src/json/block.rs @@ -51,17 +51,17 @@ impl From for Block { /// [`Block::miner_tx`]. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[serde(untagged)] +#[cfg_attr(feature = "serde", serde(untagged))] pub enum MinerTransaction { V1 { /// This field is [flattened](https://serde.rs/field-attrs.html#flatten). - #[serde(flatten)] + #[cfg_attr(feature = "serde", serde(flatten))] prefix: MinerTransactionPrefix, signatures: [(); 0], }, V2 { /// This field is [flattened](https://serde.rs/field-attrs.html#flatten). - #[serde(flatten)] + #[cfg_attr(feature = "serde", serde(flatten))] prefix: MinerTransactionPrefix, rct_signatures: MinerTransactionRctSignatures, }, diff --git a/types/src/json/output.rs b/types/src/json/output.rs index 050132ae..182618cd 100644 --- a/types/src/json/output.rs +++ b/types/src/json/output.rs @@ -20,7 +20,7 @@ pub struct Output { /// [`Output::target`]. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[serde(untagged)] +#[cfg_attr(feature = "serde", serde(untagged))] pub enum Target { Key { key: HexBytes<32> }, TaggedKey { tagged_key: TaggedKey }, diff --git a/types/src/json/tx.rs b/types/src/json/tx.rs index 46ec827b..a18dc89a 100644 --- a/types/src/json/tx.rs +++ b/types/src/json/tx.rs @@ -24,17 +24,17 @@ use crate::{ /// - [`/get_transaction_pool` -> `tx_json`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_transaction_pool) #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[serde(untagged)] +#[cfg_attr(feature = "serde", serde(untagged))] pub enum Transaction { V1 { /// This field is [flattened](https://serde.rs/field-attrs.html#flatten). - #[serde(flatten)] + #[cfg_attr(feature = "serde", serde(flatten))] prefix: TransactionPrefix, signatures: Vec>, }, V2 { /// This field is [flattened](https://serde.rs/field-attrs.html#flatten). - #[serde(flatten)] + #[cfg_attr(feature = "serde", serde(flatten))] prefix: TransactionPrefix, rct_signatures: RctSignatures, /// This field is [`Some`] if [`Self::V2::rct_signatures`] diff --git a/types/src/lib.rs b/types/src/lib.rs index b86bb20f..a5a04f9d 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -9,19 +9,23 @@ // // Documentation for each module is located in the respective file. +mod address_type; mod block_complete_entry; +mod connection_state; mod hard_fork; mod transaction_verification_data; mod types; +pub use address_type::AddressType; pub use block_complete_entry::{BlockCompleteEntry, PrunedTxBlobEntry, TransactionBlobs}; +pub use connection_state::ConnectionState; pub use hard_fork::{HardFork, HardForkError}; pub use transaction_verification_data::{ CachedVerificationState, TransactionVerificationData, TxVersion, }; pub use types::{ - AltBlockInformation, Chain, ChainId, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, - FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry, MissingTxsInBlock, + AddAuxPow, AltBlockInformation, AuxPow, Chain, ChainId, ChainInfo, CoinbaseTxSum, + ExtendedBlockHeader, FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry, OutputHistogramEntry, OutputHistogramInput, OutputOnChain, VerifiedBlockInformation, VerifiedTransactionInformation, }; diff --git a/types/src/types.rs b/types/src/types.rs index 4c269cd6..6386e917 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -177,8 +177,6 @@ pub struct OutputHistogramEntry { pub struct CoinbaseTxSum { pub emission_amount: u128, pub fee_amount: u128, - pub wide_emission_amount: u128, - pub wide_fee_amount: u128, } /// Data to create a custom block template. @@ -242,7 +240,23 @@ pub struct ChainInfo { pub height: u64, pub length: u64, pub main_chain_parent_block: [u8; 32], - pub wide_difficulty: u128, +} + +/// Used in RPC's `add_aux_pow`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AuxPow { + pub id: [u8; 32], + pub hash: [u8; 32], +} + +/// Used in RPC's `add_aux_pow`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AddAuxPow { + pub blocktemplate_blob: Vec, + pub blockhashing_blob: Vec, + pub merkle_root: [u8; 32], + pub merkle_tree_depth: u64, + pub aux_pow: Vec, } #[derive(Clone, Debug, PartialEq, Eq)]