mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 11:39:30 +00:00
Compare commits
9 commits
79b03e386a
...
fd84940ee6
Author | SHA1 | Date | |
---|---|---|---|
|
fd84940ee6 | ||
|
9374d08a07 | ||
|
228a718e04 | ||
|
e30eeb8a35 | ||
|
0cb6a76fc2 | ||
|
544287d88a | ||
5a5f88cb13 | |||
525e20e841 | |||
|
b6c4adc83a |
18 changed files with 397 additions and 221 deletions
34
.github/workflows/audit.yml
vendored
34
.github/workflows/audit.yml
vendored
|
@ -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
|
74
Cargo.lock
generated
74
Cargo.lock
generated
|
@ -87,7 +87,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -98,7 +98,7 @@ checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -292,7 +292,7 @@ dependencies = [
|
|||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
"syn_derive",
|
||||
]
|
||||
|
||||
|
@ -319,7 +319,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -399,7 +399,7 @@ dependencies = [
|
|||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -855,6 +855,14 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuprate-p2p-bucket"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuprate-p2p-core"
|
||||
version = "0.1.0"
|
||||
|
@ -1101,7 +1109,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1122,11 +1130,12 @@ 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",
|
||||
"crossbeam-utils",
|
||||
"hashbrown",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
|
@ -1326,7 +1335,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2091,7 +2100,7 @@ dependencies = [
|
|||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2120,7 +2129,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2217,13 +2226,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]]
|
||||
|
@ -2372,7 +2381,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2579,7 +2588,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2749,7 +2758,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2758,17 +2767,6 @@ version = "2.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
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"
|
||||
|
@ -2789,7 +2787,7 @@ dependencies = [
|
|||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2849,7 +2847,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2909,7 +2907,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3054,7 +3052,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3230,7 +3228,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -3252,7 +3250,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -3334,7 +3332,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3345,7 +3343,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3557,7 +3555,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3577,5 +3575,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn",
|
||||
]
|
||||
|
|
77
Cargo.toml
77
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",
|
||||
|
@ -64,6 +65,7 @@ cuprate-levin = { path = "net/levin" ,default-feature
|
|||
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}
|
||||
|
@ -79,54 +81,55 @@ cuprate-rpc-types = { path = "rpc/types" ,default-feature
|
|||
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 }
|
||||
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 } # <https://github.com/tower-rs/tower/pull/796>
|
||||
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.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! RPC request handler functions (binary endpoints).
|
||||
|
||||
use anyhow::Error;
|
||||
|
||||
use cuprate_rpc_types::{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Dummy implementation of [`RpcHandler`].
|
||||
//! `cuprated`'s implementation of [`RpcHandler`].
|
||||
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
|
@ -7,7 +7,7 @@ use futures::future::BoxFuture;
|
|||
use monero_serai::block::Block;
|
||||
use tower::Service;
|
||||
|
||||
use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
|
||||
use cuprate_blockchain::service::BlockchainReadHandle;
|
||||
use cuprate_consensus::BlockChainContextService;
|
||||
use cuprate_pruning::PruningSeed;
|
||||
use cuprate_rpc_interface::RpcHandler;
|
||||
|
@ -16,8 +16,7 @@ use cuprate_rpc_types::{
|
|||
json::{JsonRpcRequest, JsonRpcResponse},
|
||||
other::{OtherRequest, OtherResponse},
|
||||
};
|
||||
use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle};
|
||||
use cuprate_types::{AddAuxPow, AuxPow, HardFork};
|
||||
use cuprate_txpool::service::TxpoolReadHandle;
|
||||
|
||||
use crate::rpc::{bin, json, other};
|
||||
|
||||
|
|
|
@ -5,27 +5,16 @@
|
|||
//!
|
||||
//! These build on-top of [`crate::rpc::request`] functions.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use futures::StreamExt;
|
||||
use monero_serai::block::Block;
|
||||
use tower::{Service, ServiceExt};
|
||||
|
||||
use cuprate_consensus::BlockchainResponse;
|
||||
use cuprate_constants::rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE};
|
||||
use cuprate_helper::{
|
||||
cast::{u64_to_usize, usize_to_u64},
|
||||
map::split_u128_into_low_high_bits,
|
||||
};
|
||||
use cuprate_helper::{cast::usize_to_u64, map::split_u128_into_low_high_bits};
|
||||
use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus};
|
||||
use cuprate_types::{
|
||||
blockchain::BlockchainReadRequest, Chain, ExtendedBlockHeader, VerifiedBlockInformation,
|
||||
};
|
||||
use cuprate_types::ExtendedBlockHeader;
|
||||
|
||||
use crate::{rpc::request::blockchain, rpc::CupratedRpcHandler};
|
||||
|
||||
fn into_block_header(
|
||||
pub(super) fn into_block_header(
|
||||
height: u64,
|
||||
top_height: u64,
|
||||
fill_pow_hash: bool,
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use std::{
|
||||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
//! RPC request handler functions (JSON-RPC).
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use futures::TryFutureExt;
|
||||
use monero_serai::block::Block;
|
||||
use strum::{EnumCount, VariantArray};
|
||||
use tower::{Service, ServiceExt};
|
||||
|
@ -18,7 +16,7 @@ use cuprate_helper::{
|
|||
cast::{u64_to_usize, usize_to_u64},
|
||||
map::split_u128_into_low_high_bits,
|
||||
};
|
||||
use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet};
|
||||
use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet, Network};
|
||||
use cuprate_rpc_interface::RpcHandler;
|
||||
use cuprate_rpc_types::{
|
||||
base::{AccessResponseBase, ResponseBase},
|
||||
|
@ -48,7 +46,7 @@ use cuprate_rpc_types::{
|
|||
},
|
||||
CORE_RPC_VERSION,
|
||||
};
|
||||
use cuprate_types::{Chain, HardFork};
|
||||
use cuprate_types::HardFork;
|
||||
|
||||
use crate::{
|
||||
constants::VERSION_BUILD,
|
||||
|
@ -60,6 +58,8 @@ use crate::{
|
|||
statics::START_INSTANT_UNIX,
|
||||
};
|
||||
|
||||
use super::constants::FIELD_NOT_SUPPORTED;
|
||||
|
||||
/// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`].
|
||||
pub(super) async fn map_request(
|
||||
state: CupratedRpcHandler,
|
||||
|
@ -135,8 +135,12 @@ async fn on_get_block_hash(
|
|||
request: OnGetBlockHashRequest,
|
||||
) -> Result<OnGetBlockHashResponse, Error> {
|
||||
let [height] = request.block_height;
|
||||
let hash = blockchain::block_hash(&mut state.blockchain_read, height, todo!("access to chain"))
|
||||
.await?;
|
||||
let hash = blockchain::block_hash(
|
||||
&mut state.blockchain_read,
|
||||
height,
|
||||
todo!("access to `cuprated`'s Chain"),
|
||||
)
|
||||
.await?;
|
||||
let block_hash = hex::encode(hash);
|
||||
|
||||
Ok(OnGetBlockHashResponse { block_hash })
|
||||
|
@ -171,8 +175,9 @@ async fn generate_blocks(
|
|||
return Err(anyhow!("Regtest required when generating blocks"));
|
||||
}
|
||||
|
||||
// TODO: is this value only used as a local variable in the handler?
|
||||
// it may not be needed in the request type.
|
||||
// FIXME:
|
||||
// is this field only used as a local variable in the handler in `monerod`?
|
||||
// It may not be needed in the request type.
|
||||
let prev_block = helper::hex_to_hash(request.prev_block)?;
|
||||
|
||||
let (blocks, height) = blockchain_manager::generate_blocks(
|
||||
|
@ -273,32 +278,39 @@ async fn get_block_headers_range(
|
|||
return Err(anyhow!("Invalid start/end heights"));
|
||||
}
|
||||
|
||||
if state.restricted()
|
||||
&& request.end_height.saturating_sub(request.start_height) + 1
|
||||
> RESTRICTED_BLOCK_HEADER_RANGE
|
||||
{
|
||||
let too_many_blocks = || {
|
||||
request.end_height.saturating_sub(request.start_height) + 1 > RESTRICTED_BLOCK_HEADER_RANGE
|
||||
};
|
||||
|
||||
if state.restricted() && too_many_blocks() {
|
||||
return Err(anyhow!("Too many block headers requested."));
|
||||
}
|
||||
|
||||
let block_len = u64_to_usize(request.end_height.saturating_sub(request.start_height));
|
||||
let mut tasks = Vec::with_capacity(block_len);
|
||||
let mut headers = Vec::with_capacity(block_len);
|
||||
// FIXME:
|
||||
// This code currently:
|
||||
// 1. requests a specific `(Block, BlockHeader)`
|
||||
// 2. maps them to the RPC type
|
||||
// 3. pushes them to the a `Vec` sequentially
|
||||
//
|
||||
// It could be more efficient by:
|
||||
// 1. requesting all `(Block, Header)`s in the range at once
|
||||
// 2. mapping all at once and collect into a `Vec`
|
||||
//
|
||||
// This isn't currently possible because there
|
||||
// is no internal request for a range of blocks.
|
||||
|
||||
{
|
||||
let ready = state.blockchain_read.ready().await?;
|
||||
for height in request.start_height..=request.end_height {
|
||||
let height = u64_to_usize(height);
|
||||
let task = tokio::task::spawn(ready.call(BlockchainReadRequest::Block { height }));
|
||||
tasks.push(task);
|
||||
}
|
||||
}
|
||||
let (range, expected_len) = {
|
||||
let start = u64_to_usize(request.start_height);
|
||||
let end = u64_to_usize(request.end_height).saturating_add(1);
|
||||
(start..end, end.saturating_sub(start))
|
||||
};
|
||||
|
||||
for task in tasks {
|
||||
let BlockchainResponse::Block(header) = task.await?? else {
|
||||
unreachable!();
|
||||
};
|
||||
// headers.push((&header).into());
|
||||
headers.push(todo!());
|
||||
let mut headers = Vec::with_capacity(expected_len);
|
||||
|
||||
for height in range {
|
||||
let height = usize_to_u64(height);
|
||||
let header = helper::block_header(&mut state, height, request.fill_pow_hash).await?;
|
||||
headers.push(header);
|
||||
}
|
||||
|
||||
Ok(GetBlockHeadersRangeResponse {
|
||||
|
@ -390,7 +402,11 @@ async fn get_info(
|
|||
split_u128_into_low_high_bits(cumulative_difficulty);
|
||||
let (database_size, free_space) = blockchain::database_size(&mut state.blockchain_read).await?;
|
||||
let (database_size, free_space) = if restricted {
|
||||
let database_size = todo!(); // round_up(res.database_size, 5ull* 1024 * 1024 * 1024) */
|
||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L131-L134>
|
||||
fn round_up(value: u64, quantum: u64) -> u64 {
|
||||
(value + quantum - 1) / quantum * quantum
|
||||
}
|
||||
let database_size = round_up(database_size, 5 * 1024 * 1024 * 1024);
|
||||
(database_size, u64::MAX)
|
||||
} else {
|
||||
(database_size, free_space)
|
||||
|
@ -403,22 +419,37 @@ async fn get_info(
|
|||
} else {
|
||||
address_book::connection_count::<ClearNet>(&mut DummyAddressBook).await?
|
||||
};
|
||||
let mainnet = todo!();
|
||||
let nettype = todo!();
|
||||
let offline = todo!();
|
||||
let rpc_connections_count = if restricted { 0 } else { todo!() };
|
||||
let stagenet = todo!();
|
||||
let (mainnet, testnet, stagenet) = match todo!("access to `cuprated`'s `Network`") {
|
||||
Network::Mainnet => (true, false, false),
|
||||
Network::Testnet => (false, true, false),
|
||||
Network::Stagenet => (false, false, true),
|
||||
};
|
||||
// TODO: make sure this is:
|
||||
// - the same case as `monerod`
|
||||
// - untagged (no `Network::`)
|
||||
let nettype = todo!("access to `cuprated`'s `Network`").to_string();
|
||||
let offline = todo!("access to CLI/config's `--offline`");
|
||||
let rpc_connections_count = if restricted {
|
||||
0
|
||||
} else {
|
||||
todo!(
|
||||
"implement a connection counter in axum/RPC, maybe `AtomicU64` any handler activating"
|
||||
)
|
||||
};
|
||||
let start_time = if restricted { 0 } else { *START_INSTANT_UNIX };
|
||||
let synchronized = blockchain_manager::synced(&mut state.blockchain_manager).await?;
|
||||
let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?;
|
||||
let target = blockchain_manager::target(&mut state.blockchain_manager)
|
||||
.await?
|
||||
.as_secs();
|
||||
let testnet = todo!();
|
||||
let top_block_hash = hex::encode(c.top_hash);
|
||||
let tx_count = blockchain::total_tx_count(&mut state.blockchain_read).await?;
|
||||
let tx_pool_size = txpool::size(&mut state.txpool_read, !restricted).await?;
|
||||
let update_available = if restricted { false } else { todo!() };
|
||||
let update_available = if restricted {
|
||||
false
|
||||
} else {
|
||||
todo!("implement an update checker for `cuprated`")
|
||||
};
|
||||
let version = if restricted {
|
||||
String::new()
|
||||
} else {
|
||||
|
@ -570,7 +601,16 @@ async fn banned(
|
|||
state: CupratedRpcHandler,
|
||||
request: BannedRequest,
|
||||
) -> Result<BannedResponse, Error> {
|
||||
let peer = todo!("create Z::Addr from request.address");
|
||||
let peer = match request.address.parse::<std::net::SocketAddr>() {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
return Err(anyhow!(
|
||||
"Failed to parse address: {} ({e})",
|
||||
request.address
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let ban = address_book::get_ban::<ClearNet>(&mut DummyAddressBook, peer).await?;
|
||||
|
||||
let (banned, seconds) = if let Some(instant) = ban {
|
||||
|
@ -677,7 +717,7 @@ async fn get_version(
|
|||
|
||||
let mut hard_forks = Vec::with_capacity(HardFork::COUNT);
|
||||
|
||||
// FIXME: use an iterator `collect()` version.
|
||||
// FIXME: use an async iterator `collect()` version.
|
||||
for hf in HardFork::VARIANTS {
|
||||
if let Ok(hf) = blockchain_context::hard_fork_info(&mut state.blockchain_context, *hf).await
|
||||
{
|
||||
|
@ -784,16 +824,15 @@ async fn sync_info(
|
|||
.map(|info| SyncInfoPeer { info })
|
||||
.collect();
|
||||
|
||||
// TODO
|
||||
// let next_needed_pruning_seed =
|
||||
// address_book::next_needed_pruning_seed::<ClearNet>(&mut DummyAddressBook)
|
||||
// .await?
|
||||
// .compress();
|
||||
// let overview = blockchain_manager::overview(&mut state.blockchain_manager, height).await?;
|
||||
// let spans = address_book::spans::<ClearNet>(&mut DummyAddressBook).await?;
|
||||
let next_needed_pruning_seed = todo!();
|
||||
let overview = todo!();
|
||||
let spans = todo!();
|
||||
let next_needed_pruning_seed =
|
||||
blockchain_manager::next_needed_pruning_seed(&mut state.blockchain_manager)
|
||||
.await?
|
||||
.compress();
|
||||
|
||||
let spans = blockchain_manager::spans::<ClearNet>(&mut state.blockchain_manager).await?;
|
||||
|
||||
// <https://github.com/Cuprate/cuprate/pull/320#discussion_r1811063772>
|
||||
let overview = String::from(FIELD_NOT_SUPPORTED);
|
||||
|
||||
Ok(SyncInfoResponse {
|
||||
base: AccessResponseBase::OK,
|
||||
|
@ -833,24 +872,24 @@ async fn get_miner_data(
|
|||
request: GetMinerDataRequest,
|
||||
) -> Result<GetMinerDataResponse, Error> {
|
||||
let context = blockchain_context::context(&mut state.blockchain_context).await?;
|
||||
let context = context.unchecked_blockchain_context();
|
||||
let major_version = context.current_hf.as_u8();
|
||||
let height = usize_to_u64(context.chain_height);
|
||||
let prev_id = hex::encode(context.top_hash);
|
||||
let seed_hash = todo!();
|
||||
let difficulty = format!("{:#x}", context.next_difficulty);
|
||||
let median_weight = usize_to_u64(context.median_weight_for_block_reward);
|
||||
let already_generated_coins = context.already_generated_coins;
|
||||
let tx_backlog = todo!();
|
||||
// let tx_backlog = txpool::block_template_backlog(&mut state.txpool_read)
|
||||
// .await?
|
||||
// .into_iter()
|
||||
// .map(|entry| GetMinerDataTxBacklogEntry {
|
||||
// id: hex::encode(entry.id),
|
||||
// weight: entry.weight,
|
||||
// fee: entry.fee,
|
||||
// })
|
||||
// .collect();
|
||||
let c = context.unchecked_blockchain_context();
|
||||
|
||||
let major_version = c.current_hf.as_u8();
|
||||
let height = usize_to_u64(c.chain_height);
|
||||
let prev_id = hex::encode(c.top_hash);
|
||||
let seed_hash = hex::encode(c.top_hash);
|
||||
let difficulty = format!("{:#x}", c.next_difficulty);
|
||||
let median_weight = usize_to_u64(c.median_weight_for_block_reward);
|
||||
let already_generated_coins = c.already_generated_coins;
|
||||
let tx_backlog = txpool::backlog(&mut state.txpool_read)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|entry| GetMinerDataTxBacklogEntry {
|
||||
id: hex::encode(entry.id),
|
||||
weight: entry.weight,
|
||||
fee: entry.fee,
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(GetMinerDataResponse {
|
||||
base: ResponseBase::OK,
|
||||
|
@ -971,7 +1010,7 @@ async fn get_tx_ids_loose(
|
|||
request: GetTxIdsLooseRequest,
|
||||
) -> Result<GetTxIdsLooseResponse, Error> {
|
||||
// TODO: this RPC call is not yet in the v0.18 branch.
|
||||
return Err(anyhow!("not implemented"));
|
||||
return Err(anyhow!("Not implemented"));
|
||||
|
||||
Ok(GetTxIdsLooseResponse {
|
||||
base: ResponseBase::OK,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! RPC request handler functions (other JSON endpoints).
|
||||
|
||||
use anyhow::Error;
|
||||
|
||||
use cuprate_rpc_types::other::{
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Functions for TODO: doc enum message.
|
||||
|
||||
use std::convert::Infallible;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use tower::ServiceExt;
|
||||
|
||||
|
@ -11,12 +9,7 @@ use cuprate_p2p_core::{
|
|||
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.
|
||||
use cuprate_rpc_types::misc::ConnectionInfo;
|
||||
|
||||
// FIXME: use `anyhow::Error` over `tower::BoxError` in address book.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Functions for [`BlockchainReadRequest`].
|
||||
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap, HashSet},
|
||||
collections::{HashMap, HashSet},
|
||||
ops::Range,
|
||||
};
|
||||
|
||||
|
@ -9,12 +9,12 @@ use anyhow::Error;
|
|||
use monero_serai::block::Block;
|
||||
use tower::{Service, ServiceExt};
|
||||
|
||||
use cuprate_blockchain::{service::BlockchainReadHandle, types::AltChainInfo};
|
||||
use cuprate_blockchain::service::BlockchainReadHandle;
|
||||
use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
|
||||
use cuprate_types::{
|
||||
blockchain::{BlockchainReadRequest, BlockchainResponse},
|
||||
Chain, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, HardFork, MinerData,
|
||||
OutputHistogramEntry, OutputHistogramInput, OutputOnChain,
|
||||
Chain, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, OutputHistogramEntry,
|
||||
OutputHistogramInput, OutputOnChain,
|
||||
};
|
||||
|
||||
/// [`BlockchainReadRequest::Block`].
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Functions for [`BlockChainContextRequest`] and [`BlockChainContextResponse`].
|
||||
|
||||
use std::convert::Infallible;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use monero_serai::block::Block;
|
||||
use tower::{Service, ServiceExt};
|
||||
|
|
|
@ -8,11 +8,9 @@ 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::{
|
||||
constants::FIELD_NOT_SUPPORTED,
|
||||
handler::{BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse},
|
||||
use crate::rpc::handler::{
|
||||
BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse,
|
||||
};
|
||||
|
||||
/// [`BlockchainManagerRequest::PopBlocks`]
|
||||
|
@ -185,7 +183,8 @@ pub(crate) async fn spans<Z: NetworkZone>(
|
|||
// unreachable!();
|
||||
// };
|
||||
|
||||
let vec: Vec<cuprate_p2p_core::types::Span<Z::Addr>> = todo!();
|
||||
let vec: Vec<cuprate_p2p_core::types::Span<Z::Addr>> =
|
||||
todo!("waiting on blockchain downloader/syncer: <https://github.com/Cuprate/cuprate/pull/320#discussion_r1811089758>");
|
||||
|
||||
// FIXME: impl this map somewhere instead of inline.
|
||||
let vec = vec
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![expect(non_local_definitions, reason = "proptest macro")]
|
||||
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
|
|
|
@ -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
|
||||
|
|
13
p2p/bucket/Cargo.toml
Normal file
13
p2p/bucket/Cargo.toml
Normal file
|
@ -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
|
172
p2p/bucket/src/lib.rs
Normal file
172
p2p/bucket/src/lib.rs
Normal file
|
@ -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<const N: usize, I: Bucketable> {
|
||||
/// The storage of the bucket
|
||||
storage: BTreeMap<I::Discriminant, ArrayVec<I, N>>,
|
||||
}
|
||||
|
||||
impl<const N: usize, I: Bucketable> Bucket<N, I> {
|
||||
/// 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<I> {
|
||||
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::<I, N>::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<I> {
|
||||
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<usize> {
|
||||
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::<usize>() / len).unwrap();
|
||||
|
||||
// Return a reference chose at random.
|
||||
vec.get(random::<usize>() / vec.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, I: Bucketable> Default for Bucket<N, I> {
|
||||
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]]
|
||||
}
|
||||
}
|
|
@ -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>,
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue