0

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 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?

2 Answers 2

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.

4
  • Is this low difficulty chain filter really just tied to assumevalid? What if I run Bitcoin Core with -assumevalid=0? Jun 27 at 6:30
  • No, it has its own option, -minimumchainwork.
    – Andrew Chow
    Jun 27 at 14:21
  • I see, thanks! I assume other node implementation also use a hardcoded minimum chain work? Jun 27 at 16:16
  • 1
    @VojtěchStrnad I would not necessarily assume that and would check each individually.
    – Andrew Chow
    Jun 28 at 1:24
2

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.