Griefing vector through fork handling in btclightclient
Description
The btclightclient module processes Bitcoin block headers submitted by reporters to maintain an up-to-date view of the Bitcoin main chain. However, a scenario exists where submitting a batch of headers that includes already processed blocks can trigger unnecessary fork-handling logic, leading to increased computational and storage overhead.
Below is an example scenario.
Assume the current BTC main chain is Block A → Block B → Block C → Block D. The btclightclient module currently recognizes Block C as its
currentTip
.Normally, a reporter would submit only Block D to extend the chain. However, if a reporter submits Blocks A, B, C, and D, the fork-handling mechanism is unnecessarily triggered.
The logic at
handleFork
↗ executes, and the already processed blocks (A, B, C) are redundantly processed.This unnecessary processing results in additional gas consumption, increased database reads and writes, and an increased workload on
handleInsertResult
, potentially causing a DOS when processing large headers.
Due to the gas-refund mechanism, the reporter does not bear the cost of this unnecessary computation, enabling griefing attacks at little expense.
Impact
Reprocessing already known headers results in redundant computations and storage operations, increasing network overhead and degrading performance. Additionally, a malicious reporter could exploit this by repeatedly submitting large headers with redundant data, consuming processing resources unnecessarily and potentially leading to a DOS attack that slows down network operations.
Recommendations
Before processing, verify whether the firstHeaderOfExtensionChain
has already been processed, and reject the batch if it has. This ensures that only new portions of a fork are accepted, preventing redundant execution of previously processed headers. Additionally, limit gas refunds for large-header submissions to discourage excessive and unnecessary reporting.
Remediation
This issue has been acknowledged by Babylon Labs, and a fix was implemented in commit 6b348844↗.
This was remediated by adding logic that rejects forks if their first header is already known.