Companion for Substrate #13889 (#7063)

* Companion for substrate #13889

* Remove leftover

* Remove removed dependency

* Remove sp-consensus-vrf from lock

* Revert "Remove sp-consensus-vrf from lock"

This reverts commit 2269ca1e32df89272e8fd4544292204db387f436.

* Fix after substrate modifications

* Fix tests to use new VRF Signature type

* Don't rely of Deref trait

* Fix test

* Further code simplification

* Reuse garbage_vrf_signature

* update lockfile for {"substrate"}

---------

Co-authored-by: parity-processbot <>
This commit is contained in:
Davide Galassi
2023-04-19 11:43:42 +02:00
committed by GitHub
parent bef85c32be
commit 83fb51a21c
8 changed files with 240 additions and 282 deletions
+184 -205
View File
File diff suppressed because it is too large Load Diff
@@ -356,10 +356,10 @@ fn compute_relay_vrf_modulo_assignments(
// has been executed. // has been executed.
let cert = AssignmentCert { let cert = AssignmentCert {
kind: AssignmentCertKind::RelayVRFModulo { sample: rvm_sample }, kind: AssignmentCertKind::RelayVRFModulo { sample: rvm_sample },
vrf: ( vrf: approval_types::VrfSignature {
approval_types::VRFOutput(vrf_in_out.to_output()), output: approval_types::VrfOutput(vrf_in_out.to_output()),
approval_types::VRFProof(vrf_proof), proof: approval_types::VrfProof(vrf_proof),
), },
}; };
// All assignments of type RelayVRFModulo have tranche 0. // All assignments of type RelayVRFModulo have tranche 0.
@@ -393,10 +393,10 @@ fn compute_relay_vrf_delay_assignments(
let cert = AssignmentCert { let cert = AssignmentCert {
kind: AssignmentCertKind::RelayVRFDelay { core_index: core }, kind: AssignmentCertKind::RelayVRFDelay { core_index: core },
vrf: ( vrf: approval_types::VrfSignature {
approval_types::VRFOutput(vrf_in_out.to_output()), output: approval_types::VrfOutput(vrf_in_out.to_output()),
approval_types::VRFProof(vrf_proof), proof: approval_types::VrfProof(vrf_proof),
), },
}; };
let our_assignment = OurAssignment { cert, tranche, validator_index, triggered: false }; let our_assignment = OurAssignment { cert, tranche, validator_index, triggered: false };
@@ -496,7 +496,7 @@ pub(crate) fn check_assignment_cert(
return Err(InvalidAssignment(Reason::IsInBackingGroup)) return Err(InvalidAssignment(Reason::IsInBackingGroup))
} }
let (vrf_output, vrf_proof) = &assignment.vrf; let vrf_signature = &assignment.vrf;
match assignment.kind { match assignment.kind {
AssignmentCertKind::RelayVRFModulo { sample } => { AssignmentCertKind::RelayVRFModulo { sample } => {
if sample >= config.relay_vrf_modulo_samples { if sample >= config.relay_vrf_modulo_samples {
@@ -506,8 +506,8 @@ pub(crate) fn check_assignment_cert(
let (vrf_in_out, _) = public let (vrf_in_out, _) = public
.vrf_verify_extra( .vrf_verify_extra(
relay_vrf_modulo_transcript(relay_vrf_story, sample), relay_vrf_modulo_transcript(relay_vrf_story, sample),
&vrf_output.0, &vrf_signature.output.0,
&vrf_proof.0, &vrf_signature.proof.0,
assigned_core_transcript(claimed_core_index), assigned_core_transcript(claimed_core_index),
) )
.map_err(|_| InvalidAssignment(Reason::VRFModuloOutputMismatch))?; .map_err(|_| InvalidAssignment(Reason::VRFModuloOutputMismatch))?;
@@ -527,8 +527,8 @@ pub(crate) fn check_assignment_cert(
let (vrf_in_out, _) = public let (vrf_in_out, _) = public
.vrf_verify( .vrf_verify(
relay_vrf_delay_transcript(relay_vrf_story, core_index), relay_vrf_delay_transcript(relay_vrf_story, core_index),
&vrf_output.0, &vrf_signature.output.0,
&vrf_proof.0, &vrf_signature.proof.0,
) )
.map_err(|_| InvalidAssignment(Reason::VRFDelayOutputMismatch))?; .map_err(|_| InvalidAssignment(Reason::VRFDelayOutputMismatch))?;
@@ -552,7 +552,7 @@ fn is_in_backing_group(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use polkadot_node_primitives::approval::{VRFOutput, VRFProof}; use crate::import::tests::garbage_vrf_signature;
use polkadot_primitives::{Hash, ASSIGNMENT_KEY_TYPE_ID}; use polkadot_primitives::{Hash, ASSIGNMENT_KEY_TYPE_ID};
use sp_application_crypto::sr25519; use sp_application_crypto::sr25519;
use sp_core::crypto::Pair as PairT; use sp_core::crypto::Pair as PairT;
@@ -606,15 +606,6 @@ mod tests {
.collect() .collect()
} }
// used for generating assignments where the validity of the VRF doesn't matter.
fn garbage_vrf() -> (VRFOutput, VRFProof) {
let key = Sr25519Keyring::Alice.pair();
let key: &schnorrkel::Keypair = key.as_ref();
let (o, p, _) = key.vrf_sign(Transcript::new(b"test-garbage"));
(VRFOutput(o.to_output()), VRFProof(p))
}
#[test] #[test]
fn assignments_produced_for_non_backing() { fn assignments_produced_for_non_backing() {
let keystore = make_keystore(&[Sr25519Keyring::Alice]); let keystore = make_keystore(&[Sr25519Keyring::Alice]);
@@ -825,7 +816,7 @@ mod tests {
check_mutated_assignments(40, 10, 8, |m| { check_mutated_assignments(40, 10, 8, |m| {
match m.cert.kind.clone() { match m.cert.kind.clone() {
AssignmentCertKind::RelayVRFDelay { .. } => { AssignmentCertKind::RelayVRFDelay { .. } => {
m.cert.vrf = garbage_vrf(); m.cert.vrf = garbage_vrf_signature();
Some(false) Some(false)
}, },
_ => None, // skip everything else. _ => None, // skip everything else.
@@ -838,7 +829,7 @@ mod tests {
check_mutated_assignments(200, 100, 25, |m| { check_mutated_assignments(200, 100, 25, |m| {
match m.cert.kind.clone() { match m.cert.kind.clone() {
AssignmentCertKind::RelayVRFModulo { .. } => { AssignmentCertKind::RelayVRFModulo { .. } => {
m.cert.vrf = garbage_vrf(); m.cert.vrf = garbage_vrf_signature();
Some(false) Some(false)
}, },
_ => None, // skip everything else. _ => None, // skip everything else.
@@ -612,8 +612,7 @@ pub(crate) mod tests {
use crate::approval_db::v1::DbBackend; use crate::approval_db::v1::DbBackend;
use ::test_helpers::{dummy_candidate_receipt, dummy_hash}; use ::test_helpers::{dummy_candidate_receipt, dummy_hash};
use assert_matches::assert_matches; use assert_matches::assert_matches;
use merlin::Transcript; use polkadot_node_primitives::approval::{VrfSignature, VrfTranscript};
use polkadot_node_primitives::approval::{VRFOutput, VRFProof};
use polkadot_node_subsystem::messages::{AllMessages, ApprovalVotingMessage}; use polkadot_node_subsystem::messages::{AllMessages, ApprovalVotingMessage};
use polkadot_node_subsystem_test_helpers::make_subsystem_context; use polkadot_node_subsystem_test_helpers::make_subsystem_context;
use polkadot_node_subsystem_util::database::Database; use polkadot_node_subsystem_util::database::Database;
@@ -622,7 +621,7 @@ pub(crate) mod tests {
digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest}, digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest},
AllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch, AllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch,
}; };
use sp_core::testing::TaskExecutor; use sp_core::{crypto::VrfSigner, testing::TaskExecutor};
use sp_keyring::sr25519::Keyring as Sr25519Keyring; use sp_keyring::sr25519::Keyring as Sr25519Keyring;
pub(crate) use sp_runtime::{Digest, DigestItem}; pub(crate) use sp_runtime::{Digest, DigestItem};
use std::{pin::Pin, sync::Arc}; use std::{pin::Pin, sync::Arc};
@@ -703,12 +702,9 @@ pub(crate) mod tests {
} }
// used for generating assignments where the validity of the VRF doesn't matter. // used for generating assignments where the validity of the VRF doesn't matter.
pub(crate) fn garbage_vrf() -> (VRFOutput, VRFProof) { pub(crate) fn garbage_vrf_signature() -> VrfSignature {
let key = Sr25519Keyring::Alice.pair(); let transcript = VrfTranscript::new(b"test-garbage", &[]);
let key: &schnorrkel::Keypair = key.as_ref(); Sr25519Keyring::Alice.pair().vrf_sign(&transcript)
let (o, p, _) = key.vrf_sign(Transcript::new(b"test-garbage"));
(VRFOutput(o.to_output()), VRFProof(p))
} }
fn dummy_session_info(index: SessionIndex) -> SessionInfo { fn dummy_session_info(index: SessionIndex) -> SessionInfo {
@@ -743,9 +739,9 @@ pub(crate) mod tests {
let header = Header { let header = Header {
digest: { digest: {
let mut d = Digest::default(); let mut d = Digest::default();
let (vrf_output, vrf_proof) = garbage_vrf(); let vrf_signature = garbage_vrf_signature();
d.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF( d.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF(
SecondaryVRFPreDigest { authority_index: 0, slot, vrf_output, vrf_proof }, SecondaryVRFPreDigest { authority_index: 0, slot, vrf_signature },
))); )));
d d
@@ -1042,9 +1038,9 @@ pub(crate) mod tests {
let header = Header { let header = Header {
digest: { digest: {
let mut d = Digest::default(); let mut d = Digest::default();
let (vrf_output, vrf_proof) = garbage_vrf(); let vrf_signature = garbage_vrf_signature();
d.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF( d.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF(
SecondaryVRFPreDigest { authority_index: 0, slot, vrf_output, vrf_proof }, SecondaryVRFPreDigest { authority_index: 0, slot, vrf_signature },
))); )));
d.push(ConsensusLog::ForceApprove(3).into()); d.push(ConsensusLog::ForceApprove(3).into());
@@ -1194,9 +1190,9 @@ pub(crate) mod tests {
let header = Header { let header = Header {
digest: { digest: {
let mut d = Digest::default(); let mut d = Digest::default();
let (vrf_output, vrf_proof) = garbage_vrf(); let vrf_signature = garbage_vrf_signature();
d.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF( d.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF(
SecondaryVRFPreDigest { authority_index: 0, slot, vrf_output, vrf_proof }, SecondaryVRFPreDigest { authority_index: 0, slot, vrf_signature },
))); )));
d d
@@ -19,7 +19,7 @@ use crate::tests::test_constants::TEST_CONFIG;
use super::*; use super::*;
use polkadot_node_primitives::{ use polkadot_node_primitives::{
approval::{ approval::{
AssignmentCert, AssignmentCertKind, DelayTranche, VRFOutput, VRFProof, AssignmentCert, AssignmentCertKind, DelayTranche, VrfOutput, VrfProof, VrfSignature,
RELAY_VRF_MODULO_CONTEXT, RELAY_VRF_MODULO_CONTEXT,
}, },
AvailableData, BlockData, PoV, AvailableData, BlockData, PoV,
@@ -56,8 +56,8 @@ use super::{
approval_db::v1::StoredBlockRange, approval_db::v1::StoredBlockRange,
backend::BackendWriteOp, backend::BackendWriteOp,
import::tests::{ import::tests::{
garbage_vrf, AllowedSlots, BabeEpoch, BabeEpochConfiguration, CompatibleDigestItem, Digest, garbage_vrf_signature, AllowedSlots, BabeEpoch, BabeEpochConfiguration,
DigestItem, PreDigest, SecondaryVRFPreDigest, CompatibleDigestItem, Digest, DigestItem, PreDigest, SecondaryVRFPreDigest,
}, },
}; };
@@ -392,7 +392,7 @@ fn garbage_assignment_cert(kind: AssignmentCertKind) -> AssignmentCert {
let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg)); let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg));
let out = inout.to_output(); let out = inout.to_output();
AssignmentCert { kind, vrf: (VRFOutput(out), VRFProof(proof)) } AssignmentCert { kind, vrf: VrfSignature { output: VrfOutput(out), proof: VrfProof(proof) } }
} }
fn sign_approval( fn sign_approval(
@@ -721,9 +721,9 @@ impl ChainBuilder {
fn make_header(parent_hash: Hash, slot: Slot, number: u32) -> Header { fn make_header(parent_hash: Hash, slot: Slot, number: u32) -> Header {
let digest = { let digest = {
let mut digest = Digest::default(); let mut digest = Digest::default();
let (vrf_output, vrf_proof) = garbage_vrf(); let vrf_signature = garbage_vrf_signature();
digest.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF( digest.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF(
SecondaryVRFPreDigest { authority_index: 0, slot, vrf_output, vrf_proof }, SecondaryVRFPreDigest { authority_index: 0, slot, vrf_signature },
))); )));
digest digest
}; };
@@ -24,7 +24,7 @@ use polkadot_node_network_protocol::{
view, ObservedRole, view, ObservedRole,
}; };
use polkadot_node_primitives::approval::{ use polkadot_node_primitives::approval::{
AssignmentCertKind, VRFOutput, VRFProof, RELAY_VRF_MODULO_CONTEXT, AssignmentCertKind, VrfOutput, VrfProof, VrfSignature, RELAY_VRF_MODULO_CONTEXT,
}; };
use polkadot_node_subsystem::messages::{network_bridge_event, AllMessages, ApprovalCheckError}; use polkadot_node_subsystem::messages::{network_bridge_event, AllMessages, ApprovalCheckError};
use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_test_helpers as test_helpers;
@@ -265,7 +265,7 @@ fn fake_assignment_cert(block_hash: Hash, validator: ValidatorIndex) -> Indirect
validator, validator,
cert: AssignmentCert { cert: AssignmentCert {
kind: AssignmentCertKind::RelayVRFModulo { sample: 1 }, kind: AssignmentCertKind::RelayVRFModulo { sample: 1 },
vrf: (VRFOutput(out), VRFProof(proof)), vrf: VrfSignature { output: VrfOutput(out), proof: VrfProof(proof) },
}, },
} }
} }
-1
View File
@@ -12,7 +12,6 @@ polkadot-primitives = { path = "../../primitives" }
parity-scale-codec = { version = "3.4.0", default-features = false, features = ["derive"] } parity-scale-codec = { version = "3.4.0", default-features = false, features = ["derive"] }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "master" }
+12 -16
View File
@@ -16,8 +16,7 @@
//! Types relevant for approval. //! Types relevant for approval.
pub use sp_consensus_babe::Slot; pub use sp_consensus_babe::{Randomness, Slot, VrfOutput, VrfProof, VrfSignature, VrfTranscript};
pub use sp_consensus_vrf::schnorrkel::{Randomness, VRFOutput, VRFProof};
use parity_scale_codec::{Decode, Encode}; use parity_scale_codec::{Decode, Encode};
use polkadot_primitives::{ use polkadot_primitives::{
@@ -82,8 +81,8 @@ pub enum AssignmentCertKind {
pub struct AssignmentCert { pub struct AssignmentCert {
/// The criterion which is claimed to be met by this cert. /// The criterion which is claimed to be met by this cert.
pub kind: AssignmentCertKind, pub kind: AssignmentCertKind,
/// The VRF showing the criterion is met. /// The VRF signature showing the criterion is met.
pub vrf: (VRFOutput, VRFProof), pub vrf: VrfSignature,
} }
/// An assignment criterion which refers to the candidate under which the assignment is /// An assignment criterion which refers to the candidate under which the assignment is
@@ -144,7 +143,7 @@ pub enum ApprovalError {
/// An unsafe VRF output. Provide BABE Epoch info to create a `RelayVRFStory`. /// An unsafe VRF output. Provide BABE Epoch info to create a `RelayVRFStory`.
pub struct UnsafeVRFOutput { pub struct UnsafeVRFOutput {
vrf_output: VRFOutput, vrf_output: VrfOutput,
slot: Slot, slot: Slot,
authority_index: u32, authority_index: u32,
} }
@@ -170,12 +169,12 @@ impl UnsafeVRFOutput {
let pubkey = schnorrkel::PublicKey::from_bytes(author.as_slice()) let pubkey = schnorrkel::PublicKey::from_bytes(author.as_slice())
.map_err(ApprovalError::SchnorrkelSignature)?; .map_err(ApprovalError::SchnorrkelSignature)?;
let transcript = babe_primitives::make_transcript(randomness, self.slot, epoch_index); let transcript = sp_consensus_babe::make_transcript(randomness, self.slot, epoch_index);
let inout = self let inout = self
.vrf_output .vrf_output
.0 .0
.attach_input_hash(&pubkey, transcript) .attach_input_hash(&pubkey, transcript.0)
.map_err(ApprovalError::SchnorrkelSignature)?; .map_err(ApprovalError::SchnorrkelSignature)?;
Ok(RelayVRFStory(inout.make_bytes(RELAY_VRF_STORY_CONTEXT))) Ok(RelayVRFStory(inout.make_bytes(RELAY_VRF_STORY_CONTEXT)))
} }
@@ -187,21 +186,18 @@ impl UnsafeVRFOutput {
/// the digest has type `SecondaryPlain`, which Substrate nodes do /// the digest has type `SecondaryPlain`, which Substrate nodes do
/// not produce or accept anymore. /// not produce or accept anymore.
pub fn babe_unsafe_vrf_info(header: &Header) -> Option<UnsafeVRFOutput> { pub fn babe_unsafe_vrf_info(header: &Header) -> Option<UnsafeVRFOutput> {
use babe_primitives::digests::{CompatibleDigestItem, PreDigest}; use babe_primitives::digests::CompatibleDigestItem;
for digest in &header.digest.logs { for digest in &header.digest.logs {
if let Some(pre) = digest.as_babe_pre_digest() { if let Some(pre) = digest.as_babe_pre_digest() {
let slot = pre.slot(); let slot = pre.slot();
let authority_index = pre.authority_index(); let authority_index = pre.authority_index();
// exhaustive match to defend against upstream variant changes. return pre.vrf_signature().map(|sig| UnsafeVRFOutput {
let vrf_output = match pre { vrf_output: sig.output.clone(),
PreDigest::Primary(primary) => primary.vrf_output, slot,
PreDigest::SecondaryVRF(secondary) => secondary.vrf_output, authority_index,
PreDigest::SecondaryPlain(_) => return None, })
};
return Some(UnsafeVRFOutput { vrf_output, slot, authority_index })
} }
} }
+9 -12
View File
@@ -17,15 +17,16 @@
use super::{relay_chain_selection::*, *}; use super::{relay_chain_selection::*, *};
use futures::channel::oneshot::Receiver; use futures::channel::oneshot::Receiver;
use polkadot_node_primitives::approval::{VRFOutput, VRFProof}; use polkadot_node_primitives::approval::VrfSignature;
use polkadot_node_subsystem::messages::{AllMessages, BlockDescription}; use polkadot_node_subsystem::messages::{AllMessages, BlockDescription};
use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_test_helpers as test_helpers;
use polkadot_node_subsystem_util::TimeoutExt; use polkadot_node_subsystem_util::TimeoutExt;
use polkadot_test_client::Sr25519Keyring; use polkadot_test_client::Sr25519Keyring;
use sp_consensus_babe::{ use sp_consensus_babe::{
digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest}, digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest},
Transcript, VrfTranscript,
}; };
use sp_core::{crypto::VrfSigner, testing::TaskExecutor};
use sp_runtime::{testing::*, DigestItem}; use sp_runtime::{testing::*, DigestItem};
use std::{ use std::{
collections::{BTreeMap, HashMap, HashSet}, collections::{BTreeMap, HashMap, HashSet},
@@ -74,7 +75,7 @@ fn test_harness<T: Future<Output = VirtualOverseer>>(
.filter_level(log::LevelFilter::Trace) .filter_level(log::LevelFilter::Trace)
.try_init(); .try_init();
let pool = sp_core::testing::TaskExecutor::new(); let pool = TaskExecutor::new();
let (mut context, virtual_overseer) = test_helpers::make_subsystem_context(pool); let (mut context, virtual_overseer) = test_helpers::make_subsystem_context(pool);
let (finality_target_tx, finality_target_rx) = oneshot::channel::<Option<Hash>>(); let (finality_target_tx, finality_target_rx) = oneshot::channel::<Option<Hash>>();
@@ -129,12 +130,9 @@ async fn overseer_recv_with_timeout(
const TIMEOUT: Duration = Duration::from_millis(2000); const TIMEOUT: Duration = Duration::from_millis(2000);
// used for generating assignments where the validity of the VRF doesn't matter. // used for generating assignments where the validity of the VRF doesn't matter.
fn garbage_vrf() -> (VRFOutput, VRFProof) { fn garbage_vrf_signature() -> VrfSignature {
let key = Sr25519Keyring::Alice.pair(); let transcript = VrfTranscript::new(b"test-garbage", &[]);
let key = key.as_ref(); Sr25519Keyring::Alice.pair().vrf_sign(&transcript)
let (o, p, _) = key.vrf_sign(Transcript::new(b"test-garbage"));
(VRFOutput(o.to_output()), VRFProof(p))
} }
/// Representation of a local representation /// Representation of a local representation
@@ -316,13 +314,12 @@ impl ChainBuilder {
fn make_header(parent_hash: Hash, number: u32) -> Header { fn make_header(parent_hash: Hash, number: u32) -> Header {
let digest = { let digest = {
let mut digest = Digest::default(); let mut digest = Digest::default();
let (vrf_output, vrf_proof) = garbage_vrf(); let vrf_signature = garbage_vrf_signature();
digest.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF( digest.push(DigestItem::babe_pre_digest(PreDigest::SecondaryVRF(
SecondaryVRFPreDigest { SecondaryVRFPreDigest {
authority_index: 0, authority_index: 0,
slot: 1.into(), // slot, unused slot: 1.into(), // slot, unused
vrf_output, vrf_signature,
vrf_proof,
}, },
))); )));
digest digest