darkfi_sdk/crypto/constants/
fixed_bases.rs

1/* This file is part of DarkFi (https://dark.fi)
2 *
3 * Copyright (C) 2020-2025 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19//! Orchard fixed bases.
20use super::{L_ORCHARD_SCALAR, L_VALUE};
21use halo2_gadgets::ecc::{
22    chip::{BaseFieldElem, FixedPoint, FullScalar, ShortScalar},
23    FixedPoints,
24};
25
26use pasta_curves::pallas;
27
28pub mod commit_ivk_r;
29pub mod note_commit_r;
30pub mod nullifier_k;
31pub mod spend_auth_g;
32pub mod value_commit_r;
33pub mod value_commit_v;
34
35/// SWU hash-to-curve personalization for the spending key base point and
36/// the nullifier base point K^Orchard
37pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard";
38
39/// SWU hash-to-curve personalization for the value commitment generator
40pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv";
41
42/// SWU hash-to-curve value for the value commitment generator
43pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v";
44
45/// SWU hash-to-curve value for the value commitment generator
46pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r";
47
48/// SWU hash-to-curve personalization for the note commitment generator
49pub const NOTE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-NoteCommit";
50
51/// SWU hash-to-curve personalization for the IVK commitment generator
52pub const COMMIT_IVK_PERSONALIZATION: &str = "z.cash:Orchard-CommitIvk";
53
54/// Window size for fixed-base scalar multiplication
55pub const FIXED_BASE_WINDOW_SIZE: usize = 3;
56
57/// $2^{`FIXED_BASE_WINDOW_SIZE`}$
58pub const H: usize = 1 << FIXED_BASE_WINDOW_SIZE;
59
60/// Number of windows for a full-width scalar
61pub const NUM_WINDOWS: usize = L_ORCHARD_SCALAR.div_ceil(FIXED_BASE_WINDOW_SIZE);
62
63/// Number of windows for a short signed scalar
64pub const NUM_WINDOWS_SHORT: usize = L_VALUE.div_ceil(FIXED_BASE_WINDOW_SIZE);
65
66#[derive(Copy, Clone, Debug, Eq, PartialEq)]
67// A sum type for both full-width and short bases. This enables us to use the
68// shared functionality of full-width and short fixed-base scalar multiplication.
69pub enum OrchardFixedBases {
70    Full(OrchardFixedBasesFull),
71    NullifierK,
72    ValueCommitV,
73}
74
75impl From<OrchardFixedBasesFull> for OrchardFixedBases {
76    fn from(full_width_base: OrchardFixedBasesFull) -> Self {
77        Self::Full(full_width_base)
78    }
79}
80
81impl From<ValueCommitV> for OrchardFixedBases {
82    fn from(_value_commit_v: ValueCommitV) -> Self {
83        Self::ValueCommitV
84    }
85}
86
87impl From<NullifierK> for OrchardFixedBases {
88    fn from(_nullifier_k: NullifierK) -> Self {
89        Self::NullifierK
90    }
91}
92
93/// The Orchard fixed bases used in scalar mul with full-width scalars.
94#[derive(Copy, Clone, Debug, Eq, PartialEq)]
95pub enum OrchardFixedBasesFull {
96    CommitIvkR,
97    NoteCommitR,
98    ValueCommitR,
99    SpendAuthG,
100}
101
102/// NullifierK is used in scalar mul with a base field element.
103#[derive(Copy, Clone, Debug, Eq, PartialEq)]
104pub struct NullifierK;
105
106/// ValueCommitV is used in scalar mul with a short signed scalar.
107#[derive(Copy, Clone, Debug, Eq, PartialEq)]
108pub struct ValueCommitV;
109
110/// ConstBaseFieldElement is used in scalar mul with a base field element.
111#[derive(Clone, Debug, Eq, PartialEq)]
112#[allow(non_snake_case)] // Rust bug: see https://github.com/rust-lang/rust/issues/60681
113pub struct ConstBaseFieldElement {
114    G: pallas::Affine,
115    u: Vec<[[u8; 32]; H]>,
116    z: Vec<u64>,
117}
118
119impl ConstBaseFieldElement {
120    pub fn value_commit_r() -> Self {
121        Self {
122            G: value_commit_r::generator(),
123            u: value_commit_r::U.to_vec(),
124            z: value_commit_r::Z.to_vec(),
125        }
126    }
127    pub fn nullifier_k() -> Self {
128        Self { G: nullifier_k::generator(), u: nullifier_k::U.to_vec(), z: nullifier_k::Z.to_vec() }
129    }
130}
131
132impl FixedPoints<pallas::Affine> for OrchardFixedBases {
133    type FullScalar = OrchardFixedBasesFull;
134    type ShortScalar = ValueCommitV;
135    type Base = ConstBaseFieldElement;
136}
137
138impl FixedPoint<pallas::Affine> for OrchardFixedBasesFull {
139    type FixedScalarKind = FullScalar;
140
141    fn generator(&self) -> pallas::Affine {
142        match self {
143            Self::CommitIvkR => commit_ivk_r::generator(),
144            Self::NoteCommitR => note_commit_r::generator(),
145            Self::ValueCommitR => value_commit_r::generator(),
146            Self::SpendAuthG => spend_auth_g::generator(),
147        }
148    }
149
150    fn u(&self) -> Vec<[[u8; 32]; H]> {
151        match self {
152            Self::CommitIvkR => commit_ivk_r::U.to_vec(),
153            Self::NoteCommitR => note_commit_r::U.to_vec(),
154            Self::ValueCommitR => value_commit_r::U.to_vec(),
155            Self::SpendAuthG => spend_auth_g::U.to_vec(),
156        }
157    }
158
159    fn z(&self) -> Vec<u64> {
160        match self {
161            Self::CommitIvkR => commit_ivk_r::Z.to_vec(),
162            Self::NoteCommitR => note_commit_r::Z.to_vec(),
163            Self::ValueCommitR => value_commit_r::Z.to_vec(),
164            Self::SpendAuthG => spend_auth_g::Z.to_vec(),
165        }
166    }
167}
168
169impl FixedPoint<pallas::Affine> for ConstBaseFieldElement {
170    type FixedScalarKind = BaseFieldElem;
171
172    fn generator(&self) -> pallas::Affine {
173        self.G
174    }
175
176    fn u(&self) -> Vec<[[u8; 32]; H]> {
177        self.u.clone()
178    }
179
180    fn z(&self) -> Vec<u64> {
181        self.z.clone()
182    }
183}
184
185impl FixedPoint<pallas::Affine> for NullifierK {
186    type FixedScalarKind = BaseFieldElem;
187
188    fn generator(&self) -> pallas::Affine {
189        nullifier_k::generator()
190    }
191
192    fn u(&self) -> Vec<[[u8; 32]; H]> {
193        nullifier_k::U.to_vec()
194    }
195
196    fn z(&self) -> Vec<u64> {
197        nullifier_k::Z.to_vec()
198    }
199}
200
201impl FixedPoint<pallas::Affine> for ValueCommitV {
202    type FixedScalarKind = ShortScalar;
203
204    fn generator(&self) -> pallas::Affine {
205        value_commit_v::generator()
206    }
207
208    fn u(&self) -> Vec<[[u8; 32]; H]> {
209        value_commit_v::U_SHORT.to_vec()
210    }
211
212    fn z(&self) -> Vec<u64> {
213        value_commit_v::Z_SHORT.to_vec()
214    }
215}