zcash_primitives: Introduce traits for protocol-specific bundles

This commit is contained in:
Jack Grigg 2024-05-10 20:09:16 +00:00
parent 5bd911f63b
commit ebc6561eb2
6 changed files with 157 additions and 6 deletions

View File

@ -1,4 +1,9 @@
//! Structs representing the components within Zcash transactions.
//! Types representing the components within Zcash transactions.
use std::marker::PhantomData;
use zcash_protocol::value::BalanceError;
pub mod amount {
pub use zcash_protocol::value::{
BalanceError, ZatBalance as Amount, Zatoshis as NonNegativeAmount, COIN,
@ -31,3 +36,136 @@ pub use self::tze::{TzeIn, TzeOut};
// π_A + π_B + π_C
pub const GROTH_PROOF_SIZE: usize = 48 + 96 + 48;
/// The protocol-agnostic parts of a shielded bundle.
///
/// The trait methods can be implemented without any knowledge of protocol-specific
/// details, only requiring the ability to parse the general bundle structure within a
/// transaction.
pub trait ShieldedBundle {
fn value_balance(&self) -> Amount;
}
impl ShieldedBundle for sprout::Bundle {
fn value_balance(&self) -> Amount {
// We don't support building Sprout bundles in Rust.
self.value_balance()
.expect("Sprout bundles are all checked by consensus")
}
}
impl<A: ::sapling::bundle::Authorization> ShieldedBundle for ::sapling::Bundle<A, Amount> {
fn value_balance(&self) -> Amount {
*self.value_balance()
}
}
impl<A: ::orchard::bundle::Authorization> ShieldedBundle for ::orchard::Bundle<A, Amount> {
fn value_balance(&self) -> Amount {
*self.value_balance()
}
}
/// The transparent part of a transaction.
pub trait TransparentPart {
type Bundle;
fn value_balance<E, F>(bundle: &Self::Bundle, get_prevout_value: F) -> Result<Amount, E>
where
E: From<BalanceError>,
F: FnMut(&OutPoint) -> Result<Amount, E>;
}
#[derive(Debug)]
pub struct Transparent<A: transparent::Authorization> {
_auth: PhantomData<A>,
}
impl<A: transparent::Authorization> TransparentPart for Transparent<A> {
type Bundle = transparent::Bundle<A>;
fn value_balance<E, F>(bundle: &Self::Bundle, get_prevout_value: F) -> Result<Amount, E>
where
E: From<BalanceError>,
F: FnMut(&OutPoint) -> Result<Amount, E>,
{
bundle.value_balance(get_prevout_value)
}
}
/// The Sprout part of a transaction.
pub trait SproutPart {
type Bundle: ShieldedBundle;
}
/// Marker type for a transaction that may contain a Sprout part.
#[derive(Debug)]
pub struct Sprout;
impl SproutPart for Sprout {
type Bundle = sprout::Bundle;
}
/// The Sapling part of a transaction.
pub trait SaplingPart {
type Bundle: ShieldedBundle;
}
/// Marker type for a transaction that may contain a Sapling part.
#[derive(Debug)]
pub struct Sapling<A> {
_auth: PhantomData<A>,
}
impl<A: ::sapling::bundle::Authorization> SaplingPart for Sapling<A> {
type Bundle = ::sapling::Bundle<A, Amount>;
}
/// The Orchard part of a transaction.
pub trait OrchardPart {
type Bundle: ShieldedBundle;
}
/// Marker type for a transaction that may contain an Orchard part.
#[derive(Debug)]
pub struct Orchard<A> {
_auth: PhantomData<A>,
}
impl<A: ::orchard::bundle::Authorization> OrchardPart for Orchard<A> {
type Bundle = ::orchard::bundle::Bundle<A, Amount>;
}
/// The TZE part of a transaction.
#[cfg(zcash_unstable = "zfuture")]
pub trait TzePart {
type Bundle;
}
/// Marker type for a transaction that may contain a TZE part.
#[cfg(zcash_unstable = "zfuture")]
#[derive(Debug)]
pub struct Tze<A: tze::Authorization> {
_auth: PhantomData<A>,
}
#[cfg(zcash_unstable = "zfuture")]
impl<A: tze::Authorization> TzePart for Tze<A> {
type Bundle = tze::Bundle<A>;
}
/// The Transparent part of an authorized transaction.
pub trait AuthorizedTransparentPart: TransparentPart {}
/// The Sprout part of an authorized transaction.
pub trait AuthorizedSproutPart: SproutPart {}
/// The Sapling part of an authorized transaction.
pub trait AuthorizedSaplingPart: SaplingPart {}
/// The Orchard part of an authorized transaction.
pub trait AuthorizedOrchardPart: OrchardPart {}
/// The TZE part of an authorized transaction.
#[cfg(zcash_unstable = "zfuture")]
pub trait AuthorizedTzePart: TzePart {}

View File

@ -13,7 +13,7 @@ use orchard::{
};
use zcash_encoding::{Array, CompactSize, Vector};
use super::Amount;
use super::{Amount, AuthorizedOrchardPart, Orchard};
use crate::transaction::Transaction;
pub const FLAG_SPENDS_ENABLED: u8 = 0b0000_0001;
@ -44,6 +44,8 @@ impl MapAuth<Authorized, Authorized> for () {
}
}
impl AuthorizedOrchardPart for Orchard<orchard::bundle::Authorized> {}
/// Reads an [`orchard::Bundle`] from a v5 transaction format.
pub fn read_v5_bundle<R: Read>(
mut reader: R,

View File

@ -21,7 +21,7 @@ use crate::{
transaction::Transaction,
};
use super::{Amount, GROTH_PROOF_SIZE};
use super::{Amount, AuthorizedSaplingPart, Sapling, GROTH_PROOF_SIZE};
/// Returns the enforcement policy for ZIP 212 at the given height.
pub fn zip212_enforcement(params: &impl Parameters, height: BlockHeight) -> Zip212Enforcement {
@ -84,6 +84,8 @@ impl MapAuth<Authorized, Authorized> for () {
}
}
impl AuthorizedSaplingPart for Sapling<sapling::bundle::Authorized> {}
/// Consensus rules (§4.4) & (§4.5):
/// - Canonical encoding is enforced here.
/// - "Not small order" is enforced here.

View File

@ -2,7 +2,7 @@
use std::io::{self, Read, Write};
use super::{amount::Amount, GROTH_PROOF_SIZE};
use super::{amount::Amount, AuthorizedSproutPart, Sprout, GROTH_PROOF_SIZE};
// π_A + π_A' + π_B + π_B' + π_C + π_C' + π_K + π_H
const PHGR_PROOF_SIZE: usize = 33 + 33 + 65 + 33 + 33 + 33 + 33 + 33;
@ -29,6 +29,8 @@ impl Bundle {
}
}
impl AuthorizedSproutPart for Sprout {}
#[derive(Clone)]
#[allow(clippy::upper_case_acronyms)]
pub(crate) enum SproutProof {

View File

@ -7,7 +7,10 @@ use std::io::{self, Read, Write};
use crate::legacy::{Script, TransparentAddress};
use super::amount::{Amount, BalanceError, NonNegativeAmount};
use super::{
amount::{Amount, BalanceError, NonNegativeAmount},
AuthorizedTransparentPart, Transparent,
};
pub mod builder;
@ -202,6 +205,8 @@ impl TxOut {
}
}
impl AuthorizedTransparentPart for Transparent<Authorized> {}
#[cfg(any(test, feature = "test-dependencies"))]
pub mod testing {
use proptest::collection::vec;

View File

@ -7,7 +7,7 @@ use std::io::{self, Read, Write};
use zcash_encoding::{CompactSize, Vector};
use super::amount::Amount;
use super::{amount::Amount, AuthorizedTzePart, Tze};
use crate::{extensions::transparent as tze, transaction::TxId};
pub mod builder;
@ -211,6 +211,8 @@ impl TzeOut {
}
}
impl AuthorizedTzePart for Tze<Authorized> {}
#[cfg(any(test, feature = "test-dependencies"))]
pub mod testing {
use proptest::collection::vec;