github.com/ethereum/go-ethereum@v1.14.3/consensus/misc/eip4844/eip4844.go (about)

     1  // Copyright 2023 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package eip4844
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/params"
    26  )
    27  
    28  var (
    29  	minBlobGasPrice            = big.NewInt(params.BlobTxMinBlobGasprice)
    30  	blobGaspriceUpdateFraction = big.NewInt(params.BlobTxBlobGaspriceUpdateFraction)
    31  )
    32  
    33  // VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
    34  // if the current block contains no transactions, the excessBlobGas is updated
    35  // accordingly.
    36  func VerifyEIP4844Header(parent, header *types.Header) error {
    37  	// Verify the header is not malformed
    38  	if header.ExcessBlobGas == nil {
    39  		return errors.New("header is missing excessBlobGas")
    40  	}
    41  	if header.BlobGasUsed == nil {
    42  		return errors.New("header is missing blobGasUsed")
    43  	}
    44  	// Verify that the blob gas used remains within reasonable limits.
    45  	if *header.BlobGasUsed > params.MaxBlobGasPerBlock {
    46  		return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock)
    47  	}
    48  	if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
    49  		return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
    50  	}
    51  	// Verify the excessBlobGas is correct based on the parent header
    52  	var (
    53  		parentExcessBlobGas uint64
    54  		parentBlobGasUsed   uint64
    55  	)
    56  	if parent.ExcessBlobGas != nil {
    57  		parentExcessBlobGas = *parent.ExcessBlobGas
    58  		parentBlobGasUsed = *parent.BlobGasUsed
    59  	}
    60  	expectedExcessBlobGas := CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
    61  	if *header.ExcessBlobGas != expectedExcessBlobGas {
    62  		return fmt.Errorf("invalid excessBlobGas: have %d, want %d, parent excessBlobGas %d, parent blobDataUsed %d",
    63  			*header.ExcessBlobGas, expectedExcessBlobGas, parentExcessBlobGas, parentBlobGasUsed)
    64  	}
    65  	return nil
    66  }
    67  
    68  // CalcExcessBlobGas calculates the excess blob gas after applying the set of
    69  // blobs on top of the excess blob gas.
    70  func CalcExcessBlobGas(parentExcessBlobGas uint64, parentBlobGasUsed uint64) uint64 {
    71  	excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
    72  	if excessBlobGas < params.BlobTxTargetBlobGasPerBlock {
    73  		return 0
    74  	}
    75  	return excessBlobGas - params.BlobTxTargetBlobGasPerBlock
    76  }
    77  
    78  // CalcBlobFee calculates the blobfee from the header's excess blob gas field.
    79  func CalcBlobFee(excessBlobGas uint64) *big.Int {
    80  	return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(excessBlobGas), blobGaspriceUpdateFraction)
    81  }
    82  
    83  // fakeExponential approximates factor * e ** (numerator / denominator) using
    84  // Taylor expansion.
    85  func fakeExponential(factor, numerator, denominator *big.Int) *big.Int {
    86  	var (
    87  		output = new(big.Int)
    88  		accum  = new(big.Int).Mul(factor, denominator)
    89  	)
    90  	for i := 1; accum.Sign() > 0; i++ {
    91  		output.Add(output, accum)
    92  
    93  		accum.Mul(accum, numerator)
    94  		accum.Div(accum, denominator)
    95  		accum.Div(accum, big.NewInt(int64(i)))
    96  	}
    97  	return output.Div(output, denominator)
    98  }