mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
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:
parent
540af96ef7
commit
70bc7f7a25
@ -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
80
consensus/misc/eip4844.go
Normal 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))
|
||||
}
|
89
consensus/misc/eip4844_test.go
Normal file
89
consensus/misc/eip4844_test.go
Normal 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)
|
||||
}
|
||||
}
|
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 (
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user