The XVG Verge Chain Reorg Attack

ocminer
8 min readFeb 17, 2021

On February 15th 2021 at around 0:15 UTC the XVG Verge network suffered a major chain reorganization from block 4749908 back to block 4186331 (at least). 563577 Blocks from the official main chain were rolled back and probably replaced by blocks from the malicious chain.

Here’s a logfile from a daemon of a pool connected to the XVG network shortly before, while and after the attack:

2021–02–15T00:10:53Z UpdateTip: new best=bb189253b440d1456215f596e0bfa6ee45edfc126d2ab6aadbbf3cbab27938a7 height=4749904 version=0x00001004 log2_work=87.733766 tx=9409729 date=’2021–02–15T00:10:45Z’ progress=0.999999 cache=1.8MiB(10198txo)
2021–02–15T00:10:53Z FindStealthTransactions() tx: 9dfdb3b7b4b3a2450d126aec114e46087b382d0a850726d78b49f66403c55ffa
2021–02–15T00:10:53Z Disconnecting outbound peer 278245 for old chain, best known block = 720a9c43186031eaa328e38c44d50c586b66753dc5964379916ccb60f9ebb8bb
2021–02–15T00:10:53Z CreateNewBlock(): block weight: 796 txs: 0 fees: 0 sigops 400
2021–02–15T00:10:57Z FindStealthTransactions() tx: dc7936f856f9b406066a73f000d04bbf273abc1a024381a11570df8326553203
2021–02–15T00:10:59Z CreateNewBlock(): block weight: 1580 txs: 1 fees: 100000 sigops 404
2021–02–15T00:11:48Z FindStealthTransactions() tx: 7c450c3c1dc141bbbd61ebe2097fc235fee7a8add9bd851c508c9a7d191bd760
2021–02–15T00:11:48Z CreateNewBlock(): block weight: 3084 txs: 2 fees: 200000 sigops 412
2021–02–15T00:11:55Z Socks5() connect to 91.65.103.62:21102 failed: general failure
2021–02–15T00:12:00Z FindStealthTransactions() tx: 5eb10ea3ed081d66baf73182f8c0596f42bf62788c91bc6bb17d5c8bd29d31bb
2021–02–15T00:12:00Z CreateNewBlock(): block weight: 4004 txs: 3 fees: 300000 sigops 420
2021–02–15T00:12:17Z Socks5() connect to 98.115.147.74:21102 failed: general failure
2021–02–15T00:12:23Z UpdateTip: new best=e7e309a8e32b3b44fe42d92c4c78fcf90498e1ddfe4680e87072f92f176ec680 height=4749905 version=0x00001004 log2_work=87.733766 tx=9409730 date=’2021–02–15T00:12:16Z’ progress=0.999999 cache=1.8MiB(10202txo)
2021–02–15T00:12:23Z FindStealthTransactions() tx: 867182257182cee1b9278d06c9ad72c9e7ba8a54477f7fb97d8226feb22e7b64
2021–02–15T00:12:23Z CreateNewBlock(): block weight: 4004 txs: 3 fees: 300000 sigops 420
2021–02–15T00:12:31Z UpdateTip: new best=00000000000188f8d1e76ad1a92260665340ae6038e7b3833a0d470f3ba14f42 height=4749906 version=0x00000804 log2_work=87.733766 tx=9409731 date=’2021–02–15T00:12:23Z’ progress=0.999999 cache=1.8MiB(10203txo)
2021–02–15T00:12:31Z FindStealthTransactions() tx: 0b32b82adfa5d7f1d323d1d25bd6fd54afd63c59efe80c6ce83043e71b26547a
2021–02–15T00:12:31Z CreateNewBlock(): block weight: 4004 txs: 3 fees: 300000 sigops 420
2021–02–15T00:12:32Z UpdateTip: new best=0000000000007651820a1db634926c3e5c2827f0fb2cb0a6bc6cd6394c31feb4 height=4749907 version=0x00000804 log2_work=87.733766 tx=9409732 date=’2021–02–15T00:12:31Z’ progress=1.000000 cache=1.8MiB(10204txo)
2021–02–15T00:12:32Z FindStealthTransactions() tx: 1eeaf96def7adae5c8fdfd177c2dbc257f075f1175d526d36502e87d9b583850
2021–02–15T00:12:32Z CreateNewBlock(): block weight: 4004 txs: 3 fees: 300000 sigops 420
2021–02–15T00:12:59Z New outbound peer connected: version: 90001, blocks=4749907, peer=287491
2021–02–15T00:12:59Z Socks5() connect to 104.131.144.82:21102 failed: general failure
2021–02–15T00:13:18Z UpdateTip: new best=7436eb75e9409c0d290d7d743796d2b42ef214704d5dedbfb645a5d7fd92e53f height=4749908 version=0x00001004 log2_work=87.733766 tx=9409733 date=’2021–02–15T00:13:04Z’ progress=0.999999 cache=1.8MiB(10205txo)
2021–02–15T00:13:18Z FindStealthTransactions() tx: a4c58bdb80df25bc124f22294483ea4d2c1aca6fa833c6f090509ac74d5d3886
2021–02–15T00:13:18Z CreateNewBlock(): block weight: 4004 txs: 3 fees: 300000 sigops 420

Above you see some normal logfile entries, the daemon is just reporting new blocks as the come in and you can tell from the timestamps everything looks relatively normal, there’s about 30 seconds between the blocks which matches the target of XVG and every other block is also a different algo, maybe it be Lyra, Myriad-Groestl, X17 or scrypt.

Starting exactly at

2021–02–15T00:14:16Z UpdateTip: new best=0000000000007651820a1db634926c3e5c2827f0fb2cb0a6bc6cd6394c31feb4 height=4749907 version=0x00000804 log2_work=87.733766 tx=9409732 date=’2021–02–15T00:12:31Z’ progress=0.999989 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=00000000000188f8d1e76ad1a92260665340ae6038e7b3833a0d470f3ba14f42 height=4749906 version=0x00000804 log2_work=87.733766 tx=9409731 date=’2021–02–15T00:12:23Z’ progress=0.999988 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=e7e309a8e32b3b44fe42d92c4c78fcf90498e1ddfe4680e87072f92f176ec680 height=4749905 version=0x00001004 log2_work=87.733766 tx=9409730 date=’2021–02–15T00:12:16Z’ progress=0.999987 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=bb189253b440d1456215f596e0bfa6ee45edfc126d2ab6aadbbf3cbab27938a7 height=4749904 version=0x00001004 log2_work=87.733766 tx=9409729 date=’2021–02–15T00:10:45Z’ progress=0.999978 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=346344899005093d40a04ba737c8517f1f0fc7f65943929e246f44b12995109f height=4749903 version=0x00001804 log2_work=87.733766 tx=9409728 date=’2021–02–15T00:10:34Z’ progress=0.999976 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=216db9ad07b4918194f84747537d5794c811f2d0f26b26bbd3cb73c9079edb94 height=4749902 version=0x00005004 log2_work=87.733763 tx=9409727 date=’2021–02–15T00:10:13Z’ progress=0.999974 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=000000000005939953a918b76a102a748557d473e219d0a19cc86661ae835870 height=4749901 version=0x00000804 log2_work=87.733759 tx=9409725 date=’2021–02–15T00:09:59Z’ progress=0.999973 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=4d0728f23444841af0e7dc784a0791fc12006c6fe6a3ed189f68e10fae89ecba height=4749900 version=0x00001804 log2_work=87.733759 tx=9409724 date=’2021–02–15T00:09:45Z’ progress=0.999971 cache=1.8MiB(10205txo)
2021–02–15T00:14:16Z UpdateTip: new best=958de6db0bec69f43afb740c464c7258b7984e469296655771f3102685f0e0a6 height=4749899 version=0x00002004 log2_work=87.733756 tx=9409723 date=’2021–02–15T00:08:59Z’ progress=0.999966 cache=1.8MiB(10205txo)

The massive reorganization of blocks took place. Take notice of the block numbers counting reverse, which means those blocks substitute older blocks of the chain.

During this reorg the wallet becomes unresponsive as it maxes out CPU as the daemon tries to reorganize it’s transactions and keeps the blockchain uptodate:

2021–02–15T00:17:50Z WARNING: request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting

The reorg ends at block:

2021–02–15T00:17:49Z UpdateTip: new best=56d003fa0159b35c3b0334bd1c7f8f62b43d3ccb539bf01c698f5f249391b91f height=4186331 version=0x00001804 log2_work=86.712616 tx=8666560 date=’2020–07–07T08:48:45Z’ progress=0.310595 cache=82.7MiB(597854txo)

This means all transactions from exchanges, all blocks, all mining rewards in pools etc. in this range has been manipulated and been replaced by the attacking chain with own transactions.

During and after the attack the daemon is still reorganizing it’s database:

2021–02–15T00:22:50Z FindStealthTransactions() tx: be9d756168abdf8919bcce879d020f0998c412270b663857a20f8101da736f16
2021–02–15T00:22:50Z FindStealthTransactions() tx: 52044929c40f8b4c956ed26a30248843305adfafdb9428dc7a470222084edee4
2021–02–15T00:22:50Z FindStealthTransactions() tx: dc12500affdab29de891d07272a42f60bb4bf89a7cc0bc57bc125ebb42f54315
2021–02–15T00:22:50Z FindStealthTransactions() tx: cb60f4e69bee88c09ba9755721c7f3d8986e9d62e476040cef6752d21b6694cd
2021–02–15T00:22:50Z FindStealthTransactions() tx: 7a1cffeb0aca3375f7c4c7e28b80f68bd331b1ba43391c96087337f7a7fa1a51
2021–02–15T00:22:50Z FindStealthTransactions() tx: 4026943d18f5031634807b269158860bfaa56a695ed4fab8feeefe1f7a7e18d4
2021–02–15T00:22:50Z FindStealthTransactions() tx: 71b5797e24186716bb2ca9e7aee6ac1952f83f6e8bc4235085d32c48310b1515
2021–02–15T00:22:50Z FindStealthTransactions() tx: 31fc2bf80333712a6f8737e7c14b1558e6814c1490226708276c4ae5d38f3ba0
2021–02–15T00:22:50Z FindStealthTransactions() tx: 73b5129e6971d38315aa96251d47eab8e5379c33f610225c09f29f9ef7c6d59e
2021–02–15T00:22:50Z FindStealthTransactions() tx: f4f4a4e62eb930b1255c0c6fec1e73358f0546ea40d62fab10b00dc25360bed3
2021–02–15T00:22:50Z FindStealthTransactions() tx: 9aa15961c632e57c6965d19e122a39a9f74b5a41c8c3d9197ac372216fe5ebe8
2021–02–15T00:22:50Z FindStealthTransactions() tx: 7bbaf1617d151f5c24abaf1061865832003e4f3141a87e5fda23df18eb4a06a0
2021–02–15T00:22:50Z FindStealthTransactions() tx: ee462e4aaf21e33854ce6b210e1c5210cc8edd793f641da4e4a9881480f64aaa
2021–02–15T00:22:50Z FindStealthTransactions() tx: 847d1dff008c012687b36c55933be6232343d45ebba1932f144caab34801db75
2021–02–15T00:22:50Z FindStealthTransactions() tx: efcab538c59846014bec08a103d9cbda23336b1004bb77ef31cd436e1e839c98
2021–02–15T00:22:50Z FindStealthTransactions() tx: 22db5820538337ed3c7a1db353c42e5cfcbe7eae11ded5b360cf4eaf0f72e191
2021–02–15T00:22:50Z FindStealthTransactions() tx: 23709adb589296dcf148bfd8004d1238312b60b41ade6d0e7c34d27c14f1ed23
2021–02–15T00:22:50Z FindStealthTransactions() tx: 26f8b1e6eb177542b7d6f0fef9add5e921926e2e42b3f20edd81e344da595b86
2021–02–15T00:22:50Z FindStealthTransactions() tx: 846d2772592c93fc19900b6b3ef965f2b58f9158a3d283df606d3a24f2dc795f
2021–02–15T00:22:50Z FindStealthTransactions() tx: 4b3ae629df8879607bb1b61e7b276036b788878ff20966a5c378294ccf1e73e1
2021–02–15T00:22:50Z FindStealthTransactions() tx: 93bf32c291be5303feb0560a418f830772dc52aef5f4d1fa3850f52c1b376e54
2021–02–15T00:22:50Z FindStealthTransactions() tx: fddf36f280f1567058fd0e7faa9cabf6b898bdd295c2e402c3d94068c2b7620e
2021–02–15T00:22:50Z FindStealthTransactions() tx: e82087223157e455ac886b51cbc5d079d39b2898ae6bce7a52e299dc09142c64
2021–02–15T00:22:50Z FindStealthTransactions() tx: 47716632e57972d24ae657635de8c63fd568393325500c5eefb454c3ddcd98e1
2021–02–15T00:22:50Z FindStealthTransactions() tx: 4abead460249f329b419ab06ba8dec1b66d66360e0e51fd36a2703f771a471bf
2021–02–15T00:22:50Z FindStealthTransactions() tx: 131c7d59968a532a94b643ae6393efb549c0230f8b6860e5bc7d08cb14b9c3c2
2021–02–15T00:22:50Z FindStealthTransactions() tx: a187bfde8a9b99a2f6785359d99d88ec8a42150a532b05aa0bb210ba633e8bc9
2021–02–15T00:22:50Z FindStealthTransactions() tx: 566a7bca0bcec6db90809354353bf0f6ba159186f60baecf4ba4df20e2b8a700
2021–02–15T00:22:50Z FindStealthTransactions() tx: 29476b2295dd2842f1bacf96128449ff1e9234806103297c09b8433be4f36c93
2021–02–15T00:22:50Z FindStealthTransactions() tx: b252cabfc641372d6f03187793e787314df4c3fc3e8654a70952558f80d3907d
2021–02–15T00:22:50Z FindStealthTransactions() tx: 6ab941189cdd37528b933fcbc7edd126e02586ca2b901da09044d9f1e979e7b3
2021–02–15T00:22:50Z FindStealthTransactions() tx: 98c43f23823cde5901b26968eff832815b8be02bd3b919960fc6a61daaad836d
2021–02–15T00:22:50Z FindStealthTransactions() tx: 90fc6ae3950e4f712f9839d04048511d8f1c708192869cbc117e78849607fc7c
2021–02–15T00:22:50Z FindStealthTransactions() tx: b716fd7ced300b10177c915d9eee79af3947c565f08014d308de5f53ac4a697f
2021–02–15T00:22:50Z FindStealthTransactions() tx: 2fd7b28a853e2675aca7141028d32f9920d888869d4eaef9137e2e1075ecf005
2021–02–15T00:22:50Z FindStealthTransactions() tx: 54a43964d82241e35aab926ba5bc38aab3810625a9f524e654c57fed714be776
2021–02–15T00:22:50Z FindStealthTransactions() tx: 704943920cac22fda58769cb3601e0ea7e055502d8d453d4d5b3c7757f933cff

021–02–15T01:18:44Z FindStealthTransactions() tx: c9e121a7a135076e8ff3260e31935884facc2a66480c362c595c788183ac72a9
2021–02–15T01:18:44Z FindStealthTransactions() tx: 2a59d274d5670e6f80841c1102422e77132019c3128a89eab52e8d5537c12f57
2021–02–15T01:18:44Z FindStealthTransactions() tx: 11ee1eca7b4af8e3ea0b4f21019438a3932791dad89006898a23010d01f8e6c4
2021–02–15T01:18:44Z CreateNewBlock(): block weight: 24364 txs: 6 fees: 1000000 sigops 452
2021–02–15T01:18:47Z UpdateTip: new best=0000000014b6d38afdd068635c4b762d3afc37621c05136a66e33cb938b3a08e height=4751560 version=0x00000804 log2_work=86.712646 tx=9237348 date=’2021–02–15T01:18:41Z’ progress=0.999999 cache=157.8MiB(1141984txo)
2021–02–15T01:18:47Z CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain.
Chain state database corruption likely.
2021–02–15T01:18:47Z FindStealthTransactions() tx: df8576e7a212da19cc32f0983c5781c6b2c8d6695dfcbd4b144cf042daf3d640
2021–02–15T01:18:47Z CreateNewBlock(): block weight: 24364 txs: 6 fees: 1000000 sigops 452
2021–02–15T01:18:52Z UpdateTip: new best=000000003d7c3bfab484692999b363c4c1448057f581b6a9ab47ce2cad488203 height=4751561 version=0x00000804 log2_work=86.712646 tx=9237349 date=’2021–02–15T01:18:47Z’ progress=0.999999 cache=157.8MiB(1141985txo)
2021–02–15T01:18:52Z CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain.
Chain state database corruption likely.

The whole attack took place between 0:15 UTC and about 01:18 UTC on 15. Feb of 2021. The attack itself probably was much quicker, but the wallet(s) simply need a lot of time to basically “resync” to the new state because of the massive reorganization.

Shortly after the attack obviously most wallets showed a different balance than before as the transactions of the last 500.000 blocks were gone or at least elsewhere. Pools, Exchanges and Block Explorers put their wallets into maintenance mode and the XVG Devs were contacted via Twitter for the first time that something was ongoing i.e. a massive reorg took place.

The team denied a successful attack took place and also denied a 51% attack.

Later they posted this on Medium:

Well this is probably not true :-)

The Re-Org TOOK PLACE as you can see from the logfile above and the obvious missing balances on exchanges, pools etc. As of time of writing it’s not clear how many blocks exactly have been rolled back and how much funds were lost.

A similar attack was already successfully completed in 2018 and a post was made on a public forum bitcointalk.org: https://bitcointalk.org/index.php?topic=3256693.0

Since that attack and the post on bitcointalk.org no significant changes on the wallet code was made and there were several successful (smaller) reorgs of the chain until now. In fact the old VERGE 4.0 wallet still connects and works fine as time of writing to current nodes and you can just use it fine as old peer (protocol version) banning was never introduced or rather bumped in XVG.

After the attack several issues were opened on github to face some problems:

The XVG “Team” rapidly attacked all public postings about the reorg and at a certain point simply implied that a public mining pool, suprnova, started the attack on the network and put all the blame to that pool however this is just not how such an attack would work.

The principle of mining in pools is that a lot of small miners with a few graphic cards bundle their power in one larger mining pool which concentrates the power, applies that mining power to the network and then mines blocks with that power. Those blocks are then split into smaller pieces proportional to the effort every little miner has done and this effort is then paid to the miners.

If an individual would attack a chain, he would not do that by pushing a lot of power into one small or big mining pool which is mining that coin as that mining pool would simply stay on the main chain and add one block after the other on the end of the current chain and paying its miners. As with increased power the network difficulty would simply rise and it would become harder to mine blocks thus reducing payouts to miners with small power even more.

A 51% attack works by concentrating more power to a single node (not a pool!) than the whole network currently has and then mining a longer chain on that “malicious” node for a certain amount of time until either the attacker runs out of power or has satisfactory manipulated his new chain and is ready to “collide” his now malicious node which is hosting his malicious chain with the public chain all the wallets and pools are on. Since the network, if not secured through dPow, checkpoints, max reorg depth or other measures, always looks for the longest chain (most work done) it will likely accept that other chain and replace it’s own chain with the “more work done” chain thus replacing all it’s transactions back to the first malicious block.

This is a highly orchestrated and sophisticated attack — it needs a lot of planning, a lot of hashing power over a very long period of time, you always have to keep your malicious chain longer than the friendly chain and also a lot of care not letting the bad chain connect to early to the friendly chain thus losing all work done so far. This is impossible on a public pool as the pool always agrees with the network as it is connected to it.

Due to the nature of the attack, all transactions are now replaced by the malicious chain, so all pools also suffer losses of all the blocks they’ve mined until the first block of the malicious chain — that’s why it makes no sense at all a public pool would ever do that, he would lose all his rewards for his miners.

After the successful attack, the XVG network was split into forks, pools, exchanges, miners and block explorers where on different chains thus not agreeing to each other. The attack was long over since it only held for a few minutes but these forks will exist until all hashing power is depleted/removed; basically until the last miner shuts his miner down on that fork. Even if a pool continues to mine, alone, on its fork it’s not an “attack” because the work or rather difficulty done on that pool is so low that it won’t be accepted by the main chain which difficulty is much higher so you cannot “continue” an attack by continuing to mine on a low power/difficulty fork.

An independent, confirming analysis with technical details of the attack can also be found here:

https://github.com/zawy12/difficulty-algorithms/issues/68

What could be done to mitigate this kind of attack ?

First of all: Limit the max reorg depth. There is already an issue open on github for that: https://github.com/vergecurrency/verge/issues/1059

Then fix the difficulty retarget algorithm, also as issue already open:https://github.com/vergecurrency/verge/issues/1058

dPow like in Komodo could be used to secure the chain by using bitcoin’s hashing power as a backup for securing the chain.

And also old nodes need to be banned off the network:https://github.com/vergecurrency/verge/issue/1060

As we’re in the first day after the attack it’s not clear yet how far the reorg really took place, how many coins exactly are lost and where the funds have been moved to. I’ll post the logfile of the attack on a public gist so researchers can have a close look what happened and I’m happily awaiting any constructive feedback and will also try to shed as much light as I can in working through this attack.

If you want to read more about 51% attacks, read up this very good article:

There’s even a list how much a 51% attack costs per Coin: (At the time of writing it says it costs $45 per hour to attack XVG)

Here’s a zipped version of the attack in one of the logs for research:

http://www.suprnova.cc/xvg-verge-attack-log-1.txt.gz

Tweets about the attack:

Feel free to contact me at admin@suprnova.cc

--

--