Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
djrtwo committed Sep 27, 2021
2 parents 91f5e56 + cc92c2a commit 67fd797
Show file tree
Hide file tree
Showing 28 changed files with 719 additions and 34 deletions.
8 changes: 5 additions & 3 deletions configs/mainnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ PRESET_BASE: 'mainnet'

# Transition
# ---------------------------------------------------------------
# TBD, 2**256-1 is a placeholder
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129639935
# TBD, 2**256-2**10 is a placeholder
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129638912
# By default, don't use this param
TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000


# Genesis
Expand All @@ -29,7 +31,7 @@ GENESIS_DELAY: 604800

# Altair
ALTAIR_FORK_VERSION: 0x01000000
ALTAIR_FORK_EPOCH: 18446744073709551615
ALTAIR_FORK_EPOCH: 74240 # Oct 27, 2021, 10:56:23am UTC
# Merge
MERGE_FORK_VERSION: 0x02000000
MERGE_FORK_EPOCH: 18446744073709551615
Expand Down
6 changes: 4 additions & 2 deletions configs/minimal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ PRESET_BASE: 'minimal'

# Transition
# ---------------------------------------------------------------
# TBD, 2**256-1 is a placeholder
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129639935
# TBD, 2**256-2**10 is a placeholder
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129638912
# By default, don't use this param
TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000


# Genesis
Expand Down
12 changes: 7 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,26 @@
from typing import Dict, NamedTuple, List, Sequence, Optional, TypeVar
from abc import ABC, abstractmethod
import ast

import subprocess
import sys

# NOTE: have to programmatically include third-party dependencies in `setup.py`.
def installPackage(package: str):
subprocess.check_call([sys.executable, '-m', 'pip', 'install', package])

RUAMEL_YAML_VERSION = "ruamel.yaml==0.16.5"
try:
import ruamel.yaml
except ImportError:
import pip
pip.main(["install", RUAMEL_YAML_VERSION])
installPackage(RUAMEL_YAML_VERSION)

from ruamel.yaml import YAML

MARKO_VERSION = "marko==1.0.2"
try:
import marko
except ImportError:
import pip
pip.main(["install", MARKO_VERSION])
installPackage(MARKO_VERSION)

from marko.block import Heading, FencedCode, LinkRefDef, BlankLine
from marko.inline import CodeSpan
Expand Down
6 changes: 2 additions & 4 deletions specs/altair/fork.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Altair -- Fork Logic

**Notice**: This document is a work-in-progress for researchers and implementers.

## Table of contents

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
Expand All @@ -26,13 +24,13 @@ Warning: this configuration is not definitive.
| Name | Value |
| - | - |
| `ALTAIR_FORK_VERSION` | `Version('0x01000000')` |
| `ALTAIR_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** |
| `ALTAIR_FORK_EPOCH` | `Epoch(74240)` (Oct 27, 2021, 10:56:23am UTC) |

## Fork to Altair

### Fork trigger

TBD. Social consensus, along with state conditions such as epoch boundary, finality, deposits, active validator count, etc. may be part of the decision process to trigger the fork. For now we assume the condition will be triggered at epoch `ALTAIR_FORK_EPOCH`.
The fork is triggered at epoch `ALTAIR_FORK_EPOCH`.

Note that for the pure Altair networks, we don't apply `upgrade_to_altair` since it starts with Altair version logic.

Expand Down
1 change: 1 addition & 0 deletions specs/merge/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ This patch adds transaction execution to the beacon chain as part of the Merge f
| Name | Value |
| - | - |
| `TERMINAL_TOTAL_DIFFICULTY` | **TBD** |
| `TERMINAL_BLOCK_HASH` | `Hash32('0x0000000000000000000000000000000000000000000000000000000000000000')` |

## Containers

Expand Down
7 changes: 7 additions & 0 deletions specs/merge/client-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- [The Merge -- Client Settings](#the-merge----client-settings)
- [Override terminal total difficulty](#override-terminal-total-difficulty)
- [Override terminal block hash](#override-terminal-block-hash)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand All @@ -19,3 +20,9 @@ To coordinate manual overrides to [`TERMINAL_TOTAL_DIFFICULTY`](./beacon-chain.m

Except under exceptional scenarios, this setting is expected to not be used. Sufficient warning to the user about this exceptional configurable setting should be provided.

### Override terminal block hash

To allow for transition coordination around a specific PoW block, clients must also provide `--terminal-block-hash-override` as a configurable setting.
The value provided by this setting takes precedence over the pre-configured `TERMINAL_BLOCK_HASH` parameter.

Except under exceptional scenarios, this setting is expected to not be used. Sufficient warning to the user about this exceptional configurable setting should be provided.
10 changes: 6 additions & 4 deletions specs/merge/fork-choice.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ def notify_forkchoice_updated(self: ExecutionEngine, head_block_hash: Hash32, fi
### `PowBlock`

```python
@dataclass
class PowBlock(object):
class PowBlock(Container):
block_hash: Hash32
parent_hash: Hash32
total_difficulty: uint256
Expand All @@ -75,6 +74,9 @@ Used by fork-choice handler, `on_block`.

```python
def is_valid_terminal_pow_block(block: PowBlock, parent: PowBlock) -> bool:
if block.block_hash == TERMINAL_BLOCK_HASH:
return True

is_total_difficulty_reached = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
is_parent_total_difficulty_valid = parent.total_difficulty < TERMINAL_TOTAL_DIFFICULTY
return is_total_difficulty_reached and is_parent_total_difficulty_valid
Expand All @@ -101,7 +103,7 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
assert block.slot > finalized_slot
# Check block is a descendant of the finalized block at the checkpoint finalized slot
assert get_ancestor(store, block.parent_root, finalized_slot) == store.finalized_checkpoint.root

# Check the block is valid and compute the post-state
state = pre_state.copy()
state_transition(state, signed_block, True)
Expand All @@ -127,7 +129,7 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
# Update finalized checkpoint
if state.finalized_checkpoint.epoch > store.finalized_checkpoint.epoch:
store.finalized_checkpoint = state.finalized_checkpoint

# Potentially update justified if different from store
if store.justified_checkpoint != state.current_justified_checkpoint:
# Update justified if new justified is later than store justified
Expand Down
25 changes: 19 additions & 6 deletions specs/merge/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,29 +97,42 @@ To obtain an execution payload, a block proposer building a block on top of a `s
* `pow_chain` is a list that abstractly represents all blocks in the PoW chain
* `fee_recipient` is the value suggested to be used for the `coinbase` field of the execution payload


```python
def get_pow_block_at_total_difficulty(total_difficulty: uint256, pow_chain: Sequence[PowBlock]) -> Optional[PowBlock]:
def get_pow_block_at_terminal_total_difficulty(pow_chain: Sequence[PowBlock]) -> Optional[PowBlock]:
# `pow_chain` abstractly represents all blocks in the PoW chain
for block in pow_chain:
parent = get_pow_block(block.parent_hash)
if block.total_difficulty >= total_difficulty and parent.total_difficulty < total_difficulty:
block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
if block_reached_ttd and not parent_reached_ttd:
return block

return None


def get_terminal_pow_block(pow_chain: Sequence[PowBlock]) -> Optional[PowBlock]:
if TERMINAL_BLOCK_HASH != Hash32():
# Terminal block hash override takes precedence over terminal total difficulty
pow_block_overrides = [block for block in pow_chain if block.block_hash == TERMINAL_BLOCK_HASH]
if not any(pow_block_overrides):
return None
return pow_block_overrides[0]

return get_pow_block_at_terminal_total_difficulty(pow_chain)


def prepare_execution_payload(state: BeaconState,
pow_chain: Sequence[PowBlock],
fee_recipient: ExecutionAddress,
execution_engine: ExecutionEngine) -> Optional[PayloadId]:
if not is_merge_complete(state):
terminal_pow_block = get_pow_block_at_total_difficulty(TERMINAL_TOTAL_DIFFICULTY, pow_chain)
terminal_pow_block = get_terminal_pow_block(pow_chain)
if terminal_pow_block is None:
# Pre-merge, no prepare payload call is needed
return None
else:
# Signify merge via producing on top of the last PoW block
parent_hash = terminal_pow_block.block_hash
# Signify merge via producing on top of the terminal PoW block
parent_hash = terminal_pow_block.block_hash
else:
# Post-merge, normal payload
parent_hash = state.latest_execution_payload_header.block_hash
Expand Down
2 changes: 1 addition & 1 deletion tests/core/pyspec/eth2spec/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0-beta.5
1.1.0
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@

@with_phases([ALTAIR])
@spec_state_test
def test_next_sync_committee_tree(spec, state):
def test_next_sync_committee_merkle_proof(spec, state):
yield "state", state
next_sync_committee_branch = build_proof(state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX)
yield "proof", {
"leaf": "0x" + state.next_sync_committee.hash_tree_root().hex(),
"leaf_index": spec.NEXT_SYNC_COMMITTEE_INDEX,
"branch": ['0x' + root.hex() for root in next_sync_committee_branch]
}
assert spec.is_valid_merkle_branch(
leaf=state.next_sync_committee.hash_tree_root(),
branch=next_sync_committee_branch,
Expand All @@ -21,8 +27,15 @@ def test_next_sync_committee_tree(spec, state):

@with_phases([ALTAIR])
@spec_state_test
def test_finality_root_tree(spec, state):
def test_finality_root_merkle_proof(spec, state):
yield "state", state
finality_branch = build_proof(state.get_backing(), spec.FINALIZED_ROOT_INDEX)
yield "proof", {
"leaf": "0x" + state.finalized_checkpoint.root.hex(),
"leaf_index": spec.FINALIZED_ROOT_INDEX,
"branch": ['0x' + root.hex() for root in finality_branch]
}

assert spec.is_valid_merkle_branch(
leaf=state.finalized_checkpoint.root,
branch=finality_branch,
Expand Down
4 changes: 4 additions & 0 deletions tests/core/pyspec/eth2spec/test/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
class SkippedTest(Exception):
...


class BlockNotFoundException(Exception):
...
44 changes: 40 additions & 4 deletions tests/core/pyspec/eth2spec/test/helpers/fork_choice.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from random import Random
from eth_utils import encode_hex
from eth2spec.test.exceptions import BlockNotFoundException
from eth2spec.utils.ssz.ssz_typing import uint256
from eth2spec.test.helpers.attestations import (
next_epoch_with_attestations,
next_slots_with_attestations,
Expand All @@ -22,15 +25,22 @@ def add_block_to_store(spec, store, signed_block):
spec.on_block(store, signed_block)


def tick_and_add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_attestations=False):
def tick_and_add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_attestations=False,
merge_block=False, block_not_found=False):
pre_state = store.block_states[signed_block.message.parent_root]
block_time = pre_state.genesis_time + signed_block.message.slot * spec.config.SECONDS_PER_SLOT
if merge_block:
assert spec.is_merge_block(pre_state, signed_block.message.body)

if store.time < block_time:
on_tick_and_append_step(spec, store, block_time, test_steps)

post_state = yield from add_block(
spec, store, signed_block, test_steps, valid=valid, allow_invalid_attestations=allow_invalid_attestations)
spec, store, signed_block, test_steps,
valid=valid,
allow_invalid_attestations=allow_invalid_attestations,
block_not_found=block_not_found,
)

return post_state

Expand Down Expand Up @@ -118,7 +128,13 @@ def run_on_block(spec, store, signed_block, valid=True):
assert store.blocks[signed_block.message.hash_tree_root()] == signed_block.message


def add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_attestations=False):
def add_block(spec,
store,
signed_block,
test_steps,
valid=True,
allow_invalid_attestations=False,
block_not_found=False):
"""
Run on_block and on_attestation
"""
Expand All @@ -127,7 +143,9 @@ def add_block(spec, store, signed_block, test_steps, valid=True, allow_invalid_a
if not valid:
try:
run_on_block(spec, store, signed_block, valid=True)
except AssertionError:
except (AssertionError, BlockNotFoundException) as e:
if isinstance(e, BlockNotFoundException) and not block_not_found:
assert False
test_steps.append({
'block': get_block_file_name(signed_block),
'valid': False,
Expand Down Expand Up @@ -227,3 +245,21 @@ def apply_next_slots_with_attestations(spec,
assert store.block_states[block_root].hash_tree_root() == post_state.hash_tree_root()

return post_state, store, last_signed_block


def prepare_empty_pow_block(spec, rng=Random(3131)):
return spec.PowBlock(
block_hash=spec.Hash32(spec.hash(bytearray(rng.getrandbits(8) for _ in range(32)))),
parent_hash=spec.Hash32(spec.hash(bytearray(rng.getrandbits(8) for _ in range(32)))),
total_difficulty=uint256(0),
difficulty=uint256(0)
)


def get_pow_block_file_name(pow_block):
return f"pow_block_{encode_hex(pow_block.block_hash)}"


def add_pow_block(spec, store, pow_block, test_steps):
yield get_pow_block_file_name(pow_block), pow_block
test_steps.append({'pow_block': get_pow_block_file_name(pow_block)})
Loading

0 comments on commit 67fd797

Please sign in to comment.