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

EIP-3675: Upgrade consensus to Proof-of-Stake #3675

Merged
merged 15 commits into from Jul 29, 2021
247 changes: 247 additions & 0 deletions EIPS/eip-3675.md
@@ -0,0 +1,247 @@
---
eip: 3675
title: Upgrade consensus to Proof-of-Stake
author: Mikhail Kalinin (@mkalinin), Danny Ryan (@djrtwo), Vitalik Buterin (@vbuterin)
discussions-to: https://ethereum-magicians.org/t/eip-3675-upgrade-consensus-to-proof-of-stake/6706
status: Draft
type: Standards Track
category: Core
created: 2021-07-22
---


## Simple Summary

Specification of the consensus mechanism upgrade on Ethereum Mainnet that introduces Proof-of-Stake.


## Abstract

This EIP deprecates Proof-of-Work (PoW) and supersedes it with the new Proof-of-Stake consensus mechanism (PoS) driven by the beacon chain. Information on the bootstrapping of the new consensus mechanism is documented in [EIP-2982](./eip-2982.md). Full specification of the beacon chain can be found in the [eth2.0-specs](https://github.com/ethereum/eth2.0-specs/) repository.

This document specifies the set of changes to the block structure, block processing, fork choice rule and network interface introduced by the consensus upgrade.


## Motivation

The beacon chain network has been up and running since December 2020. Neither safety nor liveness failures were detected during this period of time. This long period of running without failure demonstrates the sustainability of the beacon chain system and its readiness to become a security provider for the Ethereum Mainnet.

To understand the motivation of introducing the Proof-of-Stake consensus see the Motivation section of [EIP-2982](./eip-2982.md#motivation).


## Specification

### Definitions

* **PoW block**: Block that is built and verified by the existing proof-of-work mechanism. In other words, a block of the Ethereum network before the consensus upgrade.
* **PoS block**: Block that is built and verified by the new proof-of-stake mechanism.
* **Terminal PoW block**: A PoW block that satisfies the following conditions --
`pow_block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY` *and* `pow_block.parent_block.total_difficulty < TERMINAL_TOTAL_DIFFICULTY`.
There can be more than one terminal PoW block in the network, e.g. multiple children of the same pre-terminal block.
* **`TERMINAL_TOTAL_DIFFICULTY`** The amount of total difficulty reached by the network that triggers the consensus upgrade.
* **`TRANSITION_BLOCK`** The earliest PoS block of the canonical chain, i.e. the PoS block with the lowest block height.
`TRANSITION_BLOCK` **MUST** be a child of a terminal PoW block.
* **`POS_CONSENSUS_VALIDATED`** An event occurring when the PoS block is validated with respect to the proof-of-stake consensus rules.
* **`POS_CHAINHEAD_SET`** An event occurring when the PoS block is designated as the head of the canonical chain.
* **`POS_BLOCK_FINALIZED`** An event occurring when the PoS block is considered as finalized.

#### PoS events

Events having the `POS_` prefix in the name (PoS events) are emitted by the new proof-of-stake consensus mechanism. They signify the corresponding assertion that has been made regarding a block specified by the event. The underlying logic of PoS events can be found in the beacon chain specification. On the occurrence of each PoS event the corresponding action that is specified by this EIP **MUST** be taken.

Each `POS_BLOCK_FINALIZED` event has a reference to the head of the canonical chain in addition to the finalized block and incorporates the semantics of the `POS_CHAINHEAD_SET` event. Thus, every action and effect that is specified on the occurrence of `POS_CHAINHEAD_SET` event according to this EIP **MUST** also be taken on every occurrence of `POS_BLOCK_FINALIZED` event.


### PoW block processing

PoW blocks that are descendants of any terminal PoW block **MUST NOT** be imported. This implies that a terminal PoW block will be the last PoW block in the canonical chain.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be worth mentioning here that execution clients should accept, validate, store, and gossip all peers to the terminal proof of work block until the first POS_BLOCK_FINALIZED event is received. This note may need to be split up between this section and the networking section.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean that there is a bit of inconsistency between the two sections? Like, this section says keep processing terminal PoW blocks and their ancestors and puts no time boundary on it while the network section implies more strict behaviour and deprecates gossip at a strict boundary. And we might want to reflect this restriction here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to add the following kind of statement:

Beginning with the first POS_BLOCK_FINALIZED event, client software MUST NOT import any PoW block that doesn't belong to the canonical chain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern is that currently I don't think clients gossip siblings until they see a new longest chain (maybe I'm wrong about this)? If that assumption is true, then this will be a behavior change that clients need to implement.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, interesting. I would assume they do verify PoW upon receiving a block and propagate this block further if the verification passed. In the mean time this block is stored. And here we have options, it either processed right away or processing is deferred until the fork that this block does belong to becomes the longest chain.

And this is where we may have a real issue (not related to gossip). If the terminal PoW block that is picked by the beacon chain proposer has been received but hasn't been processed by our node due to conditions described above (our node may receive another terminal block with the same TD and thus refuse to re-org). Then our node won't be able to verify the beacon block that has been received because it will stuck verifying the PoW block that is the parent of the execution payload. So, it means that the spec must force every terminal PoW block to be processed, not only stored.

cc @holiman

Copy link
Contributor Author

@mkalinin mkalinin Jul 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative solution for this edge case would be the corresponding method in the Consensus API, let's say verifyTerminalPoWBlock(block_hash: Hash32). This method would enforce the execution of a sibling terminal PoW block if it hasn't been executed yet. The downside of this approach is the delay between receiving a beacon block and considering it for further processing due to calling to this method, especially, if there are more than one block on this sibling fork that must be executed. But this approach seems to be less intrusive in terms of execution clients change set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A solution with verifyTerminalPoWBlock(block_hash: Hash32) or a similar call aids mitigation of the DoS vector that is described in #3675 (comment). If miners have a cheap way to produce terminal PoW blocks to spam the network it is better for a node to avoid executing them all and execute terminal PoW blocks from non-canonical chains on demand.



### Block structure

Beginning with `TRANSITION_BLOCK`, a number of previously dynamic block fields are deprecated by enforcing these values to instead be constants. Each block field listed in the table below **MUST** be replaced with the corresponding constant value.

| Field | Constant value | Comment |
|-|-|-|
| **`ommersHash`** | `0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347` | `= Keccak256(RLP([]))` |
| **`difficulty`** | `0` | |
| **`extraData`** | `b''` | `RLP(b'') = 0x80` |
| **`mixHash`** | `0x0000000000000000000000000000000000000000000000000000000000000000` | |
| **`nonce`** | `0x0000000000000000` | |
| **`ommers`** | `[]` | `RLP([]) = 0xc0` |

*Note*: Logic and validity conditions of block fields that are *not* specified here **MUST** remain unchanged. Additionally, the overall block format **MUST** remain unchanged.


### Block validity

Beginning with `TRANSITION_BLOCK`, the block validity conditions **MUST** be altered by the following:
* Remove verification of the block's **`difficulty`** value with respect to the difficulty formula.
* Remove verification of the block's **`nonce`** and **`mixHash`** values with respect to the Ethash function.
* Remove all validation rules that are evaluated over the list of ommers and each member of this list, except for enforcing this list to be empty.
* Add verification of the fields noted in [block structure](#block-structure) as their specified constant value, including the enforcement of empty ommers list.
Comment on lines +81 to +82
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On these two lines you call out the ommers list specifically, but you don't call out any other fields specifically. This is confusing because it makes it seem like ommers is special when I believe it is not, it should be validated as a constant just like all other fields mentioned in the Block structure section.

* Add verification of block validity with respect to the PoS consensus rules, i.e. assert that there **MUST** be a corresponding event for the block to consider it valid. Such events are limited to the following:
* A `POS_CONSENSUS_VALIDATED` event considering the block or any of its descendants as valid.
* A `POS_CHAINHEAD_SET` event, including the `POS_BLOCK_FINALIZED` form of this event, designating the block or any of its descendants as the head of the canonical chain.

*Note*: If one of the new rules fails then the block **MUST** be invalidated.

*Note*: Validity rules that are not specified in the list above **MUST** remain unchanged.


### Block and ommer rewards

Beginning with `TRANSITION_BLOCK`, block and ommer rewards are deprecated. Specifically, the following actions **MUST** be taken:
* Remove increasing the balance of the block's **`beneficiary`** account by the basic block reward.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is referred to just as block reward in most places. Calling it basic block reward may lead to confusion since that phrase isn't commonly used.

* Remove increasing the balance of the block's **`beneficiary`** account by the ommer inclusion reward per each ommer.
* Remove increasing the balance of the ommer's **`beneficiary`** account by the ommer block reward per each ommer.
Comment on lines +96 to +97
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels redundant, since PoS blocks cannot have any ommers. As mentioned above, calling this out specially makes it feel to the reader like something special is happening with ommers when in reality nothing special is happening. This can lead the reader to searching for answers to "why are ommers special" when there is nothing to be found.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may fill redundant but the purpose of this statement is to be consistent with respect to the YP when removing PoW rewards, i.e. the intention is to explicitly remove each source of these rewards.


*Note*: Transaction fee mechanics affecting the block's `beneficiary` account **MUST** remain unchanged.


### Fork choice rule

As of the first `POS_CHAINHEAD_SET` event, the fork choice rule **MUST** be altered in the following way:
* Remove the existing PoW heaviest chain rule.
* Adhere to the new PoS LMD-GHOST rule.

The new PoS LMD-GHOST fork choice rule is specified as follows. On each occurrence of a `POS_CHAINHEAD_SET` event including the first one, the following actions **MUST** be taken:
* Consider the chain starting at genesis and ending with the block nominated by the event as the canonical blockchain.
* Set the head of the canonical blockchain to the block nominated by the event.


### Network

The networking stack **SHOULD NOT** send the following messages if they advertise the descendant of any terminal PoW block:
* [`NewBlockHashes (0x01)`](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#newblockhashes-0x01)
* [`NewBlock (0x07)`](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#newblock-0x07)

Beginning with the first `POS_BLOCK_FINALIZED` event, the networking stack **MUST** remove the handlers corresponding to the following ETH protocol messages:
mkalinin marked this conversation as resolved.
Show resolved Hide resolved
* [`NewBlockHashes (0x01)`](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#newblockhashes-0x01)
* [`NewBlock (0x07)`](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#newblock-0x07)

Beginning with the first `POS_BLOCK_FINALIZED` event, peers that keep sending these messages **SHOULD** be disconnected.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will introduce a race condition. Not all peers will receive POS_BLOCK_FINALIZED at the same time, so some may still be broadcasting NewBlockHashes and NewBlock for siblings of the terminal PoW block after some of their peers have received the POS_BLOCK_FINALIZED event.

Consider changing this rule to be that after the second POS_BLOCK_FINALIZED event peers are disconnected, as by that time all peers should have received the first POS_BLOCK_FINALIZED event and should no longer be gossping sibling terminal PoW blocks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, but there is also the following statement above:

  • The networking stack SHOULD NOT send the following messages if they advertise the descendant of any terminal PoW block

Which means that effectively block gossip SHOULD be stopped before POS_BLOCK_FINALIZED.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would block gossip stop before POS_BLOCK_FINALIZED? I think we should assume that there will be a steady stream of new siblings until POS_BLOCK_FINALIZED, since the protocol rules as I understand them suggest you continue to gossip those.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because there is enough time between the terminal PoW block event and the first POS_BLOCK_FINALIZED event that is issued when the first PoS block gets finalized (it is not issued when the beacon block with empty execution payload is finalized). The gap between these two events is at least 2 epochs and unless there is a party that is constantly mining terminal PoW blocks there should be a plenty of time to disseminate all terminal PoW blocks existing in the network.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I feel like we should assume that one or more miners mine terminal PoW siblings. They have a huge pile of hashing power and nothing to do with it. Maybe we'll get lucky and they don't, but I feel like we should prepare for them doing this.

I wonder if a miner could do something interesting where once the first terminal PoW block is produced (the most likely one to be finalized) they switch to mining a forked chain some number of blocks back that lowers the difficulty with each block. The goal here would be to drive the difficulty down as far as possible in this fork given their hashpower while still reaching the target total difficulty. Once you get to one block shy of target total difficulty, you then produce terminal PoW blocks over and over as fast as you can in order to spam the network?

I'm not sure how much you could manipulate given 2 epochs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how much you could manipulate given 2 epochs.

Good question. There are possibilities depending on whether whole hashing power participates in anything like that, whether this attack started in advance by switching a portion of hashing power from mainnet to start producing such a chain before the transition. If all hashing power participates it may produce roughly 60 blocks during 2 epochs period but with lowering the difficulty this number increases; like 20 blocks with 1000 seconds gap between their timestamps is required to reduce the difficulty ~8 times and produce roughly 40*8=320 blocks during the rest of the period, it also doesn't count how many blocks needed to reach the terminal total difficulty threshold. If we assume that somehow miners become able to produce a block in a second then during two epochs we would got 768 terminal PoW blocks, I don't know how bad is it for the network if we assume that these blocks are not executed, only propagated with PoW verification.

As for the network stack, if handlers are removed won't peers sending unknown messages be disconnected by clients?

Copy link
Contributor Author

@mkalinin mkalinin Jul 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the health of the network under this kind of attack it makes sense for clients to stop propagating any blocks upon receiving the first POS_BLOCK_FINALIZED and remove handlers with the corresponding penalty upon receiving the second POS_BLOCK_FINALIZED. So, the updated spec should look like:

The networking stack SHOULD NOT send the following messages if they advertise the descendant of any terminal PoW block:

Beginning with the first POS_BLOCK_FINALIZED event, the networking stack MUST discard the following ingress messages:

Beginning with the second POS_BLOCK_FINALIZED event, the networking stack MUST remove the handlers corresponding to the following messages:

Peers that keep sending these messages after the handlers have been removed SHOULD be disconnected.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably move this conversation to the discussions-to link. PR comments should be assumed to be transient, especially on merged PRs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


*Note:* The logic of message handlers that are not affected by this section **MUST** remain unchanged.


## Rationale

The changes specified in this EIP target a minimal requisite set of consensus and client software modifications to safely replace the existing proof-of-work consensus algorithm with the new proof-of-stake consensus represented by the already in-production beacon chain.

This EIP was designed to minimize the complexity of hot-swapping the live consensus of the Ethereum network. Both the safety of the operation and time to production were taken into consideration. Additionally, a minimal changeset helps ensure that *most* smart contracts and services will continue to function as intended during and after the transition with little to no required intervention.

### Total difficulty triggering the upgrade

See [Security considerations](#terminal-total-difficulty-vs-block-number).

### Halting the import of PoW blocks

See [Security considerations](#halt-the-importing-of-pow-blocks).

### Replacing block fields with constants

Deprecated block fields are replaced with constant values to ensure the block format remains backwards compatible. Preserving the block format aids existing smart contracts and services in providing uninterrupted service during and after this transition.

Particularly, this is important for those smart contracts that verify Merkle proofs of transaction/receipt inclusion and state by validating the hash of externally provided block header string against the corresponding value returned by the `BLOCKHASH` operation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Particularly, this is important for those smart contracts that verify Merkle proofs of transaction/receipt inclusion and state by validating the hash of externally provided block header string against the corresponding value returned by the `BLOCKHASH` operation.
Particularly, this is important for those smart contracts that verify Merkle proofs of transaction/receipt inclusion and state by validating the hash of externally provided block header against the corresponding value returned by the `BLOCKHASH` operation.

The string there I think makes the sentence a bit more confusing, as you may receive a block header in many forms such as a structured format, a byte array, a hex string, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, theoretically they may receive a block header as a set of field values, then RLP encode it, compute a hash and verify this hash. Although it does seem like a suboptimal solution we better remove this "string".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need to pull data out of the header, it may be easier to serialize from raw inputs than it is to parse/decerialize to pull bits out of the header.

Copy link
Contributor Author

@mkalinin mkalinin Jul 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably it may be cheaper given a string to verify it against the corresponding BLOCKHASH value by parsing out a number using some optimized RLP decoder that jumps between list elements and then read the needed field in the same fashion than RLP encoding the whole thing as a preliminary to the verification. Anyway, I am going to remove the "string" term.


This change introduces an additional validity rule that enforces the replacement of deprecated block fields.

### Replacing `difficulty` with `0`

After deprecating the proof-of-work the notion of difficulty no longer exists and replacing the block header **`difficulty`** field with `0` constant is semantically sound.

### Deprecating `extraData`

The **`extraData`** field is deprecated in favour of the corresponding **`graffiti`** field of the beacon block.

### Changing block validity rules

The rule set enforcing the PoW seal validity is replaced with the corresponding PoS rules along with the consensus upgrade as the rationale behind this change.

An additional rule validating a set of deprecated block fields is required by the block format changes introduced by this specification.

### Removing block rewards

Existing rewards for producing and sealing blocks are deprecated along with the PoW mechanism. The new PoS consensus becomes both responsible for sealing blocks and for issuing block rewards once this specification enters into effect.

### Supplanting fork choice rule

The fork choice rule of the PoW mechanism becomes completely irrelevant after the upgrade and is replaced with the corresponding rule of the new PoS consensus mechanism.

### Removing block gossip
mkalinin marked this conversation as resolved.
Show resolved Hide resolved

After the upgrade of the consensus mechanism only the beacon chain network will have enough information to validate a block. Thus, block gossip provided by the `eth` network protocol will become unsafe and is deprecated in favour of the block gossip existing in the beacon chain network.

It is recommended for the client software to not propagate descendants of any terminal PoW block to reduce the load on processing the P2P component and stop operating in the environment with unknown security properties.

## Test Cases
*TBD*

## Reference Implementation
*TBD*

Comment on lines +178 to +183
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Test Cases
*TBD*
## Reference Implementation
*TBD*

Consider removing these until you are ready to fill them in. They are optional sections, and thus not required to be present to merge this as a draft and if they never get filled in that is technically acceptable. Generally, we want to write EIPs in a way that is "ready to merge as final" without TODOs.


## Backwards Compatibility

This EIP introduces backward incompatibilities in block validity, block rewards and fork choice rule.

The design of the consensus upgrade specified by this document does not introduce backward incompatibilities for existing applications and services built on top of Ethereum except for those that are described in the [EVM](#evm) section below or heavily depends on the PoW consensus in any other way.


### EVM

Although this EIP does not introduce any explicit changes to the EVM there are a couple of places where it may affect the logic of existing smart contracts.

#### DIFFICULTY

`DIFFICULTY` operation will always return `0` after this EIP takes effect and deprecates the **`difficulty`** field by replacing it with `0` constant.

*Note:* Altering the `DIFFICULTY` semantics to return randomness accumulated by the beacon chain is under consideration but will be introduced in a separate EIP.

#### BLOCKHASH

Pseudo-random numbers obtained as the output of `BLOCKHASH` operation become more insecure after this EIP takes effect and the PoW mechanism (which decreases the malleability of block hashes) gets supplanted by PoS.


## Security Considerations

### Beacon chain

See Security Considerations section of [EIP-2982](./eip-2982.md#security-considerations).


### Transition process

The transition process used to take this specification into effect is a more sophisticated version of a hardfork -- the regular procedure of applying backwards incompatible changes in the Ethereum network. This process has multiple successive steps instead of the normal block-height point condition of simpler hardforks.

The complexity of this upgrade process stems from this fork targeting the underlying consensus mechanism rather than the application layer within the consensus mechanism. Although the design seeks simplicity where possible, safety and liveness considerations during this transition have been prioritized.

#### Terminal total difficulty vs block number

Using a pre-defined block number for the hardfork is unsafe in this context due to the PoS fork choice taking priority during the transition.

An attacker may use a minority of hash power to build a malicious chain fork that would satisfy the block height requirement. Then the first PoS block may be maliciously proposed on top of the PoW block from this adversarial fork, becoming the head and subverting the security of the transition.

To protect the network from this attack scenario, difficulty accumulated by the chain (total difficulty) is used to trigger the upgrade.

#### Ability to jump between terminal PoW blocks

There could be the case when a terminal PoW block is not observed by the majority of network participants due to (temporal) network partitioning. In such a case, this minority would switch their fork choice to the new rule provided by the PoS rooted on the minority terminal PoW block that they observed.

The transition process allows the network to re-org between forks with different terminal PoW blocks as long as (a) these blocks satisfy the terminal PoW block conditions and (b) a `POS_BLOCK_FINALIZED` has not yet been received. This provides resilience against adverse network conditions during the transition process and prevents irreparable forks/partitions.

#### Halt the importing of PoW blocks

Suppose the part of the client software that is connected to the beacon chain network goes offline before the Ethereum network reaches the `TERMINAL_TOTAL_DIFFICULTY` and stays offline while the network meets this threshold. Such an event makes the client software unable to switch to PoS and allows it to keep following the PoW chain if this chain is being built beyond the terminal PoW block. Depending on how long the beacon chain part was offline, it could result in different adverse effects such as:
* The client has no post-state for the terminal PoW block (the state has been pruned) which prevents it from doing the re-org to the PoS chain and leaving syncing from scratch as the only option to recover.
* An application, a user or a service uses the data from the wrong fork (PoW chain that is kept being built) which can cause security issues on their side.

Not importing PoW blocks that are beyond the terminal PoW block prevents these adverse effects on safety/re-orgs in the event of software or configuration failures *in favor* of a liveness failure.

### Further threat analysis
_TBD_

Comment on lines +242 to +244
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Further threat analysis
_TBD_

As above, recommend leaving out unfinished sections until you have something to put into them.


## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).