BABE Randomness using PreRuntime digests (#2929)

* Initial work on exposing pre-runtime digests

This provides the primitive API, as well as exposing it from BABE.

* Initial work on using pre-digests in runtimes

This includes both code to expose them from `srml_system`, as well as
using it in (currently dead) code in `srml_babe`.

* Bump `{spec,impl}_version`

* Add `u64_backend` feature to curve25519-dalek

Otherwise, it errors out at compile-time.

* Bump `Cargo.lock`

* Do not depend on the schnorrkel crate in the runtime

The schnorrkel crate does not work on `#![no_std]`, but the runtime only
needs constants from it.  This adds our own definitions of those
constants, and checks them for correctness at compile-time.

* Actually implement storage of VRF outputs

* Trivial formatting change

* Provide a `hash_randomness` function in BABE

for processing VRF outputs.

* Implement a basic randomness generating function

It just XORs the VRF outputs together.

* Actually implement on-chain randomness

Blake2b is used for hashing.

* Update dependencies

* Run `cargo update` where needed

* Re-add a newline at EOF

* Remove broken and unsafe code

XOR is not a hash function, and must not be used as such.  The
implementation was also needlessly unsafe.

* Run `cargo update` where needed

* Remove spurious dependency

* Document security guarantees of BABE randomness

* Add a `RandomnessBeacon` trait

* Document `RandomnessBeacon::random`

* Fix silly compile error (unexpected type arguments)

* Fix BABE randomness

* Implement `FindAuthor` for `babe::Module`

* Apply suggestions from code review

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>
Co-Authored-By: Robert Habermeier <rphmeier@gmail.com>

* Respond to suggestions from code review and fix bugs

* Store an authority index, not the authority itself.
* Avoid unnecessary decoding.
* Implement relative slots and BABE randomness fully and correctly.

* Remove spurious dependency

* Fix error reported by rust-analyzer

* Update Cargo.lock files

* `wrapping_add` → `checked_add`

The epoch index will not overflow.  Panic if it does.

* Move randomness documentation to trait

* Fix compile error in test suite

* Explain 2^64 limit

Co-Authored-By: Robert Habermeier <rphmeier@gmail.com>
This commit is contained in:
DemiMarie-parity
2019-07-03 08:49:08 -04:00
committed by Gavin Wood
parent dcb1a590e2
commit 81d8a5d01d
18 changed files with 1810 additions and 1916 deletions
+14 -13
View File
@@ -16,15 +16,12 @@
//! Private implementation details of BABE digests.
use primitives::sr25519::{Public, Signature};
use babe_primitives::BABE_ENGINE_ID;
use primitives::sr25519::Signature;
use babe_primitives::{self, BABE_ENGINE_ID};
use runtime_primitives::{DigestItem, generic::OpaqueDigestItemId};
use std::fmt::Debug;
use parity_codec::{Decode, Encode, Codec, Input};
use schnorrkel::{
vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH},
PUBLIC_KEY_LENGTH,
};
use schnorrkel::{vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH}};
/// A BABE pre-digest. It includes:
///
@@ -36,26 +33,26 @@ use schnorrkel::{
pub struct BabePreDigest {
pub(super) vrf_output: VRFOutput,
pub(super) proof: VRFProof,
pub(super) author: Public,
pub(super) index: u64,
pub(super) slot_num: u64,
}
/// The prefix used by BABE for its VRF keys.
pub const BABE_VRF_PREFIX: &'static [u8] = b"substrate-babe-vrf";
type TmpDecode = (
type RawBabePreDigest = (
[u8; VRF_OUTPUT_LENGTH],
[u8; VRF_PROOF_LENGTH],
[u8; PUBLIC_KEY_LENGTH],
u64,
u64,
);
impl Encode for BabePreDigest {
fn encode(&self) -> Vec<u8> {
let tmp: TmpDecode = (
let tmp: RawBabePreDigest = (
*self.vrf_output.as_bytes(),
self.proof.to_bytes(),
self.author.0,
self.index,
self.slot_num,
);
parity_codec::Encode::encode(&tmp)
@@ -64,11 +61,15 @@ impl Encode for BabePreDigest {
impl Decode for BabePreDigest {
fn decode<R: Input>(i: &mut R) -> Option<Self> {
let (output, proof, public_key, slot_num): TmpDecode = Decode::decode(i)?;
let (output, proof, index, slot_num): RawBabePreDigest = Decode::decode(i)?;
// Verify (at compile time) that the sizes in babe_primitives are correct
let _: [u8; babe_primitives::VRF_OUTPUT_LENGTH] = output;
let _: [u8; babe_primitives::VRF_PROOF_LENGTH] = proof;
Some(BabePreDigest {
proof: VRFProof::from_bytes(&proof).ok()?,
vrf_output: VRFOutput::from_bytes(&output).ok()?,
author: Public(public_key),
index,
slot_num,
})
}