If soft forks are safer than hard forks, why not use them for everything? What can soft forks change?

Let’s start again with the definitions of what soft and hard forks are:

  • Soft forks add new rules to the protocol, making previously valid blocks invalid.

  • Hard forks remove rules from the protocol, making previous invalid blocks valid.

When we talk about a “rule”, we mean something quite specific and technical. For instance, it’s common knowledge that there will only ever be 21 million bitcoins, and the supply graph of those bitcoins is an exponentially decreasing curve:

Coin Supply

In Bitcoin Core v0.11.2 that supply curve is enforced by the function GetBlockSubsidy():

CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
    int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
    // Force block reward to zero when right shift is undefined.
    if (halvings >= 64)
        return 0;

    CAmount nSubsidy = 50 * COIN;
    // Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
    nSubsidy >>= halvings;
    return nSubsidy;
}

along with the following code in ConnectBlock():

CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus());
if (block.vtx[0].GetValueOut() > blockReward)
    return state.DoS(100,
                     error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
                           block.vtx[0].GetValueOut(), blockReward),
                           REJECT_INVALID, "bad-cb-amount");

For those of you unfamiliar with C++ that code basically means:

  • A block is invalid if it creates more than (height / 210,000) * 50 bitcoins

So can a block contain less than the subsidy? Yes! In fact, it’s completely valid for blocks to create no coins at all. This means we can soft fork in a new rule by changing the code to the following:

CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus());
if (block.vtx[0].GetValueOut() > blockReward)
    return state.DoS(100,
                     error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
                           block.vtx[0].GetValueOut(), blockReward),
                           REJECT_INVALID, "bad-cb-amount");

if (pindex->nHeight > 600000 && block.vtx[0].GetValueOut() > nFees)
    return state.DoS(100,
                     error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
                           block.vtx[0].GetValueOut(), blockReward),
                           REJECT_INVALID, "bad-cb-amount");

In English:

  • A block is invalid if:
    • It creates more than ((height / 210,000) * 50 bitcoins
    • After block 600,000 it creates any coins at all

Of course, getting a majority of hashing power to agree to this change might be rather difficult, but from a technical point of view, this is perfectly possible.

Radical Changes

As with the coin supply, there’s no protocol rule that requires blocks to have transactions in them (other than the coinbase). Thus we can soft fork in these additional new rules:

  • If >= 95% of the past 2000 blocks voted for Bitcoin 2.0 all blocks must:
    • Vote for Bitcoin 2.0
    • Contain exactly one transaction, the coinbase
    • The coinbase must include the hash of a valid Bitcoin 2.0 block

This is a soft fork! All the previous validity rules have been followed to letter, even if the result is totally useless to Bitcoin 1.0 users. These users can’t spend their funds at all until they change their software - why this type of soft fork is referred to as a forced soft fork, or depending on your perspective, an evil soft fork.

Forced Soft Fork

So what is a valid Bitcoin 2.0 block? It could be anything at all! For example, the inflation schedule can be changed to make the coin supply unlimited.

Are Forced Soft Forks Safe?

Depends on what you mean by “safe”. As with all soft forks, they guarantee that old nodes won’t accidentally accept invalid transactions. While all nodes - SPV and full nodes alike - need to be upgraded if the new block format doesn’t change how transactions are serialized the code changes required are surprisingly small and self contained (in most cases); with some simple protocol changes forced soft forks can even be standardized and turned into a routine upgrade procedure. Finally they guarantee that there will be just one chain going forward, at least if the fork is accepted by the community.

But what if the rules aren’t accepted by the community? For instance, what if miners use a forced soft fork to make the inflation subsidy 50 BTC forever?

Frankly the answer is no-one knows for sure. While the usual argument is that users running full nodes control Bitcoin, not miners, full nodes only let you detect if miners are breaking the rules - without hashing power there isn’t necessarily anything you can do about it other than (try to) sell your coins and stop using the system. Whether the proponents of a controversial change will succeed or not is a question of how many users leave the system in response to the change, or even that a controversial fork - soft or hard - has shown that future controversial changes are also possible:

[T]he truth that most of the current developers are interested in Bitcoin as a
decentralized consensus system existing outside and above the realm of human
affairs. Lose that property, and it ceases to be an interesting system.

I'm passionate about Bitcoin. I have zero passion for majority-vote to change
the rules [of the] system. We have one of those already - it's called fiat.

-Mark Friedenbach