Skip to content

Commit

Permalink
fix: added inline comments
Browse files Browse the repository at this point in the history
  • Loading branch information
nakul1010 committed Sep 21, 2023
1 parent 6df4339 commit 3d9c0c8
Showing 1 changed file with 37 additions and 5 deletions.
42 changes: 37 additions & 5 deletions crates/btc-relay/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,15 +795,28 @@ impl<T: Config> Pallet<T> {
}

fn get_block_hash_from_forks(chain_id: u32, block_height: u32) -> Result<H256Le, DispatchError> {
// Get the blockchain associated with the given chain_id.
let chain = Self::get_block_chain_from_id(chain_id)?;

// If the requested block height is before the chain's start height,
// recursively fetch the block hash from the previous chain.
if block_height < chain.start_height {
// Get the hash of the block at the start height of the current chain.
let start_height_hash = Self::get_block_hash(chain_id, chain.start_height)?;

// Get the previous block's header from its hash.
let prev_hash = Self::get_block_header_from_hash(start_height_hash)?
.block_header
.hash_prev_block;

// Get the chain_id of the previous chain.
let prev_chain_id = Self::get_block_header_from_hash(prev_hash)?.chain_id;

// Recursively call the function for the previous chain and requested block height.
Self::get_block_hash_from_forks(prev_chain_id, block_height)
} else {
// If the requested block height is within the current chain's range,
// directly fetch the block hash from the current chain.
Self::get_block_hash(chain_id, block_height)
}
}
Expand Down Expand Up @@ -1217,7 +1230,7 @@ impl<T: Config> Pallet<T> {
// update: ensure_no_ongoing_fork
if prev_height.saturating_add(Self::get_stable_transaction_confirmations()) <= current_height
&&
// We should only reorg when the fork has more work than the current main chain
// We should only reorg when the fork has more or equal work than the current main chain
current_fork_work >= prev_fork_work
{
// Swap the mainchain. As an optimization, this function returns the
Expand Down Expand Up @@ -1259,6 +1272,8 @@ impl<T: Config> Pallet<T> {
fn get_target(chain_id: u32, height: u32) -> Result<u32, DispatchError> {
let block_hash = Self::get_block_hash_from_forks(chain_id, height)?;
let block_header = Self::get_block_header_from_hash(block_hash)?;
// Fixme: Should this be kept as a U256 type and other u32 type can be converted to U256?
// Currently taking low_u32/as_u32 loses precision
Ok(block_header.block_header.target.low_u32())
}

Expand All @@ -1272,7 +1287,9 @@ impl<T: Config> Pallet<T> {
}

// Reference: https://github.com/spesmilo/electrum/blob/cee22abcb5544c5a6fa7f8a8108ccda9c32c2e29/electrum/blockchain.py#L589-L614
// Calculate the cumulative chainwork of a blockchain.
fn get_chainwork(chain: BlockChain) -> Result<u32, DispatchError> {
// Calculate the height of the last retarget point.
let last_retarget = chain
.max_height
.saturating_div(DIFFICULTY_ADJUSTMENT_INTERVAL)
Expand All @@ -1281,40 +1298,55 @@ impl<T: Config> Pallet<T> {

let mut cached_height = last_retarget;

// Iterate backward to find the last block with known chainwork.
while Self::get_block_chainwork(Self::get_block_hash_from_forks(chain.chain_id, cached_height)?).is_none() {
if cached_height == 0 {
break;
}
cached_height = cached_height.saturating_sub(DIFFICULTY_ADJUSTMENT_INTERVAL)
}

// Get the chainwork of the last known block.
let cache_chain_work =
Self::get_block_chainwork(Self::get_block_hash_from_forks(chain.chain_id, cached_height)?);
let mut running_total = if let Some(chain_work) = cache_chain_work {
chain_work
} else {
//genesis chain work should be 0
// Genesis chain work should be 0.
0_u32
};

// Loop to calculate chain work for blocks between 'cached_height' and 'last_retarget' 0 to 2015
// Loop to calculate chainwork for blocks between 'cached_height' and 'last_retarget' (0 to 2015).
while cached_height < last_retarget {
cached_height = cached_height.saturating_add(DIFFICULTY_ADJUSTMENT_INTERVAL);

// Calculate the chainwork for a single header at the current height.
let work_in_single_header = Self::chainwork_of_header_at_height(chain.chain_id, cached_height)?;

// Calculate the chainwork for a chunk of blocks (DIFFICULTY_ADJUSTMENT_INTERVAL) at the current height.
let work_in_chunk = DIFFICULTY_ADJUSTMENT_INTERVAL.saturating_mul(work_in_single_header);

// Update the running total chainwork.
running_total = running_total.saturating_add(work_in_chunk);

// Store the calculated chainwork for the block.
Self::set_block_chainwork(
Self::get_block_hash_from_forks(chain.chain_id, cached_height)?,
Self::get_block_hash_from_forks(chain.chain_id, cached_height)?, /* ToDo: Done repeatedly in
* work_in_single_header */
running_total,
);
}

// Move to the next height.
cached_height = cached_height.saturating_add(DIFFICULTY_ADJUSTMENT_INTERVAL);

// Calculate the chainwork for the last partial chunk of blocks.
let work_in_single_header = Self::chainwork_of_header_at_height(chain.chain_id, cached_height)?;

let work_in_last_partial_chunk = ((chain.max_height % DIFFICULTY_ADJUSTMENT_INTERVAL).saturating_add(1))
let work_in_last_partial_chunk = ((chain.max_height % DIFFICULTY_ADJUSTMENT_INTERVAL).saturating_plus_one())
.saturating_mul(work_in_single_header);

// Return the total chainwork, which is the running total plus the chain work of the last partial chunk.
Ok(running_total.saturating_add(work_in_last_partial_chunk))
}

Expand Down

0 comments on commit 3d9c0c8

Please sign in to comment.