Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/ethereum/prague/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,16 @@
from .vm import Message
from .vm.eoa_delegation import is_valid_delegation
from .vm.gas import (
calculate_base_fee_per_gas,
)
from .vm.interpreter import MessageCallOutput, process_message_call
from .gas_pricing import (
calculate_blob_gas_price,
calculate_data_fee,
calculate_excess_blob_gas,
calculate_total_blob_gas,
MAX_BLOB_GAS_PER_BLOCK,
)
from .vm.interpreter import MessageCallOutput, process_message_call

BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8)
ELASTICITY_MULTIPLIER = Uint(2)
Expand All @@ -84,7 +88,6 @@
"0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"
)
SYSTEM_TRANSACTION_GAS = Uint(30000000)
MAX_BLOB_GAS_PER_BLOCK = U64(1179648)
VERSIONED_HASH_VERSION_KZG = b"\x01"

WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address(
Expand Down
118 changes: 118 additions & 0 deletions src/ethereum/prague/gas_pricing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
"""
Gas Pricing Calculations
^^^^^^^^^^^^^^^^^^^^^^^

.. contents:: Table of Contents
:backlinks: none
:local:

Introduction
------------

Gas pricing calculations for blocks and transactions.
"""

from ethereum_types.numeric import U64, Uint

from .blocks import Header
from .transactions import BlobTransaction, Transaction
from .utils.numeric import taylor_exponential

# Blob gas constants
TARGET_BLOB_GAS_PER_BLOCK = U64(786432)
GAS_PER_BLOB = U64(2**17)
MIN_BLOB_GASPRICE = Uint(1)
BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716)


def calculate_excess_blob_gas(parent_header: Header) -> U64:
"""
Calculated the excess blob gas for the current block based
on the gas used in the parent block.

Parameters
----------
parent_header :
The parent block of the current block.

Returns
-------
excess_blob_gas: `ethereum.base_types.U64`
The excess blob gas for the current block.
"""
# At the fork block, these are defined as zero.
excess_blob_gas = U64(0)
blob_gas_used = U64(0)

if isinstance(parent_header, Header):
# After the fork block, read them from the parent header.
excess_blob_gas = parent_header.excess_blob_gas
blob_gas_used = parent_header.blob_gas_used

parent_blob_gas = excess_blob_gas + blob_gas_used
if parent_blob_gas < TARGET_BLOB_GAS_PER_BLOCK:
return U64(0)
else:
return parent_blob_gas - TARGET_BLOB_GAS_PER_BLOCK


def calculate_total_blob_gas(tx: Transaction) -> U64:
"""
Calculate the total blob gas for a transaction.

Parameters
----------
tx :
The transaction for which the blob gas is to be calculated.

Returns
-------
total_blob_gas: `ethereum.base_types.Uint`
The total blob gas for the transaction.
"""
if isinstance(tx, BlobTransaction):
return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes))
else:
return U64(0)


def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint:
"""
Calculate the blob gasprice for a block.

Parameters
----------
excess_blob_gas :
The excess blob gas for the block.

Returns
-------
blob_gasprice: `Uint`
The blob gasprice.
"""
return taylor_exponential(
MIN_BLOB_GASPRICE,
Uint(excess_blob_gas),
BLOB_BASE_FEE_UPDATE_FRACTION,
)


def calculate_data_fee(excess_blob_gas: U64, tx: Transaction) -> Uint:
"""
Calculate the blob data fee for a transaction.

Parameters
----------
excess_blob_gas :
The excess_blob_gas for the execution.
tx :
The transaction for which the blob data fee is to be calculated.

Returns
-------
data_fee: `Uint`
The blob data fee.
"""
return Uint(calculate_total_blob_gas(tx)) * calculate_blob_gas_price(
excess_blob_gas
)
116 changes: 8 additions & 108 deletions src/ethereum/prague/vm/gas.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from ethereum.utils.numeric import ceil32, taylor_exponential

from ..blocks import Header
from ..transactions import BlobTransaction, Transaction
from ..transactions import Transaction
from . import Evm
from .exceptions import OutOfGasError

Expand Down Expand Up @@ -68,11 +68,6 @@
GAS_BLOBHASH_OPCODE = Uint(3)
GAS_POINT_EVALUATION = Uint(50000)

TARGET_BLOB_GAS_PER_BLOCK = U64(786432)
GAS_PER_BLOB = U64(2**17)
MIN_BLOB_GASPRICE = Uint(1)
BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716)

GAS_BLS_G1_ADD = Uint(375)
GAS_BLS_G1_MUL = Uint(12000)
GAS_BLS_G1_MAP = Uint(5500)
Expand Down Expand Up @@ -258,113 +253,18 @@ def max_message_call_gas(gas: Uint) -> Uint:
return gas - (gas // Uint(64))


def init_code_cost(init_code_length: Uint) -> Uint:
"""
Calculates the gas to be charged for the init code in CREAT*
opcodes as well as create transactions.

Parameters
----------
init_code_length :
The length of the init code provided to the opcode
or a create transaction

Returns
-------
init_code_gas: `ethereum.base_types.Uint`
The gas to be charged for the init code.
"""
return GAS_INIT_CODE_WORD_COST * ceil32(init_code_length) // Uint(32)


def calculate_excess_blob_gas(parent_header: Header) -> U64:
"""
Calculated the excess blob gas for the current block based
on the gas used in the parent block.

Parameters
----------
parent_header :
The parent block of the current block.

Returns
-------
excess_blob_gas: `ethereum.base_types.U64`
The excess blob gas for the current block.
"""
# At the fork block, these are defined as zero.
excess_blob_gas = U64(0)
blob_gas_used = U64(0)

if isinstance(parent_header, Header):
# After the fork block, read them from the parent header.
excess_blob_gas = parent_header.excess_blob_gas
blob_gas_used = parent_header.blob_gas_used

parent_blob_gas = excess_blob_gas + blob_gas_used
if parent_blob_gas < TARGET_BLOB_GAS_PER_BLOCK:
return U64(0)
else:
return parent_blob_gas - TARGET_BLOB_GAS_PER_BLOCK


def calculate_total_blob_gas(tx: Transaction) -> U64:
"""
Calculate the total blob gas for a transaction.

Parameters
----------
tx :
The transaction for which the blob gas is to be calculated.

Returns
-------
total_blob_gas: `ethereum.base_types.Uint`
The total blob gas for the transaction.
"""
if isinstance(tx, BlobTransaction):
return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes))
else:
return U64(0)


def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint:
"""
Calculate the blob gasprice for a block.

Parameters
----------
excess_blob_gas :
The excess blob gas for the block.

Returns
-------
blob_gasprice: `Uint`
The blob gasprice.
"""
return taylor_exponential(
MIN_BLOB_GASPRICE,
Uint(excess_blob_gas),
BLOB_BASE_FEE_UPDATE_FRACTION,
)


def calculate_data_fee(excess_blob_gas: U64, tx: Transaction) -> Uint:
def init_code_cost(length: Uint) -> Uint:
"""
Calculate the blob data fee for a transaction.
Calculate the gas cost for init code.

Parameters
----------
excess_blob_gas :
The excess_blob_gas for the execution.
tx :
The transaction for which the blob data fee is to be calculated.
length :
The length of the init code.

Returns
-------
data_fee: `Uint`
The blob data fee.
gas_cost : `ethereum.base_types.Uint`
The gas cost for the init code.
"""
return Uint(calculate_total_blob_gas(tx)) * calculate_blob_gas_price(
excess_blob_gas
)
return length * GAS_INIT_CODE_WORD_COST
4 changes: 2 additions & 2 deletions src/ethereum/prague/vm/instructions/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from ...state import get_account
from ...utils.address import to_address
from ...vm.memory import buffer_read, memory_write
from ...gas_pricing import calculate_blob_gas_price
from .. import Evm
from ..exceptions import OutOfBoundsRead
from ..gas import (
Expand All @@ -33,7 +34,6 @@
GAS_RETURN_DATA_COPY,
GAS_VERY_LOW,
GAS_WARM_ACCESS,
calculate_blob_gas_price,
calculate_gas_extend_memory,
charge_gas,
)
Expand Down Expand Up @@ -460,7 +460,7 @@ def returndatacopy(evm: Evm) -> None:

def extcodehash(evm: Evm) -> None:
"""
Returns the keccak256 hash of a contracts bytecode
Returns the keccak256 hash of a contract's bytecode
Parameters
----------
evm :
Expand Down
Loading