Skip to content

Commit

Permalink
and note
Browse files Browse the repository at this point in the history
  • Loading branch information
abenso committed Nov 14, 2024
1 parent 80762e0 commit 238b722
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 51 deletions.
89 changes: 41 additions & 48 deletions app/rust/src/parser/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,26 @@ use crate::address::Address;
use crate::parser::{
address::AddressC,
bytes::BytesC,
plans::{amount::Amount, rseed::Rseed, value::ValueC},
plans::{rseed::Rseed, value::{Value, ValueC}},
};
use crate::ParserError;
use decaf377::Fq;

pub struct Note {
/// The typed value recorded by this note.
value: Value,
/// A uniformly random 32-byte sequence used to derive an ephemeral secret key
/// and note blinding factor.
rseed: Rseed,
/// The address controlling this note.
address: Address,
/// The s-component of the transmission key of the destination address.
/// We store this separately to ensure that every `Note` is constructed
/// with a valid transmission key (the `ka::Public` does not validate
/// the curve point until it is used, since validation is not free).
transmission_key_s: Fq,
}

#[repr(C)]
#[derive(Clone)]
#[cfg_attr(any(feature = "derive-debug", test), derive(Debug))]
Expand All @@ -16,78 +31,56 @@ pub struct NoteC {
pub address: AddressC,
}

impl NoteC {
impl TryFrom<NoteC> for Note {
type Error = ParserError;

fn try_from(note_c: NoteC) -> Result<Self, Self::Error> {
let value = Value::try_from(note_c.value)?;
let rseed = Rseed::try_from(note_c.rseed)?;
let address = Address::try_from(note_c.address.inner.get_bytes()?)?;
let transmission_key_s = Fq::from_bytes_checked(&address.transmission_key().0).map_err(|_| ParserError::InvalidFvk).unwrap();

Ok(Note {
value,
rseed,
address,
transmission_key_s,
})
}
}

impl Note {
pub fn commit(&self) -> Result<Fq, ParserError> {
let commit = poseidon377::hash_6(
&Self::notecommit_domain_sep(),
(
self.note_blinding()?,
Amount::try_from(self.value.amount.clone())?.into(),
self.get_asset_id_fq()?,
self.value.amount.clone().into(),
self.value.asset_id.0,
self.diversified_generator()?,
self.transmission_key_s()?,
self.transmission_key_s,
self.clue_key()?,
),
);
Ok(commit)
}

pub fn note_blinding(&self) -> Result<Fq, ParserError> {
let rseed_array: &[u8; 32] = self
.get_rseed()?
.try_into()
.expect("rseed should be 32 bytes");
let rseed = Rseed(*rseed_array).derive_note_blinding()?;
let rseed = self.rseed.derive_note_blinding()?;
Ok(rseed)
}

pub fn diversified_generator(&self) -> Result<Fq, ParserError> {
let diversifier_generator = Address::try_from(self.get_address()?)
.map_err(|_| ParserError::InvalidAddress)
.unwrap()
.diversifier()
.diversified_generator()
.vartime_compress_to_field();
let diversifier_generator = self.address.diversifier().diversified_generator().vartime_compress_to_field();
Ok(diversifier_generator)
}

pub fn transmission_key_s(&self) -> Result<Fq, ParserError> {
let transmission_key_s = Fq::from_bytes_checked(
&Address::try_from(self.get_address()?)
.unwrap()
.transmission_key()
.0,
)
.map_err(|_| ParserError::InvalidFvk)
.unwrap();
Ok(transmission_key_s)
}

pub fn clue_key(&self) -> Result<Fq, ParserError> {
let address =
Address::try_from(self.get_address()?).map_err(|_| ParserError::InvalidAddress)?;
let clue_key = address.clue_key();
let clue_key = self.address.clue_key();
Ok(Fq::from_le_bytes_mod_order(&clue_key.0[..]))
}

pub fn notecommit_domain_sep() -> Fq {
Fq::from_le_bytes_mod_order(blake2b_simd::blake2b(b"penumbra.notecommit").as_bytes())
}

pub fn get_rseed(&self) -> Result<&[u8], ParserError> {
self.rseed.get_bytes()
}

pub fn get_asset_id(&self) -> Result<&[u8], ParserError> {
self.value.asset_id.inner.get_bytes()
}

pub fn get_address(&self) -> Result<&[u8], ParserError> {
self.address.inner.get_bytes()
}

pub fn get_asset_id_fq(&self) -> Result<Fq, ParserError> {
let asset_id_bytes = self.get_asset_id()?;
Ok(Fq::from_le_bytes_mod_order(asset_id_bytes))
}
}
14 changes: 13 additions & 1 deletion app/rust/src/parser/plans/rseed.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use decaf377::Fq;
use crate::{ParserError, utils::prf};
use crate::parser::bytes::BytesC;

pub struct Rseed(pub [u8; 32]);

Expand All @@ -9,4 +10,15 @@ impl Rseed {
let hash_result = prf::expand(b"Penumbra_DeriRcm", &self.0, &[5u8])?;
Ok(Fq::from_le_bytes_mod_order(&hash_result))
}
}
}

impl TryFrom<BytesC> for Rseed {
type Error = ParserError;

fn try_from(value: BytesC) -> Result<Self, Self::Error> {
assert_eq!(value.len, 32, "Invalid rseed length");
let mut rseed = [0u8; 32];
rseed.copy_from_slice(value.get_bytes()?);
Ok(Rseed(rseed))
}
}
5 changes: 3 additions & 2 deletions app/rust/src/parser/plans/spend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::effect_hash::{create_personalized_state, EffectHash};
use crate::keys::FullViewingKey;
use crate::parser::{
bytes::BytesC,
note::NoteC,
note::{Note, NoteC},
plans::{nullifier::Nullifier, value::Value},
};
use crate::ParserError;
Expand Down Expand Up @@ -134,7 +134,8 @@ impl SpendPlanC {

pub fn nullifier(&self, fvk: &FullViewingKey) -> Result<[u8; 32], ParserError> {
let nk = fvk.nullifier_key();
let nullifier = Nullifier::derive(&nk, self.position, &self.note.commit()?);
let note = Note::try_from(self.note.clone())?;
let nullifier = Nullifier::derive(&nk, self.position, &note.commit()?);
Ok(nullifier.0.to_bytes())
}

Expand Down

0 comments on commit 238b722

Please sign in to comment.