Skip to content

Commit a8b5d0b

Browse files
authored
Merge pull request #66 from dashpay/small-fix
Fix: Allow Block hash of 0s to represent genesis.
2 parents 4f0f9b9 + 61872fd commit a8b5d0b

File tree

8 files changed

+87
-58
lines changed

8 files changed

+87
-58
lines changed

dash/src/bip32.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ use serde;
3636

3737
use crate::base58;
3838
use crate::crypto::key::{self, Keypair, PrivateKey, PublicKey};
39-
use crate::dip9::{COINJOIN_PATH_MAINNET, COINJOIN_PATH_TESTNET, DASH_BIP44_PATH_MAINNET, DASH_BIP44_PATH_TESTNET, IDENTITY_AUTHENTICATION_PATH_MAINNET, IDENTITY_AUTHENTICATION_PATH_TESTNET, IDENTITY_INVITATION_PATH_MAINNET, IDENTITY_INVITATION_PATH_TESTNET, IDENTITY_REGISTRATION_PATH_MAINNET, IDENTITY_REGISTRATION_PATH_TESTNET, IDENTITY_TOPUP_PATH_MAINNET, IDENTITY_TOPUP_PATH_TESTNET};
39+
use crate::dip9::{
40+
COINJOIN_PATH_MAINNET, COINJOIN_PATH_TESTNET, DASH_BIP44_PATH_MAINNET, DASH_BIP44_PATH_TESTNET,
41+
IDENTITY_AUTHENTICATION_PATH_MAINNET, IDENTITY_AUTHENTICATION_PATH_TESTNET,
42+
IDENTITY_INVITATION_PATH_MAINNET, IDENTITY_INVITATION_PATH_TESTNET,
43+
IDENTITY_REGISTRATION_PATH_MAINNET, IDENTITY_REGISTRATION_PATH_TESTNET,
44+
IDENTITY_TOPUP_PATH_MAINNET, IDENTITY_TOPUP_PATH_TESTNET,
45+
};
4046
use crate::hash_types::XpubIdentifier;
4147
use crate::internal_macros::impl_bytes_newtype;
4248
use crate::io::Write;
@@ -489,16 +495,15 @@ impl DerivationPath {
489495
]);
490496
root_derivation_path
491497
}
492-
pub fn coinjoin_path(
493-
network: Network,
494-
account: u32,
495-
) -> Self {
498+
pub fn coinjoin_path(network: Network, account: u32) -> Self {
496499
let mut root_derivation_path: DerivationPath = match network {
497500
Network::Dash => COINJOIN_PATH_MAINNET,
498501
_ => COINJOIN_PATH_TESTNET,
499502
}
500503
.into();
501-
root_derivation_path.0.extend(&[ChildNumber::Hardened { index: account }]);
504+
root_derivation_path.0.extend(&[ChildNumber::Hardened {
505+
index: account,
506+
}]);
502507
root_derivation_path
503508
}
504509

dash/src/dip9.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,18 +155,30 @@ pub const DASH_BIP44_PATH_TESTNET: IndexConstPath<2> = IndexConstPath {
155155

156156
pub const COINJOIN_PATH_MAINNET: IndexConstPath<3> = IndexConstPath {
157157
indexes: [
158-
ChildNumber::Hardened { index: FEATURE_PURPOSE },
159-
ChildNumber::Hardened { index: DASH_COIN_TYPE },
160-
ChildNumber::Hardened { index: FEATURE_PURPOSE_COINJOIN },
158+
ChildNumber::Hardened {
159+
index: FEATURE_PURPOSE,
160+
},
161+
ChildNumber::Hardened {
162+
index: DASH_COIN_TYPE,
163+
},
164+
ChildNumber::Hardened {
165+
index: FEATURE_PURPOSE_COINJOIN,
166+
},
161167
],
162168
reference: DerivationPathReference::CoinJoin,
163169
path_type: DerivationPathType::ANONYMOUS_FUNDS,
164170
};
165171
pub const COINJOIN_PATH_TESTNET: IndexConstPath<3> = IndexConstPath {
166172
indexes: [
167-
ChildNumber::Hardened { index: FEATURE_PURPOSE },
168-
ChildNumber::Hardened { index: DASH_TESTNET_COIN_TYPE },
169-
ChildNumber::Hardened { index: FEATURE_PURPOSE_COINJOIN },
173+
ChildNumber::Hardened {
174+
index: FEATURE_PURPOSE,
175+
},
176+
ChildNumber::Hardened {
177+
index: DASH_TESTNET_COIN_TYPE,
178+
},
179+
ChildNumber::Hardened {
180+
index: FEATURE_PURPOSE_COINJOIN,
181+
},
170182
],
171183
reference: DerivationPathReference::CoinJoin,
172184
path_type: DerivationPathType::ANONYMOUS_FUNDS,

dash/src/sml/masternode_list/from_diff.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::collections::BTreeMap;
2-
31
use crate::bls_sig_utils::BLSSignature;
42
use crate::network::message_sml::MnListDiff;
53
use crate::sml::error::SmlError;
@@ -11,6 +9,8 @@ use crate::sml::quorum_entry::qualified_quorum_entry::{
119
QualifiedQuorumEntry, VerifyingChainLockSignaturesType,
1210
};
1311
use crate::{BlockHash, Network};
12+
use hashes::Hash;
13+
use std::collections::BTreeMap;
1414

1515
pub trait TryFromWithBlockHashLookup<T>: Sized {
1616
type Error;
@@ -67,7 +67,9 @@ impl TryFromWithBlockHashLookup<MnListDiff> for MasternodeList {
6767
{
6868
if let Some(genesis_block_hash) = network.known_genesis_block_hash() {
6969
// Check if the base block is the genesis block
70-
if diff.base_block_hash != genesis_block_hash {
70+
if diff.base_block_hash != genesis_block_hash
71+
&& diff.base_block_hash.as_byte_array() != &[0; 32]
72+
{
7173
return Err(SmlError::BaseBlockNotGenesis(diff.base_block_hash));
7274
}
7375
}

dash/src/sml/masternode_list_engine/mod.rs

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ mod validation;
88

99
use std::collections::{BTreeMap, BTreeSet};
1010

11-
#[cfg(feature = "bincode")]
12-
use bincode::{Decode, Encode};
13-
#[cfg(feature = "serde")]
14-
use serde::{Deserialize, Serialize};
15-
1611
use crate::bls_sig_utils::{BLSPublicKey, BLSSignature};
1712
use crate::network::message_qrinfo::{QRInfo, QuorumSnapshot};
1813
use crate::network::message_sml::MnListDiff;
@@ -28,6 +23,11 @@ use crate::sml::quorum_entry::qualified_quorum_entry::{
2823
use crate::sml::quorum_validation_error::{ClientDataRetrievalError, QuorumValidationError};
2924
use crate::transaction::special_transaction::quorum_commitment::QuorumEntry;
3025
use crate::{BlockHash, Network, QuorumHash};
26+
#[cfg(feature = "bincode")]
27+
use bincode::{Decode, Encode};
28+
use hashes::Hash;
29+
#[cfg(feature = "serde")]
30+
use serde::{Deserialize, Serialize};
3131

3232
#[derive(Clone, Eq, PartialEq, Default)]
3333
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -66,10 +66,15 @@ impl From<MasternodeListEngineBTreeMapBlockContainer> for MasternodeListEngineBl
6666
}
6767

6868
impl MasternodeListEngineBlockContainer {
69-
pub fn get_height(&self, block: &BlockHash) -> Option<&CoreBlockHeight> {
70-
match self {
71-
MasternodeListEngineBlockContainer::BTreeMapContainer(map) => {
72-
map.block_heights.get(block)
69+
pub fn get_height(&self, block_hash: &BlockHash) -> Option<CoreBlockHeight> {
70+
if block_hash.as_byte_array() == &[0; 32] {
71+
// rep
72+
Some(0)
73+
} else {
74+
match self {
75+
MasternodeListEngineBlockContainer::BTreeMapContainer(map) => {
76+
map.block_heights.get(block_hash).copied()
77+
}
7378
}
7479
}
7580
}
@@ -203,7 +208,7 @@ impl MasternodeListEngine {
203208
else {
204209
return true;
205210
};
206-
!self.masternode_lists.contains_key(block_height)
211+
!self.masternode_lists.contains_key(&block_height)
207212
})
208213
.collect()
209214
} else {
@@ -230,7 +235,7 @@ impl MasternodeListEngine {
230235
else {
231236
return true;
232237
};
233-
!self.masternode_lists.contains_key(block_height)
238+
!self.masternode_lists.contains_key(&block_height)
234239
})
235240
.collect()
236241
} else {
@@ -255,7 +260,7 @@ impl MasternodeListEngine {
255260
) -> Option<&MasternodeList> {
256261
self.block_container
257262
.get_height(block_hash)
258-
.and_then(|height| self.masternode_lists.get(height))
263+
.and_then(|height| self.masternode_lists.get(&height))
259264
}
260265

261266
pub fn feed_block_height(&mut self, height: CoreBlockHeight, block_hash: BlockHash) {
@@ -357,7 +362,7 @@ impl MasternodeListEngine {
357362
Ok(())
358363
}
359364

360-
pub fn feed_qr_info<FH, FS>(
365+
pub fn feed_qr_info<FH>(
361366
&mut self,
362367
qr_info: QRInfo,
363368
verify_tip_non_rotated_quorums: bool,
@@ -366,7 +371,6 @@ impl MasternodeListEngine {
366371
) -> Result<(), QuorumValidationError>
367372
where
368373
FH: Fn(&BlockHash) -> Result<u32, ClientDataRetrievalError>,
369-
FS: Fn(&BlockHash) -> Result<Option<BLSSignature>, ClientDataRetrievalError>,
370374
{
371375
// Fetch and process block heights using the provided callback
372376
if let Some(fetch_height) = fetch_block_height {
@@ -397,15 +401,18 @@ impl MasternodeListEngine {
397401

398402
let can_verify_previous = quorum_snapshot_and_mn_list_diff_at_h_minus_4c.is_some();
399403

400-
let h_height = self
401-
.block_container
402-
.get_height(&mn_list_diff_h.block_hash)
403-
.copied()
404-
.ok_or(QuorumValidationError::RequiredBlockNotPresent(mn_list_diff_h.block_hash))?;
405-
let tip_height =
406-
self.block_container.get_height(&mn_list_diff_tip.block_hash).copied().ok_or(
407-
QuorumValidationError::RequiredBlockNotPresent(mn_list_diff_tip.block_hash),
408-
)?;
404+
let h_height = self.block_container.get_height(&mn_list_diff_h.block_hash).ok_or(
405+
QuorumValidationError::RequiredBlockNotPresent(
406+
mn_list_diff_h.block_hash,
407+
"getting height at diff h".to_string(),
408+
),
409+
)?;
410+
let tip_height = self.block_container.get_height(&mn_list_diff_tip.block_hash).ok_or(
411+
QuorumValidationError::RequiredBlockNotPresent(
412+
mn_list_diff_tip.block_hash,
413+
"getting height at diff tip".to_string(),
414+
),
415+
)?;
409416
let rotation_quorum_type = last_commitment_per_index
410417
.first()
411418
.map(|quorum_entry| quorum_entry.llmq_type)
@@ -657,23 +664,22 @@ impl MasternodeListEngine {
657664
.known_genesis_block_hash()
658665
.or_else(|| self.block_container.get_hash(&0).cloned())
659666
{
660-
if masternode_list_diff.base_block_hash == known_genesis_block_hash {
667+
if masternode_list_diff.base_block_hash == known_genesis_block_hash
668+
|| masternode_list_diff.base_block_hash.as_byte_array() == &[0; 32]
669+
{
661670
// we are going from the start
662671
let block_hash = masternode_list_diff.block_hash;
663672

664673
let masternode_list = masternode_list_diff.try_into_with_block_hash_lookup(
665-
|block_hash| {
666-
diff_end_height.or(self.block_container.get_height(block_hash).copied())
667-
},
674+
|block_hash| diff_end_height.or(self.block_container.get_height(block_hash)),
668675
self.network,
669676
)?;
670677

671678
let diff_end_height = match diff_end_height {
672679
None => self
673680
.block_container
674681
.get_height(&block_hash)
675-
.ok_or(SmlError::BlockHashLookupFailed(block_hash))
676-
.cloned()?,
682+
.ok_or(SmlError::BlockHashLookupFailed(block_hash))?,
677683
Some(diff_end_height) => {
678684
self.block_container.feed_block_height(diff_end_height, block_hash);
679685
diff_end_height
@@ -689,7 +695,7 @@ impl MasternodeListEngine {
689695
else {
690696
return Err(SmlError::BlockHashLookupFailed(masternode_list_diff.base_block_hash));
691697
};
692-
let Some(base_masternode_list) = self.masternode_lists.get(base_height) else {
698+
let Some(base_masternode_list) = self.masternode_lists.get(&base_height) else {
693699
return Err(SmlError::MissingStartMasternodeList(masternode_list_diff.base_block_hash));
694700
};
695701

@@ -699,8 +705,7 @@ impl MasternodeListEngine {
699705
None => self
700706
.block_container
701707
.get_height(&block_hash)
702-
.ok_or(SmlError::BlockHashLookupFailed(block_hash))
703-
.cloned()?,
708+
.ok_or(SmlError::BlockHashLookupFailed(block_hash))?,
704709
Some(diff_end_height) => diff_end_height,
705710
};
706711

@@ -1107,11 +1112,8 @@ mod tests {
11071112
}
11081113

11091114
masternode_list_engine
1110-
.feed_qr_info::<fn(&BlockHash) -> Result<u32, ClientDataRetrievalError>, fn(&BlockHash) -> Result<Option<BLSSignature>, ClientDataRetrievalError>>(
1111-
qr_info,
1112-
true,
1113-
true,
1114-
None,
1115+
.feed_qr_info::<fn(&BlockHash) -> Result<u32, ClientDataRetrievalError>>(
1116+
qr_info, true, true, None,
11151117
)
11161118
.expect("expected to feed_qr_info");
11171119

dash/src/sml/masternode_list_engine/non_rotated_quorum_construction.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ impl MasternodeListEngine {
2323
))
2424
}
2525
} else {
26-
Err(QuorumValidationError::RequiredBlockNotPresent(*block_hash))
26+
Err(QuorumValidationError::RequiredBlockNotPresent(
27+
*block_hash,
28+
"looking for masternode list and height for block hash 8 blocks ago".to_string(),
29+
))
2730
}
2831
}
2932

dash/src/sml/masternode_list_engine/rotated_quorum_construction.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl MasternodeListEngine {
3535
else {
3636
return Err(QuorumValidationError::RequiredBlockNotPresent(
3737
quorum.quorum_entry.quorum_hash,
38+
"getting height when finding rotated masternodes for quorum".to_string(),
3839
));
3940
};
4041
let llmq_type = quorum.quorum_entry.llmq_type;
@@ -82,7 +83,7 @@ impl MasternodeListEngine {
8283
self.block_container.get_height(&quorum.quorum_entry.quorum_hash)
8384
else {
8485
return Err(QuorumValidationError::RequiredBlockNotPresent(
85-
quorum.quorum_entry.quorum_hash,
86+
quorum.quorum_entry.quorum_hash, "getting height for a quorum hash when trying to find rotated masternodes for quorums".to_string()
8687
));
8788
};
8889
let llmq_type = quorum.quorum_entry.llmq_type;
@@ -145,7 +146,10 @@ impl MasternodeListEngine {
145146
for quorum in &qr_info.last_commitment_per_index {
146147
let Some(quorum_block_height) = self.block_container.get_height(&quorum.quorum_hash)
147148
else {
148-
return Err(QuorumValidationError::RequiredBlockNotPresent(quorum.quorum_hash));
149+
return Err(QuorumValidationError::RequiredBlockNotPresent(
150+
quorum.quorum_hash,
151+
"getting required cl_sig heights".to_string(),
152+
));
149153
};
150154
let llmq_params = quorum.llmq_type.params();
151155
let quorum_index = quorum_block_height % llmq_params.dkg_params.interval;
@@ -164,6 +168,7 @@ impl MasternodeListEngine {
164168
else {
165169
return Err(QuorumValidationError::RequiredBlockNotPresent(
166170
quorum.quorum_hash,
171+
"getting height for quorum hash for diff at h minus 4c".to_string(),
167172
));
168173
};
169174
let llmq_params = quorum.llmq_type.params();

dash/src/sml/quorum_entry/qualified_quorum_entry.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl QualifiedQuorumEntry {
6868
/// * `result` - A `Result` containing either success (`Ok`) or a `QuorumValidationError`.
6969
pub fn update_quorum_status(&mut self, result: Result<(), QuorumValidationError>) {
7070
match result {
71-
Err(QuorumValidationError::RequiredBlockNotPresent(block_hash)) => {
71+
Err(QuorumValidationError::RequiredBlockNotPresent(block_hash, _)) => {
7272
self.verified = LLMQEntryVerificationStatus::Skipped(
7373
LLMQEntryVerificationSkipStatus::UnknownBlock(block_hash),
7474
);

dash/src/sml/quorum_validation_error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ pub enum ClientDataRetrievalError {
2424
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2525
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
2626
pub enum QuorumValidationError {
27-
#[error("Required block not present: {0}")]
28-
RequiredBlockNotPresent(BlockHash),
27+
#[error("Required block not present: {0} ({1})")]
28+
RequiredBlockNotPresent(BlockHash, String),
2929

3030
#[error("Required block height not present: {0}")]
3131
RequiredBlockHeightNotPresent(CoreBlockHeight),

0 commit comments

Comments
 (0)