From 5bad4561c1df06f2e5486416c684686e7f5efab8 Mon Sep 17 00:00:00 2001 From: Petar Ivanov <29689712+dartdart26@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:43:21 +0300 Subject: [PATCH] Add fractional CALLDATA gas cost (#75) Since an FHE-based chain could require relatively big FHE ciphertexts to be passed as transaction inputs, reduce the CALLDATA gas cost to `1 / TxFheDataFractionalGas` per byte. Currently, it costs 1/4 gas per byte. It doesn't matter if a byte is zero or non-zero, the cost is the same. The `TxFheDataFractionalGas` constant could be changed in the future as we gain more usage patterns from live networks. --- core/state_transition.go | 46 ++++++++++++--------------------------- params/protocol_params.go | 1 + 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index 3b5f81b16632..131a91082d2c 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -18,7 +18,6 @@ package core import ( "fmt" - "math" "math/big" "github.com/ethereum/go-ethereum/common" @@ -42,8 +41,10 @@ The state transitioning model does all the necessary work to work out a valid ne 3) Create a new state object if the recipient is \0*32 4) Value transfer == If contract creation == - 4a) Attempt to run transaction data - 4b) If valid, use result as code for the new state object + + 4a) Attempt to run transaction data + 4b) If valid, use result as code for the new state object + == end == 5) Run Script section 6) Derive new state root @@ -125,28 +126,9 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b } // Bump the required gas by the amount of transactional data if len(data) > 0 { - // Zero and non-zero bytes are priced differently - var nz uint64 - for _, byt := range data { - if byt != 0 { - nz++ - } - } - // Make sure we don't exceed uint64 for all data combinations - nonZeroGas := params.TxDataNonZeroGasFrontier - if isEIP2028 { - nonZeroGas = params.TxDataNonZeroGasEIP2028 - } - if (math.MaxUint64-gas)/nonZeroGas < nz { - return 0, ErrGasUintOverflow - } - gas += nz * nonZeroGas - - z := uint64(len(data)) - nz - if (math.MaxUint64-gas)/params.TxDataZeroGas < z { - return 0, ErrGasUintOverflow - } - gas += z * params.TxDataZeroGas + // We ignore EIP 20228 here. Rationale is that current gas cost calculation is very different. + // Please consult EIP 2028 for more information, especially if the current gas calculation is problematic. + gas += uint64(len(data)) / params.TxFheDataFractionalGas } if accessList != nil { gas += uint64(len(accessList)) * params.TxAccessListAddressGas @@ -262,13 +244,13 @@ func (st *StateTransition) preCheck() error { // TransitionDb will transition the state by applying the current message and // returning the evm execution result with following fields. // -// - used gas: -// total gas used (including gas being refunded) -// - returndata: -// the returned data from evm -// - concrete execution error: -// various **EVM** error which aborts the execution, -// e.g. ErrOutOfGas, ErrExecutionReverted +// - used gas: +// total gas used (including gas being refunded) +// - returndata: +// the returned data from evm +// - concrete execution error: +// various **EVM** error which aborts the execution, +// e.g. ErrOutOfGas, ErrExecutionReverted // // However if any consensus issue encountered, return the error directly with // nil evm execution result. diff --git a/params/protocol_params.go b/params/protocol_params.go index 5f154597a7fa..0637e570c99f 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -86,6 +86,7 @@ const ( TxDataNonZeroGasFrontier uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. TxDataNonZeroGasEIP2028 uint64 = 16 // Per byte of non zero data attached to a transaction after EIP 2028 (part in Istanbul) + TxFheDataFractionalGas uint64 = 4 // A byte of data attached to a transaction has fractional cost: 1 / TxFheDataFractionGas (part of an FHE-based chain) TxAccessListAddressGas uint64 = 2400 // Per address specified in EIP 2930 access list TxAccessListStorageKeyGas uint64 = 1900 // Per storage key specified in EIP 2930 access list