From a15c2973a61518f3aefb72d7f3c57d8c87c61a3b Mon Sep 17 00:00:00 2001 From: lightclient Date: Fri, 7 Feb 2025 17:24:16 -0700 Subject: [PATCH] core/txpool: all one tx from accounts with in-flight delegation --- core/txpool/legacypool/legacypool.go | 9 ++---- core/txpool/legacypool/legacypool_test.go | 37 +++++++++++++++++------ core/txpool/validation.go | 9 ------ 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 5ea6761129..e025f9a73e 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -567,8 +567,9 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error { if list := pool.queue[addr]; list != nil { have += list.Len() } - if pool.currentState.GetCodeHash(addr) != types.EmptyCodeHash { - // Allow at most one in-flight tx for delegated accounts. + if pool.currentState.GetCodeHash(addr) != types.EmptyCodeHash || len(pool.all.auths[addr]) != 0 { + // Allow at most one in-flight tx for delegated accounts or those with + // a pending authorization. return have, max(0, 1-have) } return have, math.MaxInt @@ -589,10 +590,6 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error { }, KnownConflicts: func(from common.Address, auths []common.Address) []common.Address { var conflicts []common.Address - // The transaction sender cannot have an in-flight authorization. - if _, ok := pool.all.auths[from]; ok { - conflicts = append(conflicts, from) - } // Authorities cannot conflict with any pending or queued transactions. for _, addr := range auths { if list := pool.pending[addr]; list != nil { diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 06e53590b7..36945a6e59 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -2267,24 +2267,24 @@ func TestSetCodeTransactions(t *testing.T) { t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) } if err := pool.addRemoteSync(setCodeTx(0, keyB, []unsignedAuth{{1, keyC}})); err != nil { - t.Fatalf("%s: error mismatch: want %v, have %v", txpool.ErrAuthorityReserved, name, err) + t.Fatalf("%s: failed to add conflicting delegation: %v", name, err) } }, }, { - name: "reject-tx-from-pooled-delegation", - pending: 1, + name: "allow-one-tx-from-pooled-delegation", + pending: 2, run: func(name string) { // Verify C cannot originate another transaction when it has a pooled delegation. if err := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{0, keyC}})); err != nil { t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) } - if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAuthorityReserved) { - t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAuthorityReserved, err) + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyC)); err != nil { + t.Fatalf("%s: failed to add with pending delegatio: %v", name, err) } // Also check gapped transaction is rejected. - if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAuthorityReserved) { - t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAuthorityReserved, err) + if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAccountLimitExceeded) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err) } }, }, @@ -2341,7 +2341,7 @@ func TestSetCodeTransactions(t *testing.T) { }, { name: "track-multiple-conflicting-delegations", - pending: 2, + pending: 3, run: func(name string) { // Send two setcode txs both with C as an authority. if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, []unsignedAuth{{0, keyC}})); err != nil { @@ -2354,8 +2354,25 @@ func TestSetCodeTransactions(t *testing.T) { if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyA)); err != nil { t.Fatalf("%s: failed to replace with remote transaction: %v", name, err) } - // Make sure we cannot send from keyC since it is still a pending authority. - if err, want := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)), txpool.ErrAuthorityReserved; !errors.Is(err, want) { + // Make sure we can only pool one tx from keyC since it is still a + // pending authority. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)); err != nil { + t.Fatalf("%s: failed to added single pooled for account with pending delegation: %v", name, err) + } + if err, want := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1000), keyC)), txpool.ErrAccountLimitExceeded; !errors.Is(err, want) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err) + } + }, + }, + { + name: "reject-delegation-from-pending-account", + pending: 1, + run: func(name string) { + // Attempt to submit a delegation from an account with a pending tx. + if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)); err != nil { + t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err) + } + if err, want := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{1, keyC}})), txpool.ErrAuthorityReserved; !errors.Is(err, want) { t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err) } }, diff --git a/core/txpool/validation.go b/core/txpool/validation.go index cc3c3d7967..4d53c386b6 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -284,15 +284,6 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op return fmt.Errorf("%w: authorization conflicts with other known tx", ErrAuthorityReserved) } } - // Verify the every authorization's nonce is not stale. This check is expensive. - for _, auth := range tx.SetCodeAuthorizations() { - if addr, err := auth.Authority(); err == nil { - next := opts.State.GetNonce(addr) - if auth.Nonce < next { - return fmt.Errorf("%w: next nonce %d, auth nonce %d", ErrAuthorityNonceTooLow, next, auth.Nonce) - } - } - } } return nil }