Added NoteType to Notes

This commit is contained in:
Paul 2022-04-28 14:47:05 +03:00
parent 0d7ecad8e9
commit 58158f5f96
6 changed files with 108 additions and 3 deletions

View File

@ -150,8 +150,9 @@ impl ActionInfo {
let ak: SpendValidatingKey = self.spend.fvk.clone().into();
let alpha = pallas::Scalar::random(&mut rng);
let rk = ak.randomize(&alpha);
let note_type = self.spend.note.note_type();
let note = Note::new(self.output.recipient, self.output.value, nf_old, &mut rng);
let note = Note::new(self.output.recipient, self.output.value, note_type, nf_old, &mut rng);
let cm_new = note.commitment();
let cmx = cm_new.into();

View File

@ -21,6 +21,9 @@ pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard";
/// SWU hash-to-curve personalization for the value commitment generator
pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv";
/// SWU hash-to-curve personalization for the note type generator
// pub const NOTE_TYPE_PERSONALIZATION: &str = "z.cash:Orchard-NoteType";
/// SWU hash-to-curve value for the value commitment generator
pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v";

View File

@ -967,6 +967,7 @@ mod tests {
value::NoteValue,
Note,
};
use crate::note::NoteType;
#[test]
fn spend_validating_key_from_bytes() {
@ -1047,6 +1048,7 @@ mod tests {
let note = Note::from_parts(
addr,
NoteValue::from_raw(tv.note_v),
NoteType::native(),
rho,
RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(),
);

View File

@ -19,6 +19,9 @@ pub use self::commitment::{ExtractedNoteCommitment, NoteCommitment};
pub(crate) mod nullifier;
pub use self::nullifier::Nullifier;
pub(crate) mod note_type;
pub use self::note_type::NoteType;
/// The ZIP 212 seed randomness for a note.
#[derive(Copy, Clone, Debug)]
pub(crate) struct RandomSeed([u8; 32]);
@ -86,6 +89,8 @@ pub struct Note {
recipient: Address,
/// The value of this note.
value: NoteValue,
/// The type of this note.
note_type: NoteType,
/// A unique creation ID for this note.
///
/// This is set to the nullifier of the note that was spent in the [`Action`] that
@ -111,12 +116,14 @@ impl Note {
pub(crate) fn from_parts(
recipient: Address,
value: NoteValue,
note_type: NoteType,
rho: Nullifier,
rseed: RandomSeed,
) -> Self {
Note {
recipient,
value,
note_type,
rho,
rseed,
}
@ -130,6 +137,7 @@ impl Note {
pub(crate) fn new(
recipient: Address,
value: NoteValue,
note_type: NoteType,
rho: Nullifier,
mut rng: impl RngCore,
) -> Self {
@ -137,6 +145,7 @@ impl Note {
let note = Note {
recipient,
value,
note_type,
rho,
rseed: RandomSeed::random(&mut rng, &rho),
};
@ -162,6 +171,7 @@ impl Note {
let note = Note::new(
recipient,
NoteValue::zero(),
NoteType::native(),
rho.unwrap_or_else(|| Nullifier::dummy(rng)),
rng,
);
@ -179,6 +189,11 @@ impl Note {
self.value
}
/// Returns the note type
pub fn note_type(&self) -> NoteType {
self.note_type
}
/// Returns the rseed value of this note.
pub(crate) fn rseed(&self) -> &RandomSeed {
&self.rseed
@ -268,6 +283,7 @@ pub mod testing {
use crate::{
address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue,
};
use crate::note::NoteType;
use super::{Note, RandomSeed};
@ -288,6 +304,7 @@ pub mod testing {
Note {
recipient,
value,
note_type: NoteType::native(),
rho,
rseed,
}

78
src/note/note_type.rs Normal file
View File

@ -0,0 +1,78 @@
use group::{ff::PrimeField};
use halo2_proofs::arithmetic::CurveExt;
use pasta_curves::pallas;
use subtle::CtOption;
use crate:: spec::{extract_p};
use crate::constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_V_BYTES};
// use crate::keys::SpendValidatingKey;
/// Note type identifier.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct NoteType(pub(crate) pallas::Base);
impl NoteType {
/*
/// Generates a dummy note type for use as $\rho$ in dummy spent notes.
pub(crate) fn dummy(rng: &mut impl RngCore) -> Self {
NoteType(extract_p(&pallas::Point::random(rng)))
}
*/
/// Deserialize the note_type from a byte array.
pub fn from_bytes(bytes: &[u8; 32]) -> CtOption<Self> {
pallas::Base::from_repr(*bytes).map(NoteType)
}
/// Serialize the note_type to its canonical byte representation.
pub fn to_bytes(self) -> [u8; 32] {
self.0.to_repr()
}
/// $DeriveNoteType$.
///
/// Defined in [Zcash Protocol Spec § TBD: Note Types][notetypes].
///
/// [notetypes]: https://zips.z.cash/protocol/nu5.pdf#notetypes
#[allow(non_snake_case)]
pub(super) fn derive(
asset_idx: u64
) -> Self {
let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
let V = hasher(&VALUE_COMMITMENT_V_BYTES);
let value = pallas::Scalar::from(asset_idx);
NoteType(extract_p(&(V * value)))
}
/// note type for the "native" token (zec)
pub fn native() -> Self {
Self::derive(1)
}
}
/// Generators for property testing.
#[cfg(any(test, feature = "test-dependencies"))]
#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))]
pub mod testing {
use group::Group;
use pasta_curves::{arithmetic::FieldExt, pallas};
use proptest::collection::vec;
use proptest::prelude::*;
use std::convert::TryFrom;
use super::NoteType;
use crate::spec::extract_p;
prop_compose! {
/// Generate a uniformly distributed note type
pub fn arb_nullifier()(
bytes in vec(any::<u8>(), 64)
) -> NoteType {
let point = pallas::Point::generator() * pallas::Scalar::from_bytes_wide(&<[u8; 64]>::try_from(bytes).unwrap());
NoteType(extract_p(&point))
}
}
}

View File

@ -21,6 +21,7 @@ use crate::{
value::{NoteValue, ValueCommitment},
Address, Note,
};
use crate::note::NoteType;
const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock";
@ -75,7 +76,8 @@ where
let pk_d = get_validated_pk_d(&diversifier)?;
let recipient = Address::from_parts(diversifier, pk_d);
let note = Note::from_parts(recipient, value, domain.rho, rseed);
// TODO: add note_type
let note = Note::from_parts(recipient, value, NoteType::native(), domain.rho, rseed);
Some((note, recipient))
}
@ -151,6 +153,7 @@ impl Domain for OrchardDomain {
np[0] = 0x02;
np[1..12].copy_from_slice(note.recipient().diversifier().as_array());
np[12..20].copy_from_slice(&note.value().to_bytes());
// todo: add note_type
np[20..52].copy_from_slice(note.rseed().as_bytes());
np[52..].copy_from_slice(memo);
NotePlaintextBytes(np)
@ -327,6 +330,7 @@ mod tests {
value::{NoteValue, ValueCommitment},
Address, Note,
};
use crate::note::NoteType;
#[test]
fn test_vectors() {
@ -369,7 +373,7 @@ mod tests {
assert_eq!(ock.as_ref(), tv.ock);
let recipient = Address::from_parts(d, pk_d);
let note = Note::from_parts(recipient, value, rho, rseed);
let note = Note::from_parts(recipient, value, NoteType::native(), rho, rseed);
assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx);
let action = Action::from_parts(