Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor BlockHeader #228

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Refactor BlockHeader #228

wants to merge 2 commits into from

Conversation

lukechampine
Copy link
Member

This unifies v1 and v2 block headers and promotes BlockHeader from gateway to types. It also changes how V2 block IDs are computed.

I had previously omitted the ParentID from the v2 block "header," because it is incorporated into the Commitment field (via the hash of the parent consensus.State). This left the first 32 bytes of the 80-byte hash preimage unused, so I filled them with a distinguisher string.

However, after reflecting on how headers are actually used in the Syncer, I think it's better to include the ParentID after all, even if it's slightly redundant and not strictly necessary. Here's my reasoning, in the form of a dialogue:

  • 🤔 Foo: Imagine a peer sends you a v2 header, claiming that they have found the next block. You hash the header and verify that, indeed, it meets the proof-of-work target. You therefore stop mining the current block and begin mining the next one. Unbeknownst to you, this header does not attach to the old block! Now you are wasting hashrate until you detect this deception. If the header contained the ParentID, you could check that it matched your current block before abandoning it.
  • 🤨 Bar: Including the ParentID doesn't prevent this class of attack, because the purported block could be invalid for other reasons that aren't detectable from the header alone. For example, it could have missing signatures. Moreover, this attack requires the attacker to expend a lot of hashrate; why wouldn't they use that hashrate to mine a valid block instead?
  • 🤔 Foo: Aha, but that's where the ParentID is different! You don't need to expend a lot of hashrate mining a purposefully-invalid block; instead, you can reuse the header of a recently-mined block. That header will (probably) still have sufficient proof-of-work to meet the current target, so it will pass the initial validation check.
  • 🤨 Bar: Okay, but one of the first checks you perform when receiving a relayed header is "have I seen this block before?" So if you try to cheat by reusing a recent block, it will simply be ignored.
  • 🤔 Foo: ...fine, granted. But there's basically no downside to include the ParentID anyway. We weren't using that space anyway (but we need to preserve it, for miner compatibility), it's occasionally useful, and you don't need to twist your brain into knots convincing yourself that the system is still secure without it.
  • 🤨 Bar: ...sure, whatever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

1 participant