mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-15 16:33:47 +00:00
core/txpool: reject invalid transaction in local tracker
This commit is contained in:
parent
d1fb337647
commit
05647d8126
6 changed files with 44 additions and 18 deletions
|
|
@ -1085,19 +1085,24 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
|
||||||
p.updateStorageMetrics()
|
p.updateStorageMetrics()
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateTx checks whether a transaction is valid according to the consensus
|
// ValidateTxBasics checks whether a transaction is valid according to the consensus
|
||||||
// rules and adheres to some heuristic limits of the local node (price and size).
|
// rules, but does not check state-dependent validation such as sufficient balance.
|
||||||
func (p *BlobPool) validateTx(tx *types.Transaction) error {
|
// This check is meant as an early check which only needs to be performed once,
|
||||||
// Ensure the transaction adheres to basic pool filters (type, size, tip) and
|
// and does not require the pool mutex to be held.
|
||||||
// consensus rules
|
func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error {
|
||||||
baseOpts := &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(),
|
||||||
}
|
}
|
||||||
|
return txpool.ValidateTransaction(tx, p.head, p.signer, opts)
|
||||||
|
}
|
||||||
|
|
||||||
if err := p.txValidationFn(tx, p.head, p.signer, baseOpts); err != nil {
|
// validateTx checks whether a transaction is valid according to the consensus
|
||||||
|
// rules and adheres to some heuristic limits of the local node (price and size).
|
||||||
|
func (p *BlobPool) validateTx(tx *types.Transaction) error {
|
||||||
|
if err := p.ValidateTxBasics(tx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Ensure the transaction adheres to the stateful pool filters (nonce, balance)
|
// Ensure the transaction adheres to the stateful pool filters (nonce, balance)
|
||||||
|
|
|
||||||
|
|
@ -558,11 +558,11 @@ func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address]
|
||||||
return pending
|
return pending
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateTxBasics checks whether a transaction is valid according to the consensus
|
// ValidateTxBasics checks whether a transaction is valid according to the consensus
|
||||||
// rules, but does not check state-dependent validation such as sufficient balance.
|
// rules, but does not check state-dependent validation such as sufficient balance.
|
||||||
// This check is meant as an early check which only needs to be performed once,
|
// This check is meant as an early check which only needs to be performed once,
|
||||||
// and does not require the pool mutex to be held.
|
// and does not require the pool mutex to be held.
|
||||||
func (pool *LegacyPool) validateTxBasics(tx *types.Transaction) error {
|
func (pool *LegacyPool) ValidateTxBasics(tx *types.Transaction) error {
|
||||||
opts := &txpool.ValidationOptions{
|
opts := &txpool.ValidationOptions{
|
||||||
Config: pool.chainconfig,
|
Config: pool.chainconfig,
|
||||||
Accept: 0 |
|
Accept: 0 |
|
||||||
|
|
@ -573,10 +573,7 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction) error {
|
||||||
MaxSize: txMaxSize,
|
MaxSize: txMaxSize,
|
||||||
MinTip: pool.gasTip.Load().ToBig(),
|
MinTip: pool.gasTip.Load().ToBig(),
|
||||||
}
|
}
|
||||||
if err := txpool.ValidateTransaction(tx, pool.currentHead.Load(), pool.signer, opts); err != nil {
|
return txpool.ValidateTransaction(tx, pool.currentHead.Load(), pool.signer, opts)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateTx checks whether a transaction is valid according to the consensus
|
// validateTx checks whether a transaction is valid according to the consensus
|
||||||
|
|
@ -929,7 +926,7 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error {
|
||||||
// Exclude transactions with basic errors, e.g invalid signatures and
|
// Exclude transactions with basic errors, e.g invalid signatures and
|
||||||
// insufficient intrinsic gas as soon as possible and cache senders
|
// insufficient intrinsic gas as soon as possible and cache senders
|
||||||
// in transactions before obtaining lock
|
// in transactions before obtaining lock
|
||||||
if err := pool.validateTxBasics(tx); err != nil {
|
if err := pool.ValidateTxBasics(tx); err != nil {
|
||||||
errs[i] = err
|
errs[i] = err
|
||||||
log.Trace("Discarding invalid transaction", "hash", tx.Hash(), "err", err)
|
log.Trace("Discarding invalid transaction", "hash", tx.Hash(), "err", err)
|
||||||
invalidTxMeter.Mark(1)
|
invalidTxMeter.Mark(1)
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,11 @@ func (tracker *TxTracker) TrackAll(txs []*types.Transaction) {
|
||||||
if tx.Type() == types.BlobTxType {
|
if tx.Type() == types.BlobTxType {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// Ignore the transactions which are failed for fundamental
|
||||||
|
// validation such as invalid parameters.
|
||||||
|
if tracker.pool.ValidateTxBasics(tx) != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// If we're already tracking it, it's a no-op
|
// If we're already tracking it, it's a no-op
|
||||||
if _, ok := tracker.all[tx.Hash()]; ok {
|
if _, ok := tracker.all[tx.Hash()]; ok {
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,12 @@ type SubPool interface {
|
||||||
// retrieve blobs from the pools directly instead of the network.
|
// retrieve blobs from the pools directly instead of the network.
|
||||||
GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof)
|
GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof)
|
||||||
|
|
||||||
|
// ValidateTxBasics checks whether a transaction is valid according to the consensus
|
||||||
|
// rules, but does not check state-dependent validation such as sufficient balance.
|
||||||
|
// This check is meant as a static check which can be performed without holding the
|
||||||
|
// pool mutex.
|
||||||
|
ValidateTxBasics(tx *types.Transaction) error
|
||||||
|
|
||||||
// Add enqueues a batch of transactions into the pool if they are valid. Due
|
// Add enqueues a batch of transactions into the pool if they are valid. Due
|
||||||
// to the large transaction churn, add may postpone fully integrating the tx
|
// to the large transaction churn, add may postpone fully integrating the tx
|
||||||
// to a later point to batch multiple ones together.
|
// to a later point to batch multiple ones together.
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,17 @@ func (p *TxPool) GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Pr
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateTxBasics checks whether a transaction is valid according to the consensus
|
||||||
|
// rules, but does not check state-dependent validation such as sufficient balance.
|
||||||
|
func (p *TxPool) ValidateTxBasics(tx *types.Transaction) error {
|
||||||
|
for _, subpool := range p.subpools {
|
||||||
|
if subpool.Filter(tx) {
|
||||||
|
return subpool.ValidateTxBasics(tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%w: received type %d", core.ErrTxTypeNotSupported, tx.Type())
|
||||||
|
}
|
||||||
|
|
||||||
// Add enqueues a batch of transactions into the pool if they are valid. Due
|
// Add enqueues a batch of transactions into the pool if they are valid. Due
|
||||||
// to the large transaction churn, add may postpone fully integrating the tx
|
// to the large transaction churn, add may postpone fully integrating the tx
|
||||||
// to a later point to batch multiple ones together.
|
// to a later point to batch multiple ones together.
|
||||||
|
|
|
||||||
|
|
@ -272,13 +272,15 @@ func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscri
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
||||||
if err := b.eth.txPool.Add([]*types.Transaction{signedTx}, false)[0]; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if locals := b.eth.localTxTracker; locals != nil {
|
if locals := b.eth.localTxTracker; locals != nil {
|
||||||
locals.Track(signedTx)
|
locals.Track(signedTx)
|
||||||
}
|
}
|
||||||
return nil
|
// TODO(rjl493456442): If a transaction fails stateful validation (e.g., no
|
||||||
|
// available slot), an error will be returned to the user. However, locally
|
||||||
|
// submitted transactions may be resubmitted later via the local tracker, which
|
||||||
|
// could cause confusion that a previously "rejected" transaction is later
|
||||||
|
// accepted.
|
||||||
|
return b.eth.txPool.Add([]*types.Transaction{signedTx}, false)[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
|
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue