From 1749d3a5b156a0908b8c4b5ddb40467e7a68e22a Mon Sep 17 00:00:00 2001 From: Patrik Keller Date: Thu, 22 Dec 2022 12:24:21 +0100 Subject: [PATCH 1/6] Website. Fix typo in tailstorm protocol --- website/content/en/docs/protocols/tailstorm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/protocols/tailstorm.md b/website/content/en/docs/protocols/tailstorm.md index ee7923c4..419dacb8 100644 --- a/website/content/en/docs/protocols/tailstorm.md +++ b/website/content/en/docs/protocols/tailstorm.md @@ -148,7 +148,7 @@ def preference(old: Block, new: Block): def summarize(b: Block): - assert b.kind == "block" + assert b.kind == "summary" if len(confirming_sub_blocks(b)) < k: return [] # summary infeasible else: From 196234fd89d841a73b9154008fe8a81079a1adc0 Mon Sep 17 00:00:00 2001 From: Patrik Keller Date: Thu, 22 Dec 2022 13:34:37 +0100 Subject: [PATCH 2/6] Website. Docs landing page --- website/content/en/docs/prologue/faq.md | 3 +- .../content/en/docs/prologue/introduction.md | 75 +++++++++++++++++-- website/layouts/shortcodes/post.html | 1 + 3 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 website/layouts/shortcodes/post.html diff --git a/website/content/en/docs/prologue/faq.md b/website/content/en/docs/prologue/faq.md index fd6ca2e9..eae29ed1 100644 --- a/website/content/en/docs/prologue/faq.md +++ b/website/content/en/docs/prologue/faq.md @@ -27,4 +27,5 @@ no capacity to think about proof-of-stake. Please don't hesitate. You'll find my mail address in [my GitHub profile](https://github.com/pkel). For public communication, consider -creating a [new issue](https://github.com/pkel/cpr/issues). +creating a [new GitHub issue](https://github.com/pkel/cpr/issues) or a [new +GitHub discussion](https://github.com/pkel/cpr/discussions). diff --git a/website/content/en/docs/prologue/introduction.md b/website/content/en/docs/prologue/introduction.md index 33233dc7..025edeca 100644 --- a/website/content/en/docs/prologue/introduction.md +++ b/website/content/en/docs/prologue/introduction.md @@ -15,18 +15,77 @@ weight: 100 toc: true --- -## Get started +## Work in Progress -There are different ways for getting started, depending on what you want to do. +The whole website is under construction. There's not much information +for newcomers yet. At some point I want to provide tutorials the +following use-cases. -Unfortunately, documentation is lacking for all of them. At some point I -want to provide tutorials the following use-cases. - -- Evaluate existing protocols in a virtual environment. -- Evaluate existing attacks in a virtual environment. -- Search attacks against existing protocols using reinforcement learning. +- Evaluate specified protocols in a virtual environment. +- Evaluate supported attacks in a virtual environment. +- Search attacks against specified protocols using reinforcement learning. - Specification of protocols. - Specification of attack spaces. If you want to start now, don't hesitate to contact [me](https://github.com/pkel) for support. + +## Overview + +CPR’s core component is a network simulation engine for proof-of-work +protocols. The engine takes a protocol specification and a network +topology as input, then simulates the execution of the protocol in the +network over time. Additional tooling enables automated search for +attack strategies with reinforcement learning. + +I'm working on a detailed documentation such that my tooling becomes +useful for others. So far, I've documented most parts of the core +simulation engine, most of the specified protocols, and some useful +network topologies. + +The [virtual enviroment page]({{< method "virtual-environment" >}}) +informally describes CPR's approach to network simulation. The [protocol +specification page]({{< method "protocol-specification" +>}}) describes how we specify protocols. The [simulator page]({{< method +"simulator" >}}) describes how the simulator executes the specified +protocols in a virtual network. Read these pages in order, to learn +about the inner workings of CPR. Then, continue exploring the different +[proof-of-work consensus protocols]({{< protocol "overview" >}}). + +## Python/RL Quickstart + +CPR provides an OpenAI Gym environment for attack search with Python RL +frameworks. You can install it PyPI, if you meet the following +**requirements**. + +- Unix-like operating system with x86_64 support. I've tested Linux + (Fedora and Ubuntu) and Mac OSX. +- CPython, version >= 3.9 +- `pip` package installer for Python. + +In a terminal, run `pip install cpr-gym`. Then, you are ready to run the +following Python snippet which simulates 2016 steps (mined or received +blocks) of honest behaviour in [Nakamoto consensus]({{}}). + +```python +import gym +import cpr_gym + +env = gym.make("cpr-nakamoto-v0", episode_len = 2016) +obs = env.reset() +done = False +while not done: + action = env.policy(obs, "honest") + obs, rew, done, info = env.step(action) +``` + +Until I catch up with the documentation, consider reading [our +tests](https://github.com/pkel/cpr/tree/master/gym/tests) to find out +how to attack the other protocols and how to set important parameters +like the attacker capabilities [alpha and gamma]({{< post +"emulating-gamma" >}}). + +If the PyPI package does not work for you, consult the [GitHub +project](https://github.com/pkel/cpr) for instructions on building the +project from source. diff --git a/website/layouts/shortcodes/post.html b/website/layouts/shortcodes/post.html new file mode 100644 index 00000000..d39dfa63 --- /dev/null +++ b/website/layouts/shortcodes/post.html @@ -0,0 +1 @@ +{{ printf "/blog/%s" (.Get 0) | relref . }} From 61e6416c8ee3185756135c5845b782c36ea320b7 Mon Sep 17 00:00:00 2001 From: Patrik Keller Date: Fri, 23 Dec 2022 13:29:40 +0100 Subject: [PATCH 3/6] Website. Draft simulator pseudo-code --- .../content/en/blog/emulating-gamma/index.md | 2 +- website/content/en/docs/methods/simulator.md | 81 ++++++++++++++++--- .../content/en/docs/prologue/introduction.md | 2 +- 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/website/content/en/blog/emulating-gamma/index.md b/website/content/en/blog/emulating-gamma/index.md index 7a09161d..423bca03 100644 --- a/website/content/en/blog/emulating-gamma/index.md +++ b/website/content/en/blog/emulating-gamma/index.md @@ -290,7 +290,7 @@ def mining_delay(): return random.exponential(scale=1 / lambda_) -def miner(): +def select_miner(): dhr = (1 - alpha) / (n - 1) # defender hash rate hash_rates = [alpha] + [dhr] * (n - 1) return random.choice(range(n), p=hash_rates) diff --git a/website/content/en/docs/methods/simulator.md b/website/content/en/docs/methods/simulator.md index d67b077d..991396ed 100644 --- a/website/content/en/docs/methods/simulator.md +++ b/website/content/en/docs/methods/simulator.md @@ -53,13 +53,13 @@ all nodes are honest, `node(i)` for any `i` returns the tree functions In attack scenarios, `node(i)` returns nonconforming functions for the malicious nodes. -`mining_delay() -> float` and `miner() -> int` model proof-of-work -difficulty and hash-rates of the nodes. `mining_delay()` defines the -time between consecutive mining events. It is typically a random -function returning independent and exponentially distributed values. -`miner()` defines which node is successful at a particular mining event. -It is typically a random function which selects nodes based on their -relative hash-rate. +`mining_delay() -> float` and `select_miner() -> int` model +proof-of-work difficulty and hash-rates of the nodes. `mining_delay()` +defines the time between consecutive mining events. It is typically a +random function returning independent and exponentially distributed +values. `select_miner()` defines which node is successful at a +particular mining event. It is typically a random function which selects +nodes based on their relative hash-rate. ### Example @@ -97,8 +97,8 @@ with `n = 15`. block interval of about 554 seconds. Individual block intervals are exponentially distributed. To meet the average block interval, we scale the distribution by factor 554 and let `mining_delay()` do the sampling. -`miner()` returns a random node according to the hash-rate distribution -in the table. +`select_miner()` returns a random node according to the hash-rate +distribution in the table. Regarding the communication, me make a another simplification. We assume that all nodes are connected to each other and that blocks propagate in @@ -117,7 +117,7 @@ def mining_delay(): return random.exponential(scale=554) -def miner(): +def select_miner(): hash_rates = [0.24817, 0.20147, ..., 0.00275, 0.01] # from table return random.choice(range(n), p=hash_rates) @@ -147,6 +147,67 @@ def node(i): TODO. High level description of the simulator as concurrent program with waiting. +```python +# initialization +dag = DAG() +state = [] +blocks = [dag.add(r) for r in roots()] +for b in blocks: + for i in range(n): + dag.make_visible(b, i) +for i in range(n): + dag.set_view(i) + init, _update, _mining = node(i) + state[i] = init(blocks) + +# proof-of-work loop +while true: + wait_seconds(mining_delay()) + i = select_miner() + dag.set_view(i) + _init, _update, mining = node(i) + draft = mining() + block = dag.add(draft) + block.pow = True + if validity(block): + deliver(block, i, "proof-of-work") + + +def deliver(block, i, event): + # deliver block in DAG-order + wait_until( + lambda: all([dag.is_visible(b, i) for b in block.parents()]) + ) + + # deliver block once + if dag.is_visible(block, i): + return + dag.make_visible(block, i) + + # simulate node-action + dag.set_view(i) + _init, update, _mining = node(i) + upd = update(state[i], block, event) + + # handle state update + state[i] = upd.state + + # handle communication + for m in upd.share: + for dst in neighbours(node): + after_seconds( + message_delay(node, dst), + lambda: deliver(dst, m, "network"), + ) + + # handle non-proof-of-work appends + for draft in upd.append: + block = dag.add(draft) + block.pow = False + if validity(block): + deliver(block, node, "append") +``` + ## Discrete event simulation TODO. Speeding things up with DES. diff --git a/website/content/en/docs/prologue/introduction.md b/website/content/en/docs/prologue/introduction.md index 025edeca..4707d4c4 100644 --- a/website/content/en/docs/prologue/introduction.md +++ b/website/content/en/docs/prologue/introduction.md @@ -72,7 +72,7 @@ blocks) of honest behaviour in [Nakamoto consensus]({{ Date: Fri, 20 Jan 2023 11:55:42 +0100 Subject: [PATCH 4/6] Proofread blog/emulating-gamma --- .../content/en/blog/emulating-gamma/index.md | 115 +++++++++--------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/website/content/en/blog/emulating-gamma/index.md b/website/content/en/blog/emulating-gamma/index.md index 423bca03..22e914ab 100644 --- a/website/content/en/blog/emulating-gamma/index.md +++ b/website/content/en/blog/emulating-gamma/index.md @@ -52,8 +52,8 @@ first in case of a block race. I like this approach because it reduces a wide variety of possible network conditions into a single, explainable parameter. The big drawback is the close coupling of the definition with the [attacked -protocol]({{< protocol "nakamoto" >}}) and the [corresponding attack -space](#missing-pieces). +protocol]({{< protocol "nakamoto" >}}) and the corresponding attack +space. ## CPR's Generic Network @@ -65,8 +65,8 @@ sending node, outgoing connection, and message. {{< img-figure src="net4.png" alt="Fully-connected network with 4 nodes" >}} CPR network example. Circles represent nodes, arrows represent outgoing -connections. The four nodes are fully connected; message forwarding is -not necessary. +connections. The four nodes are fully connected, thus message +forwarding is not necessary. {{< /img-figure >}} In the remainder of this post, I will describe how to model CPR networks @@ -79,38 +79,37 @@ network assumptions compatible with the Selfish Mining literature. ## Reordering Messages In the Selfish Mining literature, $\gamma$ represents the share of -defenders (by hash-rate) who adopt the attacker's block in case of a -block race. The term block race refers to a situation where one of the -honest nodes mines a new block $b_0$ while the attacker already has -mined---but kept private---a block $b_1$ of the same height. If the -attacker decides to release $b_1$ at the very same time, the defenders' -reactions depend on individual message propagation delays and hence the -network assumptions. Defender's will proceed mining on the block they -received first. Attackers with network-level capabilities can delay -propagation of $b_0$ and hence make the defenders prefer the attacker's -block $b_1$. The prevalent assumption is that, after each block race -$\gamma$ of the defender's hash-rate is used to mine on $b_1$, the rest -on $b_0$. - -The block race situation uses what BFT researches would call message -reordering. The honest miner sends $b_0$ before the attacker sends -$b_1$, but (some of) the other defender nodes receive $b_1$ before $b_0$. -The $\gamma$ parameter abstractly defines how often and to which -defenders this reordering succeeds. - -Based on the more general notion of message reordering, we can derive a -CPR-network exhibiting a given $\gamma.$ +defenders (weighted by hash-rate) who adopt the attacker's block in case +of a block race. The term *block race* refers to a situation where one +of the honest nodes mines a new block $b_0$ while the attacker already +has mined---but kept private---a block $b_1$ of the same height. If the +attacker decides to release $b_1$ at the very same time it is not +obvious how the defenders will react. The [protocol]({{< protocol +"nakamoto" >}}) prescribes to prefer the block first received, but this +depends on individual message propagation delays. Attackers with +network-level capabilities can delay propagation of $b_0$ and hence make +the defenders prefer the attacker's block $b_1$. The prevalent +assumption is that, after each block race, $\gamma$ of the defender's +hash-rate is used to mine on $b_1$, the rest on $b_0$. + +This attack relies on what BFT researches would typically call *message +reordering*. The honest miner sends $b_0$ before the attacker sends +$b_1$, but (some of) the remaining defender nodes receive $b_1$ before +$b_0$. The $\gamma$ parameter abstractly defines how often the +reordering succeeds. +Based on this more general notion of message reordering, we can derive a +CPR network exhibiting a given $\gamma$. ## Constructing a Network We start by imposing a couple of restrictions on the design space. -First, the network should consist of $n \geq 3$ nodes. One attacker and -at least two defenders. We need at least two defenders---one sends a -message before the attacker does, the other receives the two messages, -potentially in reversed order. Second, all defenders have the same -hash-rate. Third, the nodes are fully-connected, that is, each node has -outgoing connections to all other nodes. Forth, the attacker receives -all messages immediately. Fifth, message delays between defenders are +First, the network should consist of $n \geq 3$ nodes. We need one +attacker and at least two defenders---one sends a message before the +attacker does, the other receives the two messages in potentially +reversed order. Second, all defenders have the same hash-rate. Third, +the nodes are fully-connected, that is, each node has outgoing +connections to all other nodes. Forth, the attacker receives all +messages immediately. Fifth, message delays between defenders are constant but small, let's say $\varepsilon$. Sixth, all outgoing connections from the attacker to defender have the same properties. @@ -126,7 +125,7 @@ With these restrictions in place, we have only one dimension left. How do we have to delay messages from attacker to defender, such that $\gamma$ of the block races end in favor of the attacker? -There are one attacker node and $n - 1$ defender nodes. One of the +We have one attacker node and $n - 1$ defender nodes. One of the defenders sends a message---in Selfish Mining that would be a freshly mined block. The other $n - 2$ defenders receive the message after $\varepsilon$ time. The attacker receives it immediately, sends another @@ -176,7 +175,7 @@ $\gamma$-assumption in Selfish Mining. ## Limiting Gamma -It is common practice to evaluate Selfish Mining for $\gamma = 1$. +Related literature evaluates Selfish Mining for $\gamma = 1$. This is not possible with our approach. But $\gamma = 1$ is also not possible in practice. @@ -194,28 +193,28 @@ first. In our network with $n-1$ defenders this manifest as follows. After any block race, $\frac{1}{n-1}$ of the defenders' hash-rate will be used to mine on the honest block. Consequently, $\gamma$ must be lower or equal $1 - -\frac{1}{n-1} = \frac{n-2}{n-1}$. In reverse, in order to emulate a -given $\gamma$ we have to simulate at least $n \geq \frac{1}{1 - -\gamma}+ 1$ nodes. Setting $\gamma = 1$ implies $n = \infty$ and makes -simulations unfeasible. +\frac{1}{n-1} = \frac{n-2}{n-1}$. Thus, in order to emulate a given +$\gamma$ we have to simulate at least $n \geq \frac{1}{1 - \gamma}+ 1$ +nodes. Setting $\gamma = 1$ implies $n = \infty$ and makes simulations +unfeasible. Astute readers will now (at the latest) start questioning the formulas in the previous section. Why does the limitation presented here not show -up above? It's because one of the steps requires qualification. We used -that $D_i$ is uniformly distributed on the interval from $0$ to $d$. -Then we said that $P[D_i < \varepsilon] = \frac{\varepsilon}{d}$. That's -true if $d \geq \varepsilon$ but otherwise the probability is $1$. -As a result, $E[X] \leq n-2$ and $\gamma \leq \frac{n-2}{n-1}$. +up above? It's because one of the steps above requires qualification. We +used that $D_i$ is uniformly distributed on the interval from $0$ to +$d$. Then we said that $P[D_i < \varepsilon] = \frac{\varepsilon}{d}$. +That's true if $d \geq \varepsilon$ but otherwise the probability is +$1$. As a result, $E[X] \leq n-2$ and $\gamma \leq \frac{n-2}{n-1}$. -In the real world, most of the hash-rate is concentrated around a view +In the real world, most of the hash-rate is concentrated around a few nodes. In December 2022, the two biggest Bitcoin mining pools have 26% -and 19% of the overall hash-rate. Assume the bigger one turns malicious -and starts selfish mining. That leaves 74% of the hash rate to the -defender, of which about 26% belong to the second-biggest miner -(the 19% one). In 26% of the block races, the second-biggest miner will -be the sender of the block which the attacker tries to outrun. So in -26% of the cases 26% of the defender hash-rate will not mine on the -attacker's block. This alone makes $\gamma > 0.94$ unrealistic. +and 19% of the overall hash-rate. Let's assume the bigger one turns +malicious and starts selfish mining. That leaves 74% of the hash-rate to +the defender, of which about 26% belong to the second-biggest miner (the +19% one). In 26% of the block races, the second-biggest miner will be +the sender of the block which the attacker tries to outrun. So in 26% of +the cases 26% of the defender hash-rate will not mine on the attacker's +block. This alone makes any $\gamma > 0.94$ unrealistic. ## Choosing Parameters @@ -226,7 +225,7 @@ description]({{< method "simulator" >}}) additionally sets the attacker's relative hash-rate $\alpha$, and the network's overall mining rate $\lambda$. -A couple of restrictions follow either from definitions of the +A couple of restrictions follow either from the definitions of the parameters themselves or from the construction above. * Gamma and alpha are fractions, thus $0 \leq \gamma \leq 1$ and $0 \leq @@ -249,22 +248,22 @@ to avoid them. That's possible by setting $\varepsilon \ll \lambda^{-1}$, that is, making the defender's message delay much smaller than the (expected) block interval. A nice trick is to set $\lambda = 1$ which implies that the natural orphan rate is bounded by $\varepsilon$. -We typically use $\lambda = 1$ and $\varepsilon = 10^{-5}$. +We typically use $\lambda = 1$ and $\varepsilon = 10^{-9}$. The network size $n$ matters as well. In Selfish Mining, after *each* block race *exactly* $\gamma$ of the defender hash-rate mines on the attacker's block. In the constructed network, the number of defenders mining on the attacker's block is random. The expected value is $\gamma$ -by construction. But the variance depends on the number of defenders. +by construction, but the variance depends on the number of defenders. Higher $n$ implies more messages per block race and---by the law of large numbers---less variance around $\gamma$. ## Specification -Last step is to produce some Python-like specification that works as +The last step is to produce some Python-like specification that works as input for our [network simulator]({{< method "simulator" >}}). As -promised, it works with any protocol specification (supplied in Python -module `protocol`) and attack (supplied in `attacker`). +promised above, it works with any protocol specification (supplied in +Python module `protocol`) and attack (supplied in `attacker`). ```python import protocol # protocol specification @@ -275,7 +274,7 @@ from numpy import random n = 42 # network size alpha = 1 / 3 # attacker's relative hash-rate gamma = 0.5 # Selfish Mining's Gamma -epsilon = 1e-5 # propagation delay honest --> honest +epsilon = 1e-9 # propagation delay honest --> honest lambda_ = 1 / 600 # network's mining rate # Safety checks: From ecd86fae2a383c6f8706c7a2de418a837c1290fa Mon Sep 17 00:00:00 2001 From: Patrik Keller Date: Wed, 8 Feb 2023 17:08:47 +0100 Subject: [PATCH 5/6] Website. Write methods/simulator docs page --- website/config/_default/config.toml | 2 +- website/content/en/blog/btc-network/index.md | 99 +++++ .../taylor-vick-M5tzZtFCOfs-unsplash.jpg | Bin 0 -> 124393 bytes .../en/blog/launching-website/index.md | 4 +- .../methods/concurrent_programming_asyncio.py | 62 +++ .../en/docs/methods/protocol-specification.md | 68 ++-- website/content/en/docs/methods/simulator.md | 377 ++++++++++++------ .../en/docs/methods/virtual-environment.md | 31 +- website/content/en/docs/protocols/nakamoto.md | 2 +- website/package.json | 2 +- 10 files changed, 476 insertions(+), 171 deletions(-) create mode 100644 website/content/en/blog/btc-network/index.md create mode 100644 website/content/en/blog/btc-network/taylor-vick-M5tzZtFCOfs-unsplash.jpg create mode 100644 website/content/en/docs/methods/concurrent_programming_asyncio.py diff --git a/website/config/_default/config.toml b/website/config/_default/config.toml index 35a2d015..e6936183 100644 --- a/website/config/_default/config.toml +++ b/website/config/_default/config.toml @@ -62,7 +62,7 @@ rel = "sitemap" tag = "tags" [permalinks] - blog = "/blog/:title/" + blog = "/blog/:year/:month/:slugorfilename/" # docs = "/docs/1.0/:sections[1:]/:title/" [minify.tdewolff.html] diff --git a/website/content/en/blog/btc-network/index.md b/website/content/en/blog/btc-network/index.md new file mode 100644 index 00000000..84051fbd --- /dev/null +++ b/website/content/en/blog/btc-network/index.md @@ -0,0 +1,99 @@ +--- +title: "Modelling the Bitcoin Network" +description: | + (draft). This block post does not have enough content yet. +excerpt: | + (draft). This block post does not have enough content yet. +date: 2023-02-13 +draft: true +weight: 50 +images: ["taylor-vick-M5tzZtFCOfs-unsplash.jpg"] +categories: ["Constructions"] +tags: ["bitcoin", "network", "assumptions"] +contributors: ["Patrik Keller"] +pinned: false +homepage: false +--- + +**TL;DR:** (draft). This block post does not have enough content yet. + +In this blog posts I'll shortly present a simple but realistic network +scenario that models Bitcoin as it is deployed today. We'll have a look +at the Bitcoin mining statistics and model our +[virtual network]({{< method "simulator" >}}#inputs) accordingly. + +We obtain an estimate about the hash-rate distribution from +[blockchain.com](https://www.blockchain.com/explorer/charts/pools). +The following table shows mining statistics for the last 7 days before +December 14th 2022. + +| Miner / Pool | Relative Hash-Rate | Blocks Mined | +| ------------ | ------------------ | ------------ | +| Foundry USA | 24,817% | 271 | +| AntPool | 20,147% | 220 | +| F2Pool | 15,110% | 165 | +| Binance Pool | 13,736% | 150 | +| ViaBTC | 10,440% | 114 | +| Braiins Pool | 5,311% | 58 | +| Poolin | 2,473% | 27 | +| BTC.com | 1,923% | 21 | +| Luxor | 1,648% | 18 | +| Mara Pool | 1,465% | 16 | +| Ultimus | 0,641% | 7 | +| SBI Crypto | 0,641% | 7 | +| BTC M4 | 0,366% | 4 | +| Titan | 0,275% | 3 | +| Unknown | rest, about 1% | 11 | + +There are 14 big and identifiable miners. The other participants' hash +rates sum up to about 1%. We simplify the network by combining the +unknown participants into a single node. Hence we end up with `n = 15`. + +1092 blocks have been mined over the past 7 days, implying an average +block interval of about 554 seconds. The underlying proof-of-work +puzzle can only be solved by repeated guessing. Thus individual block +intervals are exponentially distributed. We define `mining_delay()` to +meet these observations. `select_miner()` returns a random node +according to the hash-rate distribution in the table. + +Regarding the communication, me make a another simplification. We assume +that all nodes are connected to each other and that blocks propagate in +6 seconds with a uniformly distributed jitter of ± 2 seconds. + +We further assume that all nodes are honest. We load [the specification +of Nakamoto consensus]({{< protocol "nakamoto" >}}) from the +module `nakamoto`. + +```python +import nakamoto # protocol specification +from numpy import random + + +def mining_delay(): + return random.exponential(scale=554) + + +def select_miner(): + hash_rates = [0.24817, 0.20147, ..., 0.00275, 0.01] # from table + return random.choice(range(n), p=hash_rates) + + +def neighbours(i): + return [x for x in range(n) if x != i] + + +def message_delay(src, dst): + return 6 + random.uniform(low=-2, high=2) + + +def roots(): + return nakamoto.roots() + + +def validity(block): + return nakamoto.validity(block) + + +def node(i): + return (nakamoto.init, nakamoto.update, nakamoto.mining) +``` diff --git a/website/content/en/blog/btc-network/taylor-vick-M5tzZtFCOfs-unsplash.jpg b/website/content/en/blog/btc-network/taylor-vick-M5tzZtFCOfs-unsplash.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3d75e70345d720ac7623ad19f6012205ad6d3a55 GIT binary patch literal 124393 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

NhSxb@rf*0fiBoEVo}8Y03XI=*>&Hr=V}Y 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 4, f, "e") +f("b") + +## end of program / script + +## begin of asyncio boilerplate + + +async def main(): + while True: + assert delay.count >= 0 + if delay.count == 0: + return + else: + await asyncio.sleep(1e-6) + + +loop.run_until_complete(main()) diff --git a/website/content/en/docs/methods/protocol-specification.md b/website/content/en/docs/methods/protocol-specification.md index a35c411a..f2d981b1 100644 --- a/website/content/en/docs/methods/protocol-specification.md +++ b/website/content/en/docs/methods/protocol-specification.md @@ -45,14 +45,12 @@ functions mentioned above. ## Blockchain -Protocols specify and use a global, append-only data-structure. [A-priori, blocks form a directed acyclic graph (DAG)](../virtual-environment#blobs-hashes-blockchain). Each block has -an arbitrary number of parent blocks and can store arbitrary data. The -`validity` function then restricts what blocks can be appended and -thereby imposes a certain structure on the DAG. - -The `validity` function takes a block as argument. It may return `True` +an arbitrary number of parent blocks and can store arbitrary data. +Protocol designers can impose additional structure by specifying a +restrictive `validity` function. +This function takes a block as argument. It may return `True` or `False`, or it may fail. The specification consumer must ensure that all appended blocks are valid, that is, `validity` returns `True`. @@ -99,7 +97,8 @@ subset](../virtual-environment#visibility-and-communication) of the blockchain depending on what information the other nodes share, when they share it, and how messages propagate through the network. -Nodes are specified with three functions `init`, `update`, and `mining`. +Protocol designers specify the behaviour of honest nodes through three +functions `init`, `update`, and `mining`. `init` takes a list of blocks as argument and returns the node's initial state. The specification consumer must ensure that the list of blocks @@ -119,22 +118,22 @@ block. {{< /code-figure >}} `update` informs the node about new blocks. It takes as argument the -node's old state, the new block, and a string indicating how the new -block became visible locally. It returns a new state, a list of blocks -to share, and a list of blocks to append without proof-of-work. The -protocol designer must ensure that +node's old state, the new block, and a string indicating the source of +the block. It returns a new state, a list of blocks to share, and a list +of blocks to append without proof-of-work. The specification consumer +must ensure that * `update` is called on all blocks as they become locally visible, -* the new block given as argument and all its ancestors are locally visible, +* the new block (second argument) and all its ancestors are locally visible, * the returned state will be given as first argument to the next update, * the to-be-shared blocks are validated and sent to the other nodes, * the to-be-appended blocks are validated, appended to the global block DAG, and made visible locally, -* the `event` argument is `"mining"` if the new block was mined +* the third argument is `"mining"` if the new block was mined locally, -* the `event` argument is `"append"` if the new block was appended locally +* the third argument is `"append"` if the new block was appended locally without proof-of-work, and -* the `event` argument is `"network"` if the new block was received from the +* the third argument is `"network"` if the new block was received from the network. {{< code-figure >}} @@ -181,14 +180,14 @@ that * `b.has_pow()` is true if and only if `b` was appended through proof-of-work, and * when a node learns about a successful proof-of-work with -`update(old_state, new_block, event = "mining")` it holds that +`update(old_state, new_block, "mining")` it holds that `new_block == mining(old_state)`. {{< code-figure >}} ```python def mining(b: Block): - return Block(height=b.height + 1, parents=[b], miner=Env.my_id) + return Block(height=b.height + 1, parents=[b], miner=my_id) ``` In [Nakamoto consensus]({{< protocol "nakamoto" >}}) all blocks require @@ -223,20 +222,11 @@ timestamps in orphaned blocks cannot be used. In short, difficulty adjustment is a complex control problem. It even has its own line of research. -Luckily, DA is somewhat orthogonal to consensus. In practice, -proof-of-work protocols require a DAA but in theory can often get away -without. Depending on the analysis, we either assume that the true -hash-rate is constant and known or we assume that the DAA does a perfect -job. To support the latter, protocols designers have to specify what -kind of growth the DAA should control for. In Bitcoin, the growth rate -equals increase in block height per time. Other protocols might choose a -different metric. - -The protocol specification defines a single function `progress` that -maps a given block (tip of blockchain) to a scalar value. The engineer -implementing the protocol will contribute a DAA that controls for -constant progress per time. The analyst sometimes assumes constant -progress per time. +Protocol designers use the `progress` function to specify what kind of +growth the DAA should control for. The function maps a given block (tip +of blockchain) to a scalar value. The engineer implementing the protocol +will contribute a DAA that controls for constant progress per time. The +analyst may just assume constant progress per time. {{< code-figure >}} @@ -261,20 +251,20 @@ participant, namely the holders of the private keys and hence users. In principle, crypto-currency users and node operators can be disjunct. -Users may operate a node but they do not have to. But in practice, +Users may operate a node but they do not have to. But in practice blockchain protocols motivate participation as operator by handing out crypto-currency denoted rewards. Hence node operators usually are crypto-currency users. As protocol designers, we want our protocol to accommodate as many -applications as possible. We avoid imposing requirements on the +applications as possible. We thus avoid imposing requirements on the crypto-currency. We just assume that each node has access to a unique identifier `my_id` that can receive rewards. In practice, `my_id` would be the account or wallet address of the node's operator. The specification itself however does not have any notion of crypto-currency address or wallet. -We specify reward calculation using four functions `local_tip`, `global_tip`, +We specify incentive mechanisms using four functions `local_tip`, `global_tip`, `history` and `reward`. * `local_tip` takes a node's state as argument and returns its preferred @@ -283,7 +273,7 @@ tip of the chain. tips. * `history` calculates the linear history of the best tip. * `reward` maps a block (in the linear history) to reward assignments. -* A reward assignment assigns a scalar reward to a node id. +* Each reward assignment assigns a scalar reward to a node id. {{< code-figure >}} @@ -326,6 +316,8 @@ calculate different useful metrics like * individual rewards for each block, and * accumulated historic rewards per node for any tip of the chain. -The reward API can model situations where miners get assigned rewards -for blocks that are not part of the linear history. This happens for -example in [tree-structured voting]({{< protocol "parallel-tree" >}}). +Note that this reward specification can model situations where miners +get assigned rewards for blocks that are not part of the linear history. +This happens for example in [tree-structured voting]({{< protocol +"parallel-tree" +>}}). diff --git a/website/content/en/docs/methods/simulator.md b/website/content/en/docs/methods/simulator.md index 991396ed..bfd5b023 100644 --- a/website/content/en/docs/methods/simulator.md +++ b/website/content/en/docs/methods/simulator.md @@ -13,8 +13,6 @@ weight: 230 toc: true --- -{{< alert icon="👉" text="WIP. You are looking at an unfinished page." />}} - Having talked about our [model for virtual protocol executions](../virtual-environment) and about [how we specify protocols](../protocol-specification), we can proceed with the @@ -25,6 +23,9 @@ in a compiled language to achieve good performance. ## Inputs +The simulator takes as input the following assumptions about the network +and participating nodes. + `n: int` defines the number of nodes, `range(n)` addresses the individual nodes. @@ -48,7 +49,7 @@ invalid blocks. `node(i: int) -> tuple[init, update, mining]` defines the behaviour of nodes as discussed in the [the section on protocol specifications](../protocol-specification). In the simplest case, when -all nodes are honest, `node(i)` for any `i` returns the tree functions +all nodes are honest, `node(i)` for all `i` returns the three functions `init`, `update`, and `mining` as defined in the protocol specification. In attack scenarios, `node(i)` returns nonconforming functions for the malicious nodes. @@ -61,64 +62,21 @@ values. `select_miner()` defines which node is successful at a particular mining event. It is typically a random function which selects nodes based on their relative hash-rate. -### Example - -We provide an intuition about the simulator inputs by walking through a -realistic (but still simplified) example scenario. We consider [Nakamoto -consensus]({{< protocol "nakamoto" >}}) as it is deployed in Bitcoin. -The following table shows mining statistics for the last 7 days before -Dec. 14 2022. We got it from -[blockchain.com](https://www.blockchain.com/explorer/charts/pools). - -| Miner / Pool | Relative Hash-Rate | Blocks Mined | -| ------------ | ------------------ | ------------ | -| Foundry USA | 24,817% | 271 | -| AntPool | 20,147% | 220 | -| F2Pool | 15,110% | 165 | -| Binance Pool | 13,736% | 150 | -| ViaBTC | 10,440% | 114 | -| Braiins Pool | 5,311% | 58 | -| Poolin | 2,473% | 27 | -| BTC.com | 1,923% | 21 | -| Luxor | 1,648% | 18 | -| Mara Pool | 1,465% | 16 | -| Ultimus | 0,641% | 7 | -| SBI Crypto | 0,641% | 7 | -| BTC M4 | 0,366% | 4 | -| Titan | 0,275% | 3 | -| Unknown | rest, about 1% | 11 | - -We observe that there are 14 big and identifiable miners. The other -participants' hash rates sum up to about 1%. In our simplified scenario -we combine the unknown participants into a single node. Hence we end up -with `n = 15`. - -1092 blocks have been mined over the past 7 days, implying an average -block interval of about 554 seconds. Individual block intervals are -exponentially distributed. To meet the average block interval, we scale -the distribution by factor 554 and let `mining_delay()` do the sampling. -`select_miner()` returns a random node according to the hash-rate -distribution in the table. - -Regarding the communication, me make a another simplification. We assume -that all nodes are connected to each other and that blocks propagate in -6 seconds with a uniformly distributed jitter of ± 2 seconds. - -We further assume that all nodes are honest and that [the specification -of Nakamoto consensus]({{< protocol "nakamoto" >}}) is provided in the -Python module `nakamoto`. +{{< code-figure >}} ```python import nakamoto # protocol specification from numpy import random +n = 7 + def mining_delay(): - return random.exponential(scale=554) + return random.exponential(scale=600) def select_miner(): - hash_rates = [0.24817, 0.20147, ..., 0.00275, 0.01] # from table + hash_rates = range(1, n + 1) return random.choice(range(n), p=hash_rates) @@ -127,7 +85,7 @@ def neighbours(i): def message_delay(src, dst): - return 6 + random.uniform(low=-2, high=2) + return 6 def roots(): @@ -142,100 +100,293 @@ def node(i): return (nakamoto.init, nakamoto.update, nakamoto.mining) ``` -## Naive real time simulation +Example network with `n = 7` nodes following the [Nakamoto +consensus]({{< protocol "nakamoto" >}}) protocol. All messages are +delayed for 6 seconds. The block interval will be about 10 minutes. +Hash-rates are chosen arbitrarily. + +{{< /code-figure >}} + +## Concurrent Programming + +We describe the simulator as a concurrent program. +The program does not use parallelism---all computations happen +sequentially in a single thread. +We introduce two primitives to delay function evaluation. + +- `delay(n, fun, *args)` schedules the evaluation of `fun(*args)` in `n` + seconds. While waiting, other computations may happen concurrently. +- `delay_until(prop, fun, *args)` schedules the evaluation of +`fun(*args)` as soon as `prop()` returns `True`. While `prop()` returns +`False` other computations may take place concurrently. + +Consider the following example program which prints the letters *a* to +*f* in order. We invite the curious reader to take a look at the +[complete program](../concurrent_programming_asyncio.py), including +an implementation of the two primitives `delay` and `delay_until` using +Python's `asyncio`. + +{{< code-figure >}} + +```python +def f(x): + f.count += 1 + t = time.time() - f.start + print(f"at second {t:.0f}: {x}") + + +f.start = time.time() +f.count = 0 + +f("a") +delay(2, f, "d") +delay(0, f, "c") +delay(1, delay, 2, f, "f") +delay_until(lambda: f.count >= 4, f, "e") +f("b") + +## expected output: +# at second 0: a +# at second 0: b +# at second 0: c +# at second 2: d +# at second 2: e +# at second 3: f +``` + +Example program demonstrating the two scheduling primitives `delay` and +`delay_until`. +{{< /code-figure >}} -TODO. High level description of the simulator as concurrent program with -waiting. +## Block DAG and Visibility + +As [discussed before]({{< method "virtual-environment" >}}) the +simulator will maintain a DAG of all blocks mined or appended by any +nodes. Individual nodes however have only a partial view on this DAG. In +our program, we set local views as follows. ```python -# initialization dag = DAG() -state = [] -blocks = [dag.add(r) for r in roots()] -for b in blocks: +... +# in this context dag represents the global view on _all_ blocks +with dag.set_view(i): + ... + # in this context visibility of parents and children is restricted + # according to the local view of node i +... +# in this context dag represents the global view on _all_ blocks +``` + +Local views are read-only. The node functions `init`, `mining`, and +`update` cannot append blocks to the DAG. Instead, they return requests +for appending a block to the simulator. We will describe below, how the +simulator handles these requests. + +The local view makes the nodes' id accessible to the node by setting +`my_id = i` within the context. + +## Initialization + +We start each simulation with the initialization of the block DAG, +the protocol's `root` blocks, and the nodes' state. + +```python +# initialize empty block DAG +dag = DAG() + +# obtain drafts for the protocol's root blocks, convert them into +# actual blocks, and make them visible to all nodes. +root_blocks = [dag.add(b) for b in roots()] +for b in root_blocks: for i in range(n): dag.make_visible(b, i) + +# nodes' state +state = [None for _ in range(n)] for i in range(n): - dag.set_view(i) init, _update, _mining = node(i) - state[i] = init(blocks) + with dag.set_view(i): + state[i] = init(blocks) +``` + +## Proof-of-Work -# proof-of-work loop -while true: - wait_seconds(mining_delay()) +After initialization, the simulator starts a concurrent loop which +models proof-of-work and mining. The loop repeatedly samples and waits +for a mining delay, selects a random node as successful miner, obtains a +block draft from this miner, converts the draft into a block, checks +block validity, and informs the miner about the freshly mined block. + +```python +def proof_of_work(): + # select random miner i = select_miner() - dag.set_view(i) + # obtain block draft from miner _init, _update, mining = node(i) - draft = mining() + with dag.set_view(i): + draft = mining() + # convert draft to block w/ proof-of-work block = dag.add(draft) - block.pow = True + block.has_pow = True + # enforce validity of all appended blocks if validity(block): + # inform miner about freshly mined block deliver(block, i, "proof-of-work") + else: + dag.remove(block) + # continue proof-of-work loop after random delay + delay(mining_delay(), proof_of_work) + + +# enter proof-of-work loop +delay(mining_delay(), proof_of_work) +``` + +## Block Delivery + +Block delivery is what we call informing a node about a new block. +From the perspective of a node, new blocks might be freshly mined +locally, just appended locally, or received from the network. +We handle these deliveries in the `deliver` function. The function makes +the block visible to the node, applies the node's `update` function, and +handles the returned instructions to share existing or append new +blocks. +```python def deliver(block, i, event): - # deliver block in DAG-order - wait_until( - lambda: all([dag.is_visible(b, i) for b in block.parents()]) - ) - - # deliver block once - if dag.is_visible(block, i): - return + # update local visibility dag.make_visible(block, i) - # simulate node-action - dag.set_view(i) + # simulate node i's action _init, update, _mining = node(i) - upd = update(state[i], block, event) + with dag.set_view(i): + ret = update(state[i], block, event) - # handle state update - state[i] = upd.state + # store updated state + state[i] = ret.state # handle communication - for m in upd.share: - for dst in neighbours(node): - after_seconds( - message_delay(node, dst), - lambda: deliver(dst, m, "network"), - ) - - # handle non-proof-of-work appends - for draft in upd.append: - block = dag.add(draft) - block.pow = False - if validity(block): - deliver(block, node, "append") + for msg in ret.share: + broadcast(i, msg) + + # handle appends w/o proof-of-work + for draft in ret.append: + append(i, draft) +``` + +The [protocol specification]({{< method "protocol-specification" >}}) +assumes that blocks are delivered in order, that is, that the parents of +a delivered block have been delivered before. For our previous use of +`deliver` in the proof-of-work loop, this invariant is trivially true. +The following wrapper ensures in-order delivery for messages received +from the network. + +```python +def deliver_in_order(block, i, event): + def deliver_once(block, i, event): + if not dag.is_visible(block, i): + deliver(block, i, event) + + def all_parents_visible(): + for parent in block.parents(): + if not dag.is_visible(parent, i): + return False + return True + + delay_until(parents_visible, deliver_once, block, i, event) ``` -## Discrete event simulation +## Communication -TODO. Speeding things up with DES. +Nodes may request block broadcasts from their `update` function. The +simulator's [`delivery`](#block-delivery) function forwards these +requests to the `broadcast` function below. For each of the sending +node's (`src`) neighbors, this function samples a message delay (`t`) +and---after waiting for delay---delivers the block to the receiver +(`dst`). -## Brainstorm +```python +def broadcast(src, block): + for dst in neighbours(src): + t = message_delay(src, dst) + delay(t, deliver_in_order, dst, block, "network") +``` -To be removed. +## Non-PoW Blocks -State: +Nodes may request block appends from their `update` function. The +simulator's [`delivery`](#block-delivery) function forwards these +requests to the `append` function below. Without delay, the function +appends the block draft to the DAG, ensures validity, and delivers the +new block to the requesting node. Block's originating from this +mechanism do not carry a proof-of-work. -* Global DAG. -* State for each node. -* Block-visibility for each node. +```python +def append(i, draft): + block = dag.add(draft) + block.pow = False + if validity(block): + deliver(block, i, "append") + else: + dag.remove(block) +``` -Time: +## Discrete Event Simulation + +[Above](#concurrent-programming) we suggest to use concurrent +programming to implement the scheduling primitives `delay` and +`delay_until`. If implemented naively, the simulator would spend most +the time waiting for the delays or checking properties becoming true. +A delay of `n` seconds would actually take `n` seconds to +simulate. Simulations would be real-time, but real-time is +inconveniently slow in the proof-of-work blockchain context. + +We speed up the simulation by skipping the delayed time instead of +waiting for it to pass. The approach is called [discrete-event +simulation](https://en.wikipedia.org/wiki/Discrete-event_simulation). +The trick is to maintain a time-ordered queue of future events and +define a loop that handles the scheduled events one after another until +none are left. In the context of this simulator, future events are +delayed function calls. Handling an event is as simple as evaluating the +call. Each call may schedule further delayed calls. The time-ordering of +the queue ensures that the calls happen in the same order as they would +with naive waiting. -(implementation detail, nice to know but maybe not fully describe this -here) +```python +from queue import PriorityQueue -* Discrete event simulation -* Time-ordered queue of future events -* Infinite loop consuming & handling first event in the queue -* Event handler might queue future events -* Time between events is skipped -* Single non-blocking process +time = 0 +queue = PriorityQueue() +props = [] -Appends: -Communication: +def delay(seconds, fun, *args): + queue.put(time + seconds, fun, args) + + +def delay_until(prop, fun, *args): + prop.append(prop, fun, args) + + +# simulator code goes here +... + +while not queue.empty(): + # dequeue and handle next event + time, fun, args = queue.get() + fun(*args) + # re-evaluate delay_until properties + next_props = [] + for prop, fun, args in props: + if prop(): + fun(*args) + else: + next_props.append(prop, fun, args) + props = next_props +``` -Proof-of-work: +Note that using `delay_until` can cause significant overhead. We +introduced this scheduling primitive to improve readability of the +simulator pseudo-code. We completely avoid this kind of scheduling in +our optimized simulator implementation. diff --git a/website/content/en/docs/methods/virtual-environment.md b/website/content/en/docs/methods/virtual-environment.md index 8b92679d..5cc0fbc4 100644 --- a/website/content/en/docs/methods/virtual-environment.md +++ b/website/content/en/docs/methods/virtual-environment.md @@ -110,8 +110,8 @@ relationship from block $a$ are called ancestors of $a$. Blocks that can be reached with the child relationship from block $a$ are called descendants of $a$. Blocks can store arbitrary data in named fields. Blocks, their parents, and their fields are persistent. That is, -changing a block creates a copy of the block. Freshly copied blocks do -not have any descendants. +modifying a block creates a copy of the block. Freshly modified blocks +do not have any descendants. Blocks and the parent relationship form a directed acyclic graph which we call block DAG. Within the DAG, blocks without parents are @@ -156,7 +156,7 @@ In practice, verifying hash-links requires full knowledge of the referenced blob. Without knowing the blob, its hash cannot be computed. Without knowing the hash, the blob cannot be referred to. It is impossible to distinguish between a link that was intentionally -broken---let's say by replacing the hash with a random number---and a +broken---let's say by replacing it with a random number---and a link to an existing but locally unavailable blob. For the virtual environment, we introduce the concept of local block @@ -164,21 +164,22 @@ visibility. Each block can be either visible to a node or not. Blocks that are locally visible to a node will stay locally visible to this node forever. If a block is locally visible, then all its ancestors are also locally visible. This restriction does not apply to block children -where we local visibility might be partial. +where local visibility can be incomplete. -In other words, we assume that nodes have partial knowledge about the +To summarize, we assume that nodes have partial knowledge about the block DAG. A node's knowledge grows over time as it learns about new blocks in the order imposed by the DAG. -Nodes can create blocks. For this, all parents must be locally visible. -Freshly created blocks are invisible to all nodes but their creator. -Nodes can decide to share blocks. Depending on the communication -assumptions (made elsewhere), the virtual environment makes visible -shared blocks, including all their ancestors, to the other nodes. -Typically, blocks which have never been shared, and whose descendants -have not been shared, will not be visible to any nodes but its creator. -We say these blocks are withheld by their creator. Usually, honest nodes -do not withhold blocks but malicious nodes do. +Nodes can create blocks and append them to the DAG. Naturally, all +parent blocks must be locally visible to the appending node. Freshly +created blocks are invisible to all nodes but their creator. Nodes can +decide to share blocks. If so, the virtual environment makes visible +shared blocks, including all their ancestors, to the other nodes +according to the communication assumptions made elsewhere. Typically, +blocks which have never been shared, and whose descendants have not been +shared, will not be visible to any nodes but their creator. We say these +blocks are withheld by their creator. Usually, honest nodes do not +withhold blocks but malicious nodes do. We model the determinism of hash-linked lists by allowing nodes to re-create blocks. If two nodes create two identical blocks---that is, @@ -203,7 +204,7 @@ the nodes themselves. Blocks with a proof-of-work are unique, that means they cannot be re-created by appending a block with the same parents and fields. -Then, the virtual environment chooses which nodes succeed when at +The virtual environment chooses which nodes succeed when at proof-of-work. Whenever a node succeeds, the environment obtains from the node a block proposal (parents, fields, and field contents), creates the corresponding block, sets the proof-of-work property to true, and diff --git a/website/content/en/docs/protocols/nakamoto.md b/website/content/en/docs/protocols/nakamoto.md index 9f0bdebf..e0c573a6 100644 --- a/website/content/en/docs/protocols/nakamoto.md +++ b/website/content/en/docs/protocols/nakamoto.md @@ -87,7 +87,7 @@ def update(old: Block, new: Block, event: string): def mining(b: Block): - return Block(height=b.height + 1, parents=[b], miner=Env.my_id) + return Block(height=b.height + 1, parents=[b], miner=my_id) ``` ### Difficulty Adjustment diff --git a/website/package.json b/website/package.json index fedf908a..4618c151 100644 --- a/website/package.json +++ b/website/package.json @@ -17,7 +17,7 @@ "init": "shx rm -rf .git && git init -b main", "create": "exec-bin node_modules/.bin/hugo/hugo new", "prestart": "npm run clean", - "start": "exec-bin node_modules/.bin/hugo/hugo server --bind=0.0.0.0 --disableFastRender", + "start": "exec-bin node_modules/.bin/hugo/hugo server -D --bind=0.0.0.0 --disableFastRender", "prebuild": "npm run clean", "build": "exec-bin node_modules/.bin/hugo/hugo --gc --minify", "build:preview": "npm run build -D -F", From da1d8904827ad7faeffa5ed08053ac94e12a98ac Mon Sep 17 00:00:00 2001 From: Patrik Keller Date: Wed, 15 Nov 2023 10:59:20 +0100 Subject: [PATCH 6/6] Website. Fix hash rates in unfairness example --- website/content/en/docs/protocols/parallel-tree.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/content/en/docs/protocols/parallel-tree.md b/website/content/en/docs/protocols/parallel-tree.md index bef7471f..45eae742 100644 --- a/website/content/en/docs/protocols/parallel-tree.md +++ b/website/content/en/docs/protocols/parallel-tree.md @@ -51,10 +51,10 @@ honest behaviour. Imagine a situation where two miners---one weak (let's say 2% of the hash-rate) and one strong (20% of the hash-rate)---mine blocks around the same time and create a fork. Obviously, the weak miner tries to confirm her block, the strong miner tries to confirm the other. -We do not know what the other miners (72% of the hash-rate) do. If we +We do not know what the other miners (78% of the hash-rate) do. If we assume that they are unbiased, that is, they mine one or the other block -with equal probability, we end up in a situation were 38% of the hash -rate tries to confirm the weak miners block and 62% of the hash rate +with equal probability, we end up in a situation were 41% of the hash +rate tries to confirm the weak miners block and 59% of the hash rate tries to confirm the strong miners block. Only one of the blocks will end up in the final blockchain. The other does not get rewards. The punishment mechanism for non-linearity is biased in favour of the strong