Kernel lookup api method (#3000)
* Kernel lookup api * Min and max height parameters, scan backwards * Return null instead of 404 if kernel not found * Return TxKernel instead of TxKernelPrintable * Update description of KernelHandler
This commit is contained in:
committed by
Antioch Peverell
parent
d36a0b29ef
commit
30156cdcf9
+68
-1
@@ -19,7 +19,8 @@ use crate::core::core::hash::{Hash, Hashed, ZERO_HASH};
|
||||
use crate::core::core::merkle_proof::MerkleProof;
|
||||
use crate::core::core::verifier_cache::VerifierCache;
|
||||
use crate::core::core::{
|
||||
Block, BlockHeader, BlockSums, Committed, Output, OutputIdentifier, Transaction, TxKernelEntry,
|
||||
Block, BlockHeader, BlockSums, Committed, Output, OutputIdentifier, Transaction, TxKernel,
|
||||
TxKernelEntry,
|
||||
};
|
||||
use crate::core::global;
|
||||
use crate::core::pow;
|
||||
@@ -1281,6 +1282,72 @@ impl Chain {
|
||||
Ok(txhashset.get_header_by_height(output_pos.height)?)
|
||||
}
|
||||
|
||||
/// Gets the kernel with a given excess and the block height it is included in.
|
||||
pub fn get_kernel_height(
|
||||
&self,
|
||||
excess: &Commitment,
|
||||
min_height: Option<u64>,
|
||||
max_height: Option<u64>,
|
||||
) -> Result<Option<(TxKernel, u64, u64)>, Error> {
|
||||
let min_index = match min_height {
|
||||
Some(h) => Some(self.get_header_by_height(h - 1)?.kernel_mmr_size + 1),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let max_index = match max_height {
|
||||
Some(h) => Some(self.get_header_by_height(h)?.kernel_mmr_size),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let (kernel, mmr_index) = match self
|
||||
.txhashset
|
||||
.read()
|
||||
.find_kernel(&excess, min_index, max_index)
|
||||
{
|
||||
Some(k) => k,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let header = self.get_header_for_kernel_index(mmr_index, min_height, max_height)?;
|
||||
|
||||
Ok(Some((kernel, header.height, mmr_index)))
|
||||
}
|
||||
|
||||
/// Gets the block header in which a given kernel mmr index appears in the txhashset.
|
||||
pub fn get_header_for_kernel_index(
|
||||
&self,
|
||||
kernel_mmr_index: u64,
|
||||
min_height: Option<u64>,
|
||||
max_height: Option<u64>,
|
||||
) -> Result<BlockHeader, Error> {
|
||||
let txhashset = self.txhashset.read();
|
||||
|
||||
let mut min = min_height.unwrap_or(0).saturating_sub(1);
|
||||
let mut max = match max_height {
|
||||
Some(h) => h,
|
||||
None => self.head()?.height,
|
||||
};
|
||||
|
||||
loop {
|
||||
let search_height = max - (max - min) / 2;
|
||||
let h = txhashset.get_header_by_height(search_height)?;
|
||||
if search_height == 0 {
|
||||
return Ok(h);
|
||||
}
|
||||
let h_prev = txhashset.get_header_by_height(search_height - 1)?;
|
||||
if kernel_mmr_index > h.kernel_mmr_size {
|
||||
min = search_height;
|
||||
} else if kernel_mmr_index < h_prev.kernel_mmr_size {
|
||||
max = search_height;
|
||||
} else {
|
||||
if kernel_mmr_index == h_prev.kernel_mmr_size {
|
||||
return Ok(h_prev);
|
||||
}
|
||||
return Ok(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the given block header is actually on the current chain.
|
||||
/// Checks the header_by_height index to verify the header is where we say
|
||||
/// it is
|
||||
|
||||
@@ -269,6 +269,29 @@ impl TxHashSet {
|
||||
.elements_from_insertion_index(start_index, max_count)
|
||||
}
|
||||
|
||||
/// Find a kernel with a given excess. Work backwards from `max_index` to `min_index`
|
||||
pub fn find_kernel(
|
||||
&self,
|
||||
excess: &Commitment,
|
||||
min_index: Option<u64>,
|
||||
max_index: Option<u64>,
|
||||
) -> Option<(TxKernel, u64)> {
|
||||
let min_index = min_index.unwrap_or(1);
|
||||
let max_index = max_index.unwrap_or(self.kernel_pmmr_h.last_pos);
|
||||
|
||||
let pmmr = ReadonlyPMMR::at(&self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos);
|
||||
let mut index = max_index + 1;
|
||||
while index > min_index {
|
||||
index -= 1;
|
||||
if let Some(t) = pmmr.get_data(index) {
|
||||
if &t.kernel.excess == excess {
|
||||
return Some((t.kernel, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Get MMR roots.
|
||||
pub fn roots(&self) -> TxHashSetRoots {
|
||||
let header_pmmr =
|
||||
|
||||
Reference in New Issue
Block a user