referrerpolicy=no-referrer-when-downgrade

sp_consensus_beefy/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#![cfg_attr(not(feature = "std"), no_std)]
19#![warn(missing_docs)]
20
21//! Primitives for BEEFY protocol.
22//!
23//! The crate contains shared data types used by BEEFY protocol and documentation (in a form of
24//! code) for building a BEEFY light client.
25//!
26//! BEEFY is a gadget that runs alongside another finality gadget (for instance GRANDPA).
27//! For simplicity (and the initially intended use case) the documentation says GRANDPA in places
28//! where a more abstract "Finality Gadget" term could be used, but there is no reason why BEEFY
29//! wouldn't run with some other finality scheme.
30//! BEEFY validator set is supposed to be tracking the Finality Gadget validator set, but note that
31//! it will use a different set of keys. For Polkadot use case we plan to use `secp256k1` for BEEFY,
32//! while GRANDPA uses `ed25519`.
33
34extern crate alloc;
35
36mod commitment;
37mod payload;
38
39pub mod mmr;
40pub mod witness;
41
42/// Test utilities
43#[cfg(feature = "std")]
44pub mod test_utils;
45
46pub use commitment::{Commitment, KnownSignature, SignedCommitment, VersionedFinalityProof};
47pub use payload::{known_payloads, BeefyPayloadId, Payload, PayloadProvider};
48
49use alloc::vec::Vec;
50use codec::{Codec, Decode, DecodeWithMemTracking, Encode};
51use core::fmt::{Debug, Display};
52use scale_info::TypeInfo;
53use sp_application_crypto::{AppPublic, RuntimeAppPublic};
54use sp_core::H256;
55use sp_runtime::{
56	traits::{Hash, Header as HeaderT, Keccak256, NumberFor},
57	OpaqueValue,
58};
59use sp_weights::Weight;
60
61/// Key type for BEEFY module.
62pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_application_crypto::key_types::BEEFY;
63
64/// Trait representing BEEFY authority id, including custom signature verification.
65///
66/// Accepts custom hashing fn for the message and custom convertor fn for the signer.
67pub trait BeefyAuthorityId<MsgHash: Hash>: RuntimeAppPublic {
68	/// Verify a signature.
69	///
70	/// Return `true` if signature over `msg` is valid for this id.
71	fn verify(&self, signature: &<Self as RuntimeAppPublic>::Signature, msg: &[u8]) -> bool;
72}
73
74/// Hasher used for BEEFY signatures.
75pub type BeefySignatureHasher = sp_runtime::traits::Keccak256;
76
77/// A trait bound which lists all traits which are required to be implemented by
78/// a BEEFY AuthorityId type in order to be able to be used in BEEFY Keystore
79pub trait AuthorityIdBound:
80	Ord
81	+ AppPublic
82	+ Display
83	+ BeefyAuthorityId<BeefySignatureHasher, Signature = Self::BoundedSignature>
84{
85	/// Necessary bounds on the Signature associated with the AuthorityId
86	type BoundedSignature: Debug + Eq + PartialEq + Clone + TypeInfo + Codec + Send + Sync;
87}
88
89/// BEEFY cryptographic types for ECDSA crypto
90///
91/// This module basically introduces four crypto types:
92/// - `ecdsa_crypto::Pair`
93/// - `ecdsa_crypto::Public`
94/// - `ecdsa_crypto::Signature`
95/// - `ecdsa_crypto::AuthorityId`
96///
97/// Your code should use the above types as concrete types for all crypto related
98/// functionality.
99pub mod ecdsa_crypto {
100	use super::{AuthorityIdBound, BeefyAuthorityId, Hash, RuntimeAppPublic, KEY_TYPE};
101	use sp_application_crypto::{app_crypto, ecdsa};
102	use sp_core::crypto::Wraps;
103
104	app_crypto!(ecdsa, KEY_TYPE);
105
106	/// Identity of a BEEFY authority using ECDSA as its crypto.
107	pub type AuthorityId = Public;
108
109	/// Signature for a BEEFY authority using ECDSA as its crypto.
110	pub type AuthoritySignature = Signature;
111
112	impl<MsgHash: Hash> BeefyAuthorityId<MsgHash> for AuthorityId
113	where
114		<MsgHash as Hash>::Output: Into<[u8; 32]>,
115	{
116		fn verify(&self, signature: &<Self as RuntimeAppPublic>::Signature, msg: &[u8]) -> bool {
117			let msg_hash = <MsgHash as Hash>::hash(msg).into();
118			match sp_io::crypto::secp256k1_ecdsa_recover_compressed(
119				signature.as_inner_ref().as_ref(),
120				&msg_hash,
121			) {
122				Ok(raw_pubkey) => raw_pubkey.as_ref() == AsRef::<[u8]>::as_ref(self),
123				_ => false,
124			}
125		}
126	}
127	impl AuthorityIdBound for AuthorityId {
128		type BoundedSignature = Signature;
129	}
130}
131
132/// BEEFY cryptographic types for BLS crypto
133///
134/// This module basically introduces four crypto types:
135/// - `bls_crypto::Pair`
136/// - `bls_crypto::Public`
137/// - `bls_crypto::Signature`
138/// - `bls_crypto::AuthorityId`
139///
140/// Your code should use the above types as concrete types for all crypto related
141/// functionality.
142
143#[cfg(feature = "bls-experimental")]
144pub mod bls_crypto {
145	use super::{AuthorityIdBound, BeefyAuthorityId, Hash, RuntimeAppPublic, KEY_TYPE};
146	use sp_application_crypto::{app_crypto, bls381};
147	use sp_core::{bls381::Pair as BlsPair, crypto::Wraps, Pair as _};
148
149	app_crypto!(bls381, KEY_TYPE);
150
151	/// Identity of a BEEFY authority using BLS as its crypto.
152	pub type AuthorityId = Public;
153
154	/// Signature for a BEEFY authority using BLS as its crypto.
155	pub type AuthoritySignature = Signature;
156
157	impl<MsgHash: Hash> BeefyAuthorityId<MsgHash> for AuthorityId
158	where
159		<MsgHash as Hash>::Output: Into<[u8; 32]>,
160	{
161		fn verify(&self, signature: &<Self as RuntimeAppPublic>::Signature, msg: &[u8]) -> bool {
162			// `w3f-bls` library uses IETF hashing standard and as such does not expose
163			// a choice of hash-to-field function.
164			// We are directly calling into the library to avoid introducing new host call.
165			// and because BeefyAuthorityId::verify is being called in the runtime so we don't have
166
167			BlsPair::verify(signature.as_inner_ref(), msg, self.as_inner_ref())
168		}
169	}
170	impl AuthorityIdBound for AuthorityId {
171		type BoundedSignature = Signature;
172	}
173}
174
175/// BEEFY cryptographic types for (ECDSA,BLS) crypto pair
176///
177/// This module basically introduces four crypto types:
178/// - `ecdsa_bls_crypto::Pair`
179/// - `ecdsa_bls_crypto::Public`
180/// - `ecdsa_bls_crypto::Signature`
181/// - `ecdsa_bls_crypto::AuthorityId`
182///
183/// Your code should use the above types as concrete types for all crypto related
184/// functionality.
185#[cfg(feature = "bls-experimental")]
186pub mod ecdsa_bls_crypto {
187	use super::{AuthorityIdBound, BeefyAuthorityId, Hash, RuntimeAppPublic, KEY_TYPE};
188	use sp_application_crypto::{app_crypto, ecdsa_bls381};
189	use sp_core::{crypto::Wraps, ecdsa_bls381::Pair as EcdsaBlsPair};
190
191	app_crypto!(ecdsa_bls381, KEY_TYPE);
192
193	/// Identity of a BEEFY authority using (ECDSA,BLS) as its crypto.
194	pub type AuthorityId = Public;
195
196	/// Signature for a BEEFY authority using (ECDSA,BLS) as its crypto.
197	pub type AuthoritySignature = Signature;
198
199	impl<H> BeefyAuthorityId<H> for AuthorityId
200	where
201		H: Hash,
202		H::Output: Into<[u8; 32]>,
203	{
204		fn verify(&self, signature: &<Self as RuntimeAppPublic>::Signature, msg: &[u8]) -> bool {
205			// We can not simply call
206			// `EcdsaBlsPair::verify(signature.as_inner_ref(), msg, self.as_inner_ref())`
207			// because that invokes ECDSA default verification which performs Blake2b hash
208			// which we don't want. This is because ECDSA signatures are meant to be verified
209			// on Ethereum network where Keccak hasher is significantly cheaper than Blake2b.
210			// See Figure 3 of [OnSc21](https://www.scitepress.org/Papers/2021/106066/106066.pdf)
211			// for comparison.
212			EcdsaBlsPair::verify_with_hasher::<H>(
213				signature.as_inner_ref(),
214				msg,
215				self.as_inner_ref(),
216			)
217		}
218	}
219
220	impl AuthorityIdBound for AuthorityId {
221		type BoundedSignature = Signature;
222	}
223}
224
225/// The `ConsensusEngineId` of BEEFY.
226pub const BEEFY_ENGINE_ID: sp_runtime::ConsensusEngineId = *b"BEEF";
227
228/// Authority set id starts with zero at BEEFY pallet genesis.
229pub const GENESIS_AUTHORITY_SET_ID: u64 = 0;
230
231/// A typedef for validator set id.
232pub type ValidatorSetId = u64;
233
234/// A set of BEEFY authorities, a.k.a. validators.
235#[derive(Decode, Encode, Debug, PartialEq, Clone, TypeInfo)]
236pub struct ValidatorSet<AuthorityId> {
237	/// Public keys of the validator set elements
238	validators: Vec<AuthorityId>,
239	/// Identifier of the validator set
240	id: ValidatorSetId,
241}
242
243impl<AuthorityId> ValidatorSet<AuthorityId> {
244	/// Return a validator set with the given validators and set id.
245	pub fn new<I>(validators: I, id: ValidatorSetId) -> Option<Self>
246	where
247		I: IntoIterator<Item = AuthorityId>,
248	{
249		let validators: Vec<AuthorityId> = validators.into_iter().collect();
250		if validators.is_empty() {
251			// No validators; the set would be empty.
252			None
253		} else {
254			Some(Self { validators, id })
255		}
256	}
257
258	/// Return a reference to the vec of validators.
259	pub fn validators(&self) -> &[AuthorityId] {
260		&self.validators
261	}
262
263	/// Return the validator set id.
264	pub fn id(&self) -> ValidatorSetId {
265		self.id
266	}
267
268	/// Return the number of validators in the set.
269	pub fn len(&self) -> usize {
270		self.validators.len()
271	}
272}
273
274/// The index of an authority.
275pub type AuthorityIndex = u32;
276
277/// The Hashing used within MMR.
278pub type MmrHashing = Keccak256;
279/// The type used to represent an MMR root hash.
280pub type MmrRootHash = H256;
281
282/// A consensus log item for BEEFY.
283#[derive(Decode, Encode, TypeInfo)]
284pub enum ConsensusLog<AuthorityId: Codec> {
285	/// The authorities have changed.
286	#[codec(index = 1)]
287	AuthoritiesChange(ValidatorSet<AuthorityId>),
288	/// Disable the authority with given index.
289	#[codec(index = 2)]
290	OnDisabled(AuthorityIndex),
291	/// MMR root hash.
292	#[codec(index = 3)]
293	MmrRoot(MmrRootHash),
294}
295
296/// BEEFY vote message.
297///
298/// A vote message is a direct vote created by a BEEFY node on every voting round
299/// and is gossiped to its peers.
300// TODO: Remove `Signature` generic type, instead get it from `Id::Signature`.
301#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
302pub struct VoteMessage<Number, Id, Signature> {
303	/// Commit to information extracted from a finalized block
304	pub commitment: Commitment<Number>,
305	/// Node authority id
306	pub id: Id,
307	/// Node signature
308	pub signature: Signature,
309}
310
311/// Proof showing that an authority voted twice in the same round.
312///
313/// One type of misbehavior in BEEFY happens when an authority votes in the same round/block
314/// for different payloads.
315/// Proving is achieved by collecting the signed commitments of conflicting votes.
316#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
317pub struct DoubleVotingProof<Number, Id, Signature> {
318	/// The first vote in the equivocation.
319	pub first: VoteMessage<Number, Id, Signature>,
320	/// The second vote in the equivocation.
321	pub second: VoteMessage<Number, Id, Signature>,
322}
323
324impl<Number, Id, Signature> DoubleVotingProof<Number, Id, Signature> {
325	/// Returns the authority id of the equivocator.
326	pub fn offender_id(&self) -> &Id {
327		&self.first.id
328	}
329	/// Returns the round number at which the equivocation occurred.
330	pub fn round_number(&self) -> &Number {
331		&self.first.commitment.block_number
332	}
333	/// Returns the set id at which the equivocation occurred.
334	pub fn set_id(&self) -> ValidatorSetId {
335		self.first.commitment.validator_set_id
336	}
337}
338
339/// Proof showing that an authority voted for a non-canonical chain.
340///
341/// Proving is achieved by providing a proof that contains relevant info about the canonical chain
342/// at `commitment.block_number`. The `commitment` can be checked against this info.
343#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
344pub struct ForkVotingProof<Header: HeaderT, Id: RuntimeAppPublic, AncestryProof> {
345	/// The equivocated vote.
346	pub vote: VoteMessage<Header::Number, Id, Id::Signature>,
347	/// Proof containing info about the canonical chain at `commitment.block_number`.
348	pub ancestry_proof: AncestryProof,
349	/// The header of the block where the ancestry proof was generated
350	pub header: Header,
351}
352
353impl<Header: HeaderT, Id: RuntimeAppPublic> ForkVotingProof<Header, Id, OpaqueValue> {
354	/// Try to decode the `AncestryProof`.
355	pub fn try_into<AncestryProof: Decode>(
356		self,
357	) -> Option<ForkVotingProof<Header, Id, AncestryProof>> {
358		Some(ForkVotingProof::<Header, Id, AncestryProof> {
359			vote: self.vote,
360			ancestry_proof: self.ancestry_proof.decode()?,
361			header: self.header,
362		})
363	}
364}
365
366/// Proof showing that an authority voted for a future block.
367#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo)]
368pub struct FutureBlockVotingProof<Number, Id: RuntimeAppPublic> {
369	/// The equivocated vote.
370	pub vote: VoteMessage<Number, Id, Id::Signature>,
371}
372
373/// Check a commitment signature by encoding the commitment and
374/// verifying the provided signature using the expected authority id.
375pub fn check_commitment_signature<Number, Id, MsgHash>(
376	commitment: &Commitment<Number>,
377	authority_id: &Id,
378	signature: &<Id as RuntimeAppPublic>::Signature,
379) -> bool
380where
381	Id: BeefyAuthorityId<MsgHash>,
382	Number: Clone + Encode + PartialEq,
383	MsgHash: Hash,
384{
385	let encoded_commitment = commitment.encode();
386	BeefyAuthorityId::<MsgHash>::verify(authority_id, signature, &encoded_commitment)
387}
388
389/// Verifies the equivocation proof by making sure that both votes target
390/// different blocks and that its signatures are valid.
391pub fn check_double_voting_proof<Number, Id, MsgHash>(
392	report: &DoubleVotingProof<Number, Id, <Id as RuntimeAppPublic>::Signature>,
393) -> bool
394where
395	Id: BeefyAuthorityId<MsgHash> + PartialEq,
396	Number: Clone + Encode + PartialEq,
397	MsgHash: Hash,
398{
399	let first = &report.first;
400	let second = &report.second;
401
402	// if votes
403	//   come from different authorities,
404	//   are for different rounds,
405	//   have different validator set ids,
406	//   or both votes have the same commitment,
407	//     --> the equivocation is invalid.
408	if first.id != second.id ||
409		first.commitment.block_number != second.commitment.block_number ||
410		first.commitment.validator_set_id != second.commitment.validator_set_id ||
411		first.commitment.payload == second.commitment.payload
412	{
413		return false
414	}
415
416	// check signatures on both votes are valid
417	let valid_first = check_commitment_signature(&first.commitment, &first.id, &first.signature);
418	let valid_second =
419		check_commitment_signature(&second.commitment, &second.id, &second.signature);
420
421	return valid_first && valid_second
422}
423
424/// New BEEFY validator set notification hook.
425pub trait OnNewValidatorSet<AuthorityId> {
426	/// Function called by the pallet when BEEFY validator set changes.
427	fn on_new_validator_set(
428		validator_set: &ValidatorSet<AuthorityId>,
429		next_validator_set: &ValidatorSet<AuthorityId>,
430	);
431}
432
433/// No-op implementation of [OnNewValidatorSet].
434impl<AuthorityId> OnNewValidatorSet<AuthorityId> for () {
435	fn on_new_validator_set(_: &ValidatorSet<AuthorityId>, _: &ValidatorSet<AuthorityId>) {}
436}
437
438/// Hook containing helper methods for proving/checking commitment canonicity.
439pub trait AncestryHelper<Header: HeaderT> {
440	/// Type containing proved info about the canonical chain at a certain height.
441	type Proof: Clone + Debug + Decode + Encode + PartialEq + TypeInfo;
442	/// The data needed for validating the proof.
443	type ValidationContext;
444
445	/// Generates a proof that the `prev_block_number` is part of the canonical chain at
446	/// `best_known_block_number`.
447	fn generate_proof(
448		prev_block_number: Header::Number,
449		best_known_block_number: Option<Header::Number>,
450	) -> Option<Self::Proof>;
451
452	/// Check if the proof is optimal.
453	fn is_proof_optimal(proof: &Self::Proof) -> bool;
454
455	/// Extract the validation context from the provided header.
456	fn extract_validation_context(header: Header) -> Option<Self::ValidationContext>;
457
458	/// Check if a commitment is pointing to a header on a non-canonical chain
459	/// against a canonicity proof generated at the same header height.
460	fn is_non_canonical(
461		commitment: &Commitment<Header::Number>,
462		proof: Self::Proof,
463		context: Self::ValidationContext,
464	) -> bool;
465}
466
467/// Weight information for the logic in `AncestryHelper`.
468pub trait AncestryHelperWeightInfo<Header: HeaderT>: AncestryHelper<Header> {
469	/// Weight info for the `AncestryHelper::is_proof_optimal()` method.
470	fn is_proof_optimal(proof: &<Self as AncestryHelper<Header>>::Proof) -> Weight;
471
472	/// Weight info for the `AncestryHelper::extract_validation_context()` method.
473	fn extract_validation_context() -> Weight;
474
475	/// Weight info for the `AncestryHelper::is_non_canonical()` method.
476	fn is_non_canonical(proof: &<Self as AncestryHelper<Header>>::Proof) -> Weight;
477}
478
479/// An opaque type used to represent the key ownership proof at the runtime API
480/// boundary. The inner value is an encoded representation of the actual key
481/// ownership proof which will be parameterized when defining the runtime. At
482/// the runtime API boundary this type is unknown and as such we keep this
483/// opaque representation, implementors of the runtime API will have to make
484/// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type.
485pub type OpaqueKeyOwnershipProof = OpaqueValue;
486
487sp_api::decl_runtime_apis! {
488	/// API necessary for BEEFY voters.
489	#[api_version(5)]
490	pub trait BeefyApi<AuthorityId> where
491		AuthorityId : Codec + RuntimeAppPublic,
492	{
493		/// Return the block number where BEEFY consensus is enabled/started
494		fn beefy_genesis() -> Option<NumberFor<Block>>;
495
496		/// Return the current active BEEFY validator set
497		fn validator_set() -> Option<ValidatorSet<AuthorityId>>;
498
499		/// Submits an unsigned extrinsic to report a double voting equivocation. The caller
500		/// must provide the double voting proof and a key ownership proof
501		/// (should be obtained using `generate_key_ownership_proof`). The
502		/// extrinsic will be unsigned and should only be accepted for local
503		/// authorship (not to be broadcast to the network). This method returns
504		/// `None` when creation of the extrinsic fails, e.g. if equivocation
505		/// reporting is disabled for the given runtime (i.e. this method is
506		/// hardcoded to return `None`). Only useful in an offchain context.
507		fn submit_report_double_voting_unsigned_extrinsic(
508			equivocation_proof:
509				DoubleVotingProof<NumberFor<Block>, AuthorityId, <AuthorityId as RuntimeAppPublic>::Signature>,
510			key_owner_proof: OpaqueKeyOwnershipProof,
511		) -> Option<()>;
512
513		/// Submits an unsigned extrinsic to report a fork voting equivocation. The caller
514		/// must provide the fork voting proof (the ancestry proof should be obtained using
515		/// `generate_ancestry_proof`) and a key ownership proof (should be obtained using
516		/// `generate_key_ownership_proof`). The extrinsic will be unsigned and should only
517		/// be accepted for local authorship (not to be broadcast to the network). This method
518		/// returns `None` when creation of the extrinsic fails, e.g. if equivocation
519		/// reporting is disabled for the given runtime (i.e. this method is
520		/// hardcoded to return `None`). Only useful in an offchain context.
521		fn submit_report_fork_voting_unsigned_extrinsic(
522			equivocation_proof:
523				ForkVotingProof<Block::Header, AuthorityId, OpaqueValue>,
524			key_owner_proof: OpaqueKeyOwnershipProof,
525		) -> Option<()>;
526
527		/// Submits an unsigned extrinsic to report a future block voting equivocation. The caller
528		/// must provide the future block voting proof and a key ownership proof
529		/// (should be obtained using `generate_key_ownership_proof`).
530		/// The extrinsic will be unsigned and should only be accepted for local
531		/// authorship (not to be broadcast to the network). This method returns
532		/// `None` when creation of the extrinsic fails, e.g. if equivocation
533		/// reporting is disabled for the given runtime (i.e. this method is
534		/// hardcoded to return `None`). Only useful in an offchain context.
535		fn submit_report_future_block_voting_unsigned_extrinsic(
536			equivocation_proof:
537				FutureBlockVotingProof<NumberFor<Block>, AuthorityId>,
538			key_owner_proof: OpaqueKeyOwnershipProof,
539		) -> Option<()>;
540
541		/// Generates a proof of key ownership for the given authority in the
542		/// given set. An example usage of this module is coupled with the
543		/// session historical module to prove that a given authority key is
544		/// tied to a given staking identity during a specific session. Proofs
545		/// of key ownership are necessary for submitting equivocation reports.
546		/// NOTE: even though the API takes a `set_id` as parameter the current
547		/// implementations ignores this parameter and instead relies on this
548		/// method being called at the correct block height, i.e. any point at
549		/// which the given set id is live on-chain. Future implementations will
550		/// instead use indexed data through an offchain worker, not requiring
551		/// older states to be available.
552		fn generate_key_ownership_proof(
553			set_id: ValidatorSetId,
554			authority_id: AuthorityId,
555		) -> Option<OpaqueKeyOwnershipProof>;
556
557		/// Generates a proof that the `prev_block_number` is part of the canonical chain at
558		/// `best_known_block_number`.
559		fn generate_ancestry_proof(
560			prev_block_number: NumberFor<Block>,
561			best_known_block_number: Option<NumberFor<Block>>,
562		) -> Option<OpaqueValue>;
563	}
564
565}
566
567#[cfg(test)]
568mod tests {
569	use super::*;
570	use sp_application_crypto::ecdsa::{self, Public};
571	use sp_core::crypto::{Pair, Wraps};
572	use sp_crypto_hashing::{blake2_256, keccak_256};
573	use sp_runtime::traits::{BlakeTwo256, Keccak256};
574
575	#[test]
576	fn validator_set() {
577		// Empty set not allowed.
578		assert_eq!(ValidatorSet::<Public>::new(vec![], 0), None);
579
580		let alice = ecdsa::Pair::from_string("//Alice", None).unwrap();
581		let set_id = 0;
582		let validators = ValidatorSet::<Public>::new(vec![alice.public()], set_id).unwrap();
583
584		assert_eq!(validators.id(), set_id);
585		assert_eq!(validators.validators(), &vec![alice.public()]);
586	}
587
588	#[test]
589	fn ecdsa_beefy_verify_works() {
590		let msg = &b"test-message"[..];
591		let (pair, _) = ecdsa_crypto::Pair::generate();
592
593		let keccak_256_signature: ecdsa_crypto::Signature =
594			pair.as_inner_ref().sign_prehashed(&keccak_256(msg)).into();
595
596		let blake2_256_signature: ecdsa_crypto::Signature =
597			pair.as_inner_ref().sign_prehashed(&blake2_256(msg)).into();
598
599		// Verification works if same hashing function is used when signing and verifying.
600		assert!(BeefyAuthorityId::<Keccak256>::verify(&pair.public(), &keccak_256_signature, msg));
601		assert!(BeefyAuthorityId::<BlakeTwo256>::verify(
602			&pair.public(),
603			&blake2_256_signature,
604			msg
605		));
606		// Verification fails if distinct hashing functions are used when signing and verifying.
607		assert!(!BeefyAuthorityId::<Keccak256>::verify(&pair.public(), &blake2_256_signature, msg));
608		assert!(!BeefyAuthorityId::<BlakeTwo256>::verify(
609			&pair.public(),
610			&keccak_256_signature,
611			msg
612		));
613
614		// Other public key doesn't work
615		let (other_pair, _) = ecdsa_crypto::Pair::generate();
616		assert!(!BeefyAuthorityId::<Keccak256>::verify(
617			&other_pair.public(),
618			&keccak_256_signature,
619			msg,
620		));
621		assert!(!BeefyAuthorityId::<BlakeTwo256>::verify(
622			&other_pair.public(),
623			&blake2_256_signature,
624			msg,
625		));
626	}
627
628	#[test]
629	#[cfg(feature = "bls-experimental")]
630	fn bls_beefy_verify_works() {
631		let msg = &b"test-message"[..];
632		let (pair, _) = bls_crypto::Pair::generate();
633
634		let signature: bls_crypto::Signature = pair.as_inner_ref().sign(&msg).into();
635
636		// Verification works if same hashing function is used when signing and verifying.
637		assert!(BeefyAuthorityId::<Keccak256>::verify(&pair.public(), &signature, msg));
638
639		// Other public key doesn't work
640		let (other_pair, _) = bls_crypto::Pair::generate();
641		assert!(!BeefyAuthorityId::<Keccak256>::verify(&other_pair.public(), &signature, msg,));
642	}
643
644	#[test]
645	#[cfg(feature = "bls-experimental")]
646	fn ecdsa_bls_beefy_verify_works() {
647		let msg = &b"test-message"[..];
648		let (pair, _) = ecdsa_bls_crypto::Pair::generate();
649
650		let signature: ecdsa_bls_crypto::Signature =
651			pair.as_inner_ref().sign_with_hasher::<Keccak256>(&msg).into();
652
653		// Verification works if same hashing function is used when signing and verifying.
654		assert!(BeefyAuthorityId::<Keccak256>::verify(&pair.public(), &signature, msg));
655
656		// Verification doesn't work if we verify function provided by pair_crypto implementation
657		assert!(!ecdsa_bls_crypto::Pair::verify(&signature, msg, &pair.public()));
658
659		// Other public key doesn't work
660		let (other_pair, _) = ecdsa_bls_crypto::Pair::generate();
661		assert!(!BeefyAuthorityId::<Keccak256>::verify(&other_pair.public(), &signature, msg,));
662	}
663}