Skip to content

Commit

Permalink
prague initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
gurukamath authored and SamWilsn committed Aug 13, 2024
1 parent fcd1275 commit 37203e6
Show file tree
Hide file tree
Showing 47 changed files with 8,877 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/ethereum/prague/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""
The Prague fork introduces transient storage, exposes beacon chain roots,
introduces a new blob-carrying transaction type, adds a memory copying
instruction, limits self-destruct to only work for contracts created in the
same transaction, and adds an instruction to read the blob base fee.
"""

from ethereum.fork_criteria import ByTimestamp

FORK_CRITERIA = ByTimestamp(1710338135)
105 changes: 105 additions & 0 deletions src/ethereum/prague/blocks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""
A `Block` is a single link in the chain that is Ethereum. Each `Block` contains
a `Header` and zero or more transactions. Each `Header` contains associated
metadata like the block number, parent block hash, and how much gas was
consumed by its transactions.
Together, these blocks form a cryptographically secure journal recording the
history of all state transitions that have happened since the genesis of the
chain.
"""
from dataclasses import dataclass
from typing import Tuple, Union

from ..base_types import (
U64,
U256,
Bytes,
Bytes8,
Bytes32,
Uint,
slotted_freezable,
)
from ..crypto.hash import Hash32
from .fork_types import Address, Bloom, Root
from .transactions import LegacyTransaction


@slotted_freezable
@dataclass
class Withdrawal:
"""
Withdrawals that have been validated on the consensus layer.
"""

index: U64
validator_index: U64
address: Address
amount: U256


@slotted_freezable
@dataclass
class Header:
"""
Header portion of a block on the chain.
"""

parent_hash: Hash32
ommers_hash: Hash32
coinbase: Address
state_root: Root
transactions_root: Root
receipt_root: Root
bloom: Bloom
difficulty: Uint
number: Uint
gas_limit: Uint
gas_used: Uint
timestamp: U256
extra_data: Bytes
prev_randao: Bytes32
nonce: Bytes8
base_fee_per_gas: Uint
withdrawals_root: Root
blob_gas_used: U64
excess_blob_gas: U64
parent_beacon_block_root: Root


@slotted_freezable
@dataclass
class Block:
"""
A complete block.
"""

header: Header
transactions: Tuple[Union[Bytes, LegacyTransaction], ...]
ommers: Tuple[Header, ...]
withdrawals: Tuple[Withdrawal, ...]


@slotted_freezable
@dataclass
class Log:
"""
Data record produced during the execution of a transaction.
"""

address: Address
topics: Tuple[Hash32, ...]
data: bytes


@slotted_freezable
@dataclass
class Receipt:
"""
Result of a transaction.
"""

succeeded: bool
cumulative_gas_used: Uint
bloom: Bloom
logs: Tuple[Log, ...]
84 changes: 84 additions & 0 deletions src/ethereum/prague/bloom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""
Ethereum Logs Bloom
^^^^^^^^^^^^^^^^^^^
.. contents:: Table of Contents
:backlinks: none
:local:
Introduction
------------
This modules defines functions for calculating bloom filters of logs. For the
general theory of bloom filters see e.g. `Wikipedia
<https://en.wikipedia.org/wiki/Bloom_filter>`_. Bloom filters are used to allow
for efficient searching of logs by address and/or topic, by rapidly
eliminating blocks and receipts from their search.
"""

from typing import Tuple

from ethereum.base_types import Uint
from ethereum.crypto.hash import keccak256

from .blocks import Log
from .fork_types import Bloom


def add_to_bloom(bloom: bytearray, bloom_entry: bytes) -> None:
"""
Add a bloom entry to the bloom filter (`bloom`).
The number of hash functions used is 3. They are calculated by taking the
least significant 11 bits from the first 3 16-bit words of the
`keccak_256()` hash of `bloom_entry`.
Parameters
----------
bloom :
The bloom filter.
bloom_entry :
An entry which is to be added to bloom filter.
"""
hash = keccak256(bloom_entry)

for idx in (0, 2, 4):
# Obtain the least significant 11 bits from the pair of bytes
# (16 bits), and set this bit in bloom bytearray.
# The obtained bit is 0-indexed in the bloom filter from the least
# significant bit to the most significant bit.
bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & 0x07FF
# Below is the index of the bit in the bytearray (where 0-indexed
# byte is the most significant byte)
bit_index = 0x07FF - bit_to_set

byte_index = bit_index // 8
bit_value = 1 << (7 - (bit_index % 8))
bloom[byte_index] = bloom[byte_index] | bit_value


def logs_bloom(logs: Tuple[Log, ...]) -> Bloom:
"""
Obtain the logs bloom from a list of log entries.
The address and each topic of a log are added to the bloom filter.
Parameters
----------
logs :
List of logs for which the logs bloom is to be obtained.
Returns
-------
logs_bloom : `Bloom`
The logs bloom obtained which is 256 bytes with some bits set as per
the caller address and the log topics.
"""
bloom: bytearray = bytearray(b"\x00" * 256)

for log in logs:
add_to_bloom(bloom, log.address)
for topic in log.topics:
add_to_bloom(bloom, topic)

return Bloom(bloom)
Loading

0 comments on commit 37203e6

Please sign in to comment.