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 */
1819//! Orchard fixed bases.
20use super::{L_ORCHARD_SCALAR, L_VALUE};
21use halo2_gadgets::ecc::{
22 chip::{BaseFieldElem, FixedPoint, FullScalar, ShortScalar},
23 FixedPoints,
24};
2526use pasta_curves::pallas;
2728pub 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;
3435/// 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";
3839/// SWU hash-to-curve personalization for the value commitment generator
40pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv";
4142/// SWU hash-to-curve value for the value commitment generator
43pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v";
4445/// SWU hash-to-curve value for the value commitment generator
46pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r";
4748/// SWU hash-to-curve personalization for the note commitment generator
49pub const NOTE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-NoteCommit";
5051/// SWU hash-to-curve personalization for the IVK commitment generator
52pub const COMMIT_IVK_PERSONALIZATION: &str = "z.cash:Orchard-CommitIvk";
5354/// Window size for fixed-base scalar multiplication
55pub const FIXED_BASE_WINDOW_SIZE: usize = 3;
5657/// $2^{`FIXED_BASE_WINDOW_SIZE`}$
58pub const H: usize = 1 << FIXED_BASE_WINDOW_SIZE;
5960/// Number of windows for a full-width scalar
61pub const NUM_WINDOWS: usize = L_ORCHARD_SCALAR.div_ceil(FIXED_BASE_WINDOW_SIZE);
6263/// Number of windows for a short signed scalar
64pub const NUM_WINDOWS_SHORT: usize = L_VALUE.div_ceil(FIXED_BASE_WINDOW_SIZE);
6566#[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}
7475impl From<OrchardFixedBasesFull> for OrchardFixedBases {
76fn from(full_width_base: OrchardFixedBasesFull) -> Self {
77Self::Full(full_width_base)
78 }
79}
8081impl From<ValueCommitV> for OrchardFixedBases {
82fn from(_value_commit_v: ValueCommitV) -> Self {
83Self::ValueCommitV
84 }
85}
8687impl From<NullifierK> for OrchardFixedBases {
88fn from(_nullifier_k: NullifierK) -> Self {
89Self::NullifierK
90 }
91}
9293/// 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}
101102/// NullifierK is used in scalar mul with a base field element.
103#[derive(Copy, Clone, Debug, Eq, PartialEq)]
104pub struct NullifierK;
105106/// ValueCommitV is used in scalar mul with a short signed scalar.
107#[derive(Copy, Clone, Debug, Eq, PartialEq)]
108pub struct ValueCommitV;
109110/// 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}
118119impl ConstBaseFieldElement {
120pub fn value_commit_r() -> Self {
121Self {
122 G: value_commit_r::generator(),
123 u: value_commit_r::U.to_vec(),
124 z: value_commit_r::Z.to_vec(),
125 }
126 }
127pub fn nullifier_k() -> Self {
128Self { G: nullifier_k::generator(), u: nullifier_k::U.to_vec(), z: nullifier_k::Z.to_vec() }
129 }
130}
131132impl FixedPoints<pallas::Affine> for OrchardFixedBases {
133type FullScalar = OrchardFixedBasesFull;
134type ShortScalar = ValueCommitV;
135type Base = ConstBaseFieldElement;
136}
137138impl FixedPoint<pallas::Affine> for OrchardFixedBasesFull {
139type FixedScalarKind = FullScalar;
140141fn generator(&self) -> pallas::Affine {
142match self {
143Self::CommitIvkR => commit_ivk_r::generator(),
144Self::NoteCommitR => note_commit_r::generator(),
145Self::ValueCommitR => value_commit_r::generator(),
146Self::SpendAuthG => spend_auth_g::generator(),
147 }
148 }
149150fn u(&self) -> Vec<[[u8; 32]; H]> {
151match self {
152Self::CommitIvkR => commit_ivk_r::U.to_vec(),
153Self::NoteCommitR => note_commit_r::U.to_vec(),
154Self::ValueCommitR => value_commit_r::U.to_vec(),
155Self::SpendAuthG => spend_auth_g::U.to_vec(),
156 }
157 }
158159fn z(&self) -> Vec<u64> {
160match self {
161Self::CommitIvkR => commit_ivk_r::Z.to_vec(),
162Self::NoteCommitR => note_commit_r::Z.to_vec(),
163Self::ValueCommitR => value_commit_r::Z.to_vec(),
164Self::SpendAuthG => spend_auth_g::Z.to_vec(),
165 }
166 }
167}
168169impl FixedPoint<pallas::Affine> for ConstBaseFieldElement {
170type FixedScalarKind = BaseFieldElem;
171172fn generator(&self) -> pallas::Affine {
173self.G
174 }
175176fn u(&self) -> Vec<[[u8; 32]; H]> {
177self.u.clone()
178 }
179180fn z(&self) -> Vec<u64> {
181self.z.clone()
182 }
183}
184185impl FixedPoint<pallas::Affine> for NullifierK {
186type FixedScalarKind = BaseFieldElem;
187188fn generator(&self) -> pallas::Affine {
189 nullifier_k::generator()
190 }
191192fn u(&self) -> Vec<[[u8; 32]; H]> {
193 nullifier_k::U.to_vec()
194 }
195196fn z(&self) -> Vec<u64> {
197 nullifier_k::Z.to_vec()
198 }
199}
200201impl FixedPoint<pallas::Affine> for ValueCommitV {
202type FixedScalarKind = ShortScalar;
203204fn generator(&self) -> pallas::Affine {
205 value_commit_v::generator()
206 }
207208fn u(&self) -> Vec<[[u8; 32]; H]> {
209 value_commit_v::U_SHORT.to_vec()
210 }
211212fn z(&self) -> Vec<u64> {
213 value_commit_v::Z_SHORT.to_vec()
214 }
215}