referrerpolicy=no-referrer-when-downgrade

sp_core/
bandersnatch.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//! VRFs backed by [Bandersnatch](https://neuromancer.sk/std/bls/Bandersnatch),
19//! an elliptic curve built over BLS12-381 scalar field.
20//!
21//! The primitive can operate both as a regular VRF or as an anonymized Ring VRF.
22
23#[cfg(feature = "full_crypto")]
24use crate::crypto::VrfSecret;
25use crate::{
26	crypto::{
27		ByteArray, CryptoType, CryptoTypeId, DeriveError, DeriveJunction, Pair as TraitPair,
28		PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, VrfPublic,
29	},
30	proof_of_possession::NonAggregatable,
31};
32use alloc::{vec, vec::Vec};
33use ark_vrf::{
34	reexports::ark_serialize::CanonicalSerialize,
35	suites::bandersnatch::{self, BandersnatchSha512Ell2 as BandersnatchSuite, Secret, VrfIo},
36	CanonicalDeserializeExact,
37};
38use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
39use scale_info::TypeInfo;
40
41/// Identifier used to match public keys against bandersnatch-vrf keys.
42pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"band");
43
44/// The byte length of secret key seed.
45pub const SEED_SERIALIZED_SIZE: usize = 32;
46
47/// The byte length of serialized public key.
48pub const PUBLIC_SERIALIZED_SIZE: usize = 32;
49
50/// The byte length of serialized signature (thin VRF proof: 32-byte point + 32-byte scalar).
51pub const SIGNATURE_SERIALIZED_SIZE: usize = 64;
52
53/// The byte length of serialized pre-output.
54pub const PREOUT_SERIALIZED_SIZE: usize = 32;
55
56#[doc(hidden)]
57pub struct BandersnatchTag;
58
59/// Bandersnatch public key.
60pub type Public = PublicBytes<PUBLIC_SERIALIZED_SIZE, BandersnatchTag>;
61
62impl CryptoType for Public {
63	type Pair = Pair;
64}
65
66/// Bandersnatch Schnorr signature.
67pub type Signature = SignatureBytes<SIGNATURE_SERIALIZED_SIZE, BandersnatchTag>;
68
69/// Proof of Possession is the same as Signature for Bandersnatch
70pub type ProofOfPossession = Signature;
71
72impl CryptoType for Signature {
73	type Pair = Pair;
74}
75
76/// The raw secret seed, which can be used to reconstruct the secret [`Pair`].
77type Seed = [u8; SEED_SERIALIZED_SIZE];
78
79/// Bandersnatch secret key.
80#[derive(Clone)]
81pub struct Pair {
82	secret: Secret,
83	seed: Seed,
84}
85
86impl Pair {
87	/// Get the key seed.
88	pub fn seed(&self) -> Seed {
89		self.seed
90	}
91}
92
93impl TraitPair for Pair {
94	type Seed = Seed;
95	type Public = Public;
96	type Signature = Signature;
97	type ProofOfPossession = Signature;
98
99	/// Make a new key pair from secret seed material.
100	///
101	/// The slice must be 32 bytes long or it will return an error.
102	fn from_seed_slice(seed_slice: &[u8]) -> Result<Pair, SecretStringError> {
103		if seed_slice.len() != SEED_SERIALIZED_SIZE {
104			return Err(SecretStringError::InvalidSeedLength);
105		}
106		let mut seed = [0; SEED_SERIALIZED_SIZE];
107		seed.copy_from_slice(seed_slice);
108		let secret = Secret::from_seed(seed);
109		Ok(Pair { secret, seed })
110	}
111
112	/// Derive a child key from a series of given (hard) junctions.
113	///
114	/// Soft junctions are not supported.
115	fn derive<Iter: Iterator<Item = DeriveJunction>>(
116		&self,
117		path: Iter,
118		_seed: Option<Seed>,
119	) -> Result<(Pair, Option<Seed>), DeriveError> {
120		let derive_hard = |seed, cc| -> Seed {
121			("bandersnatch-vrf-HDKD", seed, cc).using_encoded(sp_crypto_hashing::blake2_256)
122		};
123
124		let mut seed = self.seed();
125		for p in path {
126			if let DeriveJunction::Hard(cc) = p {
127				seed = derive_hard(seed, cc);
128			} else {
129				return Err(DeriveError::SoftKeyInPath);
130			}
131		}
132		Ok((Self::from_seed(&seed), Some(seed)))
133	}
134
135	fn public(&self) -> Public {
136		let public = self.secret.public();
137		let mut raw = [0; PUBLIC_SERIALIZED_SIZE];
138		public
139			.serialize_compressed(raw.as_mut_slice())
140			.expect("serialization length is constant and checked by test; qed");
141		Public::unchecked_from(raw)
142	}
143
144	#[cfg(feature = "full_crypto")]
145	fn sign(&self, data: &[u8]) -> Signature {
146		vrf::vrf_sign(&self.secret, &[], data)
147	}
148
149	fn verify<M: AsRef<[u8]>>(signature: &Signature, data: M, public: &Public) -> bool {
150		vrf::vrf_verify(public, &[], signature, data.as_ref())
151	}
152
153	/// Return a vector filled with the seed.
154	fn to_raw_vec(&self) -> Vec<u8> {
155		self.seed().to_vec()
156	}
157}
158
159impl CryptoType for Pair {
160	type Pair = Pair;
161}
162
163impl NonAggregatable for Pair {}
164
165/// Bandersnatch VRF types and operations.
166pub mod vrf {
167	use super::*;
168	use crate::crypto::VrfCrypto;
169
170	/// [`VrfSignature`] serialized size.
171	pub const VRF_SIGNATURE_SERIALIZED_SIZE: usize =
172		PREOUT_SERIALIZED_SIZE + SIGNATURE_SERIALIZED_SIZE;
173
174	/// VRF input to construct a [`VrfPreOutput`] instance and embeddable in [`VrfSignData`].
175	#[derive(Clone, Debug)]
176	pub struct VrfInput(pub(super) bandersnatch::Input);
177
178	impl VrfInput {
179		/// Construct a new VRF input.
180		///
181		/// Hash to Curve (H2C) using Elligator2.
182		pub fn new(data: &[u8]) -> Self {
183			Self(bandersnatch::Input::new(data).expect("H2C for Bandersnatch can't fail; qed"))
184		}
185	}
186
187	/// VRF pre-output derived from [`VrfInput`] using a [`VrfSecret`].
188	///
189	/// This object is hashed to produce the actual VRF output.
190	#[derive(Clone, Debug, PartialEq, Eq)]
191	pub struct VrfPreOutput(pub(super) bandersnatch::Output);
192
193	impl Encode for VrfPreOutput {
194		fn encode(&self) -> Vec<u8> {
195			let mut bytes = [0; PREOUT_SERIALIZED_SIZE];
196			self.0
197				.serialize_compressed(bytes.as_mut_slice())
198				.expect("serialization length is constant and checked by test; qed");
199			bytes.encode()
200		}
201	}
202
203	impl Decode for VrfPreOutput {
204		fn decode<R: codec::Input>(i: &mut R) -> Result<Self, codec::Error> {
205			let buf = <[u8; PREOUT_SERIALIZED_SIZE]>::decode(i)?;
206			let preout = bandersnatch::Output::deserialize_compressed_exact(buf.as_slice())
207				.map_err(|_| "vrf-preout decode error: bad preout")?;
208			Ok(VrfPreOutput(preout))
209		}
210	}
211
212	// `VrfPreOutput` resolves to:
213	// ```
214	// pub struct Affine<P: TECurveConfig> {
215	//     pub x: P::BaseField,
216	//     pub y: P::BaseField,
217	// }
218	// ```
219	// where each `P::BaseField` contains a `pub struct BigInt<const N: usize>(pub [u64; N]);`
220	// Since none of these structures is allocated on the heap, we don't need any special
221	// memory tracking logic. We can simply implement `DecodeWithMemTracking`.
222	impl DecodeWithMemTracking for VrfPreOutput {}
223
224	impl EncodeLike for VrfPreOutput {}
225
226	impl MaxEncodedLen for VrfPreOutput {
227		fn max_encoded_len() -> usize {
228			<[u8; PREOUT_SERIALIZED_SIZE]>::max_encoded_len()
229		}
230	}
231
232	impl TypeInfo for VrfPreOutput {
233		type Identity = [u8; PREOUT_SERIALIZED_SIZE];
234
235		fn type_info() -> scale_info::Type {
236			Self::Identity::type_info()
237		}
238	}
239
240	/// Data to be signed via one of the two provided vrf flavors.
241	///
242	/// The object contains the VRF input and additional data to be signed together
243	/// with the VRF input. Additional data doesn't influence the VRF output.
244	///
245	/// The `input` is a [`VrfInput`]s which, during the signing procedure, is first mapped
246	/// to a [`VrfPreOutput`].
247	#[derive(Clone)]
248	pub struct VrfSignData {
249		/// VRF input.
250		pub vrf_input: VrfInput,
251		/// Additional data.
252		pub aux_data: Vec<u8>,
253	}
254
255	impl VrfSignData {
256		/// Construct a new data to be signed.
257		pub fn new(vrf_input_data: &[u8], aux_data: &[u8]) -> Self {
258			Self { vrf_input: VrfInput::new(vrf_input_data), aux_data: aux_data.to_vec() }
259		}
260	}
261
262	/// VRF signature.
263	///
264	/// Includes both the VRF proof and the pre-output generated from the
265	/// [`VrfSignData::vrf_input`].
266	///
267	/// Refer to [`VrfSignData`] for more details.
268	#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
269	pub struct VrfSignature {
270		/// VRF pre-output.
271		pub pre_output: VrfPreOutput,
272		/// VRF proof.
273		pub proof: Signature,
274	}
275
276	#[cfg(feature = "full_crypto")]
277	impl VrfCrypto for Pair {
278		type VrfInput = VrfInput;
279		type VrfPreOutput = VrfPreOutput;
280		type VrfSignData = VrfSignData;
281		type VrfSignature = VrfSignature;
282	}
283
284	#[cfg(feature = "full_crypto")]
285	pub(super) fn vrf_sign(secret: &Secret, ios: &[VrfIo], aux_data: &[u8]) -> Signature {
286		let proof_impl = secret.prove_thin(ios, aux_data);
287		let mut proof = Signature::default();
288		proof_impl
289			.serialize_compressed(proof.0.as_mut_slice())
290			.expect("serialization length is constant and checked by test; qed");
291		proof
292	}
293
294	pub(super) fn vrf_verify(
295		public: &Public,
296		ios: &[VrfIo],
297		proof: &Signature,
298		aux_data: &[u8],
299	) -> bool {
300		let Ok(public) = bandersnatch::Public::deserialize_compressed_exact(public.as_slice())
301		else {
302			return false;
303		};
304		let Ok(proof) = bandersnatch::ThinProof::deserialize_compressed_exact(proof.as_slice())
305		else {
306			return false;
307		};
308		public.verify_thin(ios, aux_data, &proof).is_ok()
309	}
310
311	#[cfg(feature = "full_crypto")]
312	impl VrfSecret for Pair {
313		fn vrf_sign(&self, data: &VrfSignData) -> VrfSignature {
314			let output = self.secret.output(data.vrf_input.0);
315			let pre_output = VrfPreOutput(output);
316			let io = VrfIo { input: data.vrf_input.0, output };
317			let proof = vrf_sign(&self.secret, &[io], &data.aux_data);
318			VrfSignature { pre_output, proof }
319		}
320
321		fn vrf_pre_output(&self, input: &Self::VrfInput) -> Self::VrfPreOutput {
322			let pre_output_impl = self.secret.output(input.0);
323			VrfPreOutput(pre_output_impl)
324		}
325	}
326
327	impl VrfCrypto for Public {
328		type VrfInput = VrfInput;
329		type VrfPreOutput = VrfPreOutput;
330		type VrfSignData = VrfSignData;
331		type VrfSignature = VrfSignature;
332	}
333
334	impl VrfPublic for Public {
335		fn vrf_verify(&self, data: &VrfSignData, signature: &VrfSignature) -> bool {
336			let io = VrfIo { input: data.vrf_input.0, output: signature.pre_output.0 };
337			vrf_verify(self, &[io], &signature.proof, &data.aux_data)
338		}
339	}
340
341	#[cfg(feature = "full_crypto")]
342	impl Pair {
343		/// Generate VRF output bytes for the given `input`.
344		pub fn make_bytes(&self, input: &VrfInput) -> [u8; 32] {
345			self.vrf_pre_output(input).make_bytes()
346		}
347	}
348
349	impl VrfPreOutput {
350		/// Generate VRF output bytes.
351		pub fn make_bytes(&self) -> [u8; 32] {
352			self.0.hash::<32>()
353		}
354	}
355}
356
357/// Bandersnatch Ring-VRF types and operations.
358pub mod ring_vrf {
359	use super::{vrf::*, *};
360	pub use bandersnatch::{RingProver, RingVerifier};
361	use bandersnatch::{RingSetup, RingVerifierKey as RingVerifierKeyImpl};
362
363	// Max size of serialized ring-vrf context given `domain_len`.
364	pub(crate) fn ring_context_serialized_size(ring_size: usize) -> usize {
365		const G1_POINT_UNCOMPRESSED_SIZE: usize = 96;
366		const G2_POINT_UNCOMPRESSED_SIZE: usize = 192;
367		const OVERHEAD_SIZE: usize = 16;
368		const G2_POINTS_NUM: usize = 2;
369		let g1_points_num = ark_vrf::ring::pcs_domain_size::<BandersnatchSuite>(ring_size);
370		OVERHEAD_SIZE +
371			g1_points_num * G1_POINT_UNCOMPRESSED_SIZE +
372			G2_POINTS_NUM * G2_POINT_UNCOMPRESSED_SIZE
373	}
374
375	/// [`RingVerifierKey`] serialized size.
376	pub const RING_VERIFIER_KEY_SERIALIZED_SIZE: usize = 384;
377	/// [`RingProof`] serialized size.
378	pub(crate) const RING_PROOF_SERIALIZED_SIZE: usize = 752;
379	/// [`RingVrfSignature`] serialized size.
380	pub const RING_SIGNATURE_SERIALIZED_SIZE: usize =
381		RING_PROOF_SERIALIZED_SIZE + PREOUT_SERIALIZED_SIZE;
382
383	/// Ring verifier key
384	pub struct RingVerifierKey(RingVerifierKeyImpl);
385
386	impl Encode for RingVerifierKey {
387		fn encode(&self) -> Vec<u8> {
388			let mut buf = Vec::with_capacity(RING_VERIFIER_KEY_SERIALIZED_SIZE);
389			self.0
390				.serialize_compressed(&mut buf)
391				.expect("serialization length is constant and checked by test; qed");
392			buf
393		}
394	}
395
396	impl Decode for RingVerifierKey {
397		fn decode<R: codec::Input>(input: &mut R) -> Result<Self, codec::Error> {
398			let mut buf = vec![0; RING_VERIFIER_KEY_SERIALIZED_SIZE];
399			input.read(&mut buf[..])?;
400			let vk = RingVerifierKeyImpl::deserialize_compressed_exact(buf.as_slice())
401				.map_err(|_| "RingVerifierKey decode error")?;
402			Ok(RingVerifierKey(vk))
403		}
404	}
405
406	impl EncodeLike for RingVerifierKey {}
407
408	impl MaxEncodedLen for RingVerifierKey {
409		fn max_encoded_len() -> usize {
410			RING_VERIFIER_KEY_SERIALIZED_SIZE
411		}
412	}
413
414	impl TypeInfo for RingVerifierKey {
415		type Identity = [u8; RING_VERIFIER_KEY_SERIALIZED_SIZE];
416		fn type_info() -> scale_info::Type {
417			Self::Identity::type_info()
418		}
419	}
420
421	/// Context used to construct ring prover and verifier.
422	///
423	/// Generic parameter `R` represents the ring size.
424	#[derive(Clone)]
425	pub struct RingContext<const R: usize>(RingSetup);
426
427	impl<const R: usize> RingContext<R> {
428		/// Build an dummy instance for testing purposes.
429		pub fn new_testing() -> Self {
430			Self(RingSetup::from_seed_insecure(R, [0; 32]))
431		}
432
433		/// Get the keyset max size.
434		pub fn max_keyset_size(&self) -> usize {
435			self.0.ring_context().max_ring_size()
436		}
437
438		/// Get ring prover for the key at index `public_idx` in the `public_keys` set.
439		pub fn prover(&self, public_keys: &[Public], public_idx: usize) -> RingProver {
440			let pks = Self::make_ring_vector(public_keys);
441			let prover_key = self.0.prover_key(&pks).expect("ring size within bounds; qed");
442			self.0.ring_context().ring_prover(prover_key, public_idx)
443		}
444
445		/// Get ring verifier for the `public_keys` set.
446		pub fn verifier(&self, public_keys: &[Public]) -> RingVerifier {
447			let vk = self.verifier_key(public_keys);
448			self.0.ring_context().ring_verifier(vk.0)
449		}
450
451		/// Build `RingVerifierKey` for lazy `RingVerifier` construction.
452		pub fn verifier_key(&self, public_keys: &[Public]) -> RingVerifierKey {
453			let pks = Self::make_ring_vector(public_keys);
454			RingVerifierKey(self.0.verifier_key(&pks).expect("ring size within bounds; qed"))
455		}
456
457		/// Constructs a `RingVerifier` from a `VerifierKey` without a `RingContext` instance.
458		///
459		/// While this approach is computationally slightly less efficient than using a
460		/// pre-constructed `RingContext`, as some parameters need to be computed on-the-fly, it
461		/// is beneficial in memory or storage constrained environments. This avoids the need to
462		/// retain the full `RingContext` for ring signature verification. Instead, the
463		/// `VerifierKey` contains only the essential information needed to verify ring proofs.
464		pub fn verifier_no_context(verifier_key: RingVerifierKey) -> RingVerifier {
465			bandersnatch::RingContext::new(R).into_ring_verifier(verifier_key.0)
466		}
467
468		// A key that fails the checked decode takes the padding slot, for example the identity
469		// or a point out of the prime-order subgroup. Nobody knows the secret of the padding
470		// point, so that slot cannot sign, and a bad key cannot make the ring builder panic.
471		fn make_ring_vector(public_keys: &[Public]) -> Vec<bandersnatch::Public> {
472			public_keys
473				.iter()
474				.map(|pk| {
475					bandersnatch::Public::deserialize_compressed_exact(pk.as_slice())
476						.unwrap_or(bandersnatch::Public::padding())
477				})
478				.collect()
479		}
480	}
481
482	impl<const R: usize> Encode for RingContext<R> {
483		fn encode(&self) -> Vec<u8> {
484			let mut buf = Vec::with_capacity(ring_context_serialized_size(R));
485			self.0
486				.serialize_uncompressed(&mut buf)
487				.expect("serialization length is constant and checked by test; qed");
488			buf
489		}
490	}
491
492	impl<const R: usize> Decode for RingContext<R> {
493		fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
494			let mut buf = vec![0; ring_context_serialized_size(R)];
495			input.read(&mut buf[..])?;
496			// The SRS comes from a trusted setup, and a check of all its points costs too much.
497			let ctx = RingSetup::deserialize_uncompressed_unchecked_exact(buf.as_slice())
498				.map_err(|_| "RingContext decode error")?;
499			Ok(RingContext(ctx))
500		}
501	}
502
503	impl<const R: usize> EncodeLike for RingContext<R> {}
504
505	impl<const R: usize> MaxEncodedLen for RingContext<R> {
506		fn max_encoded_len() -> usize {
507			ring_context_serialized_size(R)
508		}
509	}
510
511	impl<const R: usize> TypeInfo for RingContext<R> {
512		type Identity = Self;
513		fn type_info() -> scale_info::Type {
514			let path = scale_info::Path::new("RingContext", module_path!());
515			let array_type_def = scale_info::TypeDefArray {
516				len: ring_context_serialized_size(R) as u32,
517				type_param: scale_info::MetaType::new::<u8>(),
518			};
519			let type_def = scale_info::TypeDef::Array(array_type_def);
520			scale_info::Type { path, type_params: Vec::new(), type_def, docs: Vec::new() }
521		}
522	}
523
524	/// Ring VRF signature.
525	#[derive(
526		Clone, Debug, PartialEq, Eq, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo,
527	)]
528	pub struct RingVrfSignature {
529		/// VRF pre-output.
530		pub pre_output: VrfPreOutput,
531		/// Ring signature.
532		pub proof: [u8; RING_PROOF_SERIALIZED_SIZE],
533	}
534
535	#[cfg(feature = "full_crypto")]
536	impl Pair {
537		/// Produce a ring-vrf signature.
538		///
539		/// The ring signature is verifiable if the public key corresponding to the
540		/// signing [`Pair`] is part of the ring from which the [`RingProver`] has
541		/// been constructed. If not, the produced signature is just useless.
542		pub fn ring_vrf_sign(&self, data: &VrfSignData, prover: &RingProver) -> RingVrfSignature {
543			let pre_output_impl = self.secret.output(data.vrf_input.0);
544			let pre_output = VrfPreOutput(pre_output_impl);
545			let io = VrfIo { input: data.vrf_input.0, output: pre_output.0 };
546			let proof_impl = self.secret.prove_ring(io, &data.aux_data, prover);
547			let mut proof = [0; RING_PROOF_SERIALIZED_SIZE];
548			proof_impl
549				.serialize_compressed(proof.as_mut_slice())
550				.expect("serialization length is constant and checked by test; qed");
551			RingVrfSignature { pre_output, proof }
552		}
553	}
554
555	impl RingVrfSignature {
556		/// Verify a ring-vrf signature.
557		///
558		/// The signature is verifiable if it has been produced by a member of the ring
559		/// from which the [`RingVerifier`] has been constructed.
560		pub fn ring_vrf_verify(&self, data: &VrfSignData, verifier: &RingVerifier) -> bool {
561			let Ok(proof) =
562				bandersnatch::RingProof::deserialize_compressed_exact(self.proof.as_slice())
563			else {
564				return false;
565			};
566			let io = VrfIo { input: data.vrf_input.0, output: self.pre_output.0 };
567			proof.verify(io, &data.aux_data, verifier).is_ok()
568		}
569	}
570}
571
572#[cfg(test)]
573mod tests {
574	use super::{ring_vrf::*, vrf::*, *};
575	use crate::{
576		crypto::{VrfPublic, VrfSecret, DEV_PHRASE},
577		proof_of_possession::{ProofOfPossessionGenerator, ProofOfPossessionVerifier},
578	};
579
580	const TEST_SEED: &[u8; SEED_SERIALIZED_SIZE] = &[0xcb; SEED_SERIALIZED_SIZE];
581	const TEST_RING_SIZE: usize = 16;
582
583	type TestRingContext = RingContext<TEST_RING_SIZE>;
584
585	#[allow(unused)]
586	fn b2h(bytes: &[u8]) -> String {
587		array_bytes::bytes2hex("", bytes)
588	}
589
590	fn h2b(hex: &str) -> Vec<u8> {
591		array_bytes::hex2bytes_unchecked(hex)
592	}
593
594	#[test]
595	fn backend_assumptions_sanity_check() {
596		use bandersnatch::{Input, RingSetup};
597
598		let ctx = RingSetup::from_seed_insecure(TEST_RING_SIZE, [0_u8; 32]);
599
600		let domain_size = ark_vrf::ring::pcs_domain_size::<BandersnatchSuite>(TEST_RING_SIZE);
601		assert_eq!(domain_size, ctx.pcs_params().powers_in_g1.len());
602		let domain_size2 =
603			ark_vrf::ring::pcs_domain_size::<BandersnatchSuite>(ctx.ring_context().max_ring_size());
604		assert_eq!(domain_size, domain_size2);
605		assert_eq!(
606			ark_vrf::ring::max_ring_size_from_pcs_domain_size::<BandersnatchSuite>(domain_size),
607			Some(ctx.ring_context().max_ring_size())
608		);
609
610		assert_eq!(ctx.uncompressed_size(), ring_context_serialized_size(TEST_RING_SIZE));
611
612		let prover_key_index = 3;
613		let secret = Secret::from_seed([prover_key_index as u8; 32]);
614		let public = secret.public();
615		assert_eq!(public.compressed_size(), PUBLIC_SERIALIZED_SIZE);
616
617		let input = Input::new(b"foo").unwrap();
618		let preout = secret.output(input);
619		assert_eq!(preout.compressed_size(), PREOUT_SERIALIZED_SIZE);
620
621		let ring_keys: Vec<_> =
622			(0..TEST_RING_SIZE).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
623
624		let verifier_key = ctx.verifier_key(&ring_keys[..]).expect("valid ring; qed");
625		assert_eq!(verifier_key.compressed_size(), RING_VERIFIER_KEY_SERIALIZED_SIZE);
626
627		let prover_key = ctx.prover_key(&ring_keys).expect("valid ring; qed");
628		let ring_prover = ctx.ring_context().ring_prover(prover_key, prover_key_index);
629
630		{
631			let io = VrfIo { input, output: preout };
632			let proof = secret.prove_thin(io, &[]);
633			assert_eq!(proof.compressed_size(), SIGNATURE_SERIALIZED_SIZE);
634		}
635
636		{
637			let io = VrfIo { input, output: preout };
638			let proof = secret.prove_ring(io, &[], &ring_prover);
639			assert_eq!(proof.compressed_size(), RING_PROOF_SERIALIZED_SIZE);
640		}
641	}
642
643	#[test]
644	fn derive_works() {
645		let pair = Pair::from_string(&format!("{}//Alice//Hard", DEV_PHRASE), None).unwrap();
646		let known = h2b("915626c7d4363856277e3dc0729c11df1f5a1caa1d3d0ec4986f0ae9226c5c45");
647		assert_eq!(pair.public().as_ref(), known);
648
649		// Soft derivation not supported
650		let res = Pair::from_string(&format!("{}//Alice/Soft", DEV_PHRASE), None);
651		assert!(res.is_err());
652	}
653
654	#[test]
655	fn generate_with_phrase_should_be_recoverable_with_from_string() {
656		let (pair, phrase, seed) = Pair::generate_with_phrase(None);
657		let repair_seed = Pair::from_seed_slice(seed.as_ref()).expect("seed slice is valid");
658		assert_eq!(pair.public(), repair_seed.public());
659		let (repair_phrase, reseed) =
660			Pair::from_phrase(phrase.as_ref(), None).expect("seed slice is valid");
661		assert_eq!(seed, reseed);
662		assert_eq!(pair.public(), repair_phrase.public());
663		let repair_string = Pair::from_string(phrase.as_str(), None).expect("seed slice is valid");
664		assert_eq!(pair.public(), repair_string.public());
665	}
666
667	#[test]
668	fn sign_verify() {
669		let pair = Pair::from_seed(TEST_SEED);
670		let public = pair.public();
671		let msg = b"foo";
672		let signature = pair.sign(msg);
673		assert!(Pair::verify(&signature, msg, &public));
674	}
675
676	#[test]
677	fn vrf_sign_verify() {
678		let pair = Pair::from_seed(TEST_SEED);
679		let public = pair.public();
680		let data = VrfSignData::new(b"foo", b"aux");
681		let signature = pair.vrf_sign(&data);
682		assert!(public.vrf_verify(&data, &signature));
683	}
684
685	#[test]
686	fn vrf_sign_verify_with_bad_input() {
687		let pair = Pair::from_seed(TEST_SEED);
688		let public = pair.public();
689		let data = VrfSignData::new(b"foo", b"aux");
690		let signature = pair.vrf_sign(&data);
691		let data = VrfSignData::new(b"foo", b"bad");
692		assert!(!public.vrf_verify(&data, &signature));
693		let data = VrfSignData::new(b"bar", b"aux");
694		assert!(!public.vrf_verify(&data, &signature));
695	}
696
697	#[test]
698	fn vrf_output_bytes_match() {
699		let pair = Pair::from_seed(TEST_SEED);
700		let data = VrfSignData::new(b"foo", b"aux");
701		let signature = pair.vrf_sign(&data);
702		let o0 = pair.make_bytes(&data.vrf_input);
703		let o1 = signature.pre_output.make_bytes();
704		assert_eq!(o0, o1);
705	}
706
707	#[test]
708	fn vrf_signature_encode_decode() {
709		let pair = Pair::from_seed(TEST_SEED);
710
711		let data = VrfSignData::new(b"data", b"aux");
712		let expected = pair.vrf_sign(&data);
713
714		let bytes = expected.encode();
715
716		let expected_len = PREOUT_SERIALIZED_SIZE + SIGNATURE_SERIALIZED_SIZE;
717		assert_eq!(bytes.len(), expected_len);
718
719		let decoded = VrfSignature::decode(&mut bytes.as_slice()).unwrap();
720		assert_eq!(expected, decoded);
721	}
722
723	#[test]
724	fn ring_vrf_sign_verify() {
725		let ring_ctx = TestRingContext::new_testing();
726
727		let mut pks: Vec<_> =
728			(0..TEST_RING_SIZE).map(|i| Pair::from_seed(&[i as u8; 32]).public()).collect();
729		assert!(pks.len() <= ring_ctx.max_keyset_size());
730
731		let pair = Pair::from_seed(TEST_SEED);
732
733		// Just pick one index to patch with the actual public key
734		let prover_idx = 3;
735		pks[prover_idx] = pair.public();
736		let prover = ring_ctx.prover(&pks, prover_idx);
737
738		let data = VrfSignData::new(b"data", b"aux");
739		let signature = pair.ring_vrf_sign(&data, &prover);
740
741		let verifier = ring_ctx.verifier(&pks);
742		assert!(signature.ring_vrf_verify(&data, &verifier));
743	}
744
745	#[test]
746	fn ring_vrf_sign_verify_with_out_of_ring_key() {
747		let ring_ctx = TestRingContext::new_testing();
748
749		let pks: Vec<_> =
750			(0..TEST_RING_SIZE).map(|i| Pair::from_seed(&[i as u8; 32]).public()).collect();
751		let pair = Pair::from_seed(TEST_SEED);
752
753		let data = VrfSignData::new(b"foo", b"aux");
754
755		// pair.public != pks[0]
756		let prover = ring_ctx.prover(&pks, 0);
757		let signature = pair.ring_vrf_sign(&data, &prover);
758
759		let verifier = ring_ctx.verifier(&pks);
760		assert!(!signature.ring_vrf_verify(&data, &verifier));
761	}
762
763	#[test]
764	fn ring_vrf_make_bytes_matches() {
765		let ring_ctx = TestRingContext::new_testing();
766
767		let mut pks: Vec<_> =
768			(0..TEST_RING_SIZE).map(|i| Pair::from_seed(&[i as u8; 32]).public()).collect();
769		assert!(pks.len() <= ring_ctx.max_keyset_size());
770
771		let pair = Pair::from_seed(TEST_SEED);
772
773		// Just pick one index to patch with the actual public key
774		let prover_idx = 3;
775		pks[prover_idx] = pair.public();
776
777		let data = VrfSignData::new(b"data", b"aux");
778
779		let prover = ring_ctx.prover(&pks, prover_idx);
780		let signature = pair.ring_vrf_sign(&data, &prover);
781
782		let o0 = pair.make_bytes(&data.vrf_input);
783		let o1 = signature.pre_output.make_bytes();
784		assert_eq!(o0, o1);
785	}
786
787	#[test]
788	fn ring_vrf_signature_encode_decode() {
789		let ring_ctx = TestRingContext::new_testing();
790
791		let mut pks: Vec<_> =
792			(0..TEST_RING_SIZE).map(|i| Pair::from_seed(&[i as u8; 32]).public()).collect();
793		assert!(pks.len() <= ring_ctx.max_keyset_size());
794
795		let pair = Pair::from_seed(TEST_SEED);
796
797		// Just pick one index to patch with the actual public key
798		let prover_idx = 3;
799		pks[prover_idx] = pair.public();
800
801		let data = VrfSignData::new(b"foo", b"aux");
802
803		let prover = ring_ctx.prover(&pks, prover_idx);
804		let expected = pair.ring_vrf_sign(&data, &prover);
805
806		let bytes = expected.encode();
807		assert_eq!(bytes.len(), RING_SIGNATURE_SERIALIZED_SIZE);
808
809		let decoded = RingVrfSignature::decode(&mut bytes.as_slice()).unwrap();
810		assert_eq!(expected, decoded);
811	}
812
813	#[test]
814	fn ring_vrf_context_encode_decode() {
815		let ctx1 = TestRingContext::new_testing();
816		let enc1 = ctx1.encode();
817
818		assert_eq!(enc1.len(), ring_context_serialized_size(TEST_RING_SIZE));
819		assert_eq!(enc1.len(), TestRingContext::max_encoded_len());
820
821		let ctx2 = TestRingContext::decode(&mut enc1.as_slice()).unwrap();
822		let enc2 = ctx2.encode();
823
824		assert_eq!(enc1, enc2);
825	}
826
827	#[test]
828	fn verifier_key_encode_decode() {
829		let ring_ctx = TestRingContext::new_testing();
830
831		let pks: Vec<_> =
832			(0..TEST_RING_SIZE).map(|i| Pair::from_seed(&[i as u8; 32]).public()).collect();
833		assert!(pks.len() <= ring_ctx.max_keyset_size());
834
835		let verifier_key = ring_ctx.verifier_key(&pks);
836		let enc1 = verifier_key.encode();
837		assert_eq!(enc1.len(), RING_VERIFIER_KEY_SERIALIZED_SIZE);
838		assert_eq!(RingVerifierKey::max_encoded_len(), RING_VERIFIER_KEY_SERIALIZED_SIZE);
839
840		let vd2 = RingVerifierKey::decode(&mut enc1.as_slice()).unwrap();
841		let enc2 = vd2.encode();
842		assert_eq!(enc1, enc2);
843	}
844
845	// Ring keys come from outside, for example from the session keys that any validator sets,
846	// and Sassafras builds the ring from them in the runtime. An identity key must not panic
847	// the ring builder, and the ring proof assumes keys in the prime-order subgroup.
848	#[test]
849	fn ring_vrf_invalid_ring_keys_become_padding() {
850		use ark_vrf::reexports::ark_ff::{One, Zero};
851		use bandersnatch::{AffinePoint, BaseField};
852
853		fn public_from(point: impl CanonicalSerialize) -> Public {
854			let mut raw = [0; PUBLIC_SERIALIZED_SIZE];
855			point.serialize_compressed(raw.as_mut_slice()).unwrap();
856			Public::unchecked_from(raw)
857		}
858		let identity = public_from(AffinePoint::zero());
859		let order_two =
860			public_from(AffinePoint::new_unchecked(BaseField::zero(), -BaseField::one()));
861		let padding = public_from(bandersnatch::Public::padding());
862
863		let ring_ctx = TestRingContext::new_testing();
864		let mut pks: Vec<_> =
865			(0..TEST_RING_SIZE).map(|i| Pair::from_seed(&[i as u8; 32]).public()).collect();
866		let mut padded_pks = pks.clone();
867		pks[1] = identity;
868		pks[2] = order_two;
869		padded_pks[1] = padding;
870		padded_pks[2] = padding;
871
872		assert_eq!(
873			ring_ctx.verifier_key(&pks).encode(),
874			ring_ctx.verifier_key(&padded_pks).encode()
875		);
876	}
877
878	// A verifier key can come from untrusted bytes. A G1 point out of the prime-order subgroup
879	// makes the pairing checks unsound, so the decoder must reject it.
880	#[test]
881	fn verifier_key_decode_rejects_point_out_of_subgroup() {
882		const G1_COMPRESSED_SIZE: usize = 48;
883		const COMPRESSED_FLAG: u8 = 0x80;
884
885		let ring_ctx = TestRingContext::new_testing();
886		let pks: Vec<_> =
887			(0..TEST_RING_SIZE).map(|i| Pair::from_seed(&[i as u8; 32]).public()).collect();
888		let mut encoded = ring_ctx.verifier_key(&pks).encode();
889
890		// The last field is the ring selector commitment. The new value is the curve point
891		// with x = 0, which is not in the prime-order subgroup.
892		let commitment = encoded.len() - G1_COMPRESSED_SIZE;
893		encoded[commitment..].fill(0);
894		encoded[commitment] = COMPRESSED_FLAG;
895		assert!(bandersnatch::RingVerifierKey::deserialize_compressed_unchecked_exact(
896			encoded.as_slice()
897		)
898		.is_ok());
899
900		assert!(RingVerifierKey::decode(&mut encoded.as_slice()).is_err());
901	}
902
903	#[test]
904	fn good_proof_of_possession_should_work_bad_proof_of_possession_should_fail() {
905		let owner = b"owner";
906		let not_owner = b"not owner";
907		let mut pair = Pair::from_seed(b"12345678901234567890123456789012");
908		let other_pair = Pair::from_seed(b"23456789012345678901234567890123");
909		let proof_of_possession = pair.generate_proof_of_possession(owner);
910		assert!(Pair::verify_proof_of_possession(owner, &proof_of_possession, &pair.public()));
911		assert!(!Pair::verify_proof_of_possession(
912			owner,
913			&proof_of_possession,
914			&other_pair.public()
915		));
916		assert!(!Pair::verify_proof_of_possession(not_owner, &proof_of_possession, &pair.public()));
917	}
918}