Skip to content

Commit 01e6fcb

Browse files
committed
osaka initial commit
1 parent 81ec8ee commit 01e6fcb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+10853
-0
lines changed

src/ethereum/osaka/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""
2+
The Osaka fork.
3+
"""
4+
5+
from ethereum.fork_criteria import ByTimestamp
6+
7+
FORK_CRITERIA = ByTimestamp(1746612311)

src/ethereum/osaka/blocks.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
"""
2+
A `Block` is a single link in the chain that is Ethereum. Each `Block` contains
3+
a `Header` and zero or more transactions. Each `Header` contains associated
4+
metadata like the block number, parent block hash, and how much gas was
5+
consumed by its transactions.
6+
7+
Together, these blocks form a cryptographically secure journal recording the
8+
history of all state transitions that have happened since the genesis of the
9+
chain.
10+
"""
11+
from dataclasses import dataclass
12+
from typing import Tuple, Union
13+
14+
from ethereum_rlp import rlp
15+
from ethereum_types.bytes import Bytes, Bytes8, Bytes32
16+
from ethereum_types.frozen import slotted_freezable
17+
from ethereum_types.numeric import U64, U256, Uint
18+
19+
from ..crypto.hash import Hash32
20+
from .fork_types import Address, Bloom, Root
21+
from .transactions import (
22+
AccessListTransaction,
23+
BlobTransaction,
24+
FeeMarketTransaction,
25+
LegacyTransaction,
26+
SetCodeTransaction,
27+
Transaction,
28+
)
29+
30+
31+
@slotted_freezable
32+
@dataclass
33+
class Withdrawal:
34+
"""
35+
Withdrawals that have been validated on the consensus layer.
36+
"""
37+
38+
index: U64
39+
validator_index: U64
40+
address: Address
41+
amount: U256
42+
43+
44+
@slotted_freezable
45+
@dataclass
46+
class Header:
47+
"""
48+
Header portion of a block on the chain.
49+
"""
50+
51+
parent_hash: Hash32
52+
ommers_hash: Hash32
53+
coinbase: Address
54+
state_root: Root
55+
transactions_root: Root
56+
receipt_root: Root
57+
bloom: Bloom
58+
difficulty: Uint
59+
number: Uint
60+
gas_limit: Uint
61+
gas_used: Uint
62+
timestamp: U256
63+
extra_data: Bytes
64+
prev_randao: Bytes32
65+
nonce: Bytes8
66+
base_fee_per_gas: Uint
67+
withdrawals_root: Root
68+
blob_gas_used: U64
69+
excess_blob_gas: U64
70+
parent_beacon_block_root: Root
71+
requests_hash: Hash32
72+
73+
74+
@slotted_freezable
75+
@dataclass
76+
class Block:
77+
"""
78+
A complete block.
79+
"""
80+
81+
header: Header
82+
transactions: Tuple[Union[Bytes, LegacyTransaction], ...]
83+
ommers: Tuple[Header, ...]
84+
withdrawals: Tuple[Withdrawal, ...]
85+
86+
87+
@slotted_freezable
88+
@dataclass
89+
class Log:
90+
"""
91+
Data record produced during the execution of a transaction.
92+
"""
93+
94+
address: Address
95+
topics: Tuple[Hash32, ...]
96+
data: Bytes
97+
98+
99+
@slotted_freezable
100+
@dataclass
101+
class Receipt:
102+
"""
103+
Result of a transaction.
104+
"""
105+
106+
succeeded: bool
107+
cumulative_gas_used: Uint
108+
bloom: Bloom
109+
logs: Tuple[Log, ...]
110+
111+
112+
def encode_receipt(tx: Transaction, receipt: Receipt) -> Union[Bytes, Receipt]:
113+
"""
114+
Encodes a receipt.
115+
"""
116+
if isinstance(tx, AccessListTransaction):
117+
return b"\x01" + rlp.encode(receipt)
118+
elif isinstance(tx, FeeMarketTransaction):
119+
return b"\x02" + rlp.encode(receipt)
120+
elif isinstance(tx, BlobTransaction):
121+
return b"\x03" + rlp.encode(receipt)
122+
elif isinstance(tx, SetCodeTransaction):
123+
return b"\x04" + rlp.encode(receipt)
124+
else:
125+
return receipt
126+
127+
128+
def decode_receipt(receipt: Union[Bytes, Receipt]) -> Receipt:
129+
"""
130+
Decodes a receipt.
131+
"""
132+
if isinstance(receipt, Bytes):
133+
assert receipt[0] in (1, 2, 3, 4)
134+
return rlp.decode_to(Receipt, receipt[1:])
135+
else:
136+
return receipt

src/ethereum/osaka/bloom.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""
2+
Ethereum Logs Bloom
3+
^^^^^^^^^^^^^^^^^^^
4+
5+
.. contents:: Table of Contents
6+
:backlinks: none
7+
:local:
8+
9+
Introduction
10+
------------
11+
12+
This modules defines functions for calculating bloom filters of logs. For the
13+
general theory of bloom filters see e.g. `Wikipedia
14+
<https://en.wikipedia.org/wiki/Bloom_filter>`_. Bloom filters are used to allow
15+
for efficient searching of logs by address and/or topic, by rapidly
16+
eliminating blocks and receipts from their search.
17+
"""
18+
19+
from typing import Tuple
20+
21+
from ethereum_types.bytes import Bytes
22+
from ethereum_types.numeric import Uint
23+
24+
from ethereum.crypto.hash import keccak256
25+
26+
from .blocks import Log
27+
from .fork_types import Bloom
28+
29+
30+
def add_to_bloom(bloom: bytearray, bloom_entry: Bytes) -> None:
31+
"""
32+
Add a bloom entry to the bloom filter (`bloom`).
33+
34+
The number of hash functions used is 3. They are calculated by taking the
35+
least significant 11 bits from the first 3 16-bit words of the
36+
`keccak_256()` hash of `bloom_entry`.
37+
38+
Parameters
39+
----------
40+
bloom :
41+
The bloom filter.
42+
bloom_entry :
43+
An entry which is to be added to bloom filter.
44+
"""
45+
hash = keccak256(bloom_entry)
46+
47+
for idx in (0, 2, 4):
48+
# Obtain the least significant 11 bits from the pair of bytes
49+
# (16 bits), and set this bit in bloom bytearray.
50+
# The obtained bit is 0-indexed in the bloom filter from the least
51+
# significant bit to the most significant bit.
52+
bit_to_set = Uint.from_be_bytes(hash[idx : idx + 2]) & Uint(0x07FF)
53+
# Below is the index of the bit in the bytearray (where 0-indexed
54+
# byte is the most significant byte)
55+
bit_index = 0x07FF - int(bit_to_set)
56+
57+
byte_index = bit_index // 8
58+
bit_value = 1 << (7 - (bit_index % 8))
59+
bloom[byte_index] = bloom[byte_index] | bit_value
60+
61+
62+
def logs_bloom(logs: Tuple[Log, ...]) -> Bloom:
63+
"""
64+
Obtain the logs bloom from a list of log entries.
65+
66+
The address and each topic of a log are added to the bloom filter.
67+
68+
Parameters
69+
----------
70+
logs :
71+
List of logs for which the logs bloom is to be obtained.
72+
73+
Returns
74+
-------
75+
logs_bloom : `Bloom`
76+
The logs bloom obtained which is 256 bytes with some bits set as per
77+
the caller address and the log topics.
78+
"""
79+
bloom: bytearray = bytearray(b"\x00" * 256)
80+
81+
for log in logs:
82+
add_to_bloom(bloom, log.address)
83+
for topic in log.topics:
84+
add_to_bloom(bloom, topic)
85+
86+
return Bloom(bloom)

src/ethereum/osaka/exceptions.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""
2+
Exceptions specific to this fork.
3+
"""
4+
5+
from typing import Final
6+
7+
from ethereum.exceptions import InvalidTransaction
8+
9+
10+
class TransactionTypeError(InvalidTransaction):
11+
"""
12+
Unknown [EIP-2718] transaction type byte.
13+
14+
[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718
15+
"""
16+
17+
transaction_type: Final[int]
18+
"""
19+
The type byte of the transaction that caused the error.
20+
"""
21+
22+
def __init__(self, transaction_type: int):
23+
super().__init__(f"unknown transaction type `{transaction_type}`")
24+
self.transaction_type = transaction_type

0 commit comments

Comments
 (0)