Skip to content

Commit

Permalink
Transaction filter (#5)
Browse files Browse the repository at this point in the history
* tx filter

* change TxFilter type

* basic filters

* lint

* fixup

* Missing lock acquisition

* fixup

* lint

* fixup

* add filter priority order

* lint

* fixup

* save: use insertion queue

* filter-as-an-option

* fmt

* fixup

* pointer filter

* fixup

* fieldalignment
  • Loading branch information
notJoon authored Apr 8, 2024
1 parent 4518663 commit 2a70d0e
Show file tree
Hide file tree
Showing 3 changed files with 428 additions and 0 deletions.
107 changes: 107 additions & 0 deletions serve/filters/filter/tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package filter

import (
"github.com/gnolang/gno/tm2/pkg/bft/types"
)

type Options struct {
GasUsed struct{ Min, Max *int64 }
GasWanted struct{ Min, Max *int64 }
GasLimit struct{ Min, Max *int64 }
}

// TxFilter holds a slice of transaction results.
// It provides methods to manipulate and query the transactions.
type TxFilter struct {
opts Options
*baseFilter
txs []*types.TxResult
}

// NewTxFilter creates a new TxFilter object.
func NewTxFilter(opts Options) *TxFilter {
return &TxFilter{
baseFilter: newBaseFilter(TxFilterType),
txs: make([]*types.TxResult, 0),
opts: opts,
}
}

// GetHashes iterates over all transactions in the filter and returns their hashes.
func (tf *TxFilter) GetHashes() [][]byte {
tf.Lock()
defer tf.Unlock()

hashes := make([][]byte, 0, len(tf.txs))

for _, txr := range tf.txs {
var hash []byte

if txr != nil && txr.Tx != nil {
hash = txr.Tx.Hash()
}

hashes = append(hashes, hash)
}

return hashes
}

func (tf *TxFilter) UpdateWithTx(tx *types.TxResult) {
tf.Lock()
defer tf.Unlock()

tf.txs = append(tf.txs, tx)
}

// Apply applies all added conditions to the transactions in the filter.
//
// It returns a slice of `TxResult` that satisfy all the conditions. If no conditions are set,
// it returns all transactions in the filter. Also, if the filter value is invalid filter will not
// be applied.
func (tf *TxFilter) Apply() []*types.TxResult {
tf.Lock()
defer tf.Unlock()

return checkOpts(tf.txs, tf.opts)
}

func checkOpts(txs []*types.TxResult, opts Options) []*types.TxResult {
filtered := make([]*types.TxResult, 0, len(txs))

for _, tx := range txs {
if checkFilterCondition(tx, opts) {
filtered = append(filtered, tx)
}
}

return filtered
}

func checkFilterCondition(tx *types.TxResult, opts Options) bool {
if opts.GasLimit.Max != nil && tx.Response.GasUsed > *opts.GasLimit.Max {
return false
}

if opts.GasLimit.Min != nil && tx.Response.GasUsed < *opts.GasLimit.Min {
return false
}

if opts.GasUsed.Max != nil && tx.Response.GasUsed > *opts.GasUsed.Max {
return false
}

if opts.GasUsed.Min != nil && tx.Response.GasUsed < *opts.GasUsed.Min {
return false
}

if opts.GasWanted.Max != nil && tx.Response.GasWanted > *opts.GasWanted.Max {
return false
}

if opts.GasWanted.Min != nil && tx.Response.GasWanted < *opts.GasWanted.Min {
return false
}

return true
}
Loading

0 comments on commit 2a70d0e

Please sign in to comment.