Rename the () placeholder to FieldNotPresent (#1987)
* Rename the () placeholder to FieldNotPresent * Use a unit struct * Update the RFC
This commit is contained in:
parent
5bf0a2954e
commit
418575458e
|
|
@ -95,14 +95,17 @@ We add an `AnchorVariant` generic type trait, because V4 transactions have a per
|
||||||
struct PerSpendAnchor {}
|
struct PerSpendAnchor {}
|
||||||
struct SharedAnchor {}
|
struct SharedAnchor {}
|
||||||
|
|
||||||
|
/// This field is not present in this transaction version.
|
||||||
|
struct FieldNotPresent;
|
||||||
|
|
||||||
impl AnchorVariant for PerSpendAnchor {
|
impl AnchorVariant for PerSpendAnchor {
|
||||||
type Shared = ();
|
type Shared = FieldNotPresent;
|
||||||
type PerSpend = tree::Root;
|
type PerSpend = tree::Root;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnchorVariant for SharedAnchor {
|
impl AnchorVariant for SharedAnchor {
|
||||||
type Shared = tree::Root;
|
type Shared = tree::Root;
|
||||||
type PerSpend = ();
|
type PerSpend = FieldNotPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait AnchorVariant {
|
trait AnchorVariant {
|
||||||
|
|
|
||||||
|
|
@ -21,5 +21,7 @@ pub use commitment::{CommitmentRandomness, NoteCommitment, ValueCommitment};
|
||||||
pub use keys::Diversifier;
|
pub use keys::Diversifier;
|
||||||
pub use note::{EncryptedNote, Note, Nullifier, WrappedNoteKey};
|
pub use note::{EncryptedNote, Note, Nullifier, WrappedNoteKey};
|
||||||
pub use output::Output;
|
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;
|
pub use spend::Spend;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ use proptest::{arbitrary::any, array, collection::vec, prelude::*};
|
||||||
use crate::primitives::Groth16Proof;
|
use crate::primitives::Groth16Proof;
|
||||||
|
|
||||||
use super::{
|
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> {
|
impl Arbitrary for Spend<PerSpendAnchor> {
|
||||||
|
|
@ -49,7 +50,7 @@ impl Arbitrary for Spend<SharedAnchor> {
|
||||||
vec(any::<u8>(), 64),
|
vec(any::<u8>(), 64),
|
||||||
)
|
)
|
||||||
.prop_map(|(nullifier, rpk_bytes, proof, sig_bytes)| Self {
|
.prop_map(|(nullifier, rpk_bytes, proof, sig_bytes)| Self {
|
||||||
per_spend_anchor: (),
|
per_spend_anchor: FieldNotPresent,
|
||||||
cv: ValueCommitment(AffinePoint::identity()),
|
cv: ValueCommitment(AffinePoint::identity()),
|
||||||
nullifier,
|
nullifier,
|
||||||
rk: redjubjub::VerificationKeyBytes::from(rpk_bytes),
|
rk: redjubjub::VerificationKeyBytes::from(rpk_bytes),
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,18 @@ pub struct PerSpendAnchor {}
|
||||||
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
pub struct SharedAnchor {}
|
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 {
|
impl AnchorVariant for PerSpendAnchor {
|
||||||
type Shared = ();
|
type Shared = FieldNotPresent;
|
||||||
type PerSpend = tree::Root;
|
type PerSpend = tree::Root;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnchorVariant for SharedAnchor {
|
impl AnchorVariant for SharedAnchor {
|
||||||
type Shared = tree::Root;
|
type Shared = tree::Root;
|
||||||
type PerSpend = ();
|
type PerSpend = FieldNotPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type trait to handle structural differences between V4 and V5 Sapling
|
/// A type trait to handle structural differences between V4 and V5 Sapling
|
||||||
|
|
@ -45,13 +49,9 @@ impl AnchorVariant for SharedAnchor {
|
||||||
/// single transaction anchor for all Spends in a transaction.
|
/// single transaction anchor for all Spends in a transaction.
|
||||||
pub trait AnchorVariant {
|
pub trait AnchorVariant {
|
||||||
/// The type of the shared anchor.
|
/// The type of the shared anchor.
|
||||||
///
|
|
||||||
/// `()` means "not present in this transaction version".
|
|
||||||
type Shared: Clone + Debug + DeserializeOwned + Serialize + Eq + PartialEq;
|
type Shared: Clone + Debug + DeserializeOwned + Serialize + Eq + PartialEq;
|
||||||
|
|
||||||
/// The type of the per-spend anchor.
|
/// The type of the per-spend anchor.
|
||||||
///
|
|
||||||
/// `()` means "not present in this transaction version".
|
|
||||||
type PerSpend: Clone + Debug + DeserializeOwned + Serialize + Eq + PartialEq;
|
type PerSpend: Clone + Debug + DeserializeOwned + Serialize + Eq + PartialEq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +74,6 @@ pub trait AnchorVariant {
|
||||||
/// In `Transaction::V4`, each `Spend` has its own anchor. In `Transaction::V5`,
|
/// In `Transaction::V4`, each `Spend` has its own anchor. In `Transaction::V5`,
|
||||||
/// there is a single `shared_anchor` for the entire transaction. This
|
/// there is a single `shared_anchor` for the entire transaction. This
|
||||||
/// structural difference is modeled using the `AnchorVariant` type trait.
|
/// structural difference is modeled using the `AnchorVariant` type trait.
|
||||||
/// A type of `()` means "not present in this transaction version".
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct ShieldedData<AnchorV>
|
pub struct ShieldedData<AnchorV>
|
||||||
where
|
where
|
||||||
|
|
@ -84,7 +83,7 @@ where
|
||||||
pub value_balance: Amount,
|
pub value_balance: Amount,
|
||||||
/// The shared anchor for all `Spend`s in this transaction.
|
/// 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,
|
pub shared_anchor: AnchorV::Shared,
|
||||||
/// Either a spend or output description.
|
/// Either a spend or output description.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -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].
|
/// A _Spend Description_, as described in [protocol specification §7.3][ps].
|
||||||
///
|
///
|
||||||
|
|
@ -26,7 +26,6 @@ use super::{commitment, note, tree, AnchorVariant, PerSpendAnchor, SharedAnchor}
|
||||||
/// In `Transaction::V4`, each `Spend` has its own anchor. In `Transaction::V5`,
|
/// In `Transaction::V4`, each `Spend` has its own anchor. In `Transaction::V5`,
|
||||||
/// there is a single `shared_anchor` for the entire transaction. This
|
/// there is a single `shared_anchor` for the entire transaction. This
|
||||||
/// structural difference is modeled using the `AnchorVariant` type trait.
|
/// 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
|
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#spendencoding
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
|
@ -35,7 +34,7 @@ pub struct Spend<AnchorV: AnchorVariant> {
|
||||||
pub cv: commitment::ValueCommitment,
|
pub cv: commitment::ValueCommitment,
|
||||||
/// A root of the Sapling note commitment tree at some block height in the past.
|
/// 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,
|
pub per_spend_anchor: AnchorV::PerSpend,
|
||||||
/// The nullifier of the input note.
|
/// The nullifier of the input note.
|
||||||
pub nullifier: note::Nullifier,
|
pub nullifier: note::Nullifier,
|
||||||
|
|
@ -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.
|
/// 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
|
per_spend.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ pub use hash::Hash;
|
||||||
pub use joinsplit::JoinSplitData;
|
pub use joinsplit::JoinSplitData;
|
||||||
pub use lock_time::LockTime;
|
pub use lock_time::LockTime;
|
||||||
pub use memo::Memo;
|
pub use memo::Memo;
|
||||||
|
pub use sapling::FieldNotPresent;
|
||||||
pub use sighash::HashType;
|
pub use sighash::HashType;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use crate::{
|
||||||
sapling, sprout, transparent,
|
sapling, sprout, transparent,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{JoinSplitData, LockTime, Memo, Transaction};
|
use super::{FieldNotPresent, JoinSplitData, LockTime, Memo, Transaction};
|
||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
/// Generate a proptest strategy for V1 Transactions
|
/// Generate a proptest strategy for V1 Transactions
|
||||||
|
|
@ -219,7 +219,7 @@ impl Arbitrary for sapling::ShieldedData<sapling::PerSpendAnchor> {
|
||||||
.prop_map(
|
.prop_map(
|
||||||
|(value_balance, first, rest_spends, rest_outputs, sig_bytes)| Self {
|
|(value_balance, first, rest_spends, rest_outputs, sig_bytes)| Self {
|
||||||
value_balance,
|
value_balance,
|
||||||
shared_anchor: (),
|
shared_anchor: FieldNotPresent,
|
||||||
first,
|
first,
|
||||||
rest_spends,
|
rest_spends,
|
||||||
rest_outputs,
|
rest_outputs,
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,7 @@ impl ZcashDeserialize for Transaction {
|
||||||
let sapling_shielded_data = if !shielded_spends.is_empty() {
|
let sapling_shielded_data = if !shielded_spends.is_empty() {
|
||||||
Some(sapling::ShieldedData {
|
Some(sapling::ShieldedData {
|
||||||
value_balance,
|
value_balance,
|
||||||
shared_anchor: (),
|
shared_anchor: FieldNotPresent,
|
||||||
first: Left(shielded_spends.remove(0)),
|
first: Left(shielded_spends.remove(0)),
|
||||||
rest_spends: shielded_spends,
|
rest_spends: shielded_spends,
|
||||||
rest_outputs: shielded_outputs,
|
rest_outputs: shielded_outputs,
|
||||||
|
|
@ -290,7 +290,7 @@ impl ZcashDeserialize for Transaction {
|
||||||
} else if !shielded_outputs.is_empty() {
|
} else if !shielded_outputs.is_empty() {
|
||||||
Some(sapling::ShieldedData {
|
Some(sapling::ShieldedData {
|
||||||
value_balance,
|
value_balance,
|
||||||
shared_anchor: (),
|
shared_anchor: FieldNotPresent,
|
||||||
first: Right(shielded_outputs.remove(0)),
|
first: Right(shielded_outputs.remove(0)),
|
||||||
// the spends are actually empty here, but we use the
|
// the spends are actually empty here, but we use the
|
||||||
// vec for consistency and readability
|
// vec for consistency and readability
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue