From beca1a4189c4cb8b37c1867d8f7cdb262eba00b0 Mon Sep 17 00:00:00 2001 From: Roberto Bayardo Date: Fri, 20 Jan 2023 17:15:40 -0800 Subject: [PATCH] Track & enforce data gas usage in transaction pool YieldBest --- txpool/pool.go | 19 ++++++++++++++----- txpool/txpool_grpc_server.go | 4 ++-- types/txn.go | 2 ++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/txpool/pool.go b/txpool/pool.go index 2d29ce13d..11e04b102 100644 --- a/txpool/pool.go +++ b/txpool/pool.go @@ -143,6 +143,8 @@ const ( BaseFeePoolBits = EnoughFeeCapProtocol + NoNonceGaps + EnoughBalance + NotTooMuchGas QueuedPoolBits = EnoughFeeCapProtocol + + DataGasPerBlob = 1 << 17 ) type DiscardReason uint8 @@ -612,7 +614,7 @@ func (p *TxPool) IsLocal(idHash []byte) bool { func (p *TxPool) AddNewGoodPeer(peerID types.PeerID) { p.recentlyConnectedPeers.AddPeer(peerID) } func (p *TxPool) Started() bool { return p.started.Load() } -func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas uint64, toSkip mapset.Set[[32]byte]) (bool, int, error) { +func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas uint64, availableDataGas uint64, toSkip mapset.Set[[32]byte]) (bool, int, error) { // First wait for the corresponding block to arrive if p.lastSeenBlock.Load() < onTopOf { return false, 0, nil // Too early @@ -641,6 +643,13 @@ func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableG continue } + // Skip transactions that require more datagas than is available + if uint64(mt.Tx.Blobs*DataGasPerBlob) > availableDataGas { + continue + } else { + availableDataGas -= uint64(mt.Tx.Blobs) * DataGasPerBlob + } + if mt.Tx.Gas >= p.blockGasLimit.Load() { // Skip transactions with very large gas limit continue @@ -695,13 +704,13 @@ func (p *TxPool) ResetYieldedStatus() { } } -func (p *TxPool) YieldBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas uint64, toSkip mapset.Set[[32]byte]) (bool, int, error) { - return p.best(n, txs, tx, onTopOf, availableGas, toSkip) +func (p *TxPool) YieldBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas, availableDataGas uint64, toSkip mapset.Set[[32]byte]) (bool, int, error) { + return p.best(n, txs, tx, onTopOf, availableGas, availableDataGas, toSkip) } -func (p *TxPool) PeekBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas uint64) (bool, error) { +func (p *TxPool) PeekBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas, availableDataGas uint64) (bool, error) { set := mapset.NewSet[[32]byte]() - onTime, _, err := p.best(n, txs, tx, onTopOf, availableGas, set) + onTime, _, err := p.best(n, txs, tx, onTopOf, availableGas, availableDataGas, set) return onTime, err } diff --git a/txpool/txpool_grpc_server.go b/txpool/txpool_grpc_server.go index 4484ea325..1481b9b05 100644 --- a/txpool/txpool_grpc_server.go +++ b/txpool/txpool_grpc_server.go @@ -51,7 +51,7 @@ var TxPoolAPIVersion = &types2.VersionReply{Major: 1, Minor: 0, Patch: 0} type txPool interface { ValidateSerializedTxn(serializedTxn []byte) error - PeekBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas uint64) (bool, error) + PeekBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas, availableDataGas uint64) (bool, error) GetRlp(tx kv.Tx, hash []byte) ([]byte, error) AddLocalTxs(ctx context.Context, newTxs types.TxSlots, tx kv.Tx) ([]DiscardReason, error) deprecatedForEach(_ context.Context, f func(rlp, sender []byte, t SubPoolType), tx kv.Tx) @@ -155,7 +155,7 @@ func (s *GrpcServer) Pending(ctx context.Context, _ *emptypb.Empty) (*txpool_pro reply := &txpool_proto.PendingReply{} reply.Txs = make([]*txpool_proto.PendingReply_Tx, 0, 32) txSlots := types.TxsRlp{} - if _, err := s.txPool.PeekBest(math.MaxInt16, &txSlots, tx, 0 /* onTopOf */, math.MaxUint64 /* available gas */); err != nil { + if _, err := s.txPool.PeekBest(math.MaxInt16, &txSlots, tx, 0 /* onTopOf */, math.MaxUint64 /* available gas */, math.MaxUint64 /* available data gas*/); err != nil { return nil, err } var senderArr [20]byte diff --git a/types/txn.go b/types/txn.go index 506a879da..58130f00f 100644 --- a/types/txn.go +++ b/types/txn.go @@ -118,6 +118,7 @@ type TxSlot struct { IDHash [32]byte // Transaction hash for the purposes of using it as a transaction Id Traced bool // Whether transaction needs to be traced throughout transaction pool code and generate debug printing Creation bool // Set to true if "To" field of the transaction is not set + Blobs int // Set to the # of blobs contained by the transaction } const ( @@ -505,6 +506,7 @@ func (ctx *TxParseContext) ParseBlobTransaction(payload []byte, slot *TxSlot, se slot.DataNonZeroLen = tx.dataNonZeroLen slot.AlAddrCount = tx.accessListAddressCount slot.AlStorCount = tx.accessListKeyCount + slot.Blobs = tx.numBlobHashes err := tx.VerifyBlobs(payload) if err != nil {