Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions pallets/qpow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub mod pallet {
traits::{BuildGenesisConfig, Time},
};
use frame_system::pallet_prelude::BlockNumberFor;
use qpow_math::{achieved_difficulty_from_hash, get_nonce_hash, is_valid_nonce};
use qpow_math::{get_nonce_hash, is_valid_nonce};
use sp_core::U512;

pub type NonceType = [u8; 64];
Expand Down Expand Up @@ -306,9 +306,23 @@ pub mod pallet {
verify
}

/// Verify nonce validity and return achieved difficulty in a single call.
/// This avoids computing the nonce hash twice when both validation and
/// achieved difficulty are needed during block import.
/// Verify the nonce and return the block's work used for chain selection.
///
/// IMPORTANT: despite the legacy name, this returns the *target* difficulty the
/// block had to satisfy (the network difficulty at this height), NOT the achieved
/// difficulty derived from the winning hash. Target-based work matches Bitcoin
/// (`2^256/(target+1)`) and Ethereum PoW (sum of the `difficulty` field): every
/// block at a given difficulty contributes an identical, deterministic amount of
/// work, so cumulative chain work tracks expended hash power instead of being
/// dominated by a single lucky hash.
///
/// The runtime API name is intentionally left unchanged so this can ship as an
/// on-chain-only upgrade: because the metric is determined by the value this
/// returns (the client merely accumulates `parent_work + value`), upgrading the
/// on-chain Wasm flips the whole network to target-based work at the `set_code`
/// block, with no coordinated node-binary upgrade and no resync. Renaming the API
/// would break that compatibility, so defer the rename to a later release once all
/// nodes run a binary that expects the new name.
///
/// Note: This is called via runtime API from the client side. Runtime API
/// calls execute in a temporary context where state changes are discarded,
Expand All @@ -317,10 +331,9 @@ pub mod pallet {
block_hash: [u8; 32],
nonce: NonceType,
) -> (bool, U512) {
let (valid, _, hash_achieved) = Self::verify_nonce_internal(block_hash, nonce);
let achieved_difficulty =
if valid { achieved_difficulty_from_hash(hash_achieved) } else { U512::zero() };
(valid, achieved_difficulty)
let (valid, difficulty, _) = Self::verify_nonce_internal(block_hash, nonce);
let block_work = if valid { difficulty } else { U512::zero() };
(valid, block_work)
}

pub fn initial_difficulty() -> Difficulty {
Expand Down
18 changes: 7 additions & 11 deletions pallets/qpow/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,26 +285,22 @@ fn test_verify_and_get_achieved_difficulty() {
let block_hash = [1u8; 32];
let nonce = [2u8; 64];

// Call the combined function
let (valid, achieved_diff) = QPow::verify_and_get_achieved_difficulty(block_hash, nonce);
// Despite the legacy name, this returns the target difficulty (block work).
let (valid, block_work) = QPow::verify_and_get_achieved_difficulty(block_hash, nonce);

// Check that verify_nonce_on_import_block returns the same validity
let expected_valid = QPow::verify_nonce_on_import_block(block_hash, nonce);
assert_eq!(valid, expected_valid, "Validity should match verify_nonce_on_import_block");

if valid {
let nonce_hash = QPow::get_nonce_hash(block_hash, nonce);
let expected_from_hash = U512::MAX / nonce_hash;
// Work is the target difficulty the block satisfied, NOT MAX / nonce_hash.
assert_eq!(
achieved_diff, expected_from_hash,
"Achieved difficulty should equal U512::MAX / nonce_hash"
block_work,
QPow::get_difficulty(),
"Block work should equal the target difficulty"
);
} else {
assert_eq!(
achieved_diff,
U512::zero(),
"Invalid nonce should yield zero achieved difficulty"
);
assert_eq!(block_work, U512::zero(), "Invalid nonce should yield zero work");
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/configs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ parameter_types! {
impl pallet_qpow::Config for Runtime {
type InitialDifficulty = QPoWInitialDifficulty;
type TargetBlockTime = TargetBlockTime;
type MaxReorgDepth = ConstU32<180>;
type MaxReorgDepth = ConstU32<100>;
type WeightInfo = ();
}

Expand Down
Loading