HeadersSyncState:
Synopsis
Declared in <headerssync.h>
class HeadersSyncState;
Description
We wish to download a peer's headers chain in a DoS‐resistant way.
The Bitcoin protocol does not offer an easy way to determine the work on a peer's chain. Currently, we can query a peer's headers by using a GETHEADERS message, and our peer can return a set of up to 2000 headers that connect to something we know. If a peer's chain has more than 2000 blocks, then we need a way to verify that the chain actually has enough work on it to be useful to us ‐‐ by being above our anti‐DoS minimum‐chain‐work threshold ‐‐ before we commit to storing those headers in memory. Otherwise, it would be cheap for an attacker to waste all our memory by serving us low‐work headers (particularly for a new node coming online for the first time).
To prevent memory‐DoS with low‐work headers, while still always being able to reorg to whatever the most‐work chain is, we require that a chain meet a work threshold before committing it to memory. We can do this by downloading a peer's headers twice, whenever we are not sure that the chain has sufficient work:
-
In the first download phase, called pre‐synchronization, we can calculate the work on the chain as we go (just by checking the nBits value on each header, and validating the proof‐of‐work).
-
Once we have reached a header where the cumulative chain work is sufficient, we switch to downloading the headers a second time, this time processing them fully, and possibly storing them in memory.
To prevent an attacker from using (eg) the honest chain to convince us that they have a high‐work chain, but then feeding us an alternate set of low‐difficulty headers in the second phase, we store commitments to the chain we see in the first download phase that we check in the second phase, as follows:
-
In phase 1 (presync), store 1 bit (using a salted hash function) for every N headers that we see. With a reasonable choice of N, this uses relatively little memory even for a very long chain.
-
In phase 2 (redownload), keep a lookahead buffer and only accept headers from that buffer into the block index (permanent memory usage) once they have some target number of verified commitments on top of them. With this parametrization, we can achieve a given security target for potential permanent memory usage, while choosing N to minimize memory use during the sync (temporary, per‐peer storage).
Types
Name |
Description |
Result data structure for ProcessNextHeaders. |
Enums
Name |
Description |
Phase of the download‐twice headers synchronization. |
Member Functions
Name |
Description |
|
Construct a HeadersSyncState object representing a headers sync via this download‐twice mechanism). |
|
Destroys the sync state, discarding any buffered commitments and headers. |
Return the height reached during the PRESYNC phase |
|
Return the block timestamp of the last header received during the PRESYNC phase. |
|
Return the amount of work in the chain received during the PRESYNC phase. |
|
Return the current state of our download |
|
Issue the next GETHEADERS message to our peer. |
|
Process a batch of headers, once a sync via this mechanism has started |
Protected Data Members
Name |
Description |
The (secret) offset on the heights for which to create commitments. |
Created with MrDocs