db: migrate from lmdb-zero to heed
This commit is contained in:
+25
-24
@@ -150,8 +150,8 @@ pub struct Chain {
|
||||
store: Arc<store::ChainStore>,
|
||||
adapter: Arc<dyn ChainAdapter + Send + Sync>,
|
||||
orphans: Arc<OrphanBlockPool>,
|
||||
txhashset: Arc<RwLock<txhashset::TxHashSet>>,
|
||||
header_pmmr: Arc<RwLock<txhashset::PMMRHandle<BlockHeader>>>,
|
||||
txhashset: Arc<RwLock<TxHashSet>>,
|
||||
header_pmmr: Arc<RwLock<PMMRHandle<BlockHeader>>>,
|
||||
pibd_segmenter: Arc<RwLock<Option<Segmenter>>>,
|
||||
pibd_desegmenter: Arc<RwLock<Option<Desegmenter>>>,
|
||||
// POW verification function
|
||||
@@ -189,9 +189,9 @@ impl Chain {
|
||||
// Initialize the output_pos index based on UTXO set
|
||||
// and NRD kernel_pos index based recent kernel history.
|
||||
{
|
||||
let batch = store.batch()?;
|
||||
txhashset.init_output_pos_index(&header_pmmr, &batch)?;
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &batch)?;
|
||||
let mut batch = store.batch()?;
|
||||
txhashset.init_output_pos_index(&header_pmmr, &mut batch)?;
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &mut batch)?;
|
||||
batch.commit()?;
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ impl Chain {
|
||||
pub fn reset_chain_head_to_genesis(&self) -> Result<(), Error> {
|
||||
let mut header_pmmr = self.header_pmmr.write();
|
||||
let mut txhashset = self.txhashset.write();
|
||||
let batch = self.store.batch()?;
|
||||
let mut batch = self.store.batch()?;
|
||||
|
||||
// Change head back to genesis
|
||||
{
|
||||
@@ -314,7 +314,7 @@ impl Chain {
|
||||
|
||||
/// Reset PIBD head
|
||||
pub fn reset_pibd_head(&self) -> Result<(), Error> {
|
||||
let batch = self.store.batch()?;
|
||||
let mut batch = self.store.batch()?;
|
||||
batch.save_pibd_head(&self.genesis().into())?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -530,9 +530,9 @@ impl Chain {
|
||||
pub fn new_ctx<'a>(
|
||||
&self,
|
||||
opts: Options,
|
||||
batch: store::Batch<'a>,
|
||||
header_pmmr: &'a mut txhashset::PMMRHandle<BlockHeader>,
|
||||
txhashset: &'a mut txhashset::TxHashSet,
|
||||
batch: Batch<'a>,
|
||||
header_pmmr: &'a mut PMMRHandle<BlockHeader>,
|
||||
txhashset: &'a mut TxHashSet,
|
||||
) -> Result<pipe::BlockContext<'a>, Error> {
|
||||
let denylist = self.denylist.read().clone();
|
||||
Ok(pipe::BlockContext {
|
||||
@@ -832,7 +832,7 @@ impl Chain {
|
||||
&self,
|
||||
header: &BlockHeader,
|
||||
ext: &mut ExtensionPair,
|
||||
batch: &Batch,
|
||||
batch: &mut Batch,
|
||||
) -> Result<BlockHeader, Error> {
|
||||
let denylist = self.denylist.read().clone();
|
||||
pipe::rewind_and_apply_fork(header, ext, batch, &|header| {
|
||||
@@ -846,7 +846,7 @@ impl Chain {
|
||||
&self,
|
||||
header: &BlockHeader,
|
||||
ext: &mut HeaderExtension,
|
||||
batch: &Batch,
|
||||
batch: &mut Batch,
|
||||
) -> Result<(), Error> {
|
||||
let denylist = self.denylist.read().clone();
|
||||
pipe::rewind_and_apply_header_fork(header, ext, batch, &|header| {
|
||||
@@ -1015,7 +1015,7 @@ impl Chain {
|
||||
fn validate_kernel_history(
|
||||
&self,
|
||||
header: &BlockHeader,
|
||||
txhashset: &txhashset::TxHashSet,
|
||||
txhashset: &TxHashSet,
|
||||
) -> Result<(), Error> {
|
||||
debug!("validate_kernel_history: rewinding and validating kernel history (readonly)");
|
||||
|
||||
@@ -1151,11 +1151,11 @@ impl Chain {
|
||||
self.validate_kernel_history(&header, &txhashset)?;
|
||||
|
||||
let header_pmmr = self.header_pmmr.read();
|
||||
let batch = self.store.batch()?;
|
||||
let mut batch = self.store.batch()?;
|
||||
txhashset.verify_kernel_pos_index(
|
||||
&self.genesis.header,
|
||||
&header_pmmr,
|
||||
&batch,
|
||||
&mut batch,
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
@@ -1213,10 +1213,10 @@ impl Chain {
|
||||
}
|
||||
|
||||
// Rebuild our output_pos index in the db based on fresh UTXO set.
|
||||
txhashset.init_output_pos_index(&header_pmmr, &batch)?;
|
||||
txhashset.init_output_pos_index(&header_pmmr, &mut batch)?;
|
||||
|
||||
// Rebuild our NRD kernel_pos index based on recent kernel history.
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &batch)?;
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &mut batch)?;
|
||||
|
||||
// Commit all the changes to the db.
|
||||
batch.commit()?;
|
||||
@@ -1257,9 +1257,9 @@ impl Chain {
|
||||
/// *Only* runs if we are not in archive mode.
|
||||
fn remove_historical_blocks(
|
||||
&self,
|
||||
header_pmmr: &txhashset::PMMRHandle<BlockHeader>,
|
||||
header_pmmr: &PMMRHandle<BlockHeader>,
|
||||
archive_header: BlockHeader,
|
||||
batch: &store::Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
) -> Result<(), Error> {
|
||||
if self.archive_mode() {
|
||||
return Ok(());
|
||||
@@ -1345,7 +1345,7 @@ impl Chain {
|
||||
// Take a write lock on the txhashet and start a new writeable db batch.
|
||||
let header_pmmr = self.header_pmmr.read();
|
||||
let mut txhashset = self.txhashset.write();
|
||||
let batch = self.store.batch()?;
|
||||
let mut batch = self.store.batch()?;
|
||||
|
||||
// Compact the txhashset itself (rewriting the pruned backend files).
|
||||
{
|
||||
@@ -1361,15 +1361,15 @@ impl Chain {
|
||||
|
||||
// If we are not in archival mode remove historical blocks from the db.
|
||||
if !self.archive_mode() {
|
||||
self.remove_historical_blocks(&header_pmmr, archive_header, &batch)?;
|
||||
self.remove_historical_blocks(&header_pmmr, archive_header, &mut batch)?;
|
||||
}
|
||||
|
||||
// Make sure our output_pos index is consistent with the UTXO set.
|
||||
txhashset.init_output_pos_index(&header_pmmr, &batch)?;
|
||||
txhashset.init_output_pos_index(&header_pmmr, &mut batch)?;
|
||||
|
||||
// TODO - Why is this part of chain compaction?
|
||||
// Rebuild our NRD kernel_pos index based on recent kernel history.
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &batch)?;
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &mut batch)?;
|
||||
|
||||
// Commit all the above db changes.
|
||||
batch.commit()?;
|
||||
@@ -1439,7 +1439,8 @@ impl Chain {
|
||||
0
|
||||
} else {
|
||||
self.get_header_by_height(start_block_height - 1)?
|
||||
.output_mmr_size + 1
|
||||
.output_mmr_size
|
||||
+ 1
|
||||
};
|
||||
let end_mmr_size = self.get_header_by_height(end_block_height)?.output_mmr_size;
|
||||
Ok((start_mmr_size, end_mmr_size))
|
||||
|
||||
+27
-12
@@ -108,7 +108,7 @@ pub trait ListIndex {
|
||||
/// Push a pos onto the list for the specified commitment.
|
||||
fn push_pos(
|
||||
&self,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
commit: Commitment,
|
||||
new_pos: <Self::Entry as ListIndexEntry>::Pos,
|
||||
) -> Result<(), Error>;
|
||||
@@ -116,7 +116,7 @@ pub trait ListIndex {
|
||||
/// Pop a pos off the list for the specified commitment.
|
||||
fn pop_pos(
|
||||
&self,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
commit: Commitment,
|
||||
) -> Result<Option<<Self::Entry as ListIndexEntry>::Pos>, Error>;
|
||||
}
|
||||
@@ -124,7 +124,12 @@ pub trait ListIndex {
|
||||
/// Supports "rewind" given the provided commit and a pos to rewind back to.
|
||||
pub trait RewindableListIndex {
|
||||
/// Rewind the index for the given commitment to the specified position.
|
||||
fn rewind(&self, batch: &Batch<'_>, commit: Commitment, rewind_pos: u64) -> Result<(), Error>;
|
||||
fn rewind(
|
||||
&self,
|
||||
batch: &mut Batch<'_>,
|
||||
commit: Commitment,
|
||||
rewind_pos: u64,
|
||||
) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// A pruneable list index supports pruning of old data from the index lists.
|
||||
@@ -133,15 +138,20 @@ pub trait RewindableListIndex {
|
||||
pub trait PruneableListIndex: ListIndex {
|
||||
/// Clear all data from the index.
|
||||
/// Used when rebuilding the index.
|
||||
fn clear(&self, batch: &Batch<'_>) -> Result<(), Error>;
|
||||
fn clear(&self, batch: &mut Batch<'_>) -> Result<(), Error>;
|
||||
|
||||
/// Prune old data.
|
||||
fn prune(&self, batch: &Batch<'_>, commit: Commitment, cutoff_pos: u64) -> Result<(), Error>;
|
||||
fn prune(
|
||||
&self,
|
||||
batch: &mut Batch<'_>,
|
||||
commit: Commitment,
|
||||
cutoff_pos: u64,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
/// Pop a pos off the back of the list (used for pruning old data).
|
||||
fn pop_pos_back(
|
||||
&self,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
commit: Commitment,
|
||||
) -> Result<Option<<Self::Entry as ListIndexEntry>::Pos>, Error>;
|
||||
}
|
||||
@@ -255,7 +265,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn push_pos(&self, batch: &Batch<'_>, commit: Commitment, new_pos: T) -> Result<(), Error> {
|
||||
fn push_pos(&self, batch: &mut Batch<'_>, commit: Commitment, new_pos: T) -> Result<(), Error> {
|
||||
match self.get_list(batch, commit)? {
|
||||
None => {
|
||||
let list = ListWrapper::Single { pos: new_pos };
|
||||
@@ -327,7 +337,7 @@ where
|
||||
/// Pop the head of the list.
|
||||
/// Returns the output_pos.
|
||||
/// Returns None if list was empty.
|
||||
fn pop_pos(&self, batch: &Batch<'_>, commit: Commitment) -> Result<Option<T>, Error> {
|
||||
fn pop_pos(&self, batch: &mut Batch<'_>, commit: Commitment) -> Result<Option<T>, Error> {
|
||||
match self.get_list(batch, commit)? {
|
||||
None => Ok(None),
|
||||
Some(ListWrapper::Single { pos }) => {
|
||||
@@ -373,7 +383,12 @@ where
|
||||
|
||||
/// List index that supports rewind.
|
||||
impl<T: PosEntry> RewindableListIndex for MultiIndex<T> {
|
||||
fn rewind(&self, batch: &Batch<'_>, commit: Commitment, rewind_pos: u64) -> Result<(), Error> {
|
||||
fn rewind(
|
||||
&self,
|
||||
batch: &mut Batch<'_>,
|
||||
commit: Commitment,
|
||||
rewind_pos: u64,
|
||||
) -> Result<(), Error> {
|
||||
while self
|
||||
.peek_pos(batch, commit)?
|
||||
.map(|x| x.pos() > rewind_pos)
|
||||
@@ -386,7 +401,7 @@ impl<T: PosEntry> RewindableListIndex for MultiIndex<T> {
|
||||
}
|
||||
|
||||
impl<T: PosEntry> PruneableListIndex for MultiIndex<T> {
|
||||
fn clear(&self, batch: &Batch<'_>) -> Result<(), Error> {
|
||||
fn clear(&self, batch: &mut Batch<'_>) -> Result<(), Error> {
|
||||
let mut list_count = 0;
|
||||
let mut entry_count = 0;
|
||||
let prefix = to_key(self.list_prefix, "");
|
||||
@@ -409,7 +424,7 @@ impl<T: PosEntry> PruneableListIndex for MultiIndex<T> {
|
||||
/// Pruning will be more performant than full rebuild but not yet necessary.
|
||||
fn prune(
|
||||
&self,
|
||||
_batch: &Batch<'_>,
|
||||
_batch: &mut Batch<'_>,
|
||||
_commit: Commitment,
|
||||
_cutoff_pos: u64,
|
||||
) -> Result<(), Error> {
|
||||
@@ -420,7 +435,7 @@ impl<T: PosEntry> PruneableListIndex for MultiIndex<T> {
|
||||
|
||||
/// Pop off the back/tail of the linked list.
|
||||
/// Used when pruning old data.
|
||||
fn pop_pos_back(&self, batch: &Batch<'_>, commit: Commitment) -> Result<Option<T>, Error> {
|
||||
fn pop_pos_back(&self, batch: &mut Batch<'_>, commit: Commitment) -> Result<Option<T>, Error> {
|
||||
match self.get_list(batch, commit)? {
|
||||
None => Ok(None),
|
||||
Some(ListWrapper::Single { pos }) => {
|
||||
|
||||
+18
-17
@@ -161,11 +161,11 @@ pub fn process_block(
|
||||
// Note we do this in the outer batch, not the child batch from the extension
|
||||
// as we only commit the child batch if the extension increases total work.
|
||||
// We want to save the block to the db regardless.
|
||||
add_block(b, &ctx.batch)?;
|
||||
add_block(b, &mut ctx.batch)?;
|
||||
|
||||
// If we have no "tail" then set it now.
|
||||
if ctx.batch.tail().is_err() {
|
||||
update_body_tail(&b.header, &ctx.batch)?;
|
||||
update_body_tail(&b.header, &mut ctx.batch)?;
|
||||
}
|
||||
|
||||
if has_more_work(&b.header, &head) {
|
||||
@@ -198,13 +198,13 @@ pub fn process_block_headers(
|
||||
// Note: This batch may later be committed even if the MMR itself is rollbacked.
|
||||
for header in headers {
|
||||
validate_header(header, ctx)?;
|
||||
add_block_header(header, &ctx.batch)?;
|
||||
add_block_header(header, &mut ctx.batch)?;
|
||||
}
|
||||
|
||||
let ctx_specific_validation = &ctx.header_allowed;
|
||||
|
||||
// Now apply this entire chunk of headers to the header MMR.
|
||||
txhashset::header_extending(&mut ctx.header_pmmr, &mut ctx.batch, |ext, batch| {
|
||||
txhashset::header_extending(&mut ctx.header_pmmr, &mut ctx.batch, |ext, mut batch| {
|
||||
rewind_and_apply_header_fork(&last_header, ext, batch, ctx_specific_validation)?;
|
||||
|
||||
// If previous sync_head is not on the "current" chain then
|
||||
@@ -216,7 +216,7 @@ pub fn process_block_headers(
|
||||
// Note the outer batch may still be committed to db assuming no errors occur in the extension.
|
||||
if has_more_work(last_header, &head) {
|
||||
let header_head = last_header.into();
|
||||
update_header_head(&header_head, &batch)?;
|
||||
update_header_head(&header_head, &mut batch)?;
|
||||
} else {
|
||||
ext.force_rollback();
|
||||
};
|
||||
@@ -275,7 +275,7 @@ pub fn process_block_header(header: &BlockHeader, ctx: &mut BlockContext<'_>) ->
|
||||
})?;
|
||||
|
||||
// Add this new block header to the db.
|
||||
add_block_header(header, &ctx.batch)?;
|
||||
add_block_header(header, &mut ctx.batch)?;
|
||||
|
||||
if has_more_work(header, &header_head) {
|
||||
update_header_head(&Tip::from_header(header), &mut ctx.batch)?;
|
||||
@@ -478,7 +478,7 @@ fn verify_coinbase_maturity(
|
||||
/// Verify kernel sums across the full utxo and kernel sets based on block_sums
|
||||
/// of previous block accounting for the inputs|outputs|kernels of the new block.
|
||||
/// Saves the new block_sums to the db via the current batch if successful.
|
||||
fn verify_block_sums(b: &Block, batch: &store::Batch<'_>) -> Result<(), Error> {
|
||||
fn verify_block_sums(b: &Block, batch: &mut store::Batch<'_>) -> Result<(), Error> {
|
||||
// Retrieve the block_sums for the previous block.
|
||||
let block_sums = batch.get_block_sums(&b.header.prev_hash)?;
|
||||
|
||||
@@ -509,7 +509,7 @@ fn verify_block_sums(b: &Block, batch: &store::Batch<'_>) -> Result<(), Error> {
|
||||
fn apply_block_to_txhashset(
|
||||
block: &Block,
|
||||
ext: &mut txhashset::ExtensionPair<'_>,
|
||||
batch: &store::Batch<'_>,
|
||||
batch: &mut store::Batch<'_>,
|
||||
) -> Result<(), Error> {
|
||||
ext.extension
|
||||
.apply_block(block, ext.header_extension, batch)?;
|
||||
@@ -520,13 +520,13 @@ fn apply_block_to_txhashset(
|
||||
|
||||
/// Officially adds the block to our chain (possibly on a losing fork).
|
||||
/// Header must be added separately (assume this has been done previously).
|
||||
fn add_block(b: &Block, batch: &store::Batch<'_>) -> Result<(), Error> {
|
||||
fn add_block(b: &Block, batch: &mut store::Batch<'_>) -> Result<(), Error> {
|
||||
batch.save_block(b)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update the block chain tail so we can know the exact tail of full blocks in this node
|
||||
fn update_body_tail(bh: &BlockHeader, batch: &store::Batch<'_>) -> Result<(), Error> {
|
||||
fn update_body_tail(bh: &BlockHeader, batch: &mut store::Batch<'_>) -> Result<(), Error> {
|
||||
let tip = Tip::from_header(bh);
|
||||
batch
|
||||
.save_body_tail(&tip)
|
||||
@@ -536,27 +536,28 @@ fn update_body_tail(bh: &BlockHeader, batch: &store::Batch<'_>) -> Result<(), Er
|
||||
}
|
||||
|
||||
/// Officially adds the block header to our header chain.
|
||||
fn add_block_header(bh: &BlockHeader, batch: &store::Batch<'_>) -> Result<(), Error> {
|
||||
fn add_block_header(bh: &BlockHeader, batch: &mut store::Batch<'_>) -> Result<(), Error> {
|
||||
batch
|
||||
.save_block_header(bh)
|
||||
.map_err(|e| Error::StoreErr(e, "pipe save header".to_owned()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_header_head(head: &Tip, batch: &store::Batch<'_>) -> Result<(), Error> {
|
||||
fn update_header_head(head: &Tip, batch: &mut store::Batch<'_>) -> Result<(), Error> {
|
||||
batch
|
||||
.save_header_head(&head)
|
||||
.map_err(|e| Error::StoreErr(e, "pipe save header head".to_owned()))?;
|
||||
|
||||
debug!(
|
||||
trace!(
|
||||
"header head updated to {} at {}",
|
||||
head.last_block_h, head.height
|
||||
head.last_block_h,
|
||||
head.height
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_head(head: &Tip, batch: &store::Batch<'_>) -> Result<(), Error> {
|
||||
fn update_head(head: &Tip, batch: &mut store::Batch<'_>) -> Result<(), Error> {
|
||||
batch
|
||||
.save_body_head(&head)
|
||||
.map_err(|e| Error::StoreErr(e, "pipe save body".to_owned()))?;
|
||||
@@ -575,7 +576,7 @@ fn has_more_work(header: &BlockHeader, head: &Tip) -> bool {
|
||||
pub fn rewind_and_apply_header_fork(
|
||||
header: &BlockHeader,
|
||||
ext: &mut txhashset::HeaderExtension<'_>,
|
||||
batch: &store::Batch<'_>,
|
||||
batch: &mut store::Batch<'_>,
|
||||
ctx_specific_validation: &dyn Fn(&BlockHeader) -> Result<(), Error>,
|
||||
) -> Result<(), Error> {
|
||||
let mut fork_hashes = vec![];
|
||||
@@ -616,7 +617,7 @@ pub fn rewind_and_apply_header_fork(
|
||||
pub fn rewind_and_apply_fork(
|
||||
header: &BlockHeader,
|
||||
ext: &mut txhashset::ExtensionPair<'_>,
|
||||
batch: &store::Batch<'_>,
|
||||
batch: &mut store::Batch<'_>,
|
||||
ctx_specific_validation: &dyn Fn(&BlockHeader) -> Result<(), Error>,
|
||||
) -> Result<BlockHeader, Error> {
|
||||
let extension = &mut ext.extension;
|
||||
|
||||
+23
-17
@@ -201,22 +201,22 @@ impl<'a> Batch<'a> {
|
||||
}
|
||||
|
||||
/// Save body head to db.
|
||||
pub fn save_body_head(&self, t: &Tip) -> Result<(), Error> {
|
||||
pub fn save_body_head(&mut self, t: &Tip) -> Result<(), Error> {
|
||||
self.db.put_ser(&[HEAD_PREFIX], t)
|
||||
}
|
||||
|
||||
/// Save body "tail" to db.
|
||||
pub fn save_body_tail(&self, t: &Tip) -> Result<(), Error> {
|
||||
pub fn save_body_tail(&mut self, t: &Tip) -> Result<(), Error> {
|
||||
self.db.put_ser(&[TAIL_PREFIX], t)
|
||||
}
|
||||
|
||||
/// Save header head to db.
|
||||
pub fn save_header_head(&self, t: &Tip) -> Result<(), Error> {
|
||||
pub fn save_header_head(&mut self, t: &Tip) -> Result<(), Error> {
|
||||
self.db.put_ser(&[HEADER_HEAD_PREFIX], t)
|
||||
}
|
||||
|
||||
/// Save PIBD head to db.
|
||||
pub fn save_pibd_head(&self, t: &Tip) -> Result<(), Error> {
|
||||
pub fn save_pibd_head(&mut self, t: &Tip) -> Result<(), Error> {
|
||||
self.db.put_ser(&[PIBD_HEAD_PREFIX], t)
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ impl<'a> Batch<'a> {
|
||||
|
||||
/// Save the block to the db.
|
||||
/// Note: the block header is not saved to the db here, assumes this has already been done.
|
||||
pub fn save_block(&self, b: &Block) -> Result<(), Error> {
|
||||
pub fn save_block(&mut self, b: &Block) -> Result<(), Error> {
|
||||
debug!(
|
||||
"save_block: {} at {} ({} -> v{})",
|
||||
b.header.hash(),
|
||||
@@ -248,20 +248,20 @@ impl<'a> Batch<'a> {
|
||||
|
||||
/// We maintain a "spent" index for each full block to allow the output_pos
|
||||
/// to be easily reverted during rewind.
|
||||
pub fn save_spent_index(&self, h: &Hash, spent: &[CommitPos]) -> Result<(), Error> {
|
||||
pub fn save_spent_index(&mut self, h: &Hash, spent: &[CommitPos]) -> Result<(), Error> {
|
||||
self.db
|
||||
.put_ser(&to_key(BLOCK_SPENT_PREFIX, h)[..], &spent.to_vec())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Low level function to delete directly by raw key.
|
||||
pub fn delete(&self, key: &[u8]) -> Result<(), Error> {
|
||||
pub fn delete(&mut self, key: &[u8]) -> Result<(), Error> {
|
||||
self.db.delete(key)
|
||||
}
|
||||
|
||||
/// Delete a full block. Does not delete any record associated with a block
|
||||
/// header.
|
||||
pub fn delete_block(&self, bh: &Hash) -> Result<(), Error> {
|
||||
pub fn delete_block(&mut self, bh: &Hash) -> Result<(), Error> {
|
||||
self.db.delete(&to_key(BLOCK_PREFIX, bh)[..])?;
|
||||
|
||||
// Best effort at deleting associated data for this block.
|
||||
@@ -275,7 +275,7 @@ impl<'a> Batch<'a> {
|
||||
}
|
||||
|
||||
/// Save block header to db.
|
||||
pub fn save_block_header(&self, header: &BlockHeader) -> Result<(), Error> {
|
||||
pub fn save_block_header(&mut self, header: &BlockHeader) -> Result<(), Error> {
|
||||
let hash = header.hash();
|
||||
|
||||
// Store the header itself indexed by hash.
|
||||
@@ -286,13 +286,17 @@ impl<'a> Batch<'a> {
|
||||
}
|
||||
|
||||
/// Save output_pos and block height to index.
|
||||
pub fn save_output_pos_height(&self, commit: &Commitment, pos: CommitPos) -> Result<(), Error> {
|
||||
pub fn save_output_pos_height(
|
||||
&mut self,
|
||||
commit: &Commitment,
|
||||
pos: CommitPos,
|
||||
) -> Result<(), Error> {
|
||||
self.db
|
||||
.put_ser(&to_key(OUTPUT_POS_PREFIX, commit)[..], &pos)
|
||||
}
|
||||
|
||||
/// Delete the output_pos index entry for a spent output.
|
||||
pub fn delete_output_pos_height(&self, commit: &Commitment) -> Result<(), Error> {
|
||||
pub fn delete_output_pos_height(&mut self, commit: &Commitment) -> Result<(), Error> {
|
||||
self.db.delete(&to_key(OUTPUT_POS_PREFIX, commit))
|
||||
}
|
||||
|
||||
@@ -305,7 +309,9 @@ impl<'a> Batch<'a> {
|
||||
}
|
||||
|
||||
/// Iterator over the output_pos index.
|
||||
pub fn output_pos_iter(&self) -> Result<impl Iterator<Item = (Vec<u8>, CommitPos)>, Error> {
|
||||
pub fn output_pos_iter(
|
||||
&self,
|
||||
) -> Result<impl Iterator<Item = (Vec<u8>, CommitPos)> + 'a, Error> {
|
||||
let key = to_key(OUTPUT_POS_PREFIX, "");
|
||||
let protocol_version = self.db.protocol_version();
|
||||
self.db.iter(&key, move |k, mut v| {
|
||||
@@ -366,12 +372,12 @@ impl<'a> Batch<'a> {
|
||||
}
|
||||
|
||||
/// Delete the block spent index.
|
||||
fn delete_spent_index(&self, bh: &Hash) -> Result<(), Error> {
|
||||
fn delete_spent_index(&mut self, bh: &Hash) -> Result<(), Error> {
|
||||
self.db.delete(&to_key(BLOCK_SPENT_PREFIX, bh))
|
||||
}
|
||||
|
||||
/// Save block_sums for the block.
|
||||
pub fn save_block_sums(&self, h: &Hash, sums: BlockSums) -> Result<(), Error> {
|
||||
pub fn save_block_sums(&mut self, h: &Hash, sums: BlockSums) -> Result<(), Error> {
|
||||
self.db.put_ser(&to_key(BLOCK_SUMS_PREFIX, h)[..], &sums)
|
||||
}
|
||||
|
||||
@@ -383,7 +389,7 @@ impl<'a> Batch<'a> {
|
||||
}
|
||||
|
||||
/// Delete the block_sums for the block.
|
||||
fn delete_block_sums(&self, bh: &Hash) -> Result<(), Error> {
|
||||
fn delete_block_sums(&mut self, bh: &Hash) -> Result<(), Error> {
|
||||
self.db.delete(&to_key(BLOCK_SUMS_PREFIX, bh))
|
||||
}
|
||||
|
||||
@@ -423,7 +429,7 @@ impl<'a> Batch<'a> {
|
||||
|
||||
/// Iterator over all full blocks in the db.
|
||||
/// Uses default db serialization strategy via db protocol version.
|
||||
pub fn blocks_iter(&self) -> Result<impl Iterator<Item = Block>, Error> {
|
||||
pub fn blocks_iter(&self) -> Result<impl Iterator<Item = Block> + 'a, Error> {
|
||||
let key = to_key(BLOCK_PREFIX, "");
|
||||
let protocol_version = self.db.protocol_version();
|
||||
self.db.iter(&key, move |_, mut v| {
|
||||
@@ -434,7 +440,7 @@ impl<'a> Batch<'a> {
|
||||
|
||||
/// Iterator over raw data for full blocks in the db.
|
||||
/// Used during block migration (we need flexibility around deserialization).
|
||||
pub fn blocks_raw_iter(&self) -> Result<impl Iterator<Item = (Vec<u8>, Vec<u8>)>, Error> {
|
||||
pub fn blocks_raw_iter(&self) -> Result<impl Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a, Error> {
|
||||
let key = to_key(BLOCK_PREFIX, "");
|
||||
self.db.iter(&key, |k, v| Ok((k.to_vec(), v.to_vec())))
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ impl Desegmenter {
|
||||
|
||||
// TODO: Unwraps
|
||||
let tip = Tip::from_header(&h);
|
||||
let batch = self.store.batch()?;
|
||||
let mut batch = self.store.batch()?;
|
||||
batch.save_pibd_head(&tip)?;
|
||||
batch.commit()?;
|
||||
|
||||
@@ -283,11 +283,11 @@ impl Desegmenter {
|
||||
{
|
||||
let header_pmmr = self.header_pmmr.read();
|
||||
let txhashset = self.txhashset.read();
|
||||
let batch = self.store.batch()?;
|
||||
let mut batch = self.store.batch()?;
|
||||
txhashset.verify_kernel_pos_index(
|
||||
&self.genesis,
|
||||
&header_pmmr,
|
||||
&batch,
|
||||
&mut batch,
|
||||
Some(status.clone()),
|
||||
Some(stop_state.clone()),
|
||||
)?;
|
||||
@@ -308,9 +308,9 @@ impl Desegmenter {
|
||||
&mut header_pmmr,
|
||||
&mut txhashset,
|
||||
&mut batch,
|
||||
|ext, batch| {
|
||||
|ext, mut batch| {
|
||||
let extension = &mut ext.extension;
|
||||
extension.rewind(&self.archive_header, batch)?;
|
||||
extension.rewind(&self.archive_header, &mut batch)?;
|
||||
|
||||
// Validate the extension, generating the utxo_sum and kernel_sum.
|
||||
// Full validation, including rangeproofs and kernel signature verification.
|
||||
@@ -359,10 +359,10 @@ impl Desegmenter {
|
||||
}
|
||||
|
||||
// Rebuild our output_pos index in the db based on fresh UTXO set.
|
||||
txhashset.init_output_pos_index(&header_pmmr, &batch)?;
|
||||
txhashset.init_output_pos_index(&header_pmmr, &mut batch)?;
|
||||
|
||||
// Rebuild our NRD kernel_pos index based on recent kernel history.
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &batch)?;
|
||||
txhashset.init_recent_kernel_pos_index(&header_pmmr, &mut batch)?;
|
||||
|
||||
// Commit all the changes to the db.
|
||||
batch.commit()?;
|
||||
|
||||
@@ -538,7 +538,7 @@ impl TxHashSet {
|
||||
pub fn init_recent_kernel_pos_index(
|
||||
&self,
|
||||
header_pmmr: &PMMRHandle<BlockHeader>,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
) -> Result<(), Error> {
|
||||
let head = batch.head()?;
|
||||
let cutoff = head.height.saturating_sub(WEEK_HEIGHT * 2);
|
||||
@@ -552,7 +552,7 @@ impl TxHashSet {
|
||||
&self,
|
||||
from_header: &BlockHeader,
|
||||
header_pmmr: &PMMRHandle<BlockHeader>,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
status: Option<Arc<SyncState>>,
|
||||
stop_state: Option<Arc<StopState>>,
|
||||
) -> Result<(), Error> {
|
||||
@@ -635,7 +635,7 @@ impl TxHashSet {
|
||||
pub fn init_output_pos_index(
|
||||
&self,
|
||||
header_pmmr: &PMMRHandle<BlockHeader>,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
) -> Result<(), Error> {
|
||||
let now = Instant::now();
|
||||
|
||||
@@ -733,10 +733,10 @@ pub fn extending_readonly<F, T>(
|
||||
inner: F,
|
||||
) -> Result<T, Error>
|
||||
where
|
||||
F: FnOnce(&mut ExtensionPair<'_>, &Batch<'_>) -> Result<T, Error>,
|
||||
F: FnOnce(&mut ExtensionPair<'_>, &mut Batch<'_>) -> Result<T, Error>,
|
||||
{
|
||||
let commit_index = trees.commit_index.clone();
|
||||
let batch = commit_index.batch()?;
|
||||
let mut batch = commit_index.batch()?;
|
||||
|
||||
trace!("Starting new txhashset (readonly) extension.");
|
||||
|
||||
@@ -751,7 +751,7 @@ where
|
||||
header_extension: &mut header_extension,
|
||||
extension: &mut extension,
|
||||
};
|
||||
inner(&mut extension_pair, &batch)
|
||||
inner(&mut extension_pair, &mut batch)
|
||||
};
|
||||
|
||||
trace!("Rollbacking txhashset (readonly) extension.");
|
||||
@@ -830,7 +830,7 @@ pub fn extending<'a, F, T>(
|
||||
inner: F,
|
||||
) -> Result<T, Error>
|
||||
where
|
||||
F: FnOnce(&mut ExtensionPair<'_>, &Batch<'_>) -> Result<T, Error>,
|
||||
F: FnOnce(&mut ExtensionPair<'_>, &mut Batch<'_>) -> Result<T, Error>,
|
||||
{
|
||||
let sizes: (u64, u64, u64);
|
||||
let res: Result<T, Error>;
|
||||
@@ -842,7 +842,7 @@ where
|
||||
|
||||
// create a child transaction so if the state is rolled back by itself, all
|
||||
// index saving can be undone
|
||||
let child_batch = batch.child()?;
|
||||
let mut child_batch = batch.child()?;
|
||||
{
|
||||
trace!("Starting new txhashset extension.");
|
||||
|
||||
@@ -853,7 +853,7 @@ where
|
||||
header_extension: &mut header_extension,
|
||||
extension: &mut extension,
|
||||
};
|
||||
res = inner(&mut extension_pair, &child_batch);
|
||||
res = inner(&mut extension_pair, &mut child_batch);
|
||||
|
||||
rollback = extension_pair.extension.rollback;
|
||||
sizes = extension_pair.extension.sizes();
|
||||
@@ -901,15 +901,15 @@ where
|
||||
/// Start a new readonly header MMR extension.
|
||||
/// This MMR can be extended individually beyond the other (output, rangeproof and kernel) MMRs
|
||||
/// to allow headers to be validated before we receive the full block data.
|
||||
pub fn header_extending_readonly<'a, F, T>(
|
||||
handle: &'a mut PMMRHandle<BlockHeader>,
|
||||
pub fn header_extending_readonly<F, T>(
|
||||
handle: &mut PMMRHandle<BlockHeader>,
|
||||
store: &ChainStore,
|
||||
inner: F,
|
||||
) -> Result<T, Error>
|
||||
where
|
||||
F: FnOnce(&mut HeaderExtension<'_>, &Batch<'_>) -> Result<T, Error>,
|
||||
F: FnOnce(&mut HeaderExtension<'_>, &mut Batch<'_>) -> Result<T, Error>,
|
||||
{
|
||||
let batch = store.batch()?;
|
||||
let mut batch = store.batch()?;
|
||||
|
||||
let head = match handle.head_hash() {
|
||||
Ok(hash) => {
|
||||
@@ -921,7 +921,7 @@ where
|
||||
|
||||
let pmmr = PMMR::at(&mut handle.backend, handle.size);
|
||||
let mut extension = HeaderExtension::new(pmmr, head);
|
||||
let res = inner(&mut extension, &batch);
|
||||
let res = inner(&mut extension, &mut batch);
|
||||
|
||||
handle.backend.discard();
|
||||
|
||||
@@ -937,7 +937,7 @@ pub fn header_extending<'a, F, T>(
|
||||
inner: F,
|
||||
) -> Result<T, Error>
|
||||
where
|
||||
F: FnOnce(&mut HeaderExtension<'_>, &Batch<'_>) -> Result<T, Error>,
|
||||
F: FnOnce(&mut HeaderExtension<'_>, &mut Batch<'_>) -> Result<T, Error>,
|
||||
{
|
||||
let size: u64;
|
||||
let res: Result<T, Error>;
|
||||
@@ -945,7 +945,7 @@ where
|
||||
|
||||
// create a child transaction so if the state is rolled back by itself, all
|
||||
// index saving can be undone
|
||||
let child_batch = batch.child()?;
|
||||
let mut child_batch = batch.child()?;
|
||||
|
||||
let head = match handle.head_hash() {
|
||||
Ok(hash) => {
|
||||
@@ -958,7 +958,7 @@ where
|
||||
{
|
||||
let pmmr = PMMR::at(&mut handle.backend, handle.size);
|
||||
let mut extension = HeaderExtension::new(pmmr, head);
|
||||
res = inner(&mut extension, &child_batch);
|
||||
res = inner(&mut extension, &mut child_batch);
|
||||
|
||||
rollback = extension.rollback;
|
||||
size = extension.size();
|
||||
@@ -1233,7 +1233,7 @@ impl<'a> Extension<'a> {
|
||||
&mut self,
|
||||
b: &Block,
|
||||
header_ext: &HeaderExtension<'_>,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
) -> Result<(), Error> {
|
||||
let mut affected_pos = vec![];
|
||||
|
||||
@@ -1499,7 +1499,7 @@ impl<'a> Extension<'a> {
|
||||
&mut self,
|
||||
kernels: &[TxKernel],
|
||||
height: u64,
|
||||
batch: &Batch<'_>,
|
||||
batch: &mut Batch<'_>,
|
||||
) -> Result<(), Error> {
|
||||
for kernel in kernels {
|
||||
let pos = self.apply_kernel(kernel)?;
|
||||
@@ -1579,7 +1579,7 @@ impl<'a> Extension<'a> {
|
||||
/// Rewinds the MMRs to the provided block, rewinding to the last output pos
|
||||
/// and last kernel pos of that block. If `updated_bitmap` is supplied, the
|
||||
/// bitmap accumulator will be replaced with its contents
|
||||
pub fn rewind(&mut self, header: &BlockHeader, batch: &Batch<'_>) -> Result<(), Error> {
|
||||
pub fn rewind(&mut self, header: &BlockHeader, batch: &mut Batch) -> Result<(), Error> {
|
||||
debug!(
|
||||
"Rewind extension to {} at {} from {} at {}",
|
||||
header.hash(),
|
||||
@@ -1622,7 +1622,11 @@ impl<'a> Extension<'a> {
|
||||
// Rewind the MMRs and the output_pos index.
|
||||
// Returns a vec of "affected_pos" so we can apply the necessary updates to the bitmap
|
||||
// accumulator in a single pass for all rewound blocks.
|
||||
fn rewind_single_block(&mut self, block: &Block, batch: &Batch<'_>) -> Result<Vec<u64>, Error> {
|
||||
fn rewind_single_block(
|
||||
&mut self,
|
||||
block: &Block,
|
||||
batch: &mut Batch<'_>,
|
||||
) -> Result<Vec<u64>, Error> {
|
||||
let header = &block.header;
|
||||
let prev_header = batch.get_previous_header(&header)?;
|
||||
|
||||
@@ -2206,7 +2210,11 @@ fn input_pos_to_rewind(
|
||||
}
|
||||
|
||||
/// If NRD enabled then enforce NRD relative height rules.
|
||||
fn apply_kernel_rules(kernel: &TxKernel, pos: CommitPos, batch: &Batch<'_>) -> Result<(), Error> {
|
||||
fn apply_kernel_rules(
|
||||
kernel: &TxKernel,
|
||||
pos: CommitPos,
|
||||
batch: &mut Batch<'_>,
|
||||
) -> Result<(), Error> {
|
||||
if !global::is_nrd_enabled() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user