All: update images for reviewer feedback

Special thanks to Murchandamus who provided most of the feedback
develop
David A. Harding 9 months ago
parent 8d6972d719
commit 89b548d5b5

@ -806,7 +806,6 @@ key can produce a public key expressed in two different formats
addresses. However, the private key is identical for both Bitcoin
addresses.
//FIXME:misaligned text, see Murch CH04 feedback
[[pubkey_compression]]
[role="smallerseventy"]
.Public key compression

@ -366,7 +366,6 @@ header and summarizes all the data in all four transactions.
<<simple_merkle>> shows how the root is calculated by pair-wise hashes
of the nodes.
//FIXME: s/+/||/
[[simple_merkle]]
.Calculating the nodes in a merkle tree
image::images/mbc2_0902.png["merkle_tree"]
@ -379,7 +378,6 @@ shown in <<merkle_tree_odd>>, where transaction C is duplicated.
Similarly, if there are an odd number of hashes to process at any level,
the last hash is duplicated.
//FIXME: s/+/||/
[[merkle_tree_odd]]
.Duplicating one data element achieves an even number of data elements
image::images/mbc2_0903.png["merkle_tree_odd"]
@ -403,18 +401,11 @@ is unusual in Merkle trees). This results in certain sequences of
transactions leading to the same merkle root. For example, these two
trees:
//FIXME:replace with image to fix italics in code text
----
A A
/ \ / \
B C B C
/ \ | / \ / \
D E F D E F F
/ \ / \ / \ / \ / \ / \ / \
1 2 3 4 5 6 1 2 3 4 5 6 5 6
----
[[cve_tree]]
.Two Bitcoin-style merkle tree with the same root but a different number of leaves
image::images/cve-2012-2459.dot.png["Two Bitcoin-style merkle tree with the same root but a different number of leaves"]
for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
For transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
6 are repeated) result in the same root hash A (because the hash of both
of (F) and (F,F) is C).
@ -475,28 +466,12 @@ diagram).
image::images/mbc2_0905.png["merkle_tree_path"]
The efficiency of merkle trees becomes obvious as the scale increases.
<<block_structure2>> shows the amount of data that needs to be exchanged
as a merkle path to prove that a transaction is part of a block.
//FIXME: replace with a plot of size per txes: plot [0:16000] ceil(log2(x))
[[block_structure2]]
.Merkle tree efficiency
[options="header"]
|=======
|Number of transactions| Approx. size of block | Path size (hashes) | Path size (bytes)
| 16 transactions | 4 kilobytes | 4 hashes | 128 bytes
| 512 transactions | 128 kilobytes | 9 hashes | 288 bytes
| 2048 transactions | 512 kilobytes | 11 hashes | 352 bytes
| 65,535 transactions | 16 megabytes | 16 hashes | 512 bytes
|=======
With merkle trees, a node can download just the block headers (80
bytes per block) and still be able to identify a transaction's inclusion
in a block by retrieving a small merkle path from a full node, without
storing or transmitting the vast majority of the blockchain.
Clients that do not fully validate transactions, called lightweight
clients, use merkle paths to verify transactions without downloading
full blocks.
The largest possible block can hold almost 16,000 transactions in 4,000,000
bytes, but proving any particular one of those sixteen thousand transactions
is a part of that block only requires a copy of the transaction, a copy
of the 80-byte block header, and 448 bytes for the merkle proof. That
makes the largest possible proof almost 10,000 times smaller than the
largest possible Bitcoin block.
=== Merkle Trees and Lightweight Clients

@ -1205,11 +1205,11 @@ selection of the chain with the most Proof-of-Work.
A _best blockchain_ is whichever valid chain of blocks has
the most cumulative Proof-of-Work associated with it.
The
best chain will also have branches with blocks that are "siblings" to
best chain may also have branches with blocks that are "siblings" to
the blocks on the best chain. These blocks are valid but not part of the
best chain. They are kept for future reference, in case one of those
chains is extended and becomes the new best chain. In the next section
(<<forks>>), we will see how secondary chains occur as a result of an
many secondary chains later becomes primary. When sibling blocks occur,
they're usually the result of an
almost simultaneous mining of blocks at the same height.
When a new block is received, a node will try to add it onto the
@ -1219,7 +1219,7 @@ node will attempt to find that parent in the existing blockchain. Most
of the time, the parent will be the "tip" of the best chain, meaning
this new block extends the best chain.
Sometimes, as we will see in <<forks>>, the new block does not extend
Sometimes the new block does not extend
the best chain. In that case, the node will attach the new block to a
secondary chain and then compare the work of the secondary chain to the
previous best chain. If the secondary chain is now the best chain, the
@ -1239,138 +1239,8 @@ result of transmission delays in the global network. We will also look
at deliberately induced forks later in this chapter.
====
In the next few diagrams, we follow the progress of a "fork" event
across the network. The diagram is a simplified representation of the
Bitcoin network. For illustration purposes, different blocks are shown
as different shapes (star, triangle, upside-down triangle, rhombus),
spreading across the network. Each node in the network is represented as
a circle.
For
illustration purposes, each node contains a shape that represents the
block that it believes is currently the tip of the best chain. So, if
you see a star shape in the node, that means that the star block is the
tip of the best chain, as far as that node is concerned.
In the first diagram (<<fork1>>), the network has a unified perspective
of the blockchain, with the star block as the tip of the best chain.
[[fork1]]
[role="smallereighty"]
.Before the fork&#x2014;all nodes have the same perspective
image::images/mbc2_1002.png["Before the fork - all nodes have the same perspective"]
In <<fork2>>, we see two miners (Node X and Node Y) who mine two
different blocks almost simultaneously. Both of these blocks are
children of the star block, and extend the chain by building on top of
the star block. To help us track it, one is visualized as a triangle
block originating from Node X, and the other is shown as an upside-down
triangle block originating from Node Y.
[[fork2]]
[role="smallersixty"]
.Visualization of a blockchain fork event: two blocks found simultaneously
image::images/mbc2_1003.png["Visualization of a blockchain fork event: two blocks found simultaneously"]
Let's assume, for example, that a miner Node X finds a Proof-of-Work
solution for a block "triangle" that extends the blockchain, building on
top of the parent block "star." Almost simultaneously, the miner Node Y
who was also extending the chain from block "star" finds a solution for
block "upside-down triangle," his candidate block. Now, there are two
possible blocks; one we call "triangle," originating in Node X; and one
we call "upside-down triangle," originating in Node Y. Both blocks are
valid, both blocks contain a valid solution to the Proof-of-Work, and
both blocks extend the same parent (block "star"). Both blocks likely
contain most of the same transactions, with only perhaps a few
differences in the order of transactions.
As the two blocks propagate, some nodes receive block "triangle" first
and some receive block "upside-down triangle" first. As shown in
<<fork3>>, the network splits into two different perspectives of the
blockchain; one side topped with a triangle block, the other with the
upside-down-triangle block.
//FIXME:node X won't receive upside down triangle because it's not
//connected to a peer with that block. Same problem for Node Y
[[fork3]]
[role="smallersixty"]
.Visualization of a blockchain fork event: two blocks propagate, splitting the network
image::images/mbc2_1004.png["Visualization of a blockchain fork event: two blocks propagate, splitting the network"]
In the diagram, a randomly chosen "Node X" received the triangle block
first and extended the star chain with it. Node X selected the chain
with "triangle" block as the best chain. Later, Node X also received the
"upside-down triangle" block. Since it was received second, it is
assumed to have "lost" the race. Yet, the "upside-down triangle" block
is not discarded. It is linked to the "star" block parent and forms a
secondary chain. While Node X assumes it has correctly selected the
winning chain, it keeps the "losing" chain so that it has the
information needed to reorganize if the "losing" chain ends up
"winning."
On the other side of the network, Node Y constructs a blockchain based
on its own perspective of the sequence of events. It received
"upside-down triangle" first and elected that chain as the "winner."
When it later received "triangle" block, it connected it to the "star"
block parent as a secondary chain.
Neither side is "correct," or "incorrect." Both are valid perspectives
of the blockchain. Only in hindsight will one prevail, based on how
these two competing chains are extended by additional work.
Mining nodes whose perspective resembles Node X will immediately begin
mining a candidate block that extends the chain with "triangle" as its
tip. By linking "triangle" as the parent of their candidate block, they
are using their hashing power to build on that chain.
Any mining node whose perspective resembles Node Y will start building a
candidate node with "upside-down triangle" as its parent, extending the
chain that they believe is the best chain. And so, the race begins
again.
Forks are almost always resolved within one block. While part of the
network's hashing power is dedicated to building on top of "triangle" as
the parent, another part of the hashing power is focused on building on
top of "upside-down triangle." Even if the hashing power is almost
evenly split, it is likely that one set of miners will find a solution
and propagate it before the other set of miners have found any
solutions. Let's say, for example, that the miners building on top of
"triangle" find a new block "rhombus" that extends the chain (e.g.,
star-triangle-rhombus). They immediately propagate this new block and
the entire network sees it as a valid solution as shown in <<fork4>>.
[[fork4]]
[role="smallereighty"]
.Visualization of a blockchain fork event: a new block extends one fork, reorganizing the network
image::images/mbc2_1005.png["Visualization of a blockchain fork event: a new block extends one fork"]
All nodes that had chosen "triangle" as the winner in the previous round
will simply extend the chain one more block. The nodes that chose
"upside-down triangle" as the winner, however, will now see two chains:
star-triangle-rhombus and star-upside-down-triangle. The chain
star-triangle-rhombus now has more cumulative work than the
other chain. As a result, those nodes will set the chain
star-triangle-rhombus as the best chain and change the
star-upside-down-triangle chain to a secondary chain, as shown in
<<fork5>>. This is a chain reorganization, because those nodes are forced
to revise their view of the blockchain to incorporate the new evidence
of a longer chain. Any miners working on extending the chain
star-upside-down-triangle will now stop that work because their
block is "stale," as its parent "upside-down-triangle" is
no longer on the best chain. The transactions within
"upside-down-triangle" that are not within "triangle" are re-inserted in
the mempool for inclusion in the next block to become a part of the best
chain. The entire network converges on a single blockchain
star-triangle-rhombus, with "rhombus" as the last block in the chain.
All miners immediately start working on candidate blocks that reference
"rhombus" as their parent to extend the star-triangle-rhombus chain.
[[fork5]]
[role="smallereighty"]
.Visualization of a blockchain fork event: the network reorganizes on a new longest chain
image::images/mbc2_1006.png["Visualization of a blockchain fork event: the network reorganizes on a new longest chain"]
It is possible for a fork to extend to two blocks, if two
Forks are almost always resolved within one block.
It is possible for an accidental fork to extend to two blocks if both
blocks are found almost simultaneously by miners on opposite "sides" of
a previous fork. However, the chance of that happening is low.
@ -1856,13 +1726,9 @@ height 4, a one-block fork occurs. This is the type of spontaneous fork
we saw in <<forks>>. With the mining of block 5, the network converges
on one chain and the fork is resolved.
//FIXME:"The blocks following the new rules should have a unique color. I would have expected the "b-fork" to follow the old rules based on the colors."
// I was looking here where the other block was created, because I assumed that the enumeration would start with a) and then progress to b).
//
// Perhaps call this chain "7F11F" to indicate the new Foocoin rules?
[[blockchainwithforks]]
.A blockchain with forks
image::images/mbc2_1009.png[A blockchain with forks]
image::images/fork.dot.png[A blockchain with forks]
Later, however, at block height 6,
a new implementation of the client is released with a change in the

@ -634,7 +634,6 @@ blocks before commitment transaction #1 becomes valid.
shorter timelock, allowing it to be spent before the previous
commitments become valid.
//FIXME: s/3720/3721/
[[timelocked_commitments]]
.Each commitment sets a shorter timelock, allowing it to be spent before the previous commitments become valid
image::images/mbc2_1207.png["Each commitment sets a shorter timelock, allowing it to be spent before the previous commitments become valid"]

@ -132,7 +132,6 @@ payment to a public key hash), showing the combined script resulting
from the concatenation of the scripts prior to
validation.
//FIXME: revise to use "output script" and "input script" from chap 6
[[input_and_output_scripts_legacy]]
.Combining input and output scripts to evaluate a transaction script
image::../images/mbc2_0603.png["input_and_output_scripts"]
@ -1710,7 +1709,6 @@ his partners to spend their money frequently; the time delayed
conditions only exist in case something goes wrong. We can re-structure
our tree with this knowledge in <<diagram_mast3>>.
//FIXME: keep leaves in the same order, see Murch feedback chapter 7
[[diagram_mast3]]
.A MAST with the most-expected script in the best position
image::../images/mast3.dot.png["A MAST with the most-expected script in the best position"]

@ -0,0 +1,72 @@
// A A
// / \ / \
// B C B C
// / \ | / \ / \
// D E F D E F F
// / \ / \ / \ / \ / \ / \ / \
// 1 2 3 4 5 6 1 2 3 4 5 6 5 6
digraph MerkleTrees {
// General settings
rankdir=TB;
//node [shape=none, style=filled, color=lightblue];
node [shape=box, width=0, height=0];
ranksep=0.3;
nodesep=0.1
subgraph cluster_x {
// Merkle Tree 1
A1 [label="A"];
B1 [label="B"];
C1 [label="C"];
D1 [label="D"];
E1 [label="E"];
F1 [label="F"];
x1 [label="1"];
x2 [label="2"];
x3 [label="3"];
x4 [label="4"];
x5 [label="5"];
x6 [label="6"];
A1 -> B1;
A1 -> C1;
B1 -> D1;
B1 -> E1;
C1 -> F1;
D1 -> {x1, x2};
E1 -> {x3, x4};
F1 -> {x5, x6};
}
subgraph cluster_y {
// Merkle Tree 2
A2 [label="A"];
B2 [label="B"];
C2 [label="C"];
D2 [label="D"];
E2 [label="E"];
F2 [label="F"];
F2_dup [label = "F" ];
y1 [label="1"];
y2 [label="2"];
y3 [label="3"];
y4 [label="4"];
y5 [label="5"];
y6 [label="6"];
y5_dup [label="5"];
y6_dup [label="6"];
A2 -> B2;
A2 -> C2;
B2 -> D2;
B2 -> E2;
C2 -> {F2, F2_dup};
D2 -> {y1, y2};
E2 -> {y3, y4};
F2 -> {y5, y6};
F2_dup -> {y5_dup, y6_dup};
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

@ -0,0 +1,38 @@
digraph G {
rankdir=LR; // Left to Right direction
node [shape=box];
block1 [label="1"];
block2 [label="2"];
block3 [label="3"];
block4a [label="4a"];
block4b [label="4b"];
block5 [label="5"];
block6 [label="7"];
block7a [label="7a"];
block8a [label="8a"];
subgraph cluster_foocoin {
block7b [label="7b"];
block8b [label="8b"];
block9 [label="9"];
block10 [label="10"];
block11 [label="11"];
labelloc = "t"
label = "Using new rules"
}
block1 -> block2 [dir=back];
block2 -> block3 [dir=back];
block3 -> {block4a,block4b} [dir=back];
block4a -> block5 [dir=back];
block5 -> block6 [dir=back];
block6 -> {block7a,block7b} [dir=back];
block7a -> block8a [dir=back];
block7b -> block8b [dir=back];
block8b -> block9 [dir=back];
block9 -> block10 [dir=back];
block10 -> block11 [dir=back];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

@ -2,20 +2,20 @@ digraph merkle_tree {
splines=ortho;
node [shape=box, style="filled", color="black", fontcolor="black", fillcolor="white"];
"Merkle Root" -> "Hash AB";
"Merkle Root" -> "Hash C";
"Hash AB" -> "Hash A";
"Hash AB" -> "Hash B";
"Hash A" -> "A";
"Merkle Root" -> "Hash A";
"Merkle Root" -> "Hash BC";
"Hash BC" -> "Hash B";
"Hash BC" -> "Hash C";
"Hash A" -> "A" [minlen = 2];
"Hash B" -> "B";
"Hash C" -> "C" [minlen = 2];
"Hash C" -> "C";
"Merkle Root" [label="Merkle Root"];
"Hash AB" [label="Hash AB"];
"Hash BC" [label="Hash BC"];
"Hash A" [label="Hash A"];
"Hash B" [label="Hash B"];
"Hash C" [label="Hash C"];
"C" [label="2 <M> <S> <Z> 3 OP_CHECKMULTISIG", style="filled", fillcolor="silver"];
"A" [label="2 <M> <S> <Z> 3 OP_CHECKMULTISIG", style="filled", fillcolor="silver"];
"B" [label="<30 days> OP_CSV OP_DROP\n<Lawyer> OP_CHECKSIGVERIFY\n1 <M> <S> <Z> 3 OP_CHECKMULTISIG"];
"A" [label="<90 days> OP_CSV OP_DROP\n<Lawyer> OP_CHECKSIG"];
"C" [label="<90 days> OP_CSV OP_DROP\n<Lawyer> OP_CHECKSIG"];
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Loading…
Cancel
Save