eip-4844: small additions and modified gaspool (#7190)

This PR contains very small EIP-4844 additions. GasPool is modified and
now it is a struct with 2 fields "gas" and "dataGas" (blobs are priced
in dataGas). ExcessDataGas block header field added. ExcessDataGas
needed to compute the data gas price. EIP-4844 helper functions are
added as well.
This commit is contained in:
racytech 2023-03-28 03:39:15 +06:00 committed by GitHub
parent 540af96ef7
commit 70bc7f7a25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 406 additions and 54 deletions

View File

@ -40,6 +40,7 @@ type ExecutionPayload struct {
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
ExcessDataGas *hexutil.Big `json:"excessDataGas"`
}
// GetPayloadV2Response represents the response of the getPayloadV2 method
@ -248,6 +249,17 @@ func (e *EngineImpl) newPayload(version uint32, ctx context.Context, payload *Ex
ep.Version = 2
ep.Withdrawals = privateapi.ConvertWithdrawalsToRpc(payload.Withdrawals)
}
if version >= 3 && payload.ExcessDataGas != nil {
ep.Version = 3
var excessDataGas *uint256.Int
var overflow bool
excessDataGas, overflow = uint256.FromBig((*big.Int)(payload.ExcessDataGas))
if overflow {
log.Warn("NewPayload ExcessDataGas overflow")
return nil, fmt.Errorf("invalid request, excess data gas overflow")
}
ep.ExcessDataGas = gointerfaces.ConvertUint256IntToH256(excessDataGas)
}
res, err := e.api.EngineNewPayload(ctx, ep)
if err != nil {
@ -286,7 +298,10 @@ func convertPayloadFromRpc(payload *types2.ExecutionPayload) *ExecutionPayload {
if payload.Version >= 2 {
res.Withdrawals = privateapi.ConvertWithdrawalsFromRpc(payload.Withdrawals)
}
if payload.Version >= 3 {
edg := gointerfaces.ConvertH256ToUint256Int(payload.ExcessDataGas).ToBig()
res.ExcessDataGas = (*hexutil.Big)(edg)
}
return res
}

80
consensus/misc/eip4844.go Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package misc
import (
"fmt"
"math/big"
"github.com/ledgerwatch/erigon-lib/chain"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/params"
)
// CalcExcessDataGas implements calc_excess_data_gas from EIP-4844
func CalcExcessDataGas(parentExcessDataGas *big.Int, newBlobs int) *big.Int {
excessDataGas := new(big.Int)
if parentExcessDataGas != nil {
excessDataGas.Set(parentExcessDataGas)
}
consumedGas := big.NewInt(params.DataGasPerBlob)
consumedGas.Mul(consumedGas, big.NewInt(int64(newBlobs)))
excessDataGas.Add(excessDataGas, consumedGas)
targetGas := big.NewInt(params.TargetDataGasPerBlock)
if excessDataGas.Cmp(targetGas) < 0 {
return new(big.Int)
}
return new(big.Int).Set(excessDataGas.Sub(excessDataGas, targetGas))
}
// FakeExponential approximates factor * e ** (num / denom) using a taylor expansion
// as described in the EIP-4844 spec.
func FakeExponential(factor, num, denom *big.Int) *big.Int {
output := new(big.Int)
numAccum := new(big.Int).Mul(factor, denom)
for i := 1; numAccum.Sign() > 0; i++ {
output.Add(output, numAccum)
numAccum.Mul(numAccum, num)
iBig := big.NewInt(int64(i))
numAccum.Div(numAccum, iBig.Mul(iBig, denom))
}
return output.Div(output, denom)
}
// CountBlobs returns the number of blob transactions in txs
func CountBlobs(txs []types.Transaction) int {
var count int
for _, tx := range txs {
count += len(tx.GetDataHashes())
}
return count
}
// VerifyEip4844Header verifies that the header is not malformed
func VerifyEip4844Header(config *chain.Config, parent, header *types.Header) error {
if header.ExcessDataGas == nil {
return fmt.Errorf("header is missing excessDataGas")
}
return nil
}
// GetDataGasPrice implements get_data_gas_price from EIP-4844
func GetDataGasPrice(excessDataGas *big.Int) *big.Int {
return FakeExponential(big.NewInt(params.MinDataGasPrice), excessDataGas, big.NewInt(params.DataGasPriceUpdateFraction))
}

View File

@ -0,0 +1,89 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package misc
import (
"math/big"
"testing"
"github.com/ledgerwatch/erigon/params"
)
func TestFakeExponential(t *testing.T) {
var tests = []struct {
factor, num, denom int64
want int64
}{
// When num==0 the return value should always equal the value of factor
{1, 0, 1, 1},
{38493, 0, 1000, 38493},
{0, 1234, 2345, 0}, // should be 0
{1, 2, 1, 6}, // approximate 7.389
{1, 4, 2, 6},
{1, 3, 1, 16}, // approximate 20.09
{1, 6, 2, 18},
{1, 4, 1, 49}, // approximate 54.60
{1, 8, 2, 50},
{10, 8, 2, 542}, // approximate 540.598
{11, 8, 2, 596}, // approximate 600.58
{1, 5, 1, 136}, // approximate 148.4
{1, 5, 2, 11}, // approximate 12.18
{2, 5, 2, 23}, // approximate 24.36
}
for _, tt := range tests {
factor := big.NewInt(tt.factor)
num := big.NewInt(tt.num)
denom := big.NewInt(tt.denom)
result := FakeExponential(factor, num, denom)
//t.Logf("%v*e^(%v/%v): %v", factor, num, denom, result)
if tt.want != result.Int64() {
t.Errorf("got %v want %v", result, tt.want)
}
}
}
func TestCalcExcessDataGas(t *testing.T) {
var tests = []struct {
parentExcessDataGas int64
newBlobs int
want int64
}{
{0, 0, 0},
{0, 1, 0},
{0, params.TargetDataGasPerBlock / params.DataGasPerBlob, 0},
{0, (params.TargetDataGasPerBlock / params.DataGasPerBlob) + 1, params.DataGasPerBlob},
{100000, (params.TargetDataGasPerBlock / params.DataGasPerBlob) + 1, params.DataGasPerBlob + 100000},
{params.TargetDataGasPerBlock, 1, params.DataGasPerBlob},
{params.TargetDataGasPerBlock, 0, 0},
{params.TargetDataGasPerBlock, (params.TargetDataGasPerBlock / params.DataGasPerBlob), params.TargetDataGasPerBlock},
}
for _, tt := range tests {
parentExcessDataGas := big.NewInt(tt.parentExcessDataGas)
result := CalcExcessDataGas(parentExcessDataGas, tt.newBlobs)
if tt.want != result.Int64() {
t.Errorf("got %v want %v", result, tt.want)
}
}
// Test nil value for parentExcessDataGas
result := CalcExcessDataGas(nil, (params.TargetDataGasPerBlock/params.DataGasPerBlob)+1)
if result.Int64() != params.DataGasPerBlob {
t.Errorf("got %v want %v", result, params.DataGasPerBlob)
}
}

View File

@ -69,6 +69,10 @@ var (
// by a transaction is higher than what's left in the block.
ErrGasLimitReached = errors.New("gas limit reached")
// ErrDataGasLimitReached is returned by the gas pool if the amount of data gas required
// by a transaction is higher than what's left in the block.
ErrDataGasLimitReached = errors.New("data gas limit reached")
// ErrMaxInitCodeSizeExceeded is returned if creation transaction provides the init code bigger
// than init code size limit.
ErrMaxInitCodeSizeExceeded = errors.New("max initcode size exceeded")

View File

@ -23,36 +23,62 @@ import (
// GasPool tracks the amount of gas available during execution of the transactions
// in a block. The zero value is a pool with zero gas available.
type GasPool uint64
type GasPool struct {
gas, dataGas uint64
}
func (gp *GasPool) Reset(amount uint64) {
*gp = GasPool(amount)
gp.gas = amount
}
// AddGas makes gas available for execution.
func (gp *GasPool) AddGas(amount uint64) *GasPool {
if uint64(*gp) > math.MaxUint64-amount {
if gp.gas > math.MaxUint64-amount {
panic("gas pool pushed above uint64")
}
*(*uint64)(gp) += amount
gp.gas += amount
return gp
}
// SubGas deducts the given amount from the pool if enough gas is
// available and returns an error otherwise.
func (gp *GasPool) SubGas(amount uint64) error {
if uint64(*gp) < amount {
if gp.gas < amount {
return ErrGasLimitReached
}
*(*uint64)(gp) -= amount
gp.gas -= amount
return nil
}
// Gas returns the amount of gas remaining in the pool.
func (gp *GasPool) Gas() uint64 {
return uint64(*gp)
return gp.gas
}
// AddDataGas makes data gas available for execution.
func (gp *GasPool) AddDataGas(amount uint64) *GasPool {
if gp.dataGas > math.MaxUint64-amount {
panic("data gas pool pushed above uint64")
}
gp.dataGas += amount
return gp
}
// SubDataGas deducts the given amount from the pool if enough data gas is available and returns an
// error otherwise.
func (gp *GasPool) SubDataGas(amount uint64) error {
if gp.dataGas < amount {
return ErrDataGasLimitReached
}
gp.dataGas -= amount
return nil
}
// DataGas returns the amount of data gas remaining in the pool.
func (gp *GasPool) DataGas() uint64 {
return gp.dataGas
}
func (gp *GasPool) String() string {
return fmt.Sprintf("%d", *gp)
return fmt.Sprintf("gas: %d, data_gas: %d", gp.gas, gp.dataGas)
}

View File

@ -76,10 +76,11 @@ type Genesis struct {
// These fields are used for consensus tests. Please don't use them
// in actual genesis blocks.
Number uint64 `json:"number"`
GasUsed uint64 `json:"gasUsed"`
ParentHash libcommon.Hash `json:"parentHash"`
BaseFee *big.Int `json:"baseFeePerGas"`
Number uint64 `json:"number"`
GasUsed uint64 `json:"gasUsed"`
ParentHash libcommon.Hash `json:"parentHash"`
BaseFee *big.Int `json:"baseFeePerGas"`
ExcessDataGas *big.Int `json:"excessDataGas"`
}
// GenesisAlloc specifies the initial state that is part of the genesis block.
@ -120,15 +121,16 @@ type GenesisAccount struct {
// field type overrides for gencodec
type genesisSpecMarshaling struct {
Nonce math.HexOrDecimal64
Timestamp math.HexOrDecimal64
ExtraData hexutil.Bytes
GasLimit math.HexOrDecimal64
GasUsed math.HexOrDecimal64
Number math.HexOrDecimal64
Difficulty *math.HexOrDecimal256
BaseFee *math.HexOrDecimal256
Alloc map[common.UnprefixedAddress]GenesisAccount
Nonce math.HexOrDecimal64
Timestamp math.HexOrDecimal64
ExtraData hexutil.Bytes
GasLimit math.HexOrDecimal64
GasUsed math.HexOrDecimal64
Number math.HexOrDecimal64
Difficulty *math.HexOrDecimal256
BaseFee *math.HexOrDecimal256
ExcessDataGas *math.HexOrDecimal256
Alloc map[common.UnprefixedAddress]GenesisAccount
}
type genesisAccountMarshaling struct {
@ -335,19 +337,20 @@ func (g *Genesis) ToBlock(tmpDir string) (*types.Block, *state.IntraBlockState,
_ = g.Alloc //nil-check
head := &types.Header{
Number: new(big.Int).SetUint64(g.Number),
Nonce: types.EncodeNonce(g.Nonce),
Time: g.Timestamp,
ParentHash: g.ParentHash,
Extra: g.ExtraData,
GasLimit: g.GasLimit,
GasUsed: g.GasUsed,
Difficulty: g.Difficulty,
MixDigest: g.Mixhash,
Coinbase: g.Coinbase,
BaseFee: g.BaseFee,
AuRaStep: g.AuRaStep,
AuRaSeal: g.AuRaSeal,
Number: new(big.Int).SetUint64(g.Number),
Nonce: types.EncodeNonce(g.Nonce),
Time: g.Timestamp,
ParentHash: g.ParentHash,
Extra: g.ExtraData,
GasLimit: g.GasLimit,
GasUsed: g.GasUsed,
Difficulty: g.Difficulty,
MixDigest: g.Mixhash,
Coinbase: g.Coinbase,
BaseFee: g.BaseFee,
ExcessDataGas: g.ExcessDataGas,
AuRaStep: g.AuRaStep,
AuRaSeal: g.AuRaSeal,
}
if g.GasLimit == 0 {
head.GasLimit = params.GenesisGasLimit

View File

@ -96,6 +96,7 @@ type Header struct {
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
WithdrawalsHash *libcommon.Hash `json:"withdrawalsRoot"` // EIP-4895
ExcessDataGas *big.Int `json:"excessDataGas"` // EIP-4844
// The verkle proof is ignored in legacy headers
Verkle bool
@ -103,6 +104,17 @@ type Header struct {
VerkleKeyVals []verkle.KeyValuePair
}
// ParentExcessDataGas is a helper that returns the excess data gas value of the parent block. It
// returns nil if the parent header could not be fetched, or if the parent block's excess data gas
// is nil.
func (h *Header) ParentExcessDataGas(getHeader func(hash libcommon.Hash, number uint64) *Header) *big.Int {
p := getHeader(h.ParentHash, h.Number.Uint64())
if p != nil {
return p.ExcessDataGas
}
return nil
}
func bitsToBytes(bitLen int) (byteLen int) {
return (bitLen + 7) / 8
}
@ -158,6 +170,11 @@ func (h *Header) EncodingSize() int {
encodingSize += 33
}
if h.ExcessDataGas != nil {
encodingSize++
encodingSize += rlp.BigIntLenExcludingHead(h.ExcessDataGas)
}
if h.Verkle {
// Encoding of Verkle Proof
encodingSize++
@ -300,6 +317,12 @@ func (h *Header) EncodeRLP(w io.Writer) error {
}
}
if h.ExcessDataGas != nil {
if err := rlp.EncodeBigInt(h.ExcessDataGas, w, b[:]); err != nil {
return err
}
}
if h.Verkle {
if err := rlp.EncodeString(h.VerkleProof, w, b[:]); err != nil {
return err
@ -445,6 +468,19 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error {
h.WithdrawalsHash = new(libcommon.Hash)
h.WithdrawalsHash.SetBytes(b)
// ExcessDataGas
if b, err = s.Uint256Bytes(); err != nil {
if errors.Is(err, rlp.EOL) {
h.ExcessDataGas = nil
if err := s.ListEnd(); err != nil {
return fmt.Errorf("close header struct (no ExcessDataGas): %w", err)
}
return nil
}
return fmt.Errorf("read ExcessDataGas: %w", err)
}
h.ExcessDataGas = new(big.Int).SetBytes(b)
if h.Verkle {
if h.VerkleProof, err = s.Bytes(); err != nil {
return fmt.Errorf("read VerkleProof: %w", err)
@ -464,14 +500,27 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error {
// field type overrides for gencodec
type headerMarshaling struct {
Difficulty *hexutil.Big
Number *hexutil.Big
GasLimit hexutil.Uint64
GasUsed hexutil.Uint64
Time hexutil.Uint64
Extra hexutil.Bytes
BaseFee *hexutil.Big
Hash libcommon.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
Difficulty *hexutil.Big
Number *hexutil.Big
GasLimit hexutil.Uint64
GasUsed hexutil.Uint64
Time hexutil.Uint64
Extra hexutil.Bytes
BaseFee *hexutil.Big
ExcessDataGas *hexutil.Big
Hash libcommon.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
}
// SetExcessDataGas sets the excess_data_gas field in the header
func (h *Header) SetExcessDataGas(v *big.Int) {
h.ExcessDataGas = new(big.Int)
if v != nil {
h.ExcessDataGas.Set(v)
}
if h.WithdrawalsHash == nil {
// leaving this nil would result in a buggy encoding
h.WithdrawalsHash = &EmptyRootHash
}
}
// Hash returns the block hash of the header, which is simply the keccak256 hash of its
@ -492,6 +541,9 @@ func (h *Header) Size() common.StorageSize {
if h.WithdrawalsHash != nil {
s += common.StorageSize(32)
}
if h.ExcessDataGas != nil {
s += common.StorageSize(bitsToBytes(h.ExcessDataGas.BitLen()))
}
return s
}
@ -516,6 +568,12 @@ func (h *Header) SanityCheck() error {
return fmt.Errorf("too large base fee: bitlen %d", bfLen)
}
}
if h.ExcessDataGas != nil {
if bfLen := h.ExcessDataGas.BitLen(); bfLen > 256 {
return fmt.Errorf("too large excess data gas: bitlen %d", bfLen)
}
}
return nil
}
@ -1173,6 +1231,10 @@ func CopyHeader(h *Header) *Header {
cpy.WithdrawalsHash = new(libcommon.Hash)
cpy.WithdrawalsHash.SetBytes(h.WithdrawalsHash.Bytes())
}
if h.ExcessDataGas != nil {
cpy.ExcessDataGas = new(big.Int)
cpy.ExcessDataGas.Set(h.ExcessDataGas)
}
return &cpy
}
@ -1400,6 +1462,13 @@ func (b *Block) BaseFee() *big.Int {
func (b *Block) WithdrawalsHash() *libcommon.Hash { return b.header.WithdrawalsHash }
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
func (b *Block) ExcessDataGas() *big.Int {
if b.header.ExcessDataGas == nil {
return nil
}
return new(big.Int).Set(b.header.ExcessDataGas)
}
// Header returns a deep-copy of the entire block header using CopyHeader()
func (b *Block) Header() *Header { return CopyHeader(b.header) }
func (b *Block) HeaderNoCopy() *Header { return b.header }

View File

@ -88,6 +88,11 @@ func (ct CommonTx) IsContractDeploy() bool {
return ct.GetTo() == nil
}
func (ct *CommonTx) GetDataHashes() []libcommon.Hash {
// Only blob txs have data hashes
return []libcommon.Hash{}
}
// LegacyTx is the transaction data of regular Ethereum transactions.
type LegacyTx struct {
CommonTx

View File

@ -50,6 +50,7 @@ const (
LegacyTxType = iota
AccessListTxType
DynamicFeeTxType
BlobTxType = 5
)
// Transaction is an Ethereum transaction.
@ -62,6 +63,7 @@ type Transaction interface {
GetEffectiveGasTip(baseFee *uint256.Int) *uint256.Int
GetFeeCap() *uint256.Int
Cost() *uint256.Int
GetDataHashes() []libcommon.Hash
GetGas() uint64
GetValue() *uint256.Int
Time() time.Time

View File

@ -198,3 +198,26 @@ func enable3860(jt *JumpTable) {
jt[CREATE].dynamicGas = gasCreateEip3860
jt[CREATE2].dynamicGas = gasCreate2Eip3860
}
// enable3198 applies mini-danksharding (DATAHASH Opcode)
// - Adds an opcode that returns the versioned data hash of the tx at a index.
func enableSharding(jt *JumpTable) {
jt[DATAHASH] = &operation{
execute: opDataHash,
constantGas: GasFastestStep,
numPop: 0,
numPush: 1,
}
}
// opDataHash implements DATAHASH opcode
func opDataHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
idx := scope.Stack.Peek()
if idx.LtUint64(uint64(len(interpreter.evm.TxContext().DataHashes))) {
hash := interpreter.evm.TxContext().DataHashes[idx.Uint64()]
idx.SetBytes(hash.Bytes())
} else {
idx.Clear()
}
return nil, nil
}

View File

@ -22,23 +22,25 @@ type BlockContext struct {
GetHash GetHashFunc
// Block information
Coinbase libcommon.Address // Provides information for COINBASE
GasLimit uint64 // Provides information for GASLIMIT
MaxGasLimit bool // Use GasLimit override for 2^256-1 (to be compatible with OpenEthereum's trace_call)
BlockNumber uint64 // Provides information for NUMBER
Time uint64 // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
BaseFee *uint256.Int // Provides information for BASEFEE
PrevRanDao *libcommon.Hash // Provides information for PREVRANDAO
Coinbase libcommon.Address // Provides information for COINBASE
GasLimit uint64 // Provides information for GASLIMIT
MaxGasLimit bool // Use GasLimit override for 2^256-1 (to be compatible with OpenEthereum's trace_call)
BlockNumber uint64 // Provides information for NUMBER
Time uint64 // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
BaseFee *uint256.Int // Provides information for BASEFEE
PrevRanDao *libcommon.Hash // Provides information for PREVRANDAO
ExcessDataGas *big.Int // Provides information for handling data blobs
}
// TxContext provides the EVM with information about a transaction.
// All fields can change between transactions.
type TxContext struct {
// Message information
TxHash libcommon.Hash
Origin libcommon.Address // Provides information for ORIGIN
GasPrice *uint256.Int // Provides information for GASPRICE
TxHash libcommon.Hash
Origin libcommon.Address // Provides information for ORIGIN
GasPrice *uint256.Int // Provides information for GASPRICE
DataHashes []libcommon.Hash // Provides versioned data hashes for DATAHASH
}
type (

View File

@ -104,6 +104,7 @@ const (
CHAINID OpCode = 0x46
SELFBALANCE OpCode = 0x47
BASEFEE OpCode = 0x48
DATAHASH OpCode = 0x49
)
// 0x50 range - 'storage' and execution.
@ -277,6 +278,7 @@ var opCodeToString = map[OpCode]string{
CHAINID: "CHAINID",
SELFBALANCE: "SELFBALANCE",
BASEFEE: "BASEFEE",
DATAHASH: "DATAHASH",
// 0x50 range - 'storage' and execution.
POP: "POP",
@ -428,6 +430,7 @@ var stringToOp = map[string]OpCode{
"CALLDATACOPY": CALLDATACOPY,
"CHAINID": CHAINID,
"BASEFEE": BASEFEE,
"DATAHASH": DATAHASH,
"DELEGATECALL": DELEGATECALL,
"STATICCALL": STATICCALL,
"CODESIZE": CODESIZE,

View File

@ -334,6 +334,14 @@ func (s *EthBackendServer) EngineNewPayload(ctx context.Context, req *types2.Exe
return nil, err
}
if req.Version >= 3 {
header.ExcessDataGas = gointerfaces.ConvertH256ToUint256Int(req.ExcessDataGas).ToBig()
}
if !s.config.IsCancun(header.Time) && header.ExcessDataGas != nil || s.config.IsCancun(header.Time) && header.ExcessDataGas == nil {
return nil, &rpc.InvalidParamsError{Message: "excess data gas setting doesn't match sharding state"}
}
blockHash := gointerfaces.ConvertH256ToHash(req.BlockHash)
if header.Hash() != blockHash {
log.Error("[NewPayload] invalid block hash", "stated", libcommon.Hash(blockHash), "actual", header.Hash())
@ -590,6 +598,13 @@ func (s *EthBackendServer) EngineGetPayload(ctx context.Context, req *remote.Eng
payload.Withdrawals = ConvertWithdrawalsToRpc(block.Withdrawals())
}
if block.ExcessDataGas() != nil {
payload.Version = 3
var excessDataGas uint256.Int
excessDataGas.SetFromBig(block.Header().ExcessDataGas)
payload.ExcessDataGas = gointerfaces.ConvertUint256IntToH256(&excessDataGas)
}
blockValue := blockValue(blockWithReceipts, baseFee)
return &remote.EngineGetPayloadResponse{
ExecutionPayload: payload,

View File

@ -165,6 +165,19 @@ const (
// up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529
RefundQuotient uint64 = 2
RefundQuotientEIP3529 uint64 = 5
// stuff from EIP-4844
FieldElementsPerBlob = 4096 // each field element is 32 bytes
MaxDataGasPerBlock = 1 << 19
DataGasPerBlob = 1 << 17
TargetDataGasPerBlock = 1 << 18
MinDataGasPrice = 1
DataGasPriceUpdateFraction = 2225652
MaxBlobsPerBlock = MaxDataGasPerBlock / DataGasPerBlob
BlobVerificationGas uint64 = 1800000
BlobCommitmentVersionKZG uint8 = 0x01
PointEvaluationGas uint64 = 50000
)
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations

View File

@ -281,6 +281,9 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
if head.WithdrawalsHash != nil {
result["withdrawalsRoot"] = head.WithdrawalsHash
}
if head.ExcessDataGas != nil {
result["excessDataGas"] = (*hexutil.Big)(head.ExcessDataGas)
}
return result
}