|
16 | 16 |
|
17 | 17 | from ..base_fork import ( |
18 | 18 | BaseFork, |
| 19 | + BlobGasPriceCalculator, |
19 | 20 | CalldataGasCalculator, |
| 21 | + ExcessBlobGasCalculator, |
20 | 22 | MemoryExpansionGasCalculator, |
21 | 23 | TransactionIntrinsicCostCalculator, |
22 | 24 | ) |
23 | 25 | from ..gas_costs import GasCosts |
| 26 | +from .helpers import ceiling_division, fake_exponential |
24 | 27 |
|
25 | 28 | CURRENT_FILE = Path(realpath(__file__)) |
26 | 29 | CURRENT_FOLDER = CURRENT_FILE.parent |
27 | 30 |
|
28 | 31 |
|
29 | | -def ceiling_division(a: int, b: int) -> int: |
30 | | - """ |
31 | | - Calculates the ceil without using floating point. |
32 | | - Used by many of the EVM's formulas |
33 | | - """ |
34 | | - return -(a // -b) |
35 | | - |
36 | | - |
37 | 32 | # All forks must be listed here !!! in the order they were introduced !!! |
38 | 33 | class Frontier(BaseFork, solc_name="homestead"): |
39 | 34 | """ |
@@ -228,28 +223,60 @@ def fn( |
228 | 223 | return fn |
229 | 224 |
|
230 | 225 | @classmethod |
231 | | - def blob_gas_per_blob(cls, block_number: int, timestamp: int) -> int: |
| 226 | + def blob_gas_price_calculator( |
| 227 | + cls, block_number: int = 0, timestamp: int = 0 |
| 228 | + ) -> BlobGasPriceCalculator: |
232 | 229 | """ |
233 | | - Returns the amount of blob gas used per blob for a given fork. |
| 230 | + Returns a callable that calculates the blob gas price at a given fork. |
234 | 231 | """ |
235 | | - return 0 |
| 232 | + raise NotImplementedError("Blob gas price calculator is not supported in Frontier") |
236 | 233 |
|
237 | 234 | @classmethod |
238 | | - def target_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 235 | + def excess_blob_gas_calculator( |
| 236 | + cls, block_number: int = 0, timestamp: int = 0 |
| 237 | + ) -> ExcessBlobGasCalculator: |
239 | 238 | """ |
240 | | - Returns the target number of blobs per block for a given fork. |
| 239 | + Returns a callable that calculates the excess blob gas for a block at a given fork. |
241 | 240 | """ |
242 | | - return 0 |
| 241 | + raise NotImplementedError("Excess blob gas calculator is not supported in Frontier") |
243 | 242 |
|
244 | 243 | @classmethod |
245 | | - def max_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 244 | + def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: |
246 | 245 | """ |
247 | | - Returns the max number of blobs per block for a given fork. |
| 246 | + Returns the amount of blob gas used per blob at a given fork. |
248 | 247 | """ |
249 | | - return 0 |
| 248 | + raise NotImplementedError("Base fee per blob gas is not supported in Frontier") |
| 249 | + |
| 250 | + @classmethod |
| 251 | + def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 252 | + """ |
| 253 | + Returns the blob base fee update fraction at a given fork. |
| 254 | + """ |
| 255 | + raise NotImplementedError("Blob base fee update fraction is not supported in Frontier") |
| 256 | + |
| 257 | + @classmethod |
| 258 | + def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 259 | + """ |
| 260 | + Returns the amount of blob gas used per blob at a given fork. |
| 261 | + """ |
| 262 | + raise NotImplementedError("Blob gas per blob is not supported in Frontier") |
| 263 | + |
| 264 | + @classmethod |
| 265 | + def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 266 | + """ |
| 267 | + Returns the target number of blobs per block at a given fork. |
| 268 | + """ |
| 269 | + raise NotImplementedError("Target blobs per block is not supported in Frontier") |
250 | 270 |
|
251 | 271 | @classmethod |
252 | | - def header_requests_required(cls, block_number: int, timestamp: int) -> bool: |
| 272 | + def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 273 | + """ |
| 274 | + Returns the max number of blobs per block at a given fork. |
| 275 | + """ |
| 276 | + raise NotImplementedError("Max blobs per block is not supported in Frontier") |
| 277 | + |
| 278 | + @classmethod |
| 279 | + def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: |
253 | 280 | """ |
254 | 281 | At genesis, header must not contain beacon chain requests. |
255 | 282 | """ |
@@ -992,21 +1019,85 @@ def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) |
992 | 1019 | return True |
993 | 1020 |
|
994 | 1021 | @classmethod |
995 | | - def blob_gas_per_blob(cls, block_number: int, timestamp: int) -> int: |
| 1022 | + def blob_gas_price_calculator( |
| 1023 | + cls, block_number: int = 0, timestamp: int = 0 |
| 1024 | + ) -> BlobGasPriceCalculator: |
| 1025 | + """ |
| 1026 | + Returns a callable that calculates the blob gas price at Cancun. |
| 1027 | + """ |
| 1028 | + min_base_fee_per_blob_gas = cls.min_base_fee_per_blob_gas(block_number, timestamp) |
| 1029 | + blob_base_fee_update_fraction = cls.blob_base_fee_update_fraction(block_number, timestamp) |
| 1030 | + |
| 1031 | + def fn(*, excess_blob_gas) -> int: |
| 1032 | + return fake_exponential( |
| 1033 | + min_base_fee_per_blob_gas, |
| 1034 | + excess_blob_gas, |
| 1035 | + blob_base_fee_update_fraction, |
| 1036 | + ) |
| 1037 | + |
| 1038 | + return fn |
| 1039 | + |
| 1040 | + @classmethod |
| 1041 | + def excess_blob_gas_calculator( |
| 1042 | + cls, block_number: int = 0, timestamp: int = 0 |
| 1043 | + ) -> ExcessBlobGasCalculator: |
| 1044 | + """ |
| 1045 | + Returns a callable that calculates the excess blob gas for a block at Cancun. |
| 1046 | + """ |
| 1047 | + target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp) |
| 1048 | + blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp) |
| 1049 | + target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob |
| 1050 | + |
| 1051 | + def fn( |
| 1052 | + *, |
| 1053 | + parent_excess_blob_gas: int | None = None, |
| 1054 | + parent_excess_blobs: int | None = None, |
| 1055 | + parent_blob_gas_used: int | None = None, |
| 1056 | + parent_blob_count: int | None = None, |
| 1057 | + ) -> int: |
| 1058 | + if parent_excess_blob_gas is None: |
| 1059 | + assert parent_excess_blobs is not None, "Parent excess blobs are required" |
| 1060 | + parent_excess_blob_gas = parent_excess_blobs * blob_gas_per_blob |
| 1061 | + if parent_blob_gas_used is None: |
| 1062 | + assert parent_blob_count is not None, "Parent blob count is required" |
| 1063 | + parent_blob_gas_used = parent_blob_count * blob_gas_per_blob |
| 1064 | + if parent_excess_blob_gas + parent_blob_gas_used < target_blob_gas_per_block: |
| 1065 | + return 0 |
| 1066 | + else: |
| 1067 | + return parent_excess_blob_gas + parent_blob_gas_used - target_blob_gas_per_block |
| 1068 | + |
| 1069 | + return fn |
| 1070 | + |
| 1071 | + @classmethod |
| 1072 | + def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1073 | + """ |
| 1074 | + Returns the minimum base fee per blob gas for Cancun. |
| 1075 | + """ |
| 1076 | + return 1 |
| 1077 | + |
| 1078 | + @classmethod |
| 1079 | + def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1080 | + """ |
| 1081 | + Returns the blob base fee update fraction for Cancun. |
| 1082 | + """ |
| 1083 | + return 3338477 |
| 1084 | + |
| 1085 | + @classmethod |
| 1086 | + def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int: |
996 | 1087 | """ |
997 | 1088 | Blobs are enabled starting from Cancun. |
998 | 1089 | """ |
999 | 1090 | return 2**17 |
1000 | 1091 |
|
1001 | 1092 | @classmethod |
1002 | | - def target_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 1093 | + def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
1003 | 1094 | """ |
1004 | 1095 | Blobs are enabled starting from Cancun, with a static target of 3 blobs. |
1005 | 1096 | """ |
1006 | 1097 | return 3 |
1007 | 1098 |
|
1008 | 1099 | @classmethod |
1009 | | - def max_blobs_per_block(cls, block_number: int, timestamp: int) -> int: |
| 1100 | + def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
1010 | 1101 | """ |
1011 | 1102 | Blobs are enabled starting from Cancun, with a static max of 6 blobs. |
1012 | 1103 | """ |
@@ -1178,6 +1269,34 @@ def fn( |
1178 | 1269 |
|
1179 | 1270 | return fn |
1180 | 1271 |
|
| 1272 | + @classmethod |
| 1273 | + def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1274 | + """ |
| 1275 | + Returns the minimum base fee per blob gas for Prague. |
| 1276 | + """ |
| 1277 | + return 2**25 |
| 1278 | + |
| 1279 | + @classmethod |
| 1280 | + def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1281 | + """ |
| 1282 | + Returns the blob base fee update fraction for Prague. |
| 1283 | + """ |
| 1284 | + return 5007716 |
| 1285 | + |
| 1286 | + @classmethod |
| 1287 | + def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1288 | + """ |
| 1289 | + Target blob count of 6 for Prague. |
| 1290 | + """ |
| 1291 | + return 6 |
| 1292 | + |
| 1293 | + @classmethod |
| 1294 | + def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: |
| 1295 | + """ |
| 1296 | + Max blob count of 9 for Prague. |
| 1297 | + """ |
| 1298 | + return 9 |
| 1299 | + |
1181 | 1300 | @classmethod |
1182 | 1301 | def pre_allocation_blockchain(cls) -> Mapping: |
1183 | 1302 | """ |
@@ -1241,7 +1360,7 @@ def pre_allocation_blockchain(cls) -> Mapping: |
1241 | 1360 | return new_allocation | super(Prague, cls).pre_allocation_blockchain() # type: ignore |
1242 | 1361 |
|
1243 | 1362 | @classmethod |
1244 | | - def header_requests_required(cls, block_number: int, timestamp: int) -> bool: |
| 1363 | + def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: |
1245 | 1364 | """ |
1246 | 1365 | Prague requires that the execution layer header contains the beacon |
1247 | 1366 | chain requests hash. |
|
0 commit comments