mirror of https://github.com/zcash/orchard.git
79 lines
2.4 KiB
Rust
79 lines
2.4 KiB
Rust
use std::iter;
|
|
|
|
use bitvec::{array::BitArray, order::Lsb0};
|
|
use ff::PrimeFieldBits;
|
|
use pasta_curves::{arithmetic::FieldExt, pallas};
|
|
use subtle::CtOption;
|
|
|
|
use crate::{constants::L_ORCHARD_BASE, primitives::sinsemilla, spec::extract_p, value::NoteValue};
|
|
|
|
pub(super) struct NoteCommitTrapdoor(pub(super) pallas::Scalar);
|
|
|
|
/// A commitment to a note.
|
|
#[derive(Debug)]
|
|
pub struct NoteCommitment(pub(super) 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,
|
|
) -> CtOption<Self> {
|
|
let domain = sinsemilla::CommitDomain::new("z.cash:Orchard-NoteCommit");
|
|
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,
|
|
)
|
|
.map(NoteCommitment)
|
|
}
|
|
}
|
|
|
|
/// The x-coordinate of the commitment to a note.
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct ExtractedNoteCommitment(pub(super) pallas::Base);
|
|
|
|
impl ExtractedNoteCommitment {
|
|
/// ExtractedNoteCommitment for an uncommitted note.
|
|
pub fn uncommitted() -> Self {
|
|
Self(pallas::Base::zero())
|
|
}
|
|
|
|
/// Deserialize the extracted note commitment from a byte array.
|
|
pub fn from_bytes(bytes: &[u8; 32]) -> CtOption<Self> {
|
|
pallas::Base::from_bytes(bytes).map(ExtractedNoteCommitment)
|
|
}
|
|
|
|
/// Serialize the value commitment to its canonical byte representation.
|
|
pub fn to_bytes(&self) -> [u8; 32] {
|
|
self.0.to_bytes()
|
|
}
|
|
}
|
|
|
|
impl From<NoteCommitment> for ExtractedNoteCommitment {
|
|
fn from(cm: NoteCommitment) -> Self {
|
|
ExtractedNoteCommitment(extract_p(&cm.0))
|
|
}
|
|
}
|
|
|
|
impl std::ops::Deref for ExtractedNoteCommitment {
|
|
type Target = pallas::Base;
|
|
|
|
fn deref(&self) -> &pallas::Base {
|
|
&self.0
|
|
}
|
|
}
|