Skip to content

Commit

Permalink
feat: add lmdb
Browse files Browse the repository at this point in the history
  • Loading branch information
stringhandler committed Dec 13, 2024
1 parent 26085b4 commit b75770e
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 85 deletions.
32 changes: 14 additions & 18 deletions src/sharechain/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ impl InMemoryShareChain {

// Check if already added.
if let Some(level) = p2_chain.level_at_height(new_block_p2pool_height) {
if level.blocks.contains_key(&block.hash) {
let block_in_chain = level.blocks.get(&block.hash).unwrap();
if level.contains(&block.hash) {
let block_in_chain = level.get(&block.hash).unwrap();

info!(target: LOG_TARGET, "[{:?}] ✅ Block already added: {}:{}, verified: {}", self.pow_algo, block.height, &block.hash.to_hex()[0..8], block_in_chain.verified);

Expand All @@ -198,7 +198,7 @@ impl InMemoryShareChain {
}

// this is safe as we already checked it does exist
let tip_height = p2_chain.get_tip().unwrap().height;
let tip_height = p2_chain.get_tip().unwrap().height();
// We keep more blocks than the share window, but its only to validate the share window. If a block comes in
// older than the share window is way too old for us to care about.
if block.height < tip_height.saturating_sub(self.config.share_window) && !syncing {
Expand Down Expand Up @@ -260,10 +260,9 @@ impl InMemoryShareChain {
};

// we want to count 1 short,as the final share will be for this node
let stop_height = tip_level.height.saturating_sub(self.config.share_window - 1);
let stop_height = tip_level.height().saturating_sub(self.config.share_window - 1);
let mut cur_block = tip_level
.blocks
.get(&tip_level.chain_block)
.get(&tip_level.chain_block())
.ok_or(ShareChainError::BlockNotFound)?;
update_insert(
&mut miners_to_shares,
Expand All @@ -275,7 +274,6 @@ impl InMemoryShareChain {
let uncle_block = p2_chain
.level_at_height(uncle.0)
.ok_or(ShareChainError::UncleBlockNotFound)?
.blocks
.get(&uncle.1)
.ok_or(ShareChainError::UncleBlockNotFound)?;
update_insert(
Expand All @@ -299,7 +297,6 @@ impl InMemoryShareChain {
let uncle_block = p2_chain
.level_at_height(uncle.0)
.ok_or(ShareChainError::UncleBlockNotFound)?
.blocks
.get(&uncle.1)
.ok_or(ShareChainError::UncleBlockNotFound)?;
update_insert(
Expand Down Expand Up @@ -350,7 +347,7 @@ impl InMemoryShareChain {
res.push(block.clone());
}
} else {
for block in level.blocks.values() {
for block in level.all_blocks() {
num_actual_blocks += 1;
res.push(block.clone());
}
Expand All @@ -359,7 +356,7 @@ impl InMemoryShareChain {
return Ok(res);
}

level = if let Some(new_level) = p2_chain.level_at_height(level.height + 1) {
level = if let Some(new_level) = p2_chain.level_at_height(level.height() + 1) {
new_level
} else {
break;
Expand Down Expand Up @@ -489,7 +486,7 @@ impl ShareChain for InMemoryShareChain {
let bl = self.p2_chain.read().await;
let tip_level = bl.get_tip();
if let Some(tip_level) = tip_level {
Ok(Some((tip_level.height, tip_level.chain_block)))
Ok(Some((tip_level.height(), tip_level.chain_block())))
} else {
Ok(None)
}
Expand Down Expand Up @@ -545,7 +542,6 @@ impl ShareChain for InMemoryShareChain {
let uncle_block = chain_read_lock
.level_at_height(uncle.0)
.ok_or(ShareChainError::UncleBlockNotFound)?
.blocks
.get(&uncle.1)
.ok_or(ShareChainError::UncleBlockNotFound)?;
miners_to_shares.insert(
Expand Down Expand Up @@ -614,7 +610,7 @@ impl ShareChain for InMemoryShareChain {
for uncle in &chain_block.uncles {
excluded_uncles.push(uncle.1);
}
for block in older_level.blocks.values() {
for block in older_level.all_blocks() {
uncles.push(block.clone());
}
}
Expand All @@ -638,7 +634,7 @@ impl ShareChain for InMemoryShareChain {
if chain_read_lock
.level_at_height(parent.height)
.ok_or(ShareChainError::BlockLevelNotFound)?
.chain_block !=
.chain_block() !=
parent.hash
{
excluded_uncles.push(uncle.hash);
Expand Down Expand Up @@ -668,7 +664,7 @@ impl ShareChain for InMemoryShareChain {

for block in requested_blocks {
if let Some(level) = p2_chain_read_lock.level_at_height(block.0) {
if let Some(block) = level.blocks.get(&block.1) {
if let Some(block) = level.get(&block.1) {
blocks.push(block.clone());
} else {
// if sync requestee only sees their behind on tip, they will fill in fixedhash::zero(), so it wont
Expand Down Expand Up @@ -707,7 +703,7 @@ impl ShareChain for InMemoryShareChain {
for their_block in their_blocks {
if let Some(level) = p2_chain_read.level_at_height(their_block.0) {
// Only split if the block is in the main chain
if level.chain_block == their_block.1 {
if level.chain_block() == their_block.1 {
split_height2 = their_block.0.saturating_add(1);
break;
}
Expand All @@ -720,7 +716,7 @@ impl ShareChain for InMemoryShareChain {
self.all_blocks_with_lock(&p2_chain_read, Some(cmp::max(split_height, split_height2)), limit, true)?;
let tip_level = p2_chain_read
.get_tip()
.map(|tip_level| (tip_level.height, tip_level.chain_block));
.map(|tip_level| (tip_level.height(), tip_level.chain_block()));
let chain_pow = p2_chain_read.total_accumulated_tip_difficulty();
Ok((blocks, tip_level, chain_pow))
}
Expand Down Expand Up @@ -760,7 +756,7 @@ impl ShareChain for InMemoryShareChain {
let p2_chain_read_lock = self.p2_chain.read().await;
let mut i_have_blocks = Vec::with_capacity(size);
if let Some(tip) = p2_chain_read_lock.get_tip() {
let tip_height = tip.height;
let tip_height = tip.height();
let mut height = tip_height;
for _ in 0..size {
if let Some(level) = p2_chain_read_lock.level_at_height(height) {
Expand Down
1 change: 1 addition & 0 deletions src/sharechain/lmdb_block_storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) struct LmdbBlockStorage {}
1 change: 1 addition & 0 deletions src/sharechain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub const MIN_SHA3X_DIFFICULTY: u64 = 100_000_000; // 1 Mhs every ten seconds

pub mod error;
pub mod in_memory;
pub(crate) mod lmdb_block_storage;
pub mod p2block;
pub mod p2chain;
mod p2chain_level;
Expand Down
74 changes: 34 additions & 40 deletions src/sharechain/p2chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,13 @@ impl P2Chain {

pub fn get_block_at_height(&self, height: u64, hash: &FixedHash) -> Option<&Arc<P2Block>> {
let level = self.level_at_height(height)?;
level.blocks.get(hash)
level.get(hash)
}

#[cfg(test)]
fn get_chain_block_at_height(&self, height: u64) -> Option<&Arc<P2Block>> {
let level = self.level_at_height(height)?;
level.blocks.get(&level.chain_block)
}

pub fn level_at_height_mut(&mut self, height: u64) -> Option<&mut P2ChainLevel> {
self.levels.get_mut(&height)
level.get(&level.chain_block)
}

pub fn new_empty(total_size: u64, share_window: u64, block_time: u64) -> Self {
Expand Down Expand Up @@ -209,10 +205,10 @@ impl P2Chain {
// the newly added block == 0
self.lwma.add_back(block.timestamp, block.target_difficulty());
let level = self
.level_at_height_mut(new_height)
.level_at_height(new_height)
.ok_or(ShareChainError::BlockLevelNotFound)?;
level.chain_block = hash;
self.current_tip = level.height;
level.set_chain_block(hash);
self.current_tip = level.height();

self.cleanup_chain()
}
Expand Down Expand Up @@ -307,7 +303,7 @@ impl P2Chain {
return Ok((new_tip, Vec::new()));
}

if self.get_tip().is_some() && self.get_tip().unwrap().chain_block == block.prev_hash {
if self.get_tip().is_some() && self.get_tip().unwrap().chain_block() == block.prev_hash {
// easy this builds on the tip
info!(target: LOG_TARGET, "[{:?}] New block added to tip, and is now the new tip: {:?}:{}", algo, new_block_height, &block.hash.to_hex()[0..8]);
for uncle in &block.uncles {
Expand All @@ -320,13 +316,13 @@ impl P2Chain {
let uncle_level = self
.level_at_height(uncle.0.saturating_sub(1))
.ok_or(ShareChainError::BlockLevelNotFound)?;
if uncle_level.chain_block != uncle_parent.hash {
if uncle_level.chain_block() != uncle_parent.hash {
return Err(ShareChainError::UncleParentNotInMainChain);
}
let own_level = self
.level_at_height(uncle.0)
.ok_or(ShareChainError::BlockLevelNotFound)?;
if own_level.chain_block == uncle.1 {
if own_level.chain_block() == uncle.1 {
return Err(ShareChainError::UncleInMainChain {
height: uncle.0,
hash: uncle.1,
Expand Down Expand Up @@ -379,7 +375,7 @@ impl P2Chain {
let level = self
.level_at_height(current_counting_block.height)
.ok_or(ShareChainError::BlockLevelNotFound)?;
if level.chain_block == current_counting_block.hash {
if level.chain_block() == current_counting_block.hash {
break;
}
// we can unwrap as we now the parent exists
Expand All @@ -403,17 +399,17 @@ impl P2Chain {
.expect("Failed to create LWMA");
self.lwma.add_front(block.timestamp, block.target_difficulty());
let chain_height = self
.level_at_height_mut(block.height)
.level_at_height(block.height)
.ok_or(ShareChainError::BlockLevelNotFound)?;
chain_height.chain_block = block.hash;
chain_height.set_chain_block(block.hash);
self.cached_shares = None;
self.current_tip = block.height;
// lets fix the chain
// lets first go up and reset all chain block links
let mut current_height = block.height;
while self.level_at_height(current_height.saturating_add(1)).is_some() {
let mut_child_level = self.level_at_height_mut(current_height.saturating_add(1)).unwrap();
mut_child_level.chain_block = FixedHash::zero();
let mut_child_level = self.level_at_height(current_height.saturating_add(1)).unwrap();
mut_child_level.set_chain_block(FixedHash::zero());
current_height += 1;
}

Expand All @@ -422,37 +418,35 @@ impl P2Chain {
while self.level_at_height(current_block.height.saturating_sub(1)).is_some() {
counter += 1;
let parent_level = (self.level_at_height(current_block.height.saturating_sub(1)).unwrap()).clone();
if current_block.prev_hash != parent_level.chain_block {
if current_block.prev_hash != parent_level.chain_block() {
// safety check
let nextblock = parent_level.blocks.get(&current_block.prev_hash);
let nextblock = parent_level.get(&current_block.prev_hash);
if nextblock.is_none() {
error!(target: LOG_TARGET, "FATAL: Reorging (block in chain) failed because parent block was not found and chain data is corrupted.");
panic!(
"FATAL: Reorging (block in chain) failed because parent block was not found and chain \
data is corrupted. current_block: {:?}, current tip: {:?}",
current_block,
self.get_tip()
self.get_tip().map(|t| t.height())
);
}
// fix the main chain
let mut_parent_level = self
.level_at_height_mut(current_block.height.saturating_sub(1))
.unwrap();
mut_parent_level.chain_block = current_block.prev_hash;
let mut_parent_level = self.level_at_height(current_block.height.saturating_sub(1)).unwrap();
mut_parent_level.set_chain_block(current_block.prev_hash);
current_block = nextblock.unwrap().clone();
self.lwma
.add_front(current_block.timestamp, current_block.target_difficulty());
} else if !self.lwma.is_full() {
// we still need more blocks to fill up the lwma
let nextblock = parent_level.blocks.get(&current_block.prev_hash);
let nextblock = parent_level.get(&current_block.prev_hash);
if nextblock.is_none() {
error!(target: LOG_TARGET, "FATAL: Reorging (block not in chain) failed because parent block was not found and chain data is corrupted.");
panic!(
"FATAL: Could not calculate LMWA while reorging (block in chain) failed because \
parent block was not found and chain data is corrupted. current_block: {:?}, current \
tip: {:?}",
current_block,
self.get_tip()
self.get_tip().map(|t| t.height())
);
}

Expand Down Expand Up @@ -486,14 +480,14 @@ impl P2Chain {
// let see if we already have a block is a missing block of some other block
for check_height in (height + 1)..height + MAX_UNCLE_AGE {
if let Some(level) = self.level_at_height(check_height) {
for block in &level.blocks {
for uncles in &block.1.uncles {
for block in &level.all_blocks() {
for uncles in &block.uncles {
if uncles.1 == hash {
next_level_data.push((block.1.height, block.1.hash));
next_level_data.push((block.height, block.hash));
}
}
if block.1.prev_hash == hash {
next_level_data.push((block.1.height, block.1.hash));
if block.prev_hash == hash {
next_level_data.push((block.height, block.hash));
}
}
}
Expand All @@ -506,7 +500,7 @@ impl P2Chain {
let level = self
.level_at_height(height)
.ok_or(ShareChainError::BlockLevelNotFound)?;
let block = level.blocks.get(&hash).ok_or(ShareChainError::BlockNotFound)?;
let block = level.get(&hash).ok_or(ShareChainError::BlockNotFound)?;
if block.verified {
return Ok(());
}
Expand All @@ -533,9 +527,9 @@ impl P2Chain {
// lets replace this
actual_block.verified = verified;
let level = self
.level_at_height_mut(height)
.level_at_height(height)
.ok_or(ShareChainError::BlockLevelNotFound)?;
level.blocks.insert(hash, Arc::new(actual_block));
level.add_block(Arc::new(actual_block));
return Ok(());
}

Expand All @@ -552,9 +546,9 @@ impl P2Chain {
// lets replace this
actual_block.verified = verified;
let level = self
.level_at_height_mut(height)
.level_at_height(height)
.ok_or(ShareChainError::BlockLevelNotFound)?;
level.blocks.insert(hash, Arc::new(actual_block));
level.add_block(Arc::new(actual_block));
}

Ok(())
Expand All @@ -569,7 +563,7 @@ impl P2Chain {
self.levels.insert(new_block_height, new_level);
return self.verify_chain(new_block_height, block_hash);
}
match self.level_at_height_mut(new_block_height) {
match self.level_at_height(new_block_height) {
Some(level) => {
level.add_block(block)?;
self.verify_chain(new_block_height, block_hash)
Expand Down Expand Up @@ -603,16 +597,16 @@ impl P2Chain {
Some(level) => level,
None => return None,
};
parent_level.blocks.get(&block.prev_hash)
parent_level.get(&block.prev_hash)
}

pub fn get_tip(&self) -> Option<&P2ChainLevel> {
self.level_at_height(self.current_tip)
.filter(|&level| level.chain_block != FixedHash::zero())
.filter(|&level| level.chain_block() != FixedHash::zero())
}

pub fn get_height(&self) -> u64 {
self.get_tip().map(|tip| tip.height).unwrap_or(0)
self.get_tip().map(|tip| tip.height()).unwrap_or(0)
}

pub fn get_max_chain_length(&self) -> usize {
Expand Down
Loading

0 comments on commit b75770e

Please sign in to comment.