owned this note
owned this note
Published
Linked with GitHub
# Quick merge via fork choice change
The goal of this document is to describe a mechanism by which a merge can happen quickly, with little modification to either the ethpow or beacon clients. The only change required on the ethpow side is that the client must have a communication channel with a trusted beacon node and must change its fork choice rule.
### Beacon chain changes (consensus and fork choice)
* We add a new field to the `BeaconBlockBody`: `application_block: bytes[<= 2**24]`
* We add a new field to the `BeaconState`: `previous_application_block_hash: bytes32` (initialized to `ZERO_HASH`)
If `state.previous_application_block_hash == ZERO_HASH`, then there are two valid options for the `block.application_block`:
1. Empty
2. A ethpow block that passes formatting checks, with `difficulty=1`
If a beacon block chooses option (2), then the fork choice rule delays accepting the block until the ethpow node accepts it (regardless of whether or not an ethpow node considers it to be in the canonical chain). Additionally, the beacon node must ask the ethpow node for the `totalDifficulty` of the block (the `eth_getBlockByHash` RPC [already does this](https://eth.wiki/json-rpc/API#eth_getblockbyhash)), and the response must be `>= TRANSITION_TOTAL_DIFFICULTY`.
Note that this requires the beacon node to be able to submit the application block body to the ethpow node by RPC. Additionally, the ethpow node must have a rule that PoW checks are disabled for ethpow blocks that originate from RPC requests from the beacon node.
Note also one subtlety, which explains why the extra criterion for option (2) must be a fork choice rule and not a validity condition: suppose that someone submits a beacon block `B` containing application block `A`, and at the time of receiving `B`, the ethpow node does not know about `parent(A)` and so cannot accept `A`. However, five seconds later, the ethpow node learns about `parent(A)`. At that point, the ethpow node should also accept A, and the beacon node should then accept `B`. So an ineligible application block can later become eligible if the dependencies are satisfied after the fact.
If `state.previous_application_block_hash != ZERO_HASH`, then a beacon block is valid if BOTH:
1. `RLPDecode(block.application_block).parent_hash == state.previous_application_block_hash`
2. The ethpow node has accepted the application block.
If the beacon block is accepted in either case, we set `state.previous_application_block_hash = sha3(block.application_block)`
### Ethpow node changes
As mentioned in the previous section, the ethpow node must add an RPC `submitBlock` mechanism, and **if a block is submitted using this mechanism by the beacon node, PoW checks (including difficulty update formula checks) must be disabled**.
Additionally, the ethpow node fork choice changes:
* If the beacon block that is the current head has `state.previous_application_block_hash == ZERO_HASH`, the fork choice is as normal
* If the beacon block that is the current head has `state.previous_application_block_hash != ZERO_HASH`, the fork choice is to select the head as being the ethpow block that is contained as the `application_block` of the head beacon block
### Expected transition behavior
* The PoW chain grows until there is at least one block whose `totalDifficulty >= TRANSITION_TOTAL_DIFFICULTY`.
* As soon as the next honest proposer is scheduled, they will put that block (or a sister or descendant) into their beacon block.
* Soon, all clients will receive both the ethpow block (plus all dependencies) on the ethpow side, and the beacon block on the beacon chain side.
* From that point on, the ethpow fork choice switches over to the beacon chain, and the ethereum application chain continues from there.
### FAQ: Possible attacks
#### Can the first proposer after the transition time be malicious by including an ethpow block that is not the head of the ethpow chain?
We expect that an ethpow block will be included into the beacon chain within a minute of it becoming possible to do so (otherwise, there must be 5 malicious proposers in a row). At that point, there are very few possibilities for what ethpow blocks could be incuded: it must be the first transition block, a descendant or an uncle. In either case, the ethpow chain would not revert more than a few blocks.
#### Could miners collude to do something malicious?
Miners could do a "balance attack" and mine multiple chains, so there are many choices for what ethpow block to include. But ultimately, as long as there is at least one honest miner, eventually at least one block with `totalDifficulty >= TRANSITION_TOTAL_DIFFICULTY` gets created. If multiple options appear simultaneously, the first proposer would pick one, and as soon as the ethpow fork choice repoints to the beacon fork choice, the ethpow chain would proceed smoothly inside the beacon chain.
#### What if the beacon chain reorgs around the transition boundary?
If the beacon chain reorgs, then this would lead to the ethpow chain reorging. However, once the beacon chain stops reorging (or at least the blocks around the transition period stabilize), the ethpow fork choice would also stabilize, because the ethpow fork choice favors the chain embedded within the beacon chain if such a chain exists.
### Other FAQ
#### Does this mean we're throwing out the plans to make the beacon chain interact with the application state more directly as [Mikhail Kalinin and co are working on](https://github.com/ethereum/eth2.0-specs/pull/2229)?
**No.** Rather, the minimal merge as described above would only be the first step, and a post-merge hard fork would simplify the protocol and clean out unnecessary bits and make the interaction between the application layer and the beacon chain more "natural". Eventually we would go even further and, for example, replace the `application_block: bytes` with `application_txs: List[bytes]`) and even make the application state a "normal" part of the `BeaconState` (even though it's hashed in a non-SSZ way).
In fact, the minimal merge will make these things _easier_ to work on, as it would no longer be needed to worry about merging two chains at the same time.
#### When withdrawals?
A post-merge hard fork can add support for withdrawals.