orchard/note/
commitment.rs1use core::iter;
2
3use bitvec::{array::BitArray, order::Lsb0};
4use group::ff::{PrimeField, PrimeFieldBits};
5use pasta_curves::pallas;
6use subtle::{ConstantTimeEq, CtOption};
7
8use crate::{
9 constants::{fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, L_ORCHARD_BASE},
10 spec::extract_p,
11 value::NoteValue,
12};
13
14#[derive(Clone, Debug)]
16pub struct NoteCommitTrapdoor(pub(super) pallas::Scalar);
17
18impl NoteCommitTrapdoor {
19 pub fn inner(&self) -> pallas::Scalar {
21 self.0
22 }
23}
24
25#[derive(Clone, Debug)]
27pub struct NoteCommitment(pub(super) pallas::Point);
28
29impl NoteCommitment {
30 pub fn inner(&self) -> pallas::Point {
32 self.0
33 }
34}
35
36impl NoteCommitment {
37 pub(super) fn derive(
43 g_d: [u8; 32],
44 pk_d: [u8; 32],
45 v: NoteValue,
46 rho: pallas::Base,
47 psi: pallas::Base,
48 rcm: NoteCommitTrapdoor,
49 ) -> CtOption<Self> {
50 let domain = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION);
51 domain
52 .commit(
53 iter::empty()
54 .chain(BitArray::<_, Lsb0>::new(g_d).iter().by_vals())
55 .chain(BitArray::<_, Lsb0>::new(pk_d).iter().by_vals())
56 .chain(v.to_le_bits().iter().by_vals())
57 .chain(rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE))
58 .chain(psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)),
59 &rcm.0,
60 )
61 .map(NoteCommitment)
62 }
63}
64
65#[derive(Copy, Clone, Debug)]
67pub struct ExtractedNoteCommitment(pub(super) pallas::Base);
68
69impl ExtractedNoteCommitment {
70 pub fn from_bytes(bytes: &[u8; 32]) -> CtOption<Self> {
77 pallas::Base::from_repr(*bytes).map(ExtractedNoteCommitment)
78 }
79
80 pub fn to_bytes(self) -> [u8; 32] {
82 self.0.to_repr()
83 }
84}
85
86impl From<NoteCommitment> for ExtractedNoteCommitment {
87 fn from(cm: NoteCommitment) -> Self {
88 ExtractedNoteCommitment(extract_p(&cm.0))
89 }
90}
91
92impl ExtractedNoteCommitment {
93 pub fn inner(&self) -> pallas::Base {
95 self.0
96 }
97}
98
99impl From<&ExtractedNoteCommitment> for [u8; 32] {
100 fn from(cmx: &ExtractedNoteCommitment) -> Self {
101 cmx.to_bytes()
102 }
103}
104
105impl ConstantTimeEq for ExtractedNoteCommitment {
106 fn ct_eq(&self, other: &Self) -> subtle::Choice {
107 self.0.ct_eq(&other.0)
108 }
109}
110
111impl PartialEq for ExtractedNoteCommitment {
112 fn eq(&self, other: &Self) -> bool {
113 self.ct_eq(other).into()
114 }
115}
116
117impl Eq for ExtractedNoteCommitment {}