tp_consensus_vrf/
schnorrkel.rs

1// This file is part of Tetcore.
2
3// Copyright (C) 2019-2021 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//! Schnorrkel-based VRF.
19
20use codec::{Encode, Decode, EncodeLike};
21use tetcore_std::{convert::TryFrom, prelude::*};
22use tet_core::U512;
23use tetcore_std::ops::{Deref, DerefMut};
24use schnorrkel::errors::MultiSignatureStage;
25
26pub use schnorrkel::{SignatureError, PublicKey, vrf::{VRF_PROOF_LENGTH, VRF_OUTPUT_LENGTH}};
27
28/// The length of the Randomness.
29pub const RANDOMNESS_LENGTH: usize = VRF_OUTPUT_LENGTH;
30
31/// VRF output type available for `std` environment, suitable for schnorrkel operations.
32#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct VRFOutput(pub schnorrkel::vrf::VRFOutput);
34
35impl Deref for VRFOutput {
36	type Target = schnorrkel::vrf::VRFOutput;
37	fn deref(&self) -> &Self::Target { &self.0 }
38}
39
40impl DerefMut for VRFOutput {
41	fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
42}
43
44impl Encode for VRFOutput {
45	fn encode(&self) -> Vec<u8> {
46		self.0.as_bytes().encode()
47	}
48}
49
50impl EncodeLike for VRFOutput { }
51
52impl Decode for VRFOutput {
53	fn decode<R: codec::Input>(i: &mut R) -> Result<Self, codec::Error> {
54		let decoded = <[u8; VRF_OUTPUT_LENGTH]>::decode(i)?;
55		Ok(Self(schnorrkel::vrf::VRFOutput::from_bytes(&decoded).map_err(convert_error)?))
56	}
57}
58
59impl TryFrom<[u8; VRF_OUTPUT_LENGTH]> for VRFOutput {
60	type Error = SignatureError;
61
62	fn try_from(raw: [u8; VRF_OUTPUT_LENGTH]) -> Result<Self, Self::Error> {
63		schnorrkel::vrf::VRFOutput::from_bytes(&raw).map(VRFOutput)
64	}
65}
66
67/// VRF proof type available for `std` environment, suitable for schnorrkel operations.
68#[derive(Clone, Debug, PartialEq, Eq)]
69pub struct VRFProof(pub schnorrkel::vrf::VRFProof);
70
71impl PartialOrd for VRFProof {
72	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
73		Some(self.cmp(other))
74	}
75}
76
77impl Ord for VRFProof {
78	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
79		U512::from(self.0.to_bytes()).cmp(&U512::from(other.0.to_bytes()))
80	}
81}
82
83impl Deref for VRFProof {
84	type Target = schnorrkel::vrf::VRFProof;
85	fn deref(&self) -> &Self::Target { &self.0 }
86}
87
88impl DerefMut for VRFProof {
89	fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
90}
91
92impl Encode for VRFProof {
93	fn encode(&self) -> Vec<u8> {
94		self.0.to_bytes().encode()
95	}
96}
97
98impl EncodeLike for VRFProof { }
99
100impl Decode for VRFProof {
101	fn decode<R: codec::Input>(i: &mut R) -> Result<Self, codec::Error> {
102		let decoded = <[u8; VRF_PROOF_LENGTH]>::decode(i)?;
103		Ok(Self(schnorrkel::vrf::VRFProof::from_bytes(&decoded).map_err(convert_error)?))
104	}
105}
106
107impl TryFrom<[u8; VRF_PROOF_LENGTH]> for VRFProof {
108	type Error = SignatureError;
109
110	fn try_from(raw: [u8; VRF_PROOF_LENGTH]) -> Result<Self, Self::Error> {
111		schnorrkel::vrf::VRFProof::from_bytes(&raw).map(VRFProof)
112	}
113}
114
115fn convert_error(e: SignatureError) -> codec::Error {
116	use SignatureError::*;
117	use MultiSignatureStage::*;
118	match e {
119		EquationFalse => "Signature error: `EquationFalse`".into(),
120		PointDecompressionError => "Signature error: `PointDecompressionError`".into(),
121		ScalarFormatError => "Signature error: `ScalarFormatError`".into(),
122		NotMarkedSchnorrkel => "Signature error: `NotMarkedSchnorrkel`".into(),
123		BytesLengthError { .. } => "Signature error: `BytesLengthError`".into(),
124		MuSigAbsent { musig_stage: Commitment } =>
125			"Signature error: `MuSigAbsent` at stage `Commitment`".into(),
126		MuSigAbsent { musig_stage: Reveal } =>
127			"Signature error: `MuSigAbsent` at stage `Reveal`".into(),
128		MuSigAbsent { musig_stage: Cosignature } =>
129			"Signature error: `MuSigAbsent` at stage `Commitment`".into(),
130		MuSigInconsistent { musig_stage: Commitment, duplicate: true } =>
131			"Signature error: `MuSigInconsistent` at stage `Commitment` on duplicate".into(),
132		MuSigInconsistent { musig_stage: Commitment, duplicate: false } =>
133			"Signature error: `MuSigInconsistent` at stage `Commitment` on not duplicate".into(),
134		MuSigInconsistent { musig_stage: Reveal, duplicate: true } =>
135			"Signature error: `MuSigInconsistent` at stage `Reveal` on duplicate".into(),
136		MuSigInconsistent { musig_stage: Reveal, duplicate: false } =>
137			"Signature error: `MuSigInconsistent` at stage `Reveal` on not duplicate".into(),
138		MuSigInconsistent { musig_stage: Cosignature, duplicate: true } =>
139			"Signature error: `MuSigInconsistent` at stage `Cosignature` on duplicate".into(),
140		MuSigInconsistent { musig_stage: Cosignature, duplicate: false } =>
141			"Signature error: `MuSigInconsistent` at stage `Cosignature` on not duplicate".into(),
142	}
143}
144
145/// Schnorrkel randomness value. Same size as `VRFOutput`.
146pub type Randomness = [u8; RANDOMNESS_LENGTH];