owned this note
owned this note
Published
Linked with GitHub
# Justification widtholding attacks
Consider the following diagram
![](https://i.imgur.com/Ne44waS.png)
- At the beginning of Epoch 11, Epoch 10 has been justified. The attacker holds the last few slots to propose (in orange) and Epoch 11 has not been justified when is his turn to propose.
- The attacker does have enough votes to justify 11 within his blocks, but he does not release any of them.
- The Network continues building on the canonical chain, as if some validators were offline. At the beginning of Epoch 12 the `store.justified_checkpoint` points to Epoch 10, as 11 has not been justified.
- The network eventually will justify Epoch 11 within Epoch 12, but this will not be realized until the epoch transition into 13.
In this conditions, assuming pulled tips have been implemented, releases his blocks:
![](https://i.imgur.com/PMOjc7L.png)
A proposer for the next slot (block A) will have to build on top of the attacker's block, since the unrealized justification of these blocks is Epoch 11, which is higher than the current store's justification of Epoch 10 and higher than the previous head block B justification, which is also Epoch 10.
Notice that block A has realized justification Epoch 11, and block B has unrealized justification Epoch 11, but realized justification Epoch 10.
The following variation due to Danny Ryan does not even need pulled tips. In the same situation as in the first diagram, the attacker uses a block in Epoch 12 to realize his attack:
![](https://i.imgur.com/CBYWYFK.png)
He proposes a block in epoch 12 based on his own blocks (that he is releasing at the same time) and again the next proposer is faced with a head that has realized justification Epoch 11 vs one that has realized justification Epoch 10, but unrealized justification Epoch 11.
## Probability of this happening
This attack has been considered quite possible, here is a graph with the number of days needed in average as a function of the attacker's stake, in order to set up this attack
![](https://i.imgur.com/55Hx8az.jpg)
Any pool with over 15% of the stake can reliably consider this attack.
## A proposed fix
Modify `filter_block_tree` to use unrealized justification in the current epoch as well, only when the realized justification is lower than the store's realized justification:
```python=
...
correct_justified = (
store.justified_checkpoint.epoch == GENESIS_EPOCH
or store.u_justified_checkpoints[block_root] == store.justified_checkpoint
or head_state.current_justified_checkpoint == store.justified_checkpoint
)
correct_finalized = (
...
```
With these conditions, a proposer of block `A`, the first after the attack is realized, will see both `B` and the attacker's block as viable for head. Reorging back to the canonical chain because of LMD weight. This renders the attack inneffective since the attacker can only fork blocks in epoch 12 that have not justified Epoch 11 yet.
It behaves like the *early UJF* solution discussed by Aditya Asgaonkar, but only *on demand*, that is, when other block has already realized the justification on store, therefore it does not incurr in the problem of allowing for easy 1-block reorgs.
Danny is worried about possible split views in all solutions he has seen to this problem, I cannot see them right now.