mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 07:36:44 +00:00
check block number and timestamp options when filtering conditional transactions
This commit is contained in:
parent
bfede06618
commit
a106bd18f7
3 changed files with 151 additions and 13 deletions
|
|
@ -1673,7 +1673,7 @@ func (pool *LegacyPool) truncateQueue() {
|
|||
// to trigger a re-heap is this function
|
||||
func (pool *LegacyPool) demoteUnexecutables() {
|
||||
// Iterate over all accounts and demote any non-executable transactions
|
||||
gasLimit := pool.currentHead.Load().GasLimit
|
||||
currentHeader := pool.currentHead.Load()
|
||||
for addr, list := range pool.pending {
|
||||
nonce := pool.currentState.GetNonce(addr)
|
||||
|
||||
|
|
@ -1685,7 +1685,7 @@ func (pool *LegacyPool) demoteUnexecutables() {
|
|||
log.Trace("Removed old pending transaction", "hash", hash)
|
||||
}
|
||||
// Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later
|
||||
drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit)
|
||||
drops, invalids := list.Filter(pool.currentState.GetBalance(addr), currentHeader.GasLimit)
|
||||
for _, tx := range drops {
|
||||
hash := tx.Hash()
|
||||
log.Trace("Removed unpayable pending transaction", "hash", hash)
|
||||
|
|
@ -1701,7 +1701,7 @@ func (pool *LegacyPool) demoteUnexecutables() {
|
|||
pool.enqueueTx(hash, tx, false, false)
|
||||
}
|
||||
// Drop all transactions that no longer have valid TxOptions
|
||||
txConditionalsRemoved := list.FilterTxConditional(pool.currentState)
|
||||
txConditionalsRemoved := list.FilterTxConditional(pool.currentState, currentHeader)
|
||||
|
||||
for _, tx := range txConditionalsRemoved {
|
||||
hash := tx.Hash()
|
||||
|
|
|
|||
|
|
@ -531,14 +531,26 @@ func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactio
|
|||
return removed, invalids
|
||||
}
|
||||
|
||||
// FilterTxConditional returns the conditional transactions with invalid KnownAccounts
|
||||
// TODO - We will also have to check block range and time stamp range!
|
||||
func (l *list) FilterTxConditional(state *state.StateDB) types.Transactions {
|
||||
// FilterTxConditional returns the conditional transactions with invalid PIP15 options
|
||||
func (l *list) FilterTxConditional(state *state.StateDB, header *types.Header) types.Transactions {
|
||||
if state == nil || header == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
removed := l.txs.filter(func(tx *types.Transaction) bool {
|
||||
if options := tx.GetOptions(); options != nil {
|
||||
err := state.ValidateKnownAccounts(options.KnownAccounts)
|
||||
if err != nil {
|
||||
log.Error("Error while Filtering Tx Conditional", "err", err)
|
||||
if err := state.ValidateKnownAccounts(options.KnownAccounts); err != nil {
|
||||
log.Debug("Error while Filtering Tx Conditional's known accounts", "err", err)
|
||||
return true
|
||||
}
|
||||
|
||||
if err := header.ValidateBlockNumberOptionsPIP15(options.BlockNumberMin, options.BlockNumberMax); err != nil {
|
||||
log.Debug("Error while Filtering Tx Conditional's block number options", "err", err)
|
||||
return true
|
||||
}
|
||||
|
||||
if err := header.ValidateTimestampOptionsPIP15(options.TimestampMin, options.TimestampMax); err != nil {
|
||||
log.Debug("Error while Filtering Tx Conditional's timestamp options", "err", err)
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ func BenchmarkListAdd(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFilterTxConditional(t *testing.T) {
|
||||
func TestFilterTxConditionalKnownAccounts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create an in memory state db to test against.
|
||||
|
|
@ -105,6 +105,10 @@ func TestFilterTxConditional(t *testing.T) {
|
|||
db := state.NewDatabase(memDb)
|
||||
state, _ := state.New(common.Hash{}, db, nil)
|
||||
|
||||
header := &types.Header{
|
||||
Number: big.NewInt(0),
|
||||
}
|
||||
|
||||
// Create a private key to sign transactions.
|
||||
key, _ := crypto.GenerateKey()
|
||||
|
||||
|
|
@ -118,7 +122,7 @@ func TestFilterTxConditional(t *testing.T) {
|
|||
|
||||
// There should be no drops at this point.
|
||||
// No state has been modified.
|
||||
drops := list.FilterTxConditional(state)
|
||||
drops := list.FilterTxConditional(state, header)
|
||||
|
||||
count := len(drops)
|
||||
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)
|
||||
|
|
@ -151,7 +155,7 @@ func TestFilterTxConditional(t *testing.T) {
|
|||
list.Add(tx2, DefaultConfig.PriceBump)
|
||||
|
||||
// There should still be no drops as no state has been modified.
|
||||
drops = list.FilterTxConditional(state)
|
||||
drops = list.FilterTxConditional(state, header)
|
||||
|
||||
count = len(drops)
|
||||
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)
|
||||
|
|
@ -165,7 +169,129 @@ func TestFilterTxConditional(t *testing.T) {
|
|||
fmt.Println("after2", trie.Hash())
|
||||
|
||||
// tx2 should be the single transaction filtered out
|
||||
drops = list.FilterTxConditional(state)
|
||||
drops = list.FilterTxConditional(state, header)
|
||||
|
||||
count = len(drops)
|
||||
require.Equal(t, 1, count, "got %d filtered by TxOptions when there should be a single one", count)
|
||||
|
||||
require.Equal(t, tx2, drops[0], "Got %x, expected %x", drops[0].Hash(), tx2.Hash())
|
||||
}
|
||||
|
||||
func TestFilterTxConditionalBlockNumber(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create an in memory state db to test against.
|
||||
memDb := rawdb.NewMemoryDatabase()
|
||||
db := state.NewDatabase(memDb)
|
||||
state, _ := state.New(common.Hash{}, db, nil)
|
||||
|
||||
header := &types.Header{
|
||||
Number: big.NewInt(100),
|
||||
}
|
||||
|
||||
// Create a private key to sign transactions.
|
||||
key, _ := crypto.GenerateKey()
|
||||
|
||||
// Create a list.
|
||||
list := newList(true)
|
||||
|
||||
// Create a transaction with no defined tx options
|
||||
// and add to the list.
|
||||
tx := transaction(0, 1000, key)
|
||||
list.Add(tx, DefaultConfig.PriceBump)
|
||||
|
||||
// There should be no drops at this point.
|
||||
// No state has been modified.
|
||||
drops := list.FilterTxConditional(state, header)
|
||||
|
||||
count := len(drops)
|
||||
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)
|
||||
|
||||
// Create another transaction with a block number option and add to the list.
|
||||
tx2 := transaction(1, 1000, key)
|
||||
|
||||
var options types.OptionsPIP15
|
||||
|
||||
options.BlockNumberMin = big.NewInt(90)
|
||||
options.BlockNumberMax = big.NewInt(110)
|
||||
|
||||
tx2.PutOptions(&options)
|
||||
list.Add(tx2, DefaultConfig.PriceBump)
|
||||
|
||||
// There should still be no drops as no state has been modified.
|
||||
drops = list.FilterTxConditional(state, header)
|
||||
|
||||
count = len(drops)
|
||||
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)
|
||||
|
||||
// Set block number that conflicts with tx2's policy
|
||||
header.Number = big.NewInt(120)
|
||||
|
||||
// tx2 should be the single transaction filtered out
|
||||
drops = list.FilterTxConditional(state, header)
|
||||
|
||||
count = len(drops)
|
||||
require.Equal(t, 1, count, "got %d filtered by TxOptions when there should be a single one", count)
|
||||
|
||||
require.Equal(t, tx2, drops[0], "Got %x, expected %x", drops[0].Hash(), tx2.Hash())
|
||||
}
|
||||
|
||||
func TestFilterTxConditionalTimestamp(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create an in memory state db to test against.
|
||||
memDb := rawdb.NewMemoryDatabase()
|
||||
db := state.NewDatabase(memDb)
|
||||
state, _ := state.New(common.Hash{}, db, nil)
|
||||
|
||||
header := &types.Header{
|
||||
Number: big.NewInt(0),
|
||||
Time: 100,
|
||||
}
|
||||
|
||||
// Create a private key to sign transactions.
|
||||
key, _ := crypto.GenerateKey()
|
||||
|
||||
// Create a list.
|
||||
list := newList(true)
|
||||
|
||||
// Create a transaction with no defined tx options
|
||||
// and add to the list.
|
||||
tx := transaction(0, 1000, key)
|
||||
list.Add(tx, DefaultConfig.PriceBump)
|
||||
|
||||
// There should be no drops at this point.
|
||||
// No state has been modified.
|
||||
drops := list.FilterTxConditional(state, header)
|
||||
|
||||
count := len(drops)
|
||||
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)
|
||||
|
||||
// Create another transaction with a timestamp option and add to the list.
|
||||
tx2 := transaction(1, 1000, key)
|
||||
|
||||
var options types.OptionsPIP15
|
||||
|
||||
minTimestamp := uint64(90)
|
||||
maxTimestamp := uint64(110)
|
||||
|
||||
options.TimestampMin = &minTimestamp
|
||||
options.TimestampMax = &maxTimestamp
|
||||
|
||||
tx2.PutOptions(&options)
|
||||
list.Add(tx2, DefaultConfig.PriceBump)
|
||||
|
||||
// There should still be no drops as no state has been modified.
|
||||
drops = list.FilterTxConditional(state, header)
|
||||
|
||||
count = len(drops)
|
||||
require.Equal(t, 0, count, "got %d filtered by TxOptions when there should not be any", count)
|
||||
|
||||
// Set timestamp that conflicts with tx2's policy
|
||||
header.Time = 120
|
||||
|
||||
// tx2 should be the single transaction filtered out
|
||||
drops = list.FilterTxConditional(state, header)
|
||||
|
||||
count = len(drops)
|
||||
require.Equal(t, 1, count, "got %d filtered by TxOptions when there should be a single one", count)
|
||||
|
|
|
|||
Loading…
Reference in a new issue