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:
Janito Vaqueiro Ferreira Filho 2022-03-16 21:37:50 -03:00 committed by GitHub
parent 67b367929c
commit b563b2a1c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 3 deletions

View File

@ -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")
}
}

View File

@ -0,0 +1 @@
mod prop;

View File

@ -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);
}
}