mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 17:33:47 +00:00
core/txpool: all one tx from accounts with in-flight delegation
This commit is contained in:
parent
ffa02b82e0
commit
a15c2973a6
3 changed files with 30 additions and 25 deletions
|
|
@ -567,8 +567,9 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error {
|
||||||
if list := pool.queue[addr]; list != nil {
|
if list := pool.queue[addr]; list != nil {
|
||||||
have += list.Len()
|
have += list.Len()
|
||||||
}
|
}
|
||||||
if pool.currentState.GetCodeHash(addr) != types.EmptyCodeHash {
|
if pool.currentState.GetCodeHash(addr) != types.EmptyCodeHash || len(pool.all.auths[addr]) != 0 {
|
||||||
// Allow at most one in-flight tx for delegated accounts.
|
// Allow at most one in-flight tx for delegated accounts or those with
|
||||||
|
// a pending authorization.
|
||||||
return have, max(0, 1-have)
|
return have, max(0, 1-have)
|
||||||
}
|
}
|
||||||
return have, math.MaxInt
|
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 {
|
KnownConflicts: func(from common.Address, auths []common.Address) []common.Address {
|
||||||
var conflicts []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.
|
// Authorities cannot conflict with any pending or queued transactions.
|
||||||
for _, addr := range auths {
|
for _, addr := range auths {
|
||||||
if list := pool.pending[addr]; list != nil {
|
if list := pool.pending[addr]; list != nil {
|
||||||
|
|
|
||||||
|
|
@ -2267,24 +2267,24 @@ func TestSetCodeTransactions(t *testing.T) {
|
||||||
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
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 {
|
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",
|
name: "allow-one-tx-from-pooled-delegation",
|
||||||
pending: 1,
|
pending: 2,
|
||||||
run: func(name string) {
|
run: func(name string) {
|
||||||
// Verify C cannot originate another transaction when it has a pooled delegation.
|
// Verify C cannot originate another transaction when it has a pooled delegation.
|
||||||
if err := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{0, keyC}})); err != nil {
|
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)
|
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) {
|
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyC)); err != nil {
|
||||||
t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAuthorityReserved, err)
|
t.Fatalf("%s: failed to add with pending delegatio: %v", name, err)
|
||||||
}
|
}
|
||||||
// Also check gapped transaction is rejected.
|
// Also check gapped transaction is rejected.
|
||||||
if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAuthorityReserved) {
|
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.ErrAuthorityReserved, err)
|
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",
|
name: "track-multiple-conflicting-delegations",
|
||||||
pending: 2,
|
pending: 3,
|
||||||
run: func(name string) {
|
run: func(name string) {
|
||||||
// Send two setcode txs both with C as an authority.
|
// 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 {
|
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 {
|
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)
|
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.
|
// Make sure we can only pool one tx from keyC since it is still a
|
||||||
if err, want := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyC)), txpool.ErrAuthorityReserved; !errors.Is(err, want) {
|
// 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)
|
t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -284,15 +284,6 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op
|
||||||
return fmt.Errorf("%w: authorization conflicts with other known tx", ErrAuthorityReserved)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue