Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: small word corrections #15

Merged
merged 16 commits into from
Mar 13, 2022
2 changes: 1 addition & 1 deletion book/01__consensus/02__crash-faults.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Computers are, unsurprisingly, the foundation of computational systems. However,

Communication lines between computers are similarly abstracted to remove any notion of an underlying physical medium. Whether information is transferred via electromagnetic waves, sound waves, or even carrier pigeon makes no difference to our analysis. We instead depict "logical" connections between nodes, over which nodes can send distinct packets of information called "messages." We further assume that some unknown amount of time must elapse between the moment that a message is sent and the moment at which it is received.

Lines of communication are necessary but not sufficient for collaboration between nodes. Just as humans need languages, nodes must share a vocabulary of sorts in oder to successfully send and receive information. These communication "protocols" allow nodes to understand the meaning of messages on the network. We generally do not define any specific communication protocol in theoretical network studies, though we do assume that one exists.
Lines of communication are necessary but not sufficient for collaboration between nodes. Just as humans need languages, nodes must share a vocabulary of sorts in order to successfully send and receive information. These communication "protocols" allow nodes to understand the meaning of messages on the network. We generally do not define any specific communication protocol in theoretical network studies, though we do assume that one exists.

### Protocols as a set of behaviors

Expand Down
2 changes: 1 addition & 1 deletion book/01__consensus/03__byzantine-faults.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ If the commander is a traitor, more formal reasoning is necessary to see the cor

A traitorous commanding general could coordinate with other traitors to attempt to give loyal generals different sets of orders. For instance, the traitors could choose to only send the conflicting order to half of the loyal generals. Without further communication, the loyal generals would not act in unison. We can provide a simple solution by requiring that loyal generals relay conflicting orders to all other generals. After this second round of communication, all loyal generals are guaranteed to share the same information. The paper shows that we can achieve the same result if loyal generals only relay orders with less than `f` votes, where `f` is the maximum number of traitors that can be safely handled by the system.

One way to understand the `3f + 1` general requirement for `f` traitors is again through the lens of a "threshold" for carrying out an action. In the context of crash-faults, we needed a threshold of `n - f` votes in order to make a decision. Since crashed nodes could not vote, we could derive that all of the `n - f` votes came from properly functioning nodes. When the faulty nodes, in this cause our traitorous generals, can actually contribute to the vote, we must increase the threshold to effectively discount the possibility of malicious votes.
One way to understand the `3f + 1` general requirement for `f` traitors is again through the lens of a "threshold" for carrying out an action. In the context of crash-faults, we needed a threshold of `n - f` votes in order to make a decision. Since crashed nodes could not vote, we could derive that all of the `n - f` votes came from properly functioning nodes. When the faulty nodes, in this case our traitorous generals, can actually contribute to the vote, we must increase the threshold to effectively discount the possibility of malicious votes.
2 changes: 1 addition & 1 deletion book/02__blockchains/01__digital-cash.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: "Digital Cash"

# {{ $frontmatter.title }}

From the ubiquity of money as a dominant system of social coordination it's no challenge to understand why attempts at digital financial products have been plentiful. Given the inherently social nature of money and finance, it should also come as no surprise that these projects gained significant traction with the launch of the world wide web in 1989. As the dotcom bubble made undeniably clear, the internet-connected universe was enamoured with a wholly digital vision of the future. Digital reality held limitless possibility, but it most certainly help digital money.
From the ubiquity of money as a dominant system of social coordination it's no challenge to understand why attempts at digital financial products have been plentiful. Given the inherently social nature of money and finance, it should also come as no surprise that these projects gained significant traction with the launch of the world wide web in 1989. As the dotcom bubble made undeniably clear, the internet-connected universe was enamoured with a wholly digital vision of the future. Digital reality held limitless possibility, but it most certainly helped digital money.

Beyond the apparent social impact of such a system, already confirmed by the success of other financial conveniences like the ATM, money was ultimately relatively straightforward to construct. Accounts, balances, and transactions translated cleanly into the computer databases necessary to represent finance in cyberspace. Even the ATM required the development of digital banking tools as early as the 1960s. With most of its raw components sitting in plain sight, digital money was simply waiting to be plugged into the internet.

Expand Down
4 changes: 2 additions & 2 deletions book/02__blockchains/02__open-access.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Although this may seem surprising, email spam prevention actually faced many of

Researchers looking into this problem found an interesting solution. Spam couldn't be entirely prevented, but it could be throttled. If users were required to pay for each email they sent, then spam would become increasingly costly. One 2014 report places the average number of spam emails sent per day at 54 billion messages. A charge of even a single US cent per email would cost the global spam industry upwards of 200 billion USD annually. It's undoubtedly clear that the number of spam emails would drop under such a model.

Although this system sounds ideal in theory, it still requires the existence of some gateway through which users can make the necessary payment for each email. Any form of online payment associated with traditional finance would force email users to register accounts old-world institutions, a concept that flew in the face of openly accessible email. Instead, researchers found that users could make "payment" in the form of an expenditure of electricity. Users could generate an email "stamp" by running a program that took, on average, a small fixed amount of time to execute. Stamp generation and verification was designed so that it was essentially impossible to decrease execution time. Even a short computation time on the order of a single second per email would massively throttle spam while leaving "real" users mostly unaffected.
Although this system sounds ideal in theory, it still requires the existence of some gateway through which users can make the necessary payment for each email. Any form of online payment associated with traditional finance would force email users to register accounts with old-world institutions, a concept that flew in the face of openly accessible email. Instead, researchers found that users could make "payment" in the form of an expenditure of electricity. Users could generate an email "stamp" by running a program that took, on average, a small fixed amount of time to execute. Stamp generation and verification was designed so that it was essentially impossible to decrease execution time. Even a short computation time on the order of a single second per email would massively throttle spam while leaving "real" users mostly unaffected.

Adam Back's HashCash is likely the most widely recognized of these constructions today. Crucially, HashCash popularized the concept of using hashing algorithms as a mechanism for proving that a certain amount of computational effort had been expended. This mechanism, which we often now call "Proof-of-Work," became a keystone of the peer-to-peer digital currencies to come. Proof-of-Work's importance is so crucial that it's necessary to fully understand its basic operation before we continue with our analysis of its eventual use.

Expand All @@ -40,7 +40,7 @@ Cryptographic hash functions are designed to be highly resistant to collisions,

We can demonstrate a simple partial collision under SHA256 quite easily. In the following example, two different inputs produce hashes that share the same first few bytes:

Partial hash collisions no significant impact on the security of a hash function. We find them useful, however, because the amount of computational effort required to find a collision depends on the number of bytes we're aiming to share between the two resulting hashes. Cryptographic hash functions are constructed to be almost entirely random, such that it's infeasible to "guess" the hash of an input without actually running it through the algorithm. From this property, we can determine the probability of finding a particular collision with some light mathematics.
Partial hash collisions have no significant impact on the security of a hash function. We find them useful, however, because the amount of computational effort required to find a collision depends on the number of bytes we're aiming to share between the two resulting hashes. Cryptographic hash functions are constructed to be almost entirely random, such that it's infeasible to "guess" the hash of an input without actually running it through the algorithm. From this property, we can determine the probability of finding a particular collision with some light mathematics.

Each byte of the hash output has 256 possible values, represented in hexadecimal as `0x00` to `0xFF`. The probability of finding an input with prefix `00` (or any other specific byte prefix), as the first values of the hash is therefore one in 256, meaning it takes 256 hash attempts on average to find such an input. Similarly, the probability of finding an input with `0000` as its first two bytes is `1/256 * 1/256 = 1/65536`, a total of 65,536 attempts on average. For each additional byte we want to match, the number of hash attempts required is multiplied by 256. Clearly, the number of required attempts grows extremely quickly as the number of bytes to match increases.

Expand Down
8 changes: 4 additions & 4 deletions book/02__blockchains/03__chains-of-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Perhaps, depending on the hash function, `hash(10, "Hello!", 6)` provides us wit
TODO: Diagram
:::

At this point, we are still emulating traditional BFT system, though we've replaced the way in which votes are generated. Now, we begin to partially diverge. Most BFT systems will elect a "leader" responsible for proposing potential updates to all other nodes in the system. Within a Proof-of-Work system, nodes will most likely not be aware of all other nodes in the network. If a designated leader were to exist, then it is possible that a node not be aware of the leader and, as a result, not be able to participate. Therefore, we need to eliminate the need for a designated leader.
At this point, we are still emulating traditional BFT system, though we've replaced the way in which votes are generated. Now, we begin to partially diverge. Most BFT systems will elect a "leader" responsible for proposing potential updates to all other nodes in the system. Within a Proof-of-Work system, nodes will most likely not be aware of all other nodes in the network. If a designated leader were to exist, then it is possible that a node could not be aware of the leader and, as a result, not be able to participate. Therefore, we need to eliminate the need for a designated leader.

::: tip TODO
TODO: Diagram
Expand All @@ -54,19 +54,19 @@ Let's take a look at the perspective of any one node in the system. For simplici
TODO: Diagram
:::

AS discussed in our sections regarding state and state transitions, a transaction acts as an input to some state transition function, which in turn mutates some initial state. The initial state can have an effect on the result of the transaction, so it's important that all nodes execute any given transaction against the same state. Therefore, a record of a transaction in the system must always include a reference to the specific state on which the transaction operates. Since the state may be quite large, we often use some commitment to the state, like a hash, instead of the full state.
As discussed in our sections regarding state and state transitions, a transaction acts as an input to some state transition function, which in turn mutates some initial state. The initial state can have an effect on the result of the transaction, so it's important that all nodes execute any given transaction against the same state. Therefore, a record of a transaction in the system must always include a reference to the specific state on which the transaction operates. Since the state may be quite large, we often use some commitment to the state, like a hash, instead of the full state.

Let's assume that our node has selected some transaction, `T0`, to attempt to process. We required that all nodes share the same initial state, which we'll call `S0`. The "thing" that our node wants to have recognized is that other nodes should accept `T0` as the transaction that mutates `S0` into some second new state, `S1`. We can describe this as the message `(S0, T0, S1)`.

Our node must now produce some "voting power" to attach to this message. The extent of the voting power attached will determine whether or not other nodes accept the message. As we previously explained, this means repeatedly performing `hash(ID, message, nonce)` until the node is satisfied with the result. Of course, we have yet to define the conditions under which a node would find the result sufficient. We can take a stab at a first attempt for this metric as follows.

The level of "work" a node is willing to do for any given transaction should, in theory, depend on the expected return for doing so. Any work performed translates directly into resource expenditure on the part of the node. Assuming that the node receives a reward for its effort, it seems sensible to say that a node will continue to do work on a particular transaction until the resources expended approximately equal the value of the reward. The node can then attach whichever result is the smallest. As we will shortly find out, this method is reasonable but not entirely ideal.
The level of "work" a node is willing to do for any given transaction should, in theory, depend on the expected return for doing so. Any work performed translates directly into resource expenditure on the part of the node. Assuming that the node receives a reward for its effort, it seems sensible to say that a node will continue to do work on a particular transaction until the resources expended approximately equals the value of the reward. The node can then attach whichever result is the smallest. As we will shortly find out, this method is reasonable but not entirely ideal.

Before we continue our analysis, we should briefly touch on the topic of reward values. This is a complex subject that we explore in much greater depth later within this text. For the moment, however, one may find it useful to assume that reward value is proportional to the value or "importance" for the transaction being processed. This mental model suggests that nodes will generally do more work for transactions that users wish to see processed quickly and spend less time on non-critical tasks.

Let's now shift our attention back to our individual node. Take the scenario in which `T0` is only valuable enough such that its associated reward covers a few seconds of work. After this short period of time, our node picks its smallest result and attaches it as the voting power for the message `(S0, T0, S1)`. The node then broadcasts the combined message and vote to the network of other nodes.

To understand what happens next, we must zoom out of the perspective of an individual node and look again at the network as a whole. IF we assume that all nodes are similar to our particular node, we find a network flooded with potential transactions to be executed against the genesis state. We chose the work time of a few seconds quite deliberately. At this interval, many nodes will finish their votes before the votes from others have enough time to propagate through the network. If nodes selected different transactions from the pool, there are now many conflicting messages of the form `(S0, T?, S1)`.
To understand what happens next, we must zoom out of the perspective of an individual node and look again at the network as a whole. If we assume that all nodes are similar to our particular node, we find a network flooded with potential transactions to be executed against the genesis state. We chose the work time of a few seconds quite deliberately. At this interval, many nodes will finish their votes before the votes from others have enough time to propagate through the network. If nodes selected different transactions from the pool, there are now many conflicting messages of the form `(S0, T?, S1)`.

::: tip TODO
TODO: Diagram
Expand Down
Loading