2021-05-14 20:32:39 +00:00
|
|
|
package pool
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/hex"
|
2021-06-02 19:45:55 +00:00
|
|
|
"errors"
|
2021-05-14 20:32:39 +00:00
|
|
|
"sort"
|
|
|
|
"time"
|
|
|
|
|
2021-07-15 20:51:22 +00:00
|
|
|
"github.com/asaskevich/EventBus"
|
|
|
|
|
2021-07-11 23:23:00 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
|
2021-05-19 20:54:36 +00:00
|
|
|
types2 "github.com/Secured-Finance/dione/blockchain/types"
|
2021-05-14 20:32:39 +00:00
|
|
|
|
2021-05-19 20:54:36 +00:00
|
|
|
"github.com/Secured-Finance/dione/consensus/policy"
|
2021-05-14 20:32:39 +00:00
|
|
|
|
|
|
|
"github.com/Secured-Finance/dione/cache"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
DefaultTxTTL = 10 * time.Minute
|
|
|
|
DefaultTxPrefix = "tx_"
|
|
|
|
)
|
|
|
|
|
2021-06-02 19:45:55 +00:00
|
|
|
var (
|
|
|
|
ErrTxNotFound = errors.New("tx isn't found in mempool")
|
|
|
|
)
|
|
|
|
|
2021-05-14 20:32:39 +00:00
|
|
|
type Mempool struct {
|
2021-05-31 19:24:07 +00:00
|
|
|
cache cache.Cache
|
2021-07-15 20:51:22 +00:00
|
|
|
bus EventBus.Bus
|
2021-05-14 20:32:39 +00:00
|
|
|
}
|
|
|
|
|
2021-08-24 19:36:42 +00:00
|
|
|
func NewMempool(bus EventBus.Bus, cm cache.CacheManager) (*Mempool, error) {
|
2021-05-14 20:32:39 +00:00
|
|
|
mp := &Mempool{
|
2021-08-24 19:36:42 +00:00
|
|
|
cache: cm.Cache("mempool"),
|
2021-07-15 20:51:22 +00:00
|
|
|
bus: bus,
|
2021-05-14 20:32:39 +00:00
|
|
|
}
|
|
|
|
|
2021-08-24 19:36:42 +00:00
|
|
|
logrus.Info("Mempool has been successfully initialized!")
|
|
|
|
|
2021-05-14 20:32:39 +00:00
|
|
|
return mp, nil
|
|
|
|
}
|
|
|
|
|
2021-05-19 20:54:36 +00:00
|
|
|
func (mp *Mempool) StoreTx(tx *types2.Transaction) error {
|
2021-05-14 20:32:39 +00:00
|
|
|
hashStr := hex.EncodeToString(tx.Hash)
|
|
|
|
err := mp.cache.StoreWithTTL(DefaultTxPrefix+hashStr, tx, DefaultTxTTL)
|
2021-07-19 20:19:06 +00:00
|
|
|
logrus.WithField("txHash", hex.EncodeToString(tx.Hash)).Info("Submitted new transaction in mempool")
|
2021-07-15 20:51:22 +00:00
|
|
|
mp.bus.Publish("mempool:transactionAdded", tx)
|
2021-05-14 20:32:39 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-07-15 20:51:22 +00:00
|
|
|
func (mp *Mempool) DeleteTx(txHash []byte) error {
|
2021-07-11 23:23:00 +00:00
|
|
|
hashStr := hex.EncodeToString(txHash)
|
2021-07-15 20:51:22 +00:00
|
|
|
var tx types2.Transaction
|
|
|
|
err := mp.cache.Get(DefaultTxPrefix+hashStr, &tx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-11 23:23:00 +00:00
|
|
|
mp.cache.Delete(DefaultTxPrefix + hashStr)
|
2021-07-19 20:19:06 +00:00
|
|
|
logrus.WithField("txHash", hex.EncodeToString(txHash)).Debugf("Deleted transaction from mempool")
|
2021-07-15 20:51:22 +00:00
|
|
|
mp.bus.Publish("mempool:transactionRemoved", tx)
|
|
|
|
return nil
|
2021-07-11 23:23:00 +00:00
|
|
|
}
|
|
|
|
|
2021-06-02 19:45:55 +00:00
|
|
|
func (mp *Mempool) GetTransactionsForNewBlock() []*types2.Transaction {
|
2021-05-19 20:54:36 +00:00
|
|
|
var txForBlock []*types2.Transaction
|
2021-06-02 19:45:55 +00:00
|
|
|
allTxs := mp.GetAllTransactions()
|
2021-05-14 20:32:39 +00:00
|
|
|
sort.Slice(allTxs, func(i, j int) bool {
|
|
|
|
return allTxs[i].Timestamp.Before(allTxs[j].Timestamp)
|
|
|
|
})
|
|
|
|
|
|
|
|
for i := 0; i < policy.BlockMaxTransactionCount; i++ {
|
|
|
|
if len(allTxs) == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
tx := allTxs[0] // get oldest tx
|
|
|
|
allTxs = allTxs[1:] // pop tx
|
|
|
|
txForBlock = append(txForBlock, tx)
|
|
|
|
}
|
|
|
|
|
|
|
|
return txForBlock
|
|
|
|
}
|
|
|
|
|
2021-06-02 19:45:55 +00:00
|
|
|
func (mp *Mempool) GetAllTransactions() []*types2.Transaction {
|
2021-05-31 19:24:07 +00:00
|
|
|
var allTxs []*types2.Transaction
|
|
|
|
|
2021-08-24 19:36:42 +00:00
|
|
|
for _, v := range mp.cache.Keys() {
|
|
|
|
var tx types2.Transaction
|
|
|
|
err := mp.cache.Get(v, &tx)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Error(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
allTxs = append(allTxs, &tx)
|
2021-05-31 19:24:07 +00:00
|
|
|
}
|
|
|
|
return allTxs
|
|
|
|
}
|
|
|
|
|
2021-06-02 19:45:55 +00:00
|
|
|
func (mp *Mempool) GetTransaction(hash []byte) (*types2.Transaction, error) {
|
|
|
|
hashStr := hex.EncodeToString(hash)
|
|
|
|
var tx types2.Transaction
|
|
|
|
err := mp.cache.Get(DefaultTxPrefix+hashStr, &tx)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, cache.ErrNotFound) {
|
|
|
|
return nil, ErrTxNotFound
|
|
|
|
} else {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &tx, nil
|
2021-05-14 20:32:39 +00:00
|
|
|
}
|