feat(consensus): Validate ZIP-212 grace period blocks using checkpoints (#3889)
* Test if mandatory checkpoint is after grace period Check that the mandatory checkpoint height is after the ZIP-212 grace period for both mainnet and testnet, because Zebra is currently unable to fully validate the blocks during that grace period. * Update mandatory checkpoint height Require it to be after the ZIP-212 grace period so that the blocks during the grace period are validated by the checkpoints because Zebra can't currently fully validate blocks during that period.
This commit is contained in:
parent
67b367929c
commit
b563b2a1c1
|
@ -5,6 +5,45 @@ use crate::{block::Height, parameters::NetworkUpgrade::Canopy};
|
|||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// The ZIP-212 grace period length after the Canopy activation height.
|
||||
///
|
||||
/// # Consensus
|
||||
///
|
||||
/// ZIP-212 requires Zcash nodes to validate that Sapling spends and Orchard actions follows a
|
||||
/// specific plaintext format after Canopy's activation.
|
||||
///
|
||||
/// > [Heartwood onward] All Sapling and Orchard outputs in coinbase transactions MUST decrypt to a
|
||||
/// > note plaintext , i.e. the procedure in § 4.19.3 ‘Decryption using a Full Viewing Key (Sapling
|
||||
/// > and Orchard)’ on p. 67 does not return ⊥, using a sequence of 32 zero bytes as the outgoing
|
||||
/// > viewing key . (This implies that before Canopy activation, Sapling outputs of a coinbase
|
||||
/// > transaction MUST have note plaintext lead byte equal to 0x01.)
|
||||
///
|
||||
/// > [Canopy onward] Any Sapling or Orchard output of a coinbase transaction decrypted to a note
|
||||
/// > plaintext according to the preceding rule MUST have note plaintext lead byte equal to 0x02.
|
||||
/// > (This applies even during the “grace period” specified in [ZIP-212].)
|
||||
///
|
||||
/// https://zips.z.cash/protocol/protocol.pdf#txnencodingandconsensus
|
||||
///
|
||||
/// Wallets have a grace period of 32,256 blocks after Canopy's activation to validate those blocks,
|
||||
/// but nodes do not.
|
||||
///
|
||||
/// > There is a "grace period" of 32256 blocks starting from the block at which this ZIP activates,
|
||||
/// > during which note plaintexts with lead byte 0x01 MUST still be accepted [by wallets].
|
||||
/// >
|
||||
/// > Let ActivationHeight be the activation height of this ZIP, and let GracePeriodEndHeight be
|
||||
/// > ActivationHeight + 32256.
|
||||
///
|
||||
/// https://zips.z.cash/zip-0212#changes-to-the-process-of-receiving-sapling-or-orchard-notes
|
||||
///
|
||||
/// Zebra uses `librustzcash` to validate that rule, but it won't validate it during the grace
|
||||
/// period. Therefore Zebra must validate those blocks during the grace period using checkpoints.
|
||||
/// Therefore the mandatory checkpoint height ([`Network::mandatory_checkpoint_height`]) must be
|
||||
/// after the grace period.
|
||||
const ZIP_212_GRACE_PERIOD_DURATION: i32 = 32_256;
|
||||
|
||||
/// An enum describing the possible network choices.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||
|
@ -51,10 +90,16 @@ impl Network {
|
|||
/// If a Zcash consensus rule only applies before the mandatory checkpoint,
|
||||
/// Zebra can skip validation of that rule.
|
||||
pub fn mandatory_checkpoint_height(&self) -> Height {
|
||||
// Currently this is the Canopy activation height for both networks.
|
||||
Canopy
|
||||
// Currently this is after the ZIP-212 grace period.
|
||||
//
|
||||
// See the `ZIP_212_GRACE_PERIOD_DOCUMENTATION` for more information.
|
||||
|
||||
let canopy_activation = Canopy
|
||||
.activation_height(*self)
|
||||
.expect("Canopy activation height must be present for both networks")
|
||||
.expect("Canopy activation height must be present for both networks");
|
||||
|
||||
(canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
||||
.expect("ZIP-212 grace period ends at a valid block height")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
mod prop;
|
|
@ -0,0 +1,26 @@
|
|||
use proptest::prelude::*;
|
||||
|
||||
use super::super::{Network, ZIP_212_GRACE_PERIOD_DURATION};
|
||||
use crate::parameters::NetworkUpgrade;
|
||||
|
||||
proptest! {
|
||||
/// Check that the mandatory checkpoint is after the ZIP-212 grace period.
|
||||
///
|
||||
/// This is necessary because Zebra can't fully validate the blocks during the grace period due
|
||||
/// to a limitation of `librustzcash`.
|
||||
///
|
||||
/// See [`ZIP_212_GRACE_PERIOD_DURATION`] for more information.
|
||||
#[test]
|
||||
fn mandatory_checkpoint_is_after_zip212_grace_period(network in any::<Network>()) {
|
||||
zebra_test::init();
|
||||
|
||||
let canopy_activation = NetworkUpgrade::Canopy
|
||||
.activation_height(network)
|
||||
.expect("Canopy activation height is set");
|
||||
|
||||
let grace_period_end_height = (canopy_activation + ZIP_212_GRACE_PERIOD_DURATION)
|
||||
.expect("ZIP-212 grace period ends in a valid block height");
|
||||
|
||||
assert!(network.mandatory_checkpoint_height() >= grace_period_end_height);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue