mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43:47 +00:00
all: add blob schedule eip
This commit is contained in:
parent
52766bedb9
commit
69d5f03f21
51 changed files with 570 additions and 221 deletions
|
|
@ -743,7 +743,7 @@ func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Tra
|
||||||
GasTipCap: uint256.NewInt(1),
|
GasTipCap: uint256.NewInt(1),
|
||||||
GasFeeCap: uint256.MustFromBig(s.chain.Head().BaseFee()),
|
GasFeeCap: uint256.MustFromBig(s.chain.Head().BaseFee()),
|
||||||
Gas: 100000,
|
Gas: 100000,
|
||||||
BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(*s.chain.Head().ExcessBlobGas())),
|
BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(s.chain.config, s.chain.Head().Header())),
|
||||||
BlobHashes: makeSidecar(blobdata...).BlobHashes(),
|
BlobHashes: makeSidecar(blobdata...).BlobHashes(),
|
||||||
Sidecar: makeSidecar(blobdata...),
|
Sidecar: makeSidecar(blobdata...),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,14 @@
|
||||||
"shanghaiTime": 780,
|
"shanghaiTime": 780,
|
||||||
"cancunTime": 840,
|
"cancunTime": 840,
|
||||||
"terminalTotalDifficulty": 9454784,
|
"terminalTotalDifficulty": 9454784,
|
||||||
"ethash": {}
|
"ethash": {},
|
||||||
|
"blobSchedule": {
|
||||||
|
"cancun": {
|
||||||
|
"target": 3,
|
||||||
|
"max": 6,
|
||||||
|
"baseFeeUpdateFraction": 3338477
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"nonce": "0x0",
|
"nonce": "0x0",
|
||||||
"timestamp": "0x0",
|
"timestamp": "0x0",
|
||||||
|
|
@ -108,4 +115,4 @@
|
||||||
"baseFeePerGas": null,
|
"baseFeePerGas": null,
|
||||||
"excessBlobGas": null,
|
"excessBlobGas": null,
|
||||||
"blobGasUsed": null
|
"blobGasUsed": null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,15 +178,28 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
var excessBlobGas uint64
|
var excessBlobGas uint64
|
||||||
if pre.Env.ExcessBlobGas != nil {
|
if pre.Env.ExcessBlobGas != nil {
|
||||||
excessBlobGas = *pre.Env.ExcessBlobGas
|
excessBlobGas = *pre.Env.ExcessBlobGas
|
||||||
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
header := &types.Header{
|
||||||
|
Time: pre.Env.Timestamp,
|
||||||
|
ExcessBlobGas: pre.Env.ExcessBlobGas,
|
||||||
|
}
|
||||||
|
vmContext.BlobBaseFee = eip4844.CalcBlobFee(chainConfig, header)
|
||||||
} else {
|
} else {
|
||||||
// If it is not explicitly defined, but we have the parent values, we try
|
// If it is not explicitly defined, but we have the parent values, we try
|
||||||
// to calculate it ourselves.
|
// to calculate it ourselves.
|
||||||
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
|
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
|
||||||
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
|
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
|
||||||
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
|
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
|
||||||
excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
|
parent := &types.Header{
|
||||||
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
Time: pre.Env.ParentTimestamp,
|
||||||
|
ExcessBlobGas: pre.Env.ParentExcessBlobGas,
|
||||||
|
BlobGasUsed: pre.Env.ParentBlobGasUsed,
|
||||||
|
}
|
||||||
|
excessBlobGas = eip4844.CalcExcessBlobGas(chainConfig, parent)
|
||||||
|
header := &types.Header{
|
||||||
|
Time: pre.Env.Timestamp,
|
||||||
|
ExcessBlobGas: &excessBlobGas,
|
||||||
|
}
|
||||||
|
vmContext.BlobBaseFee = eip4844.CalcBlobFee(chainConfig, header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
||||||
|
|
@ -229,7 +242,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
txBlobGas := uint64(0)
|
txBlobGas := uint64(0)
|
||||||
if tx.Type() == types.BlobTxType {
|
if tx.Type() == types.BlobTxType {
|
||||||
txBlobGas = uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes()))
|
txBlobGas = uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes()))
|
||||||
if used, max := blobGasUsed+txBlobGas, uint64(params.MaxBlobGasPerBlock); used > max {
|
if used, max := blobGasUsed+txBlobGas, chainConfig.MaxBlobsPerBlock(pre.Env.Timestamp)*params.BlobTxBlobGasPerBlob; used > max {
|
||||||
err := fmt.Errorf("blob gas (%d) would exceed maximum allowance %d", used, max)
|
err := fmt.Errorf("blob gas (%d) would exceed maximum allowance %d", used, max)
|
||||||
log.Warn("rejected tx", "index", i, "err", err)
|
log.Warn("rejected tx", "index", i, "err", err)
|
||||||
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
|
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
|
||||||
if header.ParentBeaconRoot == nil {
|
if header.ParentBeaconRoot == nil {
|
||||||
return errors.New("header is missing beaconRoot")
|
return errors.New("header is missing beaconRoot")
|
||||||
}
|
}
|
||||||
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
|
if err := eip4844.VerifyEIP4844Header(chain.Config(), parent, header); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,17 +23,17 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/params/forks"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
minBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
|
minBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
|
||||||
blobGaspriceUpdateFraction = big.NewInt(params.BlobTxBlobGaspriceUpdateFraction)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
|
// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
|
||||||
// if the current block contains no transactions, the excessBlobGas is updated
|
// if the current block contains no transactions, the excessBlobGas is updated
|
||||||
// accordingly.
|
// accordingly.
|
||||||
func VerifyEIP4844Header(parent, header *types.Header) error {
|
func VerifyEIP4844Header(config *params.ChainConfig, parent, header *types.Header) error {
|
||||||
// Verify the header is not malformed
|
// Verify the header is not malformed
|
||||||
if header.ExcessBlobGas == nil {
|
if header.ExcessBlobGas == nil {
|
||||||
return errors.New("header is missing excessBlobGas")
|
return errors.New("header is missing excessBlobGas")
|
||||||
|
|
@ -42,14 +42,25 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
|
||||||
return errors.New("header is missing blobGasUsed")
|
return errors.New("header is missing blobGasUsed")
|
||||||
}
|
}
|
||||||
// Verify that the blob gas used remains within reasonable limits.
|
// Verify that the blob gas used remains within reasonable limits.
|
||||||
if *header.BlobGasUsed > params.MaxBlobGasPerBlock {
|
if max := config.MaxBlobsPerBlock(header.Time) * params.BlobTxBlobGasPerBlob; *header.BlobGasUsed > max {
|
||||||
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock)
|
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, max)
|
||||||
}
|
}
|
||||||
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
|
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
|
||||||
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
|
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
|
||||||
}
|
}
|
||||||
// Verify the excessBlobGas is correct based on the parent header
|
// Verify the excessBlobGas is correct based on the parent header
|
||||||
|
expectedExcessBlobGas := CalcExcessBlobGas(config, parent)
|
||||||
|
if *header.ExcessBlobGas != expectedExcessBlobGas {
|
||||||
|
return fmt.Errorf("invalid excessBlobGas: have %d, want %d", *header.ExcessBlobGas, expectedExcessBlobGas)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalcExcessBlobGas calculates the excess blob gas after applying the set of
|
||||||
|
// blobs on top of the excess blob gas.
|
||||||
|
func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header) uint64 {
|
||||||
var (
|
var (
|
||||||
|
target = config.TargetBlobsPerBlock(parent.Time) * params.BlobTxBlobGasPerBlob
|
||||||
parentExcessBlobGas uint64
|
parentExcessBlobGas uint64
|
||||||
parentBlobGasUsed uint64
|
parentBlobGasUsed uint64
|
||||||
)
|
)
|
||||||
|
|
@ -57,27 +68,23 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
|
||||||
parentExcessBlobGas = *parent.ExcessBlobGas
|
parentExcessBlobGas = *parent.ExcessBlobGas
|
||||||
parentBlobGasUsed = *parent.BlobGasUsed
|
parentBlobGasUsed = *parent.BlobGasUsed
|
||||||
}
|
}
|
||||||
expectedExcessBlobGas := CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
|
|
||||||
if *header.ExcessBlobGas != expectedExcessBlobGas {
|
|
||||||
return fmt.Errorf("invalid excessBlobGas: have %d, want %d, parent excessBlobGas %d, parent blobDataUsed %d",
|
|
||||||
*header.ExcessBlobGas, expectedExcessBlobGas, parentExcessBlobGas, parentBlobGasUsed)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalcExcessBlobGas calculates the excess blob gas after applying the set of
|
|
||||||
// blobs on top of the excess blob gas.
|
|
||||||
func CalcExcessBlobGas(parentExcessBlobGas uint64, parentBlobGasUsed uint64) uint64 {
|
|
||||||
excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
|
excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
|
||||||
if excessBlobGas < params.BlobTxTargetBlobGasPerBlock {
|
if excessBlobGas < target {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return excessBlobGas - params.BlobTxTargetBlobGasPerBlock
|
return excessBlobGas - target
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
|
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
|
||||||
func CalcBlobFee(excessBlobGas uint64) *big.Int {
|
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
|
||||||
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(excessBlobGas), blobGaspriceUpdateFraction)
|
switch config.LatestFork(header.Time) {
|
||||||
|
case forks.Prague:
|
||||||
|
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(config.BlobScheduleConfig.Prague.UpdateFraction))
|
||||||
|
case forks.Cancun:
|
||||||
|
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(config.BlobScheduleConfig.Cancun.UpdateFraction))
|
||||||
|
default:
|
||||||
|
panic("calculating blob fee on unsupported fork")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fakeExponential approximates factor * e ** (numerator / denominator) using
|
// fakeExponential approximates factor * e ** (numerator / denominator) using
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,16 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCalcExcessBlobGas(t *testing.T) {
|
func TestCalcExcessBlobGas(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = params.MainnetChainConfig
|
||||||
|
targetBlobs = config.TargetBlobsPerBlock(*config.CancunTime)
|
||||||
|
targetBlobGas = targetBlobs * params.BlobTxBlobGasPerBlob
|
||||||
|
)
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
excess uint64
|
excess uint64
|
||||||
blobs uint64
|
blobs uint64
|
||||||
|
|
@ -34,23 +40,29 @@ func TestCalcExcessBlobGas(t *testing.T) {
|
||||||
// slots are below - or equal - to the target.
|
// slots are below - or equal - to the target.
|
||||||
{0, 0, 0},
|
{0, 0, 0},
|
||||||
{0, 1, 0},
|
{0, 1, 0},
|
||||||
{0, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, 0},
|
{0, targetBlobs, 0},
|
||||||
|
|
||||||
// If the target blob gas is exceeded, the excessBlobGas should increase
|
// If the target blob gas is exceeded, the excessBlobGas should increase
|
||||||
// by however much it was overshot
|
// by however much it was overshot
|
||||||
{0, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob},
|
{0, targetBlobs + 1, params.BlobTxBlobGasPerBlob},
|
||||||
{1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob + 1},
|
{1, targetBlobs + 1, params.BlobTxBlobGasPerBlob + 1},
|
||||||
{1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 2, 2*params.BlobTxBlobGasPerBlob + 1},
|
{1, targetBlobs + 2, 2*params.BlobTxBlobGasPerBlob + 1},
|
||||||
|
|
||||||
// The excess blob gas should decrease by however much the target was
|
// The excess blob gas should decrease by however much the target was
|
||||||
// under-shot, capped at zero.
|
// under-shot, capped at zero.
|
||||||
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
|
{targetBlobGas, targetBlobs, targetBlobGas},
|
||||||
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxTargetBlobGasPerBlock - params.BlobTxBlobGasPerBlob},
|
{targetBlobGas, targetBlobs - 1, targetBlobGas - params.BlobTxBlobGasPerBlob},
|
||||||
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxTargetBlobGasPerBlock - (2 * params.BlobTxBlobGasPerBlob)},
|
{targetBlobGas, targetBlobs - 2, targetBlobGas - (2 * params.BlobTxBlobGasPerBlob)},
|
||||||
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
|
{params.BlobTxBlobGasPerBlob - 1, targetBlobs - 1, 0},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob)
|
blobGasUsed := tt.blobs * params.BlobTxBlobGasPerBlob
|
||||||
|
parent := &types.Header{
|
||||||
|
Time: *config.CancunTime,
|
||||||
|
ExcessBlobGas: &tt.excess,
|
||||||
|
BlobGasUsed: &blobGasUsed,
|
||||||
|
}
|
||||||
|
result := CalcExcessBlobGas(config, parent)
|
||||||
if result != tt.want {
|
if result != tt.want {
|
||||||
t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want)
|
t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want)
|
||||||
}
|
}
|
||||||
|
|
@ -58,6 +70,8 @@ func TestCalcExcessBlobGas(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCalcBlobFee(t *testing.T) {
|
func TestCalcBlobFee(t *testing.T) {
|
||||||
|
zero := uint64(0)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
excessBlobGas uint64
|
excessBlobGas uint64
|
||||||
blobfee int64
|
blobfee int64
|
||||||
|
|
@ -68,7 +82,9 @@ func TestCalcBlobFee(t *testing.T) {
|
||||||
{10 * 1024 * 1024, 23},
|
{10 * 1024 * 1024, 23},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
have := CalcBlobFee(tt.excessBlobGas)
|
config := ¶ms.ChainConfig{LondonBlock: big.NewInt(0), CancunTime: &zero, BlobScheduleConfig: params.DefaultBlobSchedule}
|
||||||
|
header := &types.Header{ExcessBlobGas: &tt.excessBlobGas}
|
||||||
|
have := CalcBlobFee(config, header)
|
||||||
if have.Int64() != tt.blobfee {
|
if have.Int64() != tt.blobfee {
|
||||||
t.Errorf("test %d: blobfee mismatch: have %v want %v", i, have, tt.blobfee)
|
t.Errorf("test %d: blobfee mismatch: have %v want %v", i, have, tt.blobfee)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2133,9 +2133,8 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co
|
||||||
// processing of a block. These logs are later announced as deleted or reborn.
|
// processing of a block. These logs are later announced as deleted or reborn.
|
||||||
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
||||||
var blobGasPrice *big.Int
|
var blobGasPrice *big.Int
|
||||||
excessBlobGas := b.ExcessBlobGas()
|
if b.ExcessBlobGas() != nil {
|
||||||
if excessBlobGas != nil {
|
blobGasPrice = eip4844.CalcBlobFee(bc.chainConfig, b.Header())
|
||||||
blobGasPrice = eip4844.CalcBlobFee(*excessBlobGas)
|
|
||||||
}
|
}
|
||||||
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
|
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
|
||||||
if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), blobGasPrice, b.Transactions()); err != nil {
|
if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), blobGasPrice, b.Transactions()); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ func (b *BlockGen) Difficulty() *big.Int {
|
||||||
// block.
|
// block.
|
||||||
func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
|
func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
|
||||||
b.header.ParentBeaconRoot = &root
|
b.header.ParentBeaconRoot = &root
|
||||||
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, b.cm, b.cm.config, &b.header.Coinbase)
|
||||||
ProcessBeaconBlockRoot(root, vm.NewEVM(blockContext, b.statedb, b.cm.config, vm.Config{}))
|
ProcessBeaconBlockRoot(root, vm.NewEVM(blockContext, b.statedb, b.cm.config, vm.Config{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,7 +114,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
||||||
b.SetCoinbase(common.Address{})
|
b.SetCoinbase(common.Address{})
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
blockContext = NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
|
blockContext = NewEVMBlockContext(b.header, bc, b.cm.config, &b.header.Coinbase)
|
||||||
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
|
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
|
||||||
)
|
)
|
||||||
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
|
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
|
||||||
|
|
@ -323,7 +323,7 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) {
|
||||||
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
||||||
}
|
}
|
||||||
// create EVM for system calls
|
// create EVM for system calls
|
||||||
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, b.cm, b.cm.config, &b.header.Coinbase)
|
||||||
evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
|
evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
|
||||||
// EIP-7002
|
// EIP-7002
|
||||||
ProcessWithdrawalQueue(&requests, evm)
|
ProcessWithdrawalQueue(&requests, evm)
|
||||||
|
|
@ -386,7 +386,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
|
|
||||||
if config.IsPrague(b.header.Number, b.header.Time) || config.IsVerkle(b.header.Number, b.header.Time) {
|
if config.IsPrague(b.header.Number, b.header.Time) || config.IsVerkle(b.header.Number, b.header.Time) {
|
||||||
// EIP-2935
|
// EIP-2935
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, cm, cm.config, &b.header.Coinbase)
|
||||||
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
||||||
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
||||||
ProcessParentBlockHash(b.header.ParentHash, evm)
|
ProcessParentBlockHash(b.header.ParentHash, evm)
|
||||||
|
|
@ -445,7 +445,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
}
|
}
|
||||||
var blobGasPrice *big.Int
|
var blobGasPrice *big.Int
|
||||||
if block.ExcessBlobGas() != nil {
|
if block.ExcessBlobGas() != nil {
|
||||||
blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
|
blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
|
||||||
}
|
}
|
||||||
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
|
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
@ -493,7 +493,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
// preState := statedb.Copy()
|
// preState := statedb.Copy()
|
||||||
|
|
||||||
// EIP-2935 / 7709
|
// EIP-2935 / 7709
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, cm, cm.Config(), &b.header.Coinbase)
|
||||||
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
||||||
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
||||||
ProcessParentBlockHash(b.header.ParentHash, evm)
|
ProcessParentBlockHash(b.header.ParentHash, evm)
|
||||||
|
|
@ -548,7 +548,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
}
|
}
|
||||||
var blobGasPrice *big.Int
|
var blobGasPrice *big.Int
|
||||||
if block.ExcessBlobGas() != nil {
|
if block.ExcessBlobGas() != nil {
|
||||||
blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
|
blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
|
||||||
}
|
}
|
||||||
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
|
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
@ -598,15 +598,7 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cm.config.IsCancun(header.Number, header.Time) {
|
if cm.config.IsCancun(header.Number, header.Time) {
|
||||||
var (
|
excessBlobGas := eip4844.CalcExcessBlobGas(cm.config, parent.Header())
|
||||||
parentExcessBlobGas uint64
|
|
||||||
parentBlobGasUsed uint64
|
|
||||||
)
|
|
||||||
if parent.ExcessBlobGas() != nil {
|
|
||||||
parentExcessBlobGas = *parent.ExcessBlobGas()
|
|
||||||
parentBlobGasUsed = *parent.BlobGasUsed()
|
|
||||||
}
|
|
||||||
excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
|
|
||||||
header.ExcessBlobGas = &excessBlobGas
|
header.ExcessBlobGas = &excessBlobGas
|
||||||
header.BlobGasUsed = new(uint64)
|
header.BlobGasUsed = new(uint64)
|
||||||
header.ParentBeaconRoot = new(common.Hash)
|
header.ParentBeaconRoot = new(common.Hash)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||||
aa = common.Address{0xaa}
|
aa = common.Address{0xaa}
|
||||||
bb = common.Address{0xbb}
|
bb = common.Address{0xbb}
|
||||||
funds = big.NewInt(0).Mul(big.NewInt(1337), big.NewInt(params.Ether))
|
funds = big.NewInt(0).Mul(big.NewInt(1337), big.NewInt(params.Ether))
|
||||||
config = *params.AllEthashProtocolChanges
|
config = *params.MergedTestChainConfig
|
||||||
gspec = &Genesis{
|
gspec = &Genesis{
|
||||||
Config: &config,
|
Config: &config,
|
||||||
Alloc: types.GenesisAlloc{
|
Alloc: types.GenesisAlloc{
|
||||||
|
|
@ -57,10 +57,6 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
)
|
)
|
||||||
|
|
||||||
config.TerminalTotalDifficulty = common.Big0
|
|
||||||
config.ShanghaiTime = u64(0)
|
|
||||||
config.CancunTime = u64(0)
|
|
||||||
|
|
||||||
// init 0xaa with some storage elements
|
// init 0xaa with some storage elements
|
||||||
storage := make(map[common.Hash]common.Hash)
|
storage := make(map[common.Hash]common.Hash)
|
||||||
storage[common.Hash{0x00}] = common.Hash{0x00}
|
storage[common.Hash{0x00}] = common.Hash{0x00}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -39,7 +40,7 @@ type ChainContext interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEVMBlockContext creates a new context for use in the EVM.
|
// NewEVMBlockContext creates a new context for use in the EVM.
|
||||||
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext {
|
func NewEVMBlockContext(header *types.Header, chain ChainContext, config *params.ChainConfig, author *common.Address) vm.BlockContext {
|
||||||
var (
|
var (
|
||||||
beneficiary common.Address
|
beneficiary common.Address
|
||||||
baseFee *big.Int
|
baseFee *big.Int
|
||||||
|
|
@ -57,7 +58,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
||||||
baseFee = new(big.Int).Set(header.BaseFee)
|
baseFee = new(big.Int).Set(header.BaseFee)
|
||||||
}
|
}
|
||||||
if header.ExcessBlobGas != nil {
|
if header.ExcessBlobGas != nil {
|
||||||
blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas)
|
blobBaseFee = eip4844.CalcBlobFee(config, header)
|
||||||
}
|
}
|
||||||
if header.Difficulty.Sign() == 0 {
|
if header.Difficulty.Sign() == 0 {
|
||||||
random = &header.MixDigest
|
random = &header.MixDigest
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,11 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
||||||
EnableVerkleAtGenesis: true,
|
EnableVerkleAtGenesis: true,
|
||||||
Ethash: nil,
|
Ethash: nil,
|
||||||
Clique: nil,
|
Clique: nil,
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Cancun: params.DefaultCancunBlobConfig,
|
||||||
|
Prague: params.DefaultPragueBlobConfig,
|
||||||
|
Verkle: params.DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
genesis := &Genesis{
|
genesis := &Genesis{
|
||||||
|
|
|
||||||
|
|
@ -587,7 +587,7 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, time uint64,
|
||||||
// Compute effective blob gas price.
|
// Compute effective blob gas price.
|
||||||
var blobGasPrice *big.Int
|
var blobGasPrice *big.Int
|
||||||
if header != nil && header.ExcessBlobGas != nil {
|
if header != nil && header.ExcessBlobGas != nil {
|
||||||
blobGasPrice = eip4844.CalcBlobFee(*header.ExcessBlobGas)
|
blobGasPrice = eip4844.CalcBlobFee(config, header)
|
||||||
}
|
}
|
||||||
if err := receipts.DeriveFields(config, hash, number, time, baseFee, blobGasPrice, body.Transactions); err != nil {
|
if err := receipts.DeriveFields(config, hash, number, time, baseFee, blobGasPrice, body.Transactions); err != nil {
|
||||||
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
|
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
|
||||||
var (
|
var (
|
||||||
header = block.Header()
|
header = block.Header()
|
||||||
gaspool = new(GasPool).AddGas(block.GasLimit())
|
gaspool = new(GasPool).AddGas(block.GasLimit())
|
||||||
blockContext = NewEVMBlockContext(header, p.chain, nil)
|
blockContext = NewEVMBlockContext(header, p.chain, p.config, nil)
|
||||||
evm = vm.NewEVM(blockContext, statedb, p.config, cfg)
|
evm = vm.NewEVM(blockContext, statedb, p.config, cfg)
|
||||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
if hooks := cfg.Tracer; hooks != nil {
|
if hooks := cfg.Tracer; hooks != nil {
|
||||||
tracingStateDB = state.NewHookedState(statedb, hooks)
|
tracingStateDB = state.NewHookedState(statedb, hooks)
|
||||||
}
|
}
|
||||||
context = NewEVMBlockContext(header, p.chain, nil)
|
context = NewEVMBlockContext(header, p.chain, p.config, nil)
|
||||||
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
|
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
|
||||||
|
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
|
|
|
||||||
|
|
@ -46,25 +46,7 @@ func u64(val uint64) *uint64 { return &val }
|
||||||
// contain invalid transactions
|
// contain invalid transactions
|
||||||
func TestStateProcessorErrors(t *testing.T) {
|
func TestStateProcessorErrors(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
config = ¶ms.ChainConfig{
|
config = params.MergedTestChainConfig
|
||||||
ChainID: big.NewInt(1),
|
|
||||||
HomesteadBlock: big.NewInt(0),
|
|
||||||
EIP150Block: big.NewInt(0),
|
|
||||||
EIP155Block: big.NewInt(0),
|
|
||||||
EIP158Block: big.NewInt(0),
|
|
||||||
ByzantiumBlock: big.NewInt(0),
|
|
||||||
ConstantinopleBlock: big.NewInt(0),
|
|
||||||
PetersburgBlock: big.NewInt(0),
|
|
||||||
IstanbulBlock: big.NewInt(0),
|
|
||||||
MuirGlacierBlock: big.NewInt(0),
|
|
||||||
BerlinBlock: big.NewInt(0),
|
|
||||||
LondonBlock: big.NewInt(0),
|
|
||||||
Ethash: new(params.EthashConfig),
|
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
|
||||||
ShanghaiTime: new(uint64),
|
|
||||||
CancunTime: new(uint64),
|
|
||||||
PragueTime: new(uint64),
|
|
||||||
}
|
|
||||||
signer = types.LatestSigner(config)
|
signer = types.LatestSigner(config)
|
||||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020")
|
key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020")
|
||||||
|
|
@ -425,12 +407,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
|
||||||
}
|
}
|
||||||
header.Root = common.BytesToHash(hasher.Sum(nil))
|
header.Root = common.BytesToHash(hasher.Sum(nil))
|
||||||
if config.IsCancun(header.Number, header.Time) {
|
if config.IsCancun(header.Number, header.Time) {
|
||||||
var pExcess, pUsed = uint64(0), uint64(0)
|
excess := eip4844.CalcExcessBlobGas(config, parent.Header())
|
||||||
if parent.ExcessBlobGas() != nil {
|
|
||||||
pExcess = *parent.ExcessBlobGas()
|
|
||||||
pUsed = *parent.BlobGasUsed()
|
|
||||||
}
|
|
||||||
excess := eip4844.CalcExcessBlobGas(pExcess, pUsed)
|
|
||||||
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
|
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
|
||||||
header.ExcessBlobGas = &excess
|
header.ExcessBlobGas = &excess
|
||||||
header.BlobGasUsed = &used
|
header.BlobGasUsed = &used
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,6 @@ const (
|
||||||
// transaction. There can be multiple of these embedded into a single tx.
|
// transaction. There can be multiple of these embedded into a single tx.
|
||||||
blobSize = params.BlobTxFieldElementsPerBlob * params.BlobTxBytesPerFieldElement
|
blobSize = params.BlobTxFieldElementsPerBlob * params.BlobTxBytesPerFieldElement
|
||||||
|
|
||||||
// maxBlobsPerTransaction is the maximum number of blobs a single transaction
|
|
||||||
// is allowed to contain. Whilst the spec states it's unlimited, the block
|
|
||||||
// data slots are protocol bound, which implicitly also limit this.
|
|
||||||
maxBlobsPerTransaction = params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob
|
|
||||||
|
|
||||||
// txAvgSize is an approximate byte size of a transaction metadata to avoid
|
// txAvgSize is an approximate byte size of a transaction metadata to avoid
|
||||||
// tiny overflows causing all txs to move a shelf higher, wasting disk space.
|
// tiny overflows causing all txs to move a shelf higher, wasting disk space.
|
||||||
txAvgSize = 4 * 1024
|
txAvgSize = 4 * 1024
|
||||||
|
|
@ -223,6 +218,11 @@ func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta {
|
||||||
// very relaxed ones can be included even if the fees go up, when the closer
|
// very relaxed ones can be included even if the fees go up, when the closer
|
||||||
// ones could already be invalid.
|
// ones could already be invalid.
|
||||||
//
|
//
|
||||||
|
// - Because the maximum number of blobs allowed in a block can change per
|
||||||
|
// fork, the pool is designed to handle the maximum number of blobs allowed
|
||||||
|
// in the chain's latest defined fork -- even if it isn't active. This
|
||||||
|
// avoids needing to upgrade the database around the fork boundary.
|
||||||
|
//
|
||||||
// When the pool eventually reaches saturation, some old transactions - that may
|
// When the pool eventually reaches saturation, some old transactions - that may
|
||||||
// never execute - will need to be evicted in favor of newer ones. The eviction
|
// never execute - will need to be evicted in favor of newer ones. The eviction
|
||||||
// strategy is quite complex:
|
// strategy is quite complex:
|
||||||
|
|
@ -387,7 +387,8 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.Addres
|
||||||
fails = append(fails, id)
|
fails = append(fails, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
store, err := billy.Open(billy.Options{Path: queuedir, Repair: true}, newSlotter(), index)
|
slotter := newSlotter(p.chain.Config().LatestMaxBlobsPerBlock())
|
||||||
|
store, err := billy.Open(billy.Options{Path: queuedir, Repair: true}, slotter, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -414,13 +415,13 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.Addres
|
||||||
blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
|
blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
|
||||||
)
|
)
|
||||||
if p.head.ExcessBlobGas != nil {
|
if p.head.ExcessBlobGas != nil {
|
||||||
blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(*p.head.ExcessBlobGas))
|
blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(p.chain.Config(), p.head))
|
||||||
}
|
}
|
||||||
p.evict = newPriceHeap(basefee, blobfee, p.index)
|
p.evict = newPriceHeap(basefee, blobfee, p.index)
|
||||||
|
|
||||||
// Pool initialized, attach the blob limbo to it to track blobs included
|
// Pool initialized, attach the blob limbo to it to track blobs included
|
||||||
// recently but not yet finalized
|
// recently but not yet finalized
|
||||||
p.limbo, err = newLimbo(limbodir)
|
p.limbo, err = newLimbo(limbodir, p.chain.Config().LatestMaxBlobsPerBlock())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Close()
|
p.Close()
|
||||||
return err
|
return err
|
||||||
|
|
@ -834,7 +835,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
|
||||||
blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice))
|
blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice))
|
||||||
)
|
)
|
||||||
if newHead.ExcessBlobGas != nil {
|
if newHead.ExcessBlobGas != nil {
|
||||||
blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(*newHead.ExcessBlobGas))
|
blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(p.chain.Config(), newHead))
|
||||||
}
|
}
|
||||||
p.evict.reinit(basefee, blobfee, false)
|
p.evict.reinit(basefee, blobfee, false)
|
||||||
|
|
||||||
|
|
@ -1598,7 +1599,7 @@ func (p *BlobPool) updateStorageMetrics() {
|
||||||
metrics.GetOrRegisterGauge(fmt.Sprintf(shelfSlotusedGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.FilledSlots))
|
metrics.GetOrRegisterGauge(fmt.Sprintf(shelfSlotusedGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.FilledSlots))
|
||||||
metrics.GetOrRegisterGauge(fmt.Sprintf(shelfSlotgapsGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.GappedSlots))
|
metrics.GetOrRegisterGauge(fmt.Sprintf(shelfSlotgapsGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.GappedSlots))
|
||||||
|
|
||||||
if shelf.SlotSize/blobSize > maxBlobsPerTransaction {
|
if shelf.SlotSize/blobSize > uint32(p.chain.Config().LatestMaxBlobsPerBlock()) {
|
||||||
oversizedDataused += slotDataused
|
oversizedDataused += slotDataused
|
||||||
oversizedDatagaps += slotDatagaps
|
oversizedDatagaps += slotDatagaps
|
||||||
oversizedSlotused += shelf.FilledSlots
|
oversizedSlotused += shelf.FilledSlots
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,10 @@ var (
|
||||||
testBlobVHashes [][32]byte
|
testBlobVHashes [][32]byte
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const testMaxBlobsPerBlock = 6
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 24; i++ {
|
||||||
testBlob := &kzg4844.Blob{byte(i)}
|
testBlob := &kzg4844.Blob{byte(i)}
|
||||||
testBlobs = append(testBlobs, testBlob)
|
testBlobs = append(testBlobs, testBlob)
|
||||||
|
|
||||||
|
|
@ -121,7 +123,12 @@ func (bc *testBlockChain) CurrentBlock() *types.Header {
|
||||||
mid := new(big.Int).Add(lo, hi)
|
mid := new(big.Int).Add(lo, hi)
|
||||||
mid.Div(mid, big.NewInt(2))
|
mid.Div(mid, big.NewInt(2))
|
||||||
|
|
||||||
if eip4844.CalcBlobFee(mid.Uint64()).Cmp(bc.blobfee.ToBig()) > 0 {
|
tmp := mid.Uint64()
|
||||||
|
if eip4844.CalcBlobFee(bc.Config(), &types.Header{
|
||||||
|
Number: blockNumber,
|
||||||
|
Time: blockTime,
|
||||||
|
ExcessBlobGas: &tmp,
|
||||||
|
}).Cmp(bc.blobfee.ToBig()) > 0 {
|
||||||
hi = mid
|
hi = mid
|
||||||
} else {
|
} else {
|
||||||
lo = mid
|
lo = mid
|
||||||
|
|
@ -194,10 +201,43 @@ func makeTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64,
|
||||||
return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
|
return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// makeMultiBlobTx is a utility method to construct a ramdom blob tx with
|
||||||
|
// certain number of blobs in its sidecar.
|
||||||
|
func makeMultiBlobTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64, blobCount int, key *ecdsa.PrivateKey) *types.Transaction {
|
||||||
|
var (
|
||||||
|
blobs []kzg4844.Blob
|
||||||
|
blobHashes []common.Hash
|
||||||
|
commitments []kzg4844.Commitment
|
||||||
|
proofs []kzg4844.Proof
|
||||||
|
)
|
||||||
|
for i := 0; i < blobCount; i++ {
|
||||||
|
blobs = append(blobs, *testBlobs[i])
|
||||||
|
commitments = append(commitments, testBlobCommits[i])
|
||||||
|
proofs = append(proofs, testBlobProofs[i])
|
||||||
|
blobHashes = append(blobHashes, testBlobVHashes[i])
|
||||||
|
}
|
||||||
|
blobtx := &types.BlobTx{
|
||||||
|
ChainID: uint256.MustFromBig(params.MainnetChainConfig.ChainID),
|
||||||
|
Nonce: nonce,
|
||||||
|
GasTipCap: uint256.NewInt(gasTipCap),
|
||||||
|
GasFeeCap: uint256.NewInt(gasFeeCap),
|
||||||
|
Gas: 21000,
|
||||||
|
BlobFeeCap: uint256.NewInt(blobFeeCap),
|
||||||
|
BlobHashes: blobHashes,
|
||||||
|
Value: uint256.NewInt(100),
|
||||||
|
Sidecar: &types.BlobTxSidecar{
|
||||||
|
Blobs: blobs,
|
||||||
|
Commitments: commitments,
|
||||||
|
Proofs: proofs,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
|
||||||
|
}
|
||||||
|
|
||||||
// makeUnsignedTx is a utility method to construct a random blob transaction
|
// makeUnsignedTx is a utility method to construct a random blob transaction
|
||||||
// without signing it.
|
// without signing it.
|
||||||
func makeUnsignedTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64) *types.BlobTx {
|
func makeUnsignedTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64) *types.BlobTx {
|
||||||
return makeUnsignedTxWithTestBlob(nonce, gasTipCap, gasFeeCap, blobFeeCap, rand.Intn(len(testBlobs)))
|
return makeUnsignedTxWithTestBlob(nonce, gasTipCap, gasFeeCap, blobFeeCap, rnd.Intn(len(testBlobs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeUnsignedTx is a utility method to construct a random blob transaction
|
// makeUnsignedTx is a utility method to construct a random blob transaction
|
||||||
|
|
@ -415,7 +455,7 @@ func TestOpenDrops(t *testing.T) {
|
||||||
defer os.RemoveAll(storage)
|
defer os.RemoveAll(storage)
|
||||||
|
|
||||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil)
|
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||||
|
|
||||||
// Insert a malformed transaction to verify that decoding errors (or format
|
// Insert a malformed transaction to verify that decoding errors (or format
|
||||||
// changes) are handled gracefully (case 1)
|
// changes) are handled gracefully (case 1)
|
||||||
|
|
@ -738,7 +778,7 @@ func TestOpenIndex(t *testing.T) {
|
||||||
defer os.RemoveAll(storage)
|
defer os.RemoveAll(storage)
|
||||||
|
|
||||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil)
|
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||||
|
|
||||||
// Insert a sequence of transactions with varying price points to check that
|
// Insert a sequence of transactions with varying price points to check that
|
||||||
// the cumulative minimum will be maintained.
|
// the cumulative minimum will be maintained.
|
||||||
|
|
@ -827,7 +867,7 @@ func TestOpenHeap(t *testing.T) {
|
||||||
defer os.RemoveAll(storage)
|
defer os.RemoveAll(storage)
|
||||||
|
|
||||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil)
|
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||||
|
|
||||||
// Insert a few transactions from a few accounts. To remove randomness from
|
// Insert a few transactions from a few accounts. To remove randomness from
|
||||||
// the heap initialization, use a deterministic account/tx/priority ordering.
|
// the heap initialization, use a deterministic account/tx/priority ordering.
|
||||||
|
|
@ -914,7 +954,7 @@ func TestOpenCap(t *testing.T) {
|
||||||
defer os.RemoveAll(storage)
|
defer os.RemoveAll(storage)
|
||||||
|
|
||||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil)
|
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||||
|
|
||||||
// Insert a few transactions from a few accounts
|
// Insert a few transactions from a few accounts
|
||||||
var (
|
var (
|
||||||
|
|
@ -992,6 +1032,108 @@ func TestOpenCap(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestChangingSlotterSize attempts to mimic a scenario where the max blob count
|
||||||
|
// of the pool is increased. This would happen during a client release where a
|
||||||
|
// new fork is added with a max blob count higher than the previous fork. We
|
||||||
|
// want to make sure transactions a persisted between those runs.
|
||||||
|
func TestChangingSlotterSize(t *testing.T) {
|
||||||
|
//log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
|
||||||
|
|
||||||
|
// Create a temporary folder for the persistent backend
|
||||||
|
storage, _ := os.MkdirTemp("", "blobpool-")
|
||||||
|
defer os.RemoveAll(storage)
|
||||||
|
|
||||||
|
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||||
|
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(6), nil)
|
||||||
|
|
||||||
|
// Create transactions from a few accounts.
|
||||||
|
var (
|
||||||
|
key1, _ = crypto.GenerateKey()
|
||||||
|
key2, _ = crypto.GenerateKey()
|
||||||
|
key3, _ = crypto.GenerateKey()
|
||||||
|
|
||||||
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
|
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||||
|
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||||
|
|
||||||
|
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, key1)
|
||||||
|
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, key2)
|
||||||
|
tx3 = makeMultiBlobTx(0, 1, 800, 110, 24, key3)
|
||||||
|
|
||||||
|
blob1, _ = rlp.EncodeToBytes(tx1)
|
||||||
|
blob2, _ = rlp.EncodeToBytes(tx2)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Write the two safely sized txs to store. note: although the store is
|
||||||
|
// configured for a blob count of 6, it can also support around ~1mb of call
|
||||||
|
// data - all this to say that we aren't using the the absolute largest shelf
|
||||||
|
// available.
|
||||||
|
store.Put(blob1)
|
||||||
|
store.Put(blob2)
|
||||||
|
store.Close()
|
||||||
|
|
||||||
|
// Mimic a blobpool with max blob count of 6 upgrading to a max blob count of 24.
|
||||||
|
for _, maxBlobs := range []uint64{6, 24} {
|
||||||
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
|
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
|
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
|
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
|
statedb.Commit(0, true, false)
|
||||||
|
|
||||||
|
// Make custom chain config where the max blob count changes based on the loop variable.
|
||||||
|
cancunTime := uint64(0)
|
||||||
|
config := ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(1),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
CancunTime: &cancunTime,
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Cancun: ¶ms.BlobConfig{
|
||||||
|
Target: maxBlobs / 2,
|
||||||
|
Max: maxBlobs,
|
||||||
|
UpdateFraction: params.DefaultCancunBlobConfig.UpdateFraction,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
chain := &testBlockChain{
|
||||||
|
config: config,
|
||||||
|
basefee: uint256.NewInt(1050),
|
||||||
|
blobfee: uint256.NewInt(105),
|
||||||
|
statedb: statedb,
|
||||||
|
}
|
||||||
|
pool := New(Config{Datadir: storage}, chain)
|
||||||
|
if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||||
|
t.Fatalf("failed to create blob pool: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to add the big blob tx. In the initial iteration it should overflow
|
||||||
|
// the pool. On the subsequent iteration it should be accepted.
|
||||||
|
errs := pool.Add([]*types.Transaction{tx3}, false, true)
|
||||||
|
if _, ok := pool.index[addr3]; ok && maxBlobs == 6 {
|
||||||
|
t.Errorf("expected insert of oversized blob tx to fail: blobs=24, maxBlobs=%d, err=%v", maxBlobs, errs[0])
|
||||||
|
} else if !ok && maxBlobs == 10 {
|
||||||
|
t.Errorf("expected insert of oversized blob tx to succeed: blobs=24, maxBlobs=%d, err=%v", maxBlobs, errs[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the regular two txs are always available.
|
||||||
|
if got := pool.Get(tx1.Hash()); got == nil {
|
||||||
|
t.Errorf("expected tx %s from %s in pool", tx1.Hash(), addr1)
|
||||||
|
}
|
||||||
|
if got := pool.Get(tx2.Hash()); got == nil {
|
||||||
|
t.Errorf("expected tx %s from %s in pool", tx2.Hash(), addr2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify all the calculated pool internals. Interestingly, this is **not**
|
||||||
|
// a duplication of the above checks, this actually validates the verifier
|
||||||
|
// using the above already hard coded checks.
|
||||||
|
//
|
||||||
|
// Do not remove this, nor alter the above to be generic.
|
||||||
|
verifyPoolInternals(t, pool)
|
||||||
|
|
||||||
|
pool.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that adding transaction will correctly store it in the persistent store
|
// Tests that adding transaction will correctly store it in the persistent store
|
||||||
// and update all the indices.
|
// and update all the indices.
|
||||||
//
|
//
|
||||||
|
|
@ -1369,7 +1511,7 @@ func TestAdd(t *testing.T) {
|
||||||
defer os.RemoveAll(storage) // late defer, still ok
|
defer os.RemoveAll(storage) // late defer, still ok
|
||||||
|
|
||||||
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
|
||||||
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil)
|
store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(testMaxBlobsPerBlock), nil)
|
||||||
|
|
||||||
// Insert the seed transactions for the pool startup
|
// Insert the seed transactions for the pool startup
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rand = mrand.New(mrand.NewSource(1))
|
var rnd = mrand.New(mrand.NewSource(1))
|
||||||
|
|
||||||
// verifyHeapInternals verifies that all accounts present in the index are also
|
// verifyHeapInternals verifies that all accounts present in the index are also
|
||||||
// present in the heap and internals are consistent across various indices.
|
// present in the heap and internals are consistent across various indices.
|
||||||
|
|
@ -193,12 +193,12 @@ func benchmarkPriceHeapReinit(b *testing.B, datacap uint64) {
|
||||||
index := make(map[common.Address][]*blobTxMeta)
|
index := make(map[common.Address][]*blobTxMeta)
|
||||||
for i := 0; i < int(blobs); i++ {
|
for i := 0; i < int(blobs); i++ {
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
rand.Read(addr[:])
|
rnd.Read(addr[:])
|
||||||
|
|
||||||
var (
|
var (
|
||||||
execTip = uint256.NewInt(rand.Uint64())
|
execTip = uint256.NewInt(rnd.Uint64())
|
||||||
execFee = uint256.NewInt(rand.Uint64())
|
execFee = uint256.NewInt(rnd.Uint64())
|
||||||
blobFee = uint256.NewInt(rand.Uint64())
|
blobFee = uint256.NewInt(rnd.Uint64())
|
||||||
|
|
||||||
basefeeJumps = dynamicFeeJumps(execFee)
|
basefeeJumps = dynamicFeeJumps(execFee)
|
||||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||||
|
|
@ -218,13 +218,13 @@ func benchmarkPriceHeapReinit(b *testing.B, datacap uint64) {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
// Create a price heap and reinit it over and over
|
// Create a price heap and reinit it over and over
|
||||||
heap := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), index)
|
heap := newPriceHeap(uint256.NewInt(rnd.Uint64()), uint256.NewInt(rnd.Uint64()), index)
|
||||||
|
|
||||||
basefees := make([]*uint256.Int, b.N)
|
basefees := make([]*uint256.Int, b.N)
|
||||||
blobfees := make([]*uint256.Int, b.N)
|
blobfees := make([]*uint256.Int, b.N)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
basefees[i] = uint256.NewInt(rand.Uint64())
|
basefees[i] = uint256.NewInt(rnd.Uint64())
|
||||||
blobfees[i] = uint256.NewInt(rand.Uint64())
|
blobfees[i] = uint256.NewInt(rnd.Uint64())
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
|
|
@ -269,12 +269,12 @@ func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) {
|
||||||
index := make(map[common.Address][]*blobTxMeta)
|
index := make(map[common.Address][]*blobTxMeta)
|
||||||
for i := 0; i < int(blobs); i++ {
|
for i := 0; i < int(blobs); i++ {
|
||||||
var addr common.Address
|
var addr common.Address
|
||||||
rand.Read(addr[:])
|
rnd.Read(addr[:])
|
||||||
|
|
||||||
var (
|
var (
|
||||||
execTip = uint256.NewInt(rand.Uint64())
|
execTip = uint256.NewInt(rnd.Uint64())
|
||||||
execFee = uint256.NewInt(rand.Uint64())
|
execFee = uint256.NewInt(rnd.Uint64())
|
||||||
blobFee = uint256.NewInt(rand.Uint64())
|
blobFee = uint256.NewInt(rnd.Uint64())
|
||||||
|
|
||||||
basefeeJumps = dynamicFeeJumps(execFee)
|
basefeeJumps = dynamicFeeJumps(execFee)
|
||||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||||
|
|
@ -294,18 +294,18 @@ func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
// Create a price heap and overflow it over and over
|
// Create a price heap and overflow it over and over
|
||||||
evict := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), index)
|
evict := newPriceHeap(uint256.NewInt(rnd.Uint64()), uint256.NewInt(rnd.Uint64()), index)
|
||||||
var (
|
var (
|
||||||
addrs = make([]common.Address, b.N)
|
addrs = make([]common.Address, b.N)
|
||||||
metas = make([]*blobTxMeta, b.N)
|
metas = make([]*blobTxMeta, b.N)
|
||||||
)
|
)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
rand.Read(addrs[i][:])
|
rnd.Read(addrs[i][:])
|
||||||
|
|
||||||
var (
|
var (
|
||||||
execTip = uint256.NewInt(rand.Uint64())
|
execTip = uint256.NewInt(rnd.Uint64())
|
||||||
execFee = uint256.NewInt(rand.Uint64())
|
execFee = uint256.NewInt(rnd.Uint64())
|
||||||
blobFee = uint256.NewInt(rand.Uint64())
|
blobFee = uint256.NewInt(rnd.Uint64())
|
||||||
|
|
||||||
basefeeJumps = dynamicFeeJumps(execFee)
|
basefeeJumps = dynamicFeeJumps(execFee)
|
||||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ type limbo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLimbo opens and indexes a set of limboed blob transactions.
|
// newLimbo opens and indexes a set of limboed blob transactions.
|
||||||
func newLimbo(datadir string) (*limbo, error) {
|
func newLimbo(datadir string, maxBlobsPerTransaction uint64) (*limbo, error) {
|
||||||
l := &limbo{
|
l := &limbo{
|
||||||
index: make(map[common.Hash]uint64),
|
index: make(map[common.Hash]uint64),
|
||||||
groups: make(map[uint64]map[uint64]common.Hash),
|
groups: make(map[uint64]map[uint64]common.Hash),
|
||||||
|
|
@ -60,7 +60,7 @@ func newLimbo(datadir string) (*limbo, error) {
|
||||||
fails = append(fails, id)
|
fails = append(fails, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
store, err := billy.Open(billy.Options{Path: datadir, Repair: true}, newSlotter(), index)
|
store, err := billy.Open(billy.Options{Path: datadir, Repair: true}, newSlotter(maxBlobsPerTransaction), index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ func TestPriorityCalculation(t *testing.T) {
|
||||||
func BenchmarkDynamicFeeJumpCalculation(b *testing.B) {
|
func BenchmarkDynamicFeeJumpCalculation(b *testing.B) {
|
||||||
fees := make([]*uint256.Int, b.N)
|
fees := make([]*uint256.Int, b.N)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
fees[i] = uint256.NewInt(rand.Uint64())
|
fees[i] = uint256.NewInt(rnd.Uint64())
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
|
|
@ -76,8 +76,8 @@ func BenchmarkPriorityCalculation(b *testing.B) {
|
||||||
txBasefeeJumps := make([]float64, b.N)
|
txBasefeeJumps := make([]float64, b.N)
|
||||||
txBlobfeeJumps := make([]float64, b.N)
|
txBlobfeeJumps := make([]float64, b.N)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
txBasefeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rand.Uint64()))
|
txBasefeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rnd.Uint64()))
|
||||||
txBlobfeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rand.Uint64()))
|
txBlobfeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rnd.Uint64()))
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,13 @@ package blobpool
|
||||||
// The slotter also creates a shelf for 0-blob transactions. Whilst those are not
|
// The slotter also creates a shelf for 0-blob transactions. Whilst those are not
|
||||||
// allowed in the current protocol, having an empty shelf is not a relevant use
|
// allowed in the current protocol, having an empty shelf is not a relevant use
|
||||||
// of resources, but it makes stress testing with junk transactions simpler.
|
// of resources, but it makes stress testing with junk transactions simpler.
|
||||||
func newSlotter() func() (uint32, bool) {
|
func newSlotter(maxBlobsPerTransaction uint64) func() (uint32, bool) {
|
||||||
slotsize := uint32(txAvgSize)
|
slotsize := uint32(txAvgSize)
|
||||||
slotsize -= uint32(blobSize) // underflows, it's ok, will overflow back in the first return
|
slotsize -= uint32(blobSize) // underflows, it's ok, will overflow back in the first return
|
||||||
|
|
||||||
return func() (size uint32, done bool) {
|
return func() (size uint32, done bool) {
|
||||||
slotsize += blobSize
|
slotsize += blobSize
|
||||||
finished := slotsize > maxBlobsPerTransaction*blobSize+txMaxSize
|
finished := slotsize > uint32(maxBlobsPerTransaction)*blobSize+txMaxSize
|
||||||
|
|
||||||
return slotsize, finished
|
return slotsize, finished
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import "testing"
|
||||||
// Tests that the slotter creates the expected database shelves.
|
// Tests that the slotter creates the expected database shelves.
|
||||||
func TestNewSlotter(t *testing.T) {
|
func TestNewSlotter(t *testing.T) {
|
||||||
// Generate the database shelve sizes
|
// Generate the database shelve sizes
|
||||||
slotter := newSlotter()
|
slotter := newSlotter(6)
|
||||||
|
|
||||||
var shelves []uint32
|
var shelves []uint32
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,8 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
|
||||||
if len(hashes) == 0 {
|
if len(hashes) == 0 {
|
||||||
return errors.New("blobless blob transaction")
|
return errors.New("blobless blob transaction")
|
||||||
}
|
}
|
||||||
if len(hashes) > params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob {
|
if max := opts.Config.MaxBlobsPerBlock(head.Time); uint64(len(hashes)) > max {
|
||||||
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob)
|
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), max)
|
||||||
}
|
}
|
||||||
// Ensure commitments, proofs and hashes are valid
|
// Ensure commitments, proofs and hashes are valid
|
||||||
if err := validateBlobSidecar(hashes, sidecar); err != nil {
|
if err := validateBlobSidecar(hashes, sidecar); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,9 @@ var (
|
||||||
VerkleTime: u64(0),
|
VerkleTime: u64(0),
|
||||||
TerminalTotalDifficulty: common.Big0,
|
TerminalTotalDifficulty: common.Big0,
|
||||||
EnableVerkleAtGenesis: true,
|
EnableVerkleAtGenesis: true,
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Verkle: params.DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
// TODO uncomment when proof generation is merged
|
// TODO uncomment when proof generation is merged
|
||||||
// ProofInBlocks: true,
|
// ProofInBlocks: true,
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +82,9 @@ var (
|
||||||
VerkleTime: u64(0),
|
VerkleTime: u64(0),
|
||||||
TerminalTotalDifficulty: common.Big0,
|
TerminalTotalDifficulty: common.Big0,
|
||||||
EnableVerkleAtGenesis: true,
|
EnableVerkleAtGenesis: true,
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Verkle: params.DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -226,11 +232,11 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
var num = 2
|
var num = 2
|
||||||
for i := 1; i <= num; i++ {
|
for i := 1; i <= num; i++ {
|
||||||
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
||||||
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
|
|
||||||
chainConfig := params.MergedTestChainConfig
|
chainConfig := params.MergedTestChainConfig
|
||||||
if isVerkle {
|
if isVerkle {
|
||||||
chainConfig = testVerkleChainConfig
|
chainConfig = testVerkleChainConfig
|
||||||
}
|
}
|
||||||
|
vmContext := NewEVMBlockContext(header, nil, chainConfig, new(common.Address))
|
||||||
evm := vm.NewEVM(vmContext, statedb, chainConfig, vm.Config{})
|
evm := vm.NewEVM(vmContext, statedb, chainConfig, vm.Config{})
|
||||||
ProcessParentBlockHash(header.ParentHash, evm)
|
ProcessParentBlockHash(header.ParentHash, evm)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, state *state.StateDB, header
|
||||||
if blockCtx != nil {
|
if blockCtx != nil {
|
||||||
context = *blockCtx
|
context = *blockCtx
|
||||||
} else {
|
} else {
|
||||||
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
|
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), b.eth.BlockChain().Config(), nil)
|
||||||
}
|
}
|
||||||
return vm.NewEVM(context, state, b.ChainConfig(), *vmConfig)
|
return vm.NewEVM(context, state, b.ChainConfig(), *vmConfig)
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +356,7 @@ func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount uint64, lastB
|
||||||
|
|
||||||
func (b *EthAPIBackend) BlobBaseFee(ctx context.Context) *big.Int {
|
func (b *EthAPIBackend) BlobBaseFee(ctx context.Context) *big.Int {
|
||||||
if excess := b.CurrentHeader().ExcessBlobGas; excess != nil {
|
if excess := b.CurrentHeader().ExcessBlobGas; excess != nil {
|
||||||
return eip4844.CalcBlobFee(*excess)
|
return eip4844.CalcBlobFee(b.ChainConfig(), b.CurrentHeader())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1227,6 +1227,7 @@ func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) {
|
||||||
genesis.Config.ShanghaiTime = &time
|
genesis.Config.ShanghaiTime = &time
|
||||||
genesis.Config.CancunTime = &time
|
genesis.Config.CancunTime = &time
|
||||||
genesis.Config.PragueTime = &time
|
genesis.Config.PragueTime = &time
|
||||||
|
genesis.Config.BlobScheduleConfig = params.DefaultBlobSchedule
|
||||||
|
|
||||||
n, ethservice := startEthService(t, genesis, blocks)
|
n, ethservice := startEthService(t, genesis, blocks)
|
||||||
|
|
||||||
|
|
@ -1543,6 +1544,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
|
||||||
time := blocks[len(blocks)-1].Time() + 5
|
time := blocks[len(blocks)-1].Time() + 5
|
||||||
genesis.Config.ShanghaiTime = &time
|
genesis.Config.ShanghaiTime = &time
|
||||||
genesis.Config.CancunTime = &time
|
genesis.Config.CancunTime = &time
|
||||||
|
genesis.Config.BlobScheduleConfig = params.DefaultBlobSchedule
|
||||||
|
|
||||||
n, ethservice := startEthService(t, genesis, blocks)
|
n, ethservice := startEthService(t, genesis, blocks)
|
||||||
defer n.Close()
|
defer n.Close()
|
||||||
|
|
@ -1625,6 +1627,7 @@ func TestWitnessCreationAndConsumption(t *testing.T) {
|
||||||
timestamp := blocks[len(blocks)-2].Time() + 5
|
timestamp := blocks[len(blocks)-2].Time() + 5
|
||||||
genesis.Config.ShanghaiTime = ×tamp
|
genesis.Config.ShanghaiTime = ×tamp
|
||||||
genesis.Config.CancunTime = ×tamp
|
genesis.Config.CancunTime = ×tamp
|
||||||
|
genesis.Config.BlobScheduleConfig = params.DefaultBlobSchedule
|
||||||
|
|
||||||
n, ethservice := startEthService(t, genesis, blocks[:9])
|
n, ethservice := startEthService(t, genesis, blocks[:9])
|
||||||
defer n.Close()
|
defer n.Close()
|
||||||
|
|
|
||||||
|
|
@ -1108,7 +1108,7 @@ func TestTransactionFetcherBandwidthLimiting(t *testing.T) {
|
||||||
doTxNotify{peer: "C",
|
doTxNotify{peer: "C",
|
||||||
hashes: []common.Hash{{0x07}, {0x08}},
|
hashes: []common.Hash{{0x07}, {0x08}},
|
||||||
types: []byte{types.BlobTxType, types.BlobTxType},
|
types: []byte{types.BlobTxType, types.BlobTxType},
|
||||||
sizes: []uint32{params.MaxBlobGasPerBlock, params.MaxBlobGasPerBlock},
|
sizes: []uint32{params.BlobTxBlobGasPerBlob * 10, params.BlobTxBlobGasPerBlob * 10},
|
||||||
},
|
},
|
||||||
doWait{time: txArriveTimeout, step: true},
|
doWait{time: txArriveTimeout, step: true},
|
||||||
isWaiting(nil),
|
isWaiting(nil),
|
||||||
|
|
@ -1125,8 +1125,8 @@ func TestTransactionFetcherBandwidthLimiting(t *testing.T) {
|
||||||
{common.Hash{0x06}, types.LegacyTxType, maxTxRetrievalSize},
|
{common.Hash{0x06}, types.LegacyTxType, maxTxRetrievalSize},
|
||||||
},
|
},
|
||||||
"C": {
|
"C": {
|
||||||
{common.Hash{0x07}, types.BlobTxType, params.MaxBlobGasPerBlock},
|
{common.Hash{0x07}, types.BlobTxType, params.BlobTxBlobGasPerBlob * 10},
|
||||||
{common.Hash{0x08}, types.BlobTxType, params.MaxBlobGasPerBlock},
|
{common.Hash{0x08}, types.BlobTxType, params.BlobTxBlobGasPerBlob * 10},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fetching: map[string][]common.Hash{
|
fetching: map[string][]common.Hash{
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit ui
|
||||||
func run(ctx context.Context, call *core.Message, opts *Options) (*core.ExecutionResult, error) {
|
func run(ctx context.Context, call *core.Message, opts *Options) (*core.ExecutionResult, error) {
|
||||||
// Assemble the call and the call context
|
// Assemble the call and the call context
|
||||||
var (
|
var (
|
||||||
evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil)
|
evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, opts.Config, nil)
|
||||||
dirtyState = opts.State.Copy()
|
dirtyState = opts.State.Copy()
|
||||||
)
|
)
|
||||||
if opts.BlockOverrides != nil {
|
if opts.BlockOverrides != nil {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -97,8 +96,10 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
||||||
}
|
}
|
||||||
// Fill in blob base fee and next blob base fee.
|
// Fill in blob base fee and next blob base fee.
|
||||||
if excessBlobGas := bf.header.ExcessBlobGas; excessBlobGas != nil {
|
if excessBlobGas := bf.header.ExcessBlobGas; excessBlobGas != nil {
|
||||||
bf.results.blobBaseFee = eip4844.CalcBlobFee(*excessBlobGas)
|
bf.results.blobBaseFee = eip4844.CalcBlobFee(config, bf.header)
|
||||||
bf.results.nextBlobBaseFee = eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*excessBlobGas, *bf.header.BlobGasUsed))
|
excess := eip4844.CalcExcessBlobGas(config, bf.header)
|
||||||
|
next := &types.Header{Number: bf.header.Number, Time: bf.header.Time, ExcessBlobGas: &excess}
|
||||||
|
bf.results.nextBlobBaseFee = eip4844.CalcBlobFee(config, next)
|
||||||
} else {
|
} else {
|
||||||
bf.results.blobBaseFee = new(big.Int)
|
bf.results.blobBaseFee = new(big.Int)
|
||||||
bf.results.nextBlobBaseFee = new(big.Int)
|
bf.results.nextBlobBaseFee = new(big.Int)
|
||||||
|
|
@ -106,7 +107,7 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
||||||
// Compute gas used ratio for normal and blob gas.
|
// Compute gas used ratio for normal and blob gas.
|
||||||
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
|
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
|
||||||
if blobGasUsed := bf.header.BlobGasUsed; blobGasUsed != nil {
|
if blobGasUsed := bf.header.BlobGasUsed; blobGasUsed != nil {
|
||||||
bf.results.blobGasUsedRatio = float64(*blobGasUsed) / params.MaxBlobGasPerBlock
|
bf.results.blobGasUsedRatio = float64(*blobGasUsed) / float64(config.MaxBlobsPerBlock(bf.header.Time))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(percentiles) == 0 {
|
if len(percentiles) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pe
|
||||||
ts := gspec.Timestamp + cancunBlock.Uint64()*10 // fixed 10 sec block time in blockgen
|
ts := gspec.Timestamp + cancunBlock.Uint64()*10 // fixed 10 sec block time in blockgen
|
||||||
config.ShanghaiTime = &ts
|
config.ShanghaiTime = &ts
|
||||||
config.CancunTime = &ts
|
config.CancunTime = &ts
|
||||||
|
config.BlobScheduleConfig = params.DefaultBlobSchedule
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
|
||||||
return nil, vm.BlockContext{}, nil, nil, err
|
return nil, vm.BlockContext{}, nil, nil, err
|
||||||
}
|
}
|
||||||
// Insert parent beacon block root in the state as per EIP-4788.
|
// Insert parent beacon block root in the state as per EIP-4788.
|
||||||
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
|
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, eth.blockchain.Config(), nil)
|
||||||
evm := vm.NewEVM(context, statedb, eth.blockchain.Config(), vm.Config{})
|
evm := vm.NewEVM(context, statedb, eth.blockchain.Config(), vm.Config{})
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
||||||
for task := range taskCh {
|
for task := range taskCh {
|
||||||
var (
|
var (
|
||||||
signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time())
|
signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time())
|
||||||
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
|
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
)
|
)
|
||||||
// Trace all the transactions contained within
|
// Trace all the transactions contained within
|
||||||
for i, tx := range task.block.Transactions() {
|
for i, tx := range task.block.Transactions() {
|
||||||
|
|
@ -379,7 +379,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
||||||
}
|
}
|
||||||
// Insert block's parent beacon block root in the state
|
// Insert block's parent beacon block root in the state
|
||||||
// as per EIP-4788.
|
// as per EIP-4788.
|
||||||
context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
|
context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
evm := vm.NewEVM(context, statedb, api.backend.ChainConfig(), vm.Config{})
|
evm := vm.NewEVM(context, statedb, api.backend.ChainConfig(), vm.Config{})
|
||||||
if beaconRoot := next.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := next.BeaconRoot(); beaconRoot != nil {
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
|
|
@ -533,7 +533,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
roots []common.Hash
|
roots []common.Hash
|
||||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
||||||
chainConfig = api.backend.ChainConfig()
|
chainConfig = api.backend.ChainConfig()
|
||||||
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
||||||
)
|
)
|
||||||
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
|
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
|
||||||
|
|
@ -599,7 +599,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
}
|
}
|
||||||
defer release()
|
defer release()
|
||||||
|
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
|
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
|
|
@ -675,7 +675,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
||||||
// as the GetHash function of BlockContext is not safe for
|
// as the GetHash function of BlockContext is not safe for
|
||||||
// concurrent use.
|
// concurrent use.
|
||||||
// See: https://github.com/ethereum/go-ethereum/issues/29114
|
// See: https://github.com/ethereum/go-ethereum/issues/29114
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
res, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config)
|
res, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
|
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
|
||||||
|
|
@ -688,7 +688,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
||||||
|
|
||||||
// Feed the transactions into the tracers and return
|
// Feed the transactions into the tracers and return
|
||||||
var failed error
|
var failed error
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
|
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
|
||||||
|
|
||||||
txloop:
|
txloop:
|
||||||
|
|
@ -765,7 +765,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
dumps []string
|
dumps []string
|
||||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
||||||
chainConfig = api.backend.ChainConfig()
|
chainConfig = api.backend.ChainConfig()
|
||||||
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
canon = true
|
canon = true
|
||||||
)
|
)
|
||||||
// Check if there are any overrides: the caller may wish to enable a future
|
// Check if there are any overrides: the caller may wish to enable a future
|
||||||
|
|
@ -946,7 +946,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
}
|
}
|
||||||
defer release()
|
defer release()
|
||||||
|
|
||||||
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
|
||||||
// Apply the customization rules if required.
|
// Apply the customization rules if required.
|
||||||
if config != nil {
|
if config != nil {
|
||||||
config.BlockOverrides.Apply(&vmctx)
|
config.BlockOverrides.Apply(&vmctx)
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
|
||||||
}
|
}
|
||||||
// Recompute transactions up to the target index.
|
// Recompute transactions up to the target index.
|
||||||
signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time())
|
signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time())
|
||||||
context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
|
context := core.NewEVMBlockContext(block.Header(), b.chain, b.chainConfig, nil)
|
||||||
evm := vm.NewEVM(context, statedb, b.chainConfig, vm.Config{})
|
evm := vm.NewEVM(context, statedb, b.chainConfig, vm.Config{})
|
||||||
for idx, tx := range block.Transactions() {
|
for idx, tx := range block.Transactions() {
|
||||||
if idx == txIndex {
|
if idx == txIndex {
|
||||||
|
|
|
||||||
|
|
@ -360,6 +360,7 @@ func TestSupplySelfdestruct(t *testing.T) {
|
||||||
cancunTime := uint64(0)
|
cancunTime := uint64(0)
|
||||||
gspec.Config.ShanghaiTime = &cancunTime
|
gspec.Config.ShanghaiTime = &cancunTime
|
||||||
gspec.Config.CancunTime = &cancunTime
|
gspec.Config.CancunTime = &cancunTime
|
||||||
|
gspec.Config.BlobScheduleConfig = params.DefaultBlobSchedule
|
||||||
|
|
||||||
postCancunOutput, postCancunChain, err := testSupplyTracer(t, gspec, testBlockGenerationFunc)
|
postCancunOutput, postCancunChain, err := testSupplyTracer(t, gspec, testBlockGenerationFunc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,14 @@
|
||||||
"grayGlacierBlock": 0,
|
"grayGlacierBlock": 0,
|
||||||
"shanghaiTime": 0,
|
"shanghaiTime": 0,
|
||||||
"cancunTime": 0,
|
"cancunTime": 0,
|
||||||
"terminalTotalDifficulty": 0
|
"terminalTotalDifficulty": 0,
|
||||||
|
"blobSchedule": {
|
||||||
|
"cancun": {
|
||||||
|
"target": 3,
|
||||||
|
"max": 6,
|
||||||
|
"baseFeeUpdateFraction": 3338477
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"context": {
|
"context": {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,14 @@
|
||||||
"grayGlacierBlock": 0,
|
"grayGlacierBlock": 0,
|
||||||
"shanghaiTime": 0,
|
"shanghaiTime": 0,
|
||||||
"cancunTime": 0,
|
"cancunTime": 0,
|
||||||
"terminalTotalDifficulty": 0
|
"terminalTotalDifficulty": 0,
|
||||||
|
"blobSchedule": {
|
||||||
|
"cancun": {
|
||||||
|
"target": 3,
|
||||||
|
"max": 6,
|
||||||
|
"baseFeeUpdateFraction": 3338477
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"context": {
|
"context": {
|
||||||
|
|
@ -54,7 +61,9 @@
|
||||||
},
|
},
|
||||||
"input": "0x03f8b1820539806485174876e800825208940c2c51a0990aee1d73c1228de1586883415575088080c083020000f842a00100c9fbdf97f747e85847b4f3fff408f89c26842f77c882858bf2c89923849aa00138e3896f3c27f2389147507f8bcec52028b0efca6ee842ed83c9158873943880a0dbac3f97a532c9b00e6239b29036245a5bfbb96940b9d848634661abee98b945a03eec8525f261c2e79798f7b45a5d6ccaefa24576d53ba5023e919b86841c0675",
|
"input": "0x03f8b1820539806485174876e800825208940c2c51a0990aee1d73c1228de1586883415575088080c083020000f842a00100c9fbdf97f747e85847b4f3fff408f89c26842f77c882858bf2c89923849aa00138e3896f3c27f2389147507f8bcec52028b0efca6ee842ed83c9158873943880a0dbac3f97a532c9b00e6239b29036245a5bfbb96940b9d848634661abee98b945a03eec8525f261c2e79798f7b45a5d6ccaefa24576d53ba5023e919b86841c0675",
|
||||||
"result": {
|
"result": {
|
||||||
"0x0000000000000000000000000000000000000000": { "balance": "0x272e0528" },
|
"0x0000000000000000000000000000000000000000": {
|
||||||
|
"balance": "0x272e0528"
|
||||||
|
},
|
||||||
"0x0c2c51a0990aee1d73c1228de158688341557508": {
|
"0x0c2c51a0990aee1d73c1228de158688341557508": {
|
||||||
"balance": "0xde0b6b3a7640000"
|
"balance": "0xde0b6b3a7640000"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,19 @@
|
||||||
"shanghaiTime": 0,
|
"shanghaiTime": 0,
|
||||||
"cancunTime": 0,
|
"cancunTime": 0,
|
||||||
"pragueTime": 0,
|
"pragueTime": 0,
|
||||||
"terminalTotalDifficulty": 0
|
"terminalTotalDifficulty": 0,
|
||||||
|
"blobSchedule": {
|
||||||
|
"cancun": {
|
||||||
|
"target": 3,
|
||||||
|
"max": 6,
|
||||||
|
"baseFeeUpdateFraction": 3338477
|
||||||
|
},
|
||||||
|
"prague": {
|
||||||
|
"target": 3,
|
||||||
|
"max": 6,
|
||||||
|
"baseFeeUpdateFraction": 5007716
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"context": {
|
"context": {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
||||||
// Force-load native and js packages, to trigger registration
|
// Force-load native and js packages, to trigger registration
|
||||||
|
|
@ -53,8 +54,9 @@ func (c *callContext) toBlockContext(genesis *core.Genesis) vm.BlockContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
if genesis.ExcessBlobGas != nil && genesis.BlobGasUsed != nil {
|
if genesis.ExcessBlobGas != nil && genesis.BlobGasUsed != nil {
|
||||||
excessBlobGas := eip4844.CalcExcessBlobGas(*genesis.ExcessBlobGas, *genesis.BlobGasUsed)
|
excess := eip4844.CalcExcessBlobGas(genesis.Config, genesis.ToBlock().Header())
|
||||||
context.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
header := &types.Header{ExcessBlobGas: &excess, Number: genesis.Config.LondonBlock, Time: *genesis.Config.CancunTime}
|
||||||
|
context.BlobBaseFee = eip4844.CalcBlobFee(genesis.Config, header)
|
||||||
}
|
}
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -83,6 +84,7 @@ type supplyTracer struct {
|
||||||
delta supplyInfo
|
delta supplyInfo
|
||||||
txCallstack []supplyTxCallstack // Callstack for current transaction
|
txCallstack []supplyTxCallstack // Callstack for current transaction
|
||||||
logger *lumberjack.Logger
|
logger *lumberjack.Logger
|
||||||
|
chainConfig *params.ChainConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type supplyTracerConfig struct {
|
type supplyTracerConfig struct {
|
||||||
|
|
@ -112,14 +114,15 @@ func newSupplyTracer(cfg json.RawMessage) (*tracing.Hooks, error) {
|
||||||
logger: logger,
|
logger: logger,
|
||||||
}
|
}
|
||||||
return &tracing.Hooks{
|
return &tracing.Hooks{
|
||||||
OnBlockStart: t.onBlockStart,
|
OnBlockchainInit: t.onBlockchainInit,
|
||||||
OnBlockEnd: t.onBlockEnd,
|
OnBlockStart: t.onBlockStart,
|
||||||
OnGenesisBlock: t.onGenesisBlock,
|
OnBlockEnd: t.onBlockEnd,
|
||||||
OnTxStart: t.onTxStart,
|
OnGenesisBlock: t.onGenesisBlock,
|
||||||
OnBalanceChange: t.onBalanceChange,
|
OnTxStart: t.onTxStart,
|
||||||
OnEnter: t.onEnter,
|
OnBalanceChange: t.onBalanceChange,
|
||||||
OnExit: t.onExit,
|
OnEnter: t.onEnter,
|
||||||
OnClose: t.onClose,
|
OnExit: t.onExit,
|
||||||
|
OnClose: t.onClose,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,6 +149,10 @@ func (s *supplyTracer) resetDelta() {
|
||||||
s.delta = newSupplyInfo()
|
s.delta = newSupplyInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *supplyTracer) onBlockchainInit(chainConfig *params.ChainConfig) {
|
||||||
|
s.chainConfig = chainConfig
|
||||||
|
}
|
||||||
|
|
||||||
func (s *supplyTracer) onBlockStart(ev tracing.BlockEvent) {
|
func (s *supplyTracer) onBlockStart(ev tracing.BlockEvent) {
|
||||||
s.resetDelta()
|
s.resetDelta()
|
||||||
|
|
||||||
|
|
@ -161,8 +168,7 @@ func (s *supplyTracer) onBlockStart(ev tracing.BlockEvent) {
|
||||||
// Blob burnt gas
|
// Blob burnt gas
|
||||||
if blobGas := ev.Block.BlobGasUsed(); blobGas != nil && *blobGas > 0 && ev.Block.ExcessBlobGas() != nil {
|
if blobGas := ev.Block.BlobGasUsed(); blobGas != nil && *blobGas > 0 && ev.Block.ExcessBlobGas() != nil {
|
||||||
var (
|
var (
|
||||||
excess = *ev.Block.ExcessBlobGas()
|
baseFee = eip4844.CalcBlobFee(s.chainConfig, ev.Block.Header())
|
||||||
baseFee = eip4844.CalcBlobFee(excess)
|
|
||||||
burn = new(big.Int).Mul(new(big.Int).SetUint64(*blobGas), baseFee)
|
burn = new(big.Int).Mul(new(big.Int).SetUint64(*blobGas), baseFee)
|
||||||
)
|
)
|
||||||
s.delta.Burn.Blob = burn
|
s.delta.Burn.Blob = burn
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -65,7 +66,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var genesis = &core.Genesis{
|
var genesis = &core.Genesis{
|
||||||
Config: params.AllEthashProtocolChanges,
|
Config: params.AllDevChainProtocolChanges,
|
||||||
Alloc: types.GenesisAlloc{
|
Alloc: types.GenesisAlloc{
|
||||||
testAddr: {Balance: testBalance},
|
testAddr: {Balance: testBalance},
|
||||||
revertContractAddr: {Code: revertCode},
|
revertContractAddr: {Code: revertCode},
|
||||||
|
|
@ -136,7 +137,7 @@ func generateTestChain() []*types.Block {
|
||||||
g.AddTx(testTx2)
|
g.AddTx(testTx2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 2, generate)
|
_, blocks, _ := core.GenerateChainWithGenesis(genesis, beacon.New(ethash.NewFaker()), 2, generate)
|
||||||
return append([]*types.Block{genesis.ToBlock()}, blocks...)
|
return append([]*types.Block{genesis.ToBlock()}, blocks...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +224,7 @@ func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) {
|
||||||
if got != nil && got.Number != nil && got.Number.Sign() == 0 {
|
if got != nil && got.Number != nil && got.Number.Sign() == 0 {
|
||||||
got.Number = big.NewInt(0) // hack to make DeepEqual work
|
got.Number = big.NewInt(0) // hack to make DeepEqual work
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
if got.Hash() != tt.want.Hash() {
|
||||||
t.Fatalf("HeaderByNumber(%v) got = %v, want %v", tt.block, got, tt.want)
|
t.Fatalf("HeaderByNumber(%v) got = %v, want %v", tt.block, got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -314,7 +315,7 @@ func testChainID(t *testing.T, client *rpc.Client) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if id == nil || id.Cmp(params.AllEthashProtocolChanges.ChainID) != 0 {
|
if id == nil || id.Cmp(params.AllDevChainProtocolChanges.ChainID) != 0 {
|
||||||
t.Fatalf("ChainID returned wrong number: %+v", id)
|
t.Fatalf("ChainID returned wrong number: %+v", id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -653,7 +653,7 @@ func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.H
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *override.StateOverride, blockOverrides *override.BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *override.StateOverride, blockOverrides *override.BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
||||||
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
|
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), b.ChainConfig(), nil)
|
||||||
if blockOverrides != nil {
|
if blockOverrides != nil {
|
||||||
blockOverrides.Apply(&blockCtx)
|
blockOverrides.Apply(&blockCtx)
|
||||||
}
|
}
|
||||||
|
|
@ -1145,7 +1145,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
nonce := hexutil.Uint64(db.GetNonce(args.from()))
|
nonce := hexutil.Uint64(db.GetNonce(args.from()))
|
||||||
args.Nonce = &nonce
|
args.Nonce = &nonce
|
||||||
}
|
}
|
||||||
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
|
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), b.ChainConfig(), nil)
|
||||||
if err = args.CallDefaults(b.RPCGasCap(), blockCtx.BaseFee, b.ChainConfig().ChainID); err != nil {
|
if err = args.CallDefaults(b.RPCGasCap(), blockCtx.BaseFee, b.ChainConfig().ChainID); err != nil {
|
||||||
return nil, 0, nil, err
|
return nil, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -569,7 +569,7 @@ func (b testBackend) GetEVM(ctx context.Context, state *state.StateDB, header *t
|
||||||
if vmConfig == nil {
|
if vmConfig == nil {
|
||||||
vmConfig = b.chain.GetVMConfig()
|
vmConfig = b.chain.GetVMConfig()
|
||||||
}
|
}
|
||||||
context := core.NewEVMBlockContext(header, b.chain, nil)
|
context := core.NewEVMBlockContext(header, b.chain, b.chain.Config(), nil)
|
||||||
if blockContext != nil {
|
if blockContext != nil {
|
||||||
context = *blockContext
|
context = *blockContext
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,13 +159,11 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
if sim.chainConfig.IsCancun(header.Number, header.Time) {
|
if sim.chainConfig.IsCancun(header.Number, header.Time) {
|
||||||
var excess uint64
|
var excess uint64
|
||||||
if sim.chainConfig.IsCancun(parent.Number, parent.Time) {
|
if sim.chainConfig.IsCancun(parent.Number, parent.Time) {
|
||||||
excess = eip4844.CalcExcessBlobGas(*parent.ExcessBlobGas, *parent.BlobGasUsed)
|
excess = eip4844.CalcExcessBlobGas(sim.chainConfig, parent)
|
||||||
} else {
|
|
||||||
excess = eip4844.CalcExcessBlobGas(0, 0)
|
|
||||||
}
|
}
|
||||||
header.ExcessBlobGas = &excess
|
header.ExcessBlobGas = &excess
|
||||||
}
|
}
|
||||||
blockContext := core.NewEVMBlockContext(header, sim.newSimulatedChainContext(ctx, headers), nil)
|
blockContext := core.NewEVMBlockContext(header, sim.newSimulatedChainContext(ctx, headers), sim.chainConfig, nil)
|
||||||
if block.BlockOverrides.BlobBaseFee != nil {
|
if block.BlockOverrides.BlobBaseFee != nil {
|
||||||
blockContext.BlobBaseFee = block.BlockOverrides.BlobBaseFee.ToInt()
|
blockContext.BlobBaseFee = block.BlockOverrides.BlobBaseFee.ToInt()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,6 @@ import (
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
maxBlobsPerTransaction = params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob
|
|
||||||
)
|
|
||||||
|
|
||||||
// TransactionArgs represents the arguments to construct a new transaction
|
// TransactionArgs represents the arguments to construct a new transaction
|
||||||
// or a message call.
|
// or a message call.
|
||||||
type TransactionArgs struct {
|
type TransactionArgs struct {
|
||||||
|
|
@ -125,7 +121,8 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGas
|
||||||
if args.BlobHashes != nil && len(args.BlobHashes) == 0 {
|
if args.BlobHashes != nil && len(args.BlobHashes) == 0 {
|
||||||
return errors.New(`need at least 1 blob for a blob transaction`)
|
return errors.New(`need at least 1 blob for a blob transaction`)
|
||||||
}
|
}
|
||||||
if args.BlobHashes != nil && len(args.BlobHashes) > maxBlobsPerTransaction {
|
maxBlobsPerTransaction := b.ChainConfig().MaxBlobsPerBlock(b.CurrentHeader().Time)
|
||||||
|
if args.BlobHashes != nil && uint64(len(args.BlobHashes)) > maxBlobsPerTransaction {
|
||||||
return fmt.Errorf(`too many blobs in transaction (have=%d, max=%d)`, len(args.BlobHashes), maxBlobsPerTransaction)
|
return fmt.Errorf(`too many blobs in transaction (have=%d, max=%d)`, len(args.BlobHashes), maxBlobsPerTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,7 +188,9 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend, head
|
||||||
if args.BlobFeeCap != nil && args.BlobFeeCap.ToInt().Sign() == 0 {
|
if args.BlobFeeCap != nil && args.BlobFeeCap.ToInt().Sign() == 0 {
|
||||||
return errors.New("maxFeePerBlobGas, if specified, must be non-zero")
|
return errors.New("maxFeePerBlobGas, if specified, must be non-zero")
|
||||||
}
|
}
|
||||||
args.setCancunFeeDefaults(head)
|
if b.ChainConfig().IsCancun(head.Number, head.Time) {
|
||||||
|
args.setCancunFeeDefaults(b.ChainConfig(), head)
|
||||||
|
}
|
||||||
// If both gasPrice and at least one of the EIP-1559 fee parameters are specified, error.
|
// If both gasPrice and at least one of the EIP-1559 fee parameters are specified, error.
|
||||||
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
|
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
|
||||||
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||||
|
|
@ -243,15 +242,10 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend, head
|
||||||
}
|
}
|
||||||
|
|
||||||
// setCancunFeeDefaults fills in reasonable default fee values for unspecified fields.
|
// setCancunFeeDefaults fills in reasonable default fee values for unspecified fields.
|
||||||
func (args *TransactionArgs) setCancunFeeDefaults(head *types.Header) {
|
func (args *TransactionArgs) setCancunFeeDefaults(config *params.ChainConfig, head *types.Header) {
|
||||||
// Set maxFeePerBlobGas if it is missing.
|
// Set maxFeePerBlobGas if it is missing.
|
||||||
if args.BlobHashes != nil && args.BlobFeeCap == nil {
|
if args.BlobHashes != nil && args.BlobFeeCap == nil {
|
||||||
var excessBlobGas uint64
|
blobBaseFee := eip4844.CalcBlobFee(config, head)
|
||||||
if head.ExcessBlobGas != nil {
|
|
||||||
excessBlobGas = *head.ExcessBlobGas
|
|
||||||
}
|
|
||||||
// ExcessBlobGas must be set for a Cancun block.
|
|
||||||
blobBaseFee := eip4844.CalcBlobFee(excessBlobGas)
|
|
||||||
// Set the max fee to be 2 times larger than the previous block's blob base fee.
|
// Set the max fee to be 2 times larger than the previous block's blob base fee.
|
||||||
// The additional slack allows the tx to not become invalidated if the base
|
// The additional slack allows the tx to not become invalidated if the base
|
||||||
// fee is rising.
|
// fee is rising.
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,7 @@ func newBackendMock() *backendMock {
|
||||||
BerlinBlock: big.NewInt(0),
|
BerlinBlock: big.NewInt(0),
|
||||||
LondonBlock: big.NewInt(1000),
|
LondonBlock: big.NewInt(1000),
|
||||||
CancunTime: &cancunTime,
|
CancunTime: &cancunTime,
|
||||||
|
BlobScheduleConfig: params.DefaultBlobSchedule,
|
||||||
}
|
}
|
||||||
return &backendMock{
|
return &backendMock{
|
||||||
current: &types.Header{
|
current: &types.Header{
|
||||||
|
|
|
||||||
|
|
@ -210,10 +210,7 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
|
||||||
if miner.chainConfig.IsCancun(header.Number, header.Time) {
|
if miner.chainConfig.IsCancun(header.Number, header.Time) {
|
||||||
var excessBlobGas uint64
|
var excessBlobGas uint64
|
||||||
if miner.chainConfig.IsCancun(parent.Number, parent.Time) {
|
if miner.chainConfig.IsCancun(parent.Number, parent.Time) {
|
||||||
excessBlobGas = eip4844.CalcExcessBlobGas(*parent.ExcessBlobGas, *parent.BlobGasUsed)
|
excessBlobGas = eip4844.CalcExcessBlobGas(miner.chainConfig, parent)
|
||||||
} else {
|
|
||||||
// For the first post-fork block, both parent.data_gas_used and parent.excess_data_gas are evaluated as 0
|
|
||||||
excessBlobGas = eip4844.CalcExcessBlobGas(0, 0)
|
|
||||||
}
|
}
|
||||||
header.BlobGasUsed = new(uint64)
|
header.BlobGasUsed = new(uint64)
|
||||||
header.ExcessBlobGas = &excessBlobGas
|
header.ExcessBlobGas = &excessBlobGas
|
||||||
|
|
@ -257,7 +254,7 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
|
||||||
coinbase: coinbase,
|
coinbase: coinbase,
|
||||||
header: header,
|
header: header,
|
||||||
witness: state.Witness(),
|
witness: state.Witness(),
|
||||||
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vm.Config{}),
|
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, miner.chainConfig, &coinbase), state, miner.chainConfig, vm.Config{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,7 +281,7 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio
|
||||||
// isn't really a better place right now. The blob gas limit is checked at block validation time
|
// isn't really a better place right now. The blob gas limit is checked at block validation time
|
||||||
// and not during execution. This means core.ApplyTransaction will not return an error if the
|
// and not during execution. This means core.ApplyTransaction will not return an error if the
|
||||||
// tx has too many blobs. So we have to explicitly check it here.
|
// tx has too many blobs. So we have to explicitly check it here.
|
||||||
if (env.blobs+len(sc.Blobs))*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
|
if env.blobs+len(sc.Blobs) > int(miner.chainConfig.MaxBlobsPerBlock(env.header.Time)) {
|
||||||
return errors.New("max data blobs reached")
|
return errors.New("max data blobs reached")
|
||||||
}
|
}
|
||||||
receipt, err := miner.applyTransaction(env, tx)
|
receipt, err := miner.applyTransaction(env, tx)
|
||||||
|
|
@ -333,7 +330,7 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
|
||||||
}
|
}
|
||||||
// If we don't have enough blob space for any further blob transactions,
|
// If we don't have enough blob space for any further blob transactions,
|
||||||
// skip that list altogether
|
// skip that list altogether
|
||||||
if !blobTxs.Empty() && env.blobs*params.BlobTxBlobGasPerBlob >= params.MaxBlobGasPerBlock {
|
if !blobTxs.Empty() && env.blobs >= int(miner.chainConfig.MaxBlobsPerBlock(env.header.Time)) {
|
||||||
log.Trace("Not enough blob space for further blob transactions")
|
log.Trace("Not enough blob space for further blob transactions")
|
||||||
blobTxs.Clear()
|
blobTxs.Clear()
|
||||||
// Fall though to pick up any plain txs
|
// Fall though to pick up any plain txs
|
||||||
|
|
@ -367,11 +364,7 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
|
||||||
txs.Pop()
|
txs.Pop()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if left := uint64(params.MaxBlobGasPerBlock - env.blobs*params.BlobTxBlobGasPerBlob); left < ltx.BlobGas {
|
|
||||||
log.Trace("Not enough blob gas left for transaction", "hash", ltx.Hash, "left", left, "needed", ltx.BlobGas)
|
|
||||||
txs.Pop()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Transaction seems to fit, pull it up from the pool
|
// Transaction seems to fit, pull it up from the pool
|
||||||
tx := ltx.Resolve()
|
tx := ltx.Resolve()
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
|
|
@ -379,6 +372,18 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
|
||||||
txs.Pop()
|
txs.Pop()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Most of the blob gas logic here is agnostic as to if the chain supports
|
||||||
|
// blobs or not, however the max check panics when called on a chain without
|
||||||
|
// a defined schedule, so we need to verify it's safe to call.
|
||||||
|
if miner.chainConfig.IsCancun(env.header.Number, env.header.Time) {
|
||||||
|
if left := miner.chainConfig.MaxBlobsPerBlock(env.header.Time) - uint64(env.blobs); left < (ltx.BlobGas / params.BlobTxBlobGasPerBlob) {
|
||||||
|
log.Trace("Not enough blob space left for transaction", "hash", tx.Hash(), "left", left, "needed", ltx.BlobGas/params.BlobTxBlobGasPerBlob)
|
||||||
|
txs.Pop()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Error may be ignored here. The error has already been checked
|
// Error may be ignored here. The error has already been checked
|
||||||
// during transaction acceptance in the transaction pool.
|
// during transaction acceptance in the transaction pool.
|
||||||
from, _ := types.Sender(env.signer, tx)
|
from, _ := types.Sender(env.signer, tx)
|
||||||
|
|
@ -430,7 +435,7 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
|
||||||
filter.BaseFee = uint256.MustFromBig(env.header.BaseFee)
|
filter.BaseFee = uint256.MustFromBig(env.header.BaseFee)
|
||||||
}
|
}
|
||||||
if env.header.ExcessBlobGas != nil {
|
if env.header.ExcessBlobGas != nil {
|
||||||
filter.BlobFee = uint256.MustFromBig(eip4844.CalcBlobFee(*env.header.ExcessBlobGas))
|
filter.BlobFee = uint256.MustFromBig(eip4844.CalcBlobFee(miner.chainConfig, env.header))
|
||||||
}
|
}
|
||||||
filter.OnlyPlainTxs, filter.OnlyBlobTxs = true, false
|
filter.OnlyPlainTxs, filter.OnlyBlobTxs = true, false
|
||||||
pendingPlainTxs := miner.txpool.Pending(filter)
|
pendingPlainTxs := miner.txpool.Pending(filter)
|
||||||
|
|
|
||||||
135
params/config.go
135
params/config.go
|
|
@ -60,6 +60,9 @@ var (
|
||||||
CancunTime: newUint64(1710338135),
|
CancunTime: newUint64(1710338135),
|
||||||
DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"),
|
DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"),
|
||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
|
BlobScheduleConfig: &BlobScheduleConfig{
|
||||||
|
Cancun: DefaultCancunBlobConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
|
// HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
|
||||||
HoleskyChainConfig = &ChainConfig{
|
HoleskyChainConfig = &ChainConfig{
|
||||||
|
|
@ -84,6 +87,9 @@ var (
|
||||||
ShanghaiTime: newUint64(1696000704),
|
ShanghaiTime: newUint64(1696000704),
|
||||||
CancunTime: newUint64(1707305664),
|
CancunTime: newUint64(1707305664),
|
||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
|
BlobScheduleConfig: &BlobScheduleConfig{
|
||||||
|
Cancun: DefaultCancunBlobConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
|
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
|
||||||
SepoliaChainConfig = &ChainConfig{
|
SepoliaChainConfig = &ChainConfig{
|
||||||
|
|
@ -108,6 +114,9 @@ var (
|
||||||
ShanghaiTime: newUint64(1677557088),
|
ShanghaiTime: newUint64(1677557088),
|
||||||
CancunTime: newUint64(1706655072),
|
CancunTime: newUint64(1706655072),
|
||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
|
BlobScheduleConfig: &BlobScheduleConfig{
|
||||||
|
Cancun: DefaultCancunBlobConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
|
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
// and accepted by the Ethereum core developers into the Ethash consensus.
|
// and accepted by the Ethereum core developers into the Ethash consensus.
|
||||||
|
|
@ -157,6 +166,10 @@ var (
|
||||||
CancunTime: newUint64(0),
|
CancunTime: newUint64(0),
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
PragueTime: newUint64(0),
|
PragueTime: newUint64(0),
|
||||||
|
BlobScheduleConfig: &BlobScheduleConfig{
|
||||||
|
Cancun: DefaultCancunBlobConfig,
|
||||||
|
Prague: DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
|
|
@ -244,6 +257,10 @@ var (
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
Clique: nil,
|
Clique: nil,
|
||||||
|
BlobScheduleConfig: &BlobScheduleConfig{
|
||||||
|
Cancun: DefaultCancunBlobConfig,
|
||||||
|
Prague: DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// NonActivatedConfig defines the chain configuration without activating
|
// NonActivatedConfig defines the chain configuration without activating
|
||||||
|
|
@ -277,6 +294,26 @@ var (
|
||||||
TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
|
TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultCancunBlobConfig is the default blob configuration for the Cancun fork.
|
||||||
|
DefaultCancunBlobConfig = &BlobConfig{
|
||||||
|
Target: 3,
|
||||||
|
Max: 6,
|
||||||
|
UpdateFraction: 3338477,
|
||||||
|
}
|
||||||
|
// DefaultPragueBlobConfig is the default blob configuration for the Cancun fork.
|
||||||
|
DefaultPragueBlobConfig = &BlobConfig{
|
||||||
|
Target: 6,
|
||||||
|
Max: 9,
|
||||||
|
UpdateFraction: 5007716,
|
||||||
|
}
|
||||||
|
// DefaultBlobSchedule is the latest configured blob schedule for test chains.
|
||||||
|
DefaultBlobSchedule = &BlobScheduleConfig{
|
||||||
|
Cancun: DefaultCancunBlobConfig,
|
||||||
|
Prague: DefaultPragueBlobConfig,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// NetworkNames are user friendly names to use in the chain spec banner.
|
// NetworkNames are user friendly names to use in the chain spec banner.
|
||||||
var NetworkNames = map[string]string{
|
var NetworkNames = map[string]string{
|
||||||
MainnetChainConfig.ChainID.String(): "mainnet",
|
MainnetChainConfig.ChainID.String(): "mainnet",
|
||||||
|
|
@ -340,8 +377,9 @@ type ChainConfig struct {
|
||||||
EnableVerkleAtGenesis bool `json:"enableVerkleAtGenesis,omitempty"`
|
EnableVerkleAtGenesis bool `json:"enableVerkleAtGenesis,omitempty"`
|
||||||
|
|
||||||
// Various consensus engines
|
// Various consensus engines
|
||||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
Clique *CliqueConfig `json:"clique,omitempty"`
|
||||||
|
BlobScheduleConfig *BlobScheduleConfig `json:"blobSchedule,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
||||||
|
|
@ -438,6 +476,78 @@ func (c *ChainConfig) Description() string {
|
||||||
return banner
|
return banner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlobConfig specifies the target and max blobs per block for the associated
|
||||||
|
// fork.
|
||||||
|
type BlobConfig struct {
|
||||||
|
Target uint64 `json:"target"`
|
||||||
|
Max uint64 `json:"max"`
|
||||||
|
UpdateFraction uint64 `json:"baseFeeUpdateFraction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobScheduleConfig determines target and max number of blobs allow per fork.
|
||||||
|
type BlobScheduleConfig struct {
|
||||||
|
Cancun *BlobConfig `json:"cancun,omitempty"`
|
||||||
|
Prague *BlobConfig `json:"prague,omitempty"`
|
||||||
|
Verkle *BlobConfig `json:"verkle,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetBlobsPerBlock returns the target blobs per block associated with
|
||||||
|
// requested time.
|
||||||
|
func (c *ChainConfig) TargetBlobsPerBlock(time uint64) uint64 {
|
||||||
|
if c.BlobScheduleConfig == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
london = c.LondonBlock
|
||||||
|
s = c.BlobScheduleConfig
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case c.IsPrague(london, time) && s.Prague != nil:
|
||||||
|
return s.Prague.Target
|
||||||
|
case c.IsCancun(london, time) && s.Cancun != nil:
|
||||||
|
return s.Cancun.Target
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxBlobsPerBlock returns the max blobs per block associated with
|
||||||
|
// requested time.
|
||||||
|
func (c *ChainConfig) MaxBlobsPerBlock(time uint64) uint64 {
|
||||||
|
if c.BlobScheduleConfig == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
london = c.LondonBlock
|
||||||
|
s = c.BlobScheduleConfig
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case c.IsPrague(london, time) && s.Prague != nil:
|
||||||
|
return s.Prague.Max
|
||||||
|
case c.IsCancun(london, time) && s.Cancun != nil:
|
||||||
|
return s.Cancun.Max
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LatestMaxBlobsPerBlock returns the latest max blobs per block defined by the
|
||||||
|
// configuration, regardless of the currently active fork.
|
||||||
|
func (c *ChainConfig) LatestMaxBlobsPerBlock() uint64 {
|
||||||
|
s := c.BlobScheduleConfig
|
||||||
|
if s == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case s.Prague != nil:
|
||||||
|
return s.Prague.Max
|
||||||
|
case s.Cancun != nil:
|
||||||
|
return s.Cancun.Max
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IsHomestead returns whether num is either equal to the homestead block or greater.
|
// IsHomestead returns whether num is either equal to the homestead block or greater.
|
||||||
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
|
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
|
||||||
return isBlockForked(c.HomesteadBlock, num)
|
return isBlockForked(c.HomesteadBlock, num)
|
||||||
|
|
@ -647,6 +757,27 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
|
||||||
lastFork = cur
|
lastFork = cur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that all forks with blobs explicitly define the blob schedule
|
||||||
|
// configuration.
|
||||||
|
bsc := c.BlobScheduleConfig
|
||||||
|
if bsc == nil {
|
||||||
|
bsc = &BlobScheduleConfig{}
|
||||||
|
}
|
||||||
|
for _, cur := range []struct {
|
||||||
|
name string
|
||||||
|
timestamp *uint64
|
||||||
|
config *BlobConfig
|
||||||
|
}{
|
||||||
|
{name: "cancun", timestamp: c.CancunTime, config: bsc.Cancun},
|
||||||
|
{name: "prague", timestamp: c.PragueTime, config: bsc.Prague},
|
||||||
|
{name: "verkle", timestamp: c.VerkleTime, config: bsc.Verkle},
|
||||||
|
} {
|
||||||
|
if cur.timestamp != nil && cur.config == nil {
|
||||||
|
return fmt.Errorf("unsupported fork configuration: missing blob configuration entry for %v in schedule", cur.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,12 +170,8 @@ const (
|
||||||
BlobTxFieldElementsPerBlob = 4096 // Number of field elements stored in a single data blob
|
BlobTxFieldElementsPerBlob = 4096 // Number of field elements stored in a single data blob
|
||||||
BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
|
BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
|
||||||
BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs
|
BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs
|
||||||
BlobTxBlobGaspriceUpdateFraction = 3338477 // Controls the maximum rate of change for blob gas price
|
|
||||||
BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile.
|
BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile.
|
||||||
|
|
||||||
BlobTxTargetBlobGasPerBlock = 3 * BlobTxBlobGasPerBlob // Target consumable blob gas for data blobs per block (for 1559-like pricing)
|
|
||||||
MaxBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Maximum consumable blob gas for data blobs per block
|
|
||||||
|
|
||||||
HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935.
|
HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -334,6 +334,9 @@ var Forks = map[string]*params.ChainConfig{
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
ShanghaiTime: u64(0),
|
ShanghaiTime: u64(0),
|
||||||
CancunTime: u64(0),
|
CancunTime: u64(0),
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Cancun: params.DefaultCancunBlobConfig,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"ShanghaiToCancunAtTime15k": {
|
"ShanghaiToCancunAtTime15k": {
|
||||||
ChainID: big.NewInt(1),
|
ChainID: big.NewInt(1),
|
||||||
|
|
@ -353,6 +356,9 @@ var Forks = map[string]*params.ChainConfig{
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
ShanghaiTime: u64(0),
|
ShanghaiTime: u64(0),
|
||||||
CancunTime: u64(15_000),
|
CancunTime: u64(15_000),
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Cancun: params.DefaultCancunBlobConfig,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"Prague": {
|
"Prague": {
|
||||||
ChainID: big.NewInt(1),
|
ChainID: big.NewInt(1),
|
||||||
|
|
@ -374,6 +380,10 @@ var Forks = map[string]*params.ChainConfig{
|
||||||
CancunTime: u64(0),
|
CancunTime: u64(0),
|
||||||
PragueTime: u64(0),
|
PragueTime: u64(0),
|
||||||
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
|
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Cancun: params.DefaultCancunBlobConfig,
|
||||||
|
Prague: params.DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"CancunToPragueAtTime15k": {
|
"CancunToPragueAtTime15k": {
|
||||||
ChainID: big.NewInt(1),
|
ChainID: big.NewInt(1),
|
||||||
|
|
@ -395,6 +405,10 @@ var Forks = map[string]*params.ChainConfig{
|
||||||
CancunTime: u64(0),
|
CancunTime: u64(0),
|
||||||
PragueTime: u64(15_000),
|
PragueTime: u64(15_000),
|
||||||
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
|
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Cancun: params.DefaultCancunBlobConfig,
|
||||||
|
Prague: params.DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
||||||
|
|
||||||
// Prepare the EVM.
|
// Prepare the EVM.
|
||||||
txContext := core.NewEVMTxContext(msg)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
context := core.NewEVMBlockContext(block.Header(), nil, config, &t.json.Env.Coinbase)
|
||||||
context.GetHash = vmTestBlockHash
|
context.GetHash = vmTestBlockHash
|
||||||
context.BaseFee = baseFee
|
context.BaseFee = baseFee
|
||||||
evm := vm.NewEVM(context, state.StateDB, config, vmconfig)
|
evm := vm.NewEVM(context, state.StateDB, config, vmconfig)
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
||||||
// - the block body is verified against the header in block_validator.go:ValidateBody
|
// - the block body is verified against the header in block_validator.go:ValidateBody
|
||||||
// Here, we just do this shortcut smaller fix, since state tests do not
|
// Here, we just do this shortcut smaller fix, since state tests do not
|
||||||
// utilize those codepaths
|
// utilize those codepaths
|
||||||
if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
|
if config.IsCancun(new(big.Int), block.Time()) && uint64(len(msg.BlobHashes)) > config.MaxBlobsPerBlock(block.Time()) {
|
||||||
return st, common.Hash{}, 0, errors.New("blob gas exceeds maximum")
|
return st, common.Hash{}, 0, errors.New("blob gas exceeds maximum")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -299,7 +299,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the EVM.
|
// Prepare the EVM.
|
||||||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
context := core.NewEVMBlockContext(block.Header(), nil, config, &t.json.Env.Coinbase)
|
||||||
context.GetHash = vmTestBlockHash
|
context.GetHash = vmTestBlockHash
|
||||||
context.BaseFee = baseFee
|
context.BaseFee = baseFee
|
||||||
context.Random = nil
|
context.Random = nil
|
||||||
|
|
@ -312,8 +312,13 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
||||||
context.Difficulty = big.NewInt(0)
|
context.Difficulty = big.NewInt(0)
|
||||||
}
|
}
|
||||||
if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
|
if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
|
||||||
context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
|
header := &types.Header{
|
||||||
|
Time: block.Time(),
|
||||||
|
ExcessBlobGas: t.json.Env.ExcessBlobGas,
|
||||||
|
}
|
||||||
|
context.BlobBaseFee = eip4844.CalcBlobFee(config, header)
|
||||||
}
|
}
|
||||||
|
|
||||||
evm := vm.NewEVM(context, st.StateDB, config, vmconfig)
|
evm := vm.NewEVM(context, st.StateDB, config, vmconfig)
|
||||||
|
|
||||||
if tracer := vmconfig.Tracer; tracer != nil && tracer.OnTxStart != nil {
|
if tracer := vmconfig.Tracer; tracer != nil && tracer.OnTxStart != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue