generate locator heights all the way down to 0 by powers of 2 ()

This commit is contained in:
AntiochP 2017-11-22 22:59:33 -05:00 committed by GitHub
parent 348038f0ed
commit c6b94dd2c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 33 deletions
grin/src
p2p/src

View file

@ -279,38 +279,20 @@ impl Syncer {
/// Builds a vector of block hashes that should help the remote peer sending
/// us the right block headers.
fn get_locator(&self, tip: &chain::Tip) -> Result<Vec<Hash>, Error> {
// Prepare the heights we want as the latests height minus increasing powers
// of 2 up to max.
let mut heights = vec![tip.height];
let mut tail = (1..p2p::MAX_LOCATORS)
.map(|n| 2u64.pow(n))
.filter_map(|n| if n > tip.height {
None
} else {
Some(tip.height - n)
let heights = get_locator_heights(tip.height);
debug!(LOGGER, "Sync: locator heights: {:?}", heights);
let locator = heights
.into_iter()
.map(|h| {
let header = self.chain.get_header_by_height(h).unwrap();
header.hash()
})
.collect::<Vec<_>>();
heights.append(&mut tail);
.collect();
// Include the genesis block (height 0) here as a fallback to guarantee
// both nodes share at least one common header hash in the locator
heights.push(0);
debug!(LOGGER, "Sync: locator: {:?}", locator);
debug!(LOGGER, "Sync: Loc heights: {:?}", heights);
// Iteratively travel the header chain back from our head and retain the
// headers at the wanted heights.
let mut header = self.chain.get_block_header(&tip.last_block_h)?;
let mut locator = vec![];
while heights.len() > 0 {
if header.height == heights[0] {
heights = heights[1..].to_vec();
locator.push(header.hash());
}
if header.height > 0 {
header = self.chain.get_block_header(&header.previous)?;
}
}
Ok(locator)
}
@ -323,3 +305,44 @@ impl Syncer {
}
}
}
// current height back to 0 decreasing in powers of 2
fn get_locator_heights(height: u64) -> Vec<u64> {
let mut current = height.clone();
let mut heights = vec![];
while current > 0 {
heights.push(current);
let next = 2u64.pow(heights.len() as u32);
current = if current > next {
current - next
} else {
0
}
}
heights.push(0);
heights
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_get_locator_heights() {
assert_eq!(get_locator_heights(0), vec![0]);
assert_eq!(get_locator_heights(1), vec![1, 0]);
assert_eq!(get_locator_heights(2), vec![2, 0]);
assert_eq!(get_locator_heights(3), vec![3, 1, 0]);
assert_eq!(get_locator_heights(10), vec![10, 8, 4, 0]);
assert_eq!(get_locator_heights(100), vec![100, 98, 94, 86, 70, 38, 0]);
assert_eq!(
get_locator_heights(1000),
vec![1000, 998, 994, 986, 970, 938, 874, 746, 490, 0]
);
// check the locator is still a manageable length, even for large numbers of headers
assert_eq!(
get_locator_heights(10000),
vec![10000, 9998, 9994, 9986, 9970, 9938, 9874, 9746, 9490, 8978, 7954, 5906, 1810, 0]
);
}
}

View file

@ -55,5 +55,5 @@ mod types;
pub use server::{DummyAdapter, Server};
pub use peer::Peer;
pub use types::{Capabilities, Error, NetAdapter, P2PConfig, PeerInfo, FULL_HIST, FULL_NODE,
MAX_BLOCK_HEADERS, MAX_LOCATORS, MAX_PEER_ADDRS, UNKNOWN};
MAX_BLOCK_HEADERS, MAX_PEER_ADDRS, UNKNOWN};
pub use store::{PeerData, PeerStore, State};

View file

@ -26,9 +26,6 @@ use core::core::hash::Hash;
use core::core::target::Difficulty;
use core::ser;
/// Maximum number of hashes in a block header locator request
pub const MAX_LOCATORS: u32 = 10;
/// Maximum number of block headers a peer should ever send
pub const MAX_BLOCK_HEADERS: u32 = 512;