Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Refinements to VRF types #14036

Merged
merged 19 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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
16 changes: 8 additions & 8 deletions client/consensus/babe/src/authorship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use sc_consensus_epochs::Epoch as EpochT;
use sp_application_crypto::AppCrypto;
use sp_consensus_babe::{
digests::{PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest},
make_transcript, AuthorityId, BabeAuthorityWeight, Randomness, Slot,
make_vrf_input, AuthorityId, BabeAuthorityWeight, Randomness, Slot,
};
use sp_core::{
blake2_256,
Expand Down Expand Up @@ -148,9 +148,9 @@ fn claim_secondary_slot(
for (authority_id, authority_index) in keys {
if authority_id == expected_author {
let pre_digest = if author_secondary_vrf {
let transcript = make_transcript(randomness, slot, epoch_index);
let vrf_input = make_vrf_input(randomness, slot, epoch_index);
let result =
keystore.sr25519_vrf_sign(AuthorityId::ID, authority_id.as_ref(), &transcript);
keystore.sr25519_vrf_sign(AuthorityId::ID, authority_id.as_ref(), &vrf_input);
if let Ok(Some(vrf_signature)) = result {
Some(PreDigest::SecondaryVRF(SecondaryVRFPreDigest {
slot,
Expand Down Expand Up @@ -239,19 +239,19 @@ fn claim_primary_slot(
epoch_index = epoch.clone_for_slot(slot).epoch_index;
}

let transcript = make_transcript(randomness, slot, epoch_index);
let vrf_input = make_vrf_input(randomness, slot, epoch_index);

for (authority_id, authority_index) in keys {
let result = keystore.sr25519_vrf_sign(AuthorityId::ID, authority_id.as_ref(), &transcript);
let result = keystore.sr25519_vrf_sign(AuthorityId::ID, authority_id.as_ref(), &vrf_input);
if let Ok(Some(vrf_signature)) = result {
let threshold = calculate_primary_threshold(c, authorities, *authority_index);

let can_claim = authority_id
.as_inner_ref()
.make_bytes::<[u8; AUTHORING_SCORE_LENGTH]>(
.output_bytes::<[u8; AUTHORING_SCORE_LENGTH]>(
AUTHORING_SCORE_VRF_CONTEXT,
&transcript,
&vrf_signature.output,
&vrf_input,
&vrf_signature.preout,
)
.map(|bytes| u128::from_le_bytes(bytes) < threshold)
.unwrap_or_default();
Expand Down
27 changes: 13 additions & 14 deletions client/consensus/babe/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ use sc_network_test::{Block as TestBlock, *};
use sp_application_crypto::key_types::BABE;
use sp_consensus::{DisableProofRecording, NoNetwork as DummyOracle, Proposal};
use sp_consensus_babe::{
inherents::InherentDataProvider, make_transcript, AllowedSlots, AuthorityId, AuthorityPair,
Slot,
inherents::InherentDataProvider, make_vrf_input, AllowedSlots, AuthorityId, AuthorityPair, Slot,
};
use sp_consensus_slots::SlotDuration;
use sp_core::crypto::Pair;
Expand Down Expand Up @@ -630,24 +629,24 @@ fn claim_vrf_check() {
PreDigest::Primary(d) => d,
v => panic!("Unexpected pre-digest variant {:?}", v),
};
let transcript = make_transcript(&epoch.randomness.clone(), 0.into(), epoch.epoch_index);
let vrf_input = make_vrf_input(&epoch.randomness.clone(), 0.into(), epoch.epoch_index);
let sign = keystore
.sr25519_vrf_sign(AuthorityId::ID, &public, &transcript)
.sr25519_vrf_sign(AuthorityId::ID, &public, &vrf_input)
.unwrap()
.unwrap();
assert_eq!(pre_digest.vrf_signature.output, sign.output);
assert_eq!(pre_digest.vrf_signature.preout, sign.preout);

// We expect a SecondaryVRF claim for slot 1
let pre_digest = match claim_slot(1.into(), &epoch, &keystore).unwrap().0 {
PreDigest::SecondaryVRF(d) => d,
v => panic!("Unexpected pre-digest variant {:?}", v),
};
let transcript = make_transcript(&epoch.randomness.clone(), 1.into(), epoch.epoch_index);
let vrf_input = make_vrf_input(&epoch.randomness.clone(), 1.into(), epoch.epoch_index);
let sign = keystore
.sr25519_vrf_sign(AuthorityId::ID, &public, &transcript)
.sr25519_vrf_sign(AuthorityId::ID, &public, &vrf_input)
.unwrap()
.unwrap();
assert_eq!(pre_digest.vrf_signature.output, sign.output);
assert_eq!(pre_digest.vrf_signature.preout, sign.preout);

// Check that correct epoch index has been used if epochs are skipped (primary VRF)
let slot = Slot::from(103);
Expand All @@ -656,13 +655,13 @@ fn claim_vrf_check() {
v => panic!("Unexpected claim variant {:?}", v),
};
let fixed_epoch = epoch.clone_for_slot(slot);
let transcript = make_transcript(&epoch.randomness.clone(), slot, fixed_epoch.epoch_index);
let vrf_input = make_vrf_input(&epoch.randomness.clone(), slot, fixed_epoch.epoch_index);
let sign = keystore
.sr25519_vrf_sign(AuthorityId::ID, &public, &transcript)
.sr25519_vrf_sign(AuthorityId::ID, &public, &vrf_input)
davxy marked this conversation as resolved.
Show resolved Hide resolved
.unwrap()
.unwrap();
assert_eq!(fixed_epoch.epoch_index, 11);
assert_eq!(claim.vrf_signature.output, sign.output);
assert_eq!(claim.vrf_signature.preout, sign.preout);

// Check that correct epoch index has been used if epochs are skipped (secondary VRF)
let slot = Slot::from(100);
Expand All @@ -671,13 +670,13 @@ fn claim_vrf_check() {
v => panic!("Unexpected claim variant {:?}", v),
};
let fixed_epoch = epoch.clone_for_slot(slot);
let transcript = make_transcript(&epoch.randomness.clone(), slot, fixed_epoch.epoch_index);
let vrf_input = make_vrf_input(&epoch.randomness.clone(), slot, fixed_epoch.epoch_index);
let sign = keystore
.sr25519_vrf_sign(AuthorityId::ID, &public, &transcript)
.sr25519_vrf_sign(AuthorityId::ID, &public, &vrf_input)
.unwrap()
.unwrap();
assert_eq!(fixed_epoch.epoch_index, 11);
assert_eq!(pre_digest.vrf_signature.output, sign.output);
assert_eq!(pre_digest.vrf_signature.preout, sign.preout);
}

// Propose and import a new BABE block on top of the given parent.
Expand Down
18 changes: 9 additions & 9 deletions client/consensus/babe/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ use sp_consensus_babe::{
CompatibleDigestItem, PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest,
SecondaryVRFPreDigest,
},
make_transcript, AuthorityId, AuthorityPair, AuthoritySignature,
make_vrf_input, AuthorityId, AuthorityPair, AuthoritySignature,
};
use sp_consensus_slots::Slot;
use sp_core::{
crypto::{VrfVerifier, Wraps},
crypto::{VrfPublic, Wraps},
Pair,
};
use sp_runtime::{traits::Header, DigestItem};
Expand Down Expand Up @@ -171,9 +171,9 @@ fn check_primary_header<B: BlockT + Sized>(
return Err(babe_err(Error::BadSignature(pre_hash)))
}

let transcript = make_transcript(&epoch.randomness, pre_digest.slot, epoch_index);
let vrf_input = make_vrf_input(&epoch.randomness, pre_digest.slot, epoch_index);

if !authority_id.as_inner_ref().vrf_verify(&transcript, &pre_digest.vrf_signature) {
if !authority_id.as_inner_ref().vrf_verify(&vrf_input, &pre_digest.vrf_signature) {
return Err(babe_err(Error::VrfVerificationFailed))
}

Expand All @@ -182,10 +182,10 @@ fn check_primary_header<B: BlockT + Sized>(

let score = authority_id
.as_inner_ref()
.make_bytes::<[u8; AUTHORING_SCORE_LENGTH]>(
.output_bytes::<[u8; AUTHORING_SCORE_LENGTH]>(
AUTHORING_SCORE_VRF_CONTEXT,
&transcript,
&pre_digest.vrf_signature.output,
&vrf_input,
&pre_digest.vrf_signature.preout,
)
.map(u128::from_le_bytes)
.map_err(|_| babe_err(Error::VrfVerificationFailed))?;
Expand Down Expand Up @@ -253,9 +253,9 @@ fn check_secondary_vrf_header<B: BlockT>(
return Err(Error::BadSignature(pre_hash))
}

let transcript = make_transcript(&epoch.randomness, pre_digest.slot, epoch_index);
let vrf_input = make_vrf_input(&epoch.randomness, pre_digest.slot, epoch_index);

if !author.as_inner_ref().vrf_verify(&transcript, &pre_digest.vrf_signature) {
if !author.as_inner_ref().vrf_verify(&vrf_input, &pre_digest.vrf_signature) {
return Err(Error::VrfVerificationFailed)
}

Expand Down
35 changes: 29 additions & 6 deletions client/keystore/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use parking_lot::RwLock;
use sp_application_crypto::{AppCrypto, AppPair, IsWrappedBy};
use sp_core::{
crypto::{ByteArray, ExposeSecret, KeyTypeId, Pair as CorePair, SecretString, VrfSigner},
crypto::{ByteArray, ExposeSecret, KeyTypeId, Pair as CorePair, SecretString, VrfSecret},
ecdsa, ed25519, sr25519,
};
use sp_keystore::{Error as TraitError, Keystore, KeystorePtr};
Expand Down Expand Up @@ -98,19 +98,33 @@ impl LocalKeystore {
Ok(signature)
}

fn vrf_sign<T: CorePair + VrfSigner>(
fn vrf_sign<T: CorePair + VrfSecret>(
&self,
key_type: KeyTypeId,
public: &T::Public,
transcript: &T::VrfInput,
input: &T::VrfInput,
) -> std::result::Result<Option<T::VrfSignature>, TraitError> {
let sig = self
.0
.read()
.key_pair_by_type::<T>(public, key_type)?
.map(|pair| pair.vrf_sign(transcript));
.map(|pair| pair.vrf_sign(input));
Ok(sig)
}

fn vrf_preout<T: CorePair + VrfSecret>(
&self,
key_type: KeyTypeId,
public: &T::Public,
input: &T::VrfInput,
) -> std::result::Result<Option<T::VrfPreOutput>, TraitError> {
let preout = self
.0
.read()
.key_pair_by_type::<T>(public, key_type)?
.map(|pair| pair.vrf_preout(input));
Ok(preout)
}
}

impl Keystore for LocalKeystore {
Expand Down Expand Up @@ -142,9 +156,18 @@ impl Keystore for LocalKeystore {
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
transcript: &sr25519::vrf::VrfTranscript,
input: &sr25519::vrf::VrfInput,
) -> std::result::Result<Option<sr25519::vrf::VrfSignature>, TraitError> {
self.vrf_sign::<sr25519::Pair>(key_type, public, transcript)
self.vrf_sign::<sr25519::Pair>(key_type, public, input)
}

fn sr25519_vrf_preout(
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
input: &sr25519::vrf::VrfInput,
) -> std::result::Result<Option<sr25519::vrf::VrfPreOutput>, TraitError> {
self.vrf_preout::<sr25519::Pair>(key_type, public, input)
davxy marked this conversation as resolved.
Show resolved Hide resolved
}

fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec<ed25519::Public> {
Expand Down
12 changes: 6 additions & 6 deletions frame/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ pub mod pallet {
.get(authority_index as usize)
.and_then(|(authority, _)| {
let public = authority.as_inner_ref();
let transcript = sp_consensus_babe::make_transcript(
let vrf_input = sp_consensus_babe::make_vrf_input(
&Self::randomness(),
CurrentSlot::<T>::get(),
EpochIndex::<T>::get(),
Expand All @@ -372,15 +372,15 @@ pub mod pallet {
// execution. We don't run the verification again here to avoid slowing
// down the runtime.
debug_assert!({
use sp_core::crypto::VrfVerifier;
public.vrf_verify(&transcript, &vrf_signature)
use sp_core::crypto::VrfPublic;
public.vrf_verify(&vrf_input, &vrf_signature)
});

public
.make_bytes(
.output_bytes(
RANDOMNESS_VRF_CONTEXT,
&transcript,
&vrf_signature.output,
&vrf_input,
&vrf_signature.preout,
)
.ok()
});
Expand Down
10 changes: 5 additions & 5 deletions frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use frame_support::{
use pallet_session::historical as pallet_session_historical;
use sp_consensus_babe::{AuthorityId, AuthorityPair, Randomness, Slot, VrfSignature};
use sp_core::{
crypto::{KeyTypeId, Pair, VrfSigner},
crypto::{KeyTypeId, Pair, VrfSecret},
H256, U256,
};
use sp_io;
Expand Down Expand Up @@ -314,17 +314,17 @@ pub fn make_secondary_vrf_pre_digest(
Digest { logs: vec![log] }
}

pub fn make_vrf_output(
pub fn make_vrf_signature_and_output(
slot: Slot,
pair: &sp_consensus_babe::AuthorityPair,
) -> (VrfSignature, Randomness) {
let transcript = sp_consensus_babe::make_transcript(&Babe::randomness(), slot, 0);
let vrf_input = sp_consensus_babe::make_vrf_input(&Babe::randomness(), slot, 0);

let signature = pair.as_ref().vrf_sign(&transcript);
let signature = pair.as_ref().vrf_sign(&vrf_input);

let randomness = pair
.as_ref()
.make_bytes::<Randomness>(sp_consensus_babe::RANDOMNESS_VRF_CONTEXT, &transcript);
.output_bytes::<Randomness>(sp_consensus_babe::RANDOMNESS_VRF_CONTEXT, &vrf_input);

(signature, randomness)
}
Expand Down
9 changes: 6 additions & 3 deletions frame/babe/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ fn first_block_epoch_zero_start() {

ext.execute_with(|| {
let genesis_slot = Slot::from(100);
let (vrf_signature, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
let (vrf_signature, vrf_randomness) =
make_vrf_signature_and_output(genesis_slot, &pairs[0]);

let pre_digest = make_primary_pre_digest(0, genesis_slot, vrf_signature);

Expand Down Expand Up @@ -111,7 +112,8 @@ fn current_slot_is_processed_on_initialization() {

ext.execute_with(|| {
let genesis_slot = Slot::from(10);
let (vrf_signature, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
let (vrf_signature, vrf_randomness) =
make_vrf_signature_and_output(genesis_slot, &pairs[0]);
let pre_digest = make_primary_pre_digest(0, genesis_slot, vrf_signature);

System::reset_events();
Expand Down Expand Up @@ -140,7 +142,8 @@ where

ext.execute_with(|| {
let genesis_slot = Slot::from(10);
let (vrf_signature, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
let (vrf_signature, vrf_randomness) =
make_vrf_signature_and_output(genesis_slot, &pairs[0]);
let pre_digest = make_pre_digest(0, genesis_slot, vrf_signature);

System::reset_events();
Expand Down
8 changes: 4 additions & 4 deletions primitives/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use sp_std::vec::Vec;

use crate::digests::{NextConfigDescriptor, NextEpochDescriptor};

pub use sp_core::sr25519::vrf::{VrfOutput, VrfProof, VrfSignature, VrfTranscript};
pub use sp_core::sr25519::vrf::{VrfInput, VrfPreOutput, VrfProof, VrfSignature};

/// Key type for BABE module.
pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_application_crypto::key_types::BABE;
Expand Down Expand Up @@ -94,9 +94,9 @@ pub type BabeAuthorityWeight = u64;
/// of 0 (regardless of whether they are plain or vrf secondary blocks).
pub type BabeBlockWeight = u32;

/// Make a VRF transcript data container
pub fn make_transcript(randomness: &Randomness, slot: Slot, epoch: u64) -> VrfTranscript {
VrfTranscript::new(
/// Make VRF input suitable for BABE's randomness generation.
pub fn make_vrf_input(randomness: &Randomness, slot: Slot, epoch: u64) -> VrfInput {
VrfInput::new(
&BABE_ENGINE_ID,
&[
(b"slot number", &slot.to_le_bytes()),
Expand Down
22 changes: 13 additions & 9 deletions primitives/core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,21 +1094,25 @@ impl<'a> TryFrom<&'a str> for KeyTypeId {

/// Trait grouping types shared by a VRF signer and verifiers.
pub trait VrfCrypto {
/// VRF input data.
type VrfInput;
/// VRF pre-output generated from input data.
type VrfPreOutput;
/// Associated signature type.
type VrfSignature;

/// Vrf input data. Generally some form of transcript.
type VrfInput;
}

/// VRF Signer.
pub trait VrfSigner: VrfCrypto {
/// Sign input data.
fn vrf_sign(&self, data: &Self::VrfInput) -> Self::VrfSignature;
/// VRF Secret Key.
pub trait VrfSecret: VrfCrypto {
/// Get VRF pre-output.
fn vrf_preout(&self, data: &Self::VrfInput) -> Self::VrfPreOutput;

/// Sign input data with optional pre-computed pre-output.
fn vrf_sign(&self, input: &Self::VrfInput) -> Self::VrfSignature;
}

/// VRF Verifier.
pub trait VrfVerifier: VrfCrypto {
/// VRF Public Key.
pub trait VrfPublic: VrfCrypto {
/// Verify input data signature.
fn vrf_verify(&self, data: &Self::VrfInput, signature: &Self::VrfSignature) -> bool;
}
Expand Down
Loading