diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 8818206ca2..a75767e192 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -751,6 +751,15 @@ mod test { block.header().block_output_mr.to_vec().to_hex(), ); } else { + let coinbases = block.block().body.get_coinbase_outputs().into_iter().cloned().collect(); + let normal_output_mr = block.block().body.calculate_header_normal_output_mr().unwrap(); + assert_eq!( + AggregateBody::calculate_header_block_output_mr(normal_output_mr, &coinbases) + .unwrap() + .to_vec() + .to_hex(), + block.header().block_output_mr.to_vec().to_hex(), + ); assert_eq!( block_output_mr_hash_from_pruned_mmr(&block_output_mmr) .unwrap() diff --git a/base_layer/core/src/transactions/aggregated_body.rs b/base_layer/core/src/transactions/aggregated_body.rs index ecdafcde2c..c6c31498b0 100644 --- a/base_layer/core/src/transactions/aggregated_body.rs +++ b/base_layer/core/src/transactions/aggregated_body.rs @@ -21,14 +21,17 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use std::{ cmp::max, + convert::TryFrom, fmt::{Display, Error, Formatter}, }; use borsh::{BorshDeserialize, BorshSerialize}; use log::*; use serde::{Deserialize, Serialize}; -use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey}; +use tari_common_types::types::{ComAndPubSignature, Commitment, FixedHash, PrivateKey}; use tari_crypto::commitment::HomomorphicCommitmentFactory; +#[cfg(feature = "base_node")] +use tari_mmr::pruned_hashset::PrunedHashSet; use tari_utilities::hex::Hex; use crate::transactions::{ @@ -45,6 +48,8 @@ use crate::transactions::{ }, weight::TransactionWeight, }; +#[cfg(feature = "base_node")] +use crate::{block_output_mr_hash_from_pruned_mmr, MrHashError, PrunedOutputMmr}; pub const LOG_TARGET: &str = "c::tx::aggregated_body"; @@ -446,6 +451,30 @@ impl AggregateBody { .iter() .any(|k| k.features.output_type == OutputType::Coinbase) } + + #[cfg(feature = "base_node")] + pub fn calculate_header_block_output_mr( + normal_output_mr: FixedHash, + coinbases: &Vec, + ) -> Result { + let mut block_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + for o in coinbases { + block_output_mmr.push(o.hash().to_vec())?; + } + block_output_mmr.push(normal_output_mr.to_vec())?; + block_output_mr_hash_from_pruned_mmr(&block_output_mmr) + } + + #[cfg(feature = "base_node")] + pub fn calculate_header_normal_output_mr(&self) -> Result { + let mut normal_output_mmr = PrunedOutputMmr::new(PrunedHashSet::default()); + for o in self.outputs() { + if !o.features.is_coinbase() { + normal_output_mmr.push(o.hash().to_vec())?; + } + } + Ok(FixedHash::try_from(normal_output_mmr.get_merkle_root()?)?) + } } impl PartialEq for AggregateBody {