diff --git a/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs b/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs index 85bc66b66..57de18b42 100644 --- a/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs +++ b/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs @@ -26,15 +26,15 @@ use bincode::{Decode, Encode}; use hashes::Hash; -use crate::blockdata::transaction::special_transaction::SpecialTransactionBasePayloadEncodable; use crate::blockdata::transaction::special_transaction::asset_unlock::request_info::AssetUnlockRequestInfo; use crate::blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::AssetUnlockBasePayload; +use crate::blockdata::transaction::special_transaction::SpecialTransactionBasePayloadEncodable; use crate::bls_sig_utils::BLSSignature; -use crate::consensus::{Decodable, Encodable, encode}; +use crate::consensus::{encode, Decodable, Encodable}; use crate::hash_types::SpecialTransactionPayloadHash; -use crate::transaction::special_transaction::TransactionPayload; use crate::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::AssetUnlockBaseTransactionInfo; -use crate::{Transaction, TxIn, consensus, io}; +use crate::transaction::special_transaction::TransactionPayload; +use crate::{consensus, io, Transaction, TxIn}; // Asset unlock tx size is constant since it has zero inputs and single output only pub const ASSET_UNLOCK_TX_SIZE: usize = 190; @@ -64,7 +64,9 @@ pub struct AssetUnlockPayload { impl AssetUnlockPayload { /// The size of the payload in bytes. - pub fn size(&self) -> usize { self.base.size() + self.request_info.size() + 96 } + pub fn size(&self) -> usize { + self.base.size() + self.request_info.size() + 96 + } } impl SpecialTransactionBasePayloadEncodable for AssetUnlockPayload { @@ -129,7 +131,11 @@ impl Decodable for AssetUnlockPayload { let base = AssetUnlockBasePayload::consensus_decode(r)?; let request_info = AssetUnlockRequestInfo::consensus_decode(r)?; let quorum_sig = BLSSignature::consensus_decode(r)?; - Ok(AssetUnlockPayload { base, request_info, quorum_sig }) + Ok(AssetUnlockPayload { + base, + request_info, + quorum_sig, + }) } } @@ -139,25 +145,29 @@ mod tests { use hashes::Hash; use hex::FromHex; - use internals::hex::Case; use internals::hex::display::DisplayHex; + use internals::hex::Case; use crate::bls_sig_utils::BLSSignature; use crate::consensus::Encodable; use crate::hash_types::QuorumHash; - use crate::transaction::special_transaction::TransactionPayload; use crate::transaction::special_transaction::asset_unlock::qualified_asset_unlock::{ - ASSET_UNLOCK_TX_SIZE, AssetUnlockPayload, build_asset_unlock_tx, + build_asset_unlock_tx, AssetUnlockPayload, ASSET_UNLOCK_TX_SIZE, }; use crate::transaction::special_transaction::asset_unlock::request_info::AssetUnlockRequestInfo; use crate::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::AssetUnlockBasePayload; - use crate::{ScriptBuf, Transaction, TxOut, consensus}; + use crate::transaction::special_transaction::TransactionPayload; + use crate::{consensus, ScriptBuf, Transaction, TxOut}; #[test] fn size() { let want = 145; let payload = AssetUnlockPayload { - base: AssetUnlockBasePayload { version: 0, index: 0, fee: 0 }, + base: AssetUnlockBasePayload { + version: 0, + index: 0, + fee: 0, + }, request_info: AssetUnlockRequestInfo { request_height: 0, quorum_hash: QuorumHash::all_zeros(), @@ -185,7 +195,6 @@ mod tests { "4acfa5c6d92071d206da5b767039d42f24e7ab1a694a5b8014cddc088311e448" ) .unwrap() - .reverse() ); assert_eq!(payload.quorum_sig, BLSSignature::from_str("aee468c03feec7caada0599457136ef0dfe9365657a42ef81bb4aa53af383d05d90552b2cd23480cae24036b953ba8480d2f98291271a338e4235265dea94feacb54d1fd96083151001eff4156e7475e998154a8e6082575e2ee461b394d24f7").unwrap()); } @@ -200,7 +209,7 @@ mod tests { }, request_info: AssetUnlockRequestInfo { request_height: 1317, - quorum_hash: QuorumHash::from_str("4acfa5c6d92071d206da5b767039d42f24e7ab1a694a5b8014cddc088311e448").unwrap().reverse(), + quorum_hash: QuorumHash::from_str("4acfa5c6d92071d206da5b767039d42f24e7ab1a694a5b8014cddc088311e448").unwrap(), }, quorum_sig: BLSSignature::from_str("aee468c03feec7caada0599457136ef0dfe9365657a42ef81bb4aa53af383d05d90552b2cd23480cae24036b953ba8480d2f98291271a338e4235265dea94feacb54d1fd96083151001eff4156e7475e998154a8e6082575e2ee461b394d24f7").unwrap() }; @@ -216,11 +225,11 @@ mod tests { let tx_bytes = Vec::from_hex("010009000001c8000000000000001976a914c35b782432294088e354bc28aa56d95736cb630288ac0000000001000000000000000070f915129f05000053c006055af6d0ae9aa9627df8615a71c312421a28c4712c8add83c8e1bfdadd").unwrap(); let tx_asset_unlock = build_asset_unlock_tx(&tx_bytes).unwrap(); let bytes_tx_asset_unlock = consensus::serialize(&tx_asset_unlock); - println!("tx_asset_unlock: {:?}", bytes_tx_asset_unlock); + // println!("tx_asset_unlock: {:?}", bytes_tx_asset_unlock); let hex_tx_asset_unlock = bytes_tx_asset_unlock.to_hex_string(Case::Lower); - println!("hex_tx_asset_unlock: {:?}", hex_tx_asset_unlock); - println!("OK"); + // println!("hex_tx_asset_unlock: {:?}", hex_tx_asset_unlock); + // println!("OK"); } #[test] diff --git a/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs b/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs index 419aff083..7f6a2853f 100644 --- a/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs +++ b/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs @@ -17,20 +17,19 @@ //! It is defined in DIP6 [dip-0006.md](https://github.com/dashpay/dips/blob/master/dip-0006.md). //! -#[cfg(feature = "bincode")] -use bincode::{Decode, Encode}; - use crate::bls_sig_utils::{BLSPublicKey, BLSSignature}; use crate::consensus::encode::{ compact_size_len, fixed_bitset_len, read_compact_size, read_fixed_bitset, write_compact_size, write_fixed_bitset, }; -use crate::consensus::{Decodable, Encodable, encode}; +use crate::consensus::{encode, Decodable, Encodable}; use crate::hash_types::{QuorumHash, QuorumVVecHash}; use crate::io; use crate::prelude::*; use crate::sml::llmq_type::LLMQType; use crate::sml::quorum_validation_error::QuorumValidationError; +#[cfg(feature = "bincode")] +use bincode::{Decode, Encode}; /// A Quorum Finalization Commitment. It is described in the finalization section of DIP6: /// [dip-0006.md#6-finalization-phase](https://github.com/dashpay/dips/blob/master/dip-0006.md#6-finalization-phase) @@ -66,6 +65,7 @@ impl QuorumEntry { size } + /// Validates the structure of the quorum entry and returns an error if it's not valid. pub fn validate_structure(&self) -> Result<(), QuorumValidationError> { let quorum_threshold = self.llmq_type.threshold() as u64; @@ -146,8 +146,11 @@ impl Decodable for QuorumEntry { let version = u16::consensus_decode(r)?; let llmq_type = LLMQType::consensus_decode(r)?; let quorum_hash = QuorumHash::consensus_decode(r)?; - let quorum_index = - if version == 2 || version == 4 { Some(i16::consensus_decode(r)?) } else { None }; + let quorum_index = if version == 2 || version == 4 { + Some(i16::consensus_decode(r)?) + } else { + None + }; let signers_count = read_compact_size(r)?; let signers = read_fixed_bitset(r, signers_count as usize)?; let valid_members_count = read_compact_size(r)?; @@ -188,7 +191,9 @@ pub struct QuorumCommitmentPayload { impl QuorumCommitmentPayload { /// The size of the payload in bytes. - pub fn size(&self) -> usize { 2 + 4 + self.finalization_commitment.size() } + pub fn size(&self) -> usize { + 2 + 4 + self.finalization_commitment.size() + } } impl Encodable for QuorumCommitmentPayload { @@ -206,7 +211,11 @@ impl Decodable for QuorumCommitmentPayload { let version = u16::consensus_decode(r)?; let height = u32::consensus_decode(r)?; let finalization_commitment = QuorumEntry::consensus_decode(r)?; - Ok(QuorumCommitmentPayload { version, height, finalization_commitment }) + Ok(QuorumCommitmentPayload { + version, + height, + finalization_commitment, + }) } } @@ -215,7 +224,7 @@ mod tests { use hashes::Hash; use crate::bls_sig_utils::{BLSPublicKey, BLSSignature}; - use crate::consensus::{Encodable, deserialize, serialize}; + use crate::consensus::{deserialize, serialize, Encodable}; use crate::hash_types::{QuorumHash, QuorumVVecHash}; use crate::network::message::{NetworkMessage, RawNetworkMessage}; use crate::sml::llmq_type::LLMQType; diff --git a/dash/src/hash_types.rs b/dash/src/hash_types.rs index 06f77743e..e9da40d39 100644 --- a/dash/src/hash_types.rs +++ b/dash/src/hash_types.rs @@ -73,7 +73,7 @@ mod newtypes { #[cfg(feature = "core-block-hash-use-x11")] use hashes::hash_x11; use hashes::hex::Error; - use hashes::{Hash, hash_newtype, hash_newtype_no_ord, hash160, sha256, sha256d}; + use hashes::{hash160, hash_newtype, hash_newtype_no_ord, sha256, sha256d, Hash}; use crate::alloc::string::ToString; use crate::prelude::String; @@ -83,13 +83,28 @@ mod newtypes { hash_newtype! { /// A dash block hash. pub struct BlockHash(hash_x11::Hash); + /// A hash used to identify a quorum + #[hash_newtype(forward)] + pub struct QuorumHash(hash_x11::Hash); } + + #[cfg(feature = "core-block-hash-use-x11")] + /// A raw hash that is compatible with quorum and block hash. + pub type BlockCompatibleRawHash = hash_x11::Hash; + #[cfg(not(feature = "core-block-hash-use-x11"))] hash_newtype! { /// A dash block hash. pub struct BlockHash(sha256d::Hash); + /// A hash used to identify a quorum + #[hash_newtype(forward)] + pub struct QuorumHash(sha256d::Hash) } + #[cfg(not(feature = "core-block-hash-use-x11"))] + /// A raw hash that is compatible with quorum and block hash. + pub type BlockCompatibleRawHash = sha256d::Hash; + hash_newtype! { /// A dash transaction hash/transaction ID. pub struct Txid(sha256d::Hash); @@ -168,12 +183,11 @@ mod newtypes { } impl PartialOrd for ScoreHash { - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } - /// A hash used to identify a quorum - pub type QuorumHash = BlockHash; - /// A hash used to identity a cycle pub type CycleHash = BlockHash; @@ -193,6 +207,7 @@ mod newtypes { impl_hashencode!(SpecialTransactionPayloadHash); impl_hashencode!(InputsHash); + impl_hashencode!(QuorumHash); impl_hashencode!(QuorumVVecHash); impl_hashencode!(QuorumSigningRequestId); impl_hashencode!(PubkeyHash); @@ -211,10 +226,14 @@ mod newtypes { impl Txid { /// Create a Txid from a string - pub fn from_hex(s: &str) -> Result { Ok(Self(sha256d::Hash::from_str(s)?)) } + pub fn from_hex(s: &str) -> Result { + Ok(Self(sha256d::Hash::from_str(s)?)) + } /// Convert a Txid to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } } impl ProTxHash { @@ -224,7 +243,9 @@ mod newtypes { } /// Convert a ProTxHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } } impl ScoreHash { @@ -234,7 +255,9 @@ mod newtypes { } /// Convert a ScoreHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } /// Creates a score based on the optional confirmed hash and the quorum modifier. /// @@ -266,7 +289,9 @@ mod newtypes { } /// Convert a ScoreHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } /// Creates an ordering hash based on the quorum and request id. /// @@ -285,7 +310,9 @@ mod newtypes { } impl Default for ConfirmedHash { - fn default() -> Self { ConfirmedHash::from_byte_array([0; 32]) } + fn default() -> Self { + ConfirmedHash::from_byte_array([0; 32]) + } } impl ConfirmedHash { @@ -295,7 +322,9 @@ mod newtypes { } /// Convert a ConfirmedHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } } impl ConfirmedHashHashedWithProRegTx { @@ -305,7 +334,9 @@ mod newtypes { } /// Convert a ConfirmedHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } /// Hashes the members pub fn hash_members(pro_tx_hash: &ProTxHash, confirmed_hash: &ConfirmedHash) -> Self { @@ -329,7 +360,9 @@ mod newtypes { } /// Convert a ConfirmedHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } } impl InputsHash { @@ -339,12 +372,16 @@ mod newtypes { } /// Convert an InputsHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } } impl SpecialTransactionPayloadHash { /// Create a SpecialTransactionPayloadHash from a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } } impl PubkeyHash { @@ -354,6 +391,8 @@ mod newtypes { } /// Convert a PubkeyHash to a string - pub fn to_hex(&self) -> String { self.0.to_string() } + pub fn to_hex(&self) -> String { + self.0.to_string() + } } } diff --git a/dash/src/sml/masternode_list_engine/message_request_verification.rs b/dash/src/sml/masternode_list_engine/message_request_verification.rs index 2f932522a..99bb4e006 100644 --- a/dash/src/sml/masternode_list_engine/message_request_verification.rs +++ b/dash/src/sml/masternode_list_engine/message_request_verification.rs @@ -18,7 +18,7 @@ impl MasternodeListEngine { // Get the list of quorums associated with this cycle hash let quorums = self .rotated_quorums_per_cycle - .get(&cycle_hash) + .get(cycle_hash.as_raw_hash()) .ok_or(MessageVerificationError::CycleHashNotPresent(cycle_hash))?; // Ensure that at least one quorum exists for this cycle @@ -94,8 +94,8 @@ impl MasternodeListEngine { let quorum_count = self.network.isd_llmq_type().active_quorum_count(); let n = quorum_count.ilog2(); let quorum_index_mask = (1 << n) - 1; // Extracts the last log2(quorum_count) bits - // Extract the last `n` bits from the selection hash - // Only God and maybe Odysseus knows why (64 - n - 1) + // Extract the last `n` bits from the selection hash + // Only God and maybe Odysseus knows why (64 - n - 1) let quorum_index = quorum_index_mask & (selection_hash_64 >> (64 - n - 1)) as usize; // Retrieve the selected quorum @@ -276,7 +276,7 @@ impl MasternodeListEngine { // Attempt verification using the "before" masternode list let initial_error = if let Some(before) = before { let Err(e) = - self.verify_chain_lock_with_masternode_list(chain_lock, &before, &request_id) + self.verify_chain_lock_with_masternode_list(chain_lock, before, &request_id) else { return Ok(()); }; @@ -297,15 +297,9 @@ impl MasternodeListEngine { true }; if do_check { - return self.verify_chain_lock_with_masternode_list( - chain_lock, - &after, - &request_id, - ); - } else { - if let Some(initial_error) = initial_error { - return Err(initial_error); - } + return self.verify_chain_lock_with_masternode_list(chain_lock, after, &request_id); + } else if let Some(initial_error) = initial_error { + return Err(initial_error); } } @@ -349,8 +343,8 @@ impl MasternodeListEngine { mod tests { use crate::bls_sig_utils::BLSSignature; use crate::consensus::deserialize; - use crate::hashes::Hash; use crate::hashes::hex::FromHex; + use crate::hashes::Hash; use crate::sml::llmq_type::LLMQType; use crate::sml::masternode_list_engine::MasternodeListEngine; use crate::{BlockHash, ChainLock, InstantLock, QuorumHash}; diff --git a/dash/src/sml/masternode_list_engine/mod.rs b/dash/src/sml/masternode_list_engine/mod.rs index b1996ba9e..4e9509d05 100644 --- a/dash/src/sml/masternode_list_engine/mod.rs +++ b/dash/src/sml/masternode_list_engine/mod.rs @@ -6,13 +6,9 @@ mod rotated_quorum_construction; #[cfg(feature = "quorum_validation")] mod validation; +use crate::hash_types::BlockCompatibleRawHash; use std::collections::{BTreeMap, BTreeSet}; -#[cfg(feature = "bincode")] -use bincode::{Decode, Encode}; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; - use crate::bls_sig_utils::{BLSPublicKey, BLSSignature}; use crate::network::message_qrinfo::{QRInfo, QuorumSnapshot}; use crate::network::message_sml::MnListDiff; @@ -20,12 +16,16 @@ use crate::prelude::CoreBlockHeight; use crate::sml::error::SmlError; use crate::sml::llmq_entry_verification::LLMQEntryVerificationStatus; use crate::sml::llmq_type::LLMQType; -use crate::sml::masternode_list::MasternodeList; use crate::sml::masternode_list::from_diff::TryIntoWithBlockHashLookup; +use crate::sml::masternode_list::MasternodeList; use crate::sml::quorum_entry::qualified_quorum_entry::QualifiedQuorumEntry; use crate::sml::quorum_validation_error::{ClientDataRetrievalError, QuorumValidationError}; use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; use crate::{BlockHash, Network, QuorumHash}; +#[cfg(feature = "bincode")] +use bincode::{Decode, Encode}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; #[derive(Clone, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -33,11 +33,11 @@ use crate::{BlockHash, Network, QuorumHash}; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] pub struct MasternodeListEngine { pub block_hashes: BTreeMap, - pub block_heights: BTreeMap, + pub block_heights: BTreeMap, pub masternode_lists: BTreeMap, pub known_chain_locks: BTreeMap, pub known_snapshots: BTreeMap, - pub rotated_quorums_per_cycle: BTreeMap>, + pub rotated_quorums_per_cycle: BTreeMap>, pub quorum_statuses: BTreeMap< LLMQType, BTreeMap< @@ -64,7 +64,12 @@ impl Default for MasternodeListEngine { } impl MasternodeListEngine { - pub fn default_for_network(network: Network) -> Self { Self { network, ..Default::default() } } + pub fn default_for_network(network: Network) -> Self { + Self { + network, + ..Default::default() + } + } pub fn initialize_with_diff_to_height( masternode_list_diff: MnListDiff, block_height: CoreBlockHeight, @@ -76,7 +81,11 @@ impl MasternodeListEngine { .try_into_with_block_hash_lookup(|_block_hash| Some(block_height), network)?; Ok(Self { block_hashes: [(0, base_block_hash), (block_height, block_hash)].into(), - block_heights: [(base_block_hash, 0), (block_hash, block_height)].into(), + block_heights: [ + (base_block_hash.to_raw_hash(), 0), + (block_hash.to_raw_hash(), block_height), + ] + .into(), masternode_lists: [(block_height, masternode_list)].into(), known_chain_locks: Default::default(), known_snapshots: Default::default(), @@ -110,7 +119,9 @@ impl MasternodeListEngine { list.non_rotating_quorum_hashes(exclude_quorum_types) .into_iter() .filter(|quorum_hash| { - let Some(block_height) = self.block_heights.get(quorum_hash) else { + let Some(block_height) = + self.block_heights.get(quorum_hash.as_raw_hash()) + else { return true; }; !self.masternode_lists.contains_key(block_height) @@ -136,7 +147,9 @@ impl MasternodeListEngine { list.non_rotating_quorum_hashes(exclude_quorum_types) .into_iter() .filter(|quorum_hash| { - let Some(block_height) = self.block_heights.get(quorum_hash) else { + let Some(block_height) = + self.block_heights.get(quorum_hash.as_raw_hash()) + else { return true; }; !self.masternode_lists.contains_key(block_height) @@ -162,12 +175,18 @@ impl MasternodeListEngine { &self, block_hash: &BlockHash, ) -> Option<&MasternodeList> { - self.block_heights.get(block_hash).and_then(|height| self.masternode_lists.get(height)) + self.block_heights + .get(block_hash.as_raw_hash()) + .and_then(|height| self.masternode_lists.get(height)) } - pub fn feed_block_height(&mut self, height: CoreBlockHeight, block_hash: BlockHash) { - self.block_heights.insert(block_hash, height); - self.block_hashes.insert(height, block_hash); + pub fn feed_block_height( + &mut self, + height: CoreBlockHeight, + block_raw_hash: BlockCompatibleRawHash, + ) { + self.block_heights.insert(block_raw_hash, height); + self.block_hashes.insert(height, block_raw_hash.into()); } fn request_qr_info_block_heights( @@ -176,7 +195,7 @@ impl MasternodeListEngine { fetch_block_height: &FH, ) -> Result<(), ClientDataRetrievalError> where - FH: Fn(&BlockHash) -> Result, + FH: Fn(&BlockCompatibleRawHash) -> Result, { let mn_list_diffs = [ &qr_info.mn_list_diff_tip, @@ -233,11 +252,11 @@ impl MasternodeListEngine { fetch_block_height: &FH, ) -> Result<(), ClientDataRetrievalError> where - FH: Fn(&BlockHash) -> Result, + FH: Fn(&BlockCompatibleRawHash) -> Result, { - if !self.block_heights.contains_key(&quorum_entry.quorum_hash) { - let height = fetch_block_height(&quorum_entry.quorum_hash)?; - self.feed_block_height(height, quorum_entry.quorum_hash); + if !self.block_heights.contains_key(quorum_entry.quorum_hash.as_raw_hash()) { + let height = fetch_block_height(quorum_entry.quorum_hash.as_raw_hash())?; + self.feed_block_height(height, quorum_entry.quorum_hash.to_raw_hash()); } Ok(()) } @@ -249,18 +268,18 @@ impl MasternodeListEngine { fetch_block_height: &FH, ) -> Result<(), ClientDataRetrievalError> where - FH: Fn(&BlockHash) -> Result, + FH: Fn(&BlockCompatibleRawHash) -> Result, { - if !self.block_heights.contains_key(&mn_list_diff.base_block_hash) { + if !self.block_heights.contains_key(mn_list_diff.base_block_hash.as_raw_hash()) { // Feed base block hash height - let base_height = fetch_block_height(&mn_list_diff.base_block_hash)?; - self.feed_block_height(base_height, mn_list_diff.base_block_hash); + let base_height = fetch_block_height(mn_list_diff.base_block_hash.as_raw_hash())?; + self.feed_block_height(base_height, *mn_list_diff.base_block_hash.as_raw_hash()); } - if !self.block_heights.contains_key(&mn_list_diff.block_hash) { + if !self.block_heights.contains_key(mn_list_diff.block_hash.as_raw_hash()) { // Feed block hash height - let block_height = fetch_block_height(&mn_list_diff.block_hash)?; - self.feed_block_height(block_height, mn_list_diff.block_hash); + let block_height = fetch_block_height(mn_list_diff.block_hash.as_raw_hash())?; + self.feed_block_height(block_height, *mn_list_diff.block_hash.as_raw_hash()); } Ok(()) } @@ -295,7 +314,7 @@ impl MasternodeListEngine { fetch_chain_lock_sigs: Option, ) -> Result<(), QuorumValidationError> where - FH: Fn(&BlockHash) -> Result, + FH: Fn(&BlockCompatibleRawHash) -> Result, FS: Fn(&BlockHash) -> Result, ClientDataRetrievalError>, { // Fetch and process block heights using the provided callback @@ -334,11 +353,11 @@ impl MasternodeListEngine { let h_height = self .block_heights - .get(&mn_list_diff_h.block_hash) + .get(mn_list_diff_h.block_hash.as_raw_hash()) .copied() .ok_or(QuorumValidationError::RequiredBlockNotPresent(mn_list_diff_h.block_hash))?; let tip_height = - self.block_heights.get(&mn_list_diff_tip.block_hash).copied().ok_or( + self.block_heights.get(mn_list_diff_tip.block_hash.as_raw_hash()).copied().ok_or( QuorumValidationError::RequiredBlockNotPresent(mn_list_diff_tip.block_hash), )?; let rotation_quorum_type = last_commitment_per_index @@ -387,7 +406,7 @@ impl MasternodeListEngine { let mut qualified_rotated_quorums_per_cycle = qualified_last_commitment_per_index.first().map(|quorum_entry| { self.rotated_quorums_per_cycle - .entry(quorum_entry.quorum_entry.quorum_hash) + .entry(*quorum_entry.quorum_entry.quorum_hash.as_raw_hash()) .or_default() }); @@ -516,16 +535,14 @@ impl MasternodeListEngine { } } } - } else { - if let Some(qualified_rotated_quorums_per_cycle) = - qualified_last_commitment_per_index.first().map(|quorum_entry| { - self.rotated_quorums_per_cycle - .entry(quorum_entry.quorum_entry.quorum_hash) - .or_default() - }) - { - *qualified_rotated_quorums_per_cycle = qualified_last_commitment_per_index; - } + } else if let Some(qualified_rotated_quorums_per_cycle) = + qualified_last_commitment_per_index.first().map(|quorum_entry| { + self.rotated_quorums_per_cycle + .entry(quorum_entry.quorum_entry.quorum_hash.to_raw_hash()) + .or_default() + }) + { + *qualified_rotated_quorums_per_cycle = qualified_last_commitment_per_index; } #[cfg(not(feature = "quorum_validation"))] @@ -556,19 +573,22 @@ impl MasternodeListEngine { let block_hash = masternode_list_diff.block_hash; let masternode_list = masternode_list_diff.try_into_with_block_hash_lookup( - |block_hash| diff_end_height.or(self.block_heights.get(block_hash).copied()), + |block_hash| { + diff_end_height + .or(self.block_heights.get(block_hash.as_raw_hash()).copied()) + }, self.network, )?; let diff_end_height = match diff_end_height { None => self .block_heights - .get(&block_hash) + .get(block_hash.as_raw_hash()) .ok_or(SmlError::BlockHashLookupFailed(block_hash)) .cloned()?, Some(diff_end_height) => { self.block_hashes.insert(diff_end_height, block_hash); - self.block_heights.insert(block_hash, diff_end_height); + self.block_heights.insert(block_hash.to_raw_hash(), diff_end_height); diff_end_height } }; @@ -577,7 +597,8 @@ impl MasternodeListEngine { } } - let Some(base_height) = self.block_heights.get(&masternode_list_diff.base_block_hash) + let Some(base_height) = + self.block_heights.get(masternode_list_diff.base_block_hash.as_raw_hash()) else { return Err(SmlError::MissingStartMasternodeList(masternode_list_diff.base_block_hash)); }; @@ -590,7 +611,7 @@ impl MasternodeListEngine { let diff_end_height = match diff_end_height { None => self .block_heights - .get(&block_hash) + .get(block_hash.as_raw_hash()) .ok_or(SmlError::BlockHashLookupFailed(block_hash)) .cloned()?, Some(diff_end_height) => diff_end_height, @@ -690,7 +711,7 @@ impl MasternodeListEngine { } self.block_hashes.insert(diff_end_height, block_hash); - self.block_heights.insert(block_hash, diff_end_height); + self.block_heights.insert(block_hash.to_raw_hash(), diff_end_height); Ok(()) } @@ -740,7 +761,9 @@ impl MasternodeListEngine { .find(|quorum_entry| quorum_entry.quorum_entry.quorum_index == Some(0)) .map(|quorum_entry| quorum_entry.quorum_entry.quorum_hash) { - if let Some(cycle_quorums) = self.rotated_quorums_per_cycle.get(&cycle_hash) { + if let Some(cycle_quorums) = + self.rotated_quorums_per_cycle.get(cycle_hash.as_raw_hash()) + { // Only update rotating quorum statuses based on last commitment entries for quorum in cycle_quorums { if let Some(quorum_entry) = @@ -815,7 +838,7 @@ impl MasternodeListEngine { mod tests { use crate::sml::llmq_entry_verification::LLMQEntryVerificationStatus; use crate::sml::llmq_type::LLMQType; - use crate::sml::llmq_type::LLMQType::{Llmqtype50_60, Llmqtype400_60, Llmqtype400_85}; + use crate::sml::llmq_type::LLMQType::{Llmqtype400_60, Llmqtype400_85, Llmqtype50_60}; use crate::sml::masternode_list_engine::MasternodeListEngine; #[test] @@ -853,7 +876,7 @@ mod tests { for (quorum_hash, quorum) in quorum_entries.iter() { let (_, known_block_height) = mn_list_engine .masternode_list_and_height_for_block_hash_8_blocks_ago( - &quorum.quorum_entry.quorum_hash, + quorum.quorum_entry.quorum_hash.as_raw_hash(), ) .expect("expected to find validating masternode"); assert_eq!( diff --git a/dash/src/sml/masternode_list_engine/non_rotated_quorum_construction.rs b/dash/src/sml/masternode_list_engine/non_rotated_quorum_construction.rs index c54b1e7b0..befb50eae 100644 --- a/dash/src/sml/masternode_list_engine/non_rotated_quorum_construction.rs +++ b/dash/src/sml/masternode_list_engine/non_rotated_quorum_construction.rs @@ -1,4 +1,4 @@ -use crate::BlockHash; +use crate::hash_types::BlockCompatibleRawHash; use crate::prelude::CoreBlockHeight; use crate::sml::masternode_list::MasternodeList; use crate::sml::masternode_list_engine::MasternodeListEngine; @@ -6,11 +6,12 @@ use crate::sml::masternode_list_entry::qualified_masternode_list_entry::Qualifie use crate::sml::quorum_entry::qualified_quorum_entry::QualifiedQuorumEntry; use crate::sml::quorum_entry::quorum_modifier_type::LLMQModifierType; use crate::sml::quorum_validation_error::QuorumValidationError; +use crate::BlockHash; impl MasternodeListEngine { pub(crate) fn masternode_list_and_height_for_block_hash_8_blocks_ago( &self, - block_hash: &BlockHash, + block_hash: &BlockCompatibleRawHash, ) -> Result<(&MasternodeList, CoreBlockHeight), QuorumValidationError> { if let Some(height) = self.block_heights.get(block_hash) { if let Some(masternode_list) = self.masternode_lists.get(&(height.saturating_sub(8))) { @@ -21,7 +22,9 @@ impl MasternodeListEngine { )) } } else { - Err(QuorumValidationError::RequiredBlockNotPresent(*block_hash)) + Err(QuorumValidationError::RequiredBlockNotPresent(BlockHash::from_raw_hash( + *block_hash, + ))) } } @@ -31,7 +34,7 @@ impl MasternodeListEngine { ) -> Result, QuorumValidationError> { let (masternode_list, known_block_height) = self .masternode_list_and_height_for_block_hash_8_blocks_ago( - &quorum.quorum_entry.quorum_hash, + quorum.quorum_entry.quorum_hash.as_raw_hash(), )?; let quorum_modifier_type = LLMQModifierType::new_quorum_modifier_type( quorum.quorum_entry.llmq_type, diff --git a/dash/src/sml/masternode_list_engine/rotated_quorum_construction.rs b/dash/src/sml/masternode_list_engine/rotated_quorum_construction.rs index 8a8914c5a..12f88d00a 100644 --- a/dash/src/sml/masternode_list_engine/rotated_quorum_construction.rs +++ b/dash/src/sml/masternode_list_engine/rotated_quorum_construction.rs @@ -1,17 +1,17 @@ use std::collections::{BTreeMap, BTreeSet}; -use crate::QuorumHash; use crate::hash_types::QuorumModifierHash; use crate::network::message_qrinfo::{MNSkipListMode, QRInfo}; use crate::prelude::CoreBlockHeight; -use crate::sml::llmq_type::LLMQType; use crate::sml::llmq_type::rotation::{LLMQQuarterReconstructionType, LLMQQuarterUsageType}; +use crate::sml::llmq_type::LLMQType; use crate::sml::masternode_list::MasternodeList; use crate::sml::masternode_list_engine::MasternodeListEngine; use crate::sml::masternode_list_entry::qualified_masternode_list_entry::QualifiedMasternodeListEntry; use crate::sml::quorum_entry::qualified_quorum_entry::QualifiedQuorumEntry; use crate::sml::quorum_entry::quorum_modifier_type::LLMQModifierType; use crate::sml::quorum_validation_error::QuorumValidationError; +use crate::QuorumHash; impl MasternodeListEngine { /// Determines which masternodes are responsible for signing at the given quorum index. @@ -28,10 +28,11 @@ impl MasternodeListEngine { &'a self, quorum: &'a QualifiedQuorumEntry, ) -> Result, QuorumValidationError> { - let Some(quorum_block_height) = self.block_heights.get(&quorum.quorum_entry.quorum_hash) + let Some(quorum_block_height) = + self.block_heights.get(quorum.quorum_entry.quorum_hash.as_raw_hash()) else { return Err(QuorumValidationError::RequiredBlockNotPresent( - quorum.quorum_entry.quorum_hash, + quorum.quorum_entry.quorum_hash.to_raw_hash().into(), )); }; let llmq_type = quorum.quorum_entry.llmq_type; @@ -63,10 +64,10 @@ impl MasternodeListEngine { BTreeMap::new(); for quorum in quorums { let Some(quorum_block_height) = - self.block_heights.get(&quorum.quorum_entry.quorum_hash) + self.block_heights.get(quorum.quorum_entry.quorum_hash.as_raw_hash()) else { return Err(QuorumValidationError::RequiredBlockNotPresent( - quorum.quorum_entry.quorum_hash, + quorum.quorum_entry.quorum_hash.to_raw_hash().into(), )); }; let llmq_type = quorum.quorum_entry.llmq_type; @@ -119,8 +120,12 @@ impl MasternodeListEngine { ) -> Result, QuorumValidationError> { let mut required_heights = BTreeSet::new(); for quorum in &qr_info.last_commitment_per_index { - let Some(quorum_block_height) = self.block_heights.get(&quorum.quorum_hash) else { - return Err(QuorumValidationError::RequiredBlockNotPresent(quorum.quorum_hash)); + let Some(quorum_block_height) = + self.block_heights.get(quorum.quorum_hash.as_raw_hash()) + else { + return Err(QuorumValidationError::RequiredBlockNotPresent( + quorum.quorum_hash.to_raw_hash().into(), + )); }; let llmq_params = quorum.llmq_type.params(); let quorum_index = quorum_block_height % llmq_params.dkg_params.interval; @@ -134,10 +139,11 @@ impl MasternodeListEngine { if qr_info.quorum_snapshot_and_mn_list_diff_at_h_minus_4c.is_some() { for quorum in &qr_info.mn_list_diff_h.new_quorums { if quorum.llmq_type.is_rotating_quorum_type() { - let Some(quorum_block_height) = self.block_heights.get(&quorum.quorum_hash) + let Some(quorum_block_height) = + self.block_heights.get(quorum.quorum_hash.as_raw_hash()) else { return Err(QuorumValidationError::RequiredBlockNotPresent( - quorum.quorum_hash, + quorum.quorum_hash.to_raw_hash().into(), )); }; let llmq_params = quorum.llmq_type.params(); @@ -278,7 +284,9 @@ impl MasternodeListEngine { // println!("work block height is {}", work_block_height); // println!("work block hash is {}", work_block_hash); match reconstruction_type { - LLMQQuarterReconstructionType::New { previous_quarters } => { + LLMQQuarterReconstructionType::New { + previous_quarters, + } => { let (used_masternodes, unused_masternodes, used_indexed_masternodes) = masternode_list.usage_info(previous_quarters, quorum_count); Ok(Self::apply_skip_strategy_of_type(