Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/demo_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ impl GenerateVerifiable for Trivial {
type Commitment = (Self::Member, Vec<Self::Member>);
type Proof = [u8; 32];
type Signature = [u8; 32];
type AccStep = ();
type StaticChunk = ();

fn is_member_valid(_member: &Self::Member) -> bool {
Expand Down Expand Up @@ -49,6 +50,15 @@ impl GenerateVerifiable for Trivial {
secret.clone()
}

fn batch_step(
_proof: &Self::Proof,
_members: &Self::Members,
_context: &[u8],
_message: &[u8],
) -> Self::AccStep {
()
}

fn open(
member: &Self::Member,
members: impl Iterator<Item = Self::Member>,
Expand Down Expand Up @@ -117,6 +127,7 @@ impl GenerateVerifiable for Simple {
type Commitment = (Self::Member, Vec<Self::Member>);
type Proof = ([u8; 64], Alias);
type Signature = [u8; 64];
type AccStep = ();
type StaticChunk = ();

fn is_member_valid(_member: &Self::Member) -> bool {
Expand Down Expand Up @@ -151,6 +162,15 @@ impl GenerateVerifiable for Simple {
pair.public.to_bytes()
}

fn batch_step(
_proof: &Self::Proof,
_members: &Self::Members,
_context: &[u8],
_message: &[u8],
) -> Self::AccStep {
()
}

fn open(
member: &Self::Member,
members: impl Iterator<Item = Self::Member>,
Expand Down
26 changes: 26 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ pub trait GenerateVerifiable {
/// A signature, creatable from a `Secret` for a message and which can be verified as valid
/// with respect to the corresponding `Member`.
type Signature: Clone + Eq + PartialEq + FullCodec + Debug + TypeInfo;
/// A multi-proof fragment which can be verified in a batch with other such fragments. It is
/// generated using a proof along with the data necessary to verify it in a context (the root of
/// the ring in which it was created, the context and the message).
type AccStep: Clone + Eq + PartialEq + FullCodec + Debug + TypeInfo;

type StaticChunk: Clone + Eq + PartialEq + FullCodec + Debug + TypeInfo + MaxEncodedLen;

Expand Down Expand Up @@ -137,6 +141,16 @@ pub trait GenerateVerifiable {
message: &[u8],
) -> Result<(Self::Proof, Alias), ()>;

/// Generate a batch verification step out of a proof and the information needed to verify it
/// independently. The result of this operation should be used in a batch verification operation
/// along with other such steps.
fn batch_step(
_proof: &Self::Proof,
_members: &Self::Members,
_context: &[u8],
_message: &[u8],
) -> Self::AccStep;

/// Make a non-anonymous signature of `message` using `secret`.
fn sign(_secret: &Self::Secret, _message: &[u8]) -> Result<Self::Signature, ()> {
Err(())
Expand Down Expand Up @@ -171,6 +185,18 @@ pub trait GenerateVerifiable {
Err(())
}

/// Check whether all of the proofs in this batch are valid, returning the `Alias` for each one,
/// in order of input.
fn batch_validate(_steps: Vec<Self::AccStep>) -> Result<Vec<Alias>, ()> {
Err(())
}

/// Check whether all of the proofs in this batch are valid and that the resulting `Alias` is
/// the same as the one provided as input.
fn batch_is_valid(_steps: Vec<(Self::AccStep, Alias)>) -> bool {
false
}

fn verify_signature(
_signature: &Self::Signature,
_message: &[u8],
Expand Down
48 changes: 43 additions & 5 deletions src/ring_vrf_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,8 @@ fn make_alias(output: &bandersnatch::Output) -> Alias {
pub struct BandersnatchVrfVerifiable;

impl BandersnatchVrfVerifiable {
fn to_public_key(
value: &EncodedPublicKey,
) -> Result<PublicKey, ()> {
let pt =
bandersnatch::AffinePoint::deserialize_compressed(&value.0[..]).map_err(|_| ())?;
fn to_public_key(value: &EncodedPublicKey) -> Result<PublicKey, ()> {
let pt = bandersnatch::AffinePoint::deserialize_compressed(&value.0[..]).map_err(|_| ())?;
Ok(PublicKey(pt.into()))
}

Expand All @@ -199,6 +196,7 @@ impl GenerateVerifiable for BandersnatchVrfVerifiable {
type Commitment = (u32, ArkScale<bandersnatch::RingProverKey>);
type Proof = [u8; RING_VRF_SIGNATURE_SIZE];
type Signature = [u8; PLAIN_VRF_SIGNATURE_SIZE];
type AccStep = (Self::Proof, Self::Members, Vec<u8>, Vec<u8>);
type StaticChunk = StaticChunk;

fn start_members() -> Self::Intermediate {
Expand Down Expand Up @@ -243,6 +241,20 @@ impl GenerateVerifiable for BandersnatchVrfVerifiable {
Self::to_encoded_public_key(&PublicKey(secret.public().0))
}

fn batch_step(
proof: &Self::Proof,
members: &Self::Members,
context: &[u8],
message: &[u8],
) -> Self::AccStep {
(
proof.clone(),
members.clone(),
context.to_vec(),
message.to_vec(),
)
}

fn validate(
proof: &Self::Proof,
members: &Self::Members,
Expand Down Expand Up @@ -272,6 +284,32 @@ impl GenerateVerifiable for BandersnatchVrfVerifiable {
Ok(make_alias(&signature.output))
}

fn batch_validate(steps: Vec<Self::AccStep>) -> Result<Vec<Alias>, ()> {
let mut aliases = Vec::with_capacity(steps.len());
for (proof, members, context, message) in steps.into_iter() {
aliases.push(Self::validate(
&proof,
&members,
&context[..],
&message[..],
)?);
}
Ok(aliases)
}

fn batch_is_valid(steps: Vec<(Self::AccStep, Alias)>) -> bool {
let proofs = steps.iter().map(|x| x.0.clone()).collect();
let Ok(aliases) = Self::batch_validate(proofs) else {
return false;
};
for (actual, expected) in aliases.iter().zip(steps.iter().map(|x| x.1)) {
if *actual != expected {
return false;
}
}
true
}

fn sign(secret: &Self::Secret, message: &[u8]) -> Result<Self::Signature, ()> {
use ark_vrf::ietf::Prover;
let input_msg = [VRF_INPUT_DOMAIN, message].concat();
Expand Down