mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 17:33:47 +00:00
core/txpool: allow same delegation in multiple txs
This commit is contained in:
parent
487fcd8528
commit
e01a04292e
2 changed files with 150 additions and 103 deletions
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
@ -209,13 +210,13 @@ type LegacyPool struct {
|
||||||
currentState *state.StateDB // Current state in the blockchain head
|
currentState *state.StateDB // Current state in the blockchain head
|
||||||
pendingNonces *noncer // Pending state tracking virtual nonces
|
pendingNonces *noncer // Pending state tracking virtual nonces
|
||||||
|
|
||||||
reserve txpool.AddressReserver // Address reserver to ensure exclusivity across subpools
|
reserve txpool.AddressReserver // Address reserver to ensure exclusivity across subpools
|
||||||
pending map[common.Address]*list // All currently processable transactions
|
pending map[common.Address]*list // All currently processable transactions
|
||||||
queue map[common.Address]*list // Queued but non-processable transactions
|
queue map[common.Address]*list // Queued but non-processable transactions
|
||||||
beats map[common.Address]time.Time // Last heartbeat from each known account
|
beats map[common.Address]time.Time // Last heartbeat from each known account
|
||||||
all *lookup // All transactions to allow lookups
|
all *lookup // All transactions to allow lookups
|
||||||
priced *pricedList // All transactions sorted by price
|
priced *pricedList // All transactions sorted by price
|
||||||
auths map[common.Address]*types.Transaction // All accounts with a pooled authorization
|
auths map[common.Address][]*types.Transaction // All accounts with a pooled authorization
|
||||||
|
|
||||||
reqResetCh chan *txpoolResetRequest
|
reqResetCh chan *txpoolResetRequest
|
||||||
reqPromoteCh chan *accountSet
|
reqPromoteCh chan *accountSet
|
||||||
|
|
@ -247,7 +248,7 @@ func New(config Config, chain BlockChain) *LegacyPool {
|
||||||
pending: make(map[common.Address]*list),
|
pending: make(map[common.Address]*list),
|
||||||
queue: make(map[common.Address]*list),
|
queue: make(map[common.Address]*list),
|
||||||
beats: make(map[common.Address]time.Time),
|
beats: make(map[common.Address]time.Time),
|
||||||
auths: make(map[common.Address]*types.Transaction),
|
auths: make(map[common.Address][]*types.Transaction),
|
||||||
all: newLookup(),
|
all: newLookup(),
|
||||||
reqResetCh: make(chan *txpoolResetRequest),
|
reqResetCh: make(chan *txpoolResetRequest),
|
||||||
reqPromoteCh: make(chan *accountSet),
|
reqPromoteCh: make(chan *accountSet),
|
||||||
|
|
@ -568,13 +569,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()
|
||||||
}
|
}
|
||||||
// Limit the number of setcode tranasactions per account
|
|
||||||
if pool.currentState.GetCode(addr) != nil {
|
if pool.currentState.GetCode(addr) != nil {
|
||||||
if have >= 1 {
|
// Allow at most one in-flight tx for delegated accounts.
|
||||||
return have, 0
|
return have, max(0, 1-have)
|
||||||
} else {
|
|
||||||
return have, 1 - have
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return have, math.MaxInt
|
return have, math.MaxInt
|
||||||
},
|
},
|
||||||
|
|
@ -592,12 +589,14 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
KnownConflicts: func(sender common.Address, addrs []common.Address) []common.Address {
|
KnownConflicts: func(from common.Address, auths []common.Address) []common.Address {
|
||||||
var conflicts []common.Address
|
var conflicts []common.Address
|
||||||
if _, ok := pool.auths[sender]; ok {
|
// The transaction sender cannot have an in-flight authorization.
|
||||||
conflicts = append(conflicts, sender)
|
if _, ok := pool.auths[from]; ok {
|
||||||
|
conflicts = append(conflicts, from)
|
||||||
}
|
}
|
||||||
for _, addr := range addrs {
|
// Authorities cannot conflict with any pending or queued transactions.
|
||||||
|
for _, addr := range auths {
|
||||||
var known bool
|
var known bool
|
||||||
if list := pool.pending[addr]; list != nil {
|
if list := pool.pending[addr]; list != nil {
|
||||||
known = true
|
known = true
|
||||||
|
|
@ -605,9 +604,6 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error {
|
||||||
if list := pool.queue[addr]; list != nil {
|
if list := pool.queue[addr]; list != nil {
|
||||||
known = true
|
known = true
|
||||||
}
|
}
|
||||||
if _, ok := pool.auths[addr]; ok {
|
|
||||||
known = true
|
|
||||||
}
|
|
||||||
if known {
|
if known {
|
||||||
conflicts = append(conflicts, addr)
|
conflicts = append(conflicts, addr)
|
||||||
}
|
}
|
||||||
|
|
@ -644,7 +640,6 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) {
|
||||||
|
|
||||||
// If the address is not yet known, request exclusivity to track the account
|
// If the address is not yet known, request exclusivity to track the account
|
||||||
// only by this subpool until all transactions are evicted
|
// only by this subpool until all transactions are evicted
|
||||||
// TODO: need to track every authority from setcode txs
|
|
||||||
var (
|
var (
|
||||||
_, hasPending = pool.pending[from]
|
_, hasPending = pool.pending[from]
|
||||||
_, hasQueued = pool.queue[from]
|
_, hasQueued = pool.queue[from]
|
||||||
|
|
@ -744,9 +739,7 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) {
|
||||||
pool.all.Add(tx)
|
pool.all.Add(tx)
|
||||||
pool.priced.Put(tx)
|
pool.priced.Put(tx)
|
||||||
pool.queueTxEvent(tx)
|
pool.queueTxEvent(tx)
|
||||||
for _, addr := range tx.Authorities() {
|
pool.addAuthorities(tx)
|
||||||
pool.auths[addr] = tx
|
|
||||||
}
|
|
||||||
log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To())
|
log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To())
|
||||||
|
|
||||||
// Successful promotion, bump the heartbeat
|
// Successful promotion, bump the heartbeat
|
||||||
|
|
@ -758,9 +751,7 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
for _, addr := range tx.Authorities() {
|
pool.addAuthorities(tx)
|
||||||
pool.auths[addr] = tx
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To())
|
log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To())
|
||||||
return replaced, nil
|
return replaced, nil
|
||||||
|
|
@ -828,10 +819,7 @@ func (pool *LegacyPool) enqueueTx(hash common.Hash, tx *types.Transaction, addAl
|
||||||
if _, exist := pool.beats[from]; !exist {
|
if _, exist := pool.beats[from]; !exist {
|
||||||
pool.beats[from] = time.Now()
|
pool.beats[from] = time.Now()
|
||||||
}
|
}
|
||||||
for _, auth := range tx.SetCodeAuthorizations() {
|
pool.addAuthorities(tx)
|
||||||
addr, _ := auth.Authority()
|
|
||||||
pool.auths[addr] = tx
|
|
||||||
}
|
|
||||||
return old != nil, nil
|
return old != nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1086,9 +1074,40 @@ func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bo
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addAuthorities tracks the supplied tx in relation to each authority it
|
||||||
|
// specifies.
|
||||||
|
func (pool *LegacyPool) addAuthorities(tx *types.Transaction) {
|
||||||
|
for _, addr := range tx.Authorities() {
|
||||||
|
list, ok := pool.auths[addr]
|
||||||
|
if !ok {
|
||||||
|
list = []*types.Transaction{}
|
||||||
|
}
|
||||||
|
if slices.Contains(list, tx) {
|
||||||
|
// Don't add duplicates.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
list = append(list, tx)
|
||||||
|
pool.auths[addr] = list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeAuthorities stops tracking the supplied tx in relation to its
|
||||||
|
// authorities.
|
||||||
func (pool *LegacyPool) removeAuthorities(tx *types.Transaction) {
|
func (pool *LegacyPool) removeAuthorities(tx *types.Transaction) {
|
||||||
for _, addr := range tx.Authorities() {
|
for _, addr := range tx.Authorities() {
|
||||||
delete(pool.auths, addr)
|
// Remove tx from tracker.
|
||||||
|
list := pool.auths[addr]
|
||||||
|
if i := slices.Index(list, tx); i >= 0 {
|
||||||
|
list = append(list[:i], list[i+1:]...)
|
||||||
|
} else {
|
||||||
|
log.Error("Authority with untracked tx", "addr", addr, "hash", tx.Hash())
|
||||||
|
}
|
||||||
|
if len(list) == 0 {
|
||||||
|
// If list is newly empty, delete it entirely.
|
||||||
|
delete(pool.auths, addr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pool.auths[addr] = list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1823,5 +1842,5 @@ func (pool *LegacyPool) Clear() {
|
||||||
pool.pending = make(map[common.Address]*list)
|
pool.pending = make(map[common.Address]*list)
|
||||||
pool.queue = make(map[common.Address]*list)
|
pool.queue = make(map[common.Address]*list)
|
||||||
pool.pendingNonces = newNoncer(pool.currentState)
|
pool.pendingNonces = newNoncer(pool.currentState)
|
||||||
pool.auths = make(map[common.Address]*types.Transaction)
|
pool.auths = make(map[common.Address][]*types.Transaction)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2212,13 +2212,17 @@ func TestSetCodeTransactions(t *testing.T) {
|
||||||
defer pool.Close()
|
defer pool.Close()
|
||||||
|
|
||||||
// Create the test accounts
|
// Create the test accounts
|
||||||
keys := make([]*ecdsa.PrivateKey, 4)
|
var (
|
||||||
addrs := make([]common.Address, len(keys))
|
keyA, _ = crypto.GenerateKey()
|
||||||
for i := 0; i < len(keys); i++ {
|
keyB, _ = crypto.GenerateKey()
|
||||||
keys[i], _ = crypto.GenerateKey()
|
keyC, _ = crypto.GenerateKey()
|
||||||
addrs[i] = crypto.PubkeyToAddress(keys[i].PublicKey)
|
addrA = crypto.PubkeyToAddress(keyA.PublicKey)
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(params.Ether))
|
addrB = crypto.PubkeyToAddress(keyB.PublicKey)
|
||||||
}
|
addrC = crypto.PubkeyToAddress(keyC.PublicKey)
|
||||||
|
)
|
||||||
|
testAddBalance(pool, addrA, big.NewInt(params.Ether))
|
||||||
|
testAddBalance(pool, addrB, big.NewInt(params.Ether))
|
||||||
|
testAddBalance(pool, addrC, big.NewInt(params.Ether))
|
||||||
|
|
||||||
// A few situations to test:
|
// A few situations to test:
|
||||||
// 1. Accounts with delegation set can only have one in-flight transaction.
|
// 1. Accounts with delegation set can only have one in-flight transaction.
|
||||||
|
|
@ -2237,106 +2241,140 @@ func TestSetCodeTransactions(t *testing.T) {
|
||||||
name string
|
name string
|
||||||
pending int
|
pending int
|
||||||
queued int
|
queued int
|
||||||
run func() error
|
run func(string)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
// Check that only one in-flight transaction is allowed for accounts
|
||||||
|
// with delegation set. Also verify the accepted transaction can be
|
||||||
|
// replaced by fee.
|
||||||
name: "only-one-in-flight",
|
name: "only-one-in-flight",
|
||||||
pending: 1,
|
pending: 1,
|
||||||
run: func() error {
|
run: func(name string) {
|
||||||
// Check that only one in-flight transaction is allowed for accounts
|
|
||||||
// with delegation set. Also verify the accepted transaction can be
|
|
||||||
// replaced by fee.
|
|
||||||
aa := common.Address{0xaa, 0xaa}
|
aa := common.Address{0xaa, 0xaa}
|
||||||
statedb.SetCode(addrs[0], append(types.DelegationPrefix, aa.Bytes()...))
|
statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...))
|
||||||
statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)})
|
statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)})
|
||||||
// Send transactions. First is accepted, second is rejected.
|
// Send transactions. First is accepted, second is rejected.
|
||||||
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keys[0])); err != nil {
|
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyA)); err != nil {
|
||||||
return fmt.Errorf("failed to add remote transaction: %v", err)
|
t.Fatalf("%s: failed to add remote transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); !errors.Is(err, txpool.ErrAccountLimitExceeded) {
|
if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) {
|
||||||
return fmt.Errorf("error mismatch: want %v, have %v", txpool.ErrAccountLimitExceeded, err)
|
t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err)
|
||||||
}
|
}
|
||||||
// Also check gapped transaction.
|
// Also check gapped transaction.
|
||||||
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keys[0])); !errors.Is(err, txpool.ErrAccountLimitExceeded) {
|
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, txpool.ErrAccountLimitExceeded) {
|
||||||
return fmt.Errorf("error mismatch: want %v, have %v", txpool.ErrAccountLimitExceeded, err)
|
t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAccountLimitExceeded, err)
|
||||||
}
|
}
|
||||||
// Replace by fee.
|
// Replace by fee.
|
||||||
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(10), keys[0])); err != nil {
|
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(10), keyA)); err != nil {
|
||||||
return fmt.Errorf("failed to replace with remote transaction: %v", err)
|
t.Fatalf("%s: failed to replace with remote transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reject-setcode-tx-with-pending-authority-tx",
|
name: "allow-setcode-tx-with-pending-authority-tx",
|
||||||
pending: 1,
|
pending: 2,
|
||||||
run: func() error {
|
run: func(name string) {
|
||||||
// Send two transactions where the first has no conflicting delegations and
|
// Send two transactions where the first has no conflicting delegations and
|
||||||
// the second should be rejected due to a conflict with the tx sent in 1).
|
// the second should be allowed despite conflicting with the authorities in 1).
|
||||||
if err := pool.addRemoteSync(setCodeTx(0, keys[1], []unsignedAuth{{1, keys[2]}})); err != nil {
|
if err := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{1, keyC}})); err != nil {
|
||||||
return fmt.Errorf("failed to add with remote setcode transaction: %v", err)
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
if err := pool.addRemoteSync(setCodeTx(1, keys[1], []unsignedAuth{{1, keys[2]}})); !errors.Is(err, txpool.ErrAuthorityReserved) {
|
if err := pool.addRemoteSync(setCodeTx(0, keyB, []unsignedAuth{{1, keyC}})); err != nil {
|
||||||
return fmt.Errorf("error mismatch: want %v, have %v", txpool.ErrAuthorityReserved, err)
|
t.Fatalf("%s: error mismatch: want %v, have %v", txpool.ErrAuthorityReserved, name, err)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reject-tx-from-pooled-delegation",
|
name: "reject-tx-from-pooled-delegation",
|
||||||
pending: 1,
|
pending: 1,
|
||||||
run: func() error {
|
run: func(name string) {
|
||||||
// Verify key[2] 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, keys[0], []unsignedAuth{{0, keys[2]}})); err != nil {
|
if err := pool.addRemoteSync(setCodeTx(0, keyA, []unsignedAuth{{0, keyC}})); err != nil {
|
||||||
return fmt.Errorf("failed to add with remote setcode transaction: %v", err)
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keys[2])); !errors.Is(err, txpool.ErrAuthorityReserved) {
|
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAuthorityReserved) {
|
||||||
return fmt.Errorf("error mismatch: want %v, have %v", txpool.ErrAuthorityReserved, err)
|
t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAuthorityReserved, err)
|
||||||
}
|
}
|
||||||
// Also check gapped transaction is rejected.
|
// Also check gapped transaction is rejected.
|
||||||
if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keys[2])); !errors.Is(err, txpool.ErrAuthorityReserved) {
|
if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyC)); !errors.Is(err, txpool.ErrAuthorityReserved) {
|
||||||
return fmt.Errorf("error mismatch: want %v, have %v", txpool.ErrAuthorityReserved, err)
|
t.Fatalf("%s: error mismatch: want %v, have %v", name, txpool.ErrAuthorityReserved, err)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "replace-by-fee-setcode-tx",
|
name: "replace-by-fee-setcode-tx",
|
||||||
pending: 1,
|
pending: 1,
|
||||||
run: func() error {
|
run: func(name string) {
|
||||||
// 4. Fee bump the setcode tx send.
|
// 4. Fee bump the setcode tx send.
|
||||||
if err := pool.addRemoteSync(setCodeTx(0, keys[1], []unsignedAuth{{1, keys[2]}})); err != nil {
|
if err := pool.addRemoteSync(setCodeTx(0, keyB, []unsignedAuth{{1, keyC}})); err != nil {
|
||||||
return fmt.Errorf("failed to add with remote setcode transaction: %v", err)
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(2000), uint256.NewInt(2), keys[1], []unsignedAuth{{0, keys[2]}})); err != nil {
|
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(2000), uint256.NewInt(2), keyB, []unsignedAuth{{0, keyC}})); err != nil {
|
||||||
t.Fatalf("failed to add with remote setcode transaction: %v", err)
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "allow-tx-from-replaced-authority",
|
name: "allow-tx-from-replaced-authority",
|
||||||
pending: 2,
|
pending: 2,
|
||||||
run: func() error {
|
run: func(name string) {
|
||||||
// Fee bump with a different auth list. Make sure that unlocks the authorities.
|
// Fee bump with a different auth list. Make sure that unlocks the authorities.
|
||||||
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keys[0], []unsignedAuth{{0, keys[1]}})); err != nil {
|
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, []unsignedAuth{{0, keyB}})); err != nil {
|
||||||
t.Fatalf("failed to add with remote setcode transaction: %v", err)
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(3000), uint256.NewInt(300), keys[0], []unsignedAuth{{0, keys[2]}})); err != nil {
|
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(3000), uint256.NewInt(300), keyA, []unsignedAuth{{0, keyC}})); err != nil {
|
||||||
t.Fatalf("failed to add with remote setcode transaction: %v", err)
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
}
|
}
|
||||||
fmt.Println(pool.auths)
|
// Now send a regular tx from B.
|
||||||
// Now send a regular tx from keys[1].
|
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(10), keyB)); err != nil {
|
||||||
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(10), keys[1])); err != nil {
|
t.Fatalf("%s: failed to replace with remote transaction: %v", name, err)
|
||||||
t.Fatalf("failed to replace with remote transaction: %v", err)
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "allow-tx-from-replaced-self-sponsor-authority",
|
||||||
|
pending: 2,
|
||||||
|
run: func(name string) {
|
||||||
|
//
|
||||||
|
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(10), uint256.NewInt(3), keyA, []unsignedAuth{{0, keyA}})); err != nil {
|
||||||
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
|
}
|
||||||
|
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(30), uint256.NewInt(30), keyA, []unsignedAuth{{0, keyB}})); err != nil {
|
||||||
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
|
}
|
||||||
|
// Now send a regular tx from keyA.
|
||||||
|
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 can still send from keyB.
|
||||||
|
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1000), keyB)); err != nil {
|
||||||
|
t.Fatalf("%s: failed to replace with remote transaction: %v", name, err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "track-multiple-conflicting-delegations",
|
||||||
|
pending: 2,
|
||||||
|
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 {
|
||||||
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
|
}
|
||||||
|
if err := pool.addRemoteSync(pricedSetCodeTx(0, 250000, uint256.NewInt(30), uint256.NewInt(30), keyB, []unsignedAuth{{0, keyC}})); err != nil {
|
||||||
|
t.Fatalf("%s: failed to add with remote setcode transaction: %v", name, err)
|
||||||
|
}
|
||||||
|
// Replace the tx from A with a non-setcode tx.
|
||||||
|
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) {
|
||||||
|
t.Fatalf("%s: error mismatch: want %v, have %v", name, want, err)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
if err := tt.run(); err != nil {
|
tt.run(tt.name)
|
||||||
t.Fatalf("%s: %v", tt.name, err)
|
|
||||||
}
|
|
||||||
pending, queued := pool.Stats()
|
pending, queued := pool.Stats()
|
||||||
if pending != tt.pending {
|
if pending != tt.pending {
|
||||||
t.Fatalf("%s: pending transactions mismatched: have %d, want %d", tt.name, pending, tt.pending)
|
t.Fatalf("%s: pending transactions mismatched: have %d, want %d", tt.name, pending, tt.pending)
|
||||||
|
|
@ -2349,16 +2387,6 @@ func TestSetCodeTransactions(t *testing.T) {
|
||||||
}
|
}
|
||||||
pool.Clear()
|
pool.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
pool.Clear()
|
|
||||||
|
|
||||||
|
|
||||||
// if err := pool.addRemoteSync(setCodeTx(1, keys[3], []unsignedAuth{{1, keys[2]}})); !errors.Is(err, txpool.ErrAuthorityReserved) {
|
|
||||||
// t.Fatalf("expected to reject tx from in-flight authority: want %v, have %v", txpool.ErrAuthorityReserved, err)
|
|
||||||
// }
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmarks the speed of validating the contents of the pending queue of the
|
// Benchmarks the speed of validating the contents of the pending queue of the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue