ethereum.fork_criteria

Activation criteria for forks.

Most generally, a fork is a divergence in a blockchain resulting in multiple tips. Most forks are short lived, and can be caused by networking issues or the behavior of block creators. These short-lived forks resolve themselves according to the rules of the protocol, eventually settling back to a single tip of the chain.

A second class of forks are intentionally created by changing the rules of the protocol, and never resolve back to a single tip. Older software will continue to follow the original fork, while updated software will create and follow a new fork.

For these intentional forks to succeed, all participants need to agree on exactly when to switch rules. The agreed upon criteria are represented by subclasses of ForkCriteria, like ByBlockNumber and ByTimestamp. The special type of Unscheduled is used for forks in active development that do not yet have a scheduled deployment.

ForkCriteria

Abstract base class for conditions specifying when a fork activates.

Subclasses override the comparison methods (__eq__ and __lt__) to provide an ordering for forks, and override check to determine whether a particular block meets the activation criteria.

35
@functools.total_ordering
class ForkCriteria:

BLOCK_NUMBER

Value representing a fork criteria based on the block's number.

Used for pre-merge blocks.

49
    BLOCK_NUMBER: Final[int] = 0

TIMESTAMP

Value representing a fork criteria based on the block's timestamp.

Used for post-merge blocks.

56
    TIMESTAMP: Final[int] = 1

UNSCHEDULED

Value representing a fork criteria that will never be satisfied.

Used for in-development forks.

63
    UNSCHEDULED: Final[int] = 2

_internal

70
    _internal: Tuple[int, int]

__eq__

Equality for fork criteria.

def __eq__(self, ​​other: object) -> bool:
73
        <snip>
76
        if isinstance(other, ForkCriteria):
77
            return self._internal == other._internal
78
        return NotImplemented

__lt__

Less-than comparison function, with earlier forks being less than later forks.

All BLOCK_NUMBER forks come before TIMESTAMP forks, and all scheduled forks come before UNSCHEDULED forks.

def __lt__(self, ​​other: object) -> bool:
81
        <snip>
92
        if isinstance(other, ForkCriteria):
93
            return self._internal < other._internal
94
        return NotImplemented

__hash__

Compute a hash for this instance, so it can be stored in dictionaries.

def __hash__(self) -> int:
97
        <snip>
100
        return hash(self._internal)

check

Check whether fork criteria have been met.

Returns True when the current block meets or exceeds the criteria, and False otherwise.

102
    @abstractmethod
def check(self, ​​block_number: Uint, ​​timestamp: U256) -> bool:
104
        <snip>
110
        raise NotImplementedError()

__repr__

String representation of this object.

112
    @abstractmethod
def __repr__(self) -> str:
114
        <snip>
117
        raise NotImplementedError()

ByBlockNumber

Forks that occur when a specific block number has been reached.

class ByBlockNumber:

block_number

Number of the first block in this fork.

125
    block_number: Uint

__init__

def __init__(self, ​​block_number: SupportsInt):
131
        self._internal = (ForkCriteria.BLOCK_NUMBER, int(block_number))
132
        self.block_number = Uint(int(block_number))

check

Check whether the block number has been reached.

Returns True when the given block_number is equal to or greater than block_number, and False otherwise.

134
    @override
def check(self, ​​block_number: Uint, ​​timestamp: U256) -> bool:
136
        <snip>
144
        return block_number >= self.block_number

__repr__

String representation of this object.

def __repr__(self) -> str:
147
        <snip>
150
        return f"ByBlockNumber({self.block_number})"

ByTimestamp

Forks that occur when a specific timestamp has been reached.

class ByTimestamp:

timestamp

First instance of time that is part of this fork.

158
    timestamp: U256

__init__

def __init__(self, ​​timestamp: SupportsInt):
164
        self._internal = (ForkCriteria.TIMESTAMP, int(timestamp))
165
        self.timestamp = U256(timestamp)

check

Check whether the timestamp has been reached.

Returns True when the given timestamp is equal to or greater than timestamp, and False otherwise.

167
    @override
def check(self, ​​block_number: Uint, ​​timestamp: U256) -> bool:
169
        <snip>
177
        return timestamp >= self.timestamp

__repr__

String representation of this object.

def __repr__(self) -> str:
180
        <snip>
183
        return f"ByTimestamp({self.timestamp})"

Unscheduled

Forks that have not been scheduled.

class Unscheduled:

__init__

def __init__(self, ​​order_index: int) -> None:
192
        self._internal = (ForkCriteria.UNSCHEDULED, order_index)

check

Unscheduled forks never occur; always returns False.

194
    @override
def check(self, ​​block_number: Uint, ​​timestamp: U256) -> Literal[False]:
196
        <snip>
199
        return False

__repr__

String representation of this object.

def __repr__(self) -> str:
202
        <snip>
205
        return f"Unscheduled(order_index={self._internal[1]})"