Progress on parent hash selection. Add test.
This commit is contained in:
parent
8ba7601ab3
commit
859c48d5e5
@ -2,38 +2,62 @@ use super::Hash256;
|
|||||||
use super::TransitionError;
|
use super::TransitionError;
|
||||||
|
|
||||||
pub fn get_signed_parent_hashes(
|
pub fn get_signed_parent_hashes(
|
||||||
cycle_length: u64,
|
cycle_length: u8,
|
||||||
block_slot: u64,
|
block_slot: u64,
|
||||||
attestation_slot: u64,
|
attestation_slot: u64,
|
||||||
current_hashes: Vec<Hash256>,
|
current_hashes: Vec<Hash256>,
|
||||||
oblique_hashes: Vec<Hash256>)
|
oblique_hashes: Vec<Hash256>)
|
||||||
-> Result<Vec<Hash256>, TransitionError>
|
-> Result<Vec<Hash256>, TransitionError>
|
||||||
{
|
{
|
||||||
let start = cycle_length.checked_add(attestation_slot)
|
// This cast places a limit on cycle_length. If you change it, check math
|
||||||
.and_then(|x| x.checked_sub(block_slot))
|
// for overflow.
|
||||||
.ok_or(TransitionError::IntWrapping)?;
|
let cycle_length: u64 = cycle_length as u64;
|
||||||
let start = start as usize;
|
|
||||||
|
|
||||||
let end = cycle_length.checked_mul(2)
|
if current_hashes.len() as u64 != (cycle_length * 2) {
|
||||||
.and_then(|x| x.checked_add(attestation_slot))
|
return Err(TransitionError::InvalidInput(String::from(
|
||||||
.and_then(|x| x.checked_sub(block_slot))
|
"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.
|
||||||
|
*
|
||||||
|
* Math 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))
|
.and_then(|x| x.checked_sub(oblique_hashes.len() as u64))
|
||||||
.ok_or(TransitionError::IntWrapping)?;
|
.ok_or(TransitionError::IntWrapping)?;
|
||||||
let end = end as usize;
|
|
||||||
|
|
||||||
println!("start: {}, end: {}", start, end);
|
|
||||||
|
|
||||||
if end >= current_hashes.len() {
|
|
||||||
return Err(TransitionError::OutOfBounds);
|
|
||||||
}
|
|
||||||
if start > end {
|
|
||||||
return Err(TransitionError::InvalidInput("cats"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut hashes = Vec::new();
|
let mut hashes = Vec::new();
|
||||||
|
|
||||||
hashes.extend_from_slice(
|
hashes.extend_from_slice(
|
||||||
¤t_hashes[start..end]);
|
¤t_hashes[(start as usize)..(end as usize)]);
|
||||||
hashes.append(&mut oblique_hashes.clone());
|
hashes.append(&mut oblique_hashes.clone());
|
||||||
|
|
||||||
Ok(hashes)
|
Ok(hashes)
|
||||||
@ -44,25 +68,34 @@ pub fn get_signed_parent_hashes(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn get_n_hashes(value: &[u8], n: usize) -> Vec<Hash256> {
|
fn get_range_of_hashes(from: usize, to: usize) -> Vec<Hash256> {
|
||||||
(0..n).map(|_| Hash256::from_slice(value)).collect()
|
(from..to).map(|i| get_hash(&vec![i as u8])).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_hash(value: &[u8]) -> Hash256 {
|
||||||
|
Hash256::from_slice(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_signed_hashes() {
|
fn test_get_signed_hashes_no_oblique() {
|
||||||
let cycle_length: u64 = 8;
|
/*
|
||||||
let block_slot: u64 = 500;
|
* Google Slides example.
|
||||||
let attestation_slot: u64 = 498;
|
*/
|
||||||
let current_hashes =
|
let cycle_length: u8 = 8;
|
||||||
get_n_hashes(b"0", 100);
|
let block_slot: u64 = 19;
|
||||||
let oblique_hashes = get_n_hashes(b"1", 2);
|
let attestation_slot: u64 = 15;
|
||||||
|
let current_hashes = get_range_of_hashes(3, 19);
|
||||||
|
let oblique_hashes = vec![];
|
||||||
let result = get_signed_parent_hashes(
|
let result = get_signed_parent_hashes(
|
||||||
cycle_length,
|
cycle_length,
|
||||||
block_slot,
|
block_slot,
|
||||||
attestation_slot,
|
attestation_slot,
|
||||||
current_hashes,
|
current_hashes,
|
||||||
oblique_hashes);
|
oblique_hashes);
|
||||||
// TODO: complete testing
|
|
||||||
assert!(result.is_ok());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@ pub mod helpers;
|
|||||||
pub enum TransitionError {
|
pub enum TransitionError {
|
||||||
IntWrapping,
|
IntWrapping,
|
||||||
OutOfBounds,
|
OutOfBounds,
|
||||||
InvalidInput(&str),
|
InvalidInput(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user