mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 21:26:42 +00:00
txpool: activate the new max blobs per transaction post Osaka
This commit is contained in:
parent
5035064421
commit
62d7220631
3 changed files with 110 additions and 10 deletions
|
|
@ -66,7 +66,7 @@ const (
|
||||||
// carry. We choose a smaller limit than the protocol-permitted MaxBlobsPerBlock
|
// carry. We choose a smaller limit than the protocol-permitted MaxBlobsPerBlock
|
||||||
// in order to ensure network and txpool stability.
|
// in order to ensure network and txpool stability.
|
||||||
// Note: if you increase this, validation will fail on txMaxSize.
|
// 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
|
// 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
|
||||||
|
|
@ -1102,6 +1102,11 @@ func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error {
|
||||||
MinTip: p.gasTip.ToBig(),
|
MinTip: p.gasTip.ToBig(),
|
||||||
MaxBlobCount: maxBlobsPerTx,
|
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)
|
return txpool.ValidateTransaction(tx, p.head, p.signer, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 := ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(1),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
CancunTime: &cancunTime,
|
||||||
|
PragueTime: &pragueTime,
|
||||||
|
OsakaTime: &osakaTime,
|
||||||
|
BlobScheduleConfig: ¶ms.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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -30,11 +31,9 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// blobTxMinBlobGasPrice is the big.Int version of the configured protocol
|
// blobTxMinBlobGasPrice is the big.Int version of the configured protocol
|
||||||
// parameter to avoid constructing a new big integer for every transaction.
|
// parameter to avoid constructing a new big integer for every transaction.
|
||||||
blobTxMinBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
|
var blobTxMinBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
|
||||||
)
|
|
||||||
|
|
||||||
// ValidationOptions define certain differences between transaction validation
|
// ValidationOptions define certain differences between transaction validation
|
||||||
// across the different pools without having to duplicate those checks.
|
// across the different pools without having to duplicate those checks.
|
||||||
|
|
@ -166,19 +165,27 @@ func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationO
|
||||||
if len(hashes) == 0 {
|
if len(hashes) == 0 {
|
||||||
return errors.New("blobless blob transaction")
|
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) {
|
if len(sidecar.Blobs) != len(hashes) {
|
||||||
return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", 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 {
|
if err := sidecar.ValidateBlobCommitmentHashes(hashes); err != nil {
|
||||||
return err
|
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 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)
|
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)
|
return validateBlobSidecarLegacy(sidecar, hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue