mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-01-30 15:32:14 +00:00
Consensus parameters for network upgrades
This commit is contained in:
parent
c24024b8e1
commit
cd326f2b6a
@ -1,5 +1,106 @@
|
||||
//! Consensus parameters.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Zcash consensus parameters.
|
||||
pub trait Parameters {
|
||||
fn activation_height(nu: NetworkUpgrade) -> Option<u32>;
|
||||
|
||||
fn is_nu_active(nu: NetworkUpgrade, height: u32) -> bool {
|
||||
match Self::activation_height(nu) {
|
||||
Some(h) if h <= height => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker struct for the production network.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MainNetwork;
|
||||
|
||||
impl Parameters for MainNetwork {
|
||||
fn activation_height(nu: NetworkUpgrade) -> Option<u32> {
|
||||
match nu {
|
||||
NetworkUpgrade::Overwinter => Some(347_500),
|
||||
NetworkUpgrade::Sapling => Some(419_200),
|
||||
NetworkUpgrade::Blossom => Some(653_600),
|
||||
NetworkUpgrade::Heartwood => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker struct for the test network.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct TestNetwork;
|
||||
|
||||
impl Parameters for TestNetwork {
|
||||
fn activation_height(nu: NetworkUpgrade) -> Option<u32> {
|
||||
match nu {
|
||||
NetworkUpgrade::Overwinter => Some(207_500),
|
||||
NetworkUpgrade::Sapling => Some(280_000),
|
||||
NetworkUpgrade::Blossom => Some(584_000),
|
||||
NetworkUpgrade::Heartwood => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An event that occurs at a specified height on the Zcash chain, at which point the
|
||||
/// consensus rules enforced by the network are altered.
|
||||
///
|
||||
/// See [ZIP 200](https://zips.z.cash/zip-0200) for more details.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum NetworkUpgrade {
|
||||
/// The [Overwinter] network upgrade.
|
||||
///
|
||||
/// [Overwinter]: https://z.cash/upgrade/overwinter/
|
||||
Overwinter,
|
||||
/// The [Sapling] network upgrade.
|
||||
///
|
||||
/// [Sapling]: https://z.cash/upgrade/sapling/
|
||||
Sapling,
|
||||
/// The [Blossom] network upgrade.
|
||||
///
|
||||
/// [Blossom]: https://z.cash/upgrade/blossom/
|
||||
Blossom,
|
||||
/// The [Heartwood] network upgrade.
|
||||
///
|
||||
/// [Heartwood]: https://z.cash/upgrade/heartwood/
|
||||
Heartwood,
|
||||
}
|
||||
|
||||
impl fmt::Display for NetworkUpgrade {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
NetworkUpgrade::Overwinter => write!(f, "Overwinter"),
|
||||
NetworkUpgrade::Sapling => write!(f, "Sapling"),
|
||||
NetworkUpgrade::Blossom => write!(f, "Blossom"),
|
||||
NetworkUpgrade::Heartwood => write!(f, "Heartwood"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkUpgrade {
|
||||
fn branch_id(self) -> BranchId {
|
||||
match self {
|
||||
NetworkUpgrade::Overwinter => BranchId::Overwinter,
|
||||
NetworkUpgrade::Sapling => BranchId::Sapling,
|
||||
NetworkUpgrade::Blossom => BranchId::Blossom,
|
||||
NetworkUpgrade::Heartwood => BranchId::Heartwood,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The network upgrades on the Zcash chain in order of activation.
|
||||
///
|
||||
/// This order corresponds to the activation heights, but because Rust enums are
|
||||
/// full-fledged algebraic data types, we need to define it manually.
|
||||
const UPGRADES_IN_ORDER: &[NetworkUpgrade] = &[
|
||||
NetworkUpgrade::Overwinter,
|
||||
NetworkUpgrade::Sapling,
|
||||
NetworkUpgrade::Blossom,
|
||||
NetworkUpgrade::Heartwood,
|
||||
];
|
||||
|
||||
/// A globally-unique identifier for a set of consensus rules within the Zcash chain.
|
||||
///
|
||||
/// Each branch ID in this enum corresponds to one of the epochs between a pair of Zcash
|
||||
@ -13,25 +114,17 @@
|
||||
/// See [ZIP 200](https://zips.z.cash/zip-0200) for more details.
|
||||
///
|
||||
/// [`signature_hash`]: crate::transaction::signature_hash
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum BranchId {
|
||||
/// The consensus rules at the launch of Zcash.
|
||||
Sprout,
|
||||
/// The consensus rules deployed in the [Overwinter] network upgrade.
|
||||
///
|
||||
/// [Overwinter]: https://z.cash/upgrade/overwinter/
|
||||
/// The consensus rules deployed by [`NetworkUpgrade::Overwinter`].
|
||||
Overwinter,
|
||||
/// The consensus rules deployed in the [Sapling] network upgrade.
|
||||
///
|
||||
/// [Sapling]: https://z.cash/upgrade/sapling/
|
||||
/// The consensus rules deployed by [`NetworkUpgrade::Sapling`].
|
||||
Sapling,
|
||||
/// The consensus rules deployed in the [Blossom] network upgrade.
|
||||
///
|
||||
/// [Blossom]: https://z.cash/upgrade/blossom/
|
||||
/// The consensus rules deployed by [`NetworkUpgrade::Blossom`].
|
||||
Blossom,
|
||||
/// The consensus rules deployed in the [Heartwood] network upgrade.
|
||||
///
|
||||
/// [Heartwood]: https://z.cash/upgrade/heartwood/
|
||||
/// The consensus rules deployed by [`NetworkUpgrade::Heartwood`].
|
||||
Heartwood,
|
||||
}
|
||||
|
||||
@ -46,3 +139,75 @@ impl From<BranchId> for u32 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BranchId {
|
||||
/// Returns the branch ID corresponding to the consensus rule set that is active at
|
||||
/// the given height.
|
||||
///
|
||||
/// This is the branch ID that should be used when creating transactions.
|
||||
pub fn for_height<C: Parameters>(height: u32) -> Self {
|
||||
for nu in UPGRADES_IN_ORDER.iter().rev() {
|
||||
if C::is_nu_active(*nu, height) {
|
||||
return nu.branch_id();
|
||||
}
|
||||
}
|
||||
|
||||
// Sprout rules apply before any network upgrade
|
||||
BranchId::Sprout
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{BranchId, Parameters, MainNetwork, NetworkUpgrade, UPGRADES_IN_ORDER};
|
||||
|
||||
#[test]
|
||||
fn nu_ordering() {
|
||||
for i in 1..UPGRADES_IN_ORDER.len() {
|
||||
let nu_a = UPGRADES_IN_ORDER[i - 1];
|
||||
let nu_b = UPGRADES_IN_ORDER[i];
|
||||
match (
|
||||
MainNetwork::activation_height(nu_a),
|
||||
MainNetwork::activation_height(nu_b),
|
||||
) {
|
||||
(Some(a), Some(b)) if a < b => (),
|
||||
(Some(_), None) => (),
|
||||
(None, None) => (),
|
||||
_ => panic!(
|
||||
"{} should not be before {} in UPGRADES_IN_ORDER",
|
||||
nu_a, nu_b
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nu_is_active() {
|
||||
assert!(!MainNetwork::is_nu_active(NetworkUpgrade::Overwinter, 0));
|
||||
assert!(!MainNetwork::is_nu_active(
|
||||
NetworkUpgrade::Overwinter,
|
||||
347_499
|
||||
));
|
||||
assert!(MainNetwork::is_nu_active(
|
||||
NetworkUpgrade::Overwinter,
|
||||
347_500
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn branch_id_for_height() {
|
||||
assert_eq!(BranchId::for_height::<MainNetwork>(0), BranchId::Sprout,);
|
||||
assert_eq!(
|
||||
BranchId::for_height::<MainNetwork>(419_199),
|
||||
BranchId::Overwinter,
|
||||
);
|
||||
assert_eq!(
|
||||
BranchId::for_height::<MainNetwork>(419_200),
|
||||
BranchId::Sapling,
|
||||
);
|
||||
assert_eq!(
|
||||
BranchId::for_height::<MainNetwork>(5_000_000),
|
||||
BranchId::Blossom,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user