mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
[PIBD_IMPL] PIBD Desegmenter State (#3688)
* add functions to desegmenter to report next desired segments, begin to add state to determine which segments have been requested * add segmentidentifier type to id requested segments uniquely * make a call on where to keep track of which PIBD segments have been requested * move segmenttype definition, add functions to manipulate peer segment list * remove desegmenter state enum * change chain desegmenter function to provide rwlock * trace, warning cleanup * udpate to test compliation
This commit is contained in:
parent
009a02eec1
commit
41a86b4cd9
8 changed files with 233 additions and 60 deletions
|
@ -867,11 +867,14 @@ impl Chain {
|
||||||
|
|
||||||
/// instantiate desegmenter (in same lazy fashion as segmenter, though this should not be as
|
/// instantiate desegmenter (in same lazy fashion as segmenter, though this should not be as
|
||||||
/// expensive an operation)
|
/// expensive an operation)
|
||||||
pub fn desegmenter(&self, archive_header: &BlockHeader) -> Result<Desegmenter, Error> {
|
pub fn desegmenter(
|
||||||
|
&self,
|
||||||
|
archive_header: &BlockHeader,
|
||||||
|
) -> Result<Arc<RwLock<Option<Desegmenter>>>, Error> {
|
||||||
// Use our cached desegmenter if we have one and the associated header matches.
|
// Use our cached desegmenter if we have one and the associated header matches.
|
||||||
if let Some(d) = self.pibd_desegmenter.read().as_ref() {
|
if let Some(d) = self.pibd_desegmenter.write().as_ref() {
|
||||||
if d.header() == archive_header {
|
if d.header() == archive_header {
|
||||||
return Ok(d.clone());
|
return Ok(self.pibd_desegmenter.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If no desegmenter or headers don't match init
|
// If no desegmenter or headers don't match init
|
||||||
|
@ -881,7 +884,7 @@ impl Chain {
|
||||||
let mut cache = self.pibd_desegmenter.write();
|
let mut cache = self.pibd_desegmenter.write();
|
||||||
*cache = Some(desegmenter.clone());
|
*cache = Some(desegmenter.clone());
|
||||||
|
|
||||||
return Ok(desegmenter);
|
Ok(self.pibd_desegmenter.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// initialize a desegmenter, which is capable of extending the hashset by appending
|
/// initialize a desegmenter, which is capable of extending the hashset by appending
|
||||||
|
|
|
@ -18,8 +18,11 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::core::core::hash::Hash;
|
use crate::core::core::hash::Hash;
|
||||||
use crate::core::core::pmmr;
|
use crate::core::core::{pmmr, pmmr::ReadablePMMR};
|
||||||
use crate::core::core::{BlockHeader, OutputIdentifier, Segment, TxKernel};
|
use crate::core::core::{
|
||||||
|
BlockHeader, OutputIdentifier, Segment, SegmentIdentifier, SegmentType, SegmentTypeIdentifier,
|
||||||
|
TxKernel,
|
||||||
|
};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::txhashset::{BitmapAccumulator, BitmapChunk, TxHashSet};
|
use crate::txhashset::{BitmapAccumulator, BitmapChunk, TxHashSet};
|
||||||
use crate::util::secp::pedersen::RangeProof;
|
use crate::util::secp::pedersen::RangeProof;
|
||||||
|
@ -30,10 +33,6 @@ use crate::txhashset;
|
||||||
|
|
||||||
use croaring::Bitmap;
|
use croaring::Bitmap;
|
||||||
|
|
||||||
/// States that the desegmenter can be in, to keep track of what
|
|
||||||
/// parts are needed next in the proces
|
|
||||||
pub enum DesegmenterState {}
|
|
||||||
|
|
||||||
/// Desegmenter for rebuilding a txhashset from PIBD segments
|
/// Desegmenter for rebuilding a txhashset from PIBD segments
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Desegmenter {
|
pub struct Desegmenter {
|
||||||
|
@ -42,8 +41,10 @@ pub struct Desegmenter {
|
||||||
archive_header: BlockHeader,
|
archive_header: BlockHeader,
|
||||||
store: Arc<store::ChainStore>,
|
store: Arc<store::ChainStore>,
|
||||||
|
|
||||||
|
default_segment_height: u8,
|
||||||
|
|
||||||
bitmap_accumulator: BitmapAccumulator,
|
bitmap_accumulator: BitmapAccumulator,
|
||||||
_bitmap_segments: Vec<Segment<BitmapChunk>>,
|
bitmap_segments: Vec<Segment<BitmapChunk>>,
|
||||||
_output_segments: Vec<Segment<OutputIdentifier>>,
|
_output_segments: Vec<Segment<OutputIdentifier>>,
|
||||||
_rangeproof_segments: Vec<Segment<RangeProof>>,
|
_rangeproof_segments: Vec<Segment<RangeProof>>,
|
||||||
_kernel_segments: Vec<Segment<TxKernel>>,
|
_kernel_segments: Vec<Segment<TxKernel>>,
|
||||||
|
@ -62,13 +63,15 @@ impl Desegmenter {
|
||||||
archive_header: BlockHeader,
|
archive_header: BlockHeader,
|
||||||
store: Arc<store::ChainStore>,
|
store: Arc<store::ChainStore>,
|
||||||
) -> Desegmenter {
|
) -> Desegmenter {
|
||||||
|
trace!("Creating new desegmenter");
|
||||||
let mut retval = Desegmenter {
|
let mut retval = Desegmenter {
|
||||||
txhashset,
|
txhashset,
|
||||||
header_pmmr,
|
header_pmmr,
|
||||||
archive_header,
|
archive_header,
|
||||||
store,
|
store,
|
||||||
bitmap_accumulator: BitmapAccumulator::new(),
|
bitmap_accumulator: BitmapAccumulator::new(),
|
||||||
_bitmap_segments: vec![],
|
default_segment_height: 9,
|
||||||
|
bitmap_segments: vec![],
|
||||||
_output_segments: vec![],
|
_output_segments: vec![],
|
||||||
_rangeproof_segments: vec![],
|
_rangeproof_segments: vec![],
|
||||||
_kernel_segments: vec![],
|
_kernel_segments: vec![],
|
||||||
|
@ -91,6 +94,42 @@ impl Desegmenter {
|
||||||
self.bitmap_mmr_size
|
self.bitmap_mmr_size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return list of the next preferred segments the desegmenter needs based on
|
||||||
|
/// the current real state of the underlying elements
|
||||||
|
pub fn next_desired_segments(&self, max_elements: usize) -> Vec<SegmentTypeIdentifier> {
|
||||||
|
let mut return_vec = vec![];
|
||||||
|
|
||||||
|
// First check for required bitmap elements
|
||||||
|
if self.bitmap_cache.is_none() {
|
||||||
|
trace!("Desegmenter needs bitmap segments");
|
||||||
|
// Get current size of bitmap MMR
|
||||||
|
let local_pmmr_size = self.bitmap_accumulator.readonly_pmmr().unpruned_size();
|
||||||
|
trace!("Local Bitmap PMMR Size is: {}", local_pmmr_size);
|
||||||
|
// Get iterator over expected bitmap elements
|
||||||
|
let mut identifier_iter = SegmentIdentifier::traversal_iter(
|
||||||
|
self.bitmap_mmr_size,
|
||||||
|
self.default_segment_height,
|
||||||
|
);
|
||||||
|
trace!("Expected bitmap MMR size is: {}", self.bitmap_mmr_size);
|
||||||
|
// Advance iterator to next expected segment
|
||||||
|
while let Some(id) = identifier_iter.next() {
|
||||||
|
trace!(
|
||||||
|
"ID segment pos range: {:?}",
|
||||||
|
id.segment_pos_range(self.bitmap_mmr_size)
|
||||||
|
);
|
||||||
|
if id.segment_pos_range(self.bitmap_mmr_size).1 > local_pmmr_size {
|
||||||
|
if !self.has_bitmap_segment_with_id(id) {
|
||||||
|
return_vec.push(SegmentTypeIdentifier::new(SegmentType::Bitmap, id));
|
||||||
|
if return_vec.len() >= max_elements {
|
||||||
|
return return_vec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_vec
|
||||||
|
}
|
||||||
|
|
||||||
/// 'Finalize' the bitmap accumulator, storing an in-memory copy of the bitmap for
|
/// 'Finalize' the bitmap accumulator, storing an in-memory copy of the bitmap for
|
||||||
/// use in further validation and setting the accumulator on the underlying txhashset
|
/// use in further validation and setting the accumulator on the underlying txhashset
|
||||||
/// TODO: Could be called automatically when we have the calculated number of
|
/// TODO: Could be called automatically when we have the calculated number of
|
||||||
|
@ -151,6 +190,26 @@ impl Desegmenter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cache a bitmap segment if we don't already have it
|
||||||
|
fn cache_bitmap_segment(&mut self, in_seg: Segment<BitmapChunk>) {
|
||||||
|
if self
|
||||||
|
.bitmap_segments
|
||||||
|
.iter()
|
||||||
|
.find(|i| i.identifier() == in_seg.identifier())
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
self.bitmap_segments.push(in_seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether our list already contains this bitmap segment
|
||||||
|
fn has_bitmap_segment_with_id(&self, seg_id: SegmentIdentifier) -> bool {
|
||||||
|
self.bitmap_segments
|
||||||
|
.iter()
|
||||||
|
.find(|i| i.identifier() == seg_id)
|
||||||
|
.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds and validates a bitmap chunk
|
/// Adds and validates a bitmap chunk
|
||||||
/// TODO: Still experimenting, this expects chunks received to be in order
|
/// TODO: Still experimenting, this expects chunks received to be in order
|
||||||
pub fn add_bitmap_segment(
|
pub fn add_bitmap_segment(
|
||||||
|
@ -167,11 +226,15 @@ impl Desegmenter {
|
||||||
output_root_hash, // Other root
|
output_root_hash, // Other root
|
||||||
true,
|
true,
|
||||||
)?;
|
)?;
|
||||||
|
debug!("pibd_desegmenter: adding segment to cache");
|
||||||
|
// All okay, add to our cached list of bitmap segments
|
||||||
|
self.cache_bitmap_segment(segment);
|
||||||
|
|
||||||
// All okay, add leaves to bitmap accumulator
|
// All okay, add leaves to bitmap accumulator
|
||||||
let (_sid, _hash_pos, _hashes, _leaf_pos, leaf_data, _proof) = segment.parts();
|
/*let (_sid, _hash_pos, _hashes, _leaf_pos, leaf_data, _proof) = segment.parts();
|
||||||
for chunk in leaf_data.into_iter() {
|
for chunk in leaf_data.into_iter() {
|
||||||
self.bitmap_accumulator.append_chunk(chunk)?;
|
self.bitmap_accumulator.append_chunk(chunk)?;
|
||||||
}
|
}*/
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
use chrono::prelude::{DateTime, Utc};
|
use chrono::prelude::{DateTime, Utc};
|
||||||
|
|
||||||
use crate::core::core::hash::{Hash, Hashed, ZERO_HASH};
|
use crate::core::core::hash::{Hash, Hashed, ZERO_HASH};
|
||||||
use crate::core::core::{Block, BlockHeader, HeaderVersion};
|
use crate::core::core::{Block, BlockHeader, HeaderVersion, SegmentTypeIdentifier};
|
||||||
use crate::core::pow::Difficulty;
|
use crate::core::pow::Difficulty;
|
||||||
use crate::core::ser::{self, PMMRIndexHashable, Readable, Reader, Writeable, Writer};
|
use crate::core::ser::{self, PMMRIndexHashable, Readable, Reader, Writeable, Writer};
|
||||||
use crate::error::{Error, ErrorKind};
|
use crate::error::{Error, ErrorKind};
|
||||||
|
@ -131,6 +131,14 @@ impl Default for TxHashsetDownloadStats {
|
||||||
pub struct SyncState {
|
pub struct SyncState {
|
||||||
current: RwLock<SyncStatus>,
|
current: RwLock<SyncStatus>,
|
||||||
sync_error: RwLock<Option<Error>>,
|
sync_error: RwLock<Option<Error>>,
|
||||||
|
/// Something has to keep track of segments that have been
|
||||||
|
/// requested from other peers. TODO consider: This may not
|
||||||
|
/// be the best place to put code that's concerned with peers
|
||||||
|
/// but it's currently the only place that makes the info
|
||||||
|
/// available where it will be needed (both in the adapter
|
||||||
|
/// and the sync loop)
|
||||||
|
/// TODO: Better struct for this, perhaps hash identifiers
|
||||||
|
requested_pibd_segments: RwLock<Vec<SegmentTypeIdentifier>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyncState {
|
impl SyncState {
|
||||||
|
@ -139,6 +147,7 @@ impl SyncState {
|
||||||
SyncState {
|
SyncState {
|
||||||
current: RwLock::new(SyncStatus::Initial),
|
current: RwLock::new(SyncStatus::Initial),
|
||||||
sync_error: RwLock::new(None),
|
sync_error: RwLock::new(None),
|
||||||
|
requested_pibd_segments: RwLock::new(vec![]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +217,21 @@ impl SyncState {
|
||||||
*self.current.write() = SyncStatus::TxHashsetDownload(stats);
|
*self.current.write() = SyncStatus::TxHashsetDownload(stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update PIBD segment list
|
||||||
|
pub fn add_pibd_segment(&self, id: &SegmentTypeIdentifier) {
|
||||||
|
self.requested_pibd_segments.write().push(id.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove segment from list
|
||||||
|
pub fn remove_pibd_segment(&self, id: &SegmentTypeIdentifier) {
|
||||||
|
self.requested_pibd_segments.write().retain(|i| i != id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether segment is in request list
|
||||||
|
pub fn contains_pibd_segment(&self, id: &SegmentTypeIdentifier) -> bool {
|
||||||
|
self.requested_pibd_segments.read().contains(id)
|
||||||
|
}
|
||||||
|
|
||||||
/// Communicate sync error
|
/// Communicate sync error
|
||||||
pub fn set_sync_error(&self, error: Error) {
|
pub fn set_sync_error(&self, error: Error) {
|
||||||
*self.sync_error.write() = Some(error);
|
*self.sync_error.write() = Some(error);
|
||||||
|
|
Binary file not shown.
|
@ -115,7 +115,9 @@ fn test_pibd_copy_impl(is_test_chain: bool, src_root_dir: &str, dest_root_dir: &
|
||||||
// This is going to use the same block as horizon_header
|
// This is going to use the same block as horizon_header
|
||||||
let segmenter = src_chain.segmenter().unwrap();
|
let segmenter = src_chain.segmenter().unwrap();
|
||||||
// Init desegmenter
|
// Init desegmenter
|
||||||
let mut desegmenter = dest_chain.desegmenter(&horizon_header).unwrap();
|
let desegmenter_lock = dest_chain.desegmenter(&horizon_header).unwrap();
|
||||||
|
let mut desegmenter_write = desegmenter_lock.write();
|
||||||
|
let desegmenter = desegmenter_write.as_mut().unwrap();
|
||||||
|
|
||||||
// And total size of the bitmap PMMR
|
// And total size of the bitmap PMMR
|
||||||
let bitmap_mmr_size = desegmenter.expected_bitmap_mmr_size();
|
let bitmap_mmr_size = desegmenter.expected_bitmap_mmr_size();
|
||||||
|
|
|
@ -21,6 +21,39 @@ use croaring::Bitmap;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
/// Possible segment types, according to this desegmenter
|
||||||
|
pub enum SegmentType {
|
||||||
|
/// Output Bitmap
|
||||||
|
Bitmap,
|
||||||
|
/// Output
|
||||||
|
Output,
|
||||||
|
/// RangeProof
|
||||||
|
RangeProof,
|
||||||
|
/// Kernel
|
||||||
|
Kernel,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lumps possible types with segment ids to enable a unique identifier
|
||||||
|
/// for a segment with respect to a particular archive header
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct SegmentTypeIdentifier {
|
||||||
|
/// The type of this segment
|
||||||
|
pub segment_type: SegmentType,
|
||||||
|
/// The identfier itself
|
||||||
|
pub identifier: SegmentIdentifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SegmentTypeIdentifier {
|
||||||
|
/// Create
|
||||||
|
pub fn new(segment_type: SegmentType, identifier: SegmentIdentifier) -> Self {
|
||||||
|
Self {
|
||||||
|
segment_type,
|
||||||
|
identifier,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
/// Error related to segment creation or validation
|
/// Error related to segment creation or validation
|
||||||
pub enum SegmentError {
|
pub enum SegmentError {
|
||||||
|
@ -90,6 +123,43 @@ impl SegmentIdentifier {
|
||||||
let d = 1 << segment_height;
|
let d = 1 << segment_height;
|
||||||
((pmmr::n_leaves(target_mmr_size) + d - 1) / d) as usize
|
((pmmr::n_leaves(target_mmr_size) + d - 1) / d) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maximum number of leaves in a segment, given by `2**height`
|
||||||
|
fn segment_capacity(&self) -> u64 {
|
||||||
|
1 << self.height
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Offset (in leaf idx) of first leaf in the segment
|
||||||
|
fn leaf_offset(&self) -> u64 {
|
||||||
|
self.idx * self.segment_capacity()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of leaves in this segment. Equal to capacity except for the final segment, which can be smaller
|
||||||
|
fn segment_unpruned_size(&self, mmr_size: u64) -> u64 {
|
||||||
|
min(
|
||||||
|
self.segment_capacity(),
|
||||||
|
pmmr::n_leaves(mmr_size).saturating_sub(self.leaf_offset()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inclusive (full) range of MMR positions for the segment that would be produced
|
||||||
|
/// by this Identifier
|
||||||
|
pub fn segment_pos_range(&self, mmr_size: u64) -> (u64, u64) {
|
||||||
|
let segment_size = self.segment_unpruned_size(mmr_size);
|
||||||
|
let leaf_offset = self.leaf_offset();
|
||||||
|
let first = pmmr::insertion_to_pmmr_index(leaf_offset);
|
||||||
|
let last = if self.full_segment(mmr_size) {
|
||||||
|
pmmr::insertion_to_pmmr_index(leaf_offset + segment_size - 1) + (self.height as u64)
|
||||||
|
} else {
|
||||||
|
mmr_size - 1
|
||||||
|
};
|
||||||
|
(first, last)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the segment is full (segment size == capacity)
|
||||||
|
fn full_segment(&self, mmr_size: u64) -> bool {
|
||||||
|
self.segment_unpruned_size(mmr_size) == self.segment_capacity()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Segment of a PMMR: unpruned leaves and the necessary data to verify
|
/// Segment of a PMMR: unpruned leaves and the necessary data to verify
|
||||||
|
@ -119,39 +189,27 @@ impl<T> Segment<T> {
|
||||||
|
|
||||||
/// Maximum number of leaves in a segment, given by `2**height`
|
/// Maximum number of leaves in a segment, given by `2**height`
|
||||||
fn segment_capacity(&self) -> u64 {
|
fn segment_capacity(&self) -> u64 {
|
||||||
1 << self.identifier.height
|
self.identifier.segment_capacity()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Offset (in leaf idx) of first leaf in the segment
|
/// Offset (in leaf idx) of first leaf in the segment
|
||||||
fn leaf_offset(&self) -> u64 {
|
fn leaf_offset(&self) -> u64 {
|
||||||
self.identifier.idx * self.segment_capacity()
|
self.identifier.leaf_offset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of leaves in this segment. Equal to capacity except for the final segment, which can be smaller
|
// Number of leaves in this segment. Equal to capacity except for the final segment, which can be smaller
|
||||||
fn segment_unpruned_size(&self, mmr_size: u64) -> u64 {
|
fn segment_unpruned_size(&self, mmr_size: u64) -> u64 {
|
||||||
min(
|
self.identifier.segment_unpruned_size(mmr_size)
|
||||||
self.segment_capacity(),
|
|
||||||
pmmr::n_leaves(mmr_size).saturating_sub(self.leaf_offset()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the segment is full (segment size == capacity)
|
/// Whether the segment is full (segment size == capacity)
|
||||||
fn full_segment(&self, mmr_size: u64) -> bool {
|
fn full_segment(&self, mmr_size: u64) -> bool {
|
||||||
self.segment_unpruned_size(mmr_size) == self.segment_capacity()
|
self.identifier.full_segment(mmr_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inclusive range of MMR positions for this segment
|
/// Inclusive range of MMR positions for this segment
|
||||||
pub fn segment_pos_range(&self, mmr_size: u64) -> (u64, u64) {
|
pub fn segment_pos_range(&self, mmr_size: u64) -> (u64, u64) {
|
||||||
let segment_size = self.segment_unpruned_size(mmr_size);
|
self.identifier.segment_pos_range(mmr_size)
|
||||||
let leaf_offset = self.leaf_offset();
|
|
||||||
let first = pmmr::insertion_to_pmmr_index(leaf_offset);
|
|
||||||
let last = if self.full_segment(mmr_size) {
|
|
||||||
pmmr::insertion_to_pmmr_index(leaf_offset + segment_size - 1)
|
|
||||||
+ (self.identifier.height as u64)
|
|
||||||
} else {
|
|
||||||
mmr_size - 1
|
|
||||||
};
|
|
||||||
(first, last)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO - binary_search_by_key() here (can we assume these are sorted by pos?)
|
/// TODO - binary_search_by_key() here (can we assume these are sorted by pos?)
|
||||||
|
|
|
@ -32,7 +32,7 @@ use crate::core::core::hash::{Hash, Hashed};
|
||||||
use crate::core::core::transaction::Transaction;
|
use crate::core::core::transaction::Transaction;
|
||||||
use crate::core::core::{
|
use crate::core::core::{
|
||||||
BlockHeader, BlockSums, CompactBlock, Inputs, OutputIdentifier, Segment, SegmentIdentifier,
|
BlockHeader, BlockSums, CompactBlock, Inputs, OutputIdentifier, Segment, SegmentIdentifier,
|
||||||
TxKernel,
|
SegmentType, SegmentTypeIdentifier, TxKernel,
|
||||||
};
|
};
|
||||||
use crate::core::pow::Difficulty;
|
use crate::core::pow::Difficulty;
|
||||||
use crate::core::ser::ProtocolVersion;
|
use crate::core::ser::ProtocolVersion;
|
||||||
|
@ -572,14 +572,31 @@ where
|
||||||
segment: Segment<BitmapChunk>,
|
segment: Segment<BitmapChunk>,
|
||||||
) -> Result<bool, chain::Error> {
|
) -> Result<bool, chain::Error> {
|
||||||
debug!(
|
debug!(
|
||||||
"RECEIVED BITMAP SEGMENT FOR block_hash: {}, output_root: {}",
|
"Received bitmap segment {} for block_hash: {}, output_root: {}",
|
||||||
block_hash, output_root
|
segment.identifier().idx,
|
||||||
|
block_hash,
|
||||||
|
output_root
|
||||||
);
|
);
|
||||||
|
// Remove segment from outgoing list TODO: Where is the best place to
|
||||||
|
// do this?
|
||||||
|
self.sync_state.remove_pibd_segment(&SegmentTypeIdentifier {
|
||||||
|
segment_type: SegmentType::Bitmap,
|
||||||
|
identifier: segment.identifier(),
|
||||||
|
});
|
||||||
// TODO: Entire process needs to be restarted if the horizon block
|
// TODO: Entire process needs to be restarted if the horizon block
|
||||||
// has changed (perhaps not here, NB this has to go somewhere)
|
// has changed (perhaps not here, NB this has to go somewhere)
|
||||||
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
||||||
let mut desegmenter = self.chain().desegmenter(&archive_header)?;
|
let identifier = segment.identifier().clone();
|
||||||
desegmenter.add_bitmap_segment(segment, output_root)?;
|
if let Some(d) = self.chain().desegmenter(&archive_header)?.write().as_mut() {
|
||||||
|
let res = d.add_bitmap_segment(segment, output_root);
|
||||||
|
if let Err(e) = res {
|
||||||
|
debug!(
|
||||||
|
"Validation of incoming bitmap segment failed: {:?}, reason: {}",
|
||||||
|
identifier, e
|
||||||
|
);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +608,9 @@ where
|
||||||
) -> Result<bool, chain::Error> {
|
) -> Result<bool, chain::Error> {
|
||||||
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
||||||
let desegmenter = self.chain().desegmenter(&archive_header)?;
|
let desegmenter = self.chain().desegmenter(&archive_header)?;
|
||||||
desegmenter.add_output_segment(segment, Some(bitmap_root))?;
|
if let Some(d) = desegmenter.write().as_ref() {
|
||||||
|
d.add_output_segment(segment, Some(bitmap_root))?;
|
||||||
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +621,9 @@ where
|
||||||
) -> Result<bool, chain::Error> {
|
) -> Result<bool, chain::Error> {
|
||||||
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
||||||
let desegmenter = self.chain().desegmenter(&archive_header)?;
|
let desegmenter = self.chain().desegmenter(&archive_header)?;
|
||||||
desegmenter.add_rangeproof_segment(segment)?;
|
if let Some(d) = desegmenter.write().as_ref() {
|
||||||
|
d.add_rangeproof_segment(segment)?;
|
||||||
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,7 +634,9 @@ where
|
||||||
) -> Result<bool, chain::Error> {
|
) -> Result<bool, chain::Error> {
|
||||||
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
let archive_header = self.chain().txhashset_archive_header_header_only()?;
|
||||||
let desegmenter = self.chain().desegmenter(&archive_header)?;
|
let desegmenter = self.chain().desegmenter(&archive_header)?;
|
||||||
desegmenter.add_kernel_segment(segment)?;
|
if let Some(d) = desegmenter.write().as_ref() {
|
||||||
|
d.add_kernel_segment(segment)?;
|
||||||
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,6 @@ pub struct StateSync {
|
||||||
|
|
||||||
prev_state_sync: Option<DateTime<Utc>>,
|
prev_state_sync: Option<DateTime<Utc>>,
|
||||||
state_sync_peer: Option<Arc<Peer>>,
|
state_sync_peer: Option<Arc<Peer>>,
|
||||||
|
|
||||||
sent_test_pibd_message: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StateSync {
|
impl StateSync {
|
||||||
|
@ -51,7 +49,6 @@ impl StateSync {
|
||||||
chain,
|
chain,
|
||||||
prev_state_sync: None,
|
prev_state_sync: None,
|
||||||
state_sync_peer: None,
|
state_sync_peer: None,
|
||||||
sent_test_pibd_message: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,19 +169,24 @@ impl StateSync {
|
||||||
|
|
||||||
fn continue_pibd(&mut self) {
|
fn continue_pibd(&mut self) {
|
||||||
// Check the state of our chain to figure out what we should be requesting next
|
// Check the state of our chain to figure out what we should be requesting next
|
||||||
// TODO: Just faking a single request for testing
|
|
||||||
if !self.sent_test_pibd_message {
|
|
||||||
debug!("Sending test PIBD message");
|
|
||||||
let archive_header = self.chain.txhashset_archive_header_header_only().unwrap();
|
let archive_header = self.chain.txhashset_archive_header_header_only().unwrap();
|
||||||
|
|
||||||
let target_segment_height = 11;
|
|
||||||
//let archive_header = self.chain.txhashset_archive_header().unwrap();
|
|
||||||
let desegmenter = self.chain.desegmenter(&archive_header).unwrap();
|
let desegmenter = self.chain.desegmenter(&archive_header).unwrap();
|
||||||
let bitmap_mmr_size = desegmenter.expected_bitmap_mmr_size();
|
|
||||||
let mut identifier_iter =
|
|
||||||
SegmentIdentifier::traversal_iter(bitmap_mmr_size, target_segment_height);
|
|
||||||
|
|
||||||
self.sent_test_pibd_message = true;
|
// TODO and consider: number here depends on how many simultaneous
|
||||||
|
// requests we want to send to peers
|
||||||
|
let mut next_segment_ids = vec![];
|
||||||
|
if let Some(d) = desegmenter.read().as_ref() {
|
||||||
|
next_segment_ids = d.next_desired_segments(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each segment, pick a desirable peer and send message
|
||||||
|
// (Provided we're not waiting for a response for this message from someone else)
|
||||||
|
for seg_id in next_segment_ids.iter() {
|
||||||
|
if self.sync_state.contains_pibd_segment(seg_id) {
|
||||||
|
trace!("Request list contains, continuing: {:?}", seg_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let peers_iter = || {
|
let peers_iter = || {
|
||||||
self.peers
|
self.peers
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -202,11 +204,9 @@ impl StateSync {
|
||||||
});
|
});
|
||||||
debug!("Chosen peer is {:?}", peer);
|
debug!("Chosen peer is {:?}", peer);
|
||||||
if let Some(p) = peer {
|
if let Some(p) = peer {
|
||||||
p.send_bitmap_segment_request(
|
p.send_bitmap_segment_request(archive_header.hash(), seg_id.identifier.clone())
|
||||||
archive_header.hash(),
|
|
||||||
identifier_iter.next().unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
self.sync_state.add_pibd_segment(seg_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue