Skip to content

Generic Ring backend#27

Merged
davxy merged 24 commits intomainfrom
davxy/generic-bandersnatch
Feb 19, 2026
Merged

Generic Ring backend#27
davxy merged 24 commits intomainfrom
davxy/generic-bandersnatch

Conversation

@davxy
Copy link
Member

@davxy davxy commented Dec 12, 2025

Major refactory:

  • RingSuiteExt: Enables easy integration of alternative implementations, such as those backed by polkadot-sdk hostcalls (see draft: Bandersnatch with EC hostcalls polkadot-sdk#10259).

  • RingCurveData: Centralizes pairing-curve-specific data. Bandersnatch uses BLS12-381, which can also be reused by other curves (i.e. bandersnatch alternatives hosted by BLS12-381), as well as by third-party Bandersnatch implementations (e.g., the polkadot-sdk hostcall-based version mentioned above).

  • RingProofParamsCache: Supports multiple strategies for caching pre-built parameters.

  • Bandersnatch concrete implementation (based on suite provided by ark-vrf)

  • Codebase reorganization

@davxy davxy force-pushed the davxy/generic-bandersnatch branch from e660c7a to 27129a6 Compare February 5, 2026 12:07
@davxy davxy changed the title Generic Bandersnatch suite Generic Ring backend Feb 5, 2026
@davxy davxy marked this pull request as ready for review February 5, 2026 17:58
@burdges
Copy link

burdges commented Feb 6, 2026

I wrote cleaner traits for EC VRFs and EC ring VRFs here :
https://github.com/paritytech/ring-vrf/blob/master/dleq_vrf/src/traits.rs

In particular, they handle multiple input-output pairs better, which many ring VRF protocols require.

@davxy
Copy link
Member Author

davxy commented Feb 6, 2026

I wrote cleaner traits for EC VRFs and EC ring VRFs here : https://github.com/paritytech/ring-vrf/blob/master/dleq_vrf/src/traits.rs

In particular, they handle multiple input-output pairs better, which many ring VRF protocols require.

Perhaps this is not related to this PR :-)

In this PR, we make the Verifiable trait generic over the specific Bandersnatch implementation. This enables the use of the implementation backed by the host calls we are currently working on.

Copy link
Member

@ggwpez ggwpez left a comment

Choose a reason for hiding this comment

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

Is it rebased? GH wont show me

use crate::ring::{Bls12_381RingData, RingSuiteExt, RingVrfVerifiable};
use ark_vrf::suites::bandersnatch::{BandersnatchSha512Ell2, RingProofParams};

#[cfg(any(feature = "std", feature = "no-std-prover"))]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
#[cfg(any(feature = "std", feature = "no-std-prover"))]
#[cfg(feature = "prover")]

And then enable that by feature std.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense


/// Tests that require the `builder-params` feature.
#[cfg(all(test, feature = "builder-params"))]
mod builder_tests {
Copy link
Member

Choose a reason for hiding this comment

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

Could put into bandersnatch_tests.rs file or so

Copy link
Member Author

Choose a reason for hiding this comment

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

In that case, I would also be inclined to move the entire set of Bandersnatch-related tests (the mod test above) into that file. However, why move the tests to a separate file? The current module does not appear particularly cluttered.

type Handle = alloc::boxed::Box<ark_vrf::ring::RingProofParams<S>>;

fn get(domain_size: RingDomainSize) -> Self::Handle {
alloc::boxed::Box::new(make_ring_prover_params::<S>(domain_size))
Copy link
Member

Choose a reason for hiding this comment

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

The decoding is not cached with a Once cell anymore?

Copy link
Member Author

Choose a reason for hiding this comment

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

I introduced RingProofParamsCache as an associated type of the RingSuiteExt trait.

We provide two concrete implementations of this trait:

  • () : This is the implementation you observed. It performs no parameter caching. Perhaps I can define a NullCache type, which may be more explicit.
  • BandersnatchParamsCache : Defined in the bandersnatch.rs module. It implements caching similarly to the previous approach, except that it uses the spin crate for both std and no_std environments.

This abstraction enables users to define a custom caching strategy if the default implementations provided by the crate do not meet their requirements

Copy link
Member

Choose a reason for hiding this comment

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

Okay makes sense, thanks. I must have missed it in the review.

Copy link
Contributor

Choose a reason for hiding this comment

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

I support calling it NullCache or NoCache or anything like that.

@davxy
Copy link
Member Author

davxy commented Feb 13, 2026

Is it rebased? GH wont show me

I force-pushed 🫣
Effectively, I just reused the branch name, as the current code is very different from the previous PR.

@davxy davxy requested a review from ggwpez February 13, 2026 21:19
@davxy davxy requested a review from ggwpez February 17, 2026 09:07
@davxy
Copy link
Member Author

davxy commented Feb 18, 2026

@ggwpez @georgepisaltu As I'd like to move forward, If there are no objections by tomorrow, I will proceed with merging this.

Copy link
Contributor

@georgepisaltu georgepisaltu left a comment

Choose a reason for hiding this comment

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

Sorry for the late review. Just a couple of comments, but looks good.

type Handle = alloc::boxed::Box<ark_vrf::ring::RingProofParams<S>>;

fn get(domain_size: RingDomainSize) -> Self::Handle {
alloc::boxed::Box::new(make_ring_prover_params::<S>(domain_size))
Copy link
Contributor

Choose a reason for hiding this comment

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

I support calling it NullCache or NoCache or anything like that.

src/ring/mod.rs Outdated
}

pub trait EncodedTypesBounds:
Clone + Eq + FullCodec + core::fmt::Debug + TypeInfo + MaxEncodedLen + AsRef<[u8]> + AsMut<[u8]>
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we also add DecodeWithMemTracking since this will be used in the runtime? It's not covered by FullCodec.

src/ring/mod.rs Outdated

#[inline(always)]
fn make_alias<S: RingSuiteExt>(output: &ark_vrf::Output<S>) -> Alias {
Alias::try_from(&output.hash()[..32]).expect("Suite hash should be at least 32 bytes")
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically this will panic when you try to access the slice like &output.hash()[..32] before we get to the try_from. There's not much of a difference even if we write this differently and guard against it, but maybe we can statically check with a test or something that the hash output on the ark_vrf::Output<S> we use is at least 32 bytes?

@davxy davxy merged commit a304016 into main Feb 19, 2026
1 check passed
@davxy davxy deleted the davxy/generic-bandersnatch branch February 19, 2026 11:03
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

Comments