This commit is contained in:
hinto.janai 2024-12-17 17:45:53 -05:00
parent 1bc5e4721c
commit ce6807546c
No known key found for this signature in database
GPG key ID: D47CE05FA175A499

View file

@ -17,7 +17,7 @@ use crate::{
struct Verifier { struct Verifier {
id: usize, id: usize,
now: Instant, start_of_new_pow: Instant,
thread_count: NonZeroUsize, thread_count: NonZeroUsize,
update: NonZeroU64, update: NonZeroU64,
top_height: u64, top_height: u64,
@ -33,14 +33,12 @@ pub fn spawn_verify_pool(
top_height: u64, top_height: u64,
rx: Receiver<RpcBlockData>, rx: Receiver<RpcBlockData>,
) { ) {
let now = Instant::now(); for id in 1..=thread_count.get() {
for id in 0..thread_count.get() {
let rx = rx.clone(); let rx = rx.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
Verifier { Verifier {
id, id,
now, start_of_new_pow: Instant::now(),
thread_count, thread_count,
update, update,
top_height, top_height,
@ -80,39 +78,14 @@ impl Verifier {
} = data; } = data;
let GetBlockResponse { blob, block_header } = get_block_response; let GetBlockResponse { blob, block_header } = get_block_response;
//----------------------------------------------- Calculate some data.
let calculated_block_reward = block
.miner_transaction
.prefix()
.outputs
.iter()
.map(|o| o.amount.unwrap())
.sum::<u64>();
let calculated_block_weight = txs
.iter()
.map(|RpcTxData { tx, .. }| tx.weight())
.sum::<usize>();
let calculated_pow_data = block.serialize_pow_hash();
let miner_tx_weight = block.miner_transaction.weight();
//----------------------------------------------- Verify. //----------------------------------------------- Verify.
Self::verify_block_properties(&blob, &block, calculated_block_reward, &p); Self::verify_blocks(&blob, &block, &txs, &p, block_header);
Self::verify_all_transactions_are_unique(&txs, &p); Self::verify_transactions(txs, &p);
Self::verify_transaction_properties(txs, &p);
Self::verify_block_fields(
calculated_block_weight,
calculated_block_reward,
&block,
&p,
block_header,
);
let algo = self.verify_pow( let algo = self.verify_pow(
block_header.height, block_header.height,
seed_hash, seed_hash,
block_header.pow_hash, block_header.pow_hash,
&calculated_pow_data, &block.serialize_pow_hash(),
&p, &p,
); );
@ -120,27 +93,79 @@ impl Verifier {
self.print_progress( self.print_progress(
algo, algo,
seed_height, seed_height,
miner_tx_weight, block.miner_transaction.weight(),
blocks_per_sec, blocks_per_sec,
block_header, block_header,
); );
} }
fn verify_block_properties( fn verify_blocks(
block_blob: &[u8], block_blob: &[u8],
block: &Block, block: &Block,
calculated_block_reward: u64, txs: &[RpcTxData],
p: &str, p: &str,
BlockHeader {
block_weight,
hash,
pow_hash: _,
height,
major_version,
minor_version,
miner_tx_hash,
nonce,
num_txes,
prev_hash,
reward,
timestamp,
}: BlockHeader,
) { ) {
// Test block properties. let calculated_block_reward = block
.miner_transaction
.prefix()
.outputs
.iter()
.map(|o| o.amount.unwrap())
.sum::<u64>();
let calculated_block_weight = txs
.iter()
.map(|RpcTxData { tx, .. }| tx.weight())
.sum::<usize>();
let block_number = u64::try_from(block.number().unwrap()).unwrap();
assert!(!block.miner_transaction.prefix().outputs.is_empty(), "{p}");
assert_ne!(calculated_block_reward, 0, "{p}");
assert_ne!(block.miner_transaction.weight(), 0, "{p}");
assert_eq!(block_blob, block.serialize(), "{p}"); assert_eq!(block_blob, block.serialize(), "{p}");
assert_eq!(block_weight, calculated_block_weight, "{p}");
assert_eq!(hash, block.hash(), "{p}");
assert_eq!(height, block_number, "{p}");
assert_eq!(major_version, block.header.hardfork_version, "{p}");
assert_eq!(minor_version, block.header.hardfork_signal, "{p}");
assert_eq!(miner_tx_hash, block.miner_transaction.hash(), "{p}");
assert_eq!(nonce, block.header.nonce, "{p}");
assert_eq!(num_txes, block.transactions.len(), "{p}");
assert_eq!(prev_hash, block.header.previous, "{p}");
assert_eq!(reward, calculated_block_reward, "{p}");
assert_eq!(timestamp, block.header.timestamp, "{p}");
}
assert!( fn verify_transactions(txs: Vec<RpcTxData>, p: &str) {
!block.miner_transaction.prefix().outputs.is_empty(), Self::verify_all_transactions_are_unique(&txs, p);
"miner_tx has no outputs\n{p}"
);
assert_ne!(calculated_block_reward, 0, "block reward is 0\n{p}"); for RpcTxData {
tx,
tx_blob,
tx_hash,
} in txs
{
assert_eq!(tx_hash, tx.hash(), "{p}, tx: {tx:#?}");
assert_ne!(tx.weight(), 0, "{p}, tx: {tx:#?}");
assert!(!tx.prefix().inputs.is_empty(), "{p}, tx: {tx:#?}");
assert_eq!(tx_blob, tx.serialize(), "{p}, tx: {tx:#?}");
assert!(matches!(tx.version(), 1 | 2), "{p}, tx: {tx:#?}");
}
} }
#[expect(clippy::significant_drop_tightening)] #[expect(clippy::significant_drop_tightening)]
@ -159,61 +184,6 @@ impl Verifier {
} }
} }
fn verify_transaction_properties(txs: Vec<RpcTxData>, p: &str) {
// Test transaction properties.
for RpcTxData {
tx,
tx_blob,
tx_hash,
} in txs
{
assert_eq!(tx_hash, tx.hash(), "{p}, tx: {tx:#?}");
assert_ne!(tx.weight(), 0, "{p}, tx: {tx:#?}");
assert!(!tx.prefix().inputs.is_empty(), "{p}, tx: {tx:#?}");
assert_eq!(tx_blob, tx.serialize(), "{p}, tx: {tx:#?}");
assert!(matches!(tx.version(), 1 | 2), "{p}, tx: {tx:#?}");
}
}
fn verify_block_fields(
calculated_block_weight: usize,
calculated_block_reward: u64,
block: &Block,
p: &str,
BlockHeader {
block_weight,
hash,
pow_hash: _,
height,
major_version,
minor_version,
miner_tx_hash,
nonce,
num_txes,
prev_hash,
reward,
timestamp,
}: BlockHeader,
) {
// Test block fields are correct.
assert_eq!(block_weight, calculated_block_weight, "{p}");
assert_ne!(block.miner_transaction.weight(), 0, "{p}");
assert_eq!(hash, block.hash(), "{p}");
assert_eq!(
height,
u64::try_from(block.number().unwrap()).unwrap(),
"{p}"
);
assert_eq!(major_version, block.header.hardfork_version, "{p}");
assert_eq!(minor_version, block.header.hardfork_signal, "{p}");
assert_eq!(miner_tx_hash, block.miner_transaction.hash(), "{p}");
assert_eq!(nonce, block.header.nonce, "{p}");
assert_eq!(num_txes, block.transactions.len(), "{p}");
assert_eq!(prev_hash, block.header.previous, "{p}");
assert_eq!(reward, calculated_block_reward, "{p}");
assert_eq!(timestamp, block.header.timestamp, "{p}");
}
fn verify_pow( fn verify_pow(
&mut self, &mut self,
height: u64, height: u64,
@ -222,6 +192,10 @@ impl Verifier {
calculated_pow_data: &[u8], calculated_pow_data: &[u8],
p: &str, p: &str,
) -> &'static str { ) -> &'static str {
if matches!(height, 1546000 | 1685555 | 1788000 | 1978433) {
self.start_of_new_pow = Instant::now();
}
let (algo, calculated_pow_hash) = if height < RANDOMX_START_HEIGHT { let (algo, calculated_pow_hash) = if height < RANDOMX_START_HEIGHT {
CryptoNightHash::hash(calculated_pow_data, height) CryptoNightHash::hash(calculated_pow_data, height)
} else { } else {
@ -301,7 +275,7 @@ impl Verifier {
let relative_count = find_count_relative_to_pow_activation(height); let relative_count = find_count_relative_to_pow_activation(height);
let block_buffer = self.rx.len(); let block_buffer = self.rx.len();
let elapsed = self.now.elapsed().as_secs_f64(); let elapsed = self.start_of_new_pow.elapsed().as_secs_f64();
let secs_per_hash = elapsed / relative_count as f64; let secs_per_hash = elapsed / relative_count as f64;
let verify_bps = relative_count as f64 / elapsed; let verify_bps = relative_count as f64 / elapsed;
let remaining_secs = (top_height as f64 - relative_count as f64) * secs_per_hash; let remaining_secs = (top_height as f64 - relative_count as f64) * secs_per_hash;