commit
071041a03a
@ -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 };
|
||||
@ -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);
|
||||
|
||||
|
15
lighthouse/state/chain_config.rs
Normal file
15
lighthouse/state/chain_config.rs
Normal file
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
pub struct Config {
|
||||
pub cycle_length: u8,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn standard() -> Self {
|
||||
Self {
|
||||
cycle_length: 8,
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct ShardAndCommittee {
|
||||
pub shard_id: u16,
|
||||
pub committee: Vec<u32>
|
||||
pub committee: Vec<usize>
|
||||
}
|
||||
|
||||
impl ShardAndCommittee {
|
||||
|
223
lighthouse/state/transition/attestation_parent_hashes.rs
Normal file
223
lighthouse/state/transition/attestation_parent_hashes.rs
Normal file
@ -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(
|
||||
¤t_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,
|
||||
¤t_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,
|
||||
¤t_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,
|
||||
¤t_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,
|
||||
¤t_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,
|
||||
¤t_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,
|
||||
¤t_hashes,
|
||||
&oblique_hashes);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
17
lighthouse/state/transition/mod.rs
Normal file
17
lighthouse/state/transition/mod.rs
Normal file
@ -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
lighthouse/state/transition/shuffling/README.md
Normal file
2
lighthouse/state/transition/shuffling/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
This module includes the fundamental shuffling function. It does not do the
|
||||
full validator delegation amongst slots.
|
@ -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;
|
@ -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);
|
Loading…
Reference in New Issue
Block a user