|
pub fn sync_headers<F>( |
|
peer: Arc<Peer>, |
|
store: Arc<ChainStore<Full>>, |
|
sync_fn: F, |
|
) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError> |
|
where |
|
F: Fn(usize) -> Result<(), CompactFiltersError>, |
|
{ |
|
let locators = store.get_locators()?; |
|
let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect(); |
|
let locators_map: HashMap<_, _> = locators.into_iter().collect(); |
|
|
|
peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new( |
|
locators_vec, |
|
Default::default(), |
|
)))?; |
|
let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer |
|
.recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))? |
|
.ok_or(CompactFiltersError::Timeout)? |
|
{ |
|
if headers.is_empty() { |
|
return Ok(None); |
|
} |
|
|
|
match locators_map.get(&headers[0].prev_blockhash) { |
|
None => return Err(CompactFiltersError::InvalidHeaders), |
|
Some(from) => (store.start_snapshot(*from)?, headers[0].prev_blockhash), |
|
} |
|
} else { |
|
return Err(CompactFiltersError::InvalidResponse); |
|
}; |
|
|
|
let mut sync_height = store.get_height()?; |
|
while sync_height < peer.get_version().start_height as usize { |
|
peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new( |
|
vec![last_hash], |
|
Default::default(), |
|
)))?; |
|
if let NetworkMessage::Headers(headers) = peer |
|
.recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))? |
|
.ok_or(CompactFiltersError::Timeout)? |
|
{ |
|
let batch_len = headers.len(); |
|
last_hash = snapshot.apply(sync_height, headers)?; |
|
|
|
sync_height += batch_len; |
|
sync_fn(sync_height)?; |
|
} else { |
|
return Err(CompactFiltersError::InvalidResponse); |
|
} |
|
} |
|
|
|
Ok(Some(snapshot)) |
|
} |