core: started implementing eip-7623

pull/29040/head
Marius van der Wijden 9 months ago
parent d71831255d
commit 5a06d9204a
  1. 2
      cmd/evm/internal/t8ntool/transaction.go
  2. 2
      core/bench_test.go
  3. 31
      core/state_transition.go
  4. 2
      core/txpool/validation.go
  5. 24
      params/protocol_params.go
  6. 2
      tests/transaction_test_util.go

@ -134,7 +134,7 @@ func Transaction(ctx *cli.Context) error {
} }
// Check intrinsic gas // Check intrinsic gas
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil,
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int), 0)); err != nil { chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int), 0), false); err != nil {
r.Error = err r.Error = err
results = append(results, r) results = append(results, r)
continue continue

@ -83,7 +83,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) { return func(i int, gen *BlockGen) {
toaddr := common.Address{} toaddr := common.Address{}
data := make([]byte, nbytes) data := make([]byte, nbytes)
gas, _ := IntrinsicGas(data, nil, false, false, false, false) gas, _ := IntrinsicGas(data, nil, false, false, false, false, false)
signer := gen.Signer() signer := gen.Signer()
gasPrice := big.NewInt(0) gasPrice := big.NewInt(0)
if gen.header.BaseFee != nil { if gen.header.BaseFee != nil {

@ -68,7 +68,7 @@ func (result *ExecutionResult) Revert() []byte {
} }
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data. // IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation, isHomestead, isEIP2028, isEIP3860 bool) (uint64, error) { func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation, isHomestead, isEIP2028, isEIP3860, isEIP7623 bool) (uint64, error) {
// Set the starting gas for the raw transaction // Set the starting gas for the raw transaction
var gas uint64 var gas uint64
if isContractCreation && isHomestead { if isContractCreation && isHomestead {
@ -79,6 +79,15 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation,
dataLen := uint64(len(data)) dataLen := uint64(len(data))
// Bump the required gas by the amount of transactional data // Bump the required gas by the amount of transactional data
if dataLen > 0 { if dataLen > 0 {
// Charge for the contract creation
if isContractCreation && isEIP3860 {
lenWords := toWordSize(dataLen)
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords {
return 0, ErrGasUintOverflow
}
gas += lenWords * params.InitCodeWordGas
}
// Zero and non-zero bytes are priced differently // Zero and non-zero bytes are priced differently
var nz uint64 var nz uint64
for _, byt := range data { for _, byt := range data {
@ -86,6 +95,7 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation,
nz++ nz++
} }
} }
var gasForData uint64
// Make sure we don't exceed uint64 for all data combinations // Make sure we don't exceed uint64 for all data combinations
nonZeroGas := params.TxDataNonZeroGasFrontier nonZeroGas := params.TxDataNonZeroGasFrontier
if isEIP2028 { if isEIP2028 {
@ -94,21 +104,24 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation,
if (math.MaxUint64-gas)/nonZeroGas < nz { if (math.MaxUint64-gas)/nonZeroGas < nz {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
gas += nz * nonZeroGas gasForData += nz * nonZeroGas
z := dataLen - nz z := dataLen - nz
if (math.MaxUint64-gas)/params.TxDataZeroGas < z { if (math.MaxUint64-gas-gasForData)/params.TxDataZeroGas < z {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
gas += z * params.TxDataZeroGas gasForData += z * params.TxDataZeroGas
if isContractCreation && isEIP3860 { if isEIP7623 {
lenWords := toWordSize(dataLen) tokens := z + nz*params.TokenPerNonZeroByte7623
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords { if (math.MaxUint64-gas-gasForData)/params.CostFloorPerToken7623 < tokens {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
gas += lenWords * params.InitCodeWordGas if floor := params.CostFloorPerToken7623 * tokens; gasForData < floor {
gasForData = floor
}
} }
gas += gasForData
} }
if accessList != nil { if accessList != nil {
gas += uint64(len(accessList)) * params.TxAccessListAddressGas gas += uint64(len(accessList)) * params.TxAccessListAddressGas
@ -400,7 +413,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
) )
// Check clauses 4-5, subtract intrinsic gas if everything is correct // Check clauses 4-5, subtract intrinsic gas if everything is correct
gas, err := IntrinsicGas(msg.Data, msg.AccessList, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) gas, err := IntrinsicGas(msg.Data, msg.AccessList, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -103,7 +103,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
} }
// Ensure the transaction has more gas than the bare minimum needed to cover // Ensure the transaction has more gas than the bare minimum needed to cover
// the transaction metadata // the transaction metadata
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, opts.Config.IsIstanbul(head.Number), opts.Config.IsShanghai(head.Number, head.Time)) intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, opts.Config.IsIstanbul(head.Number), opts.Config.IsShanghai(head.Number, head.Time), false)
if err != nil { if err != nil {
return err return err
} }

@ -28,17 +28,19 @@ const (
MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit (2^63-1). MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit (2^63-1).
GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block.
MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction.
SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added. SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero. CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero.
CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior. CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior.
TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions. TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions. TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation. TokenPerNonZeroByte7623 uint64 = 4 // Token cost per non-zero byte as specified by EIP-7623.
LogDataGas uint64 = 8 // Per byte in a LOG* operation's data. CostFloorPerToken7623 uint64 = 17 // Cost floor per byte of data as specified by EIP-7623.
CallStipend uint64 = 2300 // Free gas given at beginning of call. QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation.
LogDataGas uint64 = 8 // Per byte in a LOG* operation's data.
CallStipend uint64 = 2300 // Free gas given at beginning of call.
Keccak256Gas uint64 = 30 // Once per KECCAK256 operation. Keccak256Gas uint64 = 30 // Once per KECCAK256 operation.
Keccak256WordGas uint64 = 6 // Once per word of the KECCAK256 operation's data. Keccak256WordGas uint64 = 6 // Once per word of the KECCAK256 operation's data.

@ -59,7 +59,7 @@ func (tt *TransactionTest) Run(config *params.ChainConfig) error {
return nil, nil, err return nil, nil, err
} }
// Intrinsic gas // Intrinsic gas
requiredGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, isHomestead, isIstanbul, false) requiredGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, isHomestead, isIstanbul, false, false)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

Loading…
Cancel
Save