I still believe that having the node download blocks randomly can lead to a poor sync experience, and this problem is likely to become more noticeable over time, especially for new nodes with little or no history. My reasoning is the following:
-
The probability that a node randomly downloads blocks that can be applied soon to the already validated blockchain state decreases as the chain grows. For example, if the node is currently synced to block height 1000, it does not help to have blocks 1002–11000 downloaded if block 1001 is still missing, since that missing block is what would allow those 10k downloaded blocks (~10 GB) to become usable.
-
As the blockchain tip height increases, the node must probabilistically download more blocks before receiving one that can actually be applied to the current state. In other words, nodes in the future will spend more time downloading just to apply the next block than nodes do today.
-
Every downloaded block that cannot yet be applied represents work that could instead have been used to advance the synced node state and apply UTXO records, bringing the wallet balance closer to its final state.
-
The more blocks the node downloads without validating and syncing them promptly, the greater the risk that this work will be lost if the node crashes or the user restarts their computer, at least on Windows.
The change in #881 is very welcome, as it makes it possible to define the directory for downloaded blocks so they are not discarded after a computer restart, at least on Windows. That said, the default behavior is still an important part of the overall user experience. It may be worth considering whether the software should work in a convenient and intuitive way for ordinary users as well, without requiring familiarity with multiple CLI arguments.
Ideally, from UX perspective:
- Downloaded blocks are immediately or soon applied to the synced state.
With reference to discussion #827:
- Download blocks in order. Two issues: a) Starting where? A priori you might be syncing across a reorganization and the block you think you're already synced to when sync mode starts is not canonical any more. b) Duplicate work. When you're downloading from multiple peers, you don't want to ask the peers for the same block. That's a very poor use of network resources. Moreover, the counterparty serving blocks might be in sync mode themselves and incapable of sending you specific blocks because they don't have them. In this case you want to continue by downloading what you can.
Fully agree that the node should not ask for the same blocks from peers, unless there are problems.
I'd be curious to hear what the downsides would be of using the sync method below. Note: this was drafted with AI, it is high-level, and it was generated without having the full context of Neptune Cash architecture.
Node sync method
Sync method that aims for three things at once:
- Apply good blocks quickly.
- Stay correct across reorgs.
- Avoid being dragged around by bad peers.
Steps
1. Sync headers first
- Collect headers from multiple peers.
- Validate header linkage and consensus rules.
- Build a fork tree and choose the branch with the most cumulative work.
- Find the last common ancestor with the local chain.
2. Download block bodies near the execution frontier
- Keep a small window of missing blocks just ahead of the last applied block.
- Assign non-overlapping ranges to peers.
- Avoid duplicate requests unless a needed block times out.
3. Validate and apply immediately
- When a block arrives, validate it.
- If its parent is already applied, execute and commit it at once.
- Then keep applying any already-buffered children in order.
4. Handle stalls gracefully
- If one missing frontier block is delayed, reassign it to another peer.
- Meanwhile continue downloading later blocks within the window.
- As soon as the gap is filled, apply buffered blocks in sequence.
5. Handle reorgs safely
- If a better branch appears, find the fork point.
- If needed, roll back to that point and replay the stronger branch.
- Keep recent undo data or snapshots to make rollback cheap.
6. Defend against malicious peers
- Never trust one peer alone for chain choice.
- Penalize invalid data heavily.
- Penalize timeouts or missing data lightly.
- Limit side-branch/orphan buffering to prevent DoS.
I still believe that having the node download blocks randomly can lead to a poor sync experience, and this problem is likely to become more noticeable over time, especially for new nodes with little or no history. My reasoning is the following:
The probability that a node randomly downloads blocks that can be applied soon to the already validated blockchain state decreases as the chain grows. For example, if the node is currently synced to block height 1000, it does not help to have blocks 1002–11000 downloaded if block 1001 is still missing, since that missing block is what would allow those 10k downloaded blocks (~10 GB) to become usable.
As the blockchain tip height increases, the node must probabilistically download more blocks before receiving one that can actually be applied to the current state. In other words, nodes in the future will spend more time downloading just to apply the next block than nodes do today.
Every downloaded block that cannot yet be applied represents work that could instead have been used to advance the synced node state and apply UTXO records, bringing the wallet balance closer to its final state.
The more blocks the node downloads without validating and syncing them promptly, the greater the risk that this work will be lost if the node crashes or the user restarts their computer, at least on Windows.
The change in #881 is very welcome, as it makes it possible to define the directory for downloaded blocks so they are not discarded after a computer restart, at least on Windows. That said, the default behavior is still an important part of the overall user experience. It may be worth considering whether the software should work in a convenient and intuitive way for ordinary users as well, without requiring familiarity with multiple CLI arguments.
Ideally, from UX perspective:
With reference to discussion #827:
Fully agree that the node should not ask for the same blocks from peers, unless there are problems.
I'd be curious to hear what the downsides would be of using the sync method below. Note: this was drafted with AI, it is high-level, and it was generated without having the full context of Neptune Cash architecture.
Node sync method
Sync method that aims for three things at once:
Steps
1. Sync headers first
2. Download block bodies near the execution frontier
3. Validate and apply immediately
4. Handle stalls gracefully
5. Handle reorgs safely
6. Defend against malicious peers