Skip to content

Commit

Permalink
Rename the () placeholder to FieldNotPresent (#1987)
Browse files Browse the repository at this point in the history
* Rename the () placeholder to FieldNotPresent

* Use a unit struct

* Update the RFC
  • Loading branch information
teor2345 authored Apr 7, 2021
1 parent 5bf0a29 commit 4185754
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 22 deletions.
7 changes: 5 additions & 2 deletions book/src/dev/rfcs/0010-v5-transaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,17 @@ We add an `AnchorVariant` generic type trait, because V4 transactions have a per
struct PerSpendAnchor {}
struct SharedAnchor {}

/// This field is not present in this transaction version.
struct FieldNotPresent;

impl AnchorVariant for PerSpendAnchor {
type Shared = ();
type Shared = FieldNotPresent;
type PerSpend = tree::Root;
}

impl AnchorVariant for SharedAnchor {
type Shared = tree::Root;
type PerSpend = ();
type PerSpend = FieldNotPresent;
}

trait AnchorVariant {
Expand Down
4 changes: 3 additions & 1 deletion zebra-chain/src/sapling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ pub use commitment::{CommitmentRandomness, NoteCommitment, ValueCommitment};
pub use keys::Diversifier;
pub use note::{EncryptedNote, Note, Nullifier, WrappedNoteKey};
pub use output::Output;
pub use shielded_data::{AnchorVariant, PerSpendAnchor, SharedAnchor, ShieldedData};
pub use shielded_data::{
AnchorVariant, FieldNotPresent, PerSpendAnchor, SharedAnchor, ShieldedData,
};
pub use spend::Spend;
5 changes: 3 additions & 2 deletions zebra-chain/src/sapling/arbitrary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use proptest::{arbitrary::any, array, collection::vec, prelude::*};
use crate::primitives::Groth16Proof;

use super::{
keys, note, tree, NoteCommitment, Output, PerSpendAnchor, SharedAnchor, Spend, ValueCommitment,
keys, note, tree, FieldNotPresent, NoteCommitment, Output, PerSpendAnchor, SharedAnchor, Spend,
ValueCommitment,
};

impl Arbitrary for Spend<PerSpendAnchor> {
Expand Down Expand Up @@ -49,7 +50,7 @@ impl Arbitrary for Spend<SharedAnchor> {
vec(any::<u8>(), 64),
)
.prop_map(|(nullifier, rpk_bytes, proof, sig_bytes)| Self {
per_spend_anchor: (),
per_spend_anchor: FieldNotPresent,
cv: ValueCommitment(AffinePoint::identity()),
nullifier,
rk: redjubjub::VerificationKeyBytes::from(rpk_bytes),
Expand Down
15 changes: 7 additions & 8 deletions zebra-chain/src/sapling/shielded_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,18 @@ pub struct PerSpendAnchor {}
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct SharedAnchor {}

/// This field is not present in this transaction version.
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct FieldNotPresent;

impl AnchorVariant for PerSpendAnchor {
type Shared = ();
type Shared = FieldNotPresent;
type PerSpend = tree::Root;
}

impl AnchorVariant for SharedAnchor {
type Shared = tree::Root;
type PerSpend = ();
type PerSpend = FieldNotPresent;
}

/// A type trait to handle structural differences between V4 and V5 Sapling
Expand All @@ -45,13 +49,9 @@ impl AnchorVariant for SharedAnchor {
/// single transaction anchor for all Spends in a transaction.
pub trait AnchorVariant {
/// The type of the shared anchor.
///
/// `()` means "not present in this transaction version".
type Shared: Clone + Debug + DeserializeOwned + Serialize + Eq + PartialEq;

/// The type of the per-spend anchor.
///
/// `()` means "not present in this transaction version".
type PerSpend: Clone + Debug + DeserializeOwned + Serialize + Eq + PartialEq;
}

Expand All @@ -74,7 +74,6 @@ pub trait AnchorVariant {
/// In `Transaction::V4`, each `Spend` has its own anchor. In `Transaction::V5`,
/// there is a single `shared_anchor` for the entire transaction. This
/// structural difference is modeled using the `AnchorVariant` type trait.
/// A type of `()` means "not present in this transaction version".
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ShieldedData<AnchorV>
where
Expand All @@ -84,7 +83,7 @@ where
pub value_balance: Amount,
/// The shared anchor for all `Spend`s in this transaction.
///
/// A type of `()` means "not present in this transaction version".
/// Some transaction versions do not have this field.
pub shared_anchor: AnchorV::Shared,
/// Either a spend or output description.
///
Expand Down
9 changes: 4 additions & 5 deletions zebra-chain/src/sapling/spend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
},
};

use super::{commitment, note, tree, AnchorVariant, PerSpendAnchor, SharedAnchor};
use super::{commitment, note, tree, AnchorVariant, FieldNotPresent, PerSpendAnchor, SharedAnchor};

/// A _Spend Description_, as described in [protocol specification §7.3][ps].
///
Expand All @@ -26,7 +26,6 @@ use super::{commitment, note, tree, AnchorVariant, PerSpendAnchor, SharedAnchor}
/// In `Transaction::V4`, each `Spend` has its own anchor. In `Transaction::V5`,
/// there is a single `shared_anchor` for the entire transaction. This
/// structural difference is modeled using the `AnchorVariant` type trait.
/// A type of `()` means "not present in this transaction version".
///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#spendencoding
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
Expand All @@ -35,7 +34,7 @@ pub struct Spend<AnchorV: AnchorVariant> {
pub cv: commitment::ValueCommitment,
/// A root of the Sapling note commitment tree at some block height in the past.
///
/// A type of `()` means "not present in this transaction version".
/// Some transaction versions do not have this field.
pub per_spend_anchor: AnchorV::PerSpend,
/// The nullifier of the input note.
pub nullifier: note::Nullifier,
Expand All @@ -62,9 +61,9 @@ impl From<(Spend<SharedAnchor>, tree::Root)> for Spend<PerSpendAnchor> {
}
}

impl From<(Spend<PerSpendAnchor>, ())> for Spend<PerSpendAnchor> {
impl From<(Spend<PerSpendAnchor>, FieldNotPresent)> for Spend<PerSpendAnchor> {
/// Take the `Spend<PerSpendAnchor>` from a spend + anchor tuple.
fn from(per_spend: (Spend<PerSpendAnchor>, ())) -> Self {
fn from(per_spend: (Spend<PerSpendAnchor>, FieldNotPresent)) -> Self {
per_spend.0
}
}
Expand Down
1 change: 1 addition & 0 deletions zebra-chain/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub use hash::Hash;
pub use joinsplit::JoinSplitData;
pub use lock_time::LockTime;
pub use memo::Memo;
pub use sapling::FieldNotPresent;
pub use sighash::HashType;

use crate::{
Expand Down
4 changes: 2 additions & 2 deletions zebra-chain/src/transaction/arbitrary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
sapling, sprout, transparent,
};

use super::{JoinSplitData, LockTime, Memo, Transaction};
use super::{FieldNotPresent, JoinSplitData, LockTime, Memo, Transaction};

impl Transaction {
/// Generate a proptest strategy for V1 Transactions
Expand Down Expand Up @@ -219,7 +219,7 @@ impl Arbitrary for sapling::ShieldedData<sapling::PerSpendAnchor> {
.prop_map(
|(value_balance, first, rest_spends, rest_outputs, sig_bytes)| Self {
value_balance,
shared_anchor: (),
shared_anchor: FieldNotPresent,
first,
rest_spends,
rest_outputs,
Expand Down
4 changes: 2 additions & 2 deletions zebra-chain/src/transaction/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ impl ZcashDeserialize for Transaction {
let sapling_shielded_data = if !shielded_spends.is_empty() {
Some(sapling::ShieldedData {
value_balance,
shared_anchor: (),
shared_anchor: FieldNotPresent,
first: Left(shielded_spends.remove(0)),
rest_spends: shielded_spends,
rest_outputs: shielded_outputs,
Expand All @@ -290,7 +290,7 @@ impl ZcashDeserialize for Transaction {
} else if !shielded_outputs.is_empty() {
Some(sapling::ShieldedData {
value_balance,
shared_anchor: (),
shared_anchor: FieldNotPresent,
first: Right(shielded_outputs.remove(0)),
// the spends are actually empty here, but we use the
// vec for consistency and readability
Expand Down

0 comments on commit 4185754

Please sign in to comment.