Moves `subsidy.rs` to `zebra-chain`, refactors funding streams into structs, splits them into pre/post NU6 funding streams, and adds them as a field on `testnet::Parameters`
This commit is contained in:
parent
502b174c97
commit
930c488bf7
|
@ -22,7 +22,7 @@ mod transaction;
|
|||
pub mod arbitrary;
|
||||
|
||||
pub use genesis::*;
|
||||
pub use network::{magic::Magic, testnet, Network, NetworkKind};
|
||||
pub use network::{magic::Magic, subsidy, testnet, Network, NetworkKind};
|
||||
pub use network_upgrade::*;
|
||||
pub use transaction::*;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub mod magic;
|
||||
pub mod subsidy;
|
||||
pub mod testnet;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
//! Constants for Block Subsidy and Funding Streams
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use zebra_chain::{
|
||||
use crate::{
|
||||
amount::COIN,
|
||||
block::{Height, HeightDiff},
|
||||
parameters::{Network, NetworkKind, NetworkUpgrade},
|
||||
parameters::{Network, NetworkUpgrade},
|
||||
};
|
||||
|
||||
/// The largest block subsidy, used before the first halving.
|
||||
|
@ -60,76 +58,182 @@ pub const FUNDING_STREAM_RECEIVER_DENOMINATOR: u64 = 100;
|
|||
/// [ZIP-214]: https://zips.z.cash/zip-0214
|
||||
pub const FUNDING_STREAM_SPECIFICATION: &str = "https://zips.z.cash/zip-0214";
|
||||
|
||||
// TODO: use a struct for the info for each funding stream, like zcashd does:
|
||||
// https://github.com/zcash/zcash/blob/3f09cfa00a3c90336580a127e0096d99e25a38d6/src/consensus/funding.cpp#L13-L32
|
||||
/// Funding stream recipients and height ranges.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct FundingStreams {
|
||||
recipients: Vec<FundingStreamRecipient>,
|
||||
height_range: std::ops::Range<Height>,
|
||||
}
|
||||
|
||||
impl FundingStreams {
|
||||
/// Returns height range where these [`FundingStreams`] should apply.
|
||||
pub fn height_range(&self) -> &std::ops::Range<Height> {
|
||||
&self.height_range
|
||||
}
|
||||
|
||||
/// Returns recipients of these [`FundingStreams`].
|
||||
pub fn recipients(&self) -> &[FundingStreamRecipient] {
|
||||
&self.recipients
|
||||
}
|
||||
|
||||
/// Returns a recipient with the provided receiver.
|
||||
pub fn recipient_by_receiver(
|
||||
&self,
|
||||
receiver: FundingStreamReceiver,
|
||||
) -> Option<&FundingStreamRecipient> {
|
||||
self.recipients
|
||||
.iter()
|
||||
.find(|recipient| recipient.receiver() == receiver)
|
||||
}
|
||||
}
|
||||
|
||||
/// A funding stream recipient as specified in [protocol specification §7.10.1][7.10.1]
|
||||
///
|
||||
/// [7.10.1]: https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct FundingStreamRecipient {
|
||||
receiver: FundingStreamReceiver,
|
||||
name: String,
|
||||
numerator: u64,
|
||||
addresses: Vec<String>,
|
||||
}
|
||||
|
||||
impl FundingStreamRecipient {
|
||||
/// Creates a new [`FundingStreamRecipient`].
|
||||
pub fn new(
|
||||
receiver: FundingStreamReceiver,
|
||||
name: impl Into<String>,
|
||||
numerator: u64,
|
||||
addresses: Vec<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
receiver,
|
||||
name: name.into(),
|
||||
numerator,
|
||||
addresses,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the receiver of this funding stream.
|
||||
pub fn receiver(&self) -> FundingStreamReceiver {
|
||||
self.receiver
|
||||
}
|
||||
|
||||
/// Returns the name of this funding stream.
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// Returns the numerator for this funding stream.
|
||||
pub fn numerator(&self) -> u64 {
|
||||
self.numerator
|
||||
}
|
||||
|
||||
/// Returns the receiver of this funding stream.
|
||||
pub fn addresses(&self) -> &[String] {
|
||||
&self.addresses
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// The name for each funding stream receiver, as described in [ZIP-1014] and [`zcashd`].
|
||||
///
|
||||
/// [ZIP-1014]: https://zips.z.cash/zip-1014#abstract
|
||||
/// [`zcashd`]: https://github.com/zcash/zcash/blob/3f09cfa00a3c90336580a127e0096d99e25a38d6/src/consensus/funding.cpp#L13-L32
|
||||
pub static ref FUNDING_STREAM_NAMES: HashMap<FundingStreamReceiver, &'static str> = {
|
||||
let mut hash_map = HashMap::new();
|
||||
hash_map.insert(FundingStreamReceiver::Ecc, "Electric Coin Company");
|
||||
hash_map.insert(FundingStreamReceiver::ZcashFoundation, "Zcash Foundation");
|
||||
hash_map.insert(FundingStreamReceiver::MajorGrants, "Major Grants");
|
||||
hash_map
|
||||
/// The pre-NU6 funding streams for Mainnet
|
||||
pub static ref PRE_NU6_FUNDING_STREAMS_MAINNET: FundingStreams = FundingStreams {
|
||||
recipients: vec![
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::Ecc,
|
||||
"Electric Coin Company",
|
||||
7,
|
||||
FUNDING_STREAM_ECC_ADDRESSES_MAINNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::ZcashFoundation,
|
||||
"Zcash Foundation",
|
||||
5,
|
||||
FUNDING_STREAM_ZF_ADDRESSES_MAINNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::MajorGrants,
|
||||
"Major Grants",
|
||||
8,
|
||||
FUNDING_STREAM_MG_ADDRESSES_MAINNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
],
|
||||
height_range: Height(1_046_400)..Height(2_726_400),
|
||||
};
|
||||
|
||||
|
||||
/// The numerator for each funding stream receiver category
|
||||
/// as described in [protocol specification §7.10.1][7.10.1].
|
||||
///
|
||||
/// [7.10.1]: https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams
|
||||
pub static ref FUNDING_STREAM_RECEIVER_NUMERATORS: HashMap<FundingStreamReceiver, u64> = {
|
||||
let mut hash_map = HashMap::new();
|
||||
hash_map.insert(FundingStreamReceiver::Ecc, 7);
|
||||
hash_map.insert(FundingStreamReceiver::ZcashFoundation, 5);
|
||||
hash_map.insert(FundingStreamReceiver::MajorGrants, 8);
|
||||
hash_map
|
||||
/// The pre-NU6 funding streams for Testnet
|
||||
pub static ref PRE_NU6_FUNDING_STREAMS_TESTNET: FundingStreams = FundingStreams {
|
||||
recipients: vec![
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::Ecc,
|
||||
"Electric Coin Company",
|
||||
7,
|
||||
FUNDING_STREAM_ECC_ADDRESSES_TESTNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::ZcashFoundation,
|
||||
"Zcash Foundation",
|
||||
5,
|
||||
FUNDING_STREAM_ZF_ADDRESSES_TESTNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::MajorGrants,
|
||||
"Major Grants",
|
||||
8,
|
||||
FUNDING_STREAM_MG_ADDRESSES_TESTNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
],
|
||||
height_range: Height(1_028_500)..Height(2_796_000),
|
||||
};
|
||||
|
||||
/// Start and end Heights for funding streams
|
||||
/// as described in [protocol specification §7.10.1][7.10.1].
|
||||
///
|
||||
/// [7.10.1]: https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams
|
||||
// TODO: Move the value here to a field on `testnet::Parameters` (#8367)
|
||||
pub static ref FUNDING_STREAM_HEIGHT_RANGES: HashMap<NetworkKind, std::ops::Range<Height>> = {
|
||||
let mut hash_map = HashMap::new();
|
||||
hash_map.insert(NetworkKind::Mainnet, Height(1_046_400)..Height(2_726_400));
|
||||
hash_map.insert(NetworkKind::Testnet, Height(1_028_500)..Height(2_796_000));
|
||||
hash_map.insert(NetworkKind::Regtest, Height(1_028_500)..Height(2_796_000));
|
||||
hash_map
|
||||
/// The post-NU6 funding streams for Mainnet
|
||||
pub static ref POST_NU6_FUNDING_STREAMS_MAINNET: FundingStreams = FundingStreams {
|
||||
recipients: vec![
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::MajorGrants,
|
||||
"Major Grants",
|
||||
8,
|
||||
FUNDING_STREAM_MG_ADDRESSES_MAINNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
],
|
||||
height_range: Height(2_726_400)..Height(3_146_400),
|
||||
};
|
||||
|
||||
/// Convenient storage for all addresses, for all receivers and networks
|
||||
pub static ref FUNDING_STREAM_ADDRESSES: HashMap<NetworkKind, HashMap<FundingStreamReceiver, Vec<String>>> = {
|
||||
let mut addresses_by_network = HashMap::with_capacity(2);
|
||||
|
||||
// Mainnet addresses
|
||||
let mut mainnet_addresses = HashMap::with_capacity(3);
|
||||
mainnet_addresses.insert(FundingStreamReceiver::Ecc, FUNDING_STREAM_ECC_ADDRESSES_MAINNET.iter().map(|a| a.to_string()).collect());
|
||||
mainnet_addresses.insert(FundingStreamReceiver::ZcashFoundation, FUNDING_STREAM_ZF_ADDRESSES_MAINNET.iter().map(|a| a.to_string()).collect());
|
||||
mainnet_addresses.insert(FundingStreamReceiver::MajorGrants, FUNDING_STREAM_MG_ADDRESSES_MAINNET.iter().map(|a| a.to_string()).collect());
|
||||
addresses_by_network.insert(NetworkKind::Mainnet, mainnet_addresses);
|
||||
|
||||
// Testnet addresses
|
||||
let mut testnet_addresses = HashMap::with_capacity(3);
|
||||
testnet_addresses.insert(FundingStreamReceiver::Ecc, FUNDING_STREAM_ECC_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
|
||||
testnet_addresses.insert(FundingStreamReceiver::ZcashFoundation, FUNDING_STREAM_ZF_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
|
||||
testnet_addresses.insert(FundingStreamReceiver::MajorGrants, FUNDING_STREAM_MG_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
|
||||
addresses_by_network.insert(NetworkKind::Testnet, testnet_addresses);
|
||||
|
||||
|
||||
// Regtest addresses
|
||||
// TODO: Move the value here to a field on `testnet::Parameters` (#8367)
|
||||
// There are no funding stream addresses on Regtest in zcashd, zebrad should do the same for compatibility.
|
||||
let mut regtest_addresses = HashMap::with_capacity(3);
|
||||
regtest_addresses.insert(FundingStreamReceiver::Ecc, FUNDING_STREAM_ECC_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
|
||||
regtest_addresses.insert(FundingStreamReceiver::ZcashFoundation, FUNDING_STREAM_ZF_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
|
||||
regtest_addresses.insert(FundingStreamReceiver::MajorGrants, FUNDING_STREAM_MG_ADDRESSES_TESTNET.iter().map(|a| a.to_string()).collect());
|
||||
addresses_by_network.insert(NetworkKind::Testnet, regtest_addresses);
|
||||
|
||||
addresses_by_network
|
||||
/// The post-NU6 funding streams for Testnet
|
||||
pub static ref POST_NU6_FUNDING_STREAMS_TESTNET: FundingStreams = FundingStreams {
|
||||
recipients: vec![
|
||||
FundingStreamRecipient::new(
|
||||
FundingStreamReceiver::MajorGrants,
|
||||
"Major Grants",
|
||||
8,
|
||||
FUNDING_STREAM_MG_ADDRESSES_TESTNET
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
),
|
||||
],
|
||||
height_range: Height(2_942_000)..Height(3_362_000),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -200,9 +304,6 @@ pub const FUNDING_STREAM_ECC_ADDRESSES_MAINNET: [&str; FUNDING_STREAMS_NUM_ADDRE
|
|||
|
||||
/// Functionality specific to block subsidy-related consensus rules
|
||||
pub trait ParameterSubsidy {
|
||||
/// Number of addresses for each funding stream in the Network.
|
||||
/// [7.10]: <https://zips.z.cash/protocol/protocol.pdf#fundingstreams>
|
||||
fn num_funding_streams(&self) -> usize;
|
||||
/// Returns the minimum height after the first halving
|
||||
/// as described in [protocol specification §7.10][7.10]
|
||||
///
|
||||
|
@ -212,14 +313,6 @@ pub trait ParameterSubsidy {
|
|||
|
||||
/// Network methods related to Block Subsidy and Funding Streams
|
||||
impl ParameterSubsidy for Network {
|
||||
fn num_funding_streams(&self) -> usize {
|
||||
match self {
|
||||
Network::Mainnet => FUNDING_STREAMS_NUM_ADDRESSES_MAINNET,
|
||||
// TODO: Check what zcashd does here, consider adding a field to `NetworkParamters` to make this configurable.
|
||||
Network::Testnet(_params) => FUNDING_STREAMS_NUM_ADDRESSES_TESTNET,
|
||||
}
|
||||
}
|
||||
|
||||
fn height_for_first_halving(&self) -> Height {
|
||||
// First halving on Mainnet is at Canopy
|
||||
// while in Testnet is at block constant height of `1_116_000`
|
|
@ -11,7 +11,13 @@ use crate::{
|
|||
work::difficulty::{ExpandedDifficulty, U256},
|
||||
};
|
||||
|
||||
use super::magic::Magic;
|
||||
use super::{
|
||||
magic::Magic,
|
||||
subsidy::{
|
||||
FundingStreams, POST_NU6_FUNDING_STREAMS_MAINNET, POST_NU6_FUNDING_STREAMS_TESTNET,
|
||||
PRE_NU6_FUNDING_STREAMS_MAINNET, PRE_NU6_FUNDING_STREAMS_TESTNET,
|
||||
},
|
||||
};
|
||||
|
||||
/// The Regtest NU5 activation height in tests
|
||||
// TODO: Serialize testnet parameters in Config then remove this and use a configured NU5 activation height.
|
||||
|
@ -79,6 +85,10 @@ pub struct ParametersBuilder {
|
|||
activation_heights: BTreeMap<Height, NetworkUpgrade>,
|
||||
/// Slow start interval for this network
|
||||
slow_start_interval: Height,
|
||||
/// Pre-NU6 funding streams for this network
|
||||
pre_nu6_funding_streams: FundingStreams,
|
||||
/// Post-NU6 funding streams for this network
|
||||
post_nu6_funding_streams: FundingStreams,
|
||||
/// Target difficulty limit for this network
|
||||
target_difficulty_limit: ExpandedDifficulty,
|
||||
/// A flag for disabling proof-of-work checks when Zebra is validating blocks
|
||||
|
@ -113,6 +123,8 @@ impl Default for ParametersBuilder {
|
|||
.to_expanded()
|
||||
.expect("difficulty limits are valid expanded values"),
|
||||
disable_pow: false,
|
||||
pre_nu6_funding_streams: PRE_NU6_FUNDING_STREAMS_TESTNET.clone(),
|
||||
post_nu6_funding_streams: POST_NU6_FUNDING_STREAMS_TESTNET.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,6 +275,8 @@ impl ParametersBuilder {
|
|||
genesis_hash,
|
||||
activation_heights,
|
||||
slow_start_interval,
|
||||
pre_nu6_funding_streams,
|
||||
post_nu6_funding_streams,
|
||||
target_difficulty_limit,
|
||||
disable_pow,
|
||||
} = self;
|
||||
|
@ -273,6 +287,8 @@ impl ParametersBuilder {
|
|||
activation_heights,
|
||||
slow_start_interval,
|
||||
slow_start_shift: Height(slow_start_interval.0 / 2),
|
||||
pre_nu6_funding_streams,
|
||||
post_nu6_funding_streams,
|
||||
target_difficulty_limit,
|
||||
disable_pow,
|
||||
}
|
||||
|
@ -291,6 +307,8 @@ impl ParametersBuilder {
|
|||
genesis_hash,
|
||||
activation_heights,
|
||||
slow_start_interval,
|
||||
pre_nu6_funding_streams,
|
||||
post_nu6_funding_streams,
|
||||
target_difficulty_limit,
|
||||
disable_pow,
|
||||
} = Self::default();
|
||||
|
@ -299,6 +317,8 @@ impl ParametersBuilder {
|
|||
&& self.network_magic == network_magic
|
||||
&& self.genesis_hash == genesis_hash
|
||||
&& self.slow_start_interval == slow_start_interval
|
||||
&& self.pre_nu6_funding_streams == pre_nu6_funding_streams
|
||||
&& self.post_nu6_funding_streams == post_nu6_funding_streams
|
||||
&& self.target_difficulty_limit == target_difficulty_limit
|
||||
&& self.disable_pow == disable_pow
|
||||
}
|
||||
|
@ -323,6 +343,10 @@ pub struct Parameters {
|
|||
slow_start_interval: Height,
|
||||
/// Slow start shift for this network, always half the slow start interval
|
||||
slow_start_shift: Height,
|
||||
/// Pre-NU6 funding streams for this network
|
||||
pre_nu6_funding_streams: FundingStreams,
|
||||
/// Post-NU6 funding streams for this network
|
||||
post_nu6_funding_streams: FundingStreams,
|
||||
/// Target difficulty limit for this network
|
||||
target_difficulty_limit: ExpandedDifficulty,
|
||||
/// A flag for disabling proof-of-work checks when Zebra is validating blocks
|
||||
|
@ -396,6 +420,8 @@ impl Parameters {
|
|||
activation_heights: _,
|
||||
slow_start_interval,
|
||||
slow_start_shift,
|
||||
pre_nu6_funding_streams,
|
||||
post_nu6_funding_streams,
|
||||
target_difficulty_limit,
|
||||
disable_pow,
|
||||
} = Self::new_regtest(None, None);
|
||||
|
@ -404,6 +430,8 @@ impl Parameters {
|
|||
&& self.genesis_hash == genesis_hash
|
||||
&& self.slow_start_interval == slow_start_interval
|
||||
&& self.slow_start_shift == slow_start_shift
|
||||
&& self.pre_nu6_funding_streams == pre_nu6_funding_streams
|
||||
&& self.post_nu6_funding_streams == post_nu6_funding_streams
|
||||
&& self.target_difficulty_limit == target_difficulty_limit
|
||||
&& self.disable_pow == disable_pow
|
||||
}
|
||||
|
@ -438,6 +466,16 @@ impl Parameters {
|
|||
self.slow_start_shift
|
||||
}
|
||||
|
||||
/// Returns pre-NU6 funding streams for this network
|
||||
pub fn pre_nu6_funding_streams(&self) -> &FundingStreams {
|
||||
&self.pre_nu6_funding_streams
|
||||
}
|
||||
|
||||
/// Returns post-NU6 funding streams for this network
|
||||
pub fn post_nu6_funding_streams(&self) -> &FundingStreams {
|
||||
&self.post_nu6_funding_streams
|
||||
}
|
||||
|
||||
/// Returns the target difficulty limit for this network
|
||||
pub fn target_difficulty_limit(&self) -> ExpandedDifficulty {
|
||||
self.target_difficulty_limit
|
||||
|
@ -476,4 +514,31 @@ impl Network {
|
|||
SLOW_START_SHIFT
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns pre-NU6 funding streams for this network
|
||||
pub fn pre_nu6_funding_streams(&self) -> &FundingStreams {
|
||||
if let Self::Testnet(params) = self {
|
||||
params.pre_nu6_funding_streams()
|
||||
} else {
|
||||
&PRE_NU6_FUNDING_STREAMS_MAINNET
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns post-NU6 funding streams for this network
|
||||
pub fn post_nu6_funding_streams(&self) -> &FundingStreams {
|
||||
if let Self::Testnet(params) = self {
|
||||
params.pre_nu6_funding_streams()
|
||||
} else {
|
||||
&POST_NU6_FUNDING_STREAMS_MAINNET
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns funding streams for this network at the provided height
|
||||
pub fn funding_streams(&self, height: Height) -> &FundingStreams {
|
||||
if NetworkUpgrade::current(self, height) < NetworkUpgrade::Nu6 {
|
||||
self.pre_nu6_funding_streams()
|
||||
} else {
|
||||
self.post_nu6_funding_streams()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ use std::{collections::HashMap, str::FromStr};
|
|||
use zebra_chain::{
|
||||
amount::{Amount, Error, NonNegative},
|
||||
block::Height,
|
||||
parameters::{Network, NetworkUpgrade::*},
|
||||
parameters::{subsidy::*, Network, NetworkUpgrade::*},
|
||||
transaction::Transaction,
|
||||
transparent::{self, Script},
|
||||
};
|
||||
|
||||
use crate::{block::subsidy::general::block_subsidy, parameters::subsidy::*};
|
||||
use crate::block::subsidy::general::block_subsidy;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -29,19 +29,19 @@ pub fn funding_stream_values(
|
|||
let mut results = HashMap::new();
|
||||
|
||||
if height >= canopy_height {
|
||||
let range = FUNDING_STREAM_HEIGHT_RANGES.get(&network.kind()).unwrap();
|
||||
if range.contains(&height) {
|
||||
let funding_streams = network.funding_streams(height);
|
||||
if funding_streams.height_range().contains(&height) {
|
||||
let block_subsidy = block_subsidy(height, network)?;
|
||||
for (&receiver, &numerator) in FUNDING_STREAM_RECEIVER_NUMERATORS.iter() {
|
||||
for recipient in funding_streams.recipients() {
|
||||
// - Spec equation: `fs.value = floor(block_subsidy(height)*(fs.numerator/fs.denominator))`:
|
||||
// https://zips.z.cash/protocol/protocol.pdf#subsidies
|
||||
// - In Rust, "integer division rounds towards zero":
|
||||
// https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
|
||||
// This is the same as `floor()`, because these numbers are all positive.
|
||||
let amount_value =
|
||||
((block_subsidy * numerator)? / FUNDING_STREAM_RECEIVER_DENOMINATOR)?;
|
||||
let amount_value = ((block_subsidy * recipient.numerator())?
|
||||
/ FUNDING_STREAM_RECEIVER_DENOMINATOR)?;
|
||||
|
||||
results.insert(receiver, amount_value);
|
||||
results.insert(recipient.receiver(), amount_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,20 +77,23 @@ fn funding_stream_address_period(height: Height, network: &Network) -> u32 {
|
|||
///
|
||||
/// [7.10]: https://zips.z.cash/protocol/protocol.pdf#fundingstreams
|
||||
fn funding_stream_address_index(height: Height, network: &Network) -> usize {
|
||||
let num_addresses = network.num_funding_streams();
|
||||
let funding_streams = network.funding_streams(height);
|
||||
|
||||
let index = 1u32
|
||||
.checked_add(funding_stream_address_period(height, network))
|
||||
.expect("no overflow should happen in this sum")
|
||||
.checked_sub(funding_stream_address_period(
|
||||
FUNDING_STREAM_HEIGHT_RANGES
|
||||
.get(&network.kind())
|
||||
.unwrap()
|
||||
.start,
|
||||
funding_streams.height_range().start,
|
||||
network,
|
||||
))
|
||||
.expect("no overflow should happen in this sub") as usize;
|
||||
|
||||
let num_addresses = funding_streams
|
||||
.recipients()
|
||||
.first()
|
||||
.map(|recipient| recipient.addresses().len())
|
||||
.unwrap_or_default();
|
||||
|
||||
assert!(index > 0 && index <= num_addresses);
|
||||
// spec formula will output an index starting at 1 but
|
||||
// Zebra indices for addresses start at zero, return converted.
|
||||
|
@ -107,21 +110,31 @@ pub fn funding_stream_address(
|
|||
receiver: FundingStreamReceiver,
|
||||
) -> transparent::Address {
|
||||
let index = funding_stream_address_index(height, network);
|
||||
let address = &FUNDING_STREAM_ADDRESSES
|
||||
.get(&network.kind())
|
||||
.expect("there is always another hash map as value for a given valid network")
|
||||
.get(&receiver)
|
||||
.expect("in the inner hash map there is always a vector of strings with addresses")[index];
|
||||
let funding_streams = network.funding_streams(height);
|
||||
let address = &funding_streams
|
||||
.recipient_by_receiver(receiver)
|
||||
// TODO: Change return type to option and return None here instead of panicking
|
||||
.unwrap()
|
||||
.addresses()
|
||||
.get(index)
|
||||
// TODO: Change return type to option and return None here instead of panicking
|
||||
.unwrap();
|
||||
transparent::Address::from_str(address).expect("address should deserialize")
|
||||
}
|
||||
|
||||
/// Return a human-readable name and a specification URL for the funding stream `receiver`.
|
||||
pub fn funding_stream_recipient_info(
|
||||
network: &Network,
|
||||
height: Height,
|
||||
receiver: FundingStreamReceiver,
|
||||
) -> (&'static str, &'static str) {
|
||||
let name = FUNDING_STREAM_NAMES
|
||||
.get(&receiver)
|
||||
.expect("all funding streams have a name");
|
||||
) -> (String, &'static str) {
|
||||
let name = network
|
||||
.funding_streams(height)
|
||||
.recipient_by_receiver(receiver)
|
||||
// TODO: Replace with optional return type
|
||||
.unwrap()
|
||||
.name()
|
||||
.to_string();
|
||||
|
||||
(name, FUNDING_STREAM_SPECIFICATION)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Tests for funding streams.
|
||||
|
||||
use color_eyre::Report;
|
||||
use zebra_chain::parameters::subsidy::FundingStreamReceiver;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -44,7 +45,8 @@ fn test_funding_stream_values() -> Result<(), Report> {
|
|||
);
|
||||
|
||||
// funding stream period is ending
|
||||
let range = FUNDING_STREAM_HEIGHT_RANGES.get(&network.kind()).unwrap();
|
||||
let funding_streams = network.pre_nu6_funding_streams();
|
||||
let range = funding_streams.height_range();
|
||||
let end = range.end;
|
||||
let last = end - 1;
|
||||
|
||||
|
@ -61,15 +63,16 @@ fn test_funding_stream_values() -> Result<(), Report> {
|
|||
#[test]
|
||||
fn test_funding_stream_addresses() -> Result<(), Report> {
|
||||
let _init_guard = zebra_test::init();
|
||||
|
||||
for (network, receivers) in FUNDING_STREAM_ADDRESSES.iter() {
|
||||
for (receiver, addresses) in receivers {
|
||||
for address in addresses {
|
||||
for network in Network::iter() {
|
||||
for funding_stream_recipient in network.pre_nu6_funding_streams().recipients() {
|
||||
let receiver = funding_stream_recipient.receiver();
|
||||
for address in funding_stream_recipient.addresses() {
|
||||
let address =
|
||||
transparent::Address::from_str(address).expect("address should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
&address.network_kind(),
|
||||
network,
|
||||
address.network_kind(),
|
||||
network.kind(),
|
||||
"incorrect network for {receiver:?} funding stream address constant: {address}",
|
||||
);
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@ use std::collections::HashSet;
|
|||
use zebra_chain::{
|
||||
amount::{Amount, Error, NonNegative},
|
||||
block::{Height, HeightDiff},
|
||||
parameters::{Network, NetworkUpgrade::*},
|
||||
parameters::{subsidy::*, Network, NetworkUpgrade::*},
|
||||
transaction::Transaction,
|
||||
};
|
||||
|
||||
use crate::{funding_stream_values, parameters::subsidy::*};
|
||||
use crate::funding_stream_values;
|
||||
|
||||
/// The divisor used for halvings.
|
||||
///
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
mod block;
|
||||
mod checkpoint;
|
||||
mod parameters;
|
||||
mod primitives;
|
||||
mod script;
|
||||
|
||||
|
@ -64,7 +63,6 @@ pub use checkpoint::{
|
|||
};
|
||||
pub use config::Config;
|
||||
pub use error::BlockError;
|
||||
pub use parameters::{FundingStreamReceiver, ParameterSubsidy};
|
||||
pub use primitives::{ed25519, groth16, halo2, redjubjub, redpallas};
|
||||
pub use router::RouterError;
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
//! The consensus parameters for each Zcash network.
|
||||
//!
|
||||
//! This module contains the consensus parameters which are required for
|
||||
//! verification.
|
||||
//!
|
||||
//! Some consensus parameters change based on network upgrades. Each network
|
||||
//! upgrade happens at a particular block height. Some parameters have a value
|
||||
//! (or function) before the upgrade height, at the upgrade height, and after
|
||||
//! the upgrade height. (For example, the value of the reserved field in the
|
||||
//! block header during the Heartwood upgrade.)
|
||||
//!
|
||||
//! Typically, consensus parameters are accessed via a function that takes a
|
||||
//! `Network` and `block::Height`.
|
||||
|
||||
pub mod subsidy;
|
||||
|
||||
pub use subsidy::*;
|
|
@ -14,7 +14,7 @@ use zebra_chain::{
|
|||
block::{self, Block, Height, TryIntoHeight},
|
||||
chain_sync_status::ChainSyncStatus,
|
||||
chain_tip::ChainTip,
|
||||
parameters::{Network, NetworkKind, POW_AVERAGING_WINDOW},
|
||||
parameters::{subsidy::ParameterSubsidy, Network, NetworkKind, POW_AVERAGING_WINDOW},
|
||||
primitives,
|
||||
serialization::ZcashDeserializeInto,
|
||||
transparent::{
|
||||
|
@ -22,10 +22,7 @@ use zebra_chain::{
|
|||
},
|
||||
work::difficulty::{ParameterDifficulty as _, U256},
|
||||
};
|
||||
use zebra_consensus::{
|
||||
funding_stream_address, funding_stream_values, miner_subsidy, ParameterSubsidy as _,
|
||||
RouterError,
|
||||
};
|
||||
use zebra_consensus::{funding_stream_address, funding_stream_values, miner_subsidy, RouterError};
|
||||
use zebra_network::AddressBookPeers;
|
||||
use zebra_node_services::mempool;
|
||||
use zebra_state::{ReadRequest, ReadResponse};
|
||||
|
@ -1202,7 +1199,10 @@ where
|
|||
.iter()
|
||||
.map(|(receiver, value)| {
|
||||
let address = funding_stream_address(height, &network, *receiver);
|
||||
(*receiver, FundingStream::new(*receiver, *value, address))
|
||||
(
|
||||
*receiver,
|
||||
FundingStream::new(&network, height, *receiver, *value, address),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
use jsonrpc_core::ErrorCode;
|
||||
|
||||
use zebra_chain::block;
|
||||
use zebra_consensus::FundingStreamReceiver::{self, *};
|
||||
use zebra_chain::{
|
||||
block,
|
||||
parameters::subsidy::FundingStreamReceiver::{self, *},
|
||||
};
|
||||
|
||||
/// When long polling, the amount of time we wait between mempool queries.
|
||||
/// (And sync status queries, which we do right before mempool queries.)
|
||||
|
|
|
@ -14,14 +14,12 @@ use zebra_chain::{
|
|||
},
|
||||
chain_sync_status::ChainSyncStatus,
|
||||
chain_tip::ChainTip,
|
||||
parameters::{Network, NetworkUpgrade},
|
||||
parameters::{subsidy::FundingStreamReceiver, Network, NetworkUpgrade},
|
||||
serialization::ZcashDeserializeInto,
|
||||
transaction::{Transaction, UnminedTx, VerifiedUnminedTx},
|
||||
transparent,
|
||||
};
|
||||
use zebra_consensus::{
|
||||
funding_stream_address, funding_stream_values, miner_subsidy, FundingStreamReceiver,
|
||||
};
|
||||
use zebra_consensus::{funding_stream_address, funding_stream_values, miner_subsidy};
|
||||
use zebra_node_services::mempool;
|
||||
use zebra_state::GetBlockTemplateChainInfo;
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
use zebra_chain::{
|
||||
amount::{Amount, NonNegative},
|
||||
block::Height,
|
||||
parameters::{subsidy::FundingStreamReceiver, Network},
|
||||
transparent,
|
||||
};
|
||||
use zebra_consensus::{funding_stream_recipient_info, FundingStreamReceiver};
|
||||
use zebra_consensus::funding_stream_recipient_info;
|
||||
|
||||
use crate::methods::get_block_template_rpcs::types::zec::Zec;
|
||||
|
||||
|
@ -64,11 +66,13 @@ pub struct FundingStream {
|
|||
impl FundingStream {
|
||||
/// Convert a `receiver`, `value`, and `address` into a `FundingStream` response.
|
||||
pub fn new(
|
||||
network: &Network,
|
||||
height: Height,
|
||||
receiver: FundingStreamReceiver,
|
||||
value: Amount<NonNegative>,
|
||||
address: transparent::Address,
|
||||
) -> FundingStream {
|
||||
let (recipient, specification) = funding_stream_recipient_info(receiver);
|
||||
let (recipient, specification) = funding_stream_recipient_info(network, height, receiver);
|
||||
|
||||
FundingStream {
|
||||
recipient: recipient.to_string(),
|
||||
|
|
Loading…
Reference in New Issue