Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] v2.1 helpers #6

Merged
merged 13 commits into from
Sep 2, 2018
7 changes: 3 additions & 4 deletions lighthouse/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ extern crate futures;

pub mod db;
pub mod client;
pub mod shuffling;
pub mod state;
pub mod sync;
pub mod utils;
pub mod config;

use std::path::PathBuf;
use std::path::PathBuf;

use slog::Drain;
use clap::{ Arg, App };
Expand Down Expand Up @@ -59,9 +58,9 @@ fn main() {
return;
}
}

// Log configuration
info!(log, "";
info!(log, "";
"data_dir" => &config.data_dir.to_str(),
"port" => &config.p2p_listen_port);

Expand Down
15 changes: 15 additions & 0 deletions lighthouse/state/chain_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pub struct ChainConfig {
pub cycle_length: u8,
pub shard_count: u16,
pub min_committee_size: u64,
}

impl ChainConfig {
pub fn standard() -> Self {
Self {
cycle_length: 8,
shard_count: 1024,
min_committee_size: 128,
}
}
}
11 changes: 0 additions & 11 deletions lighthouse/state/config.rs

This file was deleted.

3 changes: 2 additions & 1 deletion lighthouse/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use super::utils;
pub mod active_state;
pub mod attestation_record;
pub mod crystallized_state;
pub mod config;
pub mod chain_config;
pub mod block;
pub mod crosslink_record;
pub mod shard_and_committee;
pub mod transition;
pub mod validator_record;
4 changes: 3 additions & 1 deletion lighthouse/state/shard_and_committee.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

#[derive(Clone,Debug)]
pub struct ShardAndCommittee {
pub shard_id: u16,
pub committee: Vec<u32>
pub committee: Vec<usize>
}

impl ShardAndCommittee {
Expand Down
223 changes: 223 additions & 0 deletions lighthouse/state/transition/attestation_parent_hashes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
use super::Hash256;
use super::TransitionError;

/// This function is used to select the hashes used in
/// the signing of an AttestationRecord.
///
/// It either returns Result with a vector of length `cycle_length,` or
/// returns an Error.
///
/// This function corresponds to the `get_signed_parent_hashes` function
/// in the Python reference implentation.
///
/// See this slide for more information:
/// https://tinyurl.com/ybzn2spw
pub fn attestation_parent_hashes(
cycle_length: &u8,
block_slot: &u64,
attestation_slot: &u64,
current_hashes: &Vec<Hash256>,
oblique_hashes: &Vec<Hash256>)
-> Result<Vec<Hash256>, TransitionError>
{
// This cast places a limit on cycle_length. If you change it, check math
// for overflow.
let cycle_length: u64 = *cycle_length as u64;

if current_hashes.len() as u64 != (cycle_length * 2) {
return Err(TransitionError::InvalidInput(String::from(
"current_hashes.len() must equal cycle_length * 2")));
}
if attestation_slot >= block_slot {
return Err(TransitionError::InvalidInput(String::from(
"attestation_slot must be less than block_slot")));
}
if oblique_hashes.len() as u64 > cycle_length {
return Err(TransitionError::InvalidInput(String::from(
"oblique_hashes.len() must be <= cycle_length * 2")));
}

/*
* Cannot underflow as block_slot cannot be less
* than attestation_slot.
*/
let attestation_distance = block_slot - attestation_slot;

if attestation_distance > cycle_length {
return Err(TransitionError::InvalidInput(String::from(
"attestation_slot must be withing one cycle of block_slot")));
}

/*
* Cannot underflow because attestation_distance cannot
* be larger than cycle_length.
*/
let start = cycle_length - attestation_distance;

/*
* Overflow is potentially impossible, but proof is complicated
* enough to just use checked math.
*
* Arithmetic is:
* start + cycle_length - oblique_hashes.len()
*/
let end = start.checked_add(cycle_length)
.and_then(|x| x.checked_sub(oblique_hashes.len() as u64))
.ok_or(TransitionError::IntWrapping)?;


let mut hashes = Vec::new();
hashes.extend_from_slice(
&current_hashes[(start as usize)..(end as usize)]);
hashes.append(&mut oblique_hashes.clone());

Ok(hashes)
}


#[cfg(test)]
mod tests {
use super::*;

fn get_range_of_hashes(from: usize, to: usize) -> Vec<Hash256> {
(from..to).map(|i| get_hash(&vec![i as u8])).collect()
}

fn get_hash(value: &[u8]) -> Hash256 {
Hash256::from_slice(value)
}

#[test]
fn test_get_signed_hashes_oblique_scenario_1() {
/*
* Two oblique hashes.
*/
let cycle_length: u8 = 8;
let block_slot: u64 = 19;
let attestation_slot: u64 = 15;
let current_hashes = get_range_of_hashes(3, 19);
let oblique_hashes = get_range_of_hashes(100, 102);
let result = attestation_parent_hashes(
&cycle_length,
&block_slot,
&attestation_slot,
&current_hashes,
&oblique_hashes);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(result.len(), cycle_length as usize);

let mut expected_result = get_range_of_hashes(7, 13);
expected_result.append(&mut get_range_of_hashes(100, 102));
assert_eq!(result, expected_result);
}

#[test]
fn test_get_signed_hashes_oblique_scenario_2() {
/*
* All oblique hashes.
*/
let cycle_length: u8 = 8;
let block_slot: u64 = 19;
let attestation_slot: u64 = 15;
let current_hashes = get_range_of_hashes(3, 19);
let oblique_hashes = get_range_of_hashes(100, 108);
let result = attestation_parent_hashes(
&cycle_length,
&block_slot,
&attestation_slot,
&current_hashes,
&oblique_hashes);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(result.len(), cycle_length as usize);

let expected_result = get_range_of_hashes(100, 108);
assert_eq!(result, expected_result);
}

#[test]
fn test_get_signed_hashes_scenario_1() {
/*
* Google Slides example.
* https://tinyurl.com/ybzn2spw
*/
let cycle_length: u8 = 8;
let block_slot: u64 = 19;
let attestation_slot: u64 = 15;
let current_hashes = get_range_of_hashes(3, 19);
let oblique_hashes = vec![];
let result = attestation_parent_hashes(
&cycle_length,
&block_slot,
&attestation_slot,
&current_hashes,
&oblique_hashes);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(result.len(), cycle_length as usize);
let expected_result = get_range_of_hashes(7, 15);
assert_eq!(result, expected_result);
}

#[test]
fn test_get_signed_hashes_scenario_2() {
/*
* Block 1, attestation 0.
*/
let cycle_length: u8 = 8;
let block_slot: u64 = 1;
let attestation_slot: u64 = 0;
let current_hashes = get_range_of_hashes(0, 16);
let oblique_hashes = vec![];
let result = attestation_parent_hashes(
&cycle_length,
&block_slot,
&attestation_slot,
&current_hashes,
&oblique_hashes);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(result.len(), cycle_length as usize);
let expected_result = get_range_of_hashes(7, 15);
assert_eq!(result, expected_result);
}

#[test]
fn test_get_signed_hashes_scenario_3() {
/*
* attestation_slot too large
*/
let cycle_length: u8 = 8;
let block_slot: u64 = 100;
let attestation_slot: u64 = 100;
let current_hashes = get_range_of_hashes(0, 16);
let oblique_hashes = vec![];
let result = attestation_parent_hashes(
&cycle_length,
&block_slot,
&attestation_slot,
&current_hashes,
&oblique_hashes);
assert!(result.is_err());
}

#[test]
fn test_get_signed_hashes_scenario_4() {
/*
* Current hashes too small
*/
let cycle_length: u8 = 8;
let block_slot: u64 = 100;
let attestation_slot: u64 = 99;
let current_hashes = get_range_of_hashes(0, 15);
let oblique_hashes = vec![];
let result = attestation_parent_hashes(
&cycle_length,
&block_slot,
&attestation_slot,
&current_hashes,
&oblique_hashes);
assert!(result.is_err());
}
}
17 changes: 17 additions & 0 deletions lighthouse/state/transition/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use super::super::utils::types::Hash256;

mod attestation_parent_hashes;
mod shuffling;

pub use self::attestation_parent_hashes::attestation_parent_hashes;
pub use self::shuffling::shuffle;

#[derive(Debug)]
pub enum TransitionError {
IntWrapping,
OutOfBounds,
InvalidInput(String),
}



2 changes: 2 additions & 0 deletions lighthouse/state/transition/shuffling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This module includes the fundamental shuffling function. It does not do the
full validator delegation amongst slots.
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ pub enum ShuffleErr {
ExceedsListLength,
}

/// Performs a deterministic, in-place shuffle of a vector of bytes.
/// Performs a deterministic, in-place shuffle of a vector of bytes.
/// The final order of the shuffle is determined by successive hashes
/// of the supplied `seed`.
pub fn shuffle(
seed: &[u8],
mut list: Vec<usize>)
mut list: Vec<usize>)
-> Result<Vec<usize>, ShuffleErr>
{
let mut rng = ShuffleRng::new(seed);
if list.len() > rng.rand_max as usize {
return Err(ShuffleErr::ExceedsListLength);
}
}
for i in 0..(list.len() - 1) {
let n = list.len() - i;
let j = rng.rand_range(n as u32) as usize + i;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,22 @@ mod tests {
&[0, 1, 1],
0);
assert_eq!(x, 257);

x = int_from_byte_slice(
&[1, 1, 1],
0);
assert_eq!(x, 65793);

x = int_from_byte_slice(
&[255, 1, 1],
0);
assert_eq!(x, 16711937);

x = int_from_byte_slice(
&[255, 255, 255],
0);
assert_eq!(x, 16777215);

x = int_from_byte_slice(
&[0x8f, 0xbb, 0xc7],
0);
Expand Down