|
16 | 16 |
|
17 | 17 | from ..base_fork import ( |
18 | 18 | BaseFork, |
| 19 | + BlobGasPriceCalculator, |
19 | 20 | CalldataGasCalculator, |
| 21 | + ExcessBlobGasCalculator, |
20 | 22 | MemoryExpansionGasCalculator, |
21 | 23 | TransactionDataFloorCostCalculator, |
22 | 24 | TransactionIntrinsicCostCalculator, |
23 | 25 | ) |
24 | 26 | from ..gas_costs import GasCosts |
| 27 | +from .helpers import ceiling_division, fake_exponential |
25 | 28 |
|
26 | 29 | CURRENT_FILE = Path(realpath(__file__)) |
27 | 30 | CURRENT_FOLDER = CURRENT_FILE.parent |
28 | 31 |
|
29 | 32 |
|
30 | | -def ceiling_division(a: int, b: int) -> int: |
31 | | - """ |
32 | | - Calculates the ceil without using floating point. |
33 | | - Used by many of the EVM's formulas |
34 | | - """ |
35 | | - return -(a // -b) |
36 | | - |
37 | | - |
38 | 33 | # All forks must be listed here !!! in the order they were introduced !!! |
39 | 34 | class Frontier(BaseFork, solc_name="homestead"): |
40 | 35 | """ |
@@ -245,28 +240,60 @@ def fn( |
245 | 240 | return fn |
246 | 241 |
|
247 | 242 | @classmethod |
248 | | - def blob_gas_per_blob(cls, block_number: int, timestamp: int) -> int: |
| 243 | + def blob_gas_price_calculator( |
| 244 | + cls, block_number: int = 0, timestamp: int = 0 |
| 245 | + ) -> BlobGasPriceCalculator: |
249 | 246 | """ |
250 | | - Returns the amount of blob gas used per blob for a given fork. |
| 247 | + Returns a callable that calculates the blob gas price at a given fork. |
251 | 248 | """ |
252 | | - return 0 |
| 249 | + raise NotImplementedError("Blob gas price calculator is not supported in Frontier") |
253 | 250 |
|
254 | 251 | @classmethod |
255 | | - def target_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 252 | + def excess_blob_gas_calculator( |
| 253 | + cls, block_number: int = 0, timestamp: int = 0 |
| 254 | + ) -> ExcessBlobGasCalculator: |
256 | 255 | """ |
257 | | - Returns the target number of blobs per block for a given fork. |
| 256 | + Returns a callable that calculates the excess blob gas for a block at a given fork. |
258 | 257 | """ |
259 | | - return 0 |
| 258 | + raise NotImplementedError("Excess blob gas calculator is not supported in Frontier") |
260 | 259 |
|
261 | 260 | @classmethod |
262 | | - def max_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 261 | + def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: |
263 | 262 | """ |
264 | | - Returns the max number of blobs per block for a given fork. |
| 263 | + Returns the amount of blob gas used per blob at a given fork. |
265 | 264 | """ |
266 | | - return 0 |
| 265 | + raise NotImplementedError("Base fee per blob gas is not supported in Frontier") |
| 266 | + |
| 267 | + @classmethod |
| 268 | + def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 269 | + """ |
| 270 | + Returns the blob base fee update fraction at a given fork. |
| 271 | + """ |
| 272 | + raise NotImplementedError("Blob base fee update fraction is not supported in Frontier") |
| 273 | + |
| 274 | + @classmethod |
| 275 | + def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 276 | + """ |
| 277 | + Returns the amount of blob gas used per blob at a given fork. |
| 278 | + """ |
| 279 | + raise NotImplementedError("Blob gas per blob is not supported in Frontier") |
| 280 | + |
| 281 | + @classmethod |
| 282 | + def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 283 | + """ |
| 284 | + Returns the target number of blobs per block at a given fork. |
| 285 | + """ |
| 286 | + raise NotImplementedError("Target blobs per block is not supported in Frontier") |
267 | 287 |
|
268 | 288 | @classmethod |
269 | | - def header_requests_required(cls, block_number: int, timestamp: int) -> bool: |
| 289 | + def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 290 | + """ |
| 291 | + Returns the max number of blobs per block at a given fork. |
| 292 | + """ |
| 293 | + raise NotImplementedError("Max blobs per block is not supported in Frontier") |
| 294 | + |
| 295 | + @classmethod |
| 296 | + def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: |
270 | 297 | """ |
271 | 298 | At genesis, header must not contain beacon chain requests. |
272 | 299 | """ |
@@ -1011,21 +1038,85 @@ def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) |
1011 | 1038 | return True |
1012 | 1039 |
|
1013 | 1040 | @classmethod |
1014 | | - def blob_gas_per_blob(cls, block_number: int, timestamp: int) -> int: |
| 1041 | + def blob_gas_price_calculator( |
| 1042 | + cls, block_number: int = 0, timestamp: int = 0 |
| 1043 | + ) -> BlobGasPriceCalculator: |
| 1044 | + """ |
| 1045 | + Returns a callable that calculates the blob gas price at Cancun. |
| 1046 | + """ |
| 1047 | + min_base_fee_per_blob_gas = cls.min_base_fee_per_blob_gas(block_number, timestamp) |
| 1048 | + blob_base_fee_update_fraction = cls.blob_base_fee_update_fraction(block_number, timestamp) |
| 1049 | + |
| 1050 | + def fn(*, excess_blob_gas) -> int: |
| 1051 | + return fake_exponential( |
| 1052 | + min_base_fee_per_blob_gas, |
| 1053 | + excess_blob_gas, |
| 1054 | + blob_base_fee_update_fraction, |
| 1055 | + ) |
| 1056 | + |
| 1057 | + return fn |
| 1058 | + |
| 1059 | + @classmethod |
| 1060 | + def excess_blob_gas_calculator( |
| 1061 | + cls, block_number: int = 0, timestamp: int = 0 |
| 1062 | + ) -> ExcessBlobGasCalculator: |
| 1063 | + """ |
| 1064 | + Returns a callable that calculates the excess blob gas for a block at Cancun. |
| 1065 | + """ |
| 1066 | + target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp) |
| 1067 | + blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp) |
| 1068 | + target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob |
| 1069 | + |
| 1070 | + def fn( |
| 1071 | + *, |
| 1072 | + parent_excess_blob_gas: int | None = None, |
| 1073 | + parent_excess_blobs: int | None = None, |
| 1074 | + parent_blob_gas_used: int | None = None, |
| 1075 | + parent_blob_count: int | None = None, |
| 1076 | + ) -> int: |
| 1077 | + if parent_excess_blob_gas is None: |
| 1078 | + assert parent_excess_blobs is not None, "Parent excess blobs are required" |
| 1079 | + parent_excess_blob_gas = parent_excess_blobs * blob_gas_per_blob |
| 1080 | + if parent_blob_gas_used is None: |
| 1081 | + assert parent_blob_count is not None, "Parent blob count is required" |
| 1082 | + parent_blob_gas_used = parent_blob_count * blob_gas_per_blob |
| 1083 | + if parent_excess_blob_gas + parent_blob_gas_used < target_blob_gas_per_block: |
| 1084 | + return 0 |
| 1085 | + else: |
| 1086 | + return parent_excess_blob_gas + parent_blob_gas_used - target_blob_gas_per_block |
| 1087 | + |
| 1088 | + return fn |
| 1089 | + |
| 1090 | + @classmethod |
| 1091 | + def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1092 | + """ |
| 1093 | + Returns the minimum base fee per blob gas for Cancun. |
| 1094 | + """ |
| 1095 | + return 1 |
| 1096 | + |
| 1097 | + @classmethod |
| 1098 | + def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1099 | + """ |
| 1100 | + Returns the blob base fee update fraction for Cancun. |
| 1101 | + """ |
| 1102 | + return 3338477 |
| 1103 | + |
| 1104 | + @classmethod |
| 1105 | + def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int: |
1015 | 1106 | """ |
1016 | 1107 | Blobs are enabled starting from Cancun. |
1017 | 1108 | """ |
1018 | 1109 | return 2**17 |
1019 | 1110 |
|
1020 | 1111 | @classmethod |
1021 | | - def target_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 1112 | + def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
1022 | 1113 | """ |
1023 | 1114 | Blobs are enabled starting from Cancun, with a static target of 3 blobs. |
1024 | 1115 | """ |
1025 | 1116 | return 3 |
1026 | 1117 |
|
1027 | 1118 | @classmethod |
1028 | | - def max_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 1119 | + def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
1029 | 1120 | """ |
1030 | 1121 | Blobs are enabled starting from Cancun, with a static max of 6 blobs. |
1031 | 1122 | """ |
@@ -1256,6 +1347,34 @@ def fn( |
1256 | 1347 |
|
1257 | 1348 | return fn |
1258 | 1349 |
|
| 1350 | + @classmethod |
| 1351 | + def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1352 | + """ |
| 1353 | + Returns the minimum base fee per blob gas for Prague. |
| 1354 | + """ |
| 1355 | + return 2**25 |
| 1356 | + |
| 1357 | + @classmethod |
| 1358 | + def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1359 | + """ |
| 1360 | + Returns the blob base fee update fraction for Prague. |
| 1361 | + """ |
| 1362 | + return 5007716 |
| 1363 | + |
| 1364 | + @classmethod |
| 1365 | + def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1366 | + """ |
| 1367 | + Target blob count of 6 for Prague. |
| 1368 | + """ |
| 1369 | + return 6 |
| 1370 | + |
| 1371 | + @classmethod |
| 1372 | + def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1373 | + """ |
| 1374 | + Max blob count of 9 for Prague. |
| 1375 | + """ |
| 1376 | + return 9 |
| 1377 | + |
1259 | 1378 | @classmethod |
1260 | 1379 | def pre_allocation_blockchain(cls) -> Mapping: |
1261 | 1380 | """ |
@@ -1319,7 +1438,7 @@ def pre_allocation_blockchain(cls) -> Mapping: |
1319 | 1438 | return new_allocation | super(Prague, cls).pre_allocation_blockchain() # type: ignore |
1320 | 1439 |
|
1321 | 1440 | @classmethod |
1322 | | - def header_requests_required(cls, block_number: int, timestamp: int) -> bool: |
| 1441 | + def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: |
1323 | 1442 | """ |
1324 | 1443 | Prague requires that the execution layer header contains the beacon |
1325 | 1444 | chain requests hash. |
|
0 commit comments