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

Verge Attack, February 15, 2021 #68

Open
zawy12 opened this issue Feb 17, 2021 · 1 comment
Open

Verge Attack, February 15, 2021 #68

zawy12 opened this issue Feb 17, 2021 · 1 comment

Comments

@zawy12
Copy link
Owner

zawy12 commented Feb 17, 2021

Update: the following attack worked because they were using chain height instead of work to decide the tip.

@ocminer sent me his node's log file. It shows the attacker did not need any significant hashrate. He did only 10 blocks worth of hashing to get the 567,000 blocks. This shows there's some problem (like maybe a Sybil attack on peer time) in how nodes were deciding which chain to respect. The miner just started working on a block that was dated July 7, 2020, and used "long" timestamps on 540 blocks to reduce the difficulty to basically 0 and then mined up until present day with evenly-spaced solvetimes, slightly longer than the target 30 seconds which kept the difficulty low. He ended up 1300 blocks ahead of the competing chain. It took ocminer's node 10 minutes to reorg.

The following is a summary of the details I could see from the node's log file.

At 2021-02-15 00:13:18 the node started rolling back the chain from 4749908. log2_work=87.733766
This went on for 4 minutes until 4186331 which was solved on 2020-07-07 08:48:45 with log2_work= 86.712616
Attacker's chain begins the next block 4186332 with a timestamp about 9 minutes 30 seconds later.
Attacker does these "10 minute" fake timestamps (I know they are fake because they are not random) for 540 blocks ( 2.5 days later according to the fake timestamps when it is only 10 blocks worth of normal work due to the difficulty dropping fast). This greatly lowered difficulty to basically zero. The log2_work increased only 0.000020 to 86.712636. This is only 10 blocks of work at the normal hashrate, so if he had 1% network hashrate it would take 8 hours.
Then attacker begins to use 33 second timestamps begin for 566,460 blocks. This keeps difficulty constant at the very low level.

At Feb 15, 00:22:48 (10 minutes after the beginning of the roll-back and reorg) a non-attacking miner found 4749910 on top of the attacker's chain. The attacker's timestamps on his chain were showing Feb 12 06:29:10. A couple minutes later another miner found 4749918 on top of the attacker's 4749917 block. But attacker's blocks kept going and orphaned these two honest blocks.

At 4750790 the attacker's timestamp was 2021-02-12 15:03:16. The timestamps then switched from 33 second timestamps to 28 minutes apart. This went on for 111 blocks until 4750901 ending with a timestamp 2021-02-14 18:00:05. Then timestamps were about 80 seconds apart (again, not random, so i know they are fake). This went on until 4751234 which is when the timestamps started matching the node's time 2021-02-15 00:23:31. This was the attacker's last block, or a few after that. These last two stages may have just been trying to get the timestamps back to current time. Attacker could have extended the chain a million more blocks in a short time. Timestamps were about 1 second apart for about 7 blocks when the data stops.

So attacker's chain was ultimately about 1300 blocks ahead at the end of the 10 minute reorg. His chain work was only effectively 10 blocks ahead of what chain work was on July 7, so it was 567k blocks behind on chain work. So the reorg was not based on chain work.

Block 4751251 at 00:27:46 was the first block who's timestamp matched actual time and started having random solvetimes.

When the attacker's chain reached 4749909, which is 1 block after public chain when the roll back started, every block was followed by this warning:

CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain. Chain state database corruption likely.

This comes from:
https://github.com/vergecurrency/verge/blob/43a625b19ea2c340df2e643d0f020ceac4d9b445/src/validation.cpp#L1281

The "invalid" chain appears to be the reverted public chain because it is > the chainWork of attacker's block plus 6 times that tip's difficulty. This is the (edited) conditional sequence that least to the above warning:

   if (pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6)
    {
        if (!GetfLargeWorkForkFound() && pindexBestForkBase)
                            {  'Warning: Large-work fork detected, forking after block "          }
        if (pindexBestForkTip && pindexBestForkBase)
                   {  " Warning: Large valid fork found.  forking the chain at height %d (%s) 
                     lasting to height %d (%s).  Chain state database corruption likely."        }
        else
        {   "Warning: Found invalid chain at least ~6 blocks longer than our best chain. Chain state database corruption likely."  ]
@ocminer
Copy link

ocminer commented Feb 18, 2021

Thanks a lot ! Good work !

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

No branches or pull requests

2 participants