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