Update blobpool.go

This commit is contained in:
oxBoni 2025-11-26 20:48:44 +01:00 committed by GitHub
parent 3bbf5f5b6a
commit 95d49a523d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -135,13 +135,13 @@ type blobTxMeta struct {
// newBlobTxMeta retrieves the indexed metadata fields from a blob transaction // newBlobTxMeta retrieves the indexed metadata fields from a blob transaction
// and assembles a helper struct to track in memory. // and assembles a helper struct to track in memory.
// Requires the transaction to have a sidecar (or that we introduce a special version tag for no-sidecar). // Requires the transaction to have a sidecar (or that we introduce a special version tag for no-sidecar).
func newBlobTxMeta(id uint64, size uint64, storageSize uint32, tx *types.Transaction) *blobTxMeta { func newBlobTxMeta(id uint64, size uint64, storageSize uint32, tx *types.Transaction, hash common.Hash) *blobTxMeta {
if tx.BlobTxSidecar() == nil { if tx.BlobTxSidecar() == nil {
// This should never happen, as the pool only admits blob transactions with a sidecar // This should never happen, as the pool only admits blob transactions with a sidecar
panic("missing blob tx sidecar") panic("missing blob tx sidecar")
} }
meta := &blobTxMeta{ meta := &blobTxMeta{
hash: tx.Hash(), hash: hash,
vhashes: tx.BlobHashes(), vhashes: tx.BlobHashes(),
version: tx.BlobTxSidecar().Version, version: tx.BlobTxSidecar().Version,
id: id, id: id,
@ -518,17 +518,18 @@ func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error {
log.Error("Failed to decode blob pool entry", "id", id, "err", err) log.Error("Failed to decode blob pool entry", "id", id, "err", err)
return err return err
} }
hash := tx.Hash()
if tx.BlobTxSidecar() == nil { if tx.BlobTxSidecar() == nil {
log.Error("Missing sidecar in blob pool entry", "id", id, "hash", tx.Hash()) log.Error("Missing sidecar in blob pool entry", "id", id, "hash", hash)
return errors.New("missing blob sidecar") return errors.New("missing blob sidecar")
} }
meta := newBlobTxMeta(id, tx.Size(), size, tx) meta := newBlobTxMeta(id, tx.Size(), size, tx, hash)
if p.lookup.exists(meta.hash) { if p.lookup.exists(meta.hash) {
// This path is only possible after a crash, where deleted items are not // This path is only possible after a crash, where deleted items are not
// removed via the normal shutdown-startup procedure and thus may get // removed via the normal shutdown-startup procedure and thus may get
// partially resurrected. // partially resurrected.
log.Error("Rejecting duplicate blob pool entry", "id", id, "hash", tx.Hash()) log.Error("Rejecting duplicate blob pool entry", "id", id, "hash", hash)
return errors.New("duplicate blob entry") return errors.New("duplicate blob entry")
} }
sender, err := types.Sender(p.signer, tx) sender, err := types.Sender(p.signer, tx)
@ -536,7 +537,7 @@ func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error {
// This path is impossible unless the signature validity changes across // This path is impossible unless the signature validity changes across
// restarts. For that ever improbable case, recover gracefully by ignoring // restarts. For that ever improbable case, recover gracefully by ignoring
// this data entry. // this data entry.
log.Error("Failed to recover blob tx sender", "id", id, "hash", tx.Hash(), "err", err) log.Error("Failed to recover blob tx sender", "id", id, "hash", hash, "err", err)
return err return err
} }
if _, ok := p.index[sender]; !ok { if _, ok := p.index[sender]; !ok {
@ -1125,7 +1126,8 @@ func (p *BlobPool) reorg(oldHead, newHead *types.Header) (map[common.Address][]*
from, _ := types.Sender(p.signer, tx) from, _ := types.Sender(p.signer, tx)
included[from] = append(included[from], tx) included[from] = append(included[from], tx)
inclusions[tx.Hash()] = add.NumberU64() hash := tx.Hash()
inclusions[hash] = add.NumberU64()
transactors[from] = struct{}{} transactors[from] = struct{}{}
} }
if add = p.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { if add = p.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil {
@ -1148,7 +1150,8 @@ func (p *BlobPool) reorg(oldHead, newHead *types.Header) (map[common.Address][]*
from, _ := types.Sender(p.signer, tx) from, _ := types.Sender(p.signer, tx)
included[from] = append(included[from], tx) included[from] = append(included[from], tx)
inclusions[tx.Hash()] = add.NumberU64() hash := tx.Hash()
inclusions[hash] = add.NumberU64()
transactors[from] = struct{}{} transactors[from] = struct{}{}
} }
if add = p.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { if add = p.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil {
@ -1172,7 +1175,8 @@ func (p *BlobPool) reorg(oldHead, newHead *types.Header) (map[common.Address][]*
// Update the set that was already reincluded to track the blocks in limbo // Update the set that was already reincluded to track the blocks in limbo
for _, tx := range types.TxDifference(included[addr], discarded[addr]) { for _, tx := range types.TxDifference(included[addr], discarded[addr]) {
if p.Filter(tx) { if p.Filter(tx) {
p.limbo.update(tx.Hash(), inclusions[tx.Hash()]) hash := tx.Hash()
p.limbo.update(hash, inclusions[hash])
} }
} }
} }
@ -1205,31 +1209,32 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
// 9 legacy blob transactions are allowed in a block pre-Osaka, an adversary // 9 legacy blob transactions are allowed in a block pre-Osaka, an adversary
// could theoretically halt a Geth node for ~1.2s by reorging per block. However, // could theoretically halt a Geth node for ~1.2s by reorging per block. However,
// this attack is financially inefficient to execute. // this attack is financially inefficient to execute.
hash := tx.Hash()
head := p.head.Load() head := p.head.Load()
if p.chain.Config().IsOsaka(head.Number, head.Time) && tx.BlobTxSidecar().Version == types.BlobSidecarVersion0 { if p.chain.Config().IsOsaka(head.Number, head.Time) && tx.BlobTxSidecar().Version == types.BlobSidecarVersion0 {
if err := tx.BlobTxSidecar().ToV1(); err != nil { if err := tx.BlobTxSidecar().ToV1(); err != nil {
log.Error("Failed to convert the legacy sidecar", "err", err) log.Error("Failed to convert the legacy sidecar", "err", err)
return err return err
} }
log.Info("Legacy blob transaction is reorged", "hash", tx.Hash()) log.Info("Legacy blob transaction is reorged", "hash", hash)
} }
// Serialize the transaction back into the primary datastore. // Serialize the transaction back into the primary datastore.
blob, err := rlp.EncodeToBytes(tx) blob, err := rlp.EncodeToBytes(tx)
if err != nil { if err != nil {
log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err) log.Error("Failed to encode transaction for storage", "hash", hash, "err", err)
return err return err
} }
id, err := p.store.Put(blob) id, err := p.store.Put(blob)
if err != nil { if err != nil {
log.Error("Failed to write transaction into storage", "hash", tx.Hash(), "err", err) log.Error("Failed to write transaction into storage", "hash", hash, "err", err)
return err return err
} }
// Update the indices and metrics // Update the indices and metrics
meta := newBlobTxMeta(id, tx.Size(), p.store.Size(id), tx) meta := newBlobTxMeta(id, tx.Size(), p.store.Size(id), tx, hash)
if _, ok := p.index[addr]; !ok { if _, ok := p.index[addr]; !ok {
if err := p.reserver.Hold(addr); err != nil { if err := p.reserver.Hold(addr); err != nil {
log.Warn("Failed to reserve account for blob pool", "tx", tx.Hash(), "from", addr, "err", err) log.Warn("Failed to reserve account for blob pool", "tx", hash, "from", addr, "err", err)
return err return err
} }
p.index[addr] = []*blobTxMeta{meta} p.index[addr] = []*blobTxMeta{meta}
@ -1718,9 +1723,10 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
addtimeHist.Update(time.Since(start).Nanoseconds()) addtimeHist.Update(time.Since(start).Nanoseconds())
}(time.Now()) }(time.Now())
hash := tx.Hash()
// Ensure the transaction is valid from all perspectives // Ensure the transaction is valid from all perspectives
if err := p.validateTx(tx); err != nil { if err := p.validateTx(tx); err != nil {
log.Trace("Transaction validation failed", "hash", tx.Hash(), "err", err) log.Trace("Transaction validation failed", "hash", hash, "err", err)
switch { switch {
case errors.Is(err, txpool.ErrUnderpriced): case errors.Is(err, txpool.ErrUnderpriced):
addUnderpricedMeter.Mark(1) addUnderpricedMeter.Mark(1)
@ -1765,14 +1771,14 @@ func (p *BlobPool) add(tx *types.Transaction) (err error) {
// insert it into the database and update the indices // insert it into the database and update the indices
blob, err := rlp.EncodeToBytes(tx) blob, err := rlp.EncodeToBytes(tx)
if err != nil { if err != nil {
log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err) log.Error("Failed to encode transaction for storage", "hash", hash, "err", err)
return err return err
} }
id, err := p.store.Put(blob) id, err := p.store.Put(blob)
if err != nil { if err != nil {
return err return err
} }
meta := newBlobTxMeta(id, tx.Size(), p.store.Size(id), tx) meta := newBlobTxMeta(id, tx.Size(), p.store.Size(id), tx, hash)
var ( var (
next = p.state.GetNonce(from) next = p.state.GetNonce(from)