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