From 61088f848bb63cf86e39693f6717739e7b7dec7e Mon Sep 17 00:00:00 2001 From: Tom Wambsgans Date: Fri, 12 Dec 2025 19:02:07 +0100 Subject: [PATCH 1/3] make some stuff public --- src/inc_encoding/target_sum.rs | 1 + src/lib.rs | 2 +- src/signature/generalized_xmss.rs | 14 +++++++------- .../instantiations_poseidon_top_level.rs | 14 +++++++++----- src/symmetric/message_hash/top_level_poseidon.rs | 1 + src/symmetric/tweak_hash.rs | 6 ++++-- src/symmetric/tweak_hash/poseidon.rs | 4 +++- src/symmetric/tweak_hash_tree.rs | 2 +- 8 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/inc_encoding/target_sum.rs b/src/inc_encoding/target_sum.rs index 0a735f5..aa40ab6 100644 --- a/src/inc_encoding/target_sum.rs +++ b/src/inc_encoding/target_sum.rs @@ -24,6 +24,7 @@ pub enum TargetSumError { /// const MAX_CHUNK_VALUE: usize = MH::BASE - 1 /// const EXPECTED_SUM: usize = MH::DIMENSION * MAX_CHUNK_VALUE / 2 /// ``` +#[derive(Clone)] pub struct TargetSumEncoding { _marker_mh: std::marker::PhantomData, } diff --git a/src/lib.rs b/src/lib.rs index ce6be6f..2549176 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ pub(crate) mod inc_encoding; pub mod serialization; pub mod signature; pub(crate) mod simd_utils; -pub(crate) mod symmetric; +pub mod symmetric; // Cached Poseidon2 permutations. // diff --git a/src/signature/generalized_xmss.rs b/src/signature/generalized_xmss.rs index 983e57f..2ae4e2e 100644 --- a/src/signature/generalized_xmss.rs +++ b/src/signature/generalized_xmss.rs @@ -40,12 +40,12 @@ pub struct GeneralizedXMSSSignatureScheme< /// Signature for GeneralizedXMSSSignatureScheme /// It contains a Merkle authentication path, encoding randomness, and a list of hashes -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] #[serde(bound = "")] pub struct GeneralizedXMSSSignature { - path: HashTreeOpening, - rho: IE::Randomness, - hashes: Vec, + pub path: HashTreeOpening, + pub rho: IE::Randomness, + pub hashes: Vec, } impl Encode for GeneralizedXMSSSignature { @@ -174,10 +174,10 @@ impl Decode for GeneralizedXMSSSign /// Public key for GeneralizedXMSSSignatureScheme /// It contains a Merkle root and a parameter for the tweakable hash -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct GeneralizedXMSSPublicKey { - root: TH::Domain, - parameter: TH::Parameter, + pub root: TH::Domain, + pub parameter: TH::Parameter, } /// Secret key for GeneralizedXMSSSignatureScheme diff --git a/src/signature/generalized_xmss/instantiations_poseidon_top_level.rs b/src/signature/generalized_xmss/instantiations_poseidon_top_level.rs index bea2239..23d7eff 100644 --- a/src/signature/generalized_xmss/instantiations_poseidon_top_level.rs +++ b/src/signature/generalized_xmss/instantiations_poseidon_top_level.rs @@ -86,7 +86,9 @@ pub mod lifetime_2_to_the_32 { use crate::{ inc_encoding::target_sum::TargetSumEncoding, - signature::generalized_xmss::GeneralizedXMSSSignatureScheme, + signature::generalized_xmss::{ + GeneralizedXMSSPublicKey, GeneralizedXMSSSignature, GeneralizedXMSSSignatureScheme, + }, symmetric::{ message_hash::top_level_poseidon::TopLevelPoseidonMessageHash, prf::shake_to_field::ShakePRFtoF, tweak_hash::poseidon::PoseidonTweakHash, @@ -101,10 +103,10 @@ pub mod lifetime_2_to_the_32 { const TARGET_SUM: usize = 375; const PARAMETER_LEN: usize = 5; - const TWEAK_LEN_FE: usize = 2; + pub const TWEAK_LEN_FE: usize = 2; const MSG_LEN_FE: usize = 9; - const RAND_LEN_FE: usize = 7; - const HASH_LEN_FE: usize = 8; + pub const RAND_LEN_FE: usize = 7; + pub const HASH_LEN_FE: usize = 8; const CAPACITY: usize = 9; @@ -112,7 +114,7 @@ pub mod lifetime_2_to_the_32 { const POS_INVOCATIONS: usize = 1; const POS_OUTPUT_LEN_FE: usize = POS_OUTPUT_LEN_PER_INV_FE * POS_INVOCATIONS; - type MH = TopLevelPoseidonMessageHash< + pub type MH = TopLevelPoseidonMessageHash< POS_OUTPUT_LEN_PER_INV_FE, POS_INVOCATIONS, POS_OUTPUT_LEN_FE, @@ -130,6 +132,8 @@ pub mod lifetime_2_to_the_32 { pub type SIGTopLevelTargetSumLifetime32Dim64Base8 = GeneralizedXMSSSignatureScheme; + pub type PubKeyTopLevelTargetSumLifetime32Dim64Base8 = GeneralizedXMSSPublicKey; + pub type SigTopLevelTargetSumLifetime32Dim64Base8 = GeneralizedXMSSSignature; #[cfg(test)] mod test { diff --git a/src/symmetric/message_hash/top_level_poseidon.rs b/src/symmetric/message_hash/top_level_poseidon.rs index e4c99c9..e980124 100644 --- a/src/symmetric/message_hash/top_level_poseidon.rs +++ b/src/symmetric/message_hash/top_level_poseidon.rs @@ -78,6 +78,7 @@ fn map_into_hypercube_part< /// - `POS_INVOCATIONS` must be at most 2^8. /// - `POS_OUTPUT_LEN_FE` must be equal to `POS_INVOCATIONS * POS_OUTPUT_LEN_PER_INV_FE`. /// - `BASE` must be at most 2^8. +#[derive(Clone)] pub struct TopLevelPoseidonMessageHash< const POS_OUTPUT_LEN_PER_INV_FE: usize, const POS_INVOCATIONS: usize, diff --git a/src/symmetric/tweak_hash.rs b/src/symmetric/tweak_hash.rs index efbb90d..54d5e4f 100644 --- a/src/symmetric/tweak_hash.rs +++ b/src/symmetric/tweak_hash.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + use rand::Rng; use crate::serialization::Serializable; @@ -20,10 +22,10 @@ pub trait TweakableHash { type Parameter: Copy + Send + Sync + Serializable; /// Tweak type for domain separation - type Tweak; + type Tweak: Debug; /// Domain element type (defines output and input types to the hash) - type Domain: Copy + PartialEq + Send + Sync + Serializable; + type Domain: Copy + PartialEq + Send + Sync + Serializable + Debug; /// Generates a random public parameter. fn rand_parameter(rng: &mut R) -> Self::Parameter; diff --git a/src/symmetric/tweak_hash/poseidon.rs b/src/symmetric/tweak_hash/poseidon.rs index bcd709f..f6634c3 100644 --- a/src/symmetric/tweak_hash/poseidon.rs +++ b/src/symmetric/tweak_hash/poseidon.rs @@ -23,6 +23,7 @@ const CHAIN_COMPRESSION_WIDTH: usize = 16; const MERGE_COMPRESSION_WIDTH: usize = 24; /// Enum to implement tweaks. +#[derive(Debug)] pub enum PoseidonTweak { TreeTweak { level: u8, @@ -36,7 +37,7 @@ pub enum PoseidonTweak { } impl PoseidonTweak { - fn to_field_elements(&self) -> [F; TWEAK_LEN] { + pub fn to_field_elements(&self) -> [F; TWEAK_LEN] { // We first represent the entire tweak as one big integer let mut acc = match self { Self::TreeTweak { @@ -248,6 +249,7 @@ where /// /// Note: HASH_LEN, TWEAK_LEN, CAPACITY, and PARAMETER_LEN must /// be given in the unit "number of field elements". +#[derive(Clone)] pub struct PoseidonTweakHash< const PARAMETER_LEN: usize, const HASH_LEN: usize, diff --git a/src/symmetric/tweak_hash_tree.rs b/src/symmetric/tweak_hash_tree.rs index 74ef9ad..00b1065 100644 --- a/src/symmetric/tweak_hash_tree.rs +++ b/src/symmetric/tweak_hash_tree.rs @@ -251,7 +251,7 @@ impl Decode for HashSubTree { } /// Opening in a hash-tree: a co-path, without the leaf -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] #[serde(bound = "")] pub struct HashTreeOpening { /// The co-path needed to verify From 8fc5879f8fdd0a1ba30948a6897c23c7d5f83608 Mon Sep 17 00:00:00 2001 From: Tom Wambsgans Date: Fri, 12 Dec 2025 23:06:50 +0100 Subject: [PATCH 2/3] clippy --- src/symmetric/tweak_hash.rs | 1 + src/symmetric/tweak_hash_tree.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/symmetric/tweak_hash.rs b/src/symmetric/tweak_hash.rs index 54d5e4f..5ae342e 100644 --- a/src/symmetric/tweak_hash.rs +++ b/src/symmetric/tweak_hash.rs @@ -77,6 +77,7 @@ pub trait TweakableHash { /// We start walking the chain at position `start_pos_in_chain` with `start`, /// and then walk the chain for `steps` many steps. For example, walking two steps /// with `start = A` would mean we walk A -> B -> C, and then return C. +#[allow(clippy::too_long_first_doc_paragraph)] pub fn chain( parameter: &TH::Parameter, epoch: u32, diff --git a/src/symmetric/tweak_hash_tree.rs b/src/symmetric/tweak_hash_tree.rs index 00b1065..3e8f702 100644 --- a/src/symmetric/tweak_hash_tree.rs +++ b/src/symmetric/tweak_hash_tree.rs @@ -562,6 +562,7 @@ where /// Function to compute a Merkle authentication path from a tree that is /// splitted into top tree and bottom trees. +#[must_use] pub fn combined_path( top_tree: &HashSubTree, bottom_tree: &HashSubTree, From 0ccadec7f91beadea8db0d59ac9151f3756d32d6 Mon Sep 17 00:00:00 2001 From: Tom Wambsgans Date: Fri, 12 Dec 2025 23:12:19 +0100 Subject: [PATCH 3/3] use "view" functions (unmutable ref) instead of exposing the fields completely in GeneralizedXMSSSignature / GeneralizedXMSSPublicKey --- src/signature/generalized_xmss.rs | 34 ++++++++++++++++++++++++++----- src/symmetric/tweak_hash.rs | 6 ++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/signature/generalized_xmss.rs b/src/signature/generalized_xmss.rs index 2ae4e2e..872f827 100644 --- a/src/signature/generalized_xmss.rs +++ b/src/signature/generalized_xmss.rs @@ -43,9 +43,23 @@ pub struct GeneralizedXMSSSignatureScheme< #[derive(Serialize, Deserialize, Clone)] #[serde(bound = "")] pub struct GeneralizedXMSSSignature { - pub path: HashTreeOpening, - pub rho: IE::Randomness, - pub hashes: Vec, + path: HashTreeOpening, + rho: IE::Randomness, + hashes: Vec, +} + +impl GeneralizedXMSSSignature { + pub const fn path(&self) -> &HashTreeOpening { + &self.path + } + + pub const fn rho(&self) -> &IE::Randomness { + &self.rho + } + + pub const fn hashes(&self) -> &Vec { + &self.hashes + } } impl Encode for GeneralizedXMSSSignature { @@ -176,8 +190,18 @@ impl Decode for GeneralizedXMSSSign /// It contains a Merkle root and a parameter for the tweakable hash #[derive(Serialize, Deserialize, Clone)] pub struct GeneralizedXMSSPublicKey { - pub root: TH::Domain, - pub parameter: TH::Parameter, + root: TH::Domain, + parameter: TH::Parameter, +} + +impl GeneralizedXMSSPublicKey { + pub const fn root(&self) -> &TH::Domain { + &self.root + } + + pub const fn parameter(&self) -> &TH::Parameter { + &self.parameter + } } /// Secret key for GeneralizedXMSSSignatureScheme diff --git a/src/symmetric/tweak_hash.rs b/src/symmetric/tweak_hash.rs index 5ae342e..46275b8 100644 --- a/src/symmetric/tweak_hash.rs +++ b/src/symmetric/tweak_hash.rs @@ -1,5 +1,3 @@ -use std::fmt::Debug; - use rand::Rng; use crate::serialization::Serializable; @@ -22,10 +20,10 @@ pub trait TweakableHash { type Parameter: Copy + Send + Sync + Serializable; /// Tweak type for domain separation - type Tweak: Debug; + type Tweak; /// Domain element type (defines output and input types to the hash) - type Domain: Copy + PartialEq + Send + Sync + Serializable + Debug; + type Domain: Copy + PartialEq + Send + Sync + Serializable; /// Generates a random public parameter. fn rand_parameter(rng: &mut R) -> Self::Parameter;