Skip to content

Conversation

@damrobi
Copy link
Collaborator

@damrobi damrobi commented Jan 19, 2026

Content

This PR includes changes to the stm library, more specifically to the merkle tree, protocol and proof system modules.

Pre-submit checklist

  • Branch
    • Tests are provided (if possible)
    • Crates versions are updated (if relevant)
    • CHANGELOG file is updated (if relevant)
    • Commit sequence broadly makes sense
    • Key commits have useful messages
  • PR
    • All check jobs of the CI have succeeded
    • Self-reviewed the diff
    • Useful pull request description
    • Reviewer requested
  • Documentation
    • Update README file (if relevant)
    • Update documentation website (if relevant)
    • No new TODOs introduced

Comments

Issue(s)

Relates to #2792

merkle_tree_commitment: MerkleTreeBatchCommitment<D::SnarkHash, MerkleTreeSnarkLeaf>,
}

impl<D: MembershipDigest> AggregateVerificationKeyForSnark<D> {

Check warning

Code scanning / clippy

method get_merkle_tree_commitment is never used Warning

method get_merkle_tree_commitment is never used
merkle_tree_commitment: MerkleTreeBatchCommitment<D::SnarkHash, MerkleTreeSnarkLeaf>,
}

impl<D: MembershipDigest> AggregateVerificationKeyForSnark<D> {

Check warning

Code scanning / clippy

method get_merkle_tree_commitment is never used Warning

method get_merkle_tree_commitment is never used
@github-actions
Copy link

github-actions bot commented Jan 19, 2026

Test Results

    4 files  ±0    169 suites  ±0   23m 35s ⏱️ + 1m 26s
2 322 tests ±0  2 322 ✅ ±0  0 💤 ±0  0 ❌ ±0 
7 311 runs  ±0  7 311 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit b5d320a. ± Comparison against base commit 1bd88b8.

♻️ This comment has been updated with latest results.

…move batch and changed type of EligibilityValue

impl<D: MembershipDigest> AggregateVerificationKeyForSnark<D> {
/// Get the Merkle tree batch commitment.
pub(crate) fn get_merkle_tree_commitment(

Check warning

Code scanning / clippy

method get_merkle_tree_commitment is never used Warning

method get_merkle_tree_commitment is never used

impl<D: MembershipDigest> AggregateVerificationKeyForSnark<D> {
/// Get the Merkle tree batch commitment.
pub(crate) fn get_merkle_tree_commitment(

Check warning

Code scanning / clippy

method get_merkle_tree_commitment is never used Warning

method get_merkle_tree_commitment is never used
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds key registration support for pre-aggregation primitives by introducing a Snark proof system alongside the existing Concatenation proof system. The changes rename the "Future" variant to "Snark" throughout the codebase and implement the foundational structures needed for Snark-based aggregation.

Changes:

  • Renamed "Future" to "Snark" across all proof system enums and types for better clarity
  • Added Hash trait implementation for SchnorrVerificationKey to support its use in merkle trees
  • Introduced new Snark-specific types: AggregateVerificationKeyForSnark, MerkleTreeSnarkLeaf, VerificationKeyForSnark, and EligibilityValue

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
signature_scheme/unique_schnorr_signature/verification_key.rs Adds Hash trait implementation for SchnorrVerificationKey
protocol/mod.rs Introduces VerificationKeyForSnark type alias
protocol/aggregate_signature/signature.rs Renames Future variant to Snark in AggregateSignatureType and AggregateSignature enums
protocol/aggregate_signature/clerk.rs Updates clerk to reference Snark instead of Future
protocol/aggregate_signature/aggregate_key.rs Implements Snark variant for AggregateVerificationKey with serialization support
proof_system/mod.rs Exports new halo2_snark module and its types
proof_system/halo2_snark/mod.rs Creates new module structure for Snark proof system
proof_system/halo2_snark/aggregate_key.rs Implements AggregateVerificationKeyForSnark with merkle tree commitment
membership_commitment/merkle_tree/leaf.rs Adds MerkleTreeSnarkLeaf for Snark-based merkle trees
lib.rs Exports new Snark types and defines EligibilityValue

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +84 to +85
/// The values that are committed in the Merkle Tree for `ConcatenationProof`.
/// Namely, a verified `BlsVerificationKey` and its corresponding stake.
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation comment incorrectly refers to both ConcatenationProof and BlsVerificationKey. This struct is for the Snark proof system (not Concatenation) and uses SchnorrVerificationKey (not BLS). The comment should be updated to accurately describe that this is used for the Snark proof system with Schnorr verification keys and eligibility values.

Suggested change
/// The values that are committed in the Merkle Tree for `ConcatenationProof`.
/// Namely, a verified `BlsVerificationKey` and its corresponding stake.
/// The values that are committed in the Merkle Tree for the Snark proof system.
/// Namely, a verified `SchnorrVerificationKey` and its corresponding eligibility value.

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +87
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct MerkleTreeSnarkLeaf(pub VerificationKeyForSnark, pub EligibilityValue);
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MerkleTreeSnarkLeaf struct lacks PartialOrd and Ord implementations that are present in MerkleTreeConcatenationLeaf. Given that both structures serve similar purposes (merkle tree leaves with verification keys and values), and that ordering is important for batch opening efficiency as explained in MerkleTreeConcatenationLeaf's documentation, MerkleTreeSnarkLeaf should also implement these traits.

Copilot uses AI. Check for mistakes.
}

impl<D: MembershipDigest> AggregateVerificationKeyForSnark<D> {
/// Get the Merkle tree batch commitment.
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "Get the Merkle tree batch commitment" but the method name is get_merkle_tree_commitment and returns a MerkleTreeCommitment, not a batch commitment. The documentation should be corrected to accurately describe what is being returned.

Suggested change
/// Get the Merkle tree batch commitment.
/// Get the Merkle tree commitment.

Copilot uses AI. Check for mistakes.

bytes
}

Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The from_bytes method is missing documentation. Public methods should have doc comments explaining their purpose, parameters, return values, and potential errors.

Suggested change
/// Reconstruct an aggregate verification key for Snark from its byte representation.
///
/// # Parameters
///
/// - `bytes`: A byte slice containing the serialized form of this key, as produced by
/// [`AggregateVerificationKeyForSnark::to_bytes`].
///
/// # Returns
///
/// Returns an [`AggregateVerificationKeyForSnark`] instance on success.
///
/// # Errors
///
/// Returns an error if `bytes` do not encode a valid underlying
/// [`MerkleTreeCommitment`] and deserialization fails.

Copilot uses AI. Check for mistakes.
}
#[cfg(feature = "future_snark")]
AggregateVerificationKey::Future => vec![],
AggregateVerificationKey::Snark(_) => vec![],
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The to_bytes method for AggregateVerificationKey::Snark returns an empty vector, which is inconsistent with the corresponding from_bytes implementation that expects actual data. This asymmetry will cause deserialization to fail or produce incorrect results. The Snark variant should serialize its underlying AggregateVerificationKeyForSnark data.

Suggested change
AggregateVerificationKey::Snark(_) => vec![],
AggregateVerificationKey::Snark(snark_aggregate_verification_key) => {
snark_aggregate_verification_key.to_bytes()
}

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +126
#[cfg(feature = "future_snark")]
/// The values that are committed in the Merkle Tree for `ConcatenationProof`.
/// Namely, a verified `BlsVerificationKey` and its corresponding stake.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct MerkleTreeSnarkLeaf(pub VerificationKeyForSnark, pub EligibilityValue);

#[cfg(feature = "future_snark")]
impl MerkleTreeLeaf for MerkleTreeSnarkLeaf {
fn as_bytes_for_merkle_tree(&self) -> Vec<u8> {
self.to_bytes()
}
}

#[cfg(feature = "future_snark")]
impl MerkleTreeSnarkLeaf {
fn to_bytes(self) -> Vec<u8> {
let mut result = [0u8; 64];
result[..32].copy_from_slice(&self.0.to_bytes());
result[32..].copy_from_slice(&self.1.to_bytes_le());
result.to_vec()
}

// TODO: remove this allow dead_code directive when function is called or future_snark is activated
#[allow(dead_code)]
pub(crate) fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
if bytes.len() < 32 {
return Err(anyhow!(MerkleTreeError::SerializationError)).with_context(
|| "Not enough bytes provided to construct a Merkle tree leaf for Snark.",
);
}
let schnorr_verification_key = VerificationKeyForSnark::from_bytes(&bytes[..32])
.map_err(|_| MerkleTreeError::SerializationError)?;
let mut u64_bytes = [0u8; 32];
u64_bytes.copy_from_slice(&bytes[32..]);
let eligibility_value = match EligibilityValue::from_bytes_le(&u64_bytes).into_option() {
Some(base_field_element) => Ok(base_field_element),
None => Err(anyhow!(MerkleTreeError::SerializationError)),
}?;
Ok(MerkleTreeSnarkLeaf(
schnorr_verification_key,
eligibility_value,
))
}
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MerkleTreeSnarkLeaf struct and its methods (to_bytes, from_bytes) lack test coverage. Given that similar functionality for MerkleTreeConcatenationLeaf is tested in the merkle tree test suite, this new leaf type should also include tests to verify serialization/deserialization behavior and the Hash trait implementation.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +36
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggregateVerificationKeyForSnark<D: MembershipDigest> {
merkle_tree_commitment: MerkleTreeCommitment<D::SnarkHash, MerkleTreeSnarkLeaf>,
}

impl<D: MembershipDigest> AggregateVerificationKeyForSnark<D> {
/// Get the Merkle tree batch commitment.
pub(crate) fn get_merkle_tree_commitment(
&self,
) -> MerkleTreeCommitment<D::SnarkHash, MerkleTreeSnarkLeaf> {
self.merkle_tree_commitment.clone()
}

/// Convert the aggregate verification key for Snark to bytes.
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.extend(self.merkle_tree_commitment.to_bytes());

bytes
}

pub fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
let size = bytes.len();
let merkle_tree_commitment = MerkleTreeCommitment::from_bytes(&bytes[0..size])?;
Ok(Self {
merkle_tree_commitment,
})
}
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new AggregateVerificationKeyForSnark struct and its methods (to_bytes, from_bytes, get_merkle_tree_commitment) lack test coverage. Given that similar structs like AggregateVerificationKeyForConcatenation have comprehensive tests, this new functionality should also include tests to verify serialization/deserialization and other behaviors.

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +111
if bytes.len() < 32 {
return Err(anyhow!(MerkleTreeError::SerializationError)).with_context(
|| "Not enough bytes provided to construct a Merkle tree leaf for Snark.",
);
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The from_bytes method checks if bytes.len() < 32 but then tries to copy 32 bytes from bytes[32..] without verifying that there are at least 64 bytes available. This could cause a panic if the slice is between 32 and 64 bytes. The validation should check for bytes.len() < 64 instead.

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +31
let size = bytes.len();
let merkle_tree_commitment = MerkleTreeCommitment::from_bytes(&bytes[0..size])?;
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The slice operation &bytes[0..size] is redundant since it's equivalent to just bytes. The entire byte slice is being passed to from_bytes, making the explicit slicing unnecessary.

Suggested change
let size = bytes.len();
let merkle_tree_commitment = MerkleTreeCommitment::from_bytes(&bytes[0..size])?;
let merkle_tree_commitment = MerkleTreeCommitment::from_bytes(bytes)?;

Copilot uses AI. Check for mistakes.
@curiecrypt curiecrypt force-pushed the curiecrypt/msnark/key-registration branch 3 times, most recently from 037d8b7 to b097651 Compare January 23, 2026 10:00
Base automatically changed from curiecrypt/msnark/key-registration to main January 23, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants