Skip to content

Commit 477ccf9

Browse files
committed
refactor: Cleanup HeaderValidator and ValidationManager
- Some simplifications and name changes - Some unused code - Dropping the network change parts since the rest of the codebase doesnt support it anyway - Making the `ValidationMode::Full` mode checking PoW by default, not based on yet another parameter
1 parent 45337b2 commit 477ccf9

File tree

7 files changed

+108
-229
lines changed

7 files changed

+108
-229
lines changed

dash-spv/src/client/lifecycle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<
6262
.map_err(SpvError::Sync)?;
6363

6464
// Create validation manager
65-
let validation = ValidationManager::new(config.validation_mode);
65+
let validation = ValidationManager::new(config.validation_mode, config.network);
6666

6767
// Create ChainLock manager
6868
let chainlock_manager = Arc::new(ChainLockManager::new(true));

dash-spv/src/client/sync_coordinator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ impl<
931931
// Validate headers before adding to chain state
932932
{
933933
// Validate the batch of headers
934-
if let Err(e) = self.validation.validate_header_chain(&headers, false) {
934+
if let Err(e) = self.validation.validate_headers(&headers) {
935935
tracing::error!(
936936
"Header validation failed for range {}..{}: {:?}",
937937
current_height,

dash-spv/src/validation/headers.rs

Lines changed: 18 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ pub struct HeaderValidator {
1616

1717
impl HeaderValidator {
1818
/// Create a new header validator.
19-
pub fn new(mode: ValidationMode) -> Self {
19+
pub fn new(mode: ValidationMode, network: Network) -> Self {
2020
Self {
2121
mode,
22-
network: Network::Dash, // Default to mainnet
22+
network,
2323
}
2424
}
2525

@@ -28,11 +28,6 @@ impl HeaderValidator {
2828
self.mode = mode;
2929
}
3030

31-
/// Set network.
32-
pub fn set_network(&mut self, network: Network) {
33-
self.network = network;
34-
}
35-
3631
/// Validate a single header.
3732
pub fn validate(
3833
&self,
@@ -76,55 +71,23 @@ impl HeaderValidator {
7671
// Validate proof of work with X11 hashing (now enabled with core-block-hash-use-x11 feature)
7772
let target = header.target();
7873
if let Err(e) = header.validate_pow(target) {
79-
match e {
80-
DashError::BlockBadProofOfWork => {
81-
return Err(ValidationError::InvalidProofOfWork);
82-
}
74+
return match e {
75+
DashError::BlockBadProofOfWork => Err(ValidationError::InvalidProofOfWork),
8376
DashError::BlockBadTarget => {
84-
return Err(ValidationError::InvalidHeaderChain("Invalid target".to_string()));
77+
Err(ValidationError::InvalidHeaderChain("Invalid target".to_string()))
8578
}
86-
_ => {
87-
return Err(ValidationError::InvalidHeaderChain(format!(
88-
"PoW validation error: {:?}",
89-
e
90-
)));
91-
}
92-
}
93-
}
94-
95-
Ok(())
96-
}
97-
98-
/// Validate a chain of headers with basic validation.
99-
pub fn validate_chain_basic(&self, headers: &[BlockHeader]) -> ValidationResult<()> {
100-
// Respect ValidationMode::None
101-
if self.mode == ValidationMode::None {
102-
return Ok(());
103-
}
104-
105-
if headers.is_empty() {
106-
return Ok(());
107-
}
108-
109-
// Validate chain continuity
110-
for i in 1..headers.len() {
111-
let header = &headers[i];
112-
let prev_header = &headers[i - 1];
113-
114-
self.validate_basic(header, Some(prev_header))?;
79+
_ => Err(ValidationError::InvalidHeaderChain(format!(
80+
"PoW validation error: {:?}",
81+
e
82+
))),
83+
};
11584
}
11685

117-
tracing::debug!("Basic header chain validation passed for {} headers", headers.len());
11886
Ok(())
11987
}
12088

121-
/// Validate a chain of headers with full validation.
122-
pub fn validate_chain_full(
123-
&self,
124-
headers: &[BlockHeader],
125-
validate_pow: bool,
126-
) -> ValidationResult<()> {
127-
// Respect ValidationMode::None
89+
/// Validate a chain of headers considering the validation mode.
90+
pub fn validate_headers(&self, headers: &[BlockHeader]) -> ValidationResult<()> {
12891
if self.mode == ValidationMode::None {
12992
return Ok(());
13093
}
@@ -145,14 +108,14 @@ impl HeaderValidator {
145108
None
146109
};
147110

148-
if validate_pow {
149-
self.validate_full(header, prev_header)?;
150-
} else {
151-
self.validate_basic(header, prev_header)?;
152-
}
111+
self.validate(header, prev_header)?;
153112
}
154113

155-
tracing::debug!("Full header chain validation passed for {} headers", headers.len());
114+
tracing::debug!(
115+
"Header chain validation passed for {} headers in mode: {:?}",
116+
headers.len(),
117+
self.mode
118+
);
156119
Ok(())
157120
}
158121

@@ -174,23 +137,6 @@ impl HeaderValidator {
174137

175138
Ok(())
176139
}
177-
178-
/// Validate difficulty adjustment (simplified for SPV).
179-
pub fn validate_difficulty_adjustment(
180-
&self,
181-
header: &BlockHeader,
182-
prev_header: &BlockHeader,
183-
) -> ValidationResult<()> {
184-
// For SPV client, we trust that the network has validated difficulty properly
185-
// We only check basic constraints
186-
187-
// For SPV we trust the network for difficulty validation
188-
// TODO: Implement proper difficulty validation if needed
189-
let _prev_target = prev_header.target();
190-
let _current_target = header.target();
191-
192-
Ok(())
193-
}
194140
}
195141

196142
#[cfg(test)]

dash-spv/src/validation/headers_edge_test.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@ mod tests {
3333

3434
#[test]
3535
fn test_genesis_block_validation() {
36-
let mut validator = HeaderValidator::new(ValidationMode::Full);
37-
3836
for network in [Network::Dash, Network::Testnet, Network::Regtest] {
39-
validator.set_network(network);
37+
let validator = HeaderValidator::new(ValidationMode::Full, network);
38+
4039
let genesis = genesis_block(network).header;
4140

4241
// Genesis block should validate with no previous header
@@ -50,7 +49,7 @@ mod tests {
5049

5150
#[test]
5251
fn test_maximum_target_validation() {
53-
let validator = HeaderValidator::new(ValidationMode::Full);
52+
let validator = HeaderValidator::new(ValidationMode::Full, Network::Dash);
5453

5554
// Create header with maximum allowed target (easiest difficulty)
5655
let max_target_bits = 0x1e0fffff; // Maximum target for testing
@@ -71,7 +70,7 @@ mod tests {
7170

7271
#[test]
7372
fn test_minimum_target_validation() {
74-
let validator = HeaderValidator::new(ValidationMode::Full);
73+
let validator = HeaderValidator::new(ValidationMode::Full, Network::Dash);
7574

7675
// Create header with very low target (hardest difficulty)
7776
let min_target_bits = 0x17000000; // Very difficult target
@@ -93,7 +92,7 @@ mod tests {
9392

9493
#[test]
9594
fn test_zero_prev_blockhash() {
96-
let validator = HeaderValidator::new(ValidationMode::Basic);
95+
let validator = HeaderValidator::new(ValidationMode::Basic, Network::Dash);
9796

9897
// First header with zero prev_blockhash (like genesis)
9998
let header1 = create_test_header_with_params(
@@ -126,7 +125,7 @@ mod tests {
126125

127126
#[test]
128127
fn test_all_ff_prev_blockhash() {
129-
let validator = HeaderValidator::new(ValidationMode::Basic);
128+
let validator = HeaderValidator::new(ValidationMode::Basic, Network::Dash);
130129

131130
// Header with all 0xFF prev_blockhash
132131
let header = create_test_header_with_params(
@@ -162,7 +161,7 @@ mod tests {
162161

163162
#[test]
164163
fn test_timestamp_boundaries() {
165-
let validator = HeaderValidator::new(ValidationMode::Basic);
164+
let validator = HeaderValidator::new(ValidationMode::Basic, Network::Dash);
166165

167166
// Test with minimum timestamp (0)
168167
let header_min_time = create_test_header_with_params(
@@ -193,7 +192,7 @@ mod tests {
193192

194193
#[test]
195194
fn test_version_edge_cases() {
196-
let validator = HeaderValidator::new(ValidationMode::Basic);
195+
let validator = HeaderValidator::new(ValidationMode::Basic, Network::Dash);
197196

198197
// Test various version values
199198
let versions = [0, 1, 0x20000000, 0x20000001, u32::MAX];
@@ -217,7 +216,7 @@ mod tests {
217216

218217
#[test]
219218
fn test_large_chain_validation() {
220-
let validator = HeaderValidator::new(ValidationMode::Basic);
219+
let validator = HeaderValidator::new(ValidationMode::Basic, Network::Dash);
221220

222221
// Create a large chain
223222
let chain_size = 1000;
@@ -240,7 +239,7 @@ mod tests {
240239
}
241240

242241
// Should validate entire chain
243-
assert!(validator.validate_chain_basic(&headers).is_ok());
242+
assert!(validator.validate_headers(&headers).is_ok());
244243

245244
// Break the chain in the middle
246245
let broken_index = chain_size / 2;
@@ -256,14 +255,12 @@ mod tests {
256255
);
257256

258257
// Should fail validation
259-
let result = validator.validate_chain_basic(&headers);
258+
let result = validator.validate_headers(&headers);
260259
assert!(matches!(result, Err(ValidationError::InvalidHeaderChain(_))));
261260
}
262261

263262
#[test]
264263
fn test_single_header_chain_validation() {
265-
let validator = HeaderValidator::new(ValidationMode::Full);
266-
267264
let header = create_test_header_with_params(
268265
0x20000000,
269266
dashcore::BlockHash::from_raw_hash(dashcore_hashes::hash_x11::Hash::from_byte_array(
@@ -278,13 +275,17 @@ mod tests {
278275
let headers = vec![header];
279276

280277
// Single header chain should validate in both basic and full modes
281-
assert!(validator.validate_chain_basic(&headers).is_ok());
282-
assert!(validator.validate_chain_full(&headers, false).is_ok());
278+
assert!(HeaderValidator::new(ValidationMode::Basic, Network::Dash)
279+
.validate_headers(&headers)
280+
.is_ok());
281+
assert!(HeaderValidator::new(ValidationMode::Full, Network::Dash)
282+
.validate_headers(&headers)
283+
.is_ok());
283284
}
284285

285286
#[test]
286287
fn test_duplicate_headers_in_chain() {
287-
let validator = HeaderValidator::new(ValidationMode::Basic);
288+
let validator = HeaderValidator::new(ValidationMode::Basic, Network::Dash);
288289

289290
let header = create_test_header_with_params(
290291
0x20000000,
@@ -301,13 +302,13 @@ mod tests {
301302
let headers = vec![header, header];
302303

303304
// Should fail because second header's prev_blockhash won't match first header's hash
304-
let result = validator.validate_chain_basic(&headers);
305+
let result = validator.validate_headers(&headers);
305306
assert!(matches!(result, Err(ValidationError::InvalidHeaderChain(_))));
306307
}
307308

308309
#[test]
309310
fn test_merkle_root_variations() {
310-
let validator = HeaderValidator::new(ValidationMode::Basic);
311+
let validator = HeaderValidator::new(ValidationMode::Basic, Network::Dash);
311312

312313
// Test various merkle root patterns
313314
let merkle_patterns = [
@@ -340,7 +341,7 @@ mod tests {
340341

341342
#[test]
342343
fn test_mode_switching_during_chain_validation() {
343-
let mut validator = HeaderValidator::new(ValidationMode::None);
344+
let mut validator = HeaderValidator::new(ValidationMode::None, Network::Dash);
344345

345346
// Create headers with invalid PoW
346347
let mut headers = vec![];
@@ -361,18 +362,16 @@ mod tests {
361362
headers.push(header);
362363
}
363364

364-
// Should pass with None mode (ValidationMode::None always passes)
365-
let result = validator.validate_chain_full(&headers, true);
365+
let result = validator.validate_headers(&headers);
366366
assert!(result.is_ok(), "ValidationMode::None should always pass, but got: {:?}", result);
367367

368-
// Switch to Full mode
369368
validator.set_mode(ValidationMode::Full);
370-
371369
// Should now fail due to invalid PoW
372-
let result = validator.validate_chain_full(&headers, true);
370+
let result = validator.validate_headers(&headers);
373371
assert!(matches!(result, Err(ValidationError::InvalidProofOfWork)));
374372

375-
// But should pass without PoW check
376-
assert!(validator.validate_chain_full(&headers, false).is_ok());
373+
validator.set_mode(ValidationMode::None);
374+
let result = validator.validate_headers(&headers);
375+
assert!(result.is_ok(), "ValidationMode::None should always pass, but got: {:?}", result);
377376
}
378377
}

0 commit comments

Comments
 (0)