Skip to content

Instantly share code, notes, and snippets.

@gavinandresen
Last active May 7, 2021 19:50
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gavinandresen/630d4a6c24ac6144482a to your computer and use it in GitHub Desktop.
Save gavinandresen/630d4a6c24ac6144482a to your computer and use it in GitHub Desktop.
Preventing "surprise" 51% attacks

Preventing "surprise" 51% attacks

Disclaimer: these are half-baked thoughts. Until the #bitcoin-wizards crew has had a chance to think about this really hard I won't consider them fully baked.

The idea: can we take advantage of the fact that almost all nodes are well-connected to the p2p network almost all of the time to limit the ability of a 51% attacker to pull off a multi-confirmation double-spend?

Lets start with a well-connected node that has been seeing new blocks arrive approximately every ten minutes at difficulty D. Assume for now that the node can be confident that it is not being Sybil attacked and is on the actual, best blockchain.

Scenario A: there is a natural multi-block fork due to repeated 50/50 block races, then the node will still see a new block arrive on-average every ten minutes, but half the new blocks will be on one potential best chain and half on the other.

Scenario B: the network is split by some catastrophic network event. The node will see new blocks generated more slowly until the split is resolved-- a 50/50 split would see the apparent hash rate cut in half (average block times doubled). When the network was re-connected there would be a sudden announcement of the blocks generated on the other side of the split, and possibly a long re-org onto that chain. Then the apparent hash rate would be back to pre-split levels.

Scenario C: an attacker works on a private chain for the purpose of pulling off a multi-confirmation double spend attack. This almost looks like a network split, except that the apparent hash rate doubles as soon as the attacker announces their longer chain.

Scenario D: The attacker can make it look exactly like a network split, if they use their hash power to mine honestly before carrying out the attack. The strategy would be:

  1. Mine honestly for a full difficulty adjustment period.
  2. Spend BTC
  3. Disconenct hashing power from the network, have it work on a secret alternative chain that double-spends (2)
  4. Wait required number of confirmations, cash out
  5. Re-connect hashing power to network, forcing everybody to re-organize onto attack chain

Step (3) will take, on average, twice as long as expected (e.g. ~2 hours for 6 confirmations), since the attacker withdraws a majority of hashpower to work on the secret double-spending chain.

Can we just assume away network splits?

Assuming the Bitcoin networks is densely, redundantly connected (is this true? I'm pretty certain it is, would be good to see research), we could just assume that network splits never happen-- or that if an honest split does happen, it is OK to require node operators to intervene after the split is resolved.

The main Bitcoin network has been major-split-free for at least the last four years (we have seen Tor-only-connected nodes split off the network), and it is very hard to imagine an attacker successfully splitting the network into two approximately-equal-hashing halves and maintaining that split for an hour or more. Just one connection between the two halves is sufficient for the network to regain consensus.

I find it even more implausible that an attack on physical Internet infrastructure could cause a major Bitcoin network split. Internet infrastructure is highly redundant today; see http://www.submarinecablemap.com/ to get an idea of how many cables would have to be cut to sever the wired connection between the Americas and Europe/Asia/Africa, and realize that Internet traffic can also be carried over satellite links.

Proposal: refuse long, 'surprise' forks

I'll start with some assumptions:

  1. Our node is caught up to the best blockchain.
  2. Our node is well-connected to the network, and has been well-connected for a while.
  3. Network-wide splits lasting more than a few tens of minutes never happen.

Given those assumptions, the sudden announcement of a longer chain that forks the current best chain can be assumed to be a double-spending attack. As long as the miners, merchants, and exchanges connected to the network refuse to re-organize onto that chain the attack will fail.

If the attacker continues to build on their chain, then for new nodes joining the network all three of the above assumptions fail-- there will be two competing blockchains active on the network. The reference implementation already contains code to detect this, and will warn the node operator that Something is Wrong.

A very deep chain re-organization (hundreds of blocks deep) would be a catastrophic events for Bitcoin-- causing, at the very least, huge problems for exchanges that would have to deal with deeply confirmed transactions that were suddenly invalid. Refusing to automatically re-organize onto a chain more than a few blocks deep would prevent that catastrophe.

If an attacker knows that the network will refuse to re-organize onto long forks that suddenly appear on the network, then they almost certainly won't bother trying to attack the network that way. But with sufficient hashing power they could still attempt transaction denial-of-service attacks-- they could refuse to build on blocks that include certain transactions. They could also attempt to monopolize mining rewards, refusing to build on anybody else's blocks.

If a persistent 51% attacker tried a surprise reorg-huge-chunks-of-the-chain or double-spend attack, it would trigger an alert on every node on the network (both long-running and newly-joined nodes would notice that there were two active chains). People can individually decide which fork they will follow, using the -blacklistblock / -reconsiderblock RPC commands.

Implementation

Ummm.... uhh.... these are EXTREMELY unbaked thoughts:

Until our node is caught up with the best chain, it should behave exactly as it does today, accepting the chain with the most proof-of-work without question.

Vitalik Buterin proposes exponentially subjective scoring (https://blog.ethereum.org/2014/10/03/slasher-ghost-developments-proof-stake/) to prevent very deep block-chain re-organizations. Could we use a much more aggressive version of that idea to make it difficult to switch to a 3-block-long surprise fork and make it take overwhelming hashpower to switch to a 6-block-long surprise fork? Can we tweak Vitalik's idea so that normal forks caused by block races (Scenario A above) are never affected, no matter how deep?

Alternative idea: perhaps we should keep track of the local time when we first hear about each block. If nobody is attacking then those arrival times should follow a Poisson distribution centered near 10 minutes.

When somebody does attack with a surprise chain, the arrival times of those blocks will not match that nice, Poisson distribution-- our node will get lots of blocks all at once.

When deciding on whether or not to switch to a potential fork, maybe we can measure how closely each matches an ideal Poisson distribution, and refuse to switch to the longer fork (and warn the node operator that something bad is happening) if it is a much worse match than the shorter fork.

Costs and Benefits

Benefits:

  1. Prevent "reorganize hours/days/weeks worth of blocks" attacks.
  2. Eliminate successful double-spending as a potential financial incentive for a 51% attack.

Costs:

  1. Extra complexity in consensus-critical code.
  2. Manual intervention required if there ever is a 'natural' long-lived network split.

No benefit or cost:

  1. Selfish mining (the selfish mining algorithm never publishes several blocks in a long chain all at once)
  2. 51+% attacks to monopolize mining rewards
  3. Non-economic 51+% attacks to censor transactions

References

Exponentially subjective scoring : https://blog.ethereum.org/2014/10/03/slasher-ghost-developments-proof-stake/

I'm sure there are old relevant threads on bitcointalk....

@SergioDemianLerner
Copy link

In https://bitslog.wordpress.com/2013/06/26/the-bitcoin-eternal-choice-for-the-dark-side-attack-ecdsa/ I proposed a protocol that can be applied here:

The additional protective measure would be that any chain reorg of n blocks is delayed n seconds. During that wait period, if another better chain reorg is received, is processed in the same way. After one period expires, the chain reorg is applied, and a new best chain is created. If a block that extends a waiting chain is received, then the waiting lapse is restarted from zero for that chain. If a node receives a 144 length branch in a very short period of time, it will wait 144 seconds to actually apply the reorganization, so if the network is not split, that gives plenty of time to exchange all other chains in existence and choose the best. If a node receives two 143 block competing branches in a short period of time, then any attempt to extend both chains at the same time will result in both staying in a waiting state for 144 seconds more. A chain of 144 blocks won’t accept any additional extension (the max is 144) so the attacker cannot keep playing this game forever.

You can of course change 1 second for 1 minute, or anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment