From 7cf7ea16934fe163c9098948569d04adff8ab384 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Tue, 9 Jan 2024 22:39:29 +0000 Subject: [PATCH] Make RX VM an option for `calculate_pow_hash` This means we don't have to init the dataset if it's not needed --- consensus/rules/src/blocks.rs | 5 +- consensus/rules/src/miner_tx.rs | 14 ++++- consensus/src/bin/scan_chain.rs | 101 ++++++++++++++++++------------- consensus/src/block.rs | 41 ++++++++++++- consensus/src/context/rx_seed.rs | 5 +- cryptonight/build.rs | 17 ++++-- 6 files changed, 129 insertions(+), 54 deletions(-) diff --git a/consensus/rules/src/blocks.rs b/consensus/rules/src/blocks.rs index ac1f1db..57dfdbe 100644 --- a/consensus/rules/src/blocks.rs +++ b/consensus/rules/src/blocks.rs @@ -67,9 +67,11 @@ pub fn randomx_seed_height(height: u64) -> u64 { /// Calculates the POW hash of this block. /// +/// `randomx_vm` must be [`Some`] after hf 12. +/// /// ref: https://monero-book.cuprate.org/consensus_rules/blocks.html#pow-function pub fn calculate_pow_hash( - randomx_vm: &R, + randomx_vm: Option<&R>, buf: &[u8], height: u64, hf: &HardFork, @@ -88,6 +90,7 @@ pub fn calculate_pow_hash( cryptonight_hash_r(buf, height) } else { randomx_vm + .expect("RandomX VM needed from hf 12") .calculate_hash(buf) .map_err(|_| BlockError::POWInvalid)? }) diff --git a/consensus/rules/src/miner_tx.rs b/consensus/rules/src/miner_tx.rs index 0b6c2d2..370bef4 100644 --- a/consensus/rules/src/miner_tx.rs +++ b/consensus/rules/src/miner_tx.rs @@ -129,10 +129,20 @@ fn check_time_lock(time_lock: &Timelock, chain_height: u64) -> Result<(), MinerT /// Sums the outputs checking for overflow. /// /// ref: https://monero-book.cuprate.org/consensus_rules/blocks/miner_tx.html#output-amounts -fn sum_outputs(outputs: &[Output], hf: &HardFork) -> Result { +/// && https://monero-book.cuprate.org/consensus_rules/blocks/miner_tx.html#zero-amount-v1-output +fn sum_outputs( + outputs: &[Output], + hf: &HardFork, + tx_version: &TxVersion, +) -> Result { let mut sum: u64 = 0; for out in outputs { let amt = out.amount.unwrap_or(0); + + if tx_version == &TxVersion::RingSignatures && amt == 0 { + return Err(MinerTxError::OutputAmountIncorrect); + } + if hf == &HardFork::V3 && !is_decomposed_amount(&amt) { return Err(MinerTxError::OutputNotDecomposed); } @@ -193,7 +203,7 @@ pub fn check_miner_tx( check_output_types(&tx.prefix.outputs, hf).map_err(|_| MinerTxError::InvalidOutputType)?; let reward = calculate_block_reward(block_weight, median_bw, already_generated_coins, hf); - let total_outs = sum_outputs(&tx.prefix.outputs, hf)?; + let total_outs = sum_outputs(&tx.prefix.outputs, hf, &tx_version)?; check_total_output_amt(total_outs, reward, total_fees, hf) } diff --git a/consensus/src/bin/scan_chain.rs b/consensus/src/bin/scan_chain.rs index 1a705a1..ed8933b 100644 --- a/consensus/src/bin/scan_chain.rs +++ b/consensus/src/bin/scan_chain.rs @@ -36,7 +36,8 @@ use monero_consensus::{blocks::randomx_seed_height, HardFork}; mod tx_pool; -const MAX_BLOCKS_IN_RANGE: u64 = 200; +const MAX_BLOCKS_IN_RANGE: u64 = 1000; +const BATCHES_IN_REQUEST: u64 = 3; const MAX_BLOCKS_HEADERS_IN_RANGE: u64 = 1000; /// Calls for a batch of blocks, returning the response and the time it took. @@ -100,19 +101,21 @@ where D::Future: Send + 'static, { let mut next_fut = tokio::spawn(call_batch( - start_height..(start_height + (MAX_BLOCKS_IN_RANGE * 4)).min(chain_height), + start_height..(start_height + (MAX_BLOCKS_IN_RANGE * BATCHES_IN_REQUEST)).min(chain_height), database.clone(), )); for next_batch_start in (start_height..chain_height) - .step_by((MAX_BLOCKS_IN_RANGE * 4) as usize) + .step_by((MAX_BLOCKS_IN_RANGE * BATCHES_IN_REQUEST) as usize) .skip(1) { // Call the next batch while we handle this batch. let current_fut = std::mem::replace( &mut next_fut, tokio::spawn(call_batch( - next_batch_start..(next_batch_start + (MAX_BLOCKS_IN_RANGE * 4)).min(chain_height), + next_batch_start + ..(next_batch_start + (MAX_BLOCKS_IN_RANGE * BATCHES_IN_REQUEST)) + .min(chain_height), database.clone(), )), ); @@ -123,7 +126,7 @@ where tracing::info!( "Got batch: {:?}, chain height: {}", - (next_batch_start - (MAX_BLOCKS_IN_RANGE * 4))..(next_batch_start), + (next_batch_start - (MAX_BLOCKS_IN_RANGE * BATCHES_IN_REQUEST))..(next_batch_start), chain_height ); @@ -223,50 +226,62 @@ where tokio::spawn(async move { while let Some(blocks) = incoming_blocks.next().await { - let unwrapped_rx_vms = randomx_vms.as_mut().unwrap(); + if blocks.last().unwrap().header.major_version >= 12 { + let unwrapped_rx_vms = randomx_vms.as_mut().unwrap(); - let blocks = rayon_spawn_async(move || { - blocks - .into_iter() - .map(move |block| PrePreparedBlockExPOW::new(block).unwrap()) - .collect::>() - }) - .await; - - let seeds_needed = blocks - .iter() - .map(|block| { - rx_seed_cache.new_block(block.block.number() as u64, &block.block_hash); - randomx_seed_height(block.block.number() as u64) + let blocks = rayon_spawn_async(move || { + blocks + .into_iter() + .map(move |block| PrePreparedBlockExPOW::new(block).unwrap()) + .collect::>() }) - .collect::>(); + .await; - unwrapped_rx_vms.retain(|seed_height, _| seeds_needed.contains(seed_height)); - - for seed_height in seeds_needed { - unwrapped_rx_vms.entry(seed_height).or_insert_with(|| { - RandomXVM::new(rx_seed_cache.get_seeds_hash(seed_height)).unwrap() - }); - } - - let arc_rx_vms = Arc::new(randomx_vms.take().unwrap()); - let cloned_arc_rx_vms = arc_rx_vms.clone(); - let blocks = rayon_spawn_async(move || { - blocks - .into_iter() - .map(move |block| { - let rx_vm = arc_rx_vms - .get(&randomx_seed_height(block.block.number() as u64)) - .unwrap(); - PrePreparedBlock::new(block, rx_vm).unwrap() + let seeds_needed = blocks + .iter() + .map(|block| { + rx_seed_cache.new_block(block.block.number() as u64, &block.block_hash); + randomx_seed_height(block.block.number() as u64) }) - .collect::>() - }) - .await; + .collect::>(); - randomx_vms = Some(Arc::into_inner(cloned_arc_rx_vms).unwrap()); + unwrapped_rx_vms.retain(|seed_height, _| seeds_needed.contains(seed_height)); - prepped_blocks_tx.send(blocks).await.unwrap(); + for seed_height in seeds_needed { + unwrapped_rx_vms.entry(seed_height).or_insert_with(|| { + RandomXVM::new(rx_seed_cache.get_seeds_hash(seed_height)).unwrap() + }); + } + + let arc_rx_vms = Arc::new(randomx_vms.take().unwrap()); + let cloned_arc_rx_vms = arc_rx_vms.clone(); + let blocks = rayon_spawn_async(move || { + blocks + .into_iter() + .map(move |block| { + let rx_vm = arc_rx_vms + .get(&randomx_seed_height(block.block.number() as u64)) + .unwrap(); + PrePreparedBlock::new_rx(block, rx_vm).unwrap() + }) + .collect::>() + }) + .await; + + randomx_vms = Some(Arc::into_inner(cloned_arc_rx_vms).unwrap()); + + prepped_blocks_tx.send(blocks).await.unwrap(); + } else { + let blocks = rayon_spawn_async(move || { + blocks + .into_iter() + .map(move |block| PrePreparedBlock::new(block).unwrap()) + .collect::>() + }) + .await; + + prepped_blocks_tx.send(blocks).await.unwrap(); + } } }); diff --git a/consensus/src/block.rs b/consensus/src/block.rs index d24fbb3..2fe770c 100644 --- a/consensus/src/block.rs +++ b/consensus/src/block.rs @@ -68,7 +68,44 @@ pub struct PrePreparedBlock { } impl PrePreparedBlock { - pub fn new( + pub fn new(block: Block) -> Result { + struct DummyRX; + + impl RandomX for DummyRX { + type Error = (); + fn calculate_hash(&self, _: &[u8]) -> Result<[u8; 32], Self::Error> { + panic!("DummyRX cant calculate hash") + } + } + + let (hf_version, hf_vote) = + HardFork::from_block_header(&block.header).map_err(BlockError::HardForkError)?; + + let Some(Input::Gen(height)) = block.miner_tx.prefix.inputs.first() else { + Err(ConsensusError::Block(BlockError::MinerTxError( + MinerTxError::InputNotOfTypeGen, + )))? + }; + + Ok(PrePreparedBlock { + block_blob: block.serialize(), + hf_vote, + hf_version, + + block_hash: block.hash(), + + pow_hash: calculate_pow_hash::( + None, + &block.serialize_hashable(), + *height, + &hf_version, + )?, + miner_tx_weight: block.miner_tx.weight(), + block, + }) + } + + pub fn new_rx( block: PrePreparedBlockExPOW, randomx_vm: &R, ) -> Result { @@ -85,7 +122,7 @@ impl PrePreparedBlock { block_hash: block.block_hash, pow_hash: calculate_pow_hash( - randomx_vm, + Some(randomx_vm), &block.block.serialize_hashable(), *height, &block.hf_version, diff --git a/consensus/src/context/rx_seed.rs b/consensus/src/context/rx_seed.rs index c9d95f9..4bead27 100644 --- a/consensus/src/context/rx_seed.rs +++ b/consensus/src/context/rx_seed.rs @@ -61,8 +61,11 @@ impl RandomXSeed { } } - self.seeds.pop_back(); self.seeds.push_front((height, *hash)); + + if self.seeds.len() > RX_SEEDS_CACHED { + self.seeds.pop_back(); + } } } } diff --git a/cryptonight/build.rs b/cryptonight/build.rs index f53daf4..6551aa8 100644 --- a/cryptonight/build.rs +++ b/cryptonight/build.rs @@ -1,10 +1,12 @@ extern crate cc; +use std::env; + use cc::Build; fn main() { - Build::new() - .include("c") + let mut cfg = Build::new(); + cfg.include("c") .file("c/aesb.c") .file("c/blake256.c") .file("c/groestl.c") @@ -20,8 +22,13 @@ fn main() { .file("c/slow-hash.c") .file("c/CryptonightR_JIT.c") .file("c/CryptonightR_template.S") - .flag("-maes") .flag("-O3") - .flag("-fexceptions") - .compile("cryptonight") + .flag("-fexceptions"); + + let target = env::var("TARGET").unwrap(); + if target.contains("x86_64") { + cfg.flag("-maes").flag("-msse2"); + } + + cfg.compile("cryptonight") }