Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion core/txpool/blobpool/blobpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const (
// carry. We choose a smaller limit than the protocol-permitted MaxBlobsPerBlock
// in order to ensure network and txpool stability.
// Note: if you increase this, validation will fail on txMaxSize.
maxBlobsPerTx = params.BlobTxMaxBlobs
maxBlobsPerTx = 7

// maxTxsPerAccount is the maximum number of blob transactions admitted from
// a single account. The limit is enforced to minimize the DoS potential of
Expand Down Expand Up @@ -1102,6 +1102,11 @@ func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error {
MinTip: p.gasTip.ToBig(),
MaxBlobCount: maxBlobsPerTx,
}

if p.chain.Config().IsOsaka(p.head.Number, p.head.Time) {
opts.MaxBlobCount = params.BlobTxMaxBlobs
}

return txpool.ValidateTransaction(tx, p.head, p.signer, opts)
}

Expand Down
88 changes: 88 additions & 0 deletions core/txpool/blobpool/blobpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2036,3 +2036,91 @@ func benchmarkPoolPending(b *testing.B, datacap uint64) {
}
}
}

// TestOsakaMaxBlobsPerTx verifies that the maxBlobsPerTx parameter is dynamic
// and changes according to the Osaka hardfork activation.
func TestOsakaMaxBlobsPerTx(t *testing.T) {
var (
key, _ = crypto.GenerateKey()
addr = crypto.PubkeyToAddress(key.PublicKey)
)

statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
statedb.AddBalance(addr, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
statedb.Commit(0, true, false)

osakaTime := uint64(1)
pragueTime := uint64(0)
cancunTime := uint64(0)
config := &params.ChainConfig{
ChainID: big.NewInt(1),
LondonBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
CancunTime: &cancunTime,
PragueTime: &pragueTime,
OsakaTime: &osakaTime,
BlobScheduleConfig: &params.BlobScheduleConfig{
Cancun: params.DefaultCancunBlobConfig,
Prague: params.DefaultPragueBlobConfig,
Osaka: params.DefaultOsakaBlobConfig,
},
}

chain := &testBlockChain{
config: config,
basefee: uint256.NewInt(params.InitialBaseFee),
blobfee: uint256.NewInt(params.BlobTxMinBlobGasprice),
statedb: statedb,
}

tests := []struct {
name string
header *types.Header
numBlobs int
sidecarVer uint8
expectErr error
}{
{
name: "before Osaka, maxBlobsPerTx blobs",
header: &types.Header{Number: big.NewInt(0), Time: 0, Difficulty: common.Big0, GasLimit: 30_000_000, BaseFee: big.NewInt(int64(params.InitialBaseFee))},
numBlobs: maxBlobsPerTx,
sidecarVer: types.BlobSidecarVersion0,
expectErr: nil,
},
{
name: "after Osaka, maxBlobsPerTx blobs",
header: &types.Header{Number: big.NewInt(1), Time: 1, Difficulty: common.Big0, GasLimit: 30_000_000, BaseFee: big.NewInt(int64(params.InitialBaseFee))},
numBlobs: maxBlobsPerTx,
sidecarVer: types.BlobSidecarVersion1,
expectErr: txpool.ErrTxBlobLimitExceeded,
},
{
name: "after Osaka, BlobTxMaxBlobs blobs",
header: &types.Header{Number: big.NewInt(1), Time: 1, Difficulty: common.Big0, GasLimit: 30_000_000, BaseFee: big.NewInt(int64(params.InitialBaseFee))},
numBlobs: params.BlobTxMaxBlobs,
sidecarVer: types.BlobSidecarVersion1,
expectErr: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pool := New(Config{Datadir: t.TempDir()}, chain, nil)
if err := pool.Init(1, tt.header, newReserver()); err != nil {
t.Fatalf("failed to create blob pool: %v", err)
}
tx := makeMultiBlobTx(0, 1, 1, 1, tt.numBlobs, 0, key, tt.sidecarVer)
err := pool.add(tx)
if tt.expectErr != nil {
if !errors.Is(err, tt.expectErr) {
t.Errorf("expected error %v, got: %v", tt.expectErr, err)
}
} else {
if err != nil {
t.Errorf("expected success, got: %v", err)
}
}
pool.Close()
})
}
}
25 changes: 16 additions & 9 deletions core/txpool/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
Expand All @@ -30,11 +31,9 @@ import (
"github.com/ethereum/go-ethereum/params"
)

var (
// blobTxMinBlobGasPrice is the big.Int version of the configured protocol
// parameter to avoid constructing a new big integer for every transaction.
blobTxMinBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
)
// blobTxMinBlobGasPrice is the big.Int version of the configured protocol
// parameter to avoid constructing a new big integer for every transaction.
var blobTxMinBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)

// ValidationOptions define certain differences between transaction validation
// across the different pools without having to duplicate those checks.
Expand Down Expand Up @@ -166,19 +165,27 @@ func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationO
if len(hashes) == 0 {
return errors.New("blobless blob transaction")
}
if len(hashes) > params.BlobTxMaxBlobs {
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.BlobTxMaxBlobs)
}

if len(sidecar.Blobs) != len(hashes) {
return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes))
}
if err := sidecar.ValidateBlobCommitmentHashes(hashes); err != nil {
return err
}
// Fork-specific sidecar checks, including proof verification.
// Post-Osaka checks, Fork-specific sidecar checks, including proof verification.
if opts.Config.IsOsaka(head.Number, head.Time) {
if len(hashes) > params.BlobTxMaxBlobs {
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.BlobTxMaxBlobs)
}

return validateBlobSidecarOsaka(sidecar, hashes)
}

maxBlobs := eip4844.MaxBlobsPerBlock(opts.Config, head.Time)
if len(hashes) > maxBlobs {
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), maxBlobs)
}

return validateBlobSidecarLegacy(sidecar, hashes)
}

Expand Down
Loading