Describe Soft And Hard Forks

Based on a suggestion made by @petertodd to the -devel mailing list and
the discussion in that thread by him and other participants.

* We've been using the term "consensus", but this commit introduces a
  formal definition for it and "consensus rules" as part of the block
  chain introduction.

* Describe that consensus rules may change and may happen when they
  do: hard or soft forks.

* Describe how full nodes can detect hard or soft forks, then describe
  how SPV clients can detect hard and soft forks using the more limited
  information available to them.
This commit is contained in:
David A. Harding 2014-10-23 12:39:18 -04:00
parent 2147b830f1
commit 2e8ceb26df
No known key found for this signature in database
GPG key ID: 4B29C30FF29EC4B7
9 changed files with 462 additions and 6 deletions

View file

@ -48,6 +48,8 @@ confirmed:
confirmation: confirmation:
confirmations: confirmations:
confirmed transactions: confirmed transactions:
consensus:
consensus rules:
denomination: denomination:
denominations: denomination denominations: denomination
DER format: der DER format: der
@ -65,8 +67,11 @@ extended keys: extended key
extended private key: extended private key:
extended public key: extended public key:
fiat: fiat:
fork: accidental fork fork:
forks: fork
genesis block: genesis block:
hard fork:
hard forks: hard fork
hardened extended private key: hardened extended private key:
HD protocol: HD protocol:
header nonce: header nonce:
@ -184,6 +189,8 @@ signature hash:
signature script: signature script:
signature scripts: signature script signature scripts: signature script
signatures: signature signatures: signature
soft fork:
soft forks: soft fork
SPV: SPV:
stack: stack:
stale block: stale block:
@ -217,10 +224,14 @@ wallet import format:
x.509: x509 x.509: x509
X509Certificates: X509Certificates:
## BIPS in numerical order; don't use padding zeros (e.g. BIP70 not BIP0070) ## BIPs in numerical order; don't use padding zeros (e.g. BIP70 not BIP0070)
BIP16:
BIP21: BIP21:
BIP30:
BIP32: BIP32:
BIP34:
BIP39: BIP39:
BIP50:
BIP70: BIP70:
BIP71: BIP71:
BIP72: BIP72:

View file

@ -4,8 +4,15 @@
The block chain provides Bitcoin's public ledger, an ordered and timestamped record The block chain provides Bitcoin's public ledger, an ordered and timestamped record
of transactions. This system is used to protect against double spending of transactions. This system is used to protect against double spending
and modification of previous transaction records, using proof of and modification of previous transaction records.
work verified by the peer-to-peer network to maintain a global consensus.
Each full node in the Bitcoin network independently stores a block chain
containing only blocks validated by that node. When several nodes all
have the same blocks in their block chain, they are considered to be in
[consensus][]{:#term-consensus}{:.term}. The validation rules these
nodes follow to maintain consensus are called [consensus
rules][]{:#term-consensus-rules}{:.term}. This section describes many of
the consensus rules used by Bitcoin Core.
{% endautocrossref %} {% endautocrossref %}
@ -148,7 +155,7 @@ block 2016 is where difficulty could have first been adjusted.
Multiple blocks can all have the same block height, as is common when Multiple blocks can all have the same block height, as is common when
two or more miners each produce a block at roughly the same time. This two or more miners each produce a block at roughly the same time. This
creates an apparent [fork][accidental fork]{:#term-accidental-fork}{:.term} in the block chain, as shown in the creates an apparent [fork][]{:#term-fork}{:.term} in the block chain, as shown in the
illustration above. illustration above.
When miners produce simultaneous blocks at the end of the block chain, each When miners produce simultaneous blocks at the end of the block chain, each
@ -244,3 +251,104 @@ Since it is impractical to have separate transactions with identical txids, this
otherwise, a valid block with the duplicates eliminated could have the same merkle root and block hash, but be rejected by the cached invalid outcome, resulting in security bugs such as CVE-2012-2459. otherwise, a valid block with the duplicates eliminated could have the same merkle root and block hash, but be rejected by the cached invalid outcome, resulting in security bugs such as CVE-2012-2459.
{% endautocrossref %} {% endautocrossref %}
### Consensus Rule Changes
{% autocrossref %}
To maintain consensus, all full nodes validate blocks using the same
consensus rules. However, sometimes the consensus rules are changed to
introduce new features or prevent network abuse. When the new rules are
implemented, there will likely be a period of time when non-upgraded
nodes follow the old rules and upgraded nodes follow the new rules,
creating two possible ways consensus can break:
1. A block following the new consensus rules is accepted by upgraded
nodes but rejected by non-upgraded nodes. For example, a new
transaction feature is used within a block: upgraded nodes understand
the feature and accept it, but non-upgraded nodes reject it because
it violates the old rules.
2. A block violating the new consensus rules is rejected by upgraded
nodes but accepted by non-upgraded nodes. For example, an abusive
transaction feature is used within a block: upgraded nodes reject it
because it violates the new rules, but non-upgraded nodes accept it
because it follows the old rules.
In the first case, rejection by non-upgraded nodes, mining software
which gets block chain data from those non-upgraded nodes refuses to
build on the same chain as mining software getting data from upgraded
nodes. This creates permanently divergent chains---one for non-upgraded
nodes and one for upgraded nodes---called a [hard
fork][]{:#term-hard-fork}{:.term}.
![Hard Fork](/img/dev/en-hard-fork.svg)
In the second case, rejection by upgraded nodes, it's possible to keep
the block chain from permanently diverging if upgraded nodes control a
majority of the hash rate. That's because, in this case, non-upgraded
nodes will accept as valid all the same blocks as upgraded nodes, so the
upgraded nodes can build a stronger chain that the non-upgraded nodes
will accept as the best valid block chain. This is called a [soft
fork][]{:#term-soft-fork}{:.term}.
![Soft Fork](/img/dev/en-soft-fork.svg)
Although a fork is an actual divergence in block chains, changes to the
consensus rules are often described by their potential to create either
a hard or soft fork. For example, "increasing the block size above 1 MB
requires a hard fork." In this example, an actual block chain fork is
not required---but it is a possible outcome.
**Resources:** [BIP16][], [BIP30][], and [BIP34][] were implemented as
changes which might have lead to soft forks. [BIP50][] describes both an
accidental hard fork, resolved by temporary downgrading the capabilities
of upgraded nodes, and an intentional hard fork when the temporary
downgrade was removed. A document from Gavin Andresen outlines [how
future rule changes may be
implemented](https://gist.github.com/gavinandresen/2355445).
{% endautocrossref %}
#### Detecting Forks
{% autocrossref %}
Non-upgraded nodes may use and distribute incorrect information during
both types of forks, creating several situations which could lead to
financial loss. In particular, non-upgraded nodes may relay and accept
transactions that are considered invalid by upgraded nodes and so will
never become part of the universally-recognized best block chain.
Non-upgraded nodes may also refuse to relay blocks or transactions which
have already been added to the best block chain, or soon will be, and so
provide incomplete information.
<!-- paragraph below based on src/main.cpp CheckForkWarningConditions() -->
Bitcoin Core includes code that detects a hard fork by looking at block
chain proof of work. If a node receives block chain headers
demonstrating six blocks more proof of work than the best chain this
node considers valid, the node reports an error in the `getinfo` RPC
results and runs the `-alertnotify` command if set.
Full nodes can also check block and transaction version numbers. If the
block or transaction version numbers seen in several recent blocks are
higher than the version numbers the node uses, it can assume it doesn't
use the current consensus rules. Future versions of Bitcoin Core
(>0.9.3) will likely report this situation through the `getinfo` RPC and
`-alertnotify` command if set.
In either case, data should not be relied upon if it comes from a node
that apparently isn't using the current consensus rules.
SPV clients which connect to full nodes can detect a likely hard fork by
connecting to several full nodes and ensuring that they're all on the
same chain with the same block height, plus or minus several blocks to
account for transmission delays and stale blocks. If there's a
divergence, the client can disconnect from nodes with weaker chains.
SPV clients should also monitor for block and transaction version number
increases to ensure they process received transactions and create new
transactions using the current consensus rules.
{% endautocrossref %}

View file

@ -1,5 +1,4 @@
[51 percent attack]: /en/developer-guide#term-51-attack "The ability of someone controlling a majority of hashing power to revise transactions history and prevent new transactions from confirming" [51 percent attack]: /en/developer-guide#term-51-attack "The ability of someone controlling a majority of hashing power to revise transactions history and prevent new transactions from confirming"
[accidental fork]: /en/developer-guide#term-accidental-fork "When two or more blocks have the same block height, forking the block chain. Happens occasionally by accident"
[addresses]: /en/developer-guide#term-address "A 20-byte hash formatted as a P2PKH or P2SH Bitcoin Address" [addresses]: /en/developer-guide#term-address "A 20-byte hash formatted as a P2PKH or P2SH Bitcoin Address"
[address]: /en/developer-guide#term-address "A 20-byte hash formatted as a P2PKH or P2SH Bitcoin Address" [address]: /en/developer-guide#term-address "A 20-byte hash formatted as a P2PKH or P2SH Bitcoin Address"
[base58Check]: /en/developer-reference#term-base58check "The method used in Bitcoin for converting 160-bit hashes into Bitcoin addresses" [base58Check]: /en/developer-reference#term-base58check "The method used in Bitcoin for converting 160-bit hashes into Bitcoin addresses"
@ -30,6 +29,8 @@
[confirmed transactions]: /en/developer-guide#term-confirmation "Transactions included in a block currently on the block chain" [confirmed transactions]: /en/developer-guide#term-confirmation "Transactions included in a block currently on the block chain"
[confirmation]: /en/developer-guide#term-confirmation "The number of blocks which would need to be modified to remove or modify a transaction" [confirmation]: /en/developer-guide#term-confirmation "The number of blocks which would need to be modified to remove or modify a transaction"
[confirmations]: /en/developer-guide#term-confirmation "The number of blocks which would need to be modified to remove or modify a transaction" [confirmations]: /en/developer-guide#term-confirmation "The number of blocks which would need to be modified to remove or modify a transaction"
[consensus]: /en/developer-guide#term-consensus "When several nodes (usually most nodes on the network) all have the same blocks in their locally-validated block chain."
[consensus rules]: /en/developer-guide#term-consensus-rules "The block validation rules that full nodes follow to stay in consensus with other nodes."
[denomination]: /en/developer-guide#term-denomination "bitcoins (BTC), bitcents (cBTC), millibits (mBTC), microbits (uBTC), or satoshis" [denomination]: /en/developer-guide#term-denomination "bitcoins (BTC), bitcents (cBTC), millibits (mBTC), microbits (uBTC), or satoshis"
[difficulty]: /en/developer-guide#term-difficulty "A number corresponding to the target threshold which indicates how difficult it will be to find the next block" [difficulty]: /en/developer-guide#term-difficulty "A number corresponding to the target threshold which indicates how difficult it will be to find the next block"
[double spend]: /en/developer-guide#term-double-spend "Attempting to spend the same satoshis which were spent in a previous transaction" [double spend]: /en/developer-guide#term-double-spend "Attempting to spend the same satoshis which were spent in a previous transaction"
@ -38,7 +39,9 @@
[extended public key]: /en/developer-guide#term-extended-public-key "A public key extended with the chain code so that it can derive child public keys" [extended public key]: /en/developer-guide#term-extended-public-key "A public key extended with the chain code so that it can derive child public keys"
[escrow contract]: /en/developer-guide#term-escrow-contract "A contract in which the spender and receiver store satoshis in a multisig output until both parties agree to release the satoshis" [escrow contract]: /en/developer-guide#term-escrow-contract "A contract in which the spender and receiver store satoshis in a multisig output until both parties agree to release the satoshis"
[fiat]: /en/developer-guide#term-fiat "National currencies such as the dollar or euro" [fiat]: /en/developer-guide#term-fiat "National currencies such as the dollar or euro"
[fork]: /en/developer-guide#term-fork "When two or more blocks have the same block height, forking the block chain."
[genesis block]: /en/developer-guide#term-genesis-block "The first block created; also called block 0" [genesis block]: /en/developer-guide#term-genesis-block "The first block created; also called block 0"
[hard fork]: /en/developer-guide#term-hard-fork "A permanent divergence in the the block chain, commonly occurs when non-upgraded nodes can't validate blocks created by upgraded nodes following newer consensus rules."
[hardened extended private key]: /en/developer-guide#term-hardened-extended-private-key "A private key whose corresponding public key cannot derive child keys" [hardened extended private key]: /en/developer-guide#term-hardened-extended-private-key "A private key whose corresponding public key cannot derive child keys"
[HD protocol]: /en/developer-guide#term-hd-protocol "The Hierarchical Deterministic (HD) key creation and transfer protocol" [HD protocol]: /en/developer-guide#term-hd-protocol "The Hierarchical Deterministic (HD) key creation and transfer protocol"
[header nonce]: /en/developer-reference#term-header-nonce "Four bytes of arbitrary data in a block header used to let miners create headers with different hashes for proof of work" [header nonce]: /en/developer-reference#term-header-nonce "Four bytes of arbitrary data in a block header used to let miners create headers with different hashes for proof of work"
@ -132,6 +135,7 @@
[signature]: /en/developer-guide#term-signature "The result of combining a private key and some data in an ECDSA signature operation which allows anyone with the corresponding public key to verify the signature" [signature]: /en/developer-guide#term-signature "The result of combining a private key and some data in an ECDSA signature operation which allows anyone with the corresponding public key to verify the signature"
[signature hash]: /en/developer-guide#term-signature-hash "A byte appended onto signatures generated in Bitcoin which allows the signer to specify what data was signed, allowing modification of the unsigned data" [signature hash]: /en/developer-guide#term-signature-hash "A byte appended onto signatures generated in Bitcoin which allows the signer to specify what data was signed, allowing modification of the unsigned data"
[signature script]: /en/developer-guide#term-signature-script "Data generated by a spender which is almost always used as variables to satisfy a pubkey script" [signature script]: /en/developer-guide#term-signature-script "Data generated by a spender which is almost always used as variables to satisfy a pubkey script"
[soft fork]: /en/developer-guide#term-soft-fork "A temporary fork in the block chain which commonly occurs when miners using non-upgraded nodes violate a new consensus rule their nodes don't know about."
[spv]: /en/developer-guide#simplified-payment-verification-spv "A method for verifying particular transactions were included in blocks without downloading the entire contents of the block chain" [spv]: /en/developer-guide#simplified-payment-verification-spv "A method for verifying particular transactions were included in blocks without downloading the entire contents of the block chain"
[ssl signature]: /en/developer-examples#term-ssl-signature "Signatures created and recognized by major SSL implementations such as OpenSSL" [ssl signature]: /en/developer-examples#term-ssl-signature "Signatures created and recognized by major SSL implementations such as OpenSSL"
[stack]: /en/developer-guide#term-stack "An evaluation stack used in Bitcoin's script language" [stack]: /en/developer-guide#term-stack "An evaluation stack used in Bitcoin's script language"
@ -160,9 +164,13 @@
[X509Certificates]: /en/developer-examples#term-x509certificates [X509Certificates]: /en/developer-examples#term-x509certificates
[BFGMiner]: https://github.com/luke-jr/bfgminer [BFGMiner]: https://github.com/luke-jr/bfgminer
[BIP16]: https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
[BIP21]: https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki [BIP21]: https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki
[BIP30]: https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki
[BIP32]: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki [BIP32]: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
[BIP34]: https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki
[BIP39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki [BIP39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
[BIP50]: https://github.com/bitcoin/bips/blob/master/bip-0050.mediawiki
[BIP70]: https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki [BIP70]: https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki
[BIP71]: https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki [BIP71]: https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki
[BIP72]: https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki [BIP72]: https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki

49
img/dev/en-hard-fork.dot Normal file
View file

@ -0,0 +1,49 @@
digraph {
size=6.25;
rankdir=LR
//splines = ortho;
ranksep = 0.2;
nodesep = 0.1;
edge [ penwidth = 1.75, fontname="Sans" ]
node [ penwidth = 1.75, shape = "box", fontname="Sans", label = "", width=0.3, height=0.3 ]
graph [ penwidth = 1.75, fontname="Sans" ]
invis1 [ shape = "none", label = "Blocks\nFrom\nUpgraded\nNodes" ]
invis0 [ shape = "none", label = "Blocks\nFrom Non-\nUpgraded\nNodes" ];
subgraph cluster_honest {
block0 [ label = "Follows\nOld\nRules" ];
block1 [ label = "Follows\nOld\nRules" ];
block2_1 [ label = "Follows\nOld\nRules" ];
block3_1 [ label = "Follows\nOld\nRules" ];
//block2_1 -> block4 [ style = "invis", minlen = 2 ];
style = "invis";
}
subgraph cluster_attack {
block2 [ label = "Follows\nNew\nRules" ];
block3 [ label = "Follows\nNew\nRules" ];
block4 [ label = "Follows\nNew\nRules" ];
block5 [ label = "Follows\nNew\nRules" ];
style = "invis"
}
invis0 -> block0 [ minlen = 2, style = "dashed" ];
block2_1 -> block3_1;
block0 -> block1 -> block2 -> block3 -> block4 -> block5;
block1 -> block2_1
label = "A Hard Fork: Non-Upgraded Nodes Reject The New Rules, Diverging The Chain"
}

BIN
img/dev/en-hard-fork.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

128
img/dev/en-hard-fork.svg Normal file
View file

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
-->
<!-- Title: _anonymous_0 Pages: 1 -->
<svg width="450pt" height="147pt"
viewBox="0.00 0.00 450.00 146.89" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(0.716561 0.716561) rotate(0) translate(4 201)">
<title>_anonymous_0</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-201 625,-201 625,5 -4,5"/>
<text text-anchor="middle" x="310" y="-8.4" font-family="Sans" font-size="14.00">A Hard Fork: &#160;Non&#45;Upgraded Nodes Reject The New Rules, Diverging The Chain</text>
<g id="graph2" class="cluster"><title>cluster_honest</title>
</g>
<g id="graph3" class="cluster"><title>cluster_attack</title>
</g>
<!-- invis1 -->
<g id="node1" class="node"><title>invis1</title>
<text text-anchor="middle" x="45" y="-90.4" font-family="Sans" font-size="14.00">Blocks</text>
<text text-anchor="middle" x="45" y="-73.4" font-family="Sans" font-size="14.00">From</text>
<text text-anchor="middle" x="45" y="-56.4" font-family="Sans" font-size="14.00">Upgraded</text>
<text text-anchor="middle" x="45" y="-39.4" font-family="Sans" font-size="14.00">Nodes</text>
</g>
<!-- invis0 -->
<g id="node2" class="node"><title>invis0</title>
<text text-anchor="middle" x="45" y="-173.4" font-family="Sans" font-size="14.00">Blocks</text>
<text text-anchor="middle" x="45" y="-156.4" font-family="Sans" font-size="14.00">From Non&#45;</text>
<text text-anchor="middle" x="45" y="-139.4" font-family="Sans" font-size="14.00">Upgraded</text>
<text text-anchor="middle" x="45" y="-122.4" font-family="Sans" font-size="14.00">Nodes</text>
</g>
<!-- block0 -->
<g id="node4" class="node"><title>block0</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="190,-181.5 122,-181.5 122,-122.5 190,-122.5 190,-181.5"/>
<text text-anchor="middle" x="156" y="-164.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="156" y="-147.9" font-family="Sans" font-size="14.00">Old</text>
<text text-anchor="middle" x="156" y="-130.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- invis0&#45;&gt;block0 -->
<g id="edge4" class="edge"><title>invis0&#45;&gt;block0</title>
<path fill="none" stroke="black" stroke-width="1.75" stroke-dasharray="5,2" d="M89.5084,-152C96.8055,-152 104.367,-152 111.66,-152"/>
<polygon fill="black" stroke="black" points="111.736,-155.5 121.736,-152 111.736,-148.5 111.736,-155.5"/>
</g>
<!-- block1 -->
<g id="node5" class="node"><title>block1</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="272,-181.5 204,-181.5 204,-122.5 272,-122.5 272,-181.5"/>
<text text-anchor="middle" x="238" y="-164.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="238" y="-147.9" font-family="Sans" font-size="14.00">Old</text>
<text text-anchor="middle" x="238" y="-130.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block0&#45;&gt;block1 -->
<g id="edge8" class="edge"><title>block0&#45;&gt;block1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M190.3,-152C191.419,-152 192.545,-152 193.675,-152"/>
<polygon fill="black" stroke="black" points="193.837,-155.5 203.837,-152 193.837,-148.5 193.837,-155.5"/>
</g>
<!-- block2_1 -->
<g id="node6" class="node"><title>block2_1</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="356,-181.5 288,-181.5 288,-122.5 356,-122.5 356,-181.5"/>
<text text-anchor="middle" x="322" y="-164.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="322" y="-147.9" font-family="Sans" font-size="14.00">Old</text>
<text text-anchor="middle" x="322" y="-130.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block1&#45;&gt;block2_1 -->
<g id="edge14" class="edge"><title>block1&#45;&gt;block2_1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M272.166,-152C273.946,-152 275.745,-152 277.551,-152"/>
<polygon fill="black" stroke="black" points="277.864,-155.5 287.864,-152 277.864,-148.5 277.864,-155.5"/>
</g>
<!-- block2 -->
<g id="node9" class="node"><title>block2</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="356,-99.5 288,-99.5 288,-40.5 356,-40.5 356,-99.5"/>
<text text-anchor="middle" x="322" y="-82.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="322" y="-65.9" font-family="Sans" font-size="14.00">New</text>
<text text-anchor="middle" x="322" y="-48.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block1&#45;&gt;block2 -->
<g id="edge9" class="edge"><title>block1&#45;&gt;block2</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M267.852,-122.859C273.422,-117.421 279.304,-111.679 285.058,-106.062"/>
<polygon fill="black" stroke="black" points="287.533,-108.537 292.244,-99.0472 282.644,-103.528 287.533,-108.537"/>
</g>
<!-- block3_1 -->
<g id="node7" class="node"><title>block3_1</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="438,-181.5 370,-181.5 370,-122.5 438,-122.5 438,-181.5"/>
<text text-anchor="middle" x="404" y="-164.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="404" y="-147.9" font-family="Sans" font-size="14.00">Old</text>
<text text-anchor="middle" x="404" y="-130.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block2_1&#45;&gt;block3_1 -->
<g id="edge6" class="edge"><title>block2_1&#45;&gt;block3_1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M356.3,-152C357.419,-152 358.545,-152 359.675,-152"/>
<polygon fill="black" stroke="black" points="359.837,-155.5 369.837,-152 359.837,-148.5 359.837,-155.5"/>
</g>
<!-- block3 -->
<g id="node10" class="node"><title>block3</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="438,-99.5 370,-99.5 370,-40.5 438,-40.5 438,-99.5"/>
<text text-anchor="middle" x="404" y="-82.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="404" y="-65.9" font-family="Sans" font-size="14.00">New</text>
<text text-anchor="middle" x="404" y="-48.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block2&#45;&gt;block3 -->
<g id="edge10" class="edge"><title>block2&#45;&gt;block3</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M356.3,-70C357.419,-70 358.545,-70 359.675,-70"/>
<polygon fill="black" stroke="black" points="359.837,-73.5001 369.837,-70 359.837,-66.5001 359.837,-73.5001"/>
</g>
<!-- block4 -->
<g id="node11" class="node"><title>block4</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="522,-99.5 454,-99.5 454,-40.5 522,-40.5 522,-99.5"/>
<text text-anchor="middle" x="488" y="-82.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="488" y="-65.9" font-family="Sans" font-size="14.00">New</text>
<text text-anchor="middle" x="488" y="-48.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block3&#45;&gt;block4 -->
<g id="edge11" class="edge"><title>block3&#45;&gt;block4</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M438.166,-70C439.946,-70 441.745,-70 443.551,-70"/>
<polygon fill="black" stroke="black" points="443.864,-73.5001 453.864,-70 443.864,-66.5001 443.864,-73.5001"/>
</g>
<!-- block5 -->
<g id="node12" class="node"><title>block5</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="604,-99.5 536,-99.5 536,-40.5 604,-40.5 604,-99.5"/>
<text text-anchor="middle" x="570" y="-82.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="570" y="-65.9" font-family="Sans" font-size="14.00">New</text>
<text text-anchor="middle" x="570" y="-48.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block4&#45;&gt;block5 -->
<g id="edge12" class="edge"><title>block4&#45;&gt;block5</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M522.3,-70C523.419,-70 524.545,-70 525.675,-70"/>
<polygon fill="black" stroke="black" points="525.837,-73.5001 535.837,-70 525.837,-66.5001 525.837,-73.5001"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

47
img/dev/en-soft-fork.dot Normal file
View file

@ -0,0 +1,47 @@
digraph {
size=6.25;
rankdir=LR
//splines = ortho;
ranksep = 0.2;
nodesep = 0.1;
edge [ penwidth = 1.75, fontname="Sans" ]
node [ penwidth = 1.75, shape = "box", fontname="Sans", label = "", width=0.3, height=0.3 ]
graph [ penwidth = 1.75, fontname="Sans" ]
invis1 [ shape = "none", label = "Blocks\nFrom\nUpgraded\nNodes" ]
invis0 [ shape = "none", label = "Blocks\nFrom Non-\nUpgraded\nNodes" ];
subgraph cluster_honest {
block0 [ label = "Follows\nOld\nRules" ];
block1 [ label = "Follows\nOld\nRules" ];
block2_1 [ label = "Follows Old Rules\nBut Violates\nNew Rules", style = "filled" ];
block2_1 -> block4 [ style = "invis", minlen = 2 ];
block4 [ label = "Follows\nOld\nRules" ];
style = "invis";
}
subgraph cluster_attack {
block2 [ label = "Follows\nOld & New\nRules" ];
block3 [ label = "Follows\nOld & New\nRules" ];
style = "invis"
}
invis0 -> block0 [ minlen = 2, style = "dashed" ];
block0 -> block1 -> block2 -> block3 -> block4;
block1 -> block2_1
label = "A Soft Fork: Blocks Violating New Rules Are Made Stale By The Upgraded Mining Majority"
}

BIN
img/dev/en-soft-fork.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

105
img/dev/en-soft-fork.svg Normal file
View file

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
-->
<!-- Title: _anonymous_0 Pages: 1 -->
<svg width="450pt" height="143pt"
viewBox="0.00 0.00 450.00 143.02" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(0.697674 0.697674) rotate(0) translate(4 201)">
<title>_anonymous_0</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-201 642,-201 642,5 -4,5"/>
<text text-anchor="middle" x="318.5" y="-8.4" font-family="Sans" font-size="14.00">A Soft Fork: &#160;Blocks Violating New Rules Are Made Stale By The Upgraded Mining Majority</text>
<g id="graph2" class="cluster"><title>cluster_honest</title>
</g>
<g id="graph3" class="cluster"><title>cluster_attack</title>
</g>
<!-- invis1 -->
<g id="node1" class="node"><title>invis1</title>
<text text-anchor="middle" x="48.5" y="-90.4" font-family="Sans" font-size="14.00">Blocks</text>
<text text-anchor="middle" x="48.5" y="-73.4" font-family="Sans" font-size="14.00">From</text>
<text text-anchor="middle" x="48.5" y="-56.4" font-family="Sans" font-size="14.00">Upgraded</text>
<text text-anchor="middle" x="48.5" y="-39.4" font-family="Sans" font-size="14.00">Nodes</text>
</g>
<!-- invis0 -->
<g id="node2" class="node"><title>invis0</title>
<text text-anchor="middle" x="48.5" y="-173.4" font-family="Sans" font-size="14.00">Blocks</text>
<text text-anchor="middle" x="48.5" y="-156.4" font-family="Sans" font-size="14.00">From Non&#45;</text>
<text text-anchor="middle" x="48.5" y="-139.4" font-family="Sans" font-size="14.00">Upgraded</text>
<text text-anchor="middle" x="48.5" y="-122.4" font-family="Sans" font-size="14.00">Nodes</text>
</g>
<!-- block0 -->
<g id="node4" class="node"><title>block0</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="193.5,-181.5 125.5,-181.5 125.5,-122.5 193.5,-122.5 193.5,-181.5"/>
<text text-anchor="middle" x="159.5" y="-164.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="159.5" y="-147.9" font-family="Sans" font-size="14.00">Old</text>
<text text-anchor="middle" x="159.5" y="-130.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- invis0&#45;&gt;block0 -->
<g id="edge6" class="edge"><title>invis0&#45;&gt;block0</title>
<path fill="none" stroke="black" stroke-width="1.75" stroke-dasharray="5,2" d="M93.0084,-152C100.305,-152 107.867,-152 115.16,-152"/>
<polygon fill="black" stroke="black" points="115.236,-155.5 125.236,-152 115.236,-148.5 115.236,-155.5"/>
</g>
<!-- block1 -->
<g id="node5" class="node"><title>block1</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="275.5,-181.5 207.5,-181.5 207.5,-122.5 275.5,-122.5 275.5,-181.5"/>
<text text-anchor="middle" x="241.5" y="-164.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="241.5" y="-147.9" font-family="Sans" font-size="14.00">Old</text>
<text text-anchor="middle" x="241.5" y="-130.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block0&#45;&gt;block1 -->
<g id="edge8" class="edge"><title>block0&#45;&gt;block1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M193.8,-152C194.919,-152 196.045,-152 197.175,-152"/>
<polygon fill="black" stroke="black" points="197.337,-155.5 207.337,-152 197.337,-148.5 197.337,-155.5"/>
</g>
<!-- block2_1 -->
<g id="node6" class="node"><title>block2_1</title>
<polygon fill="lightgrey" stroke="black" stroke-width="1.75" points="426.5,-181.5 290.5,-181.5 290.5,-122.5 426.5,-122.5 426.5,-181.5"/>
<text text-anchor="middle" x="358.5" y="-164.9" font-family="Sans" font-size="14.00">Follows Old Rules</text>
<text text-anchor="middle" x="358.5" y="-147.9" font-family="Sans" font-size="14.00">But Violates</text>
<text text-anchor="middle" x="358.5" y="-130.9" font-family="Sans" font-size="14.00">New Rules</text>
</g>
<!-- block1&#45;&gt;block2_1 -->
<g id="edge13" class="edge"><title>block1&#45;&gt;block2_1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M275.656,-152C276.946,-152 278.255,-152 279.58,-152"/>
<polygon fill="black" stroke="black" points="279.999,-155.5 289.999,-152 279.999,-148.5 279.999,-155.5"/>
</g>
<!-- block2 -->
<g id="node10" class="node"><title>block2</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="403.5,-99.5 313.5,-99.5 313.5,-40.5 403.5,-40.5 403.5,-99.5"/>
<text text-anchor="middle" x="358.5" y="-82.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="358.5" y="-65.9" font-family="Sans" font-size="14.00">Old &amp; New</text>
<text text-anchor="middle" x="358.5" y="-48.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block1&#45;&gt;block2 -->
<g id="edge9" class="edge"><title>block1&#45;&gt;block2</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M275.523,-124.375C280.165,-120.81 284.911,-117.267 289.5,-114 294.245,-110.622 299.241,-107.197 304.284,-103.827"/>
<polygon fill="black" stroke="black" points="306.358,-106.652 312.781,-98.2264 302.506,-100.808 306.358,-106.652"/>
</g>
<!-- block4 -->
<g id="node8" class="node"><title>block4</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="617.5,-181.5 549.5,-181.5 549.5,-122.5 617.5,-122.5 617.5,-181.5"/>
<text text-anchor="middle" x="583.5" y="-164.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="583.5" y="-147.9" font-family="Sans" font-size="14.00">Old</text>
<text text-anchor="middle" x="583.5" y="-130.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block2_1&#45;&gt;block4 -->
<!-- block3 -->
<g id="node11" class="node"><title>block3</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="532.5,-99.5 442.5,-99.5 442.5,-40.5 532.5,-40.5 532.5,-99.5"/>
<text text-anchor="middle" x="487.5" y="-82.9" font-family="Sans" font-size="14.00">Follows</text>
<text text-anchor="middle" x="487.5" y="-65.9" font-family="Sans" font-size="14.00">Old &amp; New</text>
<text text-anchor="middle" x="487.5" y="-48.9" font-family="Sans" font-size="14.00">Rules</text>
</g>
<!-- block2&#45;&gt;block3 -->
<g id="edge10" class="edge"><title>block2&#45;&gt;block3</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M404.344,-70C413.183,-70 422.534,-70 431.651,-70"/>
<polygon fill="black" stroke="black" points="431.804,-73.5001 441.804,-70 431.804,-66.5001 431.804,-73.5001"/>
</g>
<!-- block3&#45;&gt;block4 -->
<g id="edge11" class="edge"><title>block3&#45;&gt;block4</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M523.732,-99.0918C529.712,-104.016 535.812,-109.115 541.5,-114 542.321,-114.705 543.148,-115.419 543.981,-116.141"/>
<polygon fill="black" stroke="black" points="541.724,-118.817 551.549,-122.781 546.34,-113.555 541.724,-118.817"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB