mirror of https://github.com/zcash/orchard.git
Added NoteType to Notes
This commit is contained in:
parent
0d7ecad8e9
commit
58158f5f96
|
@ -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();
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
|
|
17
src/note.rs
17
src/note.rs
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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(¬e.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(
|
||||
|
|
Loading…
Reference in New Issue