diff --git a/src/blockchain/header_store.rs b/src/blockchain/header_store.rs index b66bc2b2f..a14c4b1bb 100644 --- a/src/blockchain/header_store.rs +++ b/src/blockchain/header_store.rs @@ -33,7 +33,7 @@ use sled_overlay::{ use crate::{util::time::Timestamp, Error, Result}; -use super::{monero::MoneroPowData, SledDbOverlayPtr}; +use super::{monero::{extract_aux_merkle_root, MoneroPowData}, SledDbOverlayPtr}; /// Struct representing the Proof of Work used in a block. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)] @@ -152,6 +152,36 @@ impl Header { HeaderHash(hasher.finalize().into()) } + + /// Validate PowData from the header. + pub fn validate_powdata(&self) -> bool { + match &self.pow_data { + // For native DarkFi PoW, this is handled so we just return `true`. + PowData::DarkFi => true, + // For Monero PoW, we have to check a few things. + PowData::Monero(powdata) => { + if !powdata.is_coinbase_valid_merkle_root() { + return false + } + + // Verify that MoneroPowData correctly corresponds to this header. + let aux_hash = monero::Hash::from(self.template_hash().inner()); + let Ok(merkle_root) = extract_aux_merkle_root(&powdata.coinbase_tx_extra) else { + return false + }; + + let Some(merkle_root) = merkle_root else { + return false + }; + + if powdata.aux_chain_merkle_proof.calculate_root(&aux_hash) != merkle_root { + return false + } + + true + } + } + } } impl Default for Header { diff --git a/src/blockchain/monero/mod.rs b/src/blockchain/monero/mod.rs index 31fcbca3d..f71574db6 100644 --- a/src/blockchain/monero/mod.rs +++ b/src/blockchain/monero/mod.rs @@ -433,13 +433,17 @@ fn parse_extra_field_truncate_on_error(raw_extra_field: &RawExtraField) -> Extra } } + /// Extract the Monero block hash from the coinbase transaction's extra field pub fn extract_aux_merkle_root_from_block(monero: &monero::Block) -> Result> { - // When we extract the merge mining hash, we do not care if the extra - // field can be parsed without error. - let extra_field = parse_extra_field_truncate_on_error(&monero.miner_tx.prefix.extra); + extract_aux_merkle_root(&monero.miner_tx.prefix.extra) +} - // Only one merge mining tag is allowed + +/// Extract the Monero block hash from the coinbase transaction's extra field +pub fn extract_aux_merkle_root(extra_field: &RawExtraField) -> Result> { + let extra_field = parse_extra_field_truncate_on_error(extra_field); + // Only one merge mining tag is allowed let merge_mining_hashes: Vec = extra_field .0 .iter()