mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-22 11:39:26 +00:00
remove empty cuprate bin and common
This commit is contained in:
parent
b20b6fdee1
commit
ed598e374e
51 changed files with 142 additions and 1027 deletions
67
Cargo.lock
generated
67
Cargo.lock
generated
|
@ -428,31 +428,20 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuprate-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"chrono",
|
||||
"futures",
|
||||
"hex",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuprate-consensus"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"clap",
|
||||
"cuprate-common",
|
||||
"cuprate-helper",
|
||||
"curve25519-dalek",
|
||||
"dalek-ff-group",
|
||||
"dirs",
|
||||
"futures",
|
||||
"hex",
|
||||
"monero-consensus",
|
||||
"monero-epee-bin-serde 1.0.1 (git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=e4a585a)",
|
||||
"monero-epee-bin-serde",
|
||||
"monero-serai",
|
||||
"monero-wire",
|
||||
"multiexp",
|
||||
|
@ -472,6 +461,18 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuprate-helper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures",
|
||||
"libc",
|
||||
"rayon",
|
||||
"tokio",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuprate-test-utils"
|
||||
version = "0.1.0"
|
||||
|
@ -816,18 +817,6 @@ version = "0.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "helper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures",
|
||||
"libc",
|
||||
"rayon",
|
||||
"tokio",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.4"
|
||||
|
@ -1098,10 +1087,10 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"async-trait",
|
||||
"borsh",
|
||||
"cuprate-common",
|
||||
"cuprate-test-utils",
|
||||
"futures",
|
||||
"monero-p2p",
|
||||
"monero-pruning",
|
||||
"monero-wire",
|
||||
"pin-project",
|
||||
"rand",
|
||||
|
@ -1117,7 +1106,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"crypto-bigint",
|
||||
"cryptonight-cuprate",
|
||||
"cuprate-common",
|
||||
"cuprate-helper",
|
||||
"curve25519-dalek",
|
||||
"dalek-ff-group",
|
||||
"hex",
|
||||
|
@ -1136,22 +1125,13 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "monero-epee-bin-serde"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=aafe4ba#aafe4ba1b9912b03cf616db7403628fc2bd82eb1"
|
||||
source = "git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=fae7a23#fae7a23f8e57f19553c341c0878b4f0fa5a6994d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monero-epee-bin-serde"
|
||||
version = "1.0.1"
|
||||
source = "git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=e4a585a#e4a585a9deda5f888ebca766d5e61a2bb987147c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monero-generators"
|
||||
version = "0.4.0"
|
||||
|
@ -1171,10 +1151,11 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"async-trait",
|
||||
"borsh",
|
||||
"cuprate-common",
|
||||
"cuprate-helper",
|
||||
"cuprate-test-utils",
|
||||
"futures",
|
||||
"hex",
|
||||
"monero-pruning",
|
||||
"monero-wire",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
|
@ -1185,6 +1166,14 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monero-pruning"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monero-serai"
|
||||
version = "0.1.4-alpha"
|
||||
|
@ -1225,7 +1214,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"hex",
|
||||
"levin-cuprate",
|
||||
"monero-epee-bin-serde 1.0.1 (git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=aafe4ba)",
|
||||
"monero-epee-bin-serde",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"thiserror",
|
||||
|
|
|
@ -2,18 +2,16 @@
|
|||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"common",
|
||||
"consensus",
|
||||
"consensus/rules",
|
||||
"cryptonight",
|
||||
# "cuprate",
|
||||
# "database",
|
||||
"helper",
|
||||
"net/levin",
|
||||
"net/monero-wire",
|
||||
"p2p/monero-p2p",
|
||||
"p2p/address-book",
|
||||
"test-utils"
|
||||
"pruning",
|
||||
"test-utils",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
@ -47,7 +45,7 @@ dirs = { version = "5.0.1", default-features = false }
|
|||
futures = { version = "0.3.29", default-features = false }
|
||||
hex = { version = "0.4.3", default-features = false }
|
||||
hex-literal = { version = "0.4", default-features = false }
|
||||
monero-epee-bin-serde = { git = "https://github.com/monero-rs/monero-epee-bin-serde.git", rev = "e4a585a", default-features = false }
|
||||
monero-epee-bin-serde = { git = "https://github.com/monero-rs/monero-epee-bin-serde.git", rev = "fae7a23", default-features = false }
|
||||
monero-serai = { git = "https://github.com/Cuprate/serai.git", rev = "a59966b", default-features = false }
|
||||
multiexp = { git = "https://github.com/Cuprate/serai.git", rev = "a59966b", default-features = false }
|
||||
pin-project = { version = "1.1.3", default-features = false }
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
[package]
|
||||
name = "cuprate-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-only"
|
||||
authors = ["Boog900"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
borsh = ["dep:borsh"]
|
||||
|
||||
[dependencies]
|
||||
chrono = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
hex = { workspace = true, features = ["std"] }
|
||||
|
||||
futures = { workspace = true, features = ["std"] }
|
||||
|
||||
borsh = { workspace = true, features = ["derive", "std"], optional = true }
|
|
@ -1,14 +0,0 @@
|
|||
Copyright (C) 2023 Cuprate Contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@ -1,250 +0,0 @@
|
|||
use chrono::NaiveDateTime;
|
||||
|
||||
use crate::network::Network;
|
||||
|
||||
// this function blindly unwraps
|
||||
// SAFETY: only call when you know the timestamp is good
|
||||
fn time_from_timestamp(stamp: i64) -> NaiveDateTime {
|
||||
NaiveDateTime::from_timestamp_opt(stamp, 0).unwrap()
|
||||
}
|
||||
|
||||
fn get_hard_forks(network: Network) -> [(u8, u64, NaiveDateTime); 16] {
|
||||
match network {
|
||||
Network::MainNet => {
|
||||
[
|
||||
// | version | Height | TimeStamp | *timestamp is when fork height was decided
|
||||
(1, 1, time_from_timestamp(1341378000)),
|
||||
(2, 1009827, time_from_timestamp(1442763710)),
|
||||
(3, 1141317, time_from_timestamp(1458558528)),
|
||||
(4, 1220516, time_from_timestamp(1483574400)),
|
||||
(5, 1288616, time_from_timestamp(1489520158)),
|
||||
(6, 1400000, time_from_timestamp(1503046577)),
|
||||
(7, 1546000, time_from_timestamp(1521303150)),
|
||||
(8, 1685555, time_from_timestamp(1535889547)),
|
||||
(9, 1686275, time_from_timestamp(1535889548)),
|
||||
(10, 1788000, time_from_timestamp(1549792439)),
|
||||
(11, 1788720, time_from_timestamp(1550225678)),
|
||||
(12, 1978433, time_from_timestamp(1571419280)),
|
||||
(13, 2210000, time_from_timestamp(1598180817)),
|
||||
(14, 2210720, time_from_timestamp(1598180818)),
|
||||
(15, 2688888, time_from_timestamp(1656629117)),
|
||||
(16, 2689608, time_from_timestamp(1656629118)),
|
||||
]
|
||||
}
|
||||
Network::TestNet => [
|
||||
(1, 1, time_from_timestamp(1341378000)),
|
||||
(2, 624634, time_from_timestamp(1445355000)),
|
||||
(3, 800500, time_from_timestamp(1472415034)),
|
||||
(4, 801219, time_from_timestamp(1472415035)),
|
||||
(5, 802660, time_from_timestamp(1472415036 + 86400 * 180)),
|
||||
(6, 971400, time_from_timestamp(1501709789)),
|
||||
(7, 1057027, time_from_timestamp(1512211236)),
|
||||
(8, 1057058, time_from_timestamp(1533211200)),
|
||||
(9, 1057778, time_from_timestamp(1533297600)),
|
||||
(10, 1154318, time_from_timestamp(1550153694)),
|
||||
(11, 1155038, time_from_timestamp(1550225678)),
|
||||
(12, 1308737, time_from_timestamp(1569582000)),
|
||||
(13, 1543939, time_from_timestamp(1599069376)),
|
||||
(14, 1544659, time_from_timestamp(1599069377)),
|
||||
(15, 1982800, time_from_timestamp(1652727000)),
|
||||
(16, 1983520, time_from_timestamp(1652813400)),
|
||||
],
|
||||
Network::StageNet => [
|
||||
(1, 1, time_from_timestamp(1341378000)),
|
||||
(2, 32000, time_from_timestamp(1521000000)),
|
||||
(3, 33000, time_from_timestamp(1521120000)),
|
||||
(4, 34000, time_from_timestamp(1521240000)),
|
||||
(5, 35000, time_from_timestamp(1521360000)),
|
||||
(6, 36000, time_from_timestamp(1521480000)),
|
||||
(7, 37000, time_from_timestamp(1521600000)),
|
||||
(8, 176456, time_from_timestamp(1537821770)),
|
||||
(9, 177176, time_from_timestamp(1537821771)),
|
||||
(10, 269000, time_from_timestamp(1550153694)),
|
||||
(11, 269720, time_from_timestamp(1550225678)),
|
||||
(12, 454721, time_from_timestamp(1571419280)),
|
||||
(13, 675405, time_from_timestamp(1598180817)),
|
||||
(14, 676125, time_from_timestamp(1598180818)),
|
||||
(15, 1151000, time_from_timestamp(1656629117)),
|
||||
(16, 1151720, time_from_timestamp(1656629118)),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HardForks {
|
||||
hard_forks: [(u8, u64, NaiveDateTime); 16],
|
||||
}
|
||||
|
||||
impl HardForks {
|
||||
pub fn new(network: Network) -> Self {
|
||||
HardForks {
|
||||
hard_forks: get_hard_forks(network),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ideal_version_from_height(&self, height: u64) -> u8 {
|
||||
for hf in self.hard_forks.iter().rev() {
|
||||
if height >= hf.1 {
|
||||
return hf.0;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
pub fn get_earliest_ideal_height_for_version(&self, version: u8) -> Option<u64> {
|
||||
if self.hard_forks.len() < version as usize {
|
||||
None
|
||||
} else if version == 0 {
|
||||
Some(0)
|
||||
} else {
|
||||
Some(self.hard_forks[(version - 1) as usize].1)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ideal_version(&self) -> u8 {
|
||||
self.hard_forks.last().expect("This is not empty").0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::network::Network;
|
||||
|
||||
use super::HardForks;
|
||||
|
||||
const MAIN_NET_FORKS: [u64; 16] = [
|
||||
1, 1009827, 1141317, 1220516, 1288616, 1400000, 1546000, 1685555, 1686275, 1788000,
|
||||
1788720, 1978433, 2210000, 2210720, 2688888, 2689608,
|
||||
];
|
||||
const TEST_NET_FORKS: [u64; 16] = [
|
||||
1, 624634, 800500, 801219, 802660, 971400, 1057027, 1057058, 1057778, 1154318, 1155038,
|
||||
1308737, 1543939, 1544659, 1982800, 1983520,
|
||||
];
|
||||
const STAGE_NET_FORKS: [u64; 16] = [
|
||||
1, 32000, 33000, 34000, 35000, 36000, 37000, 176456, 177176, 269000, 269720, 454721,
|
||||
675405, 676125, 1151000, 1151720,
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn get_ideal_version() {
|
||||
let hardforks = HardForks::new(Network::MainNet);
|
||||
|
||||
let version = hardforks.get_ideal_version();
|
||||
assert_eq!(version as usize, MAIN_NET_FORKS.len());
|
||||
assert_eq!(version as usize, TEST_NET_FORKS.len());
|
||||
assert_eq!(version as usize, STAGE_NET_FORKS.len());
|
||||
|
||||
let height = hardforks
|
||||
.get_earliest_ideal_height_for_version(version)
|
||||
.unwrap();
|
||||
let got_version = hardforks.get_ideal_version_from_height(height);
|
||||
assert_eq!(version, got_version);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_earliest_ideal_height_for_version_mainnet() {
|
||||
let hardforks = HardForks::new(Network::MainNet);
|
||||
|
||||
for (height, version) in MAIN_NET_FORKS.iter().zip(1..MAIN_NET_FORKS.len() as u8) {
|
||||
assert_eq!(
|
||||
hardforks
|
||||
.get_earliest_ideal_height_for_version(version)
|
||||
.unwrap(),
|
||||
*height
|
||||
);
|
||||
assert_eq!(
|
||||
hardforks
|
||||
.get_earliest_ideal_height_for_version(version)
|
||||
.unwrap(),
|
||||
*height
|
||||
);
|
||||
}
|
||||
assert!(hardforks
|
||||
.get_earliest_ideal_height_for_version(MAIN_NET_FORKS.len() as u8 + 1)
|
||||
.is_none())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_earliest_ideal_height_for_version_testnet() {
|
||||
let hardforks = HardForks::new(Network::TestNet);
|
||||
|
||||
for (height, version) in TEST_NET_FORKS.iter().zip(1..TEST_NET_FORKS.len() as u8) {
|
||||
assert_eq!(
|
||||
hardforks
|
||||
.get_earliest_ideal_height_for_version(version)
|
||||
.unwrap(),
|
||||
*height
|
||||
);
|
||||
assert_eq!(
|
||||
hardforks
|
||||
.get_earliest_ideal_height_for_version(version)
|
||||
.unwrap(),
|
||||
*height
|
||||
);
|
||||
}
|
||||
assert!(hardforks
|
||||
.get_earliest_ideal_height_for_version(TEST_NET_FORKS.len() as u8 + 1)
|
||||
.is_none())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_earliest_ideal_height_for_version_stagenet() {
|
||||
let hardforks = HardForks::new(Network::StageNet);
|
||||
|
||||
for (height, version) in STAGE_NET_FORKS.iter().zip(1..STAGE_NET_FORKS.len() as u8) {
|
||||
assert_eq!(
|
||||
hardforks
|
||||
.get_earliest_ideal_height_for_version(version)
|
||||
.unwrap(),
|
||||
*height
|
||||
);
|
||||
assert_eq!(
|
||||
hardforks
|
||||
.get_earliest_ideal_height_for_version(version)
|
||||
.unwrap(),
|
||||
*height
|
||||
);
|
||||
}
|
||||
assert!(hardforks
|
||||
.get_earliest_ideal_height_for_version(STAGE_NET_FORKS.len() as u8 + 1)
|
||||
.is_none())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_ideal_version_from_height_mainnet() {
|
||||
let hardforks = HardForks::new(Network::MainNet);
|
||||
|
||||
for (height, version) in MAIN_NET_FORKS.iter().zip(1..MAIN_NET_FORKS.len() as u8) {
|
||||
assert_eq!(hardforks.get_ideal_version_from_height(*height), version);
|
||||
assert_eq!(
|
||||
hardforks.get_ideal_version_from_height(*height - 1),
|
||||
version - 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_ideal_version_from_height_testnet() {
|
||||
let hardforks = HardForks::new(Network::TestNet);
|
||||
|
||||
for (height, version) in TEST_NET_FORKS.iter().zip(1..TEST_NET_FORKS.len() as u8) {
|
||||
assert_eq!(hardforks.get_ideal_version_from_height(*height), version);
|
||||
assert_eq!(
|
||||
hardforks.get_ideal_version_from_height(*height - 1),
|
||||
version - 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_ideal_version_from_height_stagenet() {
|
||||
let hardforks = HardForks::new(Network::StageNet);
|
||||
|
||||
for (height, version) in STAGE_NET_FORKS.iter().zip(1..STAGE_NET_FORKS.len() as u8) {
|
||||
assert_eq!(hardforks.get_ideal_version_from_height(*height), version);
|
||||
assert_eq!(
|
||||
hardforks.get_ideal_version_from_height(*height - 1),
|
||||
version - 1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
//pub mod hardforks;
|
||||
pub mod network;
|
||||
pub mod pruning;
|
||||
pub mod tower_utils;
|
||||
|
||||
use std::fmt::Formatter;
|
||||
//pub use hardforks::HardForks;
|
||||
pub use network::Network;
|
||||
pub use pruning::{PruningError, PruningSeed};
|
||||
|
||||
pub const CRYPTONOTE_MAX_BLOCK_NUMBER: u64 = 500000000;
|
||||
|
||||
// pruning
|
||||
pub const CRYPTONOTE_PRUNING_LOG_STRIPES: u32 = 3;
|
||||
pub const CRYPTONOTE_PRUNING_STRIPE_SIZE: u64 = 4096;
|
||||
pub const CRYPTONOTE_PRUNING_TIP_BLOCKS: u64 = 5500;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BlockID {
|
||||
Hash([u8; 32]),
|
||||
Height(u64),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for BlockID {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
BlockID::Hash(hash) => f.write_str(&format!("Hash: {}", hex::encode(hash))),
|
||||
BlockID::Height(height) => f.write_str(&format!("Height: {}", height)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for BlockID {
|
||||
fn from(value: u64) -> Self {
|
||||
BlockID::Height(value)
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use futures::channel::oneshot;
|
||||
use futures::FutureExt;
|
||||
|
||||
/// A oneshot that doesn't return an Error. This requires the sender to always
|
||||
/// return a response.
|
||||
pub struct InfallibleOneshotReceiver<T>(oneshot::Receiver<T>);
|
||||
|
||||
impl<T> From<oneshot::Receiver<T>> for InfallibleOneshotReceiver<T> {
|
||||
fn from(value: oneshot::Receiver<T>) -> Self {
|
||||
InfallibleOneshotReceiver(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Future for InfallibleOneshotReceiver<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.0
|
||||
.poll_unpin(cx)
|
||||
.map(|res| res.expect("Oneshot must not be cancelled before response!"))
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ binaries = [
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
cuprate-common = {path = "../common"}
|
||||
cuprate-helper = { path = "../helper", default-features = false, features = ["std", "asynch", "num"] }
|
||||
monero-consensus = {path = "./rules", features = ["rayon"]}
|
||||
|
||||
thiserror = { workspace = true }
|
||||
|
|
|
@ -9,8 +9,8 @@ proptest = ["dep:proptest", "dep:proptest-derive"]
|
|||
rayon = ["dep:rayon"]
|
||||
|
||||
[dependencies]
|
||||
cuprate-helper = { path = "../../helper", default-features = false, features = ["std"] }
|
||||
cryptonight-cuprate = {path = "../../cryptonight"}
|
||||
cuprate-common = {path = "../../common"}
|
||||
|
||||
monero-serai = { workspace = true, features = ["std"] }
|
||||
multiexp = { workspace = true, features = ["std", "batch"] }
|
||||
|
|
|
@ -6,7 +6,7 @@ use monero_serai::{
|
|||
transaction::Transaction,
|
||||
};
|
||||
|
||||
use cuprate_common::Network;
|
||||
use cuprate_helper::network::Network;
|
||||
|
||||
const fn genesis_nonce(network: &Network) -> u32 {
|
||||
match network {
|
||||
|
@ -42,9 +42,7 @@ pub fn generate_genesis_block(network: &Network) -> Block {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use cuprate_common::Network;
|
||||
|
||||
use super::generate_genesis_block;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn generate_genesis_blocks() {
|
||||
|
|
|
@ -19,7 +19,7 @@ mod bin {
|
|||
use tower::{Service, ServiceExt};
|
||||
use tracing::level_filters::LevelFilter;
|
||||
|
||||
use cuprate_common::Network;
|
||||
use cuprate_helper::network::Network;
|
||||
|
||||
use cuprate_consensus::{
|
||||
block::PrePreparedBlockExPOW,
|
||||
|
|
|
@ -13,7 +13,7 @@ mod bin {
|
|||
use monero_serai::transaction::Transaction;
|
||||
use tower::{Service, ServiceExt};
|
||||
|
||||
use cuprate_common::tower_utils::InfallibleOneshotReceiver;
|
||||
use cuprate_helper::asynch::InfallibleOneshotReceiver;
|
||||
|
||||
use cuprate_consensus::{
|
||||
context::{
|
||||
|
|
|
@ -3,9 +3,9 @@ use std::{collections::VecDeque, ops::Range};
|
|||
use tower::ServiceExt;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::{
|
||||
helper::median, Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork,
|
||||
};
|
||||
use cuprate_helper::num::median;
|
||||
|
||||
use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork};
|
||||
|
||||
/// The amount of blocks we account for to calculate difficulty
|
||||
const DIFFICULTY_WINDOW: usize = 720;
|
||||
|
|
|
@ -79,9 +79,7 @@ impl HardForkState {
|
|||
let DatabaseResponse::BlockExtendedHeader(ext_header) = database
|
||||
.ready()
|
||||
.await?
|
||||
.call(DatabaseRequest::BlockExtendedHeader(
|
||||
(chain_height - 1).into(),
|
||||
))
|
||||
.call(DatabaseRequest::BlockExtendedHeader(chain_height - 1))
|
||||
.await?
|
||||
else {
|
||||
panic!("Database sent incorrect response!");
|
||||
|
|
|
@ -16,12 +16,10 @@ use rayon::prelude::*;
|
|||
use tower::ServiceExt;
|
||||
use tracing::instrument;
|
||||
|
||||
use cuprate_helper::{asynch::rayon_spawn_async, num::median};
|
||||
use monero_consensus::blocks::{penalty_free_zone, PENALTY_FREE_ZONE_5};
|
||||
|
||||
use crate::{
|
||||
helper::{median, rayon_spawn_async},
|
||||
Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork,
|
||||
};
|
||||
use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork};
|
||||
|
||||
const SHORT_TERM_WINDOW: u64 = 100;
|
||||
const LONG_TERM_WINDOW: u64 = 100000;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
/// Spawns a task for the rayon thread pool and awaits the result without blocking the async runtime.
|
||||
pub(crate) async fn rayon_spawn_async<F, R>(f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
rayon::spawn(|| {
|
||||
let _ = tx.send(f());
|
||||
});
|
||||
rx.await.expect("The sender must not be dropped")
|
||||
}
|
||||
|
||||
pub(crate) fn get_mid<T>(a: T, b: T) -> T
|
||||
where
|
||||
T: Add<Output = T> + Sub<Output = T> + Div<Output = T> + Mul<Output = T> + Copy + From<u8>,
|
||||
{
|
||||
let two: T = 2_u8.into();
|
||||
|
||||
// https://github.com/monero-project/monero/blob/90294f09ae34ef96f3dea5fea544816786df87c8/contrib/epee/include/misc_language.h#L43
|
||||
(a / two) + (b / two) + ((a - two * (a / two)) + (b - two * (b / two))) / two
|
||||
}
|
||||
|
||||
/// Gets the median from a sorted slice.
|
||||
///
|
||||
/// If not sorted the output will be invalid.
|
||||
pub(crate) fn median<T>(array: &[T]) -> T
|
||||
where
|
||||
T: Add<Output = T> + Sub<Output = T> + Div<Output = T> + Mul<Output = T> + Copy + From<u8>,
|
||||
{
|
||||
let mid = array.len() / 2;
|
||||
|
||||
if array.len() == 1 {
|
||||
return array[0];
|
||||
}
|
||||
|
||||
if array.len() % 2 == 0 {
|
||||
get_mid(array[mid - 1], array[mid])
|
||||
} else {
|
||||
array[mid]
|
||||
}
|
||||
}
|
|
@ -6,11 +6,9 @@ use std::{
|
|||
|
||||
use monero_consensus::{transactions::OutputOnChain, ConsensusError, HardFork};
|
||||
|
||||
//mod batch_verifier;
|
||||
mod batch_verifier;
|
||||
pub mod block;
|
||||
pub mod context;
|
||||
mod helper;
|
||||
pub mod randomx;
|
||||
#[cfg(feature = "binaries")]
|
||||
pub mod rpc;
|
||||
|
@ -115,7 +113,7 @@ pub struct ExtendedBlockHeader {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DatabaseRequest {
|
||||
BlockExtendedHeader(cuprate_common::BlockID),
|
||||
BlockExtendedHeader(u64),
|
||||
BlockHash(u64),
|
||||
|
||||
BlockExtendedHeaderInRange(std::ops::Range<u64>),
|
||||
|
|
|
@ -15,7 +15,9 @@ use futures::{
|
|||
use tokio::sync::RwLock;
|
||||
use tower::{balance::p2c::Balance, ServiceExt};
|
||||
|
||||
use crate::{helper::rayon_spawn_async, DatabaseRequest, DatabaseResponse};
|
||||
use cuprate_helper::asynch::rayon_spawn_async;
|
||||
|
||||
use crate::{DatabaseRequest, DatabaseResponse};
|
||||
|
||||
pub mod cache;
|
||||
mod connection;
|
||||
|
|
|
@ -27,13 +27,10 @@ use tokio::{
|
|||
use tower::Service;
|
||||
use tracing::{instrument, Instrument};
|
||||
|
||||
use cuprate_common::{tower_utils::InfallibleOneshotReceiver, BlockID};
|
||||
use cuprate_helper::asynch::{rayon_spawn_async, InfallibleOneshotReceiver};
|
||||
|
||||
use super::ScanningCache;
|
||||
use crate::{
|
||||
helper::rayon_spawn_async, DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork,
|
||||
OutputOnChain,
|
||||
};
|
||||
use crate::{DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork, OutputOnChain};
|
||||
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(300);
|
||||
const OUTPUTS_TIMEOUT: Duration = Duration::from_secs(50);
|
||||
|
||||
|
@ -98,36 +95,24 @@ impl RpcConnection {
|
|||
|
||||
async fn get_extended_block_header(
|
||||
&self,
|
||||
id: BlockID,
|
||||
height: u64,
|
||||
) -> Result<ExtendedBlockHeader, tower::BoxError> {
|
||||
tracing::info!("Retrieving block info with id: {}", id);
|
||||
tracing::info!("Retrieving block info with height: {}", height);
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Response {
|
||||
block_header: BlockInfo,
|
||||
}
|
||||
|
||||
let info = match id {
|
||||
BlockID::Height(height) => {
|
||||
let res = self
|
||||
.con
|
||||
.json_rpc_call::<Response>(
|
||||
"get_block_header_by_height",
|
||||
Some(json!({"height": height})),
|
||||
)
|
||||
.await?;
|
||||
res.block_header
|
||||
}
|
||||
BlockID::Hash(hash) => {
|
||||
let res = self
|
||||
.con
|
||||
.json_rpc_call::<Response>(
|
||||
"get_block_header_by_hash",
|
||||
Some(json!({"hash": hash})),
|
||||
)
|
||||
.await?;
|
||||
res.block_header
|
||||
}
|
||||
let info = {
|
||||
let res = self
|
||||
.con
|
||||
.json_rpc_call::<Response>(
|
||||
"get_block_header_by_height",
|
||||
Some(json!({"height": height})),
|
||||
)
|
||||
.await?;
|
||||
res.block_header
|
||||
};
|
||||
|
||||
Ok(ExtendedBlockHeader {
|
||||
|
|
|
@ -2,11 +2,14 @@ use proptest::strategy::ValueTree;
|
|||
use proptest::{strategy::Strategy, test_runner::TestRunner};
|
||||
use tower::ServiceExt;
|
||||
|
||||
use crate::context::{
|
||||
initialize_blockchain_context, BlockChainContextRequest, BlockChainContextResponse,
|
||||
ContextConfig, UpdateBlockchainCacheData,
|
||||
use crate::{
|
||||
context::{
|
||||
initialize_blockchain_context, BlockChainContextRequest, BlockChainContextResponse,
|
||||
ContextConfig, UpdateBlockchainCacheData,
|
||||
},
|
||||
tests::mock_db::*,
|
||||
HardFork,
|
||||
};
|
||||
use crate::{tests::mock_db::*, HardFork};
|
||||
|
||||
pub(crate) mod data;
|
||||
mod difficulty;
|
||||
|
|
|
@ -2,7 +2,9 @@ use std::collections::VecDeque;
|
|||
|
||||
use proptest::{arbitrary::any, prop_assert_eq, prop_compose, proptest};
|
||||
|
||||
use crate::{context::difficulty::*, helper::median, tests::mock_db::*, HardFork};
|
||||
use cuprate_helper::num::median;
|
||||
|
||||
use crate::{context::difficulty::*, tests::mock_db::*, HardFork};
|
||||
|
||||
const TEST_WINDOW: usize = 72;
|
||||
const TEST_CUT: usize = 6;
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::{
|
|||
BlockWeightsCacheConfig,
|
||||
},
|
||||
tests::{context::data::BW_2850000_3050000, mock_db::*},
|
||||
HardFork,
|
||||
};
|
||||
use monero_consensus::HardFork;
|
||||
|
||||
pub const TEST_WEIGHT_CONFIG: BlockWeightsCacheConfig = BlockWeightsCacheConfig::new(100, 5000);
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ use proptest::{
|
|||
use proptest_derive::Arbitrary;
|
||||
use tower::{BoxError, Service};
|
||||
|
||||
use cuprate_common::BlockID;
|
||||
|
||||
use crate::{DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork};
|
||||
|
||||
prop_compose! {
|
||||
|
@ -140,7 +138,7 @@ impl Service<DatabaseRequest> for DummyDatabase {
|
|||
|
||||
async move {
|
||||
Ok(match req {
|
||||
DatabaseRequest::BlockExtendedHeader(BlockID::Height(id)) => {
|
||||
DatabaseRequest::BlockExtendedHeader(id) => {
|
||||
let mut id = usize::try_from(id).unwrap();
|
||||
if let Some(dummy_height) = dummy_height {
|
||||
let block_len = blocks.read().unwrap().len();
|
||||
|
|
|
@ -14,6 +14,7 @@ use rayon::prelude::*;
|
|||
use tower::{Service, ServiceExt};
|
||||
use tracing::instrument;
|
||||
|
||||
use cuprate_helper::asynch::rayon_spawn_async;
|
||||
use monero_consensus::{
|
||||
transactions::{
|
||||
check_transaction_contextual, check_transaction_semantic, RingCTError, TransactionError,
|
||||
|
@ -23,8 +24,8 @@ use monero_consensus::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
batch_verifier::MultiThreadedBatchVerifier, context::ReOrgToken, helper::rayon_spawn_async,
|
||||
Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError,
|
||||
batch_verifier::MultiThreadedBatchVerifier, context::ReOrgToken, Database, DatabaseRequest,
|
||||
DatabaseResponse, ExtendedConsensusError,
|
||||
};
|
||||
|
||||
mod contextual_data;
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
[package]
|
||||
name = "cuprate"
|
||||
authors = []
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = "4"
|
||||
serde = { version = "1", features = ["serde_derive"] }
|
||||
thiserror = "1"
|
||||
|
||||
[dependencies.abscissa_core]
|
||||
version = "0.7.0"
|
||||
# optional: use `gimli` to capture backtraces
|
||||
# see https://github.com/rust-lang/backtrace-rs/issues/189
|
||||
# features = ["gimli-backtrace"]
|
||||
|
||||
[dev-dependencies]
|
||||
abscissa_core = { version = "0.7.0", features = ["testing"] }
|
||||
once_cell = "1.2"
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
This application is authored using [Abscissa], a Rust application framework.
|
||||
|
||||
For more information, see:
|
||||
|
||||
[Documentation]
|
||||
|
||||
[Abscissa]: https://github.com/iqlusioninc/abscissa
|
||||
[Documentation]: https://docs.rs/abscissa_core/
|
|
@ -1,88 +0,0 @@
|
|||
//! Cuprate Abscissa Application
|
||||
|
||||
use crate::{commands::EntryPoint, config::CuprateConfig};
|
||||
use abscissa_core::{
|
||||
application::{self, AppCell},
|
||||
config::{self, CfgCell},
|
||||
trace, Application, FrameworkError, StandardPaths,
|
||||
};
|
||||
|
||||
/// Application state
|
||||
pub static APP: AppCell<CuprateApp> = AppCell::new();
|
||||
|
||||
/// Cuprate Application
|
||||
#[derive(Debug)]
|
||||
pub struct CuprateApp {
|
||||
/// Application configuration.
|
||||
config: CfgCell<CuprateConfig>,
|
||||
|
||||
/// Application state.
|
||||
state: application::State<Self>,
|
||||
}
|
||||
|
||||
/// Initialize a new application instance.
|
||||
///
|
||||
/// By default no configuration is loaded, and the framework state is
|
||||
/// initialized to a default, empty state (no components, threads, etc).
|
||||
impl Default for CuprateApp {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
config: CfgCell::default(),
|
||||
state: application::State::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Application for CuprateApp {
|
||||
/// Entrypoint command for this application.
|
||||
type Cmd = EntryPoint;
|
||||
|
||||
/// Application configuration.
|
||||
type Cfg = CuprateConfig;
|
||||
|
||||
/// Paths to resources within the application.
|
||||
type Paths = StandardPaths;
|
||||
|
||||
/// Accessor for application configuration.
|
||||
fn config(&self) -> config::Reader<CuprateConfig> {
|
||||
self.config.read()
|
||||
}
|
||||
|
||||
/// Borrow the application state immutably.
|
||||
fn state(&self) -> &application::State<Self> {
|
||||
&self.state
|
||||
}
|
||||
|
||||
/// Register all components used by this application.
|
||||
///
|
||||
/// If you would like to add additional components to your application
|
||||
/// beyond the default ones provided by the framework, this is the place
|
||||
/// to do so.
|
||||
fn register_components(&mut self, command: &Self::Cmd) -> Result<(), FrameworkError> {
|
||||
let framework_components = self.framework_components(command)?;
|
||||
let mut app_components = self.state.components_mut();
|
||||
app_components.register(framework_components)
|
||||
}
|
||||
|
||||
/// Post-configuration lifecycle callback.
|
||||
///
|
||||
/// Called regardless of whether config is loaded to indicate this is the
|
||||
/// time in app lifecycle when configuration would be loaded if
|
||||
/// possible.
|
||||
fn after_config(&mut self, config: Self::Cfg) -> Result<(), FrameworkError> {
|
||||
// Configure components
|
||||
let mut components = self.state.components_mut();
|
||||
components.after_config(&config)?;
|
||||
self.config.set_once(config);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get tracing configuration from command-line options
|
||||
fn tracing_config(&self, command: &EntryPoint) -> trace::Config {
|
||||
if command.verbose {
|
||||
trace::Config::verbose()
|
||||
} else {
|
||||
trace::Config::default()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
//! Main entry point for Cuprate
|
||||
|
||||
#![deny(warnings, missing_docs, trivial_casts, unused_qualifications)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use cuprate::application::APP;
|
||||
|
||||
/// Boot Cuprate
|
||||
fn main() {
|
||||
abscissa_core::boot(&APP);
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
//! Cuprate Subcommands
|
||||
//!
|
||||
//! This is where you specify the subcommands of your application.
|
||||
//!
|
||||
//! The default application comes with two subcommands:
|
||||
//!
|
||||
//! - `start`: launches the application
|
||||
//! - `--version`: print application version
|
||||
//!
|
||||
//! See the `impl Configurable` below for how to specify the path to the
|
||||
//! application's configuration file.
|
||||
|
||||
mod start;
|
||||
|
||||
use self::start::StartCmd;
|
||||
use crate::config::CuprateConfig;
|
||||
use abscissa_core::{config::Override, Command, Configurable, FrameworkError, Runnable};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Cuprate Configuration Filename
|
||||
pub const CONFIG_FILE: &str = "cuprate.toml";
|
||||
|
||||
/// Cuprate Subcommands
|
||||
/// Subcommands need to be listed in an enum.
|
||||
#[derive(clap::Parser, Command, Debug, Runnable)]
|
||||
pub enum CuprateCmd {
|
||||
/// The `start` subcommand
|
||||
Start(StartCmd),
|
||||
}
|
||||
|
||||
/// Entry point for the application. It needs to be a struct to allow using subcommands!
|
||||
#[derive(clap::Parser, Command, Debug)]
|
||||
#[command(author, about, version)]
|
||||
pub struct EntryPoint {
|
||||
#[command(subcommand)]
|
||||
cmd: CuprateCmd,
|
||||
|
||||
/// Enable verbose logging
|
||||
#[arg(short, long)]
|
||||
pub verbose: bool,
|
||||
|
||||
/// Use the specified config file
|
||||
#[arg(short, long)]
|
||||
pub config: Option<String>,
|
||||
}
|
||||
|
||||
impl Runnable for EntryPoint {
|
||||
fn run(&self) {
|
||||
self.cmd.run()
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait allows you to define how application configuration is loaded.
|
||||
impl Configurable<CuprateConfig> for EntryPoint {
|
||||
/// Location of the configuration file
|
||||
fn config_path(&self) -> Option<PathBuf> {
|
||||
// Check if the config file exists, and if it does not, ignore it.
|
||||
// If you'd like for a missing configuration file to be a hard error
|
||||
// instead, always return `Some(CONFIG_FILE)` here.
|
||||
let filename = self
|
||||
.config
|
||||
.as_ref()
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| CONFIG_FILE.into());
|
||||
|
||||
if filename.exists() {
|
||||
Some(filename)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply changes to the config after it's been loaded, e.g. overriding
|
||||
/// values in a config file using command-line options.
|
||||
///
|
||||
/// This can be safely deleted if you don't want to override config
|
||||
/// settings from command-line options.
|
||||
fn process_config(&self, config: CuprateConfig) -> Result<CuprateConfig, FrameworkError> {
|
||||
match &self.cmd {
|
||||
CuprateCmd::Start(cmd) => cmd.override_config(config),
|
||||
//
|
||||
// If you don't need special overrides for some
|
||||
// subcommands, you can just use a catch all
|
||||
// _ => Ok(config),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
//! `start` subcommand - example of how to write a subcommand
|
||||
|
||||
/// App-local prelude includes `app_reader()`/`app_writer()`/`app_config()`
|
||||
/// accessors along with logging macros. Customize as you see fit.
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::config::CuprateConfig;
|
||||
use abscissa_core::{config, Command, FrameworkError, Runnable};
|
||||
|
||||
/// `start` subcommand
|
||||
///
|
||||
/// The `Parser` proc macro generates an option parser based on the struct
|
||||
/// definition, and is defined in the `clap` crate. See their documentation
|
||||
/// for a more comprehensive example:
|
||||
///
|
||||
/// <https://docs.rs/clap/>
|
||||
#[derive(clap::Parser, Command, Debug)]
|
||||
pub struct StartCmd {
|
||||
/// To whom are we saying hello?
|
||||
recipient: Vec<String>,
|
||||
}
|
||||
|
||||
impl Runnable for StartCmd {
|
||||
/// Start the application.
|
||||
fn run(&self) {
|
||||
let config = APP.config();
|
||||
println!("Hello, {}!", &config.hello.recipient);
|
||||
}
|
||||
}
|
||||
|
||||
impl config::Override<CuprateConfig> for StartCmd {
|
||||
// Process the given command line options, overriding settings from
|
||||
// a configuration file using explicit flags taken from command-line
|
||||
// arguments.
|
||||
fn override_config(&self, mut config: CuprateConfig) -> Result<CuprateConfig, FrameworkError> {
|
||||
if !self.recipient.is_empty() {
|
||||
config.hello.recipient = self.recipient.join(" ");
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
//! Cuprate Config
|
||||
//!
|
||||
//! See instructions in `commands.rs` to specify the path to your
|
||||
//! application's configuration file and/or command-line options
|
||||
//! for specifying it.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Cuprate Configuration
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CuprateConfig {
|
||||
/// An example configuration section
|
||||
pub hello: ExampleSection,
|
||||
}
|
||||
|
||||
/// Default configuration settings.
|
||||
///
|
||||
/// Note: if your needs are as simple as below, you can
|
||||
/// use `#[derive(Default)]` on CuprateConfig instead.
|
||||
impl Default for CuprateConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
hello: ExampleSection::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Example configuration section.
|
||||
///
|
||||
/// Delete this and replace it with your actual configuration structs.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ExampleSection {
|
||||
/// Example configuration value
|
||||
pub recipient: String,
|
||||
}
|
||||
|
||||
impl Default for ExampleSection {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
recipient: "world".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
//! Error types
|
||||
|
||||
use abscissa_core::error::{BoxError, Context};
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
io,
|
||||
ops::Deref,
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Kinds of errors
|
||||
#[derive(Copy, Clone, Debug, Eq, Error, PartialEq)]
|
||||
pub enum ErrorKind {
|
||||
/// Error in configuration file
|
||||
#[error("config error")]
|
||||
Config,
|
||||
|
||||
/// Input/output error
|
||||
#[error("I/O error")]
|
||||
Io,
|
||||
}
|
||||
|
||||
impl ErrorKind {
|
||||
/// Create an error context from this error
|
||||
pub fn context(self, source: impl Into<BoxError>) -> Context<ErrorKind> {
|
||||
Context::new(self, Some(source.into()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Error type
|
||||
#[derive(Debug)]
|
||||
pub struct Error(Box<Context<ErrorKind>>);
|
||||
|
||||
impl Deref for Error {
|
||||
type Target = Context<ErrorKind>;
|
||||
|
||||
fn deref(&self) -> &Context<ErrorKind> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
self.0.source()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorKind> for Error {
|
||||
fn from(kind: ErrorKind) -> Self {
|
||||
Context::new(kind, None).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Context<ErrorKind>> for Error {
|
||||
fn from(context: Context<ErrorKind>) -> Self {
|
||||
Error(Box::new(context))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
ErrorKind::Io.context(err).into()
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
//! Cuprate
|
||||
//!
|
||||
//! Application based on the [Abscissa] framework.
|
||||
//!
|
||||
//! [Abscissa]: https://github.com/iqlusioninc/abscissa
|
||||
|
||||
// Tip: Deny warnings with `RUSTFLAGS="-D warnings"` environment variable in CI
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![warn(
|
||||
missing_docs,
|
||||
rust_2018_idioms,
|
||||
trivial_casts,
|
||||
unused_lifetimes,
|
||||
unused_qualifications
|
||||
)]
|
||||
|
||||
pub mod application;
|
||||
pub mod commands;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod prelude;
|
|
@ -1,9 +0,0 @@
|
|||
//! Application-local prelude: conveniently import types/functions/macros
|
||||
//! which are generally useful and should be available in every module with
|
||||
//! `use crate::prelude::*;
|
||||
|
||||
/// Abscissa core prelude
|
||||
pub use abscissa_core::prelude::*;
|
||||
|
||||
/// Application state
|
||||
pub use crate::application::APP;
|
|
@ -1,91 +0,0 @@
|
|||
//! Acceptance test: runs the application as a subprocess and asserts its
|
||||
//! output for given argument combinations matches what is expected.
|
||||
//!
|
||||
//! Modify and/or delete these as you see fit to test the specific needs of
|
||||
//! your application.
|
||||
//!
|
||||
//! For more information, see:
|
||||
//! <https://docs.rs/abscissa_core/latest/abscissa_core/testing/index.html>
|
||||
|
||||
// Tip: Deny warnings with `RUSTFLAGS="-D warnings"` environment variable in CI
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![warn(
|
||||
missing_docs,
|
||||
rust_2018_idioms,
|
||||
trivial_casts,
|
||||
unused_lifetimes,
|
||||
unused_qualifications
|
||||
)]
|
||||
|
||||
use abscissa_core::testing::prelude::*;
|
||||
use cuprate::config::CuprateConfig;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
/// Executes your application binary via `cargo run`.
|
||||
///
|
||||
/// Storing this value as a [`Lazy`] static ensures that all instances of
|
||||
/// the runner acquire a mutex when executing commands and inspecting
|
||||
/// exit statuses, serializing what would otherwise be multithreaded
|
||||
/// invocations as `cargo test` executes tests in parallel by default.
|
||||
pub static RUNNER: Lazy<CmdRunner> = Lazy::new(|| CmdRunner::default());
|
||||
|
||||
/// Use `CuprateConfig::default()` value if no config or args
|
||||
#[test]
|
||||
fn start_no_args() {
|
||||
let mut runner = RUNNER.clone();
|
||||
let mut cmd = runner.arg("start").capture_stdout().run();
|
||||
cmd.stdout().expect_line("Hello, world!");
|
||||
cmd.wait().unwrap().expect_success();
|
||||
}
|
||||
|
||||
/// Use command-line argument value
|
||||
#[test]
|
||||
fn start_with_args() {
|
||||
let mut runner = RUNNER.clone();
|
||||
let mut cmd = runner
|
||||
.args(&["start", "acceptance", "test"])
|
||||
.capture_stdout()
|
||||
.run();
|
||||
|
||||
cmd.stdout().expect_line("Hello, acceptance test!");
|
||||
cmd.wait().unwrap().expect_success();
|
||||
}
|
||||
|
||||
/// Use configured value
|
||||
#[test]
|
||||
fn start_with_config_no_args() {
|
||||
let mut config = CuprateConfig::default();
|
||||
config.hello.recipient = "configured recipient".to_owned();
|
||||
let expected_line = format!("Hello, {}!", &config.hello.recipient);
|
||||
|
||||
let mut runner = RUNNER.clone();
|
||||
let mut cmd = runner.config(&config).arg("start").capture_stdout().run();
|
||||
cmd.stdout().expect_line(&expected_line);
|
||||
cmd.wait().unwrap().expect_success();
|
||||
}
|
||||
|
||||
/// Override configured value with command-line argument
|
||||
#[test]
|
||||
fn start_with_config_and_args() {
|
||||
let mut config = CuprateConfig::default();
|
||||
config.hello.recipient = "configured recipient".to_owned();
|
||||
|
||||
let mut runner = RUNNER.clone();
|
||||
let mut cmd = runner
|
||||
.config(&config)
|
||||
.args(&["start", "acceptance", "test"])
|
||||
.capture_stdout()
|
||||
.run();
|
||||
|
||||
cmd.stdout().expect_line("Hello, acceptance test!");
|
||||
cmd.wait().unwrap().expect_success();
|
||||
}
|
||||
|
||||
/// Example of a test which matches a regular expression
|
||||
#[test]
|
||||
fn version_no_args() {
|
||||
let mut runner = RUNNER.clone();
|
||||
let mut cmd = runner.arg("--version").capture_stdout().run();
|
||||
cmd.stdout().expect_regex(r"\A\w+ [\d\.\-]+\z");
|
||||
}
|
|
@ -1,7 +1,12 @@
|
|||
[package]
|
||||
name = "helper"
|
||||
name = "cuprate-helper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Helper functions used around Cuprate."
|
||||
license = "MIT"
|
||||
authors = ["hinto-janai <hinto.janai@protonmail.com>", "Boog900"]
|
||||
repository = "https://github.com/Cuprate/cuprate/tree/main/consensus"
|
||||
|
||||
|
||||
[features]
|
||||
# All features on by default.
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
pub mod asynch; // async collides
|
||||
#[cfg(feature = "atomic")]
|
||||
pub mod atomic;
|
||||
pub mod network;
|
||||
#[cfg(feature = "num")]
|
||||
pub mod num;
|
||||
#[cfg(feature = "thread")]
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
//! This module contains an enum representing every Monero network: mainnet, testnet, stagenet and functionality
|
||||
//! related to that.
|
||||
//!
|
||||
//! This feels out of place for the helper crate but this is needed through out Cuprate and felt too small to split
|
||||
//! into it's own crate.
|
||||
//!
|
||||
//! `#[no_std]` compatible.
|
||||
|
||||
const MAINNET_NETWORK_ID: [u8; 16] = [
|
||||
0x12, 0x30, 0xF1, 0x71, 0x61, 0x04, 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10,
|
||||
];
|
||||
|
@ -8,15 +16,20 @@ const STAGENET_NETWORK_ID: [u8; 16] = [
|
|||
0x12, 0x30, 0xF1, 0x71, 0x61, 0x04, 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x12,
|
||||
];
|
||||
|
||||
/// An enum representing every Monero network.
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub enum Network {
|
||||
/// Mainnet
|
||||
#[default]
|
||||
Mainnet,
|
||||
/// Testnet
|
||||
Testnet,
|
||||
/// Stagenet
|
||||
Stagenet,
|
||||
}
|
||||
|
||||
impl Network {
|
||||
/// Returns the network ID for the current network.
|
||||
pub fn network_id(&self) -> [u8; 16] {
|
||||
match self {
|
||||
Network::Mainnet => MAINNET_NETWORK_ID,
|
|
@ -52,7 +52,7 @@ impl_float!(f32, f64);
|
|||
/// Returns the average of two numbers; works with at least all integral and floating point types
|
||||
///
|
||||
/// ```rust
|
||||
/// # use helper::num::*;
|
||||
/// # use cuprate_helper::num::*;
|
||||
/// assert_eq!(get_mid(0, 10), 5);
|
||||
/// assert_eq!(get_mid(0.0, 10.0), 5.0);
|
||||
/// assert_eq!(get_mid(-10.0, 10.0), 0.0);
|
||||
|
@ -76,7 +76,7 @@ where
|
|||
/// Gets the median from a sorted slice.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use helper::num::*;
|
||||
/// # use cuprate_helper::num::*;
|
||||
/// let mut vec = vec![10, 5, 1, 4, 2, 8, 9, 7, 3, 6];
|
||||
/// vec.sort();
|
||||
///
|
||||
|
@ -109,7 +109,7 @@ where
|
|||
/// Compare 2 non-`NaN` floats.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use helper::num::*;
|
||||
/// # use cuprate_helper::num::*;
|
||||
/// # use core::cmp::Ordering;
|
||||
/// assert_eq!(cmp_float(0.0, 1.0), Ordering::Less);
|
||||
/// assert_eq!(cmp_float(1.0, 1.0), Ordering::Equal);
|
||||
|
@ -128,7 +128,7 @@ where
|
|||
/// This function panics if either floats are NaNs.
|
||||
///
|
||||
/// ```rust,should_panic
|
||||
/// # use helper::num::*;
|
||||
/// # use cuprate_helper::num::*;
|
||||
/// cmp_float(0.0, f32::NAN);
|
||||
/// ```
|
||||
pub fn cmp_float<F: Float>(a: F, b: F) -> Ordering {
|
||||
|
@ -144,7 +144,7 @@ pub fn cmp_float<F: Float>(a: F, b: F) -> Ordering {
|
|||
/// Compare 2 floats, `NaN`'s will always return [`Ordering::Equal`].
|
||||
///
|
||||
/// ```rust
|
||||
/// # use helper::num::*;
|
||||
/// # use cuprate_helper::num::*;
|
||||
/// # use core::cmp::Ordering;
|
||||
/// assert_eq!(cmp_float_nan(0.0, 1.0), Ordering::Less);
|
||||
/// assert_eq!(cmp_float_nan(1.0, 1.0), Ordering::Equal);
|
||||
|
|
|
@ -9,11 +9,11 @@ repository = "https://github.com/SyntheticBird45/cuprate/tree/main/net/monero-wi
|
|||
|
||||
[dependencies]
|
||||
levin-cuprate = {path="../levin"}
|
||||
monero-epee-bin-serde = {git = "https://github.com/monero-rs/monero-epee-bin-serde.git", rev="aafe4ba"}
|
||||
serde = {version = "1", features = ["derive"]}
|
||||
serde_bytes = "0.11"
|
||||
thiserror = "1"
|
||||
monero-epee-bin-serde = { workspace = true, features = ["container_as_blob"] }
|
||||
serde = { workspace = true, features = ["derive", "std"]}
|
||||
serde_bytes = { workspace = true, features = ["std"]}
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4.3"
|
||||
hex = { workspace = true, features = ["std"]}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ authors = ["Boog900"]
|
|||
|
||||
|
||||
[dependencies]
|
||||
cuprate-common = {path = "../../common"}
|
||||
monero-wire = {path= "../../net/monero-wire"}
|
||||
monero-p2p = {path = "../monero-p2p" }
|
||||
monero-pruning = { path = "../../pruning" }
|
||||
monero-wire = { path= "../../net/monero-wire" }
|
||||
monero-p2p = { path = "../monero-p2p" }
|
||||
|
||||
tower = { workspace = true, features = ["util", "buffer"] }
|
||||
tokio = { workspace = true, features = ["time", "fs", "rt"]}
|
||||
|
|
|
@ -19,13 +19,13 @@ use tokio::{
|
|||
};
|
||||
use tower::Service;
|
||||
|
||||
use cuprate_common::PruningSeed;
|
||||
use monero_p2p::{
|
||||
client::InternalPeerID,
|
||||
handles::ConnectionHandle,
|
||||
services::{AddressBookRequest, AddressBookResponse, ZoneSpecificPeerListEntryBase},
|
||||
NetZoneAddress, NetworkZone,
|
||||
};
|
||||
use monero_pruning::PruningSeed;
|
||||
|
||||
use crate::{peer_list::PeerList, store::save_peers_to_disk, AddressBookError, Config};
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ use futures::StreamExt;
|
|||
use tokio::sync::Semaphore;
|
||||
use tokio::time::interval;
|
||||
|
||||
use cuprate_common::PruningSeed;
|
||||
use monero_p2p::handles::HandleBuilder;
|
||||
use monero_pruning::PruningSeed;
|
||||
|
||||
use super::{AddressBook, ConnectionPeerEntry, InternalPeerID};
|
||||
use crate::{peer_list::tests::make_fake_peer_list, AddressBookError, Config};
|
||||
|
|
|
@ -2,8 +2,8 @@ use std::collections::{BTreeMap, HashMap, HashSet};
|
|||
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
|
||||
use cuprate_common::{PruningSeed, CRYPTONOTE_MAX_BLOCK_NUMBER};
|
||||
use monero_p2p::{services::ZoneSpecificPeerListEntryBase, NetZoneAddress, NetworkZone};
|
||||
use monero_pruning::{PruningSeed, CRYPTONOTE_MAX_BLOCK_NUMBER};
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests;
|
||||
|
|
|
@ -2,8 +2,8 @@ use std::collections::HashSet;
|
|||
|
||||
use rand::Rng;
|
||||
|
||||
use cuprate_common::PruningSeed;
|
||||
use monero_p2p::services::ZoneSpecificPeerListEntryBase;
|
||||
use monero_pruning::PruningSeed;
|
||||
|
||||
use cuprate_test_utils::test_netzone::{TestNetZone, TestNetZoneAddr};
|
||||
use monero_p2p::NetZoneAddress;
|
||||
|
|
|
@ -7,11 +7,12 @@ authors = ["Boog900"]
|
|||
|
||||
[features]
|
||||
default = ["borsh"]
|
||||
borsh = ["dep:borsh"]
|
||||
borsh = ["dep:borsh", "monero-pruning/borsh"]
|
||||
|
||||
[dependencies]
|
||||
monero-wire = {path= "../../net/monero-wire"}
|
||||
cuprate-common = {path = "../../common", features = ["borsh"]}
|
||||
cuprate-helper = { path = "../../helper" }
|
||||
monero-wire = { path = "../../net/monero-wire" }
|
||||
monero-pruning = { path = "../../pruning" }
|
||||
|
||||
tokio = { workspace = true, features = ["net", "sync", "macros"]}
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
|
|
|
@ -9,7 +9,7 @@ use tokio::{sync::mpsc, task::JoinHandle};
|
|||
use tokio_util::sync::PollSender;
|
||||
use tower::Service;
|
||||
|
||||
use cuprate_common::tower_utils::InfallibleOneshotReceiver;
|
||||
use cuprate_helper::asynch::InfallibleOneshotReceiver;
|
||||
|
||||
use crate::{
|
||||
handles::ConnectionHandle, NetworkZone, PeerError, PeerRequest, PeerResponse, SharedError,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use cuprate_common::{PruningError, PruningSeed};
|
||||
use monero_pruning::{PruningError, PruningSeed};
|
||||
use monero_wire::{NetZone, NetworkAddress, PeerListEntryBase};
|
||||
|
||||
use crate::{
|
||||
|
|
|
@ -5,7 +5,7 @@ use futures::{channel::mpsc, StreamExt};
|
|||
use tokio::sync::{broadcast, Semaphore};
|
||||
use tower::{Service, ServiceExt};
|
||||
|
||||
use cuprate_common::Network;
|
||||
use cuprate_helper::network::Network;
|
||||
use monero_wire::{common::PeerSupportFlags, BasicNodeData};
|
||||
|
||||
use monero_p2p::{
|
||||
|
|
13
pruning/Cargo.toml
Normal file
13
pruning/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "monero-pruning"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
borsh = ["dep:borsh"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = { workspace = true }
|
||||
|
||||
borsh = { workspace = true, features = ["derive", "std"], optional = true }
|
|
@ -1,6 +1,6 @@
|
|||
//! # Pruning Mechanism for Monero
|
||||
//!
|
||||
//! This module provides an implementation of the pruning mechanism used in Monero.
|
||||
//! This crate provides an implementation of the pruning mechanism used in Monero.
|
||||
//! The main data structure, `PruningSeed`, encapsulates the logic for creating and manipulating pruning seeds,
|
||||
//! which determine the set of blocks to be pruned from the blockchain.
|
||||
//!
|
||||
|
@ -8,9 +8,9 @@
|
|||
//! split into 8 parts):
|
||||
//!
|
||||
//! ```rust
|
||||
//! use cuprate_common::pruning::PruningSeed;
|
||||
//! use monero_pruning::PruningSeed;
|
||||
//!
|
||||
//! let seed: u32 = 386; // the seed you wan't to check is valid
|
||||
//! let seed: u32 = 386; // the seed you want to check is valid
|
||||
//! match PruningSeed::try_from(seed) {
|
||||
//! Ok(seed) => seed, // seed is valid
|
||||
//! Err(e) => panic!("seed is invalid")
|
||||
|
@ -22,10 +22,11 @@ use std::cmp::Ordering;
|
|||
|
||||
use thiserror::Error;
|
||||
|
||||
use super::{
|
||||
CRYPTONOTE_MAX_BLOCK_NUMBER, CRYPTONOTE_PRUNING_LOG_STRIPES, CRYPTONOTE_PRUNING_STRIPE_SIZE,
|
||||
CRYPTONOTE_PRUNING_TIP_BLOCKS,
|
||||
};
|
||||
pub const CRYPTONOTE_MAX_BLOCK_NUMBER: u64 = 500000000;
|
||||
|
||||
pub const CRYPTONOTE_PRUNING_LOG_STRIPES: u32 = 3;
|
||||
pub const CRYPTONOTE_PRUNING_STRIPE_SIZE: u64 = 4096;
|
||||
pub const CRYPTONOTE_PRUNING_TIP_BLOCKS: u64 = 5500;
|
||||
|
||||
const PRUNING_SEED_LOG_STRIPES_SHIFT: u32 = 7;
|
||||
const PRUNING_SEED_STRIPE_SHIFT: u32 = 0;
|
||||
|
@ -185,7 +186,7 @@ impl PruningSeed {
|
|||
1
|
||||
};
|
||||
|
||||
// amt_of_cycles * blocks in a cycle + how many blocks through a cycles until the seed starts storing blocks
|
||||
// amt_of_cycles * blocks in a cycle + how many blocks through a cycles until the seed starts storing blocks
|
||||
let calculated_height = cycles_start
|
||||
* (CRYPTONOTE_PRUNING_STRIPE_SIZE << seed_log_stripes)
|
||||
+ (seed_stripe as u64 - 1) * CRYPTONOTE_PRUNING_STRIPE_SIZE;
|
||||
|
@ -289,9 +290,7 @@ fn get_block_pruning_stripe(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::pruning::{get_block_pruning_stripe, PruningSeed};
|
||||
|
||||
use super::CRYPTONOTE_PRUNING_LOG_STRIPES;
|
||||
use super::*;
|
||||
|
||||
fn make_all_pruning_seeds() -> Vec<PruningSeed> {
|
||||
let possible_stripes = 1..(1 << CRYPTONOTE_PRUNING_LOG_STRIPES);
|
Loading…
Reference in a new issue