Files
pezkuwi-subxt/substrate/primitives/consensus/vrf/src/schnorrkel.rs
T
Kian Paimani 970c5f94f2 Offchain Phragmén BREAKING. (#4517)
* Initial skeleton for offchain phragmen

* Basic compact encoding decoding for results

* add compact files

* Bring back Self::ensure_storage_upgraded();

* Make staking use compact stuff.

* First seemingly working version of reduce, full of todos

* Everything phragmen related works again.

* Signing made easier, still issues.

* Signing from offchain compile fine 😎

* make compact work with staked asssignment

* Evaluation basics are in place.

* Move reduce into crate. Document stuff

* move reduce into no_std

* Add files

* Remove other std deps. Runtime compiles

* Seemingly it is al stable; cycle implemented but not integrated.

* Add fuzzing code.

* Cleanup reduce a bit more.

* a metric ton of tests for staking; wip 🔨

* Implement a lot more of the tests.

* wip getting the unsigned stuff to work

* A bit gleanup for unsigned debug

* Clean and finalize compact code.

* Document reduce.

* Still problems with signing

* We officaly duct taped the transaction submission stuff. 🤓

* Deadlock with keys again

* Runtime builds

* Unsigned test works 🙌

* Some cleanups

* Make all the tests compile and stuff

* Minor cleanup

* fix more merge stuff

* Most tests work again.

* a very nasty bug in reduce

* Fix all integrations

* Fix more todos

* Revamp everything and everything

* Remove bogus test

* Some review grumbles.

* Some fixes

* Fix doc test

* loop for submission

* Fix cli, keyring etc.

* some cleanup

* Fix staking tests again

* fix per-things; bring patches from benchmarking

* better score prediction

* Add fuzzer, more patches.

* Some fixes

* More docs

* Remove unused generics

* Remove max-nominator footgun

* Better fuzzer

* Disable it 

* Bump.

* Another round of self-review

* Refactor a lot

* More major fixes in perThing

* Add new fuzz file

* Update lock

* fix fuzzing code.

* Fix nominator retain test

* Add slashing check

* Update frame/staking/src/tests.rs

Co-Authored-By: Joshy Orndorff <JoshOrndorff@users.noreply.github.com>

* Some formatting nits

* Review comments.

* Fix cargo file

* Almost all tests work again

* Update frame/staking/src/tests.rs

Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>

* Fix review comments

* More review stuff

* Some nits

* Fix new staking / session / babe relation

* Update primitives/phragmen/src/lib.rs

Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>

* Update primitives/phragmen/src/lib.rs

Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>

* Update primitives/phragmen/compact/src/lib.rs

Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>

* Some doc updates to slashing

* Fix derive

* Remove imports

* Remove unimplemented tests

* nits

* Remove dbg

* Better fuzzing params

* Remove unused pref map

* Deferred Slashing/Offence for offchain Phragmen  (#5151)

* Some boilerplate

* Add test

* One more test

* Review comments

* Fix build

* review comments

* fix more

* fix build

* Some cleanups and self-reviews

* More minor self reviews

* Final nits

* Some merge fixes.

* opt comment

* Fix build

* Fix build again.

* Update frame/staking/fuzz/fuzz_targets/submit_solution.rs

Co-Authored-By: Gavin Wood <gavin@parity.io>

* Update frame/staking/src/slashing.rs

Co-Authored-By: Gavin Wood <gavin@parity.io>

* Update frame/staking/src/offchain_election.rs

Co-Authored-By: Gavin Wood <gavin@parity.io>

* Fix review comments

* fix test

* === 🔑 Revamp without staking key.

* final round of changes.

* Fix cargo-deny

* Update frame/staking/src/lib.rs

Co-Authored-By: Gavin Wood <gavin@parity.io>

Co-authored-by: Joshy Orndorff <JoshOrndorff@users.noreply.github.com>
Co-authored-by: thiolliere <gui.thiolliere@gmail.com>
Co-authored-by: Gavin Wood <gavin@parity.io>
2020-03-26 15:37:40 +01:00

251 lines
7.5 KiB
Rust

// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Schnorrkel-based VRF.
use codec::{Encode, Decode};
use sp_runtime::RuntimeDebug;
use sp_std::ops::{Deref, DerefMut};
#[cfg(feature = "std")]
use std::convert::TryFrom;
#[cfg(feature = "std")]
use codec::EncodeLike;
#[cfg(feature = "std")]
use schnorrkel::errors::MultiSignatureStage;
#[cfg(feature = "std")]
use sp_core::U512;
#[cfg(feature = "std")]
pub use schnorrkel::{SignatureError, vrf::{VRF_PROOF_LENGTH, VRF_OUTPUT_LENGTH}};
/// The length of the VRF proof.
#[cfg(not(feature = "std"))]
pub const VRF_PROOF_LENGTH: usize = 64;
/// The length of the VRF output.
#[cfg(not(feature = "std"))]
pub const VRF_OUTPUT_LENGTH: usize = 32;
/// The length of the Randomness.
pub const RANDOMNESS_LENGTH: usize = VRF_OUTPUT_LENGTH;
/// Raw VRF output.
#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode)]
pub struct RawVRFOutput(pub [u8; VRF_OUTPUT_LENGTH]);
impl Deref for RawVRFOutput {
type Target = [u8; VRF_OUTPUT_LENGTH];
fn deref(&self) -> &Self::Target { &self.0 }
}
impl DerefMut for RawVRFOutput {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
/// VRF output type available for `std` environment, suitable for schnorrkel operations.
#[cfg(feature = "std")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VRFOutput(pub schnorrkel::vrf::VRFOutput);
#[cfg(feature = "std")]
impl Deref for VRFOutput {
type Target = schnorrkel::vrf::VRFOutput;
fn deref(&self) -> &Self::Target { &self.0 }
}
#[cfg(feature = "std")]
impl DerefMut for VRFOutput {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
#[cfg(feature = "std")]
impl Encode for VRFOutput {
fn encode(&self) -> Vec<u8> {
self.0.as_bytes().encode()
}
}
#[cfg(feature = "std")]
impl EncodeLike for VRFOutput { }
#[cfg(feature = "std")]
impl Decode for VRFOutput {
fn decode<R: codec::Input>(i: &mut R) -> Result<Self, codec::Error> {
let decoded = <[u8; VRF_OUTPUT_LENGTH]>::decode(i)?;
Ok(Self(schnorrkel::vrf::VRFOutput::from_bytes(&decoded).map_err(convert_error)?))
}
}
#[cfg(feature = "std")]
impl TryFrom<[u8; VRF_OUTPUT_LENGTH]> for VRFOutput {
type Error = SignatureError;
fn try_from(raw: [u8; VRF_OUTPUT_LENGTH]) -> Result<Self, Self::Error> {
schnorrkel::vrf::VRFOutput::from_bytes(&raw).map(VRFOutput)
}
}
#[cfg(feature = "std")]
impl TryFrom<RawVRFOutput> for VRFOutput {
type Error = SignatureError;
fn try_from(raw: RawVRFOutput) -> Result<VRFOutput, Self::Error> {
schnorrkel::vrf::VRFOutput::from_bytes(&raw.0).map(VRFOutput)
}
}
#[cfg(feature = "std")]
impl From<VRFOutput> for RawVRFOutput {
fn from(output: VRFOutput) -> RawVRFOutput {
RawVRFOutput(output.to_bytes())
}
}
/// Raw VRF proof.
#[derive(Clone, Copy, Encode, Decode)]
pub struct RawVRFProof(pub [u8; VRF_PROOF_LENGTH]);
impl Deref for RawVRFProof {
type Target = [u8; VRF_PROOF_LENGTH];
fn deref(&self) -> &Self::Target { &self.0 }
}
impl DerefMut for RawVRFProof {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
#[cfg(feature = "std")]
impl std::fmt::Debug for RawVRFProof {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", &self)
}
}
impl core::cmp::PartialEq for RawVRFProof {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
impl core::cmp::Eq for RawVRFProof { }
/// VRF proof type available for `std` environment, suitable for schnorrkel operations.
#[cfg(feature = "std")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VRFProof(pub schnorrkel::vrf::VRFProof);
#[cfg(feature = "std")]
impl PartialOrd for VRFProof {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[cfg(feature = "std")]
impl Ord for VRFProof {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
U512::from(self.0.to_bytes()).cmp(&U512::from(other.0.to_bytes()))
}
}
#[cfg(feature = "std")]
impl Deref for VRFProof {
type Target = schnorrkel::vrf::VRFProof;
fn deref(&self) -> &Self::Target { &self.0 }
}
#[cfg(feature = "std")]
impl DerefMut for VRFProof {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
#[cfg(feature = "std")]
impl Encode for VRFProof {
fn encode(&self) -> Vec<u8> {
self.0.to_bytes().encode()
}
}
#[cfg(feature = "std")]
impl EncodeLike for VRFProof { }
#[cfg(feature = "std")]
impl Decode for VRFProof {
fn decode<R: codec::Input>(i: &mut R) -> Result<Self, codec::Error> {
let decoded = <[u8; VRF_PROOF_LENGTH]>::decode(i)?;
Ok(Self(schnorrkel::vrf::VRFProof::from_bytes(&decoded).map_err(convert_error)?))
}
}
#[cfg(feature = "std")]
impl TryFrom<[u8; VRF_PROOF_LENGTH]> for VRFProof {
type Error = SignatureError;
fn try_from(raw: [u8; VRF_PROOF_LENGTH]) -> Result<Self, Self::Error> {
schnorrkel::vrf::VRFProof::from_bytes(&raw).map(VRFProof)
}
}
#[cfg(feature = "std")]
impl TryFrom<RawVRFProof> for VRFProof {
type Error = SignatureError;
fn try_from(raw: RawVRFProof) -> Result<VRFProof, Self::Error> {
schnorrkel::vrf::VRFProof::from_bytes(&raw.0).map(VRFProof)
}
}
#[cfg(feature = "std")]
impl From<VRFProof> for RawVRFProof {
fn from(output: VRFProof) -> RawVRFProof {
RawVRFProof(output.to_bytes())
}
}
#[cfg(feature = "std")]
fn convert_error(e: SignatureError) -> codec::Error {
use SignatureError::*;
use MultiSignatureStage::*;
match e {
EquationFalse => "Signature error: `EquationFalse`".into(),
PointDecompressionError => "Signature error: `PointDecompressionError`".into(),
ScalarFormatError => "Signature error: `ScalarFormatError`".into(),
NotMarkedSchnorrkel => "Signature error: `NotMarkedSchnorrkel`".into(),
BytesLengthError { .. } => "Signature error: `BytesLengthError`".into(),
MuSigAbsent { musig_stage: Commitment } =>
"Signature error: `MuSigAbsent` at stage `Commitment`".into(),
MuSigAbsent { musig_stage: Reveal } =>
"Signature error: `MuSigAbsent` at stage `Reveal`".into(),
MuSigAbsent { musig_stage: Cosignature } =>
"Signature error: `MuSigAbsent` at stage `Commitment`".into(),
MuSigInconsistent { musig_stage: Commitment, duplicate: true } =>
"Signature error: `MuSigInconsistent` at stage `Commitment` on duplicate".into(),
MuSigInconsistent { musig_stage: Commitment, duplicate: false } =>
"Signature error: `MuSigInconsistent` at stage `Commitment` on not duplicate".into(),
MuSigInconsistent { musig_stage: Reveal, duplicate: true } =>
"Signature error: `MuSigInconsistent` at stage `Reveal` on duplicate".into(),
MuSigInconsistent { musig_stage: Reveal, duplicate: false } =>
"Signature error: `MuSigInconsistent` at stage `Reveal` on not duplicate".into(),
MuSigInconsistent { musig_stage: Cosignature, duplicate: true } =>
"Signature error: `MuSigInconsistent` at stage `Cosignature` on duplicate".into(),
MuSigInconsistent { musig_stage: Cosignature, duplicate: false } =>
"Signature error: `MuSigInconsistent` at stage `Cosignature` on not duplicate".into(),
}
}
/// Schnorrkel randomness value. Same size as `VRFOutput`.
pub type Randomness = [u8; RANDOMNESS_LENGTH];