22Block Access List Builder for EIP-7928
33^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44
5- This module implements the Block Access List builder that tracks all account and storage
6- accesses during block execution and constructs the final BlockAccessList.
5+ This module implements the Block Access List builder that tracks all account
6+ and storage accesses during block execution and constructs the final
7+ [`BlockAccessList`].
8+
9+ The builder follows a two-phase approach:
10+
11+ 1. **Collection Phase**: During transaction execution, all state accesses are
12+ recorded via the tracking functions.
13+ 2. **Build Phase**: After block execution, the accumulated data is sorted
14+ and encoded into the final deterministic format.
15+
16+ [`BlockAccessList`]: ref:ethereum.osaka.ssz_types.BlockAccessList
717"""
818
919from dataclasses import dataclass , field
2737@dataclass
2838class AccountData :
2939 """
30- Account data stored in the builder.
40+ Account data stored in the builder during block execution.
41+
42+ This dataclass tracks all changes made to a single account throughout
43+ the execution of a block, organized by the type of change and the
44+ transaction index where it occurred.
3145 """
3246 storage_changes : Dict [Bytes , List [StorageChange ]] = field (default_factory = dict )
47+ """
48+ Mapping from storage slot to list of changes made to that slot.
49+ Each change includes the transaction index and new value.
50+ """
51+
3352 storage_reads : Set [Bytes ] = field (default_factory = set )
53+ """
54+ Set of storage slots that were read but not modified.
55+ """
56+
3457 balance_changes : List [BalanceChange ] = field (default_factory = list )
58+ """
59+ List of balance changes for this account, ordered by transaction index.
60+ """
61+
3562 nonce_changes : List [NonceChange ] = field (default_factory = list )
63+ """
64+ List of nonce changes for this account, ordered by transaction index.
65+ """
66+
3667 code_changes : List [CodeChange ] = field (default_factory = list )
68+ """
69+ List of code changes (contract deployments) for this account,
70+ ordered by transaction index.
71+ """
3772
3873
3974@dataclass
4075class BlockAccessListBuilder :
4176 """
42- Builder for constructing `BlockAccessList` efficiently during transaction
77+ Builder for constructing [ `BlockAccessList`] efficiently during transaction
4378 execution.
4479
4580 The builder accumulates all account and storage accesses during block
46- execution and constructs a deterministic access list following the pattern:
47- address -> field -> tx_index -> change
81+ execution and constructs a deterministic access list. Changes are tracked
82+ by address, field type, and transaction index to enable efficient
83+ reconstruction of state changes.
84+
85+ [`BlockAccessList`]: ref:ethereum.osaka.ssz_types.BlockAccessList
4886 """
4987 accounts : Dict [Address , AccountData ] = field (default_factory = dict )
88+ """
89+ Mapping from account address to its tracked changes during block execution.
90+ """
5091
5192
5293def ensure_account (builder : BlockAccessListBuilder , address : Address ) -> None :
5394 """
54- Ensure account exists in builder.
95+ Ensure an account exists in the builder's tracking structure.
96+
97+ Creates an empty [`AccountData`] entry for the given address if it
98+ doesn't already exist. This function is idempotent and safe to call
99+ multiple times for the same address.
55100
56- Creates an empty account entry if it doesn't already exist.
101+ Parameters
102+ ----------
103+ builder :
104+ The block access list builder instance.
105+ address :
106+ The account address to ensure exists.
107+
108+ [`AccountData`]: ref:ethereum.osaka.block_access_lists.builder.AccountData
57109 """
58110 if address not in builder .accounts :
59111 builder .accounts [address ] = AccountData ()
@@ -63,21 +115,35 @@ def add_storage_write(
63115 builder : BlockAccessListBuilder ,
64116 address : Address ,
65117 slot : Bytes ,
66- tx_index : int ,
118+ tx_index : U32 ,
67119 new_value : Bytes
68120) -> None :
69121 """
70- Add storage write to the block access list.
122+ Add a storage write operation to the block access list.
71123
72124 Records a storage slot modification for a given address at a specific
73- transaction index.
125+ transaction index. Multiple writes to the same slot are tracked
126+ separately, maintaining the order and transaction index of each change.
127+
128+ Parameters
129+ ----------
130+ builder :
131+ The block access list builder instance.
132+ address :
133+ The account address whose storage is being modified.
134+ slot :
135+ The storage slot being written to.
136+ tx_index :
137+ The index of the transaction making this change.
138+ new_value :
139+ The new value being written to the storage slot.
74140 """
75141 ensure_account (builder , address )
76142
77143 if slot not in builder .accounts [address ].storage_changes :
78144 builder .accounts [address ].storage_changes [slot ] = []
79145
80- change = StorageChange (tx_index = U32 ( tx_index ) , new_value = new_value )
146+ change = StorageChange (tx_index = tx_index , new_value = new_value )
81147 builder .accounts [address ].storage_changes [slot ].append (change )
82148
83149
@@ -87,10 +153,22 @@ def add_storage_read(
87153 slot : Bytes
88154) -> None :
89155 """
90- Add storage read to the block access list.
156+ Add a storage read operation to the block access list.
91157
92- Records a storage slot read for a given address. Only slots that are
93- not also written to will be included in the final access list.
158+ Records that a storage slot was read during execution. Storage slots
159+ that are both read and written will only appear in the storage changes
160+ list, not in the storage reads list, as per [EIP-7928].
161+
162+ Parameters
163+ ----------
164+ builder :
165+ The block access list builder instance.
166+ address :
167+ The account address whose storage is being read.
168+ slot :
169+ The storage slot being read.
170+
171+ [EIP-7928]: https://eips.ethereum.org/EIPS/eip-7928
94172 """
95173 ensure_account (builder , address )
96174 builder .accounts [address ].storage_reads .add (slot )
@@ -99,73 +177,147 @@ def add_storage_read(
99177def add_balance_change (
100178 builder : BlockAccessListBuilder ,
101179 address : Address ,
102- tx_index : int ,
180+ tx_index : U32 ,
103181 post_balance : Bytes
104182) -> None :
105183 """
106- Add balance change to the block access list.
184+ Add a balance change to the block access list.
107185
108- Records a balance change for a given address at a specific transaction
109- index.
186+ Records the post-transaction balance for an account after it has been
187+ modified. This includes changes from transfers, gas fees, block rewards,
188+ and any other balance-affecting operations.
189+
190+ Parameters
191+ ----------
192+ builder :
193+ The block access list builder instance.
194+ address :
195+ The account address whose balance changed.
196+ tx_index :
197+ The index of the transaction causing this change.
198+ post_balance :
199+ The account balance after the change, encoded as bytes.
110200 """
111201 ensure_account (builder , address )
112202
113- change = BalanceChange (tx_index = U32 ( tx_index ) , post_balance = post_balance )
203+ change = BalanceChange (tx_index = tx_index , post_balance = post_balance )
114204 builder .accounts [address ].balance_changes .append (change )
115205
116206
117207def add_nonce_change (
118208 builder : BlockAccessListBuilder ,
119209 address : Address ,
120- tx_index : int ,
121- new_nonce : int
210+ tx_index : U32 ,
211+ new_nonce : U64
122212) -> None :
123213 """
124- Add nonce change to the block access list.
214+ Add a nonce change to the block access list.
215+
216+ Records a nonce increment for an account. This occurs when an EOA sends
217+ a transaction or when a contract performs [`CREATE`] or [`CREATE2`]
218+ operations.
125219
126- Records a nonce change for a given address at a specific transaction
127- index.
220+ Parameters
221+ ----------
222+ builder :
223+ The block access list builder instance.
224+ address :
225+ The account address whose nonce changed.
226+ tx_index :
227+ The index of the transaction causing this change.
228+ new_nonce :
229+ The new nonce value after the change.
230+
231+ [`CREATE`]: ref:ethereum.osaka.vm.instructions.system.create
232+ [`CREATE2`]: ref:ethereum.osaka.vm.instructions.system.create2
128233 """
129234 ensure_account (builder , address )
130235
131- change = NonceChange (tx_index = U32 ( tx_index ) , new_nonce = U64 ( new_nonce ) )
236+ change = NonceChange (tx_index = tx_index , new_nonce = new_nonce )
132237 builder .accounts [address ].nonce_changes .append (change )
133238
134239
135240def add_code_change (
136241 builder : BlockAccessListBuilder ,
137242 address : Address ,
138- tx_index : int ,
243+ tx_index : U32 ,
139244 new_code : Bytes
140245) -> None :
141246 """
142- Add code change to the block access list.
247+ Add a code change to the block access list.
248+
249+ Records contract code deployment or modification. This typically occurs
250+ during contract creation via [`CREATE`], [`CREATE2`], or [`SETCODE`]
251+ operations.
252+
253+ Parameters
254+ ----------
255+ builder :
256+ The block access list builder instance.
257+ address :
258+ The account address receiving new code.
259+ tx_index :
260+ The index of the transaction deploying the code.
261+ new_code :
262+ The deployed contract bytecode.
143263
144- Records a code change for a given address at a specific transaction
145- index.
264+ [`CREATE`]: ref:ethereum.osaka.vm.instructions.system.create
265+ [`CREATE2`]: ref:ethereum.osaka.vm.instructions.system.create2
266+ [`SETCODE`]: ref:ethereum.osaka.vm.instructions.system.setcode
146267 """
147268 ensure_account (builder , address )
148269
149- change = CodeChange (tx_index = U32 ( tx_index ) , new_code = new_code )
270+ change = CodeChange (tx_index = tx_index , new_code = new_code )
150271 builder .accounts [address ].code_changes .append (change )
151272
152273
153274def add_touched_account (builder : BlockAccessListBuilder , address : Address ) -> None :
154275 """
155- Add an account that was touched but not changed.
276+ Add an account that was accessed but not modified.
277+
278+ Records that an account was accessed during execution without any state
279+ changes. This is used for operations like [`EXTCODEHASH`], [`BALANCE`],
280+ [`EXTCODESIZE`], and [`EXTCODECOPY`] that read account data without
281+ modifying it.
282+
283+ Parameters
284+ ----------
285+ builder :
286+ The block access list builder instance.
287+ address :
288+ The account address that was accessed.
156289
157- Used for operations like EXTCODEHASH or BALANCE checks that access
158- an account without modifying it.
290+ [`EXTCODEHASH`]: ref:ethereum.osaka.vm.instructions.environment.extcodehash
291+ [`BALANCE`]: ref:ethereum.osaka.vm.instructions.environment.balance
292+ [`EXTCODESIZE`]: ref:ethereum.osaka.vm.instructions.environment.extcodesize
293+ [`EXTCODECOPY`]: ref:ethereum.osaka.vm.instructions.environment.extcodecopy
159294 """
160295 ensure_account (builder , address )
161296
162297
163298def build (builder : BlockAccessListBuilder ) -> BlockAccessList :
164299 """
165- Build the final BlockAccessList.
300+ Build the final [`BlockAccessList`] from accumulated changes.
301+
302+ Constructs a deterministic block access list by sorting all accumulated
303+ changes. The resulting list is ordered by:
304+
305+ 1. Account addresses (lexicographically)
306+ 2. Within each account:
307+ - Storage slots (lexicographically)
308+ - Transaction indices (numerically) for each change type
309+
310+ Parameters
311+ ----------
312+ builder :
313+ The block access list builder containing all tracked changes.
314+
315+ Returns
316+ -------
317+ block_access_list :
318+ The final sorted and encoded block access list.
166319
167- Constructs a sorted and deterministic block access list from all
168- accumulated changes.
320+ [`BlockAccessList`]: ref:ethereum.osaka.ssz_types.BlockAccessList
169321 """
170322 account_changes_list = []
171323
0 commit comments