Break split function into its own crate.

- Added tests
- Remove it from the delegation dir
- Added it as a crate in utils
This commit is contained in:
Paul Hauner 2018-10-10 16:09:00 +11:00
parent ddc8037487
commit 9717698f7b
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
7 changed files with 96 additions and 46 deletions

View File

@ -37,6 +37,7 @@ members = [
"beacon_chain/utils/bls", "beacon_chain/utils/bls",
"beacon_chain/utils/boolean-bitfield", "beacon_chain/utils/boolean-bitfield",
"beacon_chain/utils/hashing", "beacon_chain/utils/hashing",
"beacon_chain/utils/honey-badger-split",
"beacon_chain/utils/shuffling", "beacon_chain/utils/shuffling",
"beacon_chain/utils/ssz", "beacon_chain/utils/ssz",
"beacon_chain/utils/ssz_helpers", "beacon_chain/utils/ssz_helpers",

View File

@ -4,5 +4,6 @@ version = "0.1.0"
authors = ["Age Manning <Age@AgeManning.com>"] authors = ["Age Manning <Age@AgeManning.com>"]
[dependencies] [dependencies]
honey-badger-split = { path = "../utils/honey-badger-split" }
types = { path = "../types" } types = { path = "../types" }
shuffling = { path = "../utils/shuffling" } shuffling = { path = "../utils/shuffling" }

View File

@ -1,3 +1,4 @@
use super::honey_badger_split;
use super::types; use super::types;
use super::TransitionError; use super::TransitionError;
use super::shuffling::shuffle; use super::shuffling::shuffle;

View File

@ -1,3 +1,4 @@
use super::honey_badger_split::SplitExt;
use super::types::{ShardAndCommittee, ValidatorRecord, ChainConfig}; use super::types::{ShardAndCommittee, ValidatorRecord, ChainConfig};
use super::TransitionError; use super::TransitionError;
use super::shuffle; use super::shuffle;
@ -5,52 +6,6 @@ use std::cmp::min;
type DelegatedCycle = Vec<Vec<ShardAndCommittee>>; type DelegatedCycle = Vec<Vec<ShardAndCommittee>>;
/// Iterator for the honey_badger_split function
struct Split<'a, T: 'a> {
n: usize,
current_pos: usize,
list: &'a [T],
list_length: usize
}
impl<'a,T> Iterator for Split<'a, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
self.current_pos +=1;
if self.current_pos <= self.n {
match self.list.get(self.list_length*(self.current_pos-1)/self.n..self.list_length*self.current_pos/self.n) {
Some(v) => Some(v),
None => unreachable!()
}
}
else {
None
}
}
}
/// Splits a slice into chunks of size n. All postive n values are applicable,
/// hence the honey_badger prefix.
/// Returns an iterator over the original list.
trait SplitExt<T> {
fn honey_badger_split(&self, n: usize) -> Split<T>;
}
impl<T> SplitExt<T> for [T] {
fn honey_badger_split(&self, n: usize) -> Split<T> {
Split {
n,
current_pos: 0,
list: &self,
list_length: self.len(),
}
}
}
/// Produce a vector of validators indicies where those validators start and end /// Produce a vector of validators indicies where those validators start and end
/// dynasties are within the supplied `dynasty`. /// dynasties are within the supplied `dynasty`.
fn active_validator_indicies( fn active_validator_indicies(

View File

@ -1,3 +1,4 @@
extern crate honey_badger_split;
extern crate types; extern crate types;
extern crate shuffling; extern crate shuffling;

View File

@ -0,0 +1,6 @@
[package]
name = "honey-badger-split"
version = "0.1.0"
authors = ["Paul Hauner <paul@paulhauner.com>"]
[dependencies]

View File

@ -0,0 +1,85 @@
/// A function for splitting a list into N pieces.
///
/// We have titled it the "honey badger split" because of its robustness. It don't care.
/// Iterator for the honey_badger_split function
pub struct Split<'a, T: 'a> {
n: usize,
current_pos: usize,
list: &'a [T],
list_length: usize
}
impl<'a,T> Iterator for Split<'a, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
self.current_pos +=1;
if self.current_pos <= self.n {
match self.list.get(self.list_length*(self.current_pos-1)/self.n..self.list_length*self.current_pos/self.n) {
Some(v) => Some(v),
None => unreachable!()
}
}
else {
None
}
}
}
/// Splits a slice into chunks of size n. All postive n values are applicable,
/// hence the honey_badger prefix.
///
/// Returns an iterator over the original list.
pub trait SplitExt<T> {
fn honey_badger_split(&self, n: usize) -> Split<T>;
}
impl<T> SplitExt<T> for [T] {
fn honey_badger_split(&self, n: usize) -> Split<T> {
Split {
n,
current_pos: 0,
list: &self,
list_length: self.len(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_honey_badger_split() {
/*
* These test cases are generated from the eth2.0 spec `split()`
* function at commit cbd254a.
*/
let input: Vec<usize> = vec![0, 1, 2, 3];
let output: Vec<&[usize]> = input.honey_badger_split(2).collect();
assert_eq!(output, vec![&[0, 1], &[2, 3]]);
let input: Vec<usize> = vec![0, 1, 2, 3];
let output: Vec<&[usize]> = input.honey_badger_split(6).collect();
let expected: Vec<&[usize]> = vec![&[], &[0], &[1], &[], &[2], &[3]];
assert_eq!(output, expected);
let input: Vec<usize> = vec![0, 1, 2, 3];
let output: Vec<&[usize]> = input.honey_badger_split(10).collect();
let expected: Vec<&[usize]> = vec![&[], &[], &[0], &[], &[1], &[], &[], &[2], &[], &[3]];
assert_eq!(output, expected);
let input: Vec<usize> = vec![0];
let output: Vec<&[usize]> = input.honey_badger_split(5).collect();
let expected: Vec<&[usize]> = vec![&[], &[], &[], &[], &[0]];
assert_eq!(output, expected);
let input: Vec<usize> = vec![0, 1, 2];
let output: Vec<&[usize]> = input.honey_badger_split(2).collect();
let expected: Vec<&[usize]> = vec![&[0], &[1, 2]];
assert_eq!(output, expected);
}
}