Skip to content

Commit 3a1894b

Browse files
documentation comments
1 parent 7dc6a7c commit 3a1894b

23 files changed

+596
-154
lines changed

dash/src/sml/llmq_type/rotation.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub enum LLMQQuarterReconstructionType<'a: 'b, 'b> {
1313
Snapshot,
1414
New {
1515
previous_quarters: [&'b Vec<Vec<&'a QualifiedMasternodeListEntry>>; 3],
16-
skip_removed_masternodes: bool,
1716
}
1817
}
1918

dash/src/sml/masternode_list/apply_diff.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
11
use crate::network::message_sml::MnListDiff;
22
use crate::prelude::CoreBlockHeight;
33
use crate::sml::error::SmlError;
4-
use crate::sml::llmq_entry_verification::{LLMQEntryVerificationSkipStatus, LLMQEntryVerificationStatus};
54
use crate::sml::masternode_list::MasternodeList;
6-
use crate::sml::quorum_entry::qualified_quorum_entry::QualifiedQuorumEntry;
75

86
impl MasternodeList {
7+
/// Applies an `MnListDiff` to update the current masternode list.
8+
///
9+
/// This function processes a masternode list diff (`MnListDiff`) and applies
10+
/// the changes to the existing masternode list. It performs the following operations:
11+
/// - Ensures the base block hash matches the expected value.
12+
/// - Removes deleted masternodes from the list.
13+
/// - Adds or updates new masternodes.
14+
/// - Removes deleted quorums.
15+
/// - Adds or updates new quorums.
16+
///
17+
/// # Parameters
18+
///
19+
/// - `diff`: The `MnListDiff` containing the changes to apply.
20+
/// - `diff_end_height`: The block height at which the diff ends.
21+
///
22+
/// # Returns
23+
///
24+
/// - `Ok(MasternodeList)`: A new `MasternodeList` reflecting the applied changes.
25+
/// - `Err(SmlError)`: An error if the base block hash does not match the expected value.
26+
///
27+
/// # Errors
28+
///
29+
/// - Returns `SmlError::BaseBlockHashMismatch` if the `base_block_hash` of the `diff`
30+
/// does not match the expected block hash of the current masternode list.
931
pub fn apply_diff(
1032
&self,
1133
diff: MnListDiff,

dash/src/sml/masternode_list/is_lock_methods.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ use crate::sml::masternode_list::MasternodeList;
55
use crate::sml::quorum_entry::qualified_quorum_entry::QualifiedQuorumEntry;
66

77
impl MasternodeList {
8+
/// Retrieves a list of qualified quorum entries ordered for InstantSend locks.
9+
///
10+
/// This function fetches all quorums for the given `quorum_type`, computes an ordering
11+
/// hash based on the provided `request_id`, and sorts them in descending order.
12+
///
13+
/// # Parameters
14+
///
15+
/// - `quorum_type`: The type of quorum to retrieve.
16+
/// - `request_id`: A 32-byte identifier used to order the quorums.
17+
///
18+
/// # Returns
19+
///
20+
/// - A vector of `QualifiedQuorumEntry` instances ordered based on the computed hash.
821
pub fn ordered_quorums_for_is_lock(&self, quorum_type: LLMQType, request_id: [u8; 32]) -> Vec<QualifiedQuorumEntry> {
922
use std::cmp::Ordering;
1023
let quorums_for_is = self.quorums
@@ -30,6 +43,20 @@ impl MasternodeList {
3043
ordered_quorums.into_iter().map(|(entry, _)| entry).collect()
3144
}
3245

46+
/// Retrieves the first valid quorum entry for a given InstantSend lock request.
47+
///
48+
/// This function finds the most suitable quorum entry for a given `request_id` and `llmq_type`
49+
/// by selecting the quorum with the lowest computed ordering hash.
50+
///
51+
/// # Parameters
52+
///
53+
/// - `request_id`: A 32-byte identifier used to determine the quorum ordering.
54+
/// - `llmq_type`: The type of quorum to retrieve.
55+
///
56+
/// # Returns
57+
///
58+
/// - `Some(QualifiedQuorumEntry)`: The most suitable quorum entry.
59+
/// - `None`: If no quorum is found.
3360
pub fn lock_llmq_request_id(
3461
&self,
3562
request_id: [u8; 32],
@@ -39,6 +66,21 @@ impl MasternodeList {
3966
.cloned()
4067
}
4168

69+
/// Retrieves a reference to the best matching quorum entry for a given InstantSend lock request.
70+
///
71+
/// This function iterates through all available quorums of the given `llmq_type`, calculates
72+
/// an ordering hash for each quorum based on the `request_id`, and returns a reference to the
73+
/// quorum with the lowest ordering hash value.
74+
///
75+
/// # Parameters
76+
///
77+
/// - `request_id`: A 32-byte identifier used for quorum selection.
78+
/// - `llmq_type`: The type of quorum to search for.
79+
///
80+
/// # Returns
81+
///
82+
/// - `Some(&QualifiedQuorumEntry)`: A reference to the best-matching quorum entry.
83+
/// - `None`: If no quorum matches the criteria.
4284
pub fn quorum_entry_for_lock_request_id(
4385
&self,
4486
request_id: [u8; 32],
@@ -57,5 +99,4 @@ impl MasternodeList {
5799
});
58100
first_quorum
59101
}
60-
61102
}

dash/src/sml/masternode_list/merkle_roots.rs

Lines changed: 83 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ use crate::sml::masternode_list::MasternodeList;
44
use crate::Transaction;
55
use crate::transaction::special_transaction::TransactionPayload;
66

7+
/// Computes the Merkle root from a list of hashes.
8+
///
9+
/// This function constructs a Merkle tree from the provided vector of 32-byte hashes.
10+
/// If the vector is empty, it returns `None`. Otherwise, it iteratively hashes pairs
11+
/// of nodes until a single root hash is obtained.
12+
///
13+
/// # Parameters
14+
///
15+
/// - `hashes`: A vector of 32-byte hashes representing the leaves of the Merkle tree.
16+
///
17+
/// # Returns
18+
///
19+
/// - `Some([u8; 32])`: The computed Merkle root if at least one hash is provided.
20+
/// - `None`: If the input vector is empty.
721
#[inline]
822
pub fn merkle_root_from_hashes(hashes: Vec<[u8; 32]>) -> Option<[u8; 32]> {
923
let length = hashes.len();
@@ -28,6 +42,19 @@ pub fn merkle_root_from_hashes(hashes: Vec<[u8; 32]>) -> Option<[u8; 32]> {
2842
}
2943

3044
impl MasternodeList {
45+
/// Validates whether the stored masternode list Merkle root matches the one in the coinbase transaction.
46+
///
47+
/// This function compares the calculated masternode Merkle root with the one provided
48+
/// in the coinbase transaction payload to verify the integrity of the masternode list.
49+
///
50+
/// # Parameters
51+
///
52+
/// - `coinbase_transaction`: The coinbase transaction containing the expected Merkle root.
53+
///
54+
/// # Returns
55+
///
56+
/// - `true` if the Merkle root matches.
57+
/// - `false` otherwise.
3158
pub fn has_valid_mn_list_root(&self, coinbase_transaction: &Transaction) -> bool {
3259
let Some(TransactionPayload::CoinbasePayloadType(coinbase_payload)) = &coinbase_transaction.special_transaction_payload else {
3360
return false;
@@ -42,6 +69,19 @@ impl MasternodeList {
4269
}
4370
}
4471

72+
/// Validates whether the stored LLMQ list Merkle root matches the one in the coinbase transaction.
73+
///
74+
/// This function compares the calculated quorum Merkle root with the one provided
75+
/// in the coinbase transaction payload to verify the integrity of the quorum list.
76+
///
77+
/// # Parameters
78+
///
79+
/// - `coinbase_transaction`: The coinbase transaction containing the expected Merkle root.
80+
///
81+
/// # Returns
82+
///
83+
/// - `true` if the Merkle root matches.
84+
/// - `false` otherwise.
4585
pub fn has_valid_llmq_list_root(&self, coinbase_transaction: &Transaction) -> bool {
4686
let Some(TransactionPayload::CoinbasePayloadType(coinbase_payload)) = &coinbase_transaction.special_transaction_payload else {
4787
return false;
@@ -61,23 +101,50 @@ impl MasternodeList {
61101
has_valid_quorum_list_root
62102
}
63103

104+
/// Computes the Merkle root for the masternode list at a given block height.
105+
///
106+
/// This function generates a Merkle root for the masternode list based on the
107+
/// masternode entries at the specified block height.
108+
///
109+
/// # Parameters
110+
///
111+
/// - `block_height`: The block height at which to compute the Merkle root.
112+
///
113+
/// # Returns
114+
///
115+
/// - `Some(MerkleRootMasternodeList)`: The calculated Merkle root.
116+
/// - `None`: If no hashes are available for the given block height.
64117
pub fn calculate_masternodes_merkle_root(&self, block_height: u32) -> Option<MerkleRootMasternodeList> {
65118
self.hashes_for_merkle_root(block_height)
66119
.and_then(merkle_root_from_hashes).map(|hash| MerkleRootMasternodeList::from_byte_array(hash))
67120
}
68-
// pub fn calculate_masternodes_merkle_root_with_block_height_lookup<BL: Fn(*const std::os::raw::c_void, [u8; 32]) -> u32>(
69-
// &self,
70-
// context: *const std::os::raw::c_void,
71-
// block_height_lookup: BL
72-
// ) -> Option<[u8; 32]> {
73-
// self.hashes_for_merkle_root_with_block_height_lookup(context, block_height_lookup)
74-
// .and_then(merkle_root_from_hashes)
75-
// }
76121

122+
/// Computes the Merkle root for the LLMQ (Long-Living Masternode Quorum) list.
123+
///
124+
/// This function constructs a Merkle tree using the commitment hashes of all known LLMQs
125+
/// and returns the root hash.
126+
///
127+
/// # Returns
128+
///
129+
/// - `Some(MerkleRootQuorums)`: The calculated Merkle root.
130+
/// - `None`: If no quorum commitment hashes are available.
77131
pub fn calculate_llmq_merkle_root(&self) -> Option<MerkleRootQuorums> {
78132
merkle_root_from_hashes(self.hashes_for_quorum_merkle_root()).map(|hash| MerkleRootQuorums::from_byte_array(hash))
79133
}
80134

135+
/// Retrieves the list of hashes required to compute the masternode list Merkle root.
136+
///
137+
/// This function sorts the masternode list by pro-reg transaction hash and extracts
138+
/// the entry hashes for the given block height.
139+
///
140+
/// # Parameters
141+
///
142+
/// - `block_height`: The block height for which to retrieve the hashes.
143+
///
144+
/// # Returns
145+
///
146+
/// - `Some(Vec<[u8; 32]>)`: A sorted list of masternode entry hashes.
147+
/// - `None`: If the block height is invalid (`u32::MAX`).
81148
pub fn hashes_for_merkle_root(&self, block_height: u32) -> Option<Vec<[u8; 32]>> {
82149
(block_height != u32::MAX).then_some({
83150
let mut pro_tx_hashes = self.reversed_pro_reg_tx_hashes();
@@ -94,23 +161,14 @@ impl MasternodeList {
94161
})
95162
}
96163

97-
// pub fn hashes_for_merkle_root_with_block_height_lookup<BL: Fn(*const std::os::raw::c_void, [u8; 32]) -> u32>(
98-
// &self,
99-
// context: *const std::os::raw::c_void,
100-
// block_height_lookup: BL
101-
// ) -> Option<Vec<[u8; 32]>> {
102-
// let pro_tx_hashes = self.provider_tx_ordered_hashes();
103-
// let block_height = block_height_lookup(context, self.block_hash);
104-
// if block_height == u32::MAX {
105-
// println!("Block height lookup queried an unknown block {}", self.block_hash);
106-
// return None; //this should never happen
107-
// }
108-
// Some(pro_tx_hashes
109-
// .into_iter()
110-
// .map(|hash| (&self.masternodes[&hash]).entry_hash_at(block_height))
111-
// .collect::<Vec<_>>())
112-
// }
113-
164+
/// Retrieves the list of hashes required to compute the quorum Merkle root.
165+
///
166+
/// This function collects and sorts the entry hashes of all known quorums
167+
/// to construct a Merkle tree.
168+
///
169+
/// # Returns
170+
///
171+
/// - `Vec<[u8; 32]>`: A sorted list of quorum commitment hashes.
114172
pub fn hashes_for_quorum_merkle_root(&self) -> Vec<[u8; 32]> {
115173
let mut llmq_commitment_hashes = self.quorums
116174
.values()

dash/src/sml/masternode_list/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ mod peer_addresses;
88
pub mod from_diff;
99
mod apply_diff;
1010
mod scores_for_quorum;
11-
mod rotation;
12-
mod valid_members_in_rotated_quorum;
1311

1412
use std::collections::BTreeMap;
1513
#[cfg(feature = "bincode")]

dash/src/sml/masternode_list/peer_addresses.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,26 @@ use crate::sml::masternode_list::MasternodeList;
66

77
impl MasternodeList {
88

9+
/// Retrieves a list of peer addresses from the masternode list, sorted using a nonce for deterministic ordering.
10+
///
11+
/// This function generates a sorted list of masternode addresses based on their registration transaction hashes,
12+
/// using a provided nonce to create a deterministic but unpredictable order. The resulting list is truncated
13+
/// to the specified maximum count.
14+
///
15+
/// # Parameters
16+
///
17+
/// - `nonce`: A 64-bit unsigned integer used to influence the sorting order.
18+
/// - `max_count`: The maximum number of peer addresses to return.
19+
///
20+
/// # Returns
21+
///
22+
/// - `Vec<SocketAddr>`: A list of masternode service addresses, sorted using the nonce and limited to `max_count`.
23+
///
24+
/// # Notes
25+
///
26+
/// - The sorting process appends the nonce to each masternode’s transaction hash and applies a BLAKE3 hash
27+
/// to determine the order.
28+
/// - Only valid masternodes (i.e., those marked as valid in the masternode list) are included in the output.
929
pub fn peer_addresses_with_connectivity_nonce(&self, nonce: u64, max_count: usize) -> Vec<SocketAddr> {
1030
let registration_transaction_hashes: Vec<_> = self.masternodes.keys().cloned().collect();
1131
let mut sorted_hashes = registration_transaction_hashes.clone();

0 commit comments

Comments
 (0)