<p>Block downloading proceeds in two phases. While they do happen mostly concurrently, it's easier to think of them as separate steps:</p>
<ul>
<li><p>First, block headers are downloaded from peers, and verified for syntactic correctness, and proof-of-work according to the difficulty adjustment rules. All headers today (june 2022) are less than 60 MiB together.</p>
</li>
<li><p>The total amount of work in every headers chain received is computed (roughly equal to the sum of the difficulties of the blocks in it), as a metric for how much work was needed to produce it. This metric cannot be faked. Once this value is high enough(*), the blocks along that chain are fetched from possible multiple peers simultaneously, and verified in order of height, once they arrive.</p>
</li>
</ul>
<p>(*) Now, what is enough work?</p>
<ul>
<li>First of all, if we already have a chain of blocks (not just headers) that were validated and accepted, we only download blocks along headers chains whose total work is at least as much as the total work in the currently accepted chain. This is because any headers chain whose total work is less than our accepted chain will clearly never actually beat our currently accepted chain.</li>
<li>Secondly, during the initial synchronization, when there is no (long) accepted chain already, a threshold &quot;minchainwork&quot; (configurable, but the default is hardcoded in the Bitcoin Core software, and updated on every release) is used. No blocks are downloaded along a chain whose total work isn't at least as much as minchainwork.</li>
</ul>
<p>So if an attacker were to construct a low-difficulty stale chain with lots of expensive signature checks, then nodes might end up downloading and verifying the corresponding headers. But those headers would never beat minchainwork (on initial sync), or the real already-accepted chain (on later sync), and thus the blocks along it would never be downloaded even, let alone validated.</p>

CC BY-SA 4.0
2022-06-29T03:50:22.333Z
2022-06-29T03:50:22.333Z
Pieter Wuille
<p>Bitcoin determines the best chain by choosing the one with the most work. As &quot;work&quot; is a bit nebulous, it is specifically determined using a metric called &quot;chainwork&quot;. Chainwork is just the expected number of hashes required to produce all of the blocks in the chain. It is calculated by computing the expected number of hashes required to produce the block, and that is added to the chainwork of the previous block. As such, chainwork can only increase.</p>
<p>Bitcoin Core's assumevalid mechanism also includes a minimum chainwork value. This is set to be the chainwork of the assumevalid block. Any chain that Bitcoin Core accepts will have to have a chainwork greater than this value.</p>
<p>With the minimum chainwork, Bitcoin Core can filter out low difficulty chains. As it does headers first sync, it will download the block headers for the low work chain, see that its chainwork is less than the minimum chainwork, and not download the blocks for that chain. It will additionally disconnect the peer that advertised that chain to it.</p>

CC BY-SA 4.0
2022-06-27T06:30:32.197Z
Is this low difficulty chain filter really just tied to assumevalid? What if I run Bitcoin Core with -assumevalid=0?
Vojtěch Strnad
CC BY-SA 4.0
2022-06-27T14:21:01.077Z
No, it has its own option, `-minimumchainwork`.
Ava Chow
CC BY-SA 4.0
2022-06-27T16:16:24.113Z
I see, thanks! I assume other node implementation also use a hardcoded minimum chain work?
Vojtěch Strnad
CC BY-SA 4.0
2022-06-28T01:24:06.620Z
@VojtěchStrnad I would not necessarily assume that and would check each individually.
Ava Chow
CC BY-SA 4.0
2022-06-27T03:38:12.983Z
2022-06-27T03:38:12.983Z
Ava Chow
<p>A DoS attack vector against a bitcoin node I haven't really seen mentioned anywhere is mining a stale chain in a low-difficulty era (say right after the genesis block), ideally with a lot of expensive operations like signature checks.</p>
<p><a href="https://bitcoin.stackexchange.com/a/93895/121614">This answer</a> mentions that in Bitcoin Core only blocks with &quot;a chance to be part of the best chain are actually downloaded and stored&quot;, how exactly is that chance quantified? And how do other node implementations deal with this attack vector?</p>

<bitcoin-core><nodes><attack><weaknesses><stale-block>
Mining stale low-difficulty blocks as a DoS attack
Vojtěch Strnad
# Mining stale low-difficulty blocks as a DoS attack

(Asked by: username_0 on 2022-06-27)

A DoS attack vector against a bitcoin node I haven't really seen mentioned anywhere is mining a stale chain in a low-difficulty era (say right after the genesis block), ideally with a lot of expensive operations like signature checks.

[This answer](https://bitcoin.stackexchange.com/a/93895/121614) mentions that in Bitcoin Core only blocks with "a chance to be part of the best chain are actually downloaded and stored", how exactly is that chance quantified? And how do other node implementations deal with this attack vector?

**Tags:** bitcoin-core, nodes, attack, weaknesses, stale-block


---

## 2 answers

### Answer by username_1 on 2022-06-29. Score: 3 | Accepted answer

Block downloading proceeds in two phases. While they do happen mostly concurrently, it's easier to think of them as separate steps:

* First, block headers are downloaded from peers, and verified for syntactic correctness, and proof-of-work according to the difficulty adjustment rules. All headers today (june 2022) are less than 60 MiB together.
* The total amount of work in every headers chain received is computed (roughly equal to the sum of the difficulties of the blocks in it), as a metric for how much work was needed to produce it. This metric cannot be faked. Once this value is high enough(\*), the blocks along that chain are fetched from possible multiple peers simultaneously, and verified in order of height, once they arrive.

(\*) Now, what is enough work?

* First of all, if we already have a chain of blocks (not just headers) that were validated and accepted, we only download blocks along headers chains whose total work is at least as much as the total work in the currently accepted chain. This is because any headers chain whose total work is less than our accepted chain will clearly never actually beat our currently accepted chain.
* Secondly, during the initial synchronization, when there is no (long) accepted chain already, a threshold "minchainwork" (configurable, but the default is hardcoded in the Bitcoin Core software, and updated on every release) is used. No blocks are downloaded along a chain whose total work isn't at least as much as minchainwork.

So if an attacker were to construct a low-difficulty stale chain with lots of expensive signature checks, then nodes might end up downloading and verifying the corresponding headers. But those headers would never beat minchainwork (on initial sync), or the real already-accepted chain (on later sync), and thus the blocks along it would never be downloaded even, let alone validated.


---

### Answer by username_2 on 2022-06-27. Score: 3

Bitcoin determines the best chain by choosing the one with the most work. As "work" is a bit nebulous, it is specifically determined using a metric called "chainwork". Chainwork is just the expected number of hashes required to produce all of the blocks in the chain. It is calculated by computing the expected number of hashes required to produce the block, and that is added to the chainwork of the previous block. As such, chainwork can only increase.

Bitcoin Core's assumevalid mechanism also includes a minimum chainwork value. This is set to be the chainwork of the assumevalid block. Any chain that Bitcoin Core accepts will have to have a chainwork greater than this value.

With the minimum chainwork, Bitcoin Core can filter out low difficulty chains. As it does headers first sync, it will download the block headers for the low work chain, see that its chainwork is less than the minimum chainwork, and not download the blocks for that chain. It will additionally disconnect the peer that advertised that chain to it.

> **Comments:**
> **username_0**: Is this low difficulty chain filter really just tied to assumevalid? What if I run Bitcoin Core with -assumevalid=0?  
> **username_2**: No, it has its own option, `-minimumchainwork`.  
> **username_0**: I see, thanks! I assume other node implementation also use a hardcoded minimum chain work?  
> **username_2**: @username_0 I would not necessarily assume that and would check each individually.  

---

