mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-22 19:49:28 +00:00
types: HardFork
improvements (#309)
Some checks failed
Audit / audit (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Deny / audit (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled
Some checks failed
Audit / audit (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Deny / audit (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled
* apply diffs * review fixes
This commit is contained in:
parent
d43f12ea3f
commit
f9b847b227
4 changed files with 122 additions and 31 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -933,6 +933,7 @@ dependencies = [
|
||||||
"proptest-derive",
|
"proptest-derive",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"strum",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2673,6 +2674,28 @@ dependencies = [
|
||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn 2.0.77",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
|
|
@ -78,6 +78,7 @@ rayon = { version = "1.10.0", default-features = false }
|
||||||
serde_bytes = { version = "0.11.15", default-features = false }
|
serde_bytes = { version = "0.11.15", default-features = false }
|
||||||
serde_json = { version = "1.0.128", default-features = false }
|
serde_json = { version = "1.0.128", default-features = false }
|
||||||
serde = { version = "1.0.210", default-features = false }
|
serde = { version = "1.0.210", default-features = false }
|
||||||
|
strum = { version = "0.26.3", default-features = false }
|
||||||
thiserror = { version = "1.0.63", default-features = false }
|
thiserror = { version = "1.0.63", default-features = false }
|
||||||
thread_local = { version = "1.1.8", default-features = false }
|
thread_local = { version = "1.1.8", default-features = false }
|
||||||
tokio-util = { version = "0.7.12", default-features = false }
|
tokio-util = { version = "0.7.12", default-features = false }
|
||||||
|
|
|
@ -27,6 +27,7 @@ curve25519-dalek = { workspace = true }
|
||||||
monero-serai = { workspace = true }
|
monero-serai = { workspace = true }
|
||||||
hex = { workspace = true, features = ["serde", "alloc"], optional = true }
|
hex = { workspace = true, features = ["serde", "alloc"], optional = true }
|
||||||
serde = { workspace = true, features = ["derive"], optional = true }
|
serde = { workspace = true, features = ["derive"], optional = true }
|
||||||
|
strum = { workspace = true, features = ["derive"] }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
proptest = { workspace = true, optional = true }
|
proptest = { workspace = true, optional = true }
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
//! The [`HardFork`] type.
|
//! The [`HardFork`] type.
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use strum::{
|
||||||
|
AsRefStr, Display, EnumCount, EnumIs, EnumString, FromRepr, IntoStaticStr, VariantArray,
|
||||||
|
};
|
||||||
|
|
||||||
use monero_serai::block::BlockHeader;
|
use monero_serai::block::BlockHeader;
|
||||||
|
|
||||||
/// Target block time for hf 1.
|
/// Target block time for hf 1.
|
||||||
|
@ -27,7 +31,25 @@ pub enum HardForkError {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An identifier for every hard-fork Monero has had.
|
/// An identifier for every hard-fork Monero has had.
|
||||||
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Hash)]
|
#[derive(
|
||||||
|
Default,
|
||||||
|
Debug,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
Hash,
|
||||||
|
EnumCount,
|
||||||
|
Display,
|
||||||
|
AsRefStr,
|
||||||
|
EnumIs,
|
||||||
|
EnumString,
|
||||||
|
FromRepr,
|
||||||
|
IntoStaticStr,
|
||||||
|
VariantArray,
|
||||||
|
)]
|
||||||
#[cfg_attr(any(feature = "proptest"), derive(proptest_derive::Arbitrary))]
|
#[cfg_attr(any(feature = "proptest"), derive(proptest_derive::Arbitrary))]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum HardFork {
|
pub enum HardFork {
|
||||||
|
@ -47,58 +69,75 @@ pub enum HardFork {
|
||||||
V13,
|
V13,
|
||||||
V14,
|
V14,
|
||||||
V15,
|
V15,
|
||||||
// remember to update from_vote!
|
|
||||||
V16,
|
V16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HardFork {
|
impl HardFork {
|
||||||
|
/// The latest [`HardFork`].
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cuprate_types::HardFork;
|
||||||
|
/// assert_eq!(HardFork::LATEST, HardFork::V16);
|
||||||
|
/// ```
|
||||||
|
pub const LATEST: Self = Self::VARIANTS[Self::COUNT - 1];
|
||||||
|
|
||||||
/// Returns the hard-fork for a blocks [`BlockHeader::hardfork_version`] field.
|
/// Returns the hard-fork for a blocks [`BlockHeader::hardfork_version`] field.
|
||||||
///
|
///
|
||||||
/// ref: <https://monero-book.cuprate.org/consensus_rules/hardforks.html#blocks-version-and-vote>
|
/// ref: <https://monero-book.cuprate.org/consensus_rules/hardforks.html#blocks-version-and-vote>
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
|
||||||
/// Will return [`Err`] if the version is not a valid [`HardFork`].
|
/// Will return [`Err`] if the version is not a valid [`HardFork`].
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cuprate_types::{HardFork, HardForkError};
|
||||||
|
/// # use strum::VariantArray;
|
||||||
|
/// assert_eq!(HardFork::from_version(0), Err(HardForkError::HardForkUnknown));
|
||||||
|
/// assert_eq!(HardFork::from_version(17), Err(HardForkError::HardForkUnknown));
|
||||||
|
///
|
||||||
|
/// for (version, hf) in HardFork::VARIANTS.iter().enumerate() {
|
||||||
|
/// // +1 because enumerate starts at 0, hf starts at 1.
|
||||||
|
/// assert_eq!(*hf, HardFork::from_version(version as u8 + 1).unwrap());
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_version(version: u8) -> Result<Self, HardForkError> {
|
pub const fn from_version(version: u8) -> Result<Self, HardForkError> {
|
||||||
Ok(match version {
|
match Self::from_repr(version) {
|
||||||
1 => Self::V1,
|
Some(this) => Ok(this),
|
||||||
2 => Self::V2,
|
None => Err(HardForkError::HardForkUnknown),
|
||||||
3 => Self::V3,
|
}
|
||||||
4 => Self::V4,
|
|
||||||
5 => Self::V5,
|
|
||||||
6 => Self::V6,
|
|
||||||
7 => Self::V7,
|
|
||||||
8 => Self::V8,
|
|
||||||
9 => Self::V9,
|
|
||||||
10 => Self::V10,
|
|
||||||
11 => Self::V11,
|
|
||||||
12 => Self::V12,
|
|
||||||
13 => Self::V13,
|
|
||||||
14 => Self::V14,
|
|
||||||
15 => Self::V15,
|
|
||||||
16 => Self::V16,
|
|
||||||
_ => return Err(HardForkError::HardForkUnknown),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the hard-fork for a blocks [`BlockHeader::hardfork_signal`] (vote) field.
|
/// Returns the hard-fork for a blocks [`BlockHeader::hardfork_signal`] (vote) field.
|
||||||
///
|
///
|
||||||
/// <https://monero-book.cuprate.org/consensus_rules/hardforks.html#blocks-version-and-vote>
|
/// <https://monero-book.cuprate.org/consensus_rules/hardforks.html#blocks-version-and-vote>
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cuprate_types::{HardFork, HardForkError};
|
||||||
|
/// # use strum::VariantArray;
|
||||||
|
/// // 0 is interpreted as 1.
|
||||||
|
/// assert_eq!(HardFork::from_vote(0), HardFork::V1);
|
||||||
|
/// // Unknown defaults to `LATEST`.
|
||||||
|
/// assert_eq!(HardFork::from_vote(17), HardFork::V16);
|
||||||
|
///
|
||||||
|
/// for (vote, hf) in HardFork::VARIANTS.iter().enumerate() {
|
||||||
|
/// // +1 because enumerate starts at 0, hf starts at 1.
|
||||||
|
/// assert_eq!(*hf, HardFork::from_vote(vote as u8 + 1));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_vote(vote: u8) -> Self {
|
pub fn from_vote(vote: u8) -> Self {
|
||||||
if vote == 0 {
|
if vote == 0 {
|
||||||
// A vote of 0 is interpreted as 1 as that's what Monero used to default to.
|
// A vote of 0 is interpreted as 1 as that's what Monero used to default to.
|
||||||
return Self::V1;
|
Self::V1
|
||||||
}
|
} else {
|
||||||
// This must default to the latest hard-fork!
|
// This must default to the latest hard-fork!
|
||||||
Self::from_version(vote).unwrap_or(Self::V16)
|
Self::from_version(vote).unwrap_or(Self::LATEST)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [`HardFork`] version and vote from this block header.
|
/// Returns the [`HardFork`] version and vote from this block header.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
|
||||||
/// Will return [`Err`] if the [`BlockHeader::hardfork_version`] is not a valid [`HardFork`].
|
/// Will return [`Err`] if the [`BlockHeader::hardfork_version`] is not a valid [`HardFork`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_block_header(header: &BlockHeader) -> Result<(Self, Self), HardForkError> {
|
pub fn from_block_header(header: &BlockHeader) -> Result<(Self, Self), HardForkError> {
|
||||||
|
@ -109,22 +148,49 @@ impl HardFork {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the raw hard-fork value, as it would appear in [`BlockHeader::hardfork_version`].
|
/// Returns the raw hard-fork value, as it would appear in [`BlockHeader::hardfork_version`].
|
||||||
pub const fn as_u8(&self) -> u8 {
|
///
|
||||||
*self as u8
|
/// ```rust
|
||||||
|
/// # use cuprate_types::{HardFork, HardForkError};
|
||||||
|
/// # use strum::VariantArray;
|
||||||
|
/// for (i, hf) in HardFork::VARIANTS.iter().enumerate() {
|
||||||
|
/// // +1 because enumerate starts at 0, hf starts at 1.
|
||||||
|
/// assert_eq!(hf.as_u8(), i as u8 + 1);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub const fn as_u8(self) -> u8 {
|
||||||
|
self as u8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the next hard-fork.
|
/// Returns the next hard-fork.
|
||||||
pub fn next_fork(&self) -> Option<Self> {
|
pub fn next_fork(self) -> Option<Self> {
|
||||||
Self::from_version(*self as u8 + 1).ok()
|
Self::from_version(self as u8 + 1).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the target block time for this hardfork.
|
/// Returns the target block time for this hardfork.
|
||||||
///
|
///
|
||||||
/// ref: <https://monero-book.cuprate.org/consensus_rules/blocks/difficulty.html#target-seconds>
|
/// ref: <https://monero-book.cuprate.org/consensus_rules/blocks/difficulty.html#target-seconds>
|
||||||
pub const fn block_time(&self) -> Duration {
|
pub const fn block_time(self) -> Duration {
|
||||||
match self {
|
match self {
|
||||||
Self::V1 => BLOCK_TIME_V1,
|
Self::V1 => BLOCK_TIME_V1,
|
||||||
_ => BLOCK_TIME_V2,
|
_ => BLOCK_TIME_V2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is [`Self::LATEST`].
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cuprate_types::HardFork;
|
||||||
|
/// # use strum::VariantArray;
|
||||||
|
///
|
||||||
|
/// for hf in HardFork::VARIANTS.iter() {
|
||||||
|
/// if *hf == HardFork::LATEST {
|
||||||
|
/// assert!(hf.is_latest());
|
||||||
|
/// } else {
|
||||||
|
/// assert!(!hf.is_latest());
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub const fn is_latest(self) -> bool {
|
||||||
|
matches!(self, Self::LATEST)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue