466 lines
19 KiB
Rust
466 lines
19 KiB
Rust
use zebra_crypto;
|
|
use zebra_keys::Address;
|
|
use {Deployment, Magic, Network};
|
|
|
|
lazy_static! {
|
|
static ref SAPLING_SPEND_VK: zebra_crypto::Groth16VerifyingKey =
|
|
zebra_crypto::load_sapling_spend_verifying_key()
|
|
.expect("hardcoded value should load without errors");
|
|
static ref SAPLING_OUTPUT_VK: zebra_crypto::Groth16VerifyingKey =
|
|
zebra_crypto::load_sapling_output_verifying_key()
|
|
.expect("hardcoded value should load without errors");
|
|
static ref JOINSPLIT_GROTH16_VK: zebra_crypto::Groth16VerifyingKey =
|
|
zebra_crypto::load_joinsplit_groth16_verifying_key()
|
|
.expect("hardcoded value should load without errors");
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
/// Parameters that influence chain consensus.
|
|
pub struct ConsensusParams {
|
|
/// Network.
|
|
pub network: Network,
|
|
/// Time when BIP16 becomes active.
|
|
/// See https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
|
|
pub bip16_time: u32,
|
|
/// Block height at which BIP34 becomes active.
|
|
/// See https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki
|
|
pub bip34_height: u32,
|
|
/// Block height at which BIP65 becomes active.
|
|
/// See https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
|
|
pub bip65_height: u32,
|
|
/// Block height at which BIP65 becomes active.
|
|
/// See https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
|
pub bip66_height: u32,
|
|
/// Version bits activation
|
|
pub rule_change_activation_threshold: u32,
|
|
/// Number of blocks with the same set of rules
|
|
pub miner_confirmation_window: u32,
|
|
/// BIP68, BIP112, BIP113 deployment
|
|
pub csv_deployment: Option<Deployment>,
|
|
|
|
/// Height of Overwinter activation.
|
|
/// Details: https://zcash.readthedocs.io/en/latest/rtd_pages/nu_dev_guide.html#overwinter
|
|
pub overwinter_height: u32,
|
|
/// Height of Sapling activation.
|
|
/// Details: https://zcash.readthedocs.io/en/latest/rtd_pages/nu_dev_guide.html#sapling
|
|
pub sapling_height: u32,
|
|
|
|
/// Interval (in blocks) to calculate average work.
|
|
pub pow_averaging_window: u32,
|
|
/// % of possible down adjustment of work.
|
|
pub pow_max_adjust_down: u32,
|
|
/// % of possible up adjustment of work.
|
|
pub pow_max_adjust_up: u32,
|
|
/// Optimal blocks interval (in seconds).
|
|
pub pow_target_spacing: u32,
|
|
/// Allow minimal difficulty after block at given height.
|
|
pub pow_allow_min_difficulty_after_height: Option<u32>,
|
|
|
|
/// 'Slow start' interval parameter.
|
|
///
|
|
/// For details on how (and why) Zcash 'slow start' works, refer to:
|
|
/// https://z.cash/support/faq/#what-is-slow-start-mining
|
|
/// https://github.com/zcash/zcash/issues/762
|
|
pub subsidy_slow_start_interval: u32,
|
|
/// Block subsidy halving interval.
|
|
///
|
|
/// Block subsidy is halved every `subsidy_halving_interval` blocks.
|
|
/// There are 64 halving intervals in total.
|
|
pub subsidy_halving_interval: u32,
|
|
/// The vector of addresses where founders reward goes.
|
|
///
|
|
/// For details on what's founders' reward, refer to:
|
|
/// https://z.cash/support/faq/#founders-reward
|
|
pub founders_addresses: Vec<Address>,
|
|
|
|
/// Equihash (N, K) parameters.
|
|
pub equihash_params: Option<(u32, u32)>,
|
|
|
|
/// Active key for pghr13 joinsplit verification
|
|
pub joinsplit_verification_key: zebra_crypto::Pghr13VerifyingKey,
|
|
|
|
/// Active key for groth16 joinsplit verification
|
|
pub joinsplit_groth16_verification_key: &'static zebra_crypto::Groth16VerifyingKey,
|
|
|
|
/// Sapling spend verification key.
|
|
pub sapling_spend_verifying_key: &'static zebra_crypto::Groth16VerifyingKey,
|
|
/// Sapling output verification key.
|
|
pub sapling_output_verifying_key: &'static zebra_crypto::Groth16VerifyingKey,
|
|
}
|
|
|
|
fn mainnet_pghr_verification_key() -> zebra_crypto::Pghr13VerifyingKey {
|
|
zebra_crypto::json::pghr13::decode(include_bytes!("../../res/sprout-verifying-key.json"))
|
|
.expect("verifying key json invalid")
|
|
.into()
|
|
}
|
|
|
|
impl ConsensusParams {
|
|
pub fn new(network: Network) -> Self {
|
|
match network {
|
|
Network::Mainnet | Network::Other(_) => ConsensusParams {
|
|
network: network,
|
|
bip16_time: 0,
|
|
bip34_height: 1,
|
|
bip65_height: 0,
|
|
bip66_height: 0,
|
|
rule_change_activation_threshold: 1916, // 95%
|
|
miner_confirmation_window: 2016,
|
|
csv_deployment: None,
|
|
|
|
overwinter_height: 347500,
|
|
sapling_height: 419200,
|
|
|
|
pow_averaging_window: 17,
|
|
pow_max_adjust_down: 32,
|
|
pow_max_adjust_up: 16,
|
|
pow_target_spacing: (2.5 * 60.0) as u32,
|
|
pow_allow_min_difficulty_after_height: None,
|
|
|
|
subsidy_slow_start_interval: 20_000,
|
|
subsidy_halving_interval: 840_000,
|
|
founders_addresses: vec![
|
|
"t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd".into(),
|
|
"t3cL9AucCajm3HXDhb5jBnJK2vapVoXsop3".into(),
|
|
"t3fqvkzrrNaMcamkQMwAyHRjfDdM2xQvDTR".into(),
|
|
"t3TgZ9ZT2CTSK44AnUPi6qeNaHa2eC7pUyF".into(),
|
|
"t3SpkcPQPfuRYHsP5vz3Pv86PgKo5m9KVmx".into(),
|
|
"t3Xt4oQMRPagwbpQqkgAViQgtST4VoSWR6S".into(),
|
|
"t3ayBkZ4w6kKXynwoHZFUSSgXRKtogTXNgb".into(),
|
|
"t3adJBQuaa21u7NxbR8YMzp3km3TbSZ4MGB".into(),
|
|
"t3K4aLYagSSBySdrfAGGeUd5H9z5Qvz88t2".into(),
|
|
"t3RYnsc5nhEvKiva3ZPhfRSk7eyh1CrA6Rk".into(),
|
|
"t3Ut4KUq2ZSMTPNE67pBU5LqYCi2q36KpXQ".into(),
|
|
"t3ZnCNAvgu6CSyHm1vWtrx3aiN98dSAGpnD".into(),
|
|
"t3fB9cB3eSYim64BS9xfwAHQUKLgQQroBDG".into(),
|
|
"t3cwZfKNNj2vXMAHBQeewm6pXhKFdhk18kD".into(),
|
|
"t3YcoujXfspWy7rbNUsGKxFEWZqNstGpeG4".into(),
|
|
"t3bLvCLigc6rbNrUTS5NwkgyVrZcZumTRa4".into(),
|
|
"t3VvHWa7r3oy67YtU4LZKGCWa2J6eGHvShi".into(),
|
|
"t3eF9X6X2dSo7MCvTjfZEzwWrVzquxRLNeY".into(),
|
|
"t3esCNwwmcyc8i9qQfyTbYhTqmYXZ9AwK3X".into(),
|
|
"t3M4jN7hYE2e27yLsuQPPjuVek81WV3VbBj".into(),
|
|
"t3gGWxdC67CYNoBbPjNvrrWLAWxPqZLxrVY".into(),
|
|
"t3LTWeoxeWPbmdkUD3NWBquk4WkazhFBmvU".into(),
|
|
"t3P5KKX97gXYFSaSjJPiruQEX84yF5z3Tjq".into(),
|
|
"t3f3T3nCWsEpzmD35VK62JgQfFig74dV8C9".into(),
|
|
"t3Rqonuzz7afkF7156ZA4vi4iimRSEn41hj".into(),
|
|
"t3fJZ5jYsyxDtvNrWBeoMbvJaQCj4JJgbgX".into(),
|
|
"t3Pnbg7XjP7FGPBUuz75H65aczphHgkpoJW".into(),
|
|
"t3WeKQDxCijL5X7rwFem1MTL9ZwVJkUFhpF".into(),
|
|
"t3Y9FNi26J7UtAUC4moaETLbMo8KS1Be6ME".into(),
|
|
"t3aNRLLsL2y8xcjPheZZwFy3Pcv7CsTwBec".into(),
|
|
"t3gQDEavk5VzAAHK8TrQu2BWDLxEiF1unBm".into(),
|
|
"t3Rbykhx1TUFrgXrmBYrAJe2STxRKFL7G9r".into(),
|
|
"t3aaW4aTdP7a8d1VTE1Bod2yhbeggHgMajR".into(),
|
|
"t3YEiAa6uEjXwFL2v5ztU1fn3yKgzMQqNyo".into(),
|
|
"t3g1yUUwt2PbmDvMDevTCPWUcbDatL2iQGP".into(),
|
|
"t3dPWnep6YqGPuY1CecgbeZrY9iUwH8Yd4z".into(),
|
|
"t3QRZXHDPh2hwU46iQs2776kRuuWfwFp4dV".into(),
|
|
"t3enhACRxi1ZD7e8ePomVGKn7wp7N9fFJ3r".into(),
|
|
"t3PkLgT71TnF112nSwBToXsD77yNbx2gJJY".into(),
|
|
"t3LQtHUDoe7ZhhvddRv4vnaoNAhCr2f4oFN".into(),
|
|
"t3fNcdBUbycvbCtsD2n9q3LuxG7jVPvFB8L".into(),
|
|
"t3dKojUU2EMjs28nHV84TvkVEUDu1M1FaEx".into(),
|
|
"t3aKH6NiWN1ofGd8c19rZiqgYpkJ3n679ME".into(),
|
|
"t3MEXDF9Wsi63KwpPuQdD6by32Mw2bNTbEa".into(),
|
|
"t3WDhPfik343yNmPTqtkZAoQZeqA83K7Y3f".into(),
|
|
"t3PSn5TbMMAEw7Eu36DYctFezRzpX1hzf3M".into(),
|
|
"t3R3Y5vnBLrEn8L6wFjPjBLnxSUQsKnmFpv".into(),
|
|
"t3Pcm737EsVkGTbhsu2NekKtJeG92mvYyoN".into(),
|
|
],
|
|
|
|
equihash_params: Some((200, 9)),
|
|
|
|
joinsplit_verification_key: mainnet_pghr_verification_key(),
|
|
joinsplit_groth16_verification_key: &JOINSPLIT_GROTH16_VK,
|
|
|
|
sapling_spend_verifying_key: &SAPLING_SPEND_VK,
|
|
sapling_output_verifying_key: &SAPLING_OUTPUT_VK,
|
|
},
|
|
Network::Testnet => ConsensusParams {
|
|
network: network,
|
|
bip16_time: 0,
|
|
bip34_height: 1,
|
|
bip65_height: 0,
|
|
bip66_height: 0,
|
|
rule_change_activation_threshold: 1512, // 75%
|
|
miner_confirmation_window: 2016,
|
|
csv_deployment: None,
|
|
|
|
overwinter_height: 207500,
|
|
sapling_height: 280000,
|
|
|
|
pow_averaging_window: 17,
|
|
pow_max_adjust_down: 32,
|
|
pow_max_adjust_up: 16,
|
|
pow_target_spacing: (2.5 * 60.0) as u32,
|
|
pow_allow_min_difficulty_after_height: Some(299187),
|
|
|
|
subsidy_slow_start_interval: 20_000,
|
|
subsidy_halving_interval: 840_000,
|
|
founders_addresses: vec![
|
|
"t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi".into(),
|
|
"t2N9PH9Wk9xjqYg9iin1Ua3aekJqfAtE543".into(),
|
|
"t2NGQjYMQhFndDHguvUw4wZdNdsssA6K7x2".into(),
|
|
"t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy".into(),
|
|
"t2BkYdVCHzvTJJUTx4yZB8qeegD8QsPx8bo".into(),
|
|
"t2J8q1xH1EuigJ52MfExyyjYtN3VgvshKDf".into(),
|
|
"t2Crq9mydTm37kZokC68HzT6yez3t2FBnFj".into(),
|
|
"t2EaMPUiQ1kthqcP5UEkF42CAFKJqXCkXC9".into(),
|
|
"t2F9dtQc63JDDyrhnfpzvVYTJcr57MkqA12".into(),
|
|
"t2LPirmnfYSZc481GgZBa6xUGcoovfytBnC".into(),
|
|
"t26xfxoSw2UV9Pe5o3C8V4YybQD4SESfxtp".into(),
|
|
"t2D3k4fNdErd66YxtvXEdft9xuLoKD7CcVo".into(),
|
|
"t2DWYBkxKNivdmsMiivNJzutaQGqmoRjRnL".into(),
|
|
"t2C3kFF9iQRxfc4B9zgbWo4dQLLqzqjpuGQ".into(),
|
|
"t2MnT5tzu9HSKcppRyUNwoTp8MUueuSGNaB".into(),
|
|
"t2AREsWdoW1F8EQYsScsjkgqobmgrkKeUkK".into(),
|
|
"t2Vf4wKcJ3ZFtLj4jezUUKkwYR92BLHn5UT".into(),
|
|
"t2K3fdViH6R5tRuXLphKyoYXyZhyWGghDNY".into(),
|
|
"t2VEn3KiKyHSGyzd3nDw6ESWtaCQHwuv9WC".into(),
|
|
"t2F8XouqdNMq6zzEvxQXHV1TjwZRHwRg8gC".into(),
|
|
"t2BS7Mrbaef3fA4xrmkvDisFVXVrRBnZ6Qj".into(),
|
|
"t2FuSwoLCdBVPwdZuYoHrEzxAb9qy4qjbnL".into(),
|
|
"t2SX3U8NtrT6gz5Db1AtQCSGjrpptr8JC6h".into(),
|
|
"t2V51gZNSoJ5kRL74bf9YTtbZuv8Fcqx2FH".into(),
|
|
"t2FyTsLjjdm4jeVwir4xzj7FAkUidbr1b4R".into(),
|
|
"t2EYbGLekmpqHyn8UBF6kqpahrYm7D6N1Le".into(),
|
|
"t2NQTrStZHtJECNFT3dUBLYA9AErxPCmkka".into(),
|
|
"t2GSWZZJzoesYxfPTWXkFn5UaxjiYxGBU2a".into(),
|
|
"t2RpffkzyLRevGM3w9aWdqMX6bd8uuAK3vn".into(),
|
|
"t2JzjoQqnuXtTGSN7k7yk5keURBGvYofh1d".into(),
|
|
"t2AEefc72ieTnsXKmgK2bZNckiwvZe3oPNL".into(),
|
|
"t2NNs3ZGZFsNj2wvmVd8BSwSfvETgiLrD8J".into(),
|
|
"t2ECCQPVcxUCSSQopdNquguEPE14HsVfcUn".into(),
|
|
"t2JabDUkG8TaqVKYfqDJ3rqkVdHKp6hwXvG".into(),
|
|
"t2FGzW5Zdc8Cy98ZKmRygsVGi6oKcmYir9n".into(),
|
|
"t2DUD8a21FtEFn42oVLp5NGbogY13uyjy9t".into(),
|
|
"t2UjVSd3zheHPgAkuX8WQW2CiC9xHQ8EvWp".into(),
|
|
"t2TBUAhELyHUn8i6SXYsXz5Lmy7kDzA1uT5".into(),
|
|
"t2Tz3uCyhP6eizUWDc3bGH7XUC9GQsEyQNc".into(),
|
|
"t2NysJSZtLwMLWEJ6MH3BsxRh6h27mNcsSy".into(),
|
|
"t2KXJVVyyrjVxxSeazbY9ksGyft4qsXUNm9".into(),
|
|
"t2J9YYtH31cveiLZzjaE4AcuwVho6qjTNzp".into(),
|
|
"t2QgvW4sP9zaGpPMH1GRzy7cpydmuRfB4AZ".into(),
|
|
"t2NDTJP9MosKpyFPHJmfjc5pGCvAU58XGa4".into(),
|
|
"t29pHDBWq7qN4EjwSEHg8wEqYe9pkmVrtRP".into(),
|
|
"t2Ez9KM8VJLuArcxuEkNRAkhNvidKkzXcjJ".into(),
|
|
"t2D5y7J5fpXajLbGrMBQkFg2mFN8fo3n8cX".into(),
|
|
"t2UV2wr1PTaUiybpkV3FdSdGxUJeZdZztyt".into(),
|
|
],
|
|
|
|
equihash_params: Some((200, 9)),
|
|
|
|
joinsplit_verification_key: mainnet_pghr_verification_key(),
|
|
joinsplit_groth16_verification_key: &JOINSPLIT_GROTH16_VK,
|
|
|
|
sapling_spend_verifying_key: &SAPLING_SPEND_VK,
|
|
sapling_output_verifying_key: &SAPLING_OUTPUT_VK,
|
|
},
|
|
Network::Regtest => ConsensusParams {
|
|
network: network,
|
|
bip16_time: 0,
|
|
bip34_height: 100000000,
|
|
bip65_height: 0,
|
|
bip66_height: 0,
|
|
rule_change_activation_threshold: 108, // 75%
|
|
miner_confirmation_window: 144,
|
|
csv_deployment: None,
|
|
|
|
overwinter_height: ::std::u32::MAX,
|
|
sapling_height: ::std::u32::MAX,
|
|
|
|
pow_averaging_window: 17,
|
|
pow_max_adjust_down: 0,
|
|
pow_max_adjust_up: 0,
|
|
pow_target_spacing: (2.5 * 60.0) as u32,
|
|
pow_allow_min_difficulty_after_height: Some(0),
|
|
|
|
subsidy_slow_start_interval: 0,
|
|
subsidy_halving_interval: 150,
|
|
founders_addresses: vec!["t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg".into()],
|
|
|
|
equihash_params: Some((200, 9)),
|
|
|
|
joinsplit_verification_key: mainnet_pghr_verification_key(),
|
|
joinsplit_groth16_verification_key: &JOINSPLIT_GROTH16_VK,
|
|
|
|
sapling_spend_verifying_key: &SAPLING_SPEND_VK,
|
|
sapling_output_verifying_key: &SAPLING_OUTPUT_VK,
|
|
},
|
|
Network::Unitest => ConsensusParams {
|
|
network: network,
|
|
bip16_time: 0,
|
|
bip34_height: 100000000,
|
|
bip65_height: 0,
|
|
bip66_height: 0,
|
|
rule_change_activation_threshold: 108, // 75%
|
|
miner_confirmation_window: 144,
|
|
csv_deployment: None,
|
|
|
|
overwinter_height: ::std::u32::MAX,
|
|
sapling_height: ::std::u32::MAX,
|
|
|
|
pow_averaging_window: 17,
|
|
pow_max_adjust_down: 0,
|
|
pow_max_adjust_up: 0,
|
|
pow_target_spacing: (2.5 * 60.0) as u32,
|
|
pow_allow_min_difficulty_after_height: Some(0),
|
|
|
|
subsidy_slow_start_interval: 0,
|
|
subsidy_halving_interval: 150,
|
|
founders_addresses: vec!["t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg".into()],
|
|
|
|
equihash_params: None,
|
|
|
|
joinsplit_verification_key: mainnet_pghr_verification_key(),
|
|
joinsplit_groth16_verification_key: &JOINSPLIT_GROTH16_VK,
|
|
|
|
sapling_spend_verifying_key: &SAPLING_SPEND_VK,
|
|
sapling_output_verifying_key: &SAPLING_OUTPUT_VK,
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn magic(&self) -> Magic {
|
|
self.network.magic()
|
|
}
|
|
|
|
pub fn averaging_window_timespan(&self) -> u32 {
|
|
self.pow_averaging_window * self.pow_target_spacing
|
|
}
|
|
|
|
pub fn min_actual_timespan(&self) -> u32 {
|
|
(self.averaging_window_timespan() * (100 - self.pow_max_adjust_up)) / 100
|
|
}
|
|
|
|
pub fn max_actual_timespan(&self) -> u32 {
|
|
(self.averaging_window_timespan() * (100 + self.pow_max_adjust_down)) / 100
|
|
}
|
|
|
|
pub fn min_block_version(&self) -> u32 {
|
|
4
|
|
}
|
|
|
|
pub fn max_block_size(&self) -> usize {
|
|
2_000_000
|
|
}
|
|
|
|
pub fn max_block_sigops(&self) -> usize {
|
|
20_000
|
|
}
|
|
|
|
pub fn max_transaction_value(&self) -> i64 {
|
|
21_000_000 * 100_000_000 // No amount larger than this (in satoshi) is valid
|
|
}
|
|
|
|
pub fn absolute_max_transaction_size(&self) -> usize {
|
|
2_000_000
|
|
}
|
|
|
|
pub fn max_transaction_size(&self, height: u32) -> usize {
|
|
if height >= self.sapling_height {
|
|
2_000_000
|
|
} else {
|
|
100_000
|
|
}
|
|
}
|
|
|
|
pub fn transaction_expiry_height_threshold(&self) -> u32 {
|
|
500_000_000
|
|
}
|
|
|
|
pub fn is_overwinter_active(&self, height: u32) -> bool {
|
|
height >= self.overwinter_height
|
|
}
|
|
|
|
pub fn is_sapling_active(&self, height: u32) -> bool {
|
|
height >= self.sapling_height
|
|
}
|
|
|
|
/// Block subsidy (total block reward).
|
|
pub fn block_reward(&self, height: u32) -> u64 {
|
|
let mut reward = 1_250_000_000u64;
|
|
if height < self.subsidy_slow_start_interval / 2 {
|
|
reward /= self.subsidy_slow_start_interval as u64;
|
|
reward *= height as u64;
|
|
} else if height < self.subsidy_slow_start_interval {
|
|
reward /= self.subsidy_slow_start_interval as u64;
|
|
reward *= height as u64 + 1;
|
|
} else {
|
|
let halvings =
|
|
(height - self.subsidy_slow_start_interval / 2) / self.subsidy_halving_interval;
|
|
if halvings >= 64 {
|
|
return 0;
|
|
}
|
|
|
|
reward >>= halvings as u64;
|
|
}
|
|
|
|
reward
|
|
}
|
|
|
|
/// Block reward (goes to miner) at given height.
|
|
pub fn miner_reward(&self, height: u32) -> u64 {
|
|
let mut miner_reward = self.block_reward(height);
|
|
if self.founder_address(height).is_some() {
|
|
miner_reward -= self.founder_reward(height);
|
|
}
|
|
miner_reward
|
|
}
|
|
|
|
/// Founders reward (goes to founders) at given height.
|
|
pub fn founder_reward(&self, height: u32) -> u64 {
|
|
self.block_reward(height) / 5
|
|
}
|
|
|
|
/// Address (transparent) where founders reward goes at given height.
|
|
pub fn founder_address(&self, height: u32) -> Option<Address> {
|
|
let last_founder_reward_block_height =
|
|
self.subsidy_halving_interval + self.subsidy_slow_start_interval / 2 - 1;
|
|
if height == 0 || height > last_founder_reward_block_height {
|
|
return None;
|
|
}
|
|
|
|
let founders_len = self.founders_addresses.len() as u32;
|
|
let address_change_interval =
|
|
(last_founder_reward_block_height + founders_len) / founders_len;
|
|
let address_index = height / address_change_interval;
|
|
Some(self.founders_addresses[address_index as usize].clone())
|
|
}
|
|
|
|
pub fn consensus_branch_id(&self, height: u32) -> u32 {
|
|
// sapling upgrade
|
|
if height >= self.sapling_height {
|
|
return 0x76b809bb;
|
|
}
|
|
|
|
// overwinter upgrade
|
|
if height >= self.overwinter_height {
|
|
return 0x5ba81b19;
|
|
}
|
|
|
|
// sprout
|
|
0
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn block_reward() {
|
|
let consensus = ConsensusParams::new(Network::Mainnet);
|
|
assert_eq!(consensus.block_reward(1), 62_500);
|
|
assert_eq!(consensus.block_reward(10_000), 625_062_500);
|
|
assert_eq!(consensus.block_reward(20_000), 1_250_000_000);
|
|
assert_eq!(consensus.block_reward(1_000_000), 625_000_000);
|
|
assert_eq!(consensus.block_reward(2_000_000), 312_500_000);
|
|
assert_eq!(consensus.block_reward(3_000_000), 156_250_000);
|
|
assert_eq!(consensus.block_reward(4_000_000), 78_125_000);
|
|
assert_eq!(consensus.block_reward(20_000_000), 149);
|
|
assert_eq!(consensus.block_reward(30_000_000), 0);
|
|
}
|
|
}
|