sp-core: Rename VrfOutput to VrfPreOutput (#2534)

This will make more sense after
https://github.com/paritytech/polkadot-sdk/pull/2524 since the
schnorrkel type for VRF outputs is also renamed in the latest version.
Can be reviewed independently though.

Can be merged after https://github.com/paritytech/polkadot-sdk/pull/1577
so that there is less pain for @davxy.

---------

Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
André Silva
2023-12-06 00:19:56 +00:00
committed by GitHub
parent 91cbe087de
commit 1f023deab8
19 changed files with 193 additions and 172 deletions
@@ -18,7 +18,8 @@
use super::*;
use crate::backend::Backend;
use polkadot_node_primitives::approval::v1::{
AssignmentCert, AssignmentCertKind, VrfOutput, VrfProof, VrfSignature, RELAY_VRF_MODULO_CONTEXT,
AssignmentCert, AssignmentCertKind, VrfPreOutput, VrfProof, VrfSignature,
RELAY_VRF_MODULO_CONTEXT,
};
use polkadot_node_subsystem_util::database::Database;
use sp_application_crypto::sp_core::H256;
@@ -30,9 +31,12 @@ fn dummy_assignment_cert(kind: AssignmentCertKind) -> AssignmentCert {
let mut prng = rand_core::OsRng;
let keypair = schnorrkel::Keypair::generate_with(&mut prng);
let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg));
let out = inout.to_output();
let preout = inout.to_output();
AssignmentCert { kind, vrf: VrfSignature { output: VrfOutput(out), proof: VrfProof(proof) } }
AssignmentCert {
kind,
vrf: VrfSignature { pre_output: VrfPreOutput(preout), proof: VrfProof(proof) },
}
}
fn make_block_entry_v1(
@@ -21,7 +21,9 @@ use parity_scale_codec::{Decode, Encode};
use polkadot_node_primitives::approval::{
self as approval_types,
v1::{AssignmentCert, AssignmentCertKind, DelayTranche, RelayVRFStory},
v2::{AssignmentCertKindV2, AssignmentCertV2, CoreBitfield, VrfOutput, VrfProof, VrfSignature},
v2::{
AssignmentCertKindV2, AssignmentCertV2, CoreBitfield, VrfPreOutput, VrfProof, VrfSignature,
},
};
use polkadot_primitives::{
AssignmentId, AssignmentPair, CandidateHash, CoreIndex, GroupIndex, IndexedVec, SessionInfo,
@@ -459,7 +461,7 @@ fn compute_relay_vrf_modulo_assignments_v1(
let cert = AssignmentCert {
kind: AssignmentCertKind::RelayVRFModulo { sample: rvm_sample },
vrf: VrfSignature {
output: VrfOutput(vrf_in_out.to_output()),
pre_output: VrfPreOutput(vrf_in_out.to_output()),
proof: VrfProof(vrf_proof),
},
};
@@ -539,7 +541,7 @@ fn compute_relay_vrf_modulo_assignments_v2(
core_bitfield: assignment_bitfield.clone(),
},
vrf: VrfSignature {
output: VrfOutput(vrf_in_out.to_output()),
pre_output: VrfPreOutput(vrf_in_out.to_output()),
proof: VrfProof(vrf_proof),
},
};
@@ -574,7 +576,7 @@ fn compute_relay_vrf_delay_assignments(
let cert = AssignmentCertV2 {
kind: AssignmentCertKindV2::RelayVRFDelay { core_index: core },
vrf: VrfSignature {
output: VrfOutput(vrf_in_out.to_output()),
pre_output: VrfPreOutput(vrf_in_out.to_output()),
proof: VrfProof(vrf_proof),
},
};
@@ -689,7 +691,7 @@ pub(crate) fn check_assignment_cert(
}
}
let vrf_output = &assignment.vrf.output;
let vrf_pre_output = &assignment.vrf.pre_output;
let vrf_proof = &assignment.vrf.proof;
let first_claimed_core_index =
claimed_core_indices.first_one().expect("Checked above; qed") as u32;
@@ -704,7 +706,7 @@ pub(crate) fn check_assignment_cert(
let (vrf_in_out, _) = public
.vrf_verify_extra(
relay_vrf_modulo_transcript_v2(relay_vrf_story),
&vrf_output.0,
&vrf_pre_output.0,
&vrf_proof.0,
assigned_cores_transcript(core_bitfield),
)
@@ -753,7 +755,7 @@ pub(crate) fn check_assignment_cert(
let (vrf_in_out, _) = public
.vrf_verify_extra(
relay_vrf_modulo_transcript_v1(relay_vrf_story, *sample),
&vrf_output.0,
&vrf_pre_output.0,
&vrf_proof.0,
assigned_core_transcript(CoreIndex(first_claimed_core_index)),
)
@@ -791,7 +793,7 @@ pub(crate) fn check_assignment_cert(
let (vrf_in_out, _) = public
.vrf_verify(
relay_vrf_delay_transcript(relay_vrf_story, *core_index),
&vrf_output.0,
&vrf_pre_output.0,
&vrf_proof.0,
)
.map_err(|_| InvalidAssignment(Reason::VRFDelayOutputMismatch))?;
@@ -20,7 +20,7 @@ use crate::backend::V1ReadBackend;
use polkadot_node_primitives::{
approval::{
v1::{
AssignmentCert, AssignmentCertKind, DelayTranche, VrfOutput, VrfProof, VrfSignature,
AssignmentCert, AssignmentCertKind, DelayTranche, VrfPreOutput, VrfProof, VrfSignature,
RELAY_VRF_MODULO_CONTEXT,
},
v2::{AssignmentCertKindV2, AssignmentCertV2},
@@ -415,9 +415,12 @@ fn garbage_assignment_cert(kind: AssignmentCertKind) -> AssignmentCert {
let mut prng = rand_core::OsRng;
let keypair = schnorrkel::Keypair::generate_with(&mut prng);
let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg));
let out = inout.to_output();
let preout = inout.to_output();
AssignmentCert { kind, vrf: VrfSignature { output: VrfOutput(out), proof: VrfProof(proof) } }
AssignmentCert {
kind,
vrf: VrfSignature { pre_output: VrfPreOutput(preout), proof: VrfProof(proof) },
}
}
fn garbage_assignment_cert_v2(kind: AssignmentCertKindV2) -> AssignmentCertV2 {
@@ -426,9 +429,12 @@ fn garbage_assignment_cert_v2(kind: AssignmentCertKindV2) -> AssignmentCertV2 {
let mut prng = rand_core::OsRng;
let keypair = schnorrkel::Keypair::generate_with(&mut prng);
let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg));
let out = inout.to_output();
let preout = inout.to_output();
AssignmentCertV2 { kind, vrf: VrfSignature { output: VrfOutput(out), proof: VrfProof(proof) } }
AssignmentCertV2 {
kind,
vrf: VrfSignature { pre_output: VrfPreOutput(preout), proof: VrfProof(proof) },
}
}
fn sign_approval(
@@ -25,7 +25,7 @@ use polkadot_node_network_protocol::{
};
use polkadot_node_primitives::approval::{
v1::{
AssignmentCert, AssignmentCertKind, IndirectAssignmentCert, VrfOutput, VrfProof,
AssignmentCert, AssignmentCertKind, IndirectAssignmentCert, VrfPreOutput, VrfProof,
VrfSignature,
},
v2::{
@@ -298,14 +298,14 @@ fn fake_assignment_cert(block_hash: Hash, validator: ValidatorIndex) -> Indirect
let mut prng = rand_core::OsRng;
let keypair = schnorrkel::Keypair::generate_with(&mut prng);
let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg));
let out = inout.to_output();
let preout = inout.to_output();
IndirectAssignmentCert {
block_hash,
validator,
cert: AssignmentCert {
kind: AssignmentCertKind::RelayVRFModulo { sample: 1 },
vrf: VrfSignature { output: VrfOutput(out), proof: VrfProof(proof) },
vrf: VrfSignature { pre_output: VrfPreOutput(preout), proof: VrfProof(proof) },
},
}
}
@@ -320,14 +320,14 @@ fn fake_assignment_cert_v2(
let mut prng = rand_core::OsRng;
let keypair = schnorrkel::Keypair::generate_with(&mut prng);
let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg));
let out = inout.to_output();
let preout = inout.to_output();
IndirectAssignmentCertV2 {
block_hash,
validator,
cert: AssignmentCertV2 {
kind: AssignmentCertKindV2::RelayVRFModuloCompact { core_bitfield },
vrf: VrfSignature { output: VrfOutput(out), proof: VrfProof(proof) },
vrf: VrfSignature { pre_output: VrfPreOutput(preout), proof: VrfProof(proof) },
},
}
}
+10 -10
View File
@@ -20,7 +20,7 @@
pub mod v1 {
use sp_consensus_babe as babe_primitives;
pub use sp_consensus_babe::{
Randomness, Slot, VrfOutput, VrfProof, VrfSignature, VrfTranscript,
Randomness, Slot, VrfPreOutput, VrfProof, VrfSignature, VrfTranscript,
};
use parity_scale_codec::{Decode, Encode};
@@ -145,14 +145,14 @@ pub mod v1 {
AuthorityOutOfBounds(usize),
}
/// An unsafe VRF output. Provide BABE Epoch info to create a `RelayVRFStory`.
pub struct UnsafeVRFOutput {
vrf_output: VrfOutput,
/// An unsafe VRF pre-output. Provide BABE Epoch info to create a `RelayVRFStory`.
pub struct UnsafeVRFPreOutput {
vrf_pre_output: VrfPreOutput,
slot: Slot,
authority_index: u32,
}
impl UnsafeVRFOutput {
impl UnsafeVRFPreOutput {
/// Get the slot.
pub fn slot(&self) -> Slot {
self.slot
@@ -177,7 +177,7 @@ pub mod v1 {
sp_consensus_babe::make_vrf_transcript(randomness, self.slot, epoch_index);
let inout = self
.vrf_output
.vrf_pre_output
.0
.attach_input_hash(&pubkey, transcript.0)
.map_err(ApprovalError::SchnorrkelSignature)?;
@@ -190,7 +190,7 @@ pub mod v1 {
/// This fails if either there is no BABE `PreRuntime` digest or
/// the digest has type `SecondaryPlain`, which Substrate nodes do
/// not produce or accept anymore.
pub fn babe_unsafe_vrf_info(header: &Header) -> Option<UnsafeVRFOutput> {
pub fn babe_unsafe_vrf_info(header: &Header) -> Option<UnsafeVRFPreOutput> {
use babe_primitives::digests::CompatibleDigestItem;
for digest in &header.digest.logs {
@@ -198,8 +198,8 @@ pub mod v1 {
let slot = pre.slot();
let authority_index = pre.authority_index();
return pre.vrf_signature().map(|sig| UnsafeVRFOutput {
vrf_output: sig.output.clone(),
return pre.vrf_signature().map(|sig| UnsafeVRFPreOutput {
vrf_pre_output: sig.pre_output.clone(),
slot,
authority_index,
})
@@ -214,7 +214,7 @@ pub mod v1 {
pub mod v2 {
use parity_scale_codec::{Decode, Encode};
pub use sp_consensus_babe::{
Randomness, Slot, VrfOutput, VrfProof, VrfSignature, VrfTranscript,
Randomness, Slot, VrfPreOutput, VrfProof, VrfSignature, VrfTranscript,
};
use std::ops::BitOr;
@@ -249,7 +249,7 @@ fn claim_primary_slot(
.make_bytes::<AUTHORING_SCORE_LENGTH>(
AUTHORING_SCORE_VRF_CONTEXT,
&data.as_ref(),
&vrf_signature.output,
&vrf_signature.pre_output,
)
.map(|bytes| u128::from_le_bytes(bytes) < threshold)
.unwrap_or_default();
+4 -4
View File
@@ -580,7 +580,7 @@ fn claim_vrf_check() {
};
let data = make_vrf_sign_data(&epoch.randomness.clone(), 0.into(), epoch.epoch_index);
let sign = keystore.sr25519_vrf_sign(AuthorityId::ID, &public, &data).unwrap().unwrap();
assert_eq!(pre_digest.vrf_signature.output, sign.output);
assert_eq!(pre_digest.vrf_signature.pre_output, sign.pre_output);
// We expect a SecondaryVRF claim for slot 1
let pre_digest = match claim_slot(1.into(), &epoch, &keystore).unwrap().0 {
@@ -589,7 +589,7 @@ fn claim_vrf_check() {
};
let data = make_vrf_sign_data(&epoch.randomness.clone(), 1.into(), epoch.epoch_index);
let sign = keystore.sr25519_vrf_sign(AuthorityId::ID, &public, &data).unwrap().unwrap();
assert_eq!(pre_digest.vrf_signature.output, sign.output);
assert_eq!(pre_digest.vrf_signature.pre_output, sign.pre_output);
// Check that correct epoch index has been used if epochs are skipped (primary VRF)
let slot = Slot::from(103);
@@ -601,7 +601,7 @@ fn claim_vrf_check() {
let data = make_vrf_sign_data(&epoch.randomness.clone(), slot, fixed_epoch.epoch_index);
let sign = keystore.sr25519_vrf_sign(AuthorityId::ID, &public, &data).unwrap().unwrap();
assert_eq!(fixed_epoch.epoch_index, 11);
assert_eq!(claim.vrf_signature.output, sign.output);
assert_eq!(claim.vrf_signature.pre_output, sign.pre_output);
// Check that correct epoch index has been used if epochs are skipped (secondary VRF)
let slot = Slot::from(100);
@@ -613,7 +613,7 @@ fn claim_vrf_check() {
let data = make_vrf_sign_data(&epoch.randomness.clone(), slot, fixed_epoch.epoch_index);
let sign = keystore.sr25519_vrf_sign(AuthorityId::ID, &public, &data).unwrap().unwrap();
assert_eq!(fixed_epoch.epoch_index, 11);
assert_eq!(pre_digest.vrf_signature.output, sign.output);
assert_eq!(pre_digest.vrf_signature.pre_output, sign.pre_output);
}
// Propose and import a new BABE block on top of the given parent.
@@ -185,7 +185,7 @@ fn check_primary_header<B: BlockT + Sized>(
.make_bytes::<AUTHORING_SCORE_LENGTH>(
AUTHORING_SCORE_VRF_CONTEXT,
&data.as_ref(),
&pre_digest.vrf_signature.output,
&pre_digest.vrf_signature.pre_output,
)
.map(u128::from_le_bytes)
.map_err(|_| babe_err(Error::VrfVerificationFailed))?;
+11 -11
View File
@@ -120,18 +120,18 @@ impl LocalKeystore {
Ok(sig)
}
fn vrf_output<T: CorePair + VrfSecret>(
fn vrf_pre_output<T: CorePair + VrfSecret>(
&self,
key_type: KeyTypeId,
public: &T::Public,
input: &T::VrfInput,
) -> std::result::Result<Option<T::VrfOutput>, TraitError> {
let preout = self
) -> std::result::Result<Option<T::VrfPreOutput>, TraitError> {
let pre_output = self
.0
.read()
.key_pair_by_type::<T>(public, key_type)?
.map(|pair| pair.vrf_output(input));
Ok(preout)
.map(|pair| pair.vrf_pre_output(input));
Ok(pre_output)
}
}
@@ -188,13 +188,13 @@ impl Keystore for LocalKeystore {
self.vrf_sign::<sr25519::Pair>(key_type, public, data)
}
fn sr25519_vrf_output(
fn sr25519_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
input: &sr25519::vrf::VrfInput,
) -> std::result::Result<Option<sr25519::vrf::VrfOutput>, TraitError> {
self.vrf_output::<sr25519::Pair>(key_type, public, input)
) -> std::result::Result<Option<sr25519::vrf::VrfPreOutput>, TraitError> {
self.vrf_pre_output::<sr25519::Pair>(key_type, public, input)
}
fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec<ed25519::Public> {
@@ -293,13 +293,13 @@ impl Keystore for LocalKeystore {
self.vrf_sign::<bandersnatch::Pair>(key_type, public, data)
}
fn bandersnatch_vrf_output(
fn bandersnatch_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &bandersnatch::Public,
input: &bandersnatch::vrf::VrfInput,
) -> std::result::Result<Option<bandersnatch::vrf::VrfOutput>, TraitError> {
self.vrf_output::<bandersnatch::Pair>(key_type, public, input)
) -> std::result::Result<Option<bandersnatch::vrf::VrfPreOutput>, TraitError> {
self.vrf_pre_output::<bandersnatch::Pair>(key_type, public, input)
}
fn bandersnatch_ring_vrf_sign(
+5 -1
View File
@@ -384,7 +384,11 @@ pub mod pallet {
});
public
.make_bytes(RANDOMNESS_VRF_CONTEXT, &transcript, &signature.output)
.make_bytes(
RANDOMNESS_VRF_CONTEXT,
&transcript,
&signature.pre_output,
)
.ok()
});
+11 -11
View File
@@ -272,11 +272,11 @@ pub mod pallet {
#[pallet::storage]
pub type RingVerifierData<T: Config> = StorageValue<_, vrf::RingVerifierData>;
/// Slot claim vrf-preoutput used to generate per-slot randomness.
/// Slot claim VRF pre-output used to generate per-slot randomness.
///
/// The value is ephemeral and is cleared on block finalization.
#[pallet::storage]
pub(crate) type ClaimTemporaryData<T> = StorageValue<_, vrf::VrfOutput>;
pub(crate) type ClaimTemporaryData<T> = StorageValue<_, vrf::VrfPreOutput>;
/// Genesis configuration for Sassafras protocol.
#[pallet::genesis_config]
@@ -324,12 +324,12 @@ pub mod pallet {
Self::post_genesis_initialize(claim.slot);
}
let randomness_output = claim
let randomness_pre_output = claim
.vrf_signature
.outputs
.pre_outputs
.get(0)
.expect("Valid claim must have vrf signature; qed");
ClaimTemporaryData::<T>::put(randomness_output);
.expect("Valid claim must have VRF signature; qed");
ClaimTemporaryData::<T>::put(randomness_pre_output);
let trigger_weight = T::EpochChangeTrigger::trigger::<T>(block_num);
@@ -346,9 +346,9 @@ pub mod pallet {
CurrentSlot::<T>::get(),
EpochIndex::<T>::get(),
);
let randomness_output = ClaimTemporaryData::<T>::take()
let randomness_pre_output = ClaimTemporaryData::<T>::take()
.expect("Unconditionally populated in `on_initialize`; `on_finalize` is always called after; qed");
let randomness = randomness_output
let randomness = randomness_pre_output
.make_bytes::<RANDOMNESS_LENGTH>(RANDOMNESS_VRF_CONTEXT, &randomness_input);
Self::deposit_slot_randomness(&randomness);
@@ -422,15 +422,15 @@ pub mod pallet {
for ticket in tickets {
debug!(target: LOG_TARGET, "Checking ring proof");
let Some(ticket_id_output) = ticket.signature.outputs.get(0) else {
debug!(target: LOG_TARGET, "Missing ticket vrf output from ring signature");
let Some(ticket_id_pre_output) = ticket.signature.pre_outputs.get(0) else {
debug!(target: LOG_TARGET, "Missing ticket VRF pre-output from ring signature");
continue
};
let ticket_id_input =
vrf::ticket_id_input(&randomness, ticket.body.attempt_idx, epoch_idx);
// Check threshold constraint
let ticket_id = vrf::make_ticket_id(&ticket_id_input, &ticket_id_output);
let ticket_id = vrf::make_ticket_id(&ticket_id_input, &ticket_id_pre_output);
if ticket_id >= ticket_threshold {
debug!(target: LOG_TARGET, "Ignoring ticket over threshold ({:032x} >= {:032x})", ticket_id, ticket_threshold);
continue
+2 -2
View File
@@ -190,9 +190,9 @@ pub fn make_ticket_body(attempt_idx: u32, pair: &AuthorityPair) -> (TicketId, Ti
let randomness = Sassafras::next_randomness();
let ticket_id_input = vrf::ticket_id_input(&randomness, attempt_idx, epoch);
let ticket_id_output = pair.as_inner_ref().vrf_output(&ticket_id_input);
let ticket_id_pre_output = pair.as_inner_ref().vrf_pre_output(&ticket_id_input);
let id = vrf::make_ticket_id(&ticket_id_input, &ticket_id_output);
let id = vrf::make_ticket_id(&ticket_id_input, &ticket_id_pre_output);
// Make a dummy ephemeral public that hopefully is unique within one test instance.
// In the tests, the values within the erased public are just used to compare
@@ -33,7 +33,7 @@ use sp_std::vec::Vec;
use crate::digests::{NextConfigDescriptor, NextEpochDescriptor};
pub use sp_core::sr25519::vrf::{
VrfInput, VrfOutput, VrfProof, VrfSignData, VrfSignature, VrfTranscript,
VrfInput, VrfPreOutput, VrfProof, VrfSignData, VrfSignature, VrfTranscript,
};
/// Key type for BABE module.
@@ -15,7 +15,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Utilities related to VRF input, output and signatures.
//! Utilities related to VRF input, pre-output and signatures.
use crate::{Randomness, TicketBody, TicketId};
use scale_codec::Encode;
@@ -24,7 +24,7 @@ use sp_std::vec::Vec;
pub use sp_core::bandersnatch::{
ring_vrf::{RingProver, RingVerifier, RingVerifierData, RingVrfSignature},
vrf::{VrfInput, VrfOutput, VrfSignData, VrfSignature},
vrf::{VrfInput, VrfPreOutput, VrfSignData, VrfSignature},
};
/// Ring VRF domain size for Sassafras consensus.
@@ -90,21 +90,21 @@ pub fn ticket_body_sign_data(ticket_body: &TicketBody, ticket_id_input: VrfInput
)
}
/// Make ticket-id from the given VRF input and output.
/// Make ticket-id from the given VRF input and pre-output.
///
/// Input should have been obtained via [`ticket_id_input`].
/// Output should have been obtained from the input directly using the vrf secret key
/// or from the vrf signature outputs.
pub fn make_ticket_id(input: &VrfInput, output: &VrfOutput) -> TicketId {
let bytes = output.make_bytes::<16>(b"ticket-id", input);
/// Pre-output should have been obtained from the input directly using the vrf
/// secret key or from the vrf signature pre-outputs.
pub fn make_ticket_id(input: &VrfInput, pre_output: &VrfPreOutput) -> TicketId {
let bytes = pre_output.make_bytes::<16>(b"ticket-id", input);
u128::from_le_bytes(bytes)
}
/// Make revealed key seed from a given VRF input and ouput.
/// Make revealed key seed from a given VRF input and pre-ouput.
///
/// Input should have been obtained via [`revealed_key_input`].
/// Output should have been obtained from the input directly using the vrf secret key
/// or from the vrf signature outputs.
pub fn make_revealed_key_seed(input: &VrfInput, output: &VrfOutput) -> [u8; 32] {
output.make_bytes::<32>(b"revealed-seed", input)
/// Pre-output should have been obtained from the input directly using the vrf
/// secret key or from the vrf signature pre-outputs.
pub fn make_revealed_key_seed(input: &VrfInput, pre_output: &VrfPreOutput) -> [u8; 32] {
pre_output.make_bytes::<32>(b"revealed-seed", input)
}
+44 -42
View File
@@ -295,7 +295,7 @@ impl TraitPair for Pair {
fn verify<M: AsRef<[u8]>>(signature: &Signature, data: M, public: &Public) -> bool {
let data = vrf::VrfSignData::new_unchecked(SIGNING_CTX, &[data.as_ref()], None);
let signature =
vrf::VrfSignature { signature: *signature, outputs: vrf::VrfIosVec::default() };
vrf::VrfSignature { signature: *signature, pre_outputs: vrf::VrfIosVec::default() };
public.vrf_verify(&data, &signature)
}
@@ -319,18 +319,18 @@ pub mod vrf {
ThinVrfSignature, Transcript,
};
/// Max number of inputs/outputs which can be handled by the VRF signing procedures.
/// Max number of inputs/pre-outputs which can be handled by the VRF signing procedures.
///
/// The number is quite arbitrary and chosen to fulfill the use cases found so far.
/// If required it can be extended in the future.
pub const MAX_VRF_IOS: u32 = 3;
/// Bounded vector used for VRF inputs and outputs.
/// Bounded vector used for VRF inputs and pre-outputs.
///
/// Can contain at most [`MAX_VRF_IOS`] elements.
pub type VrfIosVec<T> = BoundedVec<T, ConstU32<MAX_VRF_IOS>>;
/// VRF input to construct a [`VrfOutput`] instance and embeddable in [`VrfSignData`].
/// VRF input to construct a [`VrfPreOutput`] instance and embeddable in [`VrfSignData`].
#[derive(Clone, Debug)]
pub struct VrfInput(pub(super) bandersnatch_vrfs::VrfInput);
@@ -342,15 +342,15 @@ pub mod vrf {
}
}
/// VRF (pre)output derived from [`VrfInput`] using a [`VrfSecret`].
/// VRF pre-output derived from [`VrfInput`] using a [`VrfSecret`].
///
/// This object is used to produce an arbitrary number of verifiable pseudo random
/// bytes and is often called pre-output to emphasize that this is not the actual
/// output of the VRF but an object capable of generating the output.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VrfOutput(pub(super) bandersnatch_vrfs::VrfPreOut);
pub struct VrfPreOutput(pub(super) bandersnatch_vrfs::VrfPreOut);
impl Encode for VrfOutput {
impl Encode for VrfPreOutput {
fn encode(&self) -> Vec<u8> {
let mut bytes = [0; PREOUT_SERIALIZED_SIZE];
self.0
@@ -360,25 +360,25 @@ pub mod vrf {
}
}
impl Decode for VrfOutput {
impl Decode for VrfPreOutput {
fn decode<R: codec::Input>(i: &mut R) -> Result<Self, codec::Error> {
let buf = <[u8; PREOUT_SERIALIZED_SIZE]>::decode(i)?;
let preout =
bandersnatch_vrfs::VrfPreOut::deserialize_compressed_unchecked(buf.as_slice())
.map_err(|_| "vrf-preout decode error: bad preout")?;
Ok(VrfOutput(preout))
Ok(VrfPreOutput(preout))
}
}
impl EncodeLike for VrfOutput {}
impl EncodeLike for VrfPreOutput {}
impl MaxEncodedLen for VrfOutput {
impl MaxEncodedLen for VrfPreOutput {
fn max_encoded_len() -> usize {
<[u8; PREOUT_SERIALIZED_SIZE]>::max_encoded_len()
}
}
impl TypeInfo for VrfOutput {
impl TypeInfo for VrfPreOutput {
type Identity = [u8; PREOUT_SERIALIZED_SIZE];
fn type_info() -> scale_info::Type {
@@ -395,14 +395,14 @@ pub mod vrf {
/// A good explaination of the topic can be found in Merlin [docs](https://merlin.cool/)
///
/// The `inputs` is a sequence of [`VrfInput`]s which, during the signing procedure, are
/// first transformed to [`VrfOutput`]s. Both inputs and outputs are then appended to
/// first transformed to [`VrfPreOutput`]s. Both inputs and pre-outputs are then appended to
/// the transcript before signing the Fiat-Shamir transform result (the challenge).
///
/// In practice, as a user, all these technical details can be easily ignored.
/// What is important to remember is:
/// - *Transcript* is an object defining the protocol and used to produce the signature. This
/// object doesn't influence the `VrfOutput`s values.
/// - *Vrf inputs* is some additional data which is used to produce *vrf outputs*. This data
/// object doesn't influence the `VrfPreOutput`s values.
/// - *Vrf inputs* is some additional data which is used to produce *vrf pre-outputs*. This data
/// will contribute to the signature as well.
#[derive(Clone)]
pub struct VrfSignData {
@@ -473,7 +473,7 @@ pub mod vrf {
/// VRF signature.
///
/// Includes both the transcript `signature` and the `outputs` generated from the
/// Includes both the transcript `signature` and the `pre-outputs` generated from the
/// [`VrfSignData::inputs`].
///
/// Refer to [`VrfSignData`] for more details.
@@ -481,14 +481,14 @@ pub mod vrf {
pub struct VrfSignature {
/// Transcript signature.
pub signature: Signature,
/// VRF (pre)outputs.
pub outputs: VrfIosVec<VrfOutput>,
/// VRF pre-outputs.
pub pre_outputs: VrfIosVec<VrfPreOutput>,
}
#[cfg(feature = "full_crypto")]
impl VrfCrypto for Pair {
type VrfInput = VrfInput;
type VrfOutput = VrfOutput;
type VrfPreOutput = VrfPreOutput;
type VrfSignData = VrfSignData;
type VrfSignature = VrfSignature;
}
@@ -507,15 +507,15 @@ pub mod vrf {
}
}
fn vrf_output(&self, input: &Self::VrfInput) -> Self::VrfOutput {
let output = self.secret.vrf_preout(&input.0);
VrfOutput(output)
fn vrf_pre_output(&self, input: &Self::VrfInput) -> Self::VrfPreOutput {
let pre_output = self.secret.vrf_preout(&input.0);
VrfPreOutput(pre_output)
}
}
impl VrfCrypto for Public {
type VrfInput = VrfInput;
type VrfOutput = VrfOutput;
type VrfPreOutput = VrfPreOutput;
type VrfSignData = VrfSignData;
type VrfSignature = VrfSignature;
}
@@ -523,12 +523,12 @@ pub mod vrf {
impl VrfPublic for Public {
fn vrf_verify(&self, data: &Self::VrfSignData, signature: &Self::VrfSignature) -> bool {
const _: () = assert!(MAX_VRF_IOS == 3, "`MAX_VRF_IOS` expected to be 3");
let outputs_len = signature.outputs.len();
if outputs_len != data.inputs.len() {
let pre_outputs_len = signature.pre_outputs.len();
if pre_outputs_len != data.inputs.len() {
return false
}
// Workaround to overcome backend signature generic over the number of IOs.
match outputs_len {
match pre_outputs_len {
0 => self.vrf_verify_gen::<0>(data, signature),
1 => self.vrf_verify_gen::<1>(data, signature),
2 => self.vrf_verify_gen::<2>(data, signature),
@@ -546,11 +546,12 @@ pub mod vrf {
let thin_signature: ThinVrfSignature<N> =
self.secret.sign_thin_vrf(data.transcript.clone(), &ios);
let outputs: Vec<_> = thin_signature.preouts.into_iter().map(VrfOutput).collect();
let outputs = VrfIosVec::truncate_from(outputs);
let pre_outputs: Vec<_> =
thin_signature.preouts.into_iter().map(VrfPreOutput).collect();
let pre_outputs = VrfIosVec::truncate_from(pre_outputs);
let mut signature =
VrfSignature { signature: Signature([0; SIGNATURE_SERIALIZED_SIZE]), outputs };
VrfSignature { signature: Signature([0; SIGNATURE_SERIALIZED_SIZE]), pre_outputs };
thin_signature
.proof
@@ -583,7 +584,7 @@ pub mod vrf {
};
let preouts: [bandersnatch_vrfs::VrfPreOut; N] =
core::array::from_fn(|i| signature.outputs[i].0);
core::array::from_fn(|i| signature.pre_outputs[i].0);
// Deserialize only the proof, the rest has already been deserialized
// This is another hack used because backend signature type is generic over
@@ -602,7 +603,7 @@ pub mod vrf {
}
}
impl VrfOutput {
impl VrfPreOutput {
/// Generate an arbitrary number of bytes from the given `context` and VRF `input`.
pub fn make_bytes<const N: usize>(
&self,
@@ -804,8 +805,8 @@ pub mod ring_vrf {
pub struct RingVrfSignature {
/// Ring signature.
pub signature: [u8; RING_SIGNATURE_SERIALIZED_SIZE],
/// VRF (pre)outputs.
pub outputs: VrfIosVec<VrfOutput>,
/// VRF pre-outputs.
pub pre_outputs: VrfIosVec<VrfPreOutput>,
}
#[cfg(feature = "full_crypto")]
@@ -838,11 +839,12 @@ pub mod ring_vrf {
bandersnatch_vrfs::RingProver { ring_prover: prover, secret: &self.secret }
.sign_ring_vrf(data.transcript.clone(), &ios);
let outputs: Vec<_> = ring_signature.preouts.into_iter().map(VrfOutput).collect();
let outputs = VrfIosVec::truncate_from(outputs);
let pre_outputs: Vec<_> =
ring_signature.preouts.into_iter().map(VrfPreOutput).collect();
let pre_outputs = VrfIosVec::truncate_from(pre_outputs);
let mut signature =
RingVrfSignature { outputs, signature: [0; RING_SIGNATURE_SERIALIZED_SIZE] };
RingVrfSignature { pre_outputs, signature: [0; RING_SIGNATURE_SERIALIZED_SIZE] };
ring_signature
.proof
@@ -860,7 +862,7 @@ pub mod ring_vrf {
/// from which the [`RingVerifier`] has been constructed.
pub fn ring_vrf_verify(&self, data: &VrfSignData, verifier: &RingVerifier) -> bool {
const _: () = assert!(MAX_VRF_IOS == 3, "`MAX_VRF_IOS` expected to be 3");
let preouts_len = self.outputs.len();
let preouts_len = self.pre_outputs.len();
if preouts_len != data.inputs.len() {
return false
}
@@ -888,7 +890,7 @@ pub mod ring_vrf {
};
let preouts: [bandersnatch_vrfs::VrfPreOut; N] =
core::array::from_fn(|i| self.outputs[i].0);
core::array::from_fn(|i| self.pre_outputs[i].0);
let signature =
bandersnatch_vrfs::RingVrfSignature { proof: vrf_signature.proof, preouts };
@@ -1038,11 +1040,11 @@ mod tests {
let signature = pair.vrf_sign(&data);
let o10 = pair.make_bytes::<32>(b"ctx1", &i1);
let o11 = signature.outputs[0].make_bytes::<32>(b"ctx1", &i1);
let o11 = signature.pre_outputs[0].make_bytes::<32>(b"ctx1", &i1);
assert_eq!(o10, o11);
let o20 = pair.make_bytes::<48>(b"ctx2", &i2);
let o21 = signature.outputs[1].make_bytes::<48>(b"ctx2", &i2);
let o21 = signature.pre_outputs[1].make_bytes::<48>(b"ctx2", &i2);
assert_eq!(o20, o21);
}
@@ -1142,11 +1144,11 @@ mod tests {
let signature = pair.ring_vrf_sign(&data, &prover);
let o10 = pair.make_bytes::<32>(b"ctx1", &i1);
let o11 = signature.outputs[0].make_bytes::<32>(b"ctx1", &i1);
let o11 = signature.pre_outputs[0].make_bytes::<32>(b"ctx1", &i1);
assert_eq!(o10, o11);
let o20 = pair.make_bytes::<48>(b"ctx2", &i2);
let o21 = signature.outputs[1].make_bytes::<48>(b"ctx2", &i2);
let o21 = signature.pre_outputs[1].make_bytes::<48>(b"ctx2", &i2);
assert_eq!(o20, o21);
}
+4 -4
View File
@@ -1109,8 +1109,8 @@ impl<'a> TryFrom<&'a str> for KeyTypeId {
pub trait VrfCrypto {
/// VRF input.
type VrfInput;
/// VRF output.
type VrfOutput;
/// VRF pre-output.
type VrfPreOutput;
/// VRF signing data.
type VrfSignData;
/// VRF signature.
@@ -1119,8 +1119,8 @@ pub trait VrfCrypto {
/// VRF Secret Key.
pub trait VrfSecret: VrfCrypto {
/// Get VRF-specific output .
fn vrf_output(&self, data: &Self::VrfInput) -> Self::VrfOutput;
/// Get VRF-specific pre-output.
fn vrf_pre_output(&self, data: &Self::VrfInput) -> Self::VrfPreOutput;
/// Sign VRF-specific data.
fn vrf_sign(&self, input: &Self::VrfSignData) -> Self::VrfSignature;
+27 -25
View File
@@ -628,36 +628,36 @@ pub mod vrf {
/// VRF signature data
#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
pub struct VrfSignature {
/// VRF output.
pub output: VrfOutput,
/// VRF pre-output.
pub pre_output: VrfPreOutput,
/// VRF proof.
pub proof: VrfProof,
}
/// VRF output type suitable for schnorrkel operations.
/// VRF pre-output type suitable for schnorrkel operations.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VrfOutput(pub schnorrkel::vrf::VRFOutput);
pub struct VrfPreOutput(pub schnorrkel::vrf::VRFOutput);
impl Encode for VrfOutput {
impl Encode for VrfPreOutput {
fn encode(&self) -> Vec<u8> {
self.0.as_bytes().encode()
}
}
impl Decode for VrfOutput {
impl Decode for VrfPreOutput {
fn decode<R: codec::Input>(i: &mut R) -> Result<Self, codec::Error> {
let decoded = <[u8; VRF_OUTPUT_LENGTH]>::decode(i)?;
Ok(Self(schnorrkel::vrf::VRFOutput::from_bytes(&decoded).map_err(convert_error)?))
}
}
impl MaxEncodedLen for VrfOutput {
impl MaxEncodedLen for VrfPreOutput {
fn max_encoded_len() -> usize {
<[u8; VRF_OUTPUT_LENGTH]>::max_encoded_len()
}
}
impl TypeInfo for VrfOutput {
impl TypeInfo for VrfPreOutput {
type Identity = [u8; VRF_OUTPUT_LENGTH];
fn type_info() -> scale_info::Type {
@@ -699,7 +699,7 @@ pub mod vrf {
#[cfg(feature = "full_crypto")]
impl VrfCrypto for Pair {
type VrfInput = VrfTranscript;
type VrfOutput = VrfOutput;
type VrfPreOutput = VrfPreOutput;
type VrfSignData = VrfSignData;
type VrfSignature = VrfSignature;
}
@@ -717,18 +717,18 @@ pub mod vrf {
let proof = self.0.dleq_proove(extra, &inout, true).0;
VrfSignature { output: VrfOutput(inout.to_output()), proof: VrfProof(proof) }
VrfSignature { pre_output: VrfPreOutput(inout.to_output()), proof: VrfProof(proof) }
}
fn vrf_output(&self, input: &Self::VrfInput) -> Self::VrfOutput {
let output = self.0.vrf_create_hash(input.0.clone()).to_output();
VrfOutput(output)
fn vrf_pre_output(&self, input: &Self::VrfInput) -> Self::VrfPreOutput {
let pre_output = self.0.vrf_create_hash(input.0.clone()).to_output();
VrfPreOutput(pre_output)
}
}
impl VrfCrypto for Public {
type VrfInput = VrfTranscript;
type VrfOutput = VrfOutput;
type VrfPreOutput = VrfPreOutput;
type VrfSignData = VrfSignData;
type VrfSignature = VrfSignature;
}
@@ -739,7 +739,7 @@ pub mod vrf {
let public = schnorrkel::PublicKey::from_bytes(self)?;
let inout =
signature.output.0.attach_input_hash(&public, data.transcript.0.clone())?;
signature.pre_output.0.attach_input_hash(&public, data.transcript.0.clone())?;
let extra = data
.extra
@@ -802,19 +802,21 @@ pub mod vrf {
&self,
context: &[u8],
input: &VrfInput,
output: &VrfOutput,
pre_output: &VrfPreOutput,
) -> Result<[u8; N], codec::Error>
where
[u8; N]: Default,
{
let pubkey = schnorrkel::PublicKey::from_bytes(&self.0).map_err(convert_error)?;
let inout =
output.0.attach_input_hash(&pubkey, input.0.clone()).map_err(convert_error)?;
let inout = pre_output
.0
.attach_input_hash(&pubkey, input.0.clone())
.map_err(convert_error)?;
Ok(inout.make_bytes::<[u8; N]>(context))
}
}
impl VrfOutput {
impl VrfPreOutput {
/// Generate output bytes from the given VRF configuration.
pub fn make_bytes<const N: usize>(
&self,
@@ -1097,10 +1099,10 @@ mod tests {
let input = VrfTranscript::new(b"label", &[(b"domain1", b"data1")]);
let output = pair.vrf_output(&input);
let pre_output = pair.vrf_pre_output(&input);
let out1 = pair.make_bytes::<32>(ctx, &input);
let out2 = output.make_bytes::<32>(ctx, &input, &public).unwrap();
let out2 = pre_output.make_bytes::<32>(ctx, &input, &public).unwrap();
assert_eq!(out1, out2);
let extra = VrfTranscript::new(b"extra", &[(b"domain2", b"data2")]);
@@ -1108,7 +1110,7 @@ mod tests {
let signature = pair.vrf_sign(&data);
assert!(public.vrf_verify(&data, &signature));
let out3 = public.make_bytes::<32>(ctx, &input, &signature.output).unwrap();
let out3 = public.make_bytes::<32>(ctx, &input, &signature.pre_output).unwrap();
assert_eq!(out2, out3);
}
@@ -1126,7 +1128,7 @@ mod tests {
assert!(public.vrf_verify(&data, &signature));
let out1 = pair.make_bytes::<32>(ctx, &input);
let out2 = public.make_bytes::<32>(ctx, &input, &signature.output).unwrap();
let out2 = public.make_bytes::<32>(ctx, &input, &signature.pre_output).unwrap();
assert_eq!(out1, out2);
// Direct call to backend version of sign after check with extra params
@@ -1139,9 +1141,9 @@ mod tests {
})
.unwrap();
let signature2 =
VrfSignature { output: VrfOutput(inout.to_output()), proof: VrfProof(proof) };
VrfSignature { pre_output: VrfPreOutput(inout.to_output()), proof: VrfProof(proof) };
assert!(public.vrf_verify(&data, &signature2));
assert_eq!(signature.output, signature2.output);
assert_eq!(signature.pre_output, signature2.pre_output);
}
}
+12 -12
View File
@@ -92,19 +92,19 @@ pub trait Keystore: Send + Sync {
data: &sr25519::vrf::VrfSignData,
) -> Result<Option<sr25519::vrf::VrfSignature>, Error>;
/// Generate an sr25519 VRF output for a given input data.
/// Generate an sr25519 VRF pre-output for a given input data.
///
/// Receives [`KeyTypeId`] and an [`sr25519::Public`] key to be able to map
/// them to a private key that exists in the keystore.
///
/// Returns `None` if the given `key_type` and `public` combination doesn't
/// exist in the keystore or an `Err` when something failed.
fn sr25519_vrf_output(
fn sr25519_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
input: &sr25519::vrf::VrfInput,
) -> Result<Option<sr25519::vrf::VrfOutput>, Error>;
) -> Result<Option<sr25519::vrf::VrfPreOutput>, Error>;
/// Returns all ed25519 public keys for the given key type.
fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec<ed25519::Public>;
@@ -223,7 +223,7 @@ pub trait Keystore: Send + Sync {
input: &bandersnatch::vrf::VrfSignData,
) -> Result<Option<bandersnatch::vrf::VrfSignature>, Error>;
/// Generate a bandersnatch VRF (pre)output for a given input data.
/// Generate a bandersnatch VRF pre-output for a given input data.
///
/// Receives [`KeyTypeId`] and an [`bandersnatch::Public`] key to be able to map
/// them to a private key that exists in the keystore.
@@ -231,12 +231,12 @@ pub trait Keystore: Send + Sync {
/// Returns `None` if the given `key_type` and `public` combination doesn't
/// exist in the keystore or an `Err` when something failed.
#[cfg(feature = "bandersnatch-experimental")]
fn bandersnatch_vrf_output(
fn bandersnatch_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &bandersnatch::Public,
input: &bandersnatch::vrf::VrfInput,
) -> Result<Option<bandersnatch::vrf::VrfOutput>, Error>;
) -> Result<Option<bandersnatch::vrf::VrfPreOutput>, Error>;
/// Generate a bandersnatch ring-VRF signature for the given data.
///
@@ -474,13 +474,13 @@ impl<T: Keystore + ?Sized> Keystore for Arc<T> {
(**self).sr25519_vrf_sign(key_type, public, data)
}
fn sr25519_vrf_output(
fn sr25519_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
input: &sr25519::vrf::VrfInput,
) -> Result<Option<sr25519::vrf::VrfOutput>, Error> {
(**self).sr25519_vrf_output(key_type, public, input)
) -> Result<Option<sr25519::vrf::VrfPreOutput>, Error> {
(**self).sr25519_vrf_pre_output(key_type, public, input)
}
fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec<ed25519::Public> {
@@ -569,13 +569,13 @@ impl<T: Keystore + ?Sized> Keystore for Arc<T> {
}
#[cfg(feature = "bandersnatch-experimental")]
fn bandersnatch_vrf_output(
fn bandersnatch_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &bandersnatch::Public,
input: &bandersnatch::vrf::VrfInput,
) -> Result<Option<bandersnatch::vrf::VrfOutput>, Error> {
(**self).bandersnatch_vrf_output(key_type, public, input)
) -> Result<Option<bandersnatch::vrf::VrfPreOutput>, Error> {
(**self).bandersnatch_vrf_pre_output(key_type, public, input)
}
#[cfg(feature = "bandersnatch-experimental")]
+15 -14
View File
@@ -113,14 +113,14 @@ impl MemoryKeystore {
Ok(sig)
}
fn vrf_output<T: Pair + VrfSecret>(
fn vrf_pre_output<T: Pair + VrfSecret>(
&self,
key_type: KeyTypeId,
public: &T::Public,
input: &T::VrfInput,
) -> Result<Option<T::VrfOutput>, Error> {
let preout = self.pair::<T>(key_type, public).map(|pair| pair.vrf_output(input));
Ok(preout)
) -> Result<Option<T::VrfPreOutput>, Error> {
let pre_output = self.pair::<T>(key_type, public).map(|pair| pair.vrf_pre_output(input));
Ok(pre_output)
}
}
@@ -155,13 +155,13 @@ impl Keystore for MemoryKeystore {
self.vrf_sign::<sr25519::Pair>(key_type, public, data)
}
fn sr25519_vrf_output(
fn sr25519_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &sr25519::Public,
input: &sr25519::vrf::VrfInput,
) -> Result<Option<sr25519::vrf::VrfOutput>, Error> {
self.vrf_output::<sr25519::Pair>(key_type, public, input)
) -> Result<Option<sr25519::vrf::VrfPreOutput>, Error> {
self.vrf_pre_output::<sr25519::Pair>(key_type, public, input)
}
fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec<ed25519::Public> {
@@ -265,13 +265,13 @@ impl Keystore for MemoryKeystore {
}
#[cfg(feature = "bandersnatch-experimental")]
fn bandersnatch_vrf_output(
fn bandersnatch_vrf_pre_output(
&self,
key_type: KeyTypeId,
public: &bandersnatch::Public,
input: &bandersnatch::vrf::VrfInput,
) -> Result<Option<bandersnatch::vrf::VrfOutput>, Error> {
self.vrf_output::<bandersnatch::Pair>(key_type, public, input)
) -> Result<Option<bandersnatch::vrf::VrfPreOutput>, Error> {
self.vrf_pre_output::<bandersnatch::Pair>(key_type, public, input)
}
#[cfg(feature = "bls-experimental")]
@@ -443,7 +443,7 @@ mod tests {
}
#[test]
fn sr25519_vrf_output() {
fn sr25519_vrf_pre_output() {
let store = MemoryKeystore::new();
let secret_uri = "//Alice";
@@ -458,16 +458,17 @@ mod tests {
],
);
let result = store.sr25519_vrf_output(SR25519, &pair.public(), &input);
let result = store.sr25519_vrf_pre_output(SR25519, &pair.public(), &input);
assert!(result.unwrap().is_none());
store
.insert(SR25519, secret_uri, pair.public().as_ref())
.expect("Inserts unknown key");
let preout = store.sr25519_vrf_output(SR25519, &pair.public(), &input).unwrap().unwrap();
let pre_output =
store.sr25519_vrf_pre_output(SR25519, &pair.public(), &input).unwrap().unwrap();
let result = preout.make_bytes::<32>(b"rand", &input, &pair.public());
let result = pre_output.make_bytes::<32>(b"rand", &input, &pair.public());
assert!(result.is_ok());
}