Repository navigation
Add block and attestation validation #33
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
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
117a207
Add pre-written validation code
paulhauner eaa694b
Deleted some unnecessary files
paulhauner 50d7252
Remove failing benchmarks
paulhauner 49737fb
Add doc comments to attestation validation
paulhauner c30a9a7
Update comment for rejecting future block
paulhauner e2d45ea
Separate parent block checking and proposer checking
paulhauner a998ac2
Add InvalidBitfieldEndBits tests
paulhauner 9a59908
Rename voted_hashmap to voted_hashset
paulhauner f13a4ff
Fix a type in sig. ver. comment
paulhauner cf9f8c1
Fix issue with last_justified_block_hash
paulhauner 739abc0
Merge branch 'master' into validation
paulhauner 550ca79
Add block_at_slot function to block store
paulhauner 8c1d72a
Return block hash with block_at_slot()
paulhauner d729355
Add test to block_store, export BlockAtSlotError
paulhauner 6ef4268
Verify attestation justified_block_hash.
paulhauner 3139d0e
Replace hashmap with hashset
paulhauner 68ca51c
Fix "indicies" type
paulhauner b544153
Add comment regarding tightening block val.
paulhauner 1f089d4
Ensure attestation val. check parent.slot
paulhauner e8daca4
Ensure that parent_block.slot < block.slot
paulhauner 90010ce
Fix big in attestation validation
paulhauner File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [package] | ||
| name = "validation" | ||
| version = "0.1.0" | ||
| authors = ["Paul Hauner <paul@paulhauner.com>"] | ||
|
|
||
| [dependencies] | ||
| bls = { path = "../utils/bls" } | ||
| db = { path = "../../lighthouse/db" } | ||
| hashing = { path = "../utils/hashing" } | ||
| rayon = "1.0.2" | ||
| ssz = { path = "../utils/ssz" } | ||
| ssz_helpers = { path = "../utils/ssz_helpers" } | ||
| types = { path = "../types" } |
226 changes: 226 additions & 0 deletions
226
beacon_chain/validation/src/attestation_parent_hashes.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,226 @@ | ||
| use super::types::Hash256; | ||
|
|
||
| #[derive(Debug)] | ||
| pub enum ParentHashesError { | ||
| BadCurrentHashes, | ||
| BadObliqueHashes, | ||
| SlotTooHigh, | ||
| SlotTooLow, | ||
| IntWrapping, | ||
| } | ||
|
|
||
| /// 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: &[Hash256], | ||
| oblique_hashes: &[Hash256]) | ||
| -> Result<Vec<Hash256>, ParentHashesError> | ||
| { | ||
| // This cast places a limit on cycle_length. If you change it, check math | ||
| // for overflow. | ||
| let cycle_length: u64 = u64::from(cycle_length); | ||
|
|
||
| if current_hashes.len() as u64 != (cycle_length * 2) { | ||
| return Err(ParentHashesError::BadCurrentHashes); | ||
| } | ||
| if oblique_hashes.len() as u64 > cycle_length { | ||
| return Err(ParentHashesError::BadObliqueHashes); | ||
| } | ||
| if attestation_slot >= block_slot { | ||
| return Err(ParentHashesError::SlotTooHigh); | ||
| } | ||
|
|
||
| /* | ||
| * 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(ParentHashesError::SlotTooLow); | ||
| } | ||
|
|
||
| /* | ||
| * 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(ParentHashesError::IntWrapping)?; | ||
|
|
||
|
|
||
| let mut hashes = Vec::new(); | ||
| hashes.extend_from_slice( | ||
| ¤t_hashes[(start as usize)..(end as usize)]); | ||
| hashes.extend_from_slice(oblique_hashes); | ||
|
|
||
| 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); | ||
| 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()); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.