mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-22 19:49:28 +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",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cuprate-common"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"borsh",
|
|
||||||
"chrono",
|
|
||||||
"futures",
|
|
||||||
"hex",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cuprate-consensus"
|
name = "cuprate-consensus"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh",
|
"borsh",
|
||||||
"clap",
|
"clap",
|
||||||
"cuprate-common",
|
"cuprate-helper",
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"dalek-ff-group",
|
"dalek-ff-group",
|
||||||
"dirs",
|
"dirs",
|
||||||
"futures",
|
"futures",
|
||||||
"hex",
|
"hex",
|
||||||
"monero-consensus",
|
"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-serai",
|
||||||
"monero-wire",
|
"monero-wire",
|
||||||
"multiexp",
|
"multiexp",
|
||||||
|
@ -472,6 +461,18 @@ dependencies = [
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuprate-helper"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"futures",
|
||||||
|
"libc",
|
||||||
|
"rayon",
|
||||||
|
"tokio",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cuprate-test-utils"
|
name = "cuprate-test-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -816,18 +817,6 @@ version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "helper"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"futures",
|
|
||||||
"libc",
|
|
||||||
"rayon",
|
|
||||||
"tokio",
|
|
||||||
"windows",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
@ -1098,10 +1087,10 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"borsh",
|
"borsh",
|
||||||
"cuprate-common",
|
|
||||||
"cuprate-test-utils",
|
"cuprate-test-utils",
|
||||||
"futures",
|
"futures",
|
||||||
"monero-p2p",
|
"monero-p2p",
|
||||||
|
"monero-pruning",
|
||||||
"monero-wire",
|
"monero-wire",
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"rand",
|
"rand",
|
||||||
|
@ -1117,7 +1106,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-bigint",
|
"crypto-bigint",
|
||||||
"cryptonight-cuprate",
|
"cryptonight-cuprate",
|
||||||
"cuprate-common",
|
"cuprate-helper",
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"dalek-ff-group",
|
"dalek-ff-group",
|
||||||
"hex",
|
"hex",
|
||||||
|
@ -1136,22 +1125,13 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "monero-epee-bin-serde"
|
name = "monero-epee-bin-serde"
|
||||||
version = "1.0.1"
|
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 = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_bytes",
|
"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]]
|
[[package]]
|
||||||
name = "monero-generators"
|
name = "monero-generators"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -1171,10 +1151,11 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"borsh",
|
"borsh",
|
||||||
"cuprate-common",
|
"cuprate-helper",
|
||||||
"cuprate-test-utils",
|
"cuprate-test-utils",
|
||||||
"futures",
|
"futures",
|
||||||
"hex",
|
"hex",
|
||||||
|
"monero-pruning",
|
||||||
"monero-wire",
|
"monero-wire",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -1185,6 +1166,14 @@ dependencies = [
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "monero-pruning"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"borsh",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "monero-serai"
|
name = "monero-serai"
|
||||||
version = "0.1.4-alpha"
|
version = "0.1.4-alpha"
|
||||||
|
@ -1225,7 +1214,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"levin-cuprate",
|
"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",
|
||||||
"serde_bytes",
|
"serde_bytes",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
|
@ -2,18 +2,16 @@
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"common",
|
|
||||||
"consensus",
|
"consensus",
|
||||||
"consensus/rules",
|
"consensus/rules",
|
||||||
"cryptonight",
|
"cryptonight",
|
||||||
# "cuprate",
|
|
||||||
# "database",
|
|
||||||
"helper",
|
"helper",
|
||||||
"net/levin",
|
"net/levin",
|
||||||
"net/monero-wire",
|
"net/monero-wire",
|
||||||
"p2p/monero-p2p",
|
"p2p/monero-p2p",
|
||||||
"p2p/address-book",
|
"p2p/address-book",
|
||||||
"test-utils"
|
"pruning",
|
||||||
|
"test-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
@ -47,7 +45,7 @@ dirs = { version = "5.0.1", default-features = false }
|
||||||
futures = { version = "0.3.29", default-features = false }
|
futures = { version = "0.3.29", default-features = false }
|
||||||
hex = { version = "0.4.3", default-features = false }
|
hex = { version = "0.4.3", default-features = false }
|
||||||
hex-literal = { version = "0.4", 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 }
|
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 }
|
multiexp = { git = "https://github.com/Cuprate/serai.git", rev = "a59966b", default-features = false }
|
||||||
pin-project = { version = "1.1.3", 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]
|
[dependencies]
|
||||||
cuprate-common = {path = "../common"}
|
cuprate-helper = { path = "../helper", default-features = false, features = ["std", "asynch", "num"] }
|
||||||
monero-consensus = {path = "./rules", features = ["rayon"]}
|
monero-consensus = {path = "./rules", features = ["rayon"]}
|
||||||
|
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
|
|
|
@ -9,8 +9,8 @@ proptest = ["dep:proptest", "dep:proptest-derive"]
|
||||||
rayon = ["dep:rayon"]
|
rayon = ["dep:rayon"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
cuprate-helper = { path = "../../helper", default-features = false, features = ["std"] }
|
||||||
cryptonight-cuprate = {path = "../../cryptonight"}
|
cryptonight-cuprate = {path = "../../cryptonight"}
|
||||||
cuprate-common = {path = "../../common"}
|
|
||||||
|
|
||||||
monero-serai = { workspace = true, features = ["std"] }
|
monero-serai = { workspace = true, features = ["std"] }
|
||||||
multiexp = { workspace = true, features = ["std", "batch"] }
|
multiexp = { workspace = true, features = ["std", "batch"] }
|
||||||
|
|
|
@ -6,7 +6,7 @@ use monero_serai::{
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
};
|
};
|
||||||
|
|
||||||
use cuprate_common::Network;
|
use cuprate_helper::network::Network;
|
||||||
|
|
||||||
const fn genesis_nonce(network: &Network) -> u32 {
|
const fn genesis_nonce(network: &Network) -> u32 {
|
||||||
match network {
|
match network {
|
||||||
|
@ -42,9 +42,7 @@ pub fn generate_genesis_block(network: &Network) -> Block {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use cuprate_common::Network;
|
use super::*;
|
||||||
|
|
||||||
use super::generate_genesis_block;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn generate_genesis_blocks() {
|
fn generate_genesis_blocks() {
|
||||||
|
|
|
@ -19,7 +19,7 @@ mod bin {
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
use tracing::level_filters::LevelFilter;
|
use tracing::level_filters::LevelFilter;
|
||||||
|
|
||||||
use cuprate_common::Network;
|
use cuprate_helper::network::Network;
|
||||||
|
|
||||||
use cuprate_consensus::{
|
use cuprate_consensus::{
|
||||||
block::PrePreparedBlockExPOW,
|
block::PrePreparedBlockExPOW,
|
||||||
|
|
|
@ -13,7 +13,7 @@ mod bin {
|
||||||
use monero_serai::transaction::Transaction;
|
use monero_serai::transaction::Transaction;
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
|
|
||||||
use cuprate_common::tower_utils::InfallibleOneshotReceiver;
|
use cuprate_helper::asynch::InfallibleOneshotReceiver;
|
||||||
|
|
||||||
use cuprate_consensus::{
|
use cuprate_consensus::{
|
||||||
context::{
|
context::{
|
||||||
|
|
|
@ -3,9 +3,9 @@ use std::{collections::VecDeque, ops::Range};
|
||||||
use tower::ServiceExt;
|
use tower::ServiceExt;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use crate::{
|
use cuprate_helper::num::median;
|
||||||
helper::median, Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork,
|
|
||||||
};
|
use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork};
|
||||||
|
|
||||||
/// The amount of blocks we account for to calculate difficulty
|
/// The amount of blocks we account for to calculate difficulty
|
||||||
const DIFFICULTY_WINDOW: usize = 720;
|
const DIFFICULTY_WINDOW: usize = 720;
|
||||||
|
|
|
@ -79,9 +79,7 @@ impl HardForkState {
|
||||||
let DatabaseResponse::BlockExtendedHeader(ext_header) = database
|
let DatabaseResponse::BlockExtendedHeader(ext_header) = database
|
||||||
.ready()
|
.ready()
|
||||||
.await?
|
.await?
|
||||||
.call(DatabaseRequest::BlockExtendedHeader(
|
.call(DatabaseRequest::BlockExtendedHeader(chain_height - 1))
|
||||||
(chain_height - 1).into(),
|
|
||||||
))
|
|
||||||
.await?
|
.await?
|
||||||
else {
|
else {
|
||||||
panic!("Database sent incorrect response!");
|
panic!("Database sent incorrect response!");
|
||||||
|
|
|
@ -16,12 +16,10 @@ use rayon::prelude::*;
|
||||||
use tower::ServiceExt;
|
use tower::ServiceExt;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use cuprate_helper::{asynch::rayon_spawn_async, num::median};
|
||||||
use monero_consensus::blocks::{penalty_free_zone, PENALTY_FREE_ZONE_5};
|
use monero_consensus::blocks::{penalty_free_zone, PENALTY_FREE_ZONE_5};
|
||||||
|
|
||||||
use crate::{
|
use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork};
|
||||||
helper::{median, rayon_spawn_async},
|
|
||||||
Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork,
|
|
||||||
};
|
|
||||||
|
|
||||||
const SHORT_TERM_WINDOW: u64 = 100;
|
const SHORT_TERM_WINDOW: u64 = 100;
|
||||||
const LONG_TERM_WINDOW: u64 = 100000;
|
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};
|
use monero_consensus::{transactions::OutputOnChain, ConsensusError, HardFork};
|
||||||
|
|
||||||
//mod batch_verifier;
|
|
||||||
mod batch_verifier;
|
mod batch_verifier;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
mod helper;
|
|
||||||
pub mod randomx;
|
pub mod randomx;
|
||||||
#[cfg(feature = "binaries")]
|
#[cfg(feature = "binaries")]
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
|
@ -115,7 +113,7 @@ pub struct ExtendedBlockHeader {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum DatabaseRequest {
|
pub enum DatabaseRequest {
|
||||||
BlockExtendedHeader(cuprate_common::BlockID),
|
BlockExtendedHeader(u64),
|
||||||
BlockHash(u64),
|
BlockHash(u64),
|
||||||
|
|
||||||
BlockExtendedHeaderInRange(std::ops::Range<u64>),
|
BlockExtendedHeaderInRange(std::ops::Range<u64>),
|
||||||
|
|
|
@ -15,7 +15,9 @@ use futures::{
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tower::{balance::p2c::Balance, ServiceExt};
|
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;
|
pub mod cache;
|
||||||
mod connection;
|
mod connection;
|
||||||
|
|
|
@ -27,13 +27,10 @@ use tokio::{
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
use tracing::{instrument, Instrument};
|
use tracing::{instrument, Instrument};
|
||||||
|
|
||||||
use cuprate_common::{tower_utils::InfallibleOneshotReceiver, BlockID};
|
use cuprate_helper::asynch::{rayon_spawn_async, InfallibleOneshotReceiver};
|
||||||
|
|
||||||
use super::ScanningCache;
|
use super::ScanningCache;
|
||||||
use crate::{
|
use crate::{DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork, OutputOnChain};
|
||||||
helper::rayon_spawn_async, DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork,
|
|
||||||
OutputOnChain,
|
|
||||||
};
|
|
||||||
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(300);
|
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(300);
|
||||||
const OUTPUTS_TIMEOUT: Duration = Duration::from_secs(50);
|
const OUTPUTS_TIMEOUT: Duration = Duration::from_secs(50);
|
||||||
|
|
||||||
|
@ -98,17 +95,16 @@ impl RpcConnection {
|
||||||
|
|
||||||
async fn get_extended_block_header(
|
async fn get_extended_block_header(
|
||||||
&self,
|
&self,
|
||||||
id: BlockID,
|
height: u64,
|
||||||
) -> Result<ExtendedBlockHeader, tower::BoxError> {
|
) -> Result<ExtendedBlockHeader, tower::BoxError> {
|
||||||
tracing::info!("Retrieving block info with id: {}", id);
|
tracing::info!("Retrieving block info with height: {}", height);
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct Response {
|
struct Response {
|
||||||
block_header: BlockInfo,
|
block_header: BlockInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
let info = match id {
|
let info = {
|
||||||
BlockID::Height(height) => {
|
|
||||||
let res = self
|
let res = self
|
||||||
.con
|
.con
|
||||||
.json_rpc_call::<Response>(
|
.json_rpc_call::<Response>(
|
||||||
|
@ -117,17 +113,6 @@ impl RpcConnection {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
res.block_header
|
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
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ExtendedBlockHeader {
|
Ok(ExtendedBlockHeader {
|
||||||
|
|
|
@ -2,11 +2,14 @@ use proptest::strategy::ValueTree;
|
||||||
use proptest::{strategy::Strategy, test_runner::TestRunner};
|
use proptest::{strategy::Strategy, test_runner::TestRunner};
|
||||||
use tower::ServiceExt;
|
use tower::ServiceExt;
|
||||||
|
|
||||||
use crate::context::{
|
use crate::{
|
||||||
|
context::{
|
||||||
initialize_blockchain_context, BlockChainContextRequest, BlockChainContextResponse,
|
initialize_blockchain_context, BlockChainContextRequest, BlockChainContextResponse,
|
||||||
ContextConfig, UpdateBlockchainCacheData,
|
ContextConfig, UpdateBlockchainCacheData,
|
||||||
|
},
|
||||||
|
tests::mock_db::*,
|
||||||
|
HardFork,
|
||||||
};
|
};
|
||||||
use crate::{tests::mock_db::*, HardFork};
|
|
||||||
|
|
||||||
pub(crate) mod data;
|
pub(crate) mod data;
|
||||||
mod difficulty;
|
mod difficulty;
|
||||||
|
|
|
@ -2,7 +2,9 @@ use std::collections::VecDeque;
|
||||||
|
|
||||||
use proptest::{arbitrary::any, prop_assert_eq, prop_compose, proptest};
|
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_WINDOW: usize = 72;
|
||||||
const TEST_CUT: usize = 6;
|
const TEST_CUT: usize = 6;
|
||||||
|
|
|
@ -4,8 +4,8 @@ use crate::{
|
||||||
BlockWeightsCacheConfig,
|
BlockWeightsCacheConfig,
|
||||||
},
|
},
|
||||||
tests::{context::data::BW_2850000_3050000, mock_db::*},
|
tests::{context::data::BW_2850000_3050000, mock_db::*},
|
||||||
|
HardFork,
|
||||||
};
|
};
|
||||||
use monero_consensus::HardFork;
|
|
||||||
|
|
||||||
pub const TEST_WEIGHT_CONFIG: BlockWeightsCacheConfig = BlockWeightsCacheConfig::new(100, 5000);
|
pub const TEST_WEIGHT_CONFIG: BlockWeightsCacheConfig = BlockWeightsCacheConfig::new(100, 5000);
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@ use proptest::{
|
||||||
use proptest_derive::Arbitrary;
|
use proptest_derive::Arbitrary;
|
||||||
use tower::{BoxError, Service};
|
use tower::{BoxError, Service};
|
||||||
|
|
||||||
use cuprate_common::BlockID;
|
|
||||||
|
|
||||||
use crate::{DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork};
|
use crate::{DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork};
|
||||||
|
|
||||||
prop_compose! {
|
prop_compose! {
|
||||||
|
@ -140,7 +138,7 @@ impl Service<DatabaseRequest> for DummyDatabase {
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
Ok(match req {
|
Ok(match req {
|
||||||
DatabaseRequest::BlockExtendedHeader(BlockID::Height(id)) => {
|
DatabaseRequest::BlockExtendedHeader(id) => {
|
||||||
let mut id = usize::try_from(id).unwrap();
|
let mut id = usize::try_from(id).unwrap();
|
||||||
if let Some(dummy_height) = dummy_height {
|
if let Some(dummy_height) = dummy_height {
|
||||||
let block_len = blocks.read().unwrap().len();
|
let block_len = blocks.read().unwrap().len();
|
||||||
|
|
|
@ -14,6 +14,7 @@ use rayon::prelude::*;
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use cuprate_helper::asynch::rayon_spawn_async;
|
||||||
use monero_consensus::{
|
use monero_consensus::{
|
||||||
transactions::{
|
transactions::{
|
||||||
check_transaction_contextual, check_transaction_semantic, RingCTError, TransactionError,
|
check_transaction_contextual, check_transaction_semantic, RingCTError, TransactionError,
|
||||||
|
@ -23,8 +24,8 @@ use monero_consensus::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
batch_verifier::MultiThreadedBatchVerifier, context::ReOrgToken, helper::rayon_spawn_async,
|
batch_verifier::MultiThreadedBatchVerifier, context::ReOrgToken, Database, DatabaseRequest,
|
||||||
Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError,
|
DatabaseResponse, ExtendedConsensusError,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod contextual_data;
|
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]
|
[package]
|
||||||
name = "helper"
|
name = "cuprate-helper"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
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]
|
[features]
|
||||||
# All features on by default.
|
# All features on by default.
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
pub mod asynch; // async collides
|
pub mod asynch; // async collides
|
||||||
#[cfg(feature = "atomic")]
|
#[cfg(feature = "atomic")]
|
||||||
pub mod atomic;
|
pub mod atomic;
|
||||||
|
pub mod network;
|
||||||
#[cfg(feature = "num")]
|
#[cfg(feature = "num")]
|
||||||
pub mod num;
|
pub mod num;
|
||||||
#[cfg(feature = "thread")]
|
#[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] = [
|
const MAINNET_NETWORK_ID: [u8; 16] = [
|
||||||
0x12, 0x30, 0xF1, 0x71, 0x61, 0x04, 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10,
|
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,
|
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)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
|
/// Mainnet
|
||||||
#[default]
|
#[default]
|
||||||
Mainnet,
|
Mainnet,
|
||||||
|
/// Testnet
|
||||||
Testnet,
|
Testnet,
|
||||||
|
/// Stagenet
|
||||||
Stagenet,
|
Stagenet,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
|
/// Returns the network ID for the current network.
|
||||||
pub fn network_id(&self) -> [u8; 16] {
|
pub fn network_id(&self) -> [u8; 16] {
|
||||||
match self {
|
match self {
|
||||||
Network::Mainnet => MAINNET_NETWORK_ID,
|
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
|
/// Returns the average of two numbers; works with at least all integral and floating point types
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use helper::num::*;
|
/// # use cuprate_helper::num::*;
|
||||||
/// assert_eq!(get_mid(0, 10), 5);
|
/// assert_eq!(get_mid(0, 10), 5);
|
||||||
/// assert_eq!(get_mid(0.0, 10.0), 5.0);
|
/// assert_eq!(get_mid(0.0, 10.0), 5.0);
|
||||||
/// assert_eq!(get_mid(-10.0, 10.0), 0.0);
|
/// assert_eq!(get_mid(-10.0, 10.0), 0.0);
|
||||||
|
@ -76,7 +76,7 @@ where
|
||||||
/// Gets the median from a sorted slice.
|
/// Gets the median from a sorted slice.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use helper::num::*;
|
/// # use cuprate_helper::num::*;
|
||||||
/// let mut vec = vec![10, 5, 1, 4, 2, 8, 9, 7, 3, 6];
|
/// let mut vec = vec![10, 5, 1, 4, 2, 8, 9, 7, 3, 6];
|
||||||
/// vec.sort();
|
/// vec.sort();
|
||||||
///
|
///
|
||||||
|
@ -109,7 +109,7 @@ where
|
||||||
/// Compare 2 non-`NaN` floats.
|
/// Compare 2 non-`NaN` floats.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use helper::num::*;
|
/// # use cuprate_helper::num::*;
|
||||||
/// # use core::cmp::Ordering;
|
/// # use core::cmp::Ordering;
|
||||||
/// assert_eq!(cmp_float(0.0, 1.0), Ordering::Less);
|
/// assert_eq!(cmp_float(0.0, 1.0), Ordering::Less);
|
||||||
/// assert_eq!(cmp_float(1.0, 1.0), Ordering::Equal);
|
/// assert_eq!(cmp_float(1.0, 1.0), Ordering::Equal);
|
||||||
|
@ -128,7 +128,7 @@ where
|
||||||
/// This function panics if either floats are NaNs.
|
/// This function panics if either floats are NaNs.
|
||||||
///
|
///
|
||||||
/// ```rust,should_panic
|
/// ```rust,should_panic
|
||||||
/// # use helper::num::*;
|
/// # use cuprate_helper::num::*;
|
||||||
/// cmp_float(0.0, f32::NAN);
|
/// cmp_float(0.0, f32::NAN);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cmp_float<F: Float>(a: F, b: F) -> Ordering {
|
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`].
|
/// Compare 2 floats, `NaN`'s will always return [`Ordering::Equal`].
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use helper::num::*;
|
/// # use cuprate_helper::num::*;
|
||||||
/// # use core::cmp::Ordering;
|
/// # use core::cmp::Ordering;
|
||||||
/// assert_eq!(cmp_float_nan(0.0, 1.0), Ordering::Less);
|
/// assert_eq!(cmp_float_nan(0.0, 1.0), Ordering::Less);
|
||||||
/// assert_eq!(cmp_float_nan(1.0, 1.0), Ordering::Equal);
|
/// 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]
|
[dependencies]
|
||||||
levin-cuprate = {path="../levin"}
|
levin-cuprate = {path="../levin"}
|
||||||
monero-epee-bin-serde = {git = "https://github.com/monero-rs/monero-epee-bin-serde.git", rev="aafe4ba"}
|
monero-epee-bin-serde = { workspace = true, features = ["container_as_blob"] }
|
||||||
serde = {version = "1", features = ["derive"]}
|
serde = { workspace = true, features = ["derive", "std"]}
|
||||||
serde_bytes = "0.11"
|
serde_bytes = { workspace = true, features = ["std"]}
|
||||||
thiserror = "1"
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4.3"
|
hex = { workspace = true, features = ["std"]}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ authors = ["Boog900"]
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cuprate-common = {path = "../../common"}
|
monero-pruning = { path = "../../pruning" }
|
||||||
monero-wire = {path= "../../net/monero-wire"}
|
monero-wire = { path= "../../net/monero-wire" }
|
||||||
monero-p2p = {path = "../monero-p2p" }
|
monero-p2p = { path = "../monero-p2p" }
|
||||||
|
|
||||||
tower = { workspace = true, features = ["util", "buffer"] }
|
tower = { workspace = true, features = ["util", "buffer"] }
|
||||||
tokio = { workspace = true, features = ["time", "fs", "rt"]}
|
tokio = { workspace = true, features = ["time", "fs", "rt"]}
|
||||||
|
|
|
@ -19,13 +19,13 @@ use tokio::{
|
||||||
};
|
};
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
|
|
||||||
use cuprate_common::PruningSeed;
|
|
||||||
use monero_p2p::{
|
use monero_p2p::{
|
||||||
client::InternalPeerID,
|
client::InternalPeerID,
|
||||||
handles::ConnectionHandle,
|
handles::ConnectionHandle,
|
||||||
services::{AddressBookRequest, AddressBookResponse, ZoneSpecificPeerListEntryBase},
|
services::{AddressBookRequest, AddressBookResponse, ZoneSpecificPeerListEntryBase},
|
||||||
NetZoneAddress, NetworkZone,
|
NetZoneAddress, NetworkZone,
|
||||||
};
|
};
|
||||||
|
use monero_pruning::PruningSeed;
|
||||||
|
|
||||||
use crate::{peer_list::PeerList, store::save_peers_to_disk, AddressBookError, Config};
|
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::sync::Semaphore;
|
||||||
use tokio::time::interval;
|
use tokio::time::interval;
|
||||||
|
|
||||||
use cuprate_common::PruningSeed;
|
|
||||||
use monero_p2p::handles::HandleBuilder;
|
use monero_p2p::handles::HandleBuilder;
|
||||||
|
use monero_pruning::PruningSeed;
|
||||||
|
|
||||||
use super::{AddressBook, ConnectionPeerEntry, InternalPeerID};
|
use super::{AddressBook, ConnectionPeerEntry, InternalPeerID};
|
||||||
use crate::{peer_list::tests::make_fake_peer_list, AddressBookError, Config};
|
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 rand::{seq::SliceRandom, Rng};
|
||||||
|
|
||||||
use cuprate_common::{PruningSeed, CRYPTONOTE_MAX_BLOCK_NUMBER};
|
|
||||||
use monero_p2p::{services::ZoneSpecificPeerListEntryBase, NetZoneAddress, NetworkZone};
|
use monero_p2p::{services::ZoneSpecificPeerListEntryBase, NetZoneAddress, NetworkZone};
|
||||||
|
use monero_pruning::{PruningSeed, CRYPTONOTE_MAX_BLOCK_NUMBER};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
|
@ -2,8 +2,8 @@ use std::collections::HashSet;
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use cuprate_common::PruningSeed;
|
|
||||||
use monero_p2p::services::ZoneSpecificPeerListEntryBase;
|
use monero_p2p::services::ZoneSpecificPeerListEntryBase;
|
||||||
|
use monero_pruning::PruningSeed;
|
||||||
|
|
||||||
use cuprate_test_utils::test_netzone::{TestNetZone, TestNetZoneAddr};
|
use cuprate_test_utils::test_netzone::{TestNetZone, TestNetZoneAddr};
|
||||||
use monero_p2p::NetZoneAddress;
|
use monero_p2p::NetZoneAddress;
|
||||||
|
|
|
@ -7,11 +7,12 @@ authors = ["Boog900"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["borsh"]
|
default = ["borsh"]
|
||||||
borsh = ["dep:borsh"]
|
borsh = ["dep:borsh", "monero-pruning/borsh"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
monero-wire = {path= "../../net/monero-wire"}
|
cuprate-helper = { path = "../../helper" }
|
||||||
cuprate-common = {path = "../../common", features = ["borsh"]}
|
monero-wire = { path = "../../net/monero-wire" }
|
||||||
|
monero-pruning = { path = "../../pruning" }
|
||||||
|
|
||||||
tokio = { workspace = true, features = ["net", "sync", "macros"]}
|
tokio = { workspace = true, features = ["net", "sync", "macros"]}
|
||||||
tokio-util = { workspace = true, features = ["codec"] }
|
tokio-util = { workspace = true, features = ["codec"] }
|
||||||
|
|
|
@ -9,7 +9,7 @@ use tokio::{sync::mpsc, task::JoinHandle};
|
||||||
use tokio_util::sync::PollSender;
|
use tokio_util::sync::PollSender;
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
|
|
||||||
use cuprate_common::tower_utils::InfallibleOneshotReceiver;
|
use cuprate_helper::asynch::InfallibleOneshotReceiver;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
handles::ConnectionHandle, NetworkZone, PeerError, PeerRequest, PeerResponse, SharedError,
|
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 monero_wire::{NetZone, NetworkAddress, PeerListEntryBase};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -5,7 +5,7 @@ use futures::{channel::mpsc, StreamExt};
|
||||||
use tokio::sync::{broadcast, Semaphore};
|
use tokio::sync::{broadcast, Semaphore};
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
|
|
||||||
use cuprate_common::Network;
|
use cuprate_helper::network::Network;
|
||||||
use monero_wire::{common::PeerSupportFlags, BasicNodeData};
|
use monero_wire::{common::PeerSupportFlags, BasicNodeData};
|
||||||
|
|
||||||
use monero_p2p::{
|
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
|
//! # 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,
|
//! 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.
|
//! which determine the set of blocks to be pruned from the blockchain.
|
||||||
//!
|
//!
|
||||||
|
@ -8,9 +8,9 @@
|
||||||
//! split into 8 parts):
|
//! split into 8 parts):
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```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) {
|
//! match PruningSeed::try_from(seed) {
|
||||||
//! Ok(seed) => seed, // seed is valid
|
//! Ok(seed) => seed, // seed is valid
|
||||||
//! Err(e) => panic!("seed is invalid")
|
//! Err(e) => panic!("seed is invalid")
|
||||||
|
@ -22,10 +22,11 @@ use std::cmp::Ordering;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use super::{
|
pub const CRYPTONOTE_MAX_BLOCK_NUMBER: u64 = 500000000;
|
||||||
CRYPTONOTE_MAX_BLOCK_NUMBER, CRYPTONOTE_PRUNING_LOG_STRIPES, CRYPTONOTE_PRUNING_STRIPE_SIZE,
|
|
||||||
CRYPTONOTE_PRUNING_TIP_BLOCKS,
|
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_LOG_STRIPES_SHIFT: u32 = 7;
|
||||||
const PRUNING_SEED_STRIPE_SHIFT: u32 = 0;
|
const PRUNING_SEED_STRIPE_SHIFT: u32 = 0;
|
||||||
|
@ -289,9 +290,7 @@ fn get_block_pruning_stripe(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::pruning::{get_block_pruning_stripe, PruningSeed};
|
use super::*;
|
||||||
|
|
||||||
use super::CRYPTONOTE_PRUNING_LOG_STRIPES;
|
|
||||||
|
|
||||||
fn make_all_pruning_seeds() -> Vec<PruningSeed> {
|
fn make_all_pruning_seeds() -> Vec<PruningSeed> {
|
||||||
let possible_stripes = 1..(1 << CRYPTONOTE_PRUNING_LOG_STRIPES);
|
let possible_stripes = 1..(1 << CRYPTONOTE_PRUNING_LOG_STRIPES);
|
Loading…
Reference in a new issue