From bf7f95b0e96402d65b7d5974bfbbbfb95ae21aef Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 23 Apr 2020 21:38:54 -0600 Subject: [PATCH] TZE consensus context and program sets Co-authored-by: Kris Nuttycombe --- zcash_primitives/src/consensus.rs | 4 +- zcash_primitives/src/consensus/extensions.rs | 3 + .../src/consensus/extensions/transparent.rs | 109 ++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 zcash_primitives/src/consensus/extensions.rs create mode 100644 zcash_primitives/src/consensus/extensions/transparent.rs diff --git a/zcash_primitives/src/consensus.rs b/zcash_primitives/src/consensus.rs index 4cc67f49b..952c14aa3 100644 --- a/zcash_primitives/src/consensus.rs +++ b/zcash_primitives/src/consensus.rs @@ -1,8 +1,10 @@ -//! Consensus parameters. +//! Consensus logic and parameters. use std::convert::TryFrom; use std::fmt; +pub mod extensions; + /// Zcash consensus parameters. pub trait Parameters { fn activation_height(nu: NetworkUpgrade) -> Option; diff --git a/zcash_primitives/src/consensus/extensions.rs b/zcash_primitives/src/consensus/extensions.rs new file mode 100644 index 000000000..6210d3fcd --- /dev/null +++ b/zcash_primitives/src/consensus/extensions.rs @@ -0,0 +1,3 @@ +//! Consensus logic for Zcash extensions. + +pub mod transparent; diff --git a/zcash_primitives/src/consensus/extensions/transparent.rs b/zcash_primitives/src/consensus/extensions/transparent.rs new file mode 100644 index 000000000..2c3e21745 --- /dev/null +++ b/zcash_primitives/src/consensus/extensions/transparent.rs @@ -0,0 +1,109 @@ +//! Consensus logic for Transparent Zcash Extensions. + +use std::convert::TryFrom; +use zcash_extensions_api::transparent::{Error, Extension, Precondition, Witness}; + +use crate::extensions::transparent::demo; +use crate::transaction::components::TzeOut; +use crate::transaction::Transaction; + +/// The set of programs that have assigned type IDs within the Zcash consensus rules. +#[derive(Debug, Clone, Copy)] +pub enum ExtensionId { + Demo, +} + +pub struct InvalidExtId(usize); + +impl TryFrom for ExtensionId { + type Error = InvalidExtId; + + fn try_from(t: usize) -> Result { + match t { + 0 => Ok(ExtensionId::Demo), + n => Err(InvalidExtId(n)), + } + } +} + +impl From for usize { + fn from(type_id: ExtensionId) -> usize { + match type_id { + ExtensionId::Demo => 0, + } + } +} + +/// The complete set of context data that is available to any extension having +/// an assigned extension type ID. +pub struct Context<'a> { + pub height: i32, + pub tx: &'a Transaction, +} + +impl<'a> Context<'a> { + pub fn new(height: i32, tx: &'a Transaction) -> Self { + Context { height, tx } + } +} + +pub trait Epoch { + type Error; + + fn verify<'a>( + &self, + precondition: &Precondition, + witness: &Witness, + ctx: &Context<'a>, + ) -> Result<(), Error>; +} + +/// Implementation of required operations for the demo extension, as satisfied +/// by the context. +impl<'a> demo::Context for Context<'a> { + fn is_tze_only(&self) -> bool { + self.tx.vin.is_empty() + && self.tx.vout.is_empty() + && self.tx.shielded_spends.is_empty() + && self.tx.shielded_outputs.is_empty() + && self.tx.joinsplits.is_empty() + } + + fn tx_tze_outputs(&self) -> &[TzeOut] { + &self.tx.tze_outputs + } +} + +/// Wire identifier for the dummy network upgrade epoch. +pub const V1_EPOCH_ID: u32 = 0x7473_6554; + +/// A set of demo TZEs associated with the dummy network upgrade. +struct EpochV1; + +impl Epoch for EpochV1 { + type Error = String; + + fn verify<'a>( + &self, + precondition: &Precondition, + witness: &Witness, + ctx: &Context<'a>, + ) -> Result<(), Error> { + // This epoch contains the following set of programs: + let ext_id = ExtensionId::try_from(precondition.extension_id) + .map_err(|InvalidExtId(id)| Error::InvalidExtensionId(id))?; + match ext_id { + ExtensionId::Demo => demo::Program + .verify(precondition, witness, ctx) + .map_err(|e| Error::ProgramError(format!("Epoch v1 program error: {}", e))), + } + } +} + +pub fn epoch_for_branch(consensus_branch_id: u32) -> Option>> { + // Map from consensus branch IDs to epochs. + match consensus_branch_id { + V1_EPOCH_ID => Some(Box::new(EpochV1)), + _ => None, + } +}