fixed mining io issues
This commit is contained in:
parent
f651fda2dd
commit
b8c8e47b69
|
|
@ -2,6 +2,7 @@ use crate::common::skein::{skein_256_hash_data, skein_512_hash_data};
|
|||
use crate::common::types::Transaction;
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::memory::averages::asert_genesis_anchor;
|
||||
use crate::records::memory::chain_state::cached_chain_height;
|
||||
use crate::sled::Db;
|
||||
use crate::to_string;
|
||||
use crate::wallets::structures::Wallet;
|
||||
|
|
@ -178,7 +179,9 @@ impl UnminedBlock {
|
|||
db: &Db,
|
||||
current_difficulty: u64,
|
||||
) -> u64 {
|
||||
let block_number = get_height(db);
|
||||
let block_number = cached_chain_height()
|
||||
.await
|
||||
.unwrap_or_else(|| get_height(db));
|
||||
let candidate_height = block_number + 1;
|
||||
|
||||
let Some((anchor_height, anchor_timestamp, anchor_difficulty)) =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::blocks::rewards::{RewardsTransaction, UnsignedRewardsTransaction};
|
||||
use crate::common::types::BLOCKS_PER_HALVING;
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::memory::chain_state::cached_chain_height;
|
||||
use crate::records::memory::network_mapping::NodeInfo;
|
||||
use crate::sled::Db;
|
||||
|
||||
|
|
@ -35,18 +36,14 @@ pub async fn create_rewards_transaction(
|
|||
let txtype = 1;
|
||||
|
||||
// The reward belongs to the block being created, not the current tip.
|
||||
let block_height = get_height(db) + 1;
|
||||
let block_height = cached_chain_height()
|
||||
.await
|
||||
.unwrap_or_else(|| get_height(db))
|
||||
+ 1;
|
||||
|
||||
// New miners must first prove participation before receiving
|
||||
// the block subsidy, so early mined blocks pay a zero reward.
|
||||
let value = if !NodeInfo::chain_mined_count_at_least(
|
||||
short_address,
|
||||
get_height(db),
|
||||
REWARD_MATURITY_BLOCKS,
|
||||
)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let value = if NodeInfo::get_mined_count(short_address).await < REWARD_MATURITY_BLOCKS {
|
||||
0_u64
|
||||
} else {
|
||||
calculate_block_reward(block_height).await
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::log::info;
|
||||
use crate::miner::flag::{is_mining_stop_requested, is_normal_mode, set_mining_state, MiningState};
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::memory::chain_state::cached_header;
|
||||
use crate::records::unpack_block::unpack_header::load_block_header;
|
||||
use crate::sled::Db;
|
||||
use crate::sleep;
|
||||
|
|
@ -21,8 +22,12 @@ pub async fn fairness_difficulty(block_height: u32, miner_wallet: &str) -> bool
|
|||
// Walk backward through the recent headers and count how many
|
||||
// consecutive blocks were mined by this same miner.
|
||||
for i in (start_block..=block_height).rev() {
|
||||
// Load the saved header for this height.
|
||||
let block = load_block_header(i).await.unwrap();
|
||||
// Use the in-memory recent-header cache during mining, falling
|
||||
// back to disk only if the cache is not populated yet.
|
||||
let block = match cached_header(i).await {
|
||||
Some(block) => block,
|
||||
None => load_block_header(i).await.unwrap(),
|
||||
};
|
||||
|
||||
// The header stores the miner short address directly.
|
||||
let mined_by_miner = block.unmined_block.miner;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use crate::miner::nonce::run_nonce_round;
|
|||
use crate::miner::structs::MiningAttemptContext;
|
||||
use crate::miner::winner::{handle_mining_winner, verify_and_save_block};
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::memory::chain_state::{cached_chain_height, cached_tip_header};
|
||||
use crate::records::memory::connections::peer_connection_count;
|
||||
use crate::records::memory::network_mapping::NodeInfo;
|
||||
use crate::records::memory::response_channels::Command;
|
||||
|
|
@ -46,7 +47,7 @@ pub async fn mine_block(
|
|||
|
||||
// Track the height this miner expects to produce next so nonce workers
|
||||
// can stop quickly when another peer advances the chain.
|
||||
let mut expected_block_height = get_height(db) + 1;
|
||||
let mut expected_block_height = current_chain_height(db).await + 1;
|
||||
let mut fairness_paused_height: Option<u32> = None;
|
||||
let mut registration_paused_height: Option<u32> = None;
|
||||
let mut was_stopped = true;
|
||||
|
|
@ -58,7 +59,7 @@ pub async fn mine_block(
|
|||
|
||||
// Re-read height each round because peers may have saved a block
|
||||
// while this miner was paused or waiting for the next second.
|
||||
let current_block_number = get_height(db) + 1;
|
||||
let current_block_number = current_chain_height(db).await + 1;
|
||||
if current_block_number != expected_block_height {
|
||||
expected_block_height = current_block_number;
|
||||
}
|
||||
|
|
@ -191,14 +192,14 @@ async fn wait_for_next_second_or_chain_change(
|
|||
// space unless the chain tip or node mode changes first.
|
||||
if !(is_normal_mode()
|
||||
&& !is_mining_stop_requested()
|
||||
&& get_height(db) + 1 == expected_block_height)
|
||||
&& current_chain_height(db).await + 1 == expected_block_height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while is_normal_mode()
|
||||
&& !is_mining_stop_requested()
|
||||
&& get_height(db) + 1 == expected_block_height
|
||||
&& current_chain_height(db).await + 1 == expected_block_height
|
||||
{
|
||||
let now_second = Utc::now().timestamp() as u32;
|
||||
if now_second != round_second {
|
||||
|
|
@ -222,7 +223,10 @@ async fn build_attempt_context(
|
|||
return Err("Mining paused before loading previous block header".into());
|
||||
}
|
||||
let previous_block_height = current_block_number - 1;
|
||||
let previous_block = load_block_header(previous_block_height).await?;
|
||||
let previous_block = match cached_tip_header(previous_block_height).await {
|
||||
Some(header) => header,
|
||||
None => load_block_header(previous_block_height).await?,
|
||||
};
|
||||
let previous_hash = previous_block.hash().await;
|
||||
let previous_difficulty = previous_block.unmined_block.next_block_difficulty;
|
||||
|
||||
|
|
@ -237,6 +241,12 @@ async fn build_attempt_context(
|
|||
})
|
||||
}
|
||||
|
||||
async fn current_chain_height(db: &Db) -> u32 {
|
||||
cached_chain_height()
|
||||
.await
|
||||
.unwrap_or_else(|| get_height(db))
|
||||
}
|
||||
|
||||
pub async fn mine_block_internal(
|
||||
ctx: &MiningAttemptContext,
|
||||
nonce: u8,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use crate::miner::flag::{is_mining_stop_requested, is_normal_mode};
|
|||
use crate::miner::mining::mine_block_internal;
|
||||
use crate::miner::structs::MiningAttemptContext;
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::memory::chain_state::cached_chain_height;
|
||||
use crate::task;
|
||||
use crate::Arc;
|
||||
use crate::AtomicBool;
|
||||
|
|
@ -92,7 +93,10 @@ async fn nonce_range(
|
|||
}
|
||||
|
||||
// If the chain tip changed, this round is stale for every worker.
|
||||
if get_height(&ctx.db) + 1 != ctx.current_block_number {
|
||||
let current_height = cached_chain_height()
|
||||
.await
|
||||
.unwrap_or_else(|| get_height(&ctx.db));
|
||||
if current_height + 1 != ctx.current_block_number {
|
||||
stop_flag.store(true, AtomicOrdering::SeqCst);
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use crate::orphans::undo_transactions::undo_swap::undo_swap_transaction;
|
|||
use crate::orphans::undo_transactions::undo_transfer::undo_transfer_transaction;
|
||||
use crate::orphans::undo_transactions::undo_vanity::undo_vanity_transaction;
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::memory::chain_state::rebuild_chain_state_cache;
|
||||
use crate::records::memory::network_mapping::NodeInfo;
|
||||
use crate::records::memory::torrent_status::reset_all_torrent_statuses;
|
||||
use crate::records::unpack_block::load_by_block_number::load_block;
|
||||
|
|
@ -154,6 +155,7 @@ pub async fn undo_transactions(
|
|||
|
||||
let final_height = true_start_height.saturating_sub(1);
|
||||
crate::orphans::undo_block::finalize_undo_height(final_height, ¶ms.db).await;
|
||||
rebuild_chain_state_cache(¶ms.db).await?;
|
||||
|
||||
// Only now that every rolled-back block has been unwound do we test
|
||||
// whether its former transactions are still spendable on the new base.
|
||||
|
|
@ -169,6 +171,7 @@ pub async fn undo_transactions(
|
|||
// replacement blocks, and finally rebuild mined counts again
|
||||
NodeInfo::rebuild_mined_counts_from_chain(¶ms.db).await?;
|
||||
save_new_blocks(¶ms, replay_to_height, wallet, true_start_height).await?;
|
||||
rebuild_chain_state_cache(¶ms.db).await?;
|
||||
NodeInfo::rebuild_mined_counts_from_chain(¶ms.db).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
use crate::records::memory::chain_state::cached_asert_genesis_anchor;
|
||||
use crate::records::unpack_block::unpack_header::load_block_header;
|
||||
|
||||
pub async fn asert_genesis_anchor() -> Option<(u32, u32, u64)> {
|
||||
// ASERT uses genesis as a fixed consensus anchor, so long-term drift
|
||||
// toward the 15-second schedule cannot be forgotten by a rolling cache.
|
||||
if let Some(anchor) = cached_asert_genesis_anchor().await {
|
||||
return Some(anchor);
|
||||
}
|
||||
|
||||
match load_block_header(0).await {
|
||||
Ok(header) => Some((
|
||||
0,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
use crate::blocks::block::VrfBlock;
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::unpack_block::unpack_header::load_block_header;
|
||||
use crate::{lazy_static, HashMap, Mutex};
|
||||
|
||||
const RECENT_HEADER_CACHE_DEPTH: u32 = 32;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct ChainStateCache {
|
||||
height: Option<u32>,
|
||||
tip_header: Option<VrfBlock>,
|
||||
tip_hash: Option<String>,
|
||||
genesis_anchor: Option<(u32, u32, u64)>,
|
||||
recent_headers: HashMap<u32, VrfBlock>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref CHAIN_STATE: Mutex<ChainStateCache> = Mutex::new(ChainStateCache::default());
|
||||
}
|
||||
|
||||
fn recent_floor(height: u32) -> u32 {
|
||||
height.saturating_sub(RECENT_HEADER_CACHE_DEPTH)
|
||||
}
|
||||
|
||||
fn cache_genesis_anchor(cache: &mut ChainStateCache, height: u32, header: &VrfBlock) {
|
||||
if height == 0 {
|
||||
cache.genesis_anchor = Some((
|
||||
0,
|
||||
header.unmined_block.timestamp,
|
||||
header.unmined_block.next_block_difficulty,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn prune_recent_headers(cache: &mut ChainStateCache, height: u32) {
|
||||
let floor = recent_floor(height);
|
||||
cache
|
||||
.recent_headers
|
||||
.retain(|cached_height, _| *cached_height == 0 || *cached_height >= floor);
|
||||
}
|
||||
|
||||
pub async fn rebuild_chain_state_cache(db: &crate::sled::Db) -> Result<(), String> {
|
||||
let height = get_height(db);
|
||||
let mut loaded_headers = HashMap::new();
|
||||
let mut genesis_anchor = None;
|
||||
let mut tip_header = None;
|
||||
let mut tip_hash = None;
|
||||
|
||||
if let Ok(genesis_header) = load_block_header(0).await {
|
||||
genesis_anchor = Some((
|
||||
0,
|
||||
genesis_header.unmined_block.timestamp,
|
||||
genesis_header.unmined_block.next_block_difficulty,
|
||||
));
|
||||
loaded_headers.insert(0, genesis_header);
|
||||
}
|
||||
|
||||
let floor = recent_floor(height);
|
||||
for block_height in floor..=height {
|
||||
if block_height == 0 && loaded_headers.contains_key(&0) {
|
||||
continue;
|
||||
}
|
||||
if let Ok(header) = load_block_header(block_height).await {
|
||||
if block_height == height {
|
||||
tip_hash = Some(header.hash().await);
|
||||
tip_header = Some(header.clone());
|
||||
}
|
||||
loaded_headers.insert(block_height, header);
|
||||
}
|
||||
}
|
||||
|
||||
if height == 0 {
|
||||
if let Some(header) = loaded_headers.get(&0) {
|
||||
tip_hash = Some(header.hash().await);
|
||||
tip_header = Some(header.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let mut cache = CHAIN_STATE.lock().await;
|
||||
*cache = ChainStateCache {
|
||||
height: Some(height),
|
||||
tip_header,
|
||||
tip_hash,
|
||||
genesis_anchor,
|
||||
recent_headers: loaded_headers,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_chain_state_after_save(height: u32, header: VrfBlock, header_hash: String) {
|
||||
let mut cache = CHAIN_STATE.lock().await;
|
||||
cache.height = Some(height);
|
||||
cache.tip_header = Some(header.clone());
|
||||
cache.tip_hash = Some(header_hash);
|
||||
cache.recent_headers.insert(height, header.clone());
|
||||
cache_genesis_anchor(&mut cache, height, &header);
|
||||
prune_recent_headers(&mut cache, height);
|
||||
}
|
||||
|
||||
pub async fn cached_chain_height() -> Option<u32> {
|
||||
CHAIN_STATE.lock().await.height
|
||||
}
|
||||
|
||||
pub async fn cached_tip_header(expected_height: u32) -> Option<VrfBlock> {
|
||||
let cache = CHAIN_STATE.lock().await;
|
||||
if cache.height == Some(expected_height) {
|
||||
cache.tip_header.clone()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn cached_tip_hash(expected_height: u32) -> Option<String> {
|
||||
let cache = CHAIN_STATE.lock().await;
|
||||
if cache.height == Some(expected_height) {
|
||||
cache.tip_hash.clone()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn cached_header(block_height: u32) -> Option<VrfBlock> {
|
||||
CHAIN_STATE
|
||||
.lock()
|
||||
.await
|
||||
.recent_headers
|
||||
.get(&block_height)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub async fn cached_asert_genesis_anchor() -> Option<(u32, u32, u64)> {
|
||||
CHAIN_STATE.lock().await.genesis_anchor
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// The memory module holds the runtime-only structures used for active connections,
|
||||
// mempool ordering, torrent state, and other transient node state.
|
||||
pub mod averages;
|
||||
pub mod chain_state;
|
||||
pub mod connections;
|
||||
pub mod enums;
|
||||
pub mod mempool;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ use crate::orphans::snapshot_check::{snapshot_height, update_snapshot};
|
|||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::block_height::increase_block_height::increase_height;
|
||||
use crate::records::memory::averages::asert_genesis_anchor;
|
||||
use crate::records::memory::chain_state::{
|
||||
cached_tip_hash, cached_tip_header, update_chain_state_after_save,
|
||||
};
|
||||
use crate::records::memory::mempool::{
|
||||
apply_selected_transaction_math, ensure_db_connection, mark_processed_by_signatures,
|
||||
mark_selected_transactions_processed, restore_processed_by_signatures,
|
||||
|
|
@ -89,8 +92,10 @@ pub async fn save_block(params: SaveBlockParams) -> Result<(), String> {
|
|||
// before any headers, files, or mempool effects are written.
|
||||
let current_height = get_height(&db);
|
||||
if current_height > 0 {
|
||||
let current_block = load_block_header(current_height).await?;
|
||||
let current_hash = current_block.hash().await;
|
||||
let current_hash = match cached_tip_hash(current_height).await {
|
||||
Some(hash) => hash,
|
||||
None => load_block_header(current_height).await?.hash().await,
|
||||
};
|
||||
if current_hash != *previous_hash {
|
||||
if save_type == SaveType::Mining {
|
||||
return Err(format!(
|
||||
|
|
@ -113,7 +118,10 @@ pub async fn save_block(params: SaveBlockParams) -> Result<(), String> {
|
|||
// so the saved-block diagnostic log reflects the live adjustment input.
|
||||
let mut previous_difficulty = 0_u64;
|
||||
if block_header_number > 0 {
|
||||
previous_difficulty = previous_block_difficulty(block_header_number).await?;
|
||||
previous_difficulty = match cached_tip_header(block_header_number - 1).await {
|
||||
Some(header) => header.unmined_block.next_block_difficulty,
|
||||
None => previous_block_difficulty(block_header_number).await?,
|
||||
};
|
||||
}
|
||||
|
||||
log_saved_block_difficulty(
|
||||
|
|
@ -366,6 +374,13 @@ async fn save_binary_data_with_mempool_stream(
|
|||
broadcast_new_torrent_to_peers(next_number, &torrent_bytes, map).await;
|
||||
}
|
||||
|
||||
match crate::blocks::block::VrfBlock::from_bytes(header_bytes).await {
|
||||
Ok(saved_header) => {
|
||||
update_chain_state_after_save(next_number, saved_header, header_hash.to_string()).await;
|
||||
}
|
||||
Err(err) => error!("Failed to cache saved block header: {err}"),
|
||||
}
|
||||
|
||||
// Only advance mined-count tracking when this save actually moved
|
||||
// the persisted chain height forward.
|
||||
if get_height(db) > previous_height {
|
||||
|
|
@ -497,6 +512,13 @@ async fn save_binary_data(params: SaveBinaryDataParams<'_>) -> Result<(), String
|
|||
broadcast_new_torrent_to_peers(next_number, &torrent_bytes, map).await;
|
||||
}
|
||||
|
||||
match crate::blocks::block::VrfBlock::from_bytes(header_bytes).await {
|
||||
Ok(saved_header) => {
|
||||
update_chain_state_after_save(next_number, saved_header, header_hash.to_string()).await;
|
||||
}
|
||||
Err(err) => error!("Failed to cache saved block header: {err}"),
|
||||
}
|
||||
|
||||
// Only advance mined-count tracking when this save actually moved
|
||||
// the persisted chain height forward.
|
||||
if get_height(db) > previous_height {
|
||||
|
|
|
|||
|
|
@ -402,8 +402,10 @@ pub async fn receive_torrent(
|
|||
if get_client_type_from_memory(connections_key).await == Some(ClientType::Miner)
|
||||
&& !peer_is_operational(connections_key).await
|
||||
{
|
||||
let local_height = get_height(db);
|
||||
if !within_orphan_window(local_height, block_number) {
|
||||
warn!(
|
||||
"[broadcast] ignored torrent from non-operational peer: peer={connections_key} height={block_number}"
|
||||
"[broadcast] ignored torrent from non-operational peer outside orphan window: peer={connections_key} local_height={local_height} height={block_number}"
|
||||
);
|
||||
return Ok((
|
||||
uid,
|
||||
|
|
@ -414,6 +416,10 @@ pub async fn receive_torrent(
|
|||
),
|
||||
));
|
||||
}
|
||||
warn!(
|
||||
"[broadcast] accepting torrent from non-operational peer within orphan window: peer={connections_key} local_height={local_height} height={block_number}"
|
||||
);
|
||||
}
|
||||
|
||||
let outcome = torrent_submission(
|
||||
block_number,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use crate::log::{error, info};
|
|||
use crate::miner::genesis::create_genesis_transaction;
|
||||
use crate::miner::mining::mine_block;
|
||||
use crate::panic;
|
||||
use crate::records::memory::chain_state::rebuild_chain_state_cache;
|
||||
use crate::records::memory::mempool::{init_db, setup_mempool};
|
||||
use crate::records::memory::network_mapping::NodeInfo;
|
||||
use crate::records::memory::response_channels::Command;
|
||||
|
|
@ -108,6 +109,9 @@ pub async fn run_unlocked_node(wallet: Arc<Wallet>, install_shutdown: bool) -> R
|
|||
|
||||
// Open sled after Postgres is ready so block state and mempool state start together.
|
||||
let db = open_chain_state().await;
|
||||
if let Err(err) = rebuild_chain_state_cache(&db).await {
|
||||
error!("[chain_state] failed to rebuild startup chain state cache: {err}");
|
||||
}
|
||||
|
||||
if install_shutdown {
|
||||
// Console/daemon mode owns signal cleanup; Windows service shutdown is handled separately.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ use crate::common::types::Transaction;
|
|||
use crate::encode;
|
||||
use crate::miner::fairness::fairness_difficulty;
|
||||
use crate::records::block_height::get_block_height::get_height;
|
||||
use crate::records::memory::chain_state::{
|
||||
cached_chain_height, cached_tip_hash, cached_tip_header,
|
||||
};
|
||||
use crate::records::memory::network_mapping::NodeInfo;
|
||||
use crate::records::unpack_block::unpack_header::load_block_header;
|
||||
use crate::records::wallet_registry::resolve_pubkey_from_short_address;
|
||||
|
|
@ -47,7 +50,7 @@ impl Block {
|
|||
.map_err(|e| e.to_string())?
|
||||
.ok_or_else(|| "This miner address is not registered".to_string())?;
|
||||
let miner_pubkey_hex = encode(&miner_pubkey);
|
||||
let block_number = get_height(db) + 1;
|
||||
let block_number = current_chain_height(db).await + 1;
|
||||
|
||||
if !NodeInfo::address_checkup(miner, block_number).await {
|
||||
return Err("This address is not eligable to mine".to_string());
|
||||
|
|
@ -117,8 +120,11 @@ impl Block {
|
|||
// load the last block this is the current height
|
||||
// as we are always validating a height higher than
|
||||
// what is recorded.
|
||||
let previous_height = get_height(db);
|
||||
let previous_block = load_block_header(previous_height).await?;
|
||||
let previous_height = current_chain_height(db).await;
|
||||
let previous_block = match cached_tip_header(previous_height).await {
|
||||
Some(header) => header,
|
||||
None => load_block_header(previous_height).await?,
|
||||
};
|
||||
|
||||
// check if miner is eligible based on
|
||||
// fairness difficulty checker
|
||||
|
|
@ -130,7 +136,10 @@ impl Block {
|
|||
}
|
||||
|
||||
// get previous block hash
|
||||
let calculated_previous_hash = previous_block.hash().await;
|
||||
let calculated_previous_hash = match cached_tip_hash(previous_height).await {
|
||||
Some(hash) => hash,
|
||||
None => previous_block.hash().await,
|
||||
};
|
||||
|
||||
// Validate recorded previous_hash is equal to
|
||||
// the previous block hash
|
||||
|
|
@ -195,9 +204,12 @@ impl Block {
|
|||
);
|
||||
}
|
||||
}
|
||||
let current_block_number = get_height(db) + 1;
|
||||
let current_block_number = current_chain_height(db).await + 1;
|
||||
let previous_block_height = current_block_number - 1;
|
||||
let previous_block = load_block_header(previous_block_height).await?;
|
||||
let previous_block = match cached_tip_header(previous_block_height).await {
|
||||
Some(header) => header,
|
||||
None => load_block_header(previous_block_height).await?,
|
||||
};
|
||||
let difficulty_target = previous_block.unmined_block.next_block_difficulty;
|
||||
if hash >= difficulty_target {
|
||||
Err(format!(
|
||||
|
|
@ -208,3 +220,9 @@ impl Block {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn current_chain_height(db: &Db) -> u32 {
|
||||
cached_chain_height()
|
||||
.await
|
||||
.unwrap_or_else(|| get_height(db))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,7 @@ impl RewardsTransaction {
|
|||
|
||||
// New miners receive zero reward until their mined-count history
|
||||
// reaches the maturity threshold.
|
||||
let reward_value = if !NodeInfo::chain_mined_count_at_least(
|
||||
&miner,
|
||||
previous_height,
|
||||
REWARD_MATURITY_BLOCKS,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
let reward_value = if NodeInfo::get_mined_count(&miner).await < REWARD_MATURITY_BLOCKS {
|
||||
0_u64
|
||||
} else {
|
||||
calculate_block_reward(previous_height + 1).await
|
||||
|
|
|
|||
Loading…
Reference in New Issue