Skip to content

Commit fc254c5

Browse files
pauldeluciaPastaPastaPasta
authored andcommitted
sync from checkpoint works well
1 parent 3a78281 commit fc254c5

File tree

6 files changed

+164
-131
lines changed

6 files changed

+164
-131
lines changed

dash-spv/src/chain/checkpoints.rs

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -286,55 +286,31 @@ pub fn mainnet_checkpoints() -> Vec<Checkpoint> {
286286
28917698,
287287
None,
288288
),
289-
// Early network checkpoint (1 week after genesis)
290-
create_checkpoint(
291-
4991,
292-
"000000003b01809551952460744d5dbb8fcbd6cbae3c220267bf7fa43f837367",
293-
"000000001263f3327dd2f6bc445b47beb82fb8807a62e252ba064e2d2b6f91a6",
294-
1390163520,
295-
0x1e0fffff,
296-
"0x00000000000000000000000000000000000000000000000000000000271027f0",
297-
"7faff642d9e914716c50e3406df522b2b9a10ea3df4fef4e2229997367a6cab1",
298-
357631712,
299-
None,
300-
),
301-
// 3 months checkpoint
302-
create_checkpoint(
303-
107996,
304-
"00000000000a23840ac16115407488267aa3da2b9bc843e301185b7d17e4dc40",
305-
"000000000006fe4020a310786bd34e17aa7681c86a20a2e121e0e3dd599800e8",
306-
1395522898,
307-
0x1b04864c,
308-
"0x0000000000000000000000000000000000000000000000000056bf9caa56bf9d",
309-
"15c3852f9e71a6cbc0cfa96d88202746cfeae6fc645ccc878580bc29daeff193",
310-
10049236,
311-
None,
312-
),
313-
// 2017 checkpoint
289+
// Block 750000 (2017)
314290
create_checkpoint(
315291
750000,
316292
"00000000000000b4181bbbdddbae464ce11fede5d0292fb63fdede1e7c8ab21c",
317293
"00000000000001e115237541be8dd91bce2653edd712429d11371842f85bd3e1",
318-
1491953700,
319-
0x1a075a02,
320-
"0x00000000000000000000000000000000000000000000000485f01ee9f01ee9f8",
294+
1507424630,
295+
0x1a027884,
296+
"0x0000000000000000000000000000000000000000000000172210fe351643b3f1",
321297
"0ce99835e2de1240e230b5075024817aace2b03b3944967a88af079744d0aa62",
322298
2199533779,
323299
None,
324300
),
325-
// Recent checkpoint with masternode list (2022)
301+
// Block 1700000 (2022) with masternode list
326302
create_checkpoint(
327303
1700000,
328304
"000000000000001d7579a371e782fd9c4480f626a62b916fa4eb97e16a49043a",
329305
"000000000000001a5631d781a4be0d9cda08b470ac6f108843cedf32e4dc081e",
330306
1657142113,
331307
0x1927e30e,
332-
"000000000000000000000000000000000000000000007562df93a26b81386288",
308+
"0x000000000000000000000000000000000000000000007562df93a26b81386288",
333309
"dafe57cefc3bc265dfe8416e2f2e3a22af268fd587a48f36affd404bec738305",
334310
3820512540,
335311
Some("ML1700000__70227"),
336312
),
337-
// Latest checkpoint with masternode list (2022/2023)
313+
// Block 1900000 (2023) with masternode list
338314
create_checkpoint(
339315
1900000,
340316
"000000000000001b8187c744355da78857cca5b9aeb665c39d12f26a0e3a9af5",
@@ -346,6 +322,18 @@ pub fn mainnet_checkpoints() -> Vec<Checkpoint> {
346322
498598646,
347323
Some("ML1900000__70230"),
348324
),
325+
// Block 2300000 (2025) - recent checkpoint
326+
create_checkpoint(
327+
2300000,
328+
"00000000000000186f9f2fde843be3d66b8ae317cabb7d43dbde943d02a4b4d7",
329+
"000000000000000d51caa0307836ca3eabe93068a9007515ac128a43d6addd4e",
330+
1751767455,
331+
0x1938df46,
332+
"0x00000000000000000000000000000000000000000000aa3859b6456688a3fb53",
333+
"b026649607d72d486480c0cef823dba6b28d0884a0d86f5a8b9e5a7919545cef",
334+
972444458,
335+
Some("ML2300000__70232"), // Has masternode list with protocol version 70232
336+
),
349337
]
350338
}
351339

dash-spv/src/sync/masternodes.rs

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,14 @@ impl MasternodeSyncManager {
127127
// Check if the terminal block exists in our chain
128128
match storage.get_header(terminal_height).await {
129129
Ok(Some(header)) => {
130-
if header.block_hash() == expected_hash {
130+
let actual_hash = header.block_hash();
131+
tracing::info!(
132+
"Terminal block validation at height {}: expected hash {}, actual hash {}",
133+
terminal_height,
134+
expected_hash,
135+
actual_hash
136+
);
137+
if actual_hash == expected_hash {
131138
if has_precalculated_data {
132139
tracing::info!(
133140
"Using terminal block at height {} with pre-calculated masternode data as base for sync",
@@ -184,34 +191,40 @@ impl MasternodeSyncManager {
184191
return Ok(0);
185192
}
186193

187-
// Convert blockchain height to storage height
188-
let storage_height = terminal_height - sync_base_height;
194+
// When syncing from checkpoint, storage uses absolute blockchain heights
195+
// No need to convert - just use terminal_height directly
196+
let storage_height = terminal_height;
189197

190198
// Check if the terminal block exists in our chain
191199
match storage.get_header(storage_height).await {
192200
Ok(Some(header)) => {
193-
if header.block_hash() == expected_hash {
201+
let actual_hash = header.block_hash();
202+
tracing::info!(
203+
"Terminal block validation at height {}: expected hash {}, actual hash {}",
204+
terminal_height,
205+
expected_hash,
206+
actual_hash
207+
);
208+
if actual_hash == expected_hash {
194209
if has_precalculated_data {
195210
tracing::info!(
196-
"Using terminal block at blockchain height {} (storage height {}) with pre-calculated masternode data as base for sync",
197-
terminal_height,
198-
storage_height
211+
"Using terminal block at height {} with pre-calculated masternode data as base for sync",
212+
terminal_height
199213
);
200214
} else {
201215
tracing::info!(
202-
"Using terminal block at blockchain height {} (storage height {}) as base for masternode sync (no pre-calculated data)",
203-
terminal_height,
204-
storage_height
216+
"Using terminal block at height {} as base for masternode sync (no pre-calculated data)",
217+
terminal_height
205218
);
206219
}
207220
Ok(terminal_height)
208221
} else {
209222
let msg = if has_precalculated_data {
210-
"Terminal block hash mismatch at blockchain height {} (storage height {}) (with pre-calculated data) - falling back to genesis"
223+
"Terminal block hash mismatch at height {} (with pre-calculated data) - falling back to genesis"
211224
} else {
212-
"Terminal block hash mismatch at blockchain height {} (storage height {}) (without pre-calculated data) - falling back to genesis"
225+
"Terminal block hash mismatch at height {} (without pre-calculated data) - falling back to genesis"
213226
};
214-
tracing::warn!(msg, terminal_height, storage_height);
227+
tracing::warn!(msg, terminal_height);
215228
Ok(0)
216229
}
217230
}
@@ -1053,21 +1066,10 @@ impl MasternodeSyncManager {
10531066
current_height: u32,
10541067
sync_base_height: u32,
10551068
) -> SyncResult<()> {
1056-
// Convert blockchain heights to storage heights
1057-
let storage_base_height = if base_height >= sync_base_height {
1058-
base_height - sync_base_height
1059-
} else {
1060-
0
1061-
};
1062-
1063-
let storage_current_height = if current_height >= sync_base_height {
1064-
current_height - sync_base_height
1065-
} else {
1066-
return Err(SyncError::InvalidState(format!(
1067-
"Current height {} is less than sync base height {}",
1068-
current_height, sync_base_height
1069-
)));
1070-
};
1069+
// When syncing from checkpoint, storage uses absolute blockchain heights
1070+
// No need to convert
1071+
let storage_base_height = base_height;
1072+
let storage_current_height = current_height;
10711073

10721074
// Verify the storage height actually exists
10731075
let storage_tip = storage
@@ -1086,7 +1088,7 @@ impl MasternodeSyncManager {
10861088

10871089
// Use the storage tip as the current height
10881090
let adjusted_storage_height = storage_tip;
1089-
let adjusted_blockchain_height = storage_tip + sync_base_height;
1091+
let adjusted_blockchain_height = storage_tip; // Storage already uses blockchain heights
10901092

10911093
// Update the heights to use what's actually available
10921094
// Don't recurse - just continue with adjusted values
@@ -1402,8 +1404,8 @@ impl MasternodeSyncManager {
14021404
.await
14031405
.map_err(|e| SyncError::Storage(format!("Failed to lookup target hash: {}", e)))?
14041406
{
1405-
// Convert storage height to blockchain height
1406-
let blockchain_target_height = storage_target_height + self.sync_base_height;
1407+
// Storage already uses blockchain heights when syncing from checkpoint
1408+
let blockchain_target_height = storage_target_height;
14071409
engine.feed_block_height(blockchain_target_height, target_block_hash);
14081410
tracing::debug!(
14091411
"Fed target block hash {} at blockchain height {} (storage height {})",
@@ -1437,8 +1439,8 @@ impl MasternodeSyncManager {
14371439
.await
14381440
.map_err(|e| SyncError::Storage(format!("Failed to lookup base hash: {}", e)))?
14391441
{
1440-
// Convert storage height to blockchain height
1441-
let blockchain_base_height = storage_base_height + self.sync_base_height;
1442+
// Storage already uses blockchain heights when syncing from checkpoint
1443+
let blockchain_base_height = storage_base_height;
14421444
engine.feed_block_height(blockchain_base_height, base_block_hash);
14431445
tracing::debug!(
14441446
"Fed base block hash {} at blockchain height {} (storage height {})",
@@ -1479,9 +1481,8 @@ impl MasternodeSyncManager {
14791481
{
14801482
// Only feed blocks at or after start_height to avoid redundant submissions
14811483
if storage_quorum_height >= storage_start_height {
1482-
// Convert storage height to blockchain height
1483-
let blockchain_quorum_height =
1484-
storage_quorum_height + self.sync_base_height;
1484+
// Storage already uses blockchain heights when syncing from checkpoint
1485+
let blockchain_quorum_height = storage_quorum_height;
14851486

14861487
// Check if this block hash is already known to avoid duplicate feeds
14871488
if !engine.block_container.contains_hash(&quorum.quorum_hash) {
@@ -1525,8 +1526,8 @@ impl MasternodeSyncManager {
15251526
)?;
15261527

15271528
for (storage_height, header) in headers {
1528-
// Convert storage height to blockchain height
1529-
let blockchain_height = storage_height + self.sync_base_height;
1529+
// Storage already uses blockchain heights when syncing from checkpoint
1530+
let blockchain_height = storage_height;
15301531
let block_hash = header.block_hash();
15311532

15321533
// Only feed if not already known

dash-spv/src/sync/sequential/mod.rs

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,17 @@ impl SequentialSyncManager {
406406
}
407407

408408
SyncPhase::DownloadingCFHeaders {
409+
current_height,
410+
target_height,
409411
..
410412
} => {
411-
tracing::info!("📥 Starting filter header download phase");
412-
413+
tracing::info!("📥 Starting filter headers download phase");
414+
tracing::info!(
415+
"🔍 [DEBUG] Filter headers phase: current={}, target={}",
416+
current_height,
417+
target_height
418+
);
419+
413420
// Get sync base height from header sync
414421
let sync_base_height = self.header_sync.get_sync_base_height();
415422
if sync_base_height > 0 {
@@ -419,23 +426,57 @@ impl SequentialSyncManager {
419426
);
420427
self.filter_sync.set_sync_base_height(sync_base_height);
421428
}
422-
423-
// Check if filter sync actually started
424-
let sync_started = self.filter_sync.start_sync_headers(network, storage).await?;
425-
426-
if !sync_started {
427-
// No peers support compact filters or already up to date
428-
tracing::info!("Filter header sync not started (no peers support filters or already synced)");
429-
// Transition to next phase immediately
430-
self.transition_to_next_phase(storage, "Filter sync skipped - no peer support")
431-
.await?;
432-
// Return true to indicate we transitioned and can continue execution
429+
430+
// Check if we need to request filter headers
431+
if current_height < target_height {
432+
// For checkpoint sync, we need to convert target height to storage height
433+
let sync_base_height = self.header_sync.get_sync_base_height();
434+
let storage_height = if sync_base_height > 0 && *target_height > sync_base_height {
435+
target_height - sync_base_height
436+
} else {
437+
*target_height
438+
};
439+
440+
tracing::info!(
441+
"🔍 [DEBUG] Getting header at storage height {} (blockchain height {})",
442+
storage_height,
443+
target_height
444+
);
445+
446+
// Get the stop hash for the target height
447+
let stop_hash = if let Some(header) = storage.get_header(storage_height).await
448+
.map_err(|e| SyncError::Storage(format!("Failed to get header at {}: {}", storage_height, e)))? {
449+
header.block_hash()
450+
} else {
451+
tracing::error!("No header found at storage height {} (blockchain height {})", storage_height, target_height);
452+
self.transition_to_next_phase(storage, "No header at target height").await?;
453+
return Ok(true);
454+
};
455+
456+
// Request filter headers
457+
let start_height = current_height + 1;
458+
self.filter_sync.request_filter_headers(
459+
network,
460+
start_height,
461+
stop_hash,
462+
).await?;
463+
464+
tracing::info!(
465+
"📡 Requested filter headers from {} to {} (stop hash: {})",
466+
start_height,
467+
target_height,
468+
stop_hash
469+
);
470+
} else {
471+
tracing::info!("Filter headers already synced, transitioning to next phase");
472+
self.transition_to_next_phase(storage, "Filter headers already synced").await?;
433473
return Ok(true);
434474
}
475+
435476
// Return false to indicate we need to wait for messages
436477
return Ok(false);
437478
}
438-
479+
439480
SyncPhase::DownloadingFilters {
440481
..
441482
} => {
@@ -1046,59 +1087,28 @@ impl SequentialSyncManager {
10461087

10471088
let previous_phase = std::mem::discriminant(&self.current_phase);
10481089

1049-
// Execute the current phase with special handling
1050-
match &self.current_phase {
1051-
SyncPhase::DownloadingMnList {
1052-
..
1053-
} => {
1054-
// Special handling for masternode sync that might already be complete
1055-
let sync_result = self.execute_current_phase_internal(network, storage).await?;
1056-
if !sync_result {
1057-
// Phase indicated it needs to wait for messages
1058-
break;
1059-
}
1060-
}
1061-
_ => {
1062-
// Normal execution
1063-
self.execute_current_phase_internal(network, storage).await?;
1064-
}
1090+
// Execute the current phase
1091+
let continue_execution = self.execute_current_phase_internal(network, storage).await?;
1092+
1093+
if !continue_execution {
1094+
// Phase indicated it needs to wait for messages
1095+
tracing::info!("🔍 [DEBUG] Phase {} needs to wait for messages, breaking execute loop",
1096+
self.current_phase.name());
1097+
break;
10651098
}
10661099

10671100
let current_phase_discriminant = std::mem::discriminant(&self.current_phase);
10681101

10691102
// If we didn't transition to a new phase, we're done
10701103
if previous_phase == current_phase_discriminant {
1104+
tracing::info!("🔍 [DEBUG] Phase didn't change, breaking execute loop");
10711105
break;
10721106
}
1073-
1074-
// If we reached a phase that needs network messages or is complete, stop
1075-
match &self.current_phase {
1076-
SyncPhase::DownloadingHeaders {
1077-
..
1078-
}
1079-
| SyncPhase::DownloadingMnList {
1080-
..
1081-
}
1082-
| SyncPhase::DownloadingCFHeaders {
1083-
..
1084-
}
1085-
| SyncPhase::DownloadingFilters {
1086-
..
1087-
}
1088-
| SyncPhase::DownloadingBlocks {
1089-
..
1090-
} => {
1091-
// These phases need to wait for network messages
1092-
break;
1093-
}
1094-
SyncPhase::FullySynced {
1095-
..
1096-
}
1097-
| SyncPhase::Idle => {
1098-
// We're done
1099-
break;
1100-
}
1101-
}
1107+
1108+
tracing::info!("🔍 [DEBUG] Phase changed to {}, continuing execution loop",
1109+
self.current_phase.name());
1110+
1111+
// Continue looping to execute the new phase
11021112
}
11031113

11041114
Ok(())

0 commit comments

Comments
 (0)