Skip to main content

hekate_math/
field.rs

1// SPDX-License-Identifier: Apache-2.0
2// This file is part of the hekate-math project.
3// Copyright (C) 2026 Andrei Kochergin <zeek@tuta.com>
4// Copyright (C) 2026 Oumuamua Labs. All rights reserved.
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10//     http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use alloc::vec;
19use alloc::vec::Vec;
20use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
21use zeroize::Zeroize;
22
23pub trait TowerField:
24    Copy
25    + Default
26    + Clone
27    + PartialEq
28    + Eq
29    + core::fmt::Debug
30    + Send
31    + Sync
32    + From<u8>
33    + From<u32>
34    + From<u64>
35    + From<u128>
36    + Add<Output = Self>
37    + Sub<Output = Self>
38    + Mul<Output = Self>
39    + AddAssign
40    + SubAssign
41    + MulAssign
42    + CanonicalSerialize
43    + CanonicalDeserialize
44    + Zeroize
45{
46    const BITS: usize;
47    const ZERO: Self;
48    const ONE: Self;
49
50    /// The constant `TAU` needed to extend
51    /// this field to the next level.
52    /// If we are in F, then the next field
53    /// F' is constructed as F[X] / (X^2 + X + EXTENSION_TAU).
54    const EXTENSION_TAU: Self;
55
56    /// Returns the multiplicative inverse
57    /// of the element. By cryptographic
58    /// convention, the inverse of 0 is
59    /// defined as 0 to ensure constant-time
60    /// execution without branching.
61    fn invert(&self) -> Self;
62
63    /// Constructs a field element from
64    /// uniform bytes (e.g. hash output).
65    /// Used for PRNG / Blinding.
66    ///
67    /// The input is strictly 32 bytes
68    /// (standard hash size). Implementations
69    /// should use as many bytes as needed
70    /// from the prefix and ignore the rest.
71    fn from_uniform_bytes(bytes: &[u8; 32]) -> Self;
72}
73
74/// Defines how field elements are converted to bytes.
75/// Standard: Little-Endian.
76pub trait CanonicalSerialize {
77    /// Returns the size in bytes.
78    fn serialized_size(&self) -> usize;
79
80    /// Serializes the element into a buffer.
81    /// Returns error if buffer is too small.
82    #[allow(clippy::result_unit_err)]
83    fn serialize(&self, writer: &mut [u8]) -> Result<(), ()>;
84
85    /// Convenience method:
86    /// returns a Vec<u8>.
87    fn to_bytes(&self) -> Vec<u8> {
88        let size = self.serialized_size();
89        let mut buf = vec![0u8; size];
90        self.serialize(&mut buf).expect("Size calculation matches");
91
92        buf
93    }
94}
95
96/// Defines how bytes are converted back to field elements.
97/// Standard: Little-Endian.
98pub trait CanonicalDeserialize: Sized {
99    /// Deserializes from a buffer.
100    /// Returns Err if buffer is too short.
101    #[allow(clippy::result_unit_err)]
102    fn deserialize(bytes: &[u8]) -> Result<Self, ()>;
103}