Skip to content
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

[WIP] Perf: Kernel Sync Performance #1987

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
34394c1
Created GetKernels Message.
Nov 14, 2018
a8a2d4d
Modified GetKernels and Kernels message to use approach suggested by …
Nov 14, 2018
9d212f7
rustfmt
Nov 14, 2018
90c2660
Fixing comment and formatting.
Nov 14, 2018
eb87f7a
Adding in MAX_KERNELS
Nov 15, 2018
6eea9ba
Implemented read_kernels to retrieve kernels from the mmr given a blo…
Nov 15, 2018
6082089
Created kernel_sync that requests 512 kernels at a time. Currently on…
Nov 18, 2018
d41774c
rustfmt and prioritizing ENHANCED_TXHASHSET_HIST peers over others. S…
Nov 18, 2018
f940a07
Implemented sync_kernels in pipe & chain.
Nov 18, 2018
6fc61a4
Took care of a few TODOs
Nov 19, 2018
e180629
Addressed a few PR comments, and added root_validate_tip to PMMRHandle.
Nov 21, 2018
f523bdb
Skipping unzip of kernel subdir in txhashset zip if kernels already s…
Nov 23, 2018
12c56ef
Missed Kernels implementation in protocol
Nov 23, 2018
fcc0323
rustfmt
Nov 23, 2018
98fa264
Was using head_header instead of header_head
Nov 23, 2018
b570a22
Was using Tip.hash() instead of Tip.last_block_h.
Nov 24, 2018
e7fcf2d
Using header_head instead of header_head-5 to see if kernel syncing i…
Nov 24, 2018
8df281c
get_header_by_height can't be used during kernel_sync, since header h…
Nov 24, 2018
202e609
Fixing build failures.
Nov 24, 2018
07aacf6
Adding debug logs to help trace down issues.
Nov 24, 2018
14a8852
Attempting to use sync_pmmr instead of header_pmmr during kernel vali…
Nov 24, 2018
79c5790
PMMR leaves are hashed with index (why?), so that was a dead end.
Nov 24, 2018
d468f59
Changing kernels message to group kernels by block hash.
Nov 26, 2018
acff2c2
rustfmt
Nov 26, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 61 additions & 6 deletions chain/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use core::core::hash::{Hash, Hashed, ZERO_HASH};
use core::core::merkle_proof::MerkleProof;
use core::core::verifier_cache::VerifierCache;
use core::core::{
Block, BlockHeader, BlockSums, Output, OutputIdentifier, Transaction, TxKernelEntry,
Block, BlockHeader, BlockSums, Output, OutputIdentifier, Transaction, TxKernel, TxKernelEntry,
};
use core::global;
use core::pow;
Expand Down Expand Up @@ -179,7 +179,8 @@ impl Chain {
let store = Arc::new(chain_store);

// open the txhashset, creating a new one if necessary
let mut txhashset = txhashset::TxHashSet::open(db_root.clone(), store.clone(), None)?;
let mut txhashset =
txhashset::TxHashSet::open(db_root.clone(), store.clone(), None, genesis.hash())?;

setup_head(genesis.clone(), store.clone(), &mut txhashset)?;

Expand Down Expand Up @@ -345,6 +346,22 @@ impl Chain {
Ok(())
}

/// Attempt to add new kernels to the kernel mmr.
/// This is only ever used during sync.
pub fn sync_kernels(
&self,
blocks: &Vec<(Hash, Vec<TxKernel>)>,
opts: Options,
) -> Result<(), Error> {
let mut txhashset = self.txhashset.write();
let batch = self.store.batch()?;
let mut ctx = self.new_ctx(opts, batch, &mut txhashset)?;

pipe::sync_kernels(blocks, &mut ctx)?;

Ok(())
}

fn new_ctx<'a>(
&self,
opts: Options,
Expand Down Expand Up @@ -789,17 +806,37 @@ impl Chain {
}

let header = self.get_block_header(&h)?;
txhashset::zip_write(self.db_root.clone(), txhashset_data, &header)?;
let mut kernels_already_synced = false;
{
let existing_txhashset = self.txhashset.read();
let num_kernels = existing_txhashset.num_kernels();
if num_kernels >= header.kernel_mmr_size {
kernels_already_synced = true;
}
}

let mut txhashset =
txhashset::TxHashSet::open(self.db_root.clone(), self.store.clone(), Some(&header))?;
txhashset::zip_write(
self.db_root.clone(),
txhashset_data,
&header,
kernels_already_synced,
)?;

let mut txhashset = txhashset::TxHashSet::open(
self.db_root.clone(),
self.store.clone(),
Some(&header),
header.hash(),
)?;

// The txhashset.zip contains the output, rangeproof and kernel MMRs.
// We must rebuild the header MMR ourselves based on the headers in our db.
self.rebuild_header_mmr(&Tip::from_header(&header), &mut txhashset)?;

// Validate the full kernel history (kernel MMR root for every block header).
self.validate_kernel_history(&header, &txhashset)?;
if !kernels_already_synced {
self.validate_kernel_history(&header, &txhashset)?;
}

// all good, prepare a new batch and update all the required records
debug!("txhashset_write: rewinding a 2nd time (writeable)");
Expand Down Expand Up @@ -973,6 +1010,24 @@ impl Chain {
txhashset.last_n_kernel(distance)
}

/// kernels by insertion index
pub fn get_kernels_by_insertion_index(&self, start_index: u64, max: u64) -> Vec<TxKernelEntry> {
let mut txhashset = self.txhashset.write();
txhashset.kernels_by_insertion_index(start_index, max).1
}

/// returns the number of leaves in the kernel mmr
pub fn get_num_kernels(&self) -> u64 {
let txhashset = self.txhashset.read();
txhashset.num_kernels()
}
/// returns the number of leaves in the kernel mmr
pub fn get_kernel_root_validated_tip(&self) -> Result<BlockHeader, Error> {
let txhashset = self.txhashset.read();
let hash = txhashset.kernel_root_validated_tip();
self.get_block_header(&hash)
}

/// outputs by insertion index
pub fn unspent_outputs_by_insertion_index(
&self,
Expand Down
64 changes: 63 additions & 1 deletion chain/src/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use core::consensus;
use core::core::hash::{Hash, Hashed};
use core::core::verifier_cache::VerifierCache;
use core::core::Committed;
use core::core::{Block, BlockHeader, BlockSums};
use core::core::{Block, BlockHeader, BlockSums, TxKernel};
use core::global;
use core::pow;
use error::{Error, ErrorKind};
Expand Down Expand Up @@ -276,6 +276,68 @@ pub fn sync_block_headers(
}
}

/// Process the kernels.
/// This is only ever used during sync.
pub fn sync_kernels(
blocks: &Vec<(Hash, Vec<TxKernel>)>,
ctx: &mut BlockContext,
) -> Result<(), Error> {
let first_block = match blocks.first() {
Some(block) => {
debug!(
"pipe: sync_kernels: {} blocks from {}",
blocks.len(),
block.0
);
block
}
_ => return Ok(()),
};

let header = ctx.batch.get_block_header(&first_block.0)?;

let next_kernel_index = match header.height {
0 => 0,
height => {
let header = match ctx.batch.get_header_by_height(height - 1) {
Ok(header) => header,
Err(e) => {
error!("sync_kernels: Could not find header: {:?}", e);
return Ok(());
}
};
header.kernel_mmr_size
}
};

let num_kernels = ctx.txhashset.num_kernels();
if num_kernels < next_kernel_index {
// TODO: A convenient way to store and process these later
// would allow nodes to request batches of kernels in parallel.
return Err(ErrorKind::TxHashSetErr("Previous kernels missing".to_string()).into());
}

let kernels_to_add: Vec<TxKernel> = blocks.iter().flat_map(|block| block.1.clone()).collect();
if num_kernels > (next_kernel_index + kernels_to_add.len() as u64) {
debug!(
"pipe: sync_kernels: kernels from index {} not needed.",
next_kernel_index,
);
return Ok(());
}

txhashset::extending(&mut ctx.txhashset, &mut ctx.batch, |extension| {
// Rewinding kernel mmr to correct kernel index. Probably unnecessary, but playing it safe.
extension.rewind_kernel_mmr(next_kernel_index)?;

for block in blocks {
extension.apply_kernels(&block.0, &block.1)?;
}
Ok(())
})?;
Ok(())
}

/// Process block header as part of "header first" block propagation.
/// We validate the header but we do not store it or update header head based
/// on this. We will update these once we get the block back after requesting
Expand Down
Loading