mirror of https://github.com/zcash/halo2.git
Note commitment derivation
This commit is contained in:
parent
ee2bfa7f43
commit
680c917ce6
|
@ -1,4 +1,9 @@
|
|||
use crate::keys::{DiversifiedTransmissionKey, Diversifier};
|
||||
use pasta_curves::pallas;
|
||||
|
||||
use crate::{
|
||||
keys::{DiversifiedTransmissionKey, Diversifier},
|
||||
spec::diversify_hash,
|
||||
};
|
||||
|
||||
/// A shielded payment address.
|
||||
///
|
||||
|
@ -18,6 +23,18 @@ pub struct Address {
|
|||
|
||||
impl Address {
|
||||
pub(crate) fn from_parts(d: Diversifier, pk_d: DiversifiedTransmissionKey) -> Self {
|
||||
// We assume here that pk_d is correctly-derived from d. We ensure this for
|
||||
// internal APIs. For parsing from raw byte encodings, we assume that users aren't
|
||||
// modifying internals of encoded address formats. If they do, that can result in
|
||||
// lost funds, but we can't defend against that from here.
|
||||
Address { d, pk_d }
|
||||
}
|
||||
|
||||
pub(crate) fn g_d(&self) -> pallas::Point {
|
||||
diversify_hash(self.d.as_array())
|
||||
}
|
||||
|
||||
pub(crate) fn pk_d(&self) -> &DiversifiedTransmissionKey {
|
||||
&self.pk_d
|
||||
}
|
||||
}
|
||||
|
|
14
src/keys.rs
14
src/keys.rs
|
@ -229,6 +229,13 @@ impl DiversifierKey {
|
|||
#[derive(Debug)]
|
||||
pub struct Diversifier([u8; 11]);
|
||||
|
||||
impl Diversifier {
|
||||
/// Returns the byte array corresponding to this diversifier.
|
||||
pub fn as_array(&self) -> &[u8; 11] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A key that provides the capability to detect and decrypt incoming notes from the block
|
||||
/// chain, without being able to spend the notes or detect when they are spent.
|
||||
///
|
||||
|
@ -290,7 +297,12 @@ impl DiversifiedTransmissionKey {
|
|||
///
|
||||
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
|
||||
fn derive(ivk: &IncomingViewingKey, d: &Diversifier) -> Self {
|
||||
let g_d = diversify_hash(&d.0);
|
||||
let g_d = diversify_hash(&d.as_array());
|
||||
DiversifiedTransmissionKey(ka_orchard(&ivk.0, &g_d))
|
||||
}
|
||||
|
||||
/// $repr_P(self)$
|
||||
pub(crate) fn to_bytes(&self) -> [u8; 32] {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
}
|
||||
|
|
52
src/note.rs
52
src/note.rs
|
@ -1,20 +1,33 @@
|
|||
use crate::{keys::FullViewingKey, value::NoteValue, Address};
|
||||
use group::GroupEncoding;
|
||||
use pasta_curves::pallas;
|
||||
|
||||
use crate::{
|
||||
keys::FullViewingKey,
|
||||
spec::{prf_expand, to_base, to_scalar},
|
||||
value::NoteValue,
|
||||
Address,
|
||||
};
|
||||
|
||||
mod commitment;
|
||||
pub use self::commitment::NoteCommitment;
|
||||
|
||||
/// The ZIP 212 seed randomness for a note.
|
||||
#[derive(Debug)]
|
||||
struct RandomSeed([u8; 32]);
|
||||
|
||||
impl RandomSeed {
|
||||
fn psi(&self) -> () {
|
||||
todo!()
|
||||
/// Defined in [Zcash Protocol Spec § 4.7.3: Sending Notes (Orchard)][orchardsend].
|
||||
///
|
||||
/// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend
|
||||
fn psi(&self) -> pallas::Base {
|
||||
to_base(prf_expand(&self.0, &[0x09]))
|
||||
}
|
||||
|
||||
fn rcm(&self) -> () {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn esk(&self) -> () {
|
||||
todo!()
|
||||
/// Defined in [Zcash Protocol Spec § 4.7.3: Sending Notes (Orchard)][orchardsend].
|
||||
///
|
||||
/// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend
|
||||
fn esk(&self) -> pallas::Scalar {
|
||||
to_scalar(prf_expand(&self.0, &[0x04]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,8 +51,21 @@ pub struct Note {
|
|||
|
||||
impl Note {
|
||||
/// Derives the commitment to this note.
|
||||
///
|
||||
/// Defined in [Zcash Protocol Spec § 3.2: Notes][notes].
|
||||
///
|
||||
/// [notes]: https://zips.z.cash/protocol/nu5.pdf#notes
|
||||
pub fn commitment(&self) -> NoteCommitment {
|
||||
todo!()
|
||||
let g_d = self.recipient.g_d();
|
||||
|
||||
NoteCommitment::derive(
|
||||
g_d.to_bytes(),
|
||||
self.recipient.pk_d().to_bytes(),
|
||||
self.value,
|
||||
self.rho.0,
|
||||
self.rseed.psi(),
|
||||
(&self.rseed).into(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Derives the nullifier for this note.
|
||||
|
@ -52,10 +78,6 @@ impl Note {
|
|||
#[derive(Debug)]
|
||||
pub struct EncryptedNote;
|
||||
|
||||
/// A commitment to a note.
|
||||
#[derive(Debug)]
|
||||
pub struct NoteCommitment;
|
||||
|
||||
/// A unique nullifier for a note.
|
||||
#[derive(Debug)]
|
||||
pub struct Nullifier;
|
||||
pub struct Nullifier(pallas::Base);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
use std::iter;
|
||||
|
||||
use bitvec::{array::BitArray, order::Lsb0};
|
||||
use ff::PrimeField;
|
||||
use pasta_curves::pallas;
|
||||
|
||||
use crate::{
|
||||
constants::L_ORCHARD_BASE,
|
||||
primitives::sinsemilla,
|
||||
spec::{prf_expand, to_scalar},
|
||||
value::NoteValue,
|
||||
};
|
||||
|
||||
use super::RandomSeed;
|
||||
|
||||
pub(super) struct NoteCommitTrapdoor(pallas::Scalar);
|
||||
|
||||
impl From<&RandomSeed> for NoteCommitTrapdoor {
|
||||
fn from(rseed: &RandomSeed) -> Self {
|
||||
NoteCommitTrapdoor(to_scalar(prf_expand(&rseed.0, &[0x05])))
|
||||
}
|
||||
}
|
||||
|
||||
/// A commitment to a note.
|
||||
#[derive(Debug)]
|
||||
pub struct NoteCommitment(pallas::Point);
|
||||
|
||||
impl NoteCommitment {
|
||||
/// $NoteCommit^Orchard$.
|
||||
///
|
||||
/// Defined in [Zcash Protocol Spec § 5.4.8.4: Sinsemilla commitments][concretesinsemillacommit].
|
||||
///
|
||||
/// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit
|
||||
pub(super) fn derive(
|
||||
g_d: [u8; 32],
|
||||
pk_d: [u8; 32],
|
||||
v: NoteValue,
|
||||
rho: pallas::Base,
|
||||
psi: pallas::Base,
|
||||
rcm: NoteCommitTrapdoor,
|
||||
) -> Self {
|
||||
let domain = sinsemilla::CommitDomain::new("z.cash:Orchard-NoteCommit");
|
||||
NoteCommitment(
|
||||
domain.commit(
|
||||
iter::empty()
|
||||
.chain(BitArray::<Lsb0, _>::new(g_d).iter().by_val())
|
||||
.chain(BitArray::<Lsb0, _>::new(pk_d).iter().by_val())
|
||||
.chain(v.to_le_bits().iter().by_val())
|
||||
.chain(rho.to_le_bits().iter().by_val().take(L_ORCHARD_BASE))
|
||||
.chain(psi.to_le_bits().iter().by_val().take(L_ORCHARD_BASE)),
|
||||
&rcm.0,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
10
src/value.rs
10
src/value.rs
|
@ -13,10 +13,18 @@
|
|||
//! [`Action`]: crate::bundle::Action
|
||||
//! [`Bundle`]: crate::bundle::Bundle
|
||||
|
||||
use bitvec::{array::BitArray, order::Lsb0};
|
||||
|
||||
/// The value of an individual Orchard note.
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct NoteValue(u64);
|
||||
|
||||
impl NoteValue {
|
||||
pub(crate) fn to_le_bits(&self) -> BitArray<Lsb0, [u8; 8]> {
|
||||
BitArray::<Lsb0, _>::new(self.0.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
/// A sum of Orchard note values.
|
||||
#[derive(Debug)]
|
||||
pub struct ValueSum(i64);
|
||||
|
|
Loading…
Reference in New Issue