[#HeadersSyncState]
= HeadersSyncState
:mrdocs:

HeadersSyncState&colon;

== Synopsis

Declared in `&lt;headerssync&period;h&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
class HeadersSyncState;
----

== Description

We wish to download a peer&apos;s headers chain in a DoS&hyphen;resistant way&period;

The Bitcoin protocol does not offer an easy way to determine the work on a peer&apos;s chain&period; Currently, we can query a peer&apos;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&period; If a peer&apos;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 &hyphen;&hyphen; by being above our anti&hyphen;DoS minimum&hyphen;chain&hyphen;work threshold &hyphen;&hyphen; before we commit to storing those headers in memory&period; Otherwise, it would be cheap for an attacker to waste all our memory by serving us low&hyphen;work headers (particularly for a new node coming online for the first time)&period;

To prevent memory&hyphen;DoS with low&hyphen;work headers, while still always being able to reorg to whatever the most&hyphen;work chain is, we require that a chain meet a work threshold before committing it to memory&period; We can do this by downloading a peer&apos;s headers twice, whenever we are not sure that the chain has sufficient work&colon;

* In the first download phase, called pre&hyphen;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&hyphen;of&hyphen;work)&period;

* 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&period;

To prevent an attacker from using (eg) the honest chain to convince us that they have a high&hyphen;work chain, but then feeding us an alternate set of low&hyphen;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&colon;

* In phase 1 (presync), store 1 bit (using a salted hash function) for every N headers that we see&period; With a reasonable choice of N, this uses relatively little memory even for a very long chain&period;

* 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&period; 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&hyphen;peer storage)&period;

== Types

[cols="1,4"]
|===
| Name| Description
| xref:HeadersSyncState/ProcessingResult.adoc[`ProcessingResult`] 
| Result data structure for ProcessNextHeaders&period;
|===


== Enums

[cols="1,4"]
|===
| Name| Description
| xref:HeadersSyncState/State.adoc[`State`] 
| Phase of the download&hyphen;twice headers synchronization&period;
|===


== Member Functions

[cols="1,4"]
|===
| Name| Description
| xref:HeadersSyncState/2constructor.adoc[`HeadersSyncState`]         [.small]#[constructor]#
| Construct a HeadersSyncState object representing a headers sync via this download&hyphen;twice mechanism)&period;
| xref:HeadersSyncState/2destructor.adoc[`&#126;HeadersSyncState`] [.small]#[destructor]#
| Destroys the sync state, discarding any buffered commitments and headers&period;
| xref:HeadersSyncState/GetPresyncHeight.adoc[`GetPresyncHeight`] 
| Return the height reached during the PRESYNC phase
| xref:HeadersSyncState/GetPresyncTime.adoc[`GetPresyncTime`] 
| Return the block timestamp of the last header received during the PRESYNC phase&period;
| xref:HeadersSyncState/GetPresyncWork.adoc[`GetPresyncWork`] 
| Return the amount of work in the chain received during the PRESYNC phase&period;
| xref:HeadersSyncState/GetState.adoc[`GetState`] 
| Return the current state of our download
| xref:HeadersSyncState/NextHeadersRequestLocator.adoc[`NextHeadersRequestLocator`] 
| Issue the next GETHEADERS message to our peer&period;
| xref:HeadersSyncState/ProcessNextHeaders.adoc[`ProcessNextHeaders`] 
| Process a batch of headers, once a sync via this mechanism has started
|===


== Protected Data Members

[cols="1,4"]
|===
| Name| Description
| xref:HeadersSyncState/m_commit_offset.adoc[`m&lowbar;commit&lowbar;offset`] 
| The (secret) offset on the heights for which to create commitments&period;
|===



[.small]#Created with https://www.mrdocs.com[MrDocs]#
