mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
feat(blobpool): add explicit max blob count limit
This commit is contained in:
parent
1f175347c4
commit
fa08c910fb
4 changed files with 79 additions and 9 deletions
|
|
@ -62,6 +62,12 @@ const (
|
||||||
// limit can never hurt.
|
// limit can never hurt.
|
||||||
txMaxSize = 1024 * 1024
|
txMaxSize = 1024 * 1024
|
||||||
|
|
||||||
|
// maxBlobsPerTx is the maximum number of blobs that a single transaction can
|
||||||
|
// 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 = 7
|
||||||
|
|
||||||
// maxTxsPerAccount is the maximum number of blob transactions admitted from
|
// maxTxsPerAccount is the maximum number of blob transactions admitted from
|
||||||
// a single account. The limit is enforced to minimize the DoS potential of
|
// a single account. The limit is enforced to minimize the DoS potential of
|
||||||
// a private tx cancelling publicly propagated blobs.
|
// a private tx cancelling publicly propagated blobs.
|
||||||
|
|
@ -1095,10 +1101,11 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
|
||||||
// and does not require the pool mutex to be held.
|
// and does not require the pool mutex to be held.
|
||||||
func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error {
|
func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error {
|
||||||
opts := &txpool.ValidationOptions{
|
opts := &txpool.ValidationOptions{
|
||||||
Config: p.chain.Config(),
|
Config: p.chain.Config(),
|
||||||
Accept: 1 << types.BlobTxType,
|
Accept: 1 << types.BlobTxType,
|
||||||
MaxSize: txMaxSize,
|
MaxSize: txMaxSize,
|
||||||
MinTip: p.gasTip.ToBig(),
|
MinTip: p.gasTip.ToBig(),
|
||||||
|
MaxBlobCount: maxBlobsPerTx,
|
||||||
}
|
}
|
||||||
return txpool.ValidateTransaction(tx, p.head, p.signer, opts)
|
return txpool.ValidateTransaction(tx, p.head, p.signer, opts)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/holiman/billy"
|
"github.com/holiman/billy"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -1142,6 +1143,63 @@ func TestChangingSlotterSize(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestBlobCountLimit tests the blobpool enforced limits on the max blob count.
|
||||||
|
func TestBlobCountLimit(t *testing.T) {
|
||||||
|
// Create a temporary folder for the persistent backend
|
||||||
|
storage := t.TempDir()
|
||||||
|
|
||||||
|
// Create transactions from a few accounts.
|
||||||
|
var (
|
||||||
|
key1, _ = crypto.GenerateKey()
|
||||||
|
key2, _ = crypto.GenerateKey()
|
||||||
|
|
||||||
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
|
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||||
|
|
||||||
|
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 7, key1)
|
||||||
|
tx2 = makeMultiBlobTx(0, 1, 800, 70, 8, key2)
|
||||||
|
)
|
||||||
|
|
||||||
|
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.Commit(0, true, false)
|
||||||
|
|
||||||
|
// Make Prague-enabled custom chain config.
|
||||||
|
cancunTime := uint64(0)
|
||||||
|
pragueTime := uint64(0)
|
||||||
|
config := ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(1),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
CancunTime: &cancunTime,
|
||||||
|
PragueTime: &pragueTime,
|
||||||
|
BlobScheduleConfig: ¶ms.BlobScheduleConfig{
|
||||||
|
Cancun: params.DefaultCancunBlobConfig,
|
||||||
|
Prague: params.DefaultPragueBlobConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
chain := &testBlockChain{
|
||||||
|
config: config,
|
||||||
|
basefee: uint256.NewInt(1050),
|
||||||
|
blobfee: uint256.NewInt(105),
|
||||||
|
statedb: statedb,
|
||||||
|
}
|
||||||
|
pool := New(Config{Datadir: storage}, chain, nil)
|
||||||
|
if err := pool.Init(1, chain.CurrentBlock(), newReserver()); err != nil {
|
||||||
|
t.Fatalf("failed to create blob pool: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to add transactions.
|
||||||
|
errs := pool.Add([]*types.Transaction{tx1, tx2}, true)
|
||||||
|
assert.Equal(t, 2, len(errs))
|
||||||
|
assert.NoError(t, errs[0])
|
||||||
|
assert.EqualError(t, errs[1], "too many blobs in transaction: have 8, permitted 7")
|
||||||
|
|
||||||
|
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.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -571,8 +571,9 @@ func (pool *LegacyPool) ValidateTxBasics(tx *types.Transaction) error {
|
||||||
1<<types.AccessListTxType |
|
1<<types.AccessListTxType |
|
||||||
1<<types.DynamicFeeTxType |
|
1<<types.DynamicFeeTxType |
|
||||||
1<<types.SetCodeTxType,
|
1<<types.SetCodeTxType,
|
||||||
MaxSize: txMaxSize,
|
MaxSize: txMaxSize,
|
||||||
MinTip: pool.gasTip.Load().ToBig(),
|
MinTip: pool.gasTip.Load().ToBig(),
|
||||||
|
MaxBlobCount: 0,
|
||||||
}
|
}
|
||||||
return txpool.ValidateTransaction(tx, pool.currentHead.Load(), pool.signer, opts)
|
return txpool.ValidateTransaction(tx, pool.currentHead.Load(), pool.signer, opts)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,10 @@ var (
|
||||||
type ValidationOptions struct {
|
type ValidationOptions struct {
|
||||||
Config *params.ChainConfig // Chain configuration to selectively validate based on current fork rules
|
Config *params.ChainConfig // Chain configuration to selectively validate based on current fork rules
|
||||||
|
|
||||||
Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool
|
Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool
|
||||||
MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle
|
MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle
|
||||||
MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool
|
MaxBlobCount int // Maximum number of blobs allowed per transaction
|
||||||
|
MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidationFunction is an method type which the pools use to perform the tx-validations which do not
|
// ValidationFunction is an method type which the pools use to perform the tx-validations which do not
|
||||||
|
|
@ -63,6 +64,9 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
|
||||||
if opts.Accept&(1<<tx.Type()) == 0 {
|
if opts.Accept&(1<<tx.Type()) == 0 {
|
||||||
return fmt.Errorf("%w: tx type %v not supported by this pool", core.ErrTxTypeNotSupported, tx.Type())
|
return fmt.Errorf("%w: tx type %v not supported by this pool", core.ErrTxTypeNotSupported, tx.Type())
|
||||||
}
|
}
|
||||||
|
if blobCount := len(tx.BlobHashes()); blobCount > opts.MaxBlobCount {
|
||||||
|
return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", blobCount, opts.MaxBlobCount)
|
||||||
|
}
|
||||||
// Before performing any expensive validations, sanity check that the tx is
|
// Before performing any expensive validations, sanity check that the tx is
|
||||||
// smaller than the maximum limit the pool can meaningfully handle
|
// smaller than the maximum limit the pool can meaningfully handle
|
||||||
if tx.Size() > opts.MaxSize {
|
if tx.Size() > opts.MaxSize {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue