mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-16 18:00:46 +00:00
all: refactor txpool into it's own package in prep for 4844 (#26038)
This commit is contained in:
parent
05797846fc
commit
8b2e8d9b3a
29 changed files with 425 additions and 506 deletions
|
|
@ -38,6 +38,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||||
|
|
@ -261,12 +262,12 @@ var (
|
||||||
TxPoolJournalFlag = cli.StringFlag{
|
TxPoolJournalFlag = cli.StringFlag{
|
||||||
Name: "txpool.journal",
|
Name: "txpool.journal",
|
||||||
Usage: "Disk journal for local transaction to survive node restarts",
|
Usage: "Disk journal for local transaction to survive node restarts",
|
||||||
Value: core.DefaultTxPoolConfig.Journal,
|
Value: txpool.DefaultConfig.Journal,
|
||||||
}
|
}
|
||||||
TxPoolRejournalFlag = cli.DurationFlag{
|
TxPoolRejournalFlag = cli.DurationFlag{
|
||||||
Name: "txpool.rejournal",
|
Name: "txpool.rejournal",
|
||||||
Usage: "Time interval to regenerate the local transaction journal",
|
Usage: "Time interval to regenerate the local transaction journal",
|
||||||
Value: core.DefaultTxPoolConfig.Rejournal,
|
Value: txpool.DefaultConfig.Rejournal,
|
||||||
}
|
}
|
||||||
TxPoolPriceLimitFlag = cli.Uint64Flag{
|
TxPoolPriceLimitFlag = cli.Uint64Flag{
|
||||||
Name: "txpool.pricelimit",
|
Name: "txpool.pricelimit",
|
||||||
|
|
@ -1032,7 +1033,7 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
|
func setTxPool(ctx *cli.Context, cfg *txpool.Config) {
|
||||||
if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
|
if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
|
||||||
cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
|
cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import (
|
||||||
randomizeContract "github.com/XinFinOrg/XDPoSChain/contracts/randomize/contract"
|
randomizeContract "github.com/XinFinOrg/XDPoSChain/contracts/randomize/contract"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
|
|
@ -60,7 +61,7 @@ type RewardLog struct {
|
||||||
var TxSignMu sync.RWMutex
|
var TxSignMu sync.RWMutex
|
||||||
|
|
||||||
// Send tx sign for block number to smart contract blockSigner.
|
// Send tx sign for block number to smart contract blockSigner.
|
||||||
func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, manager *accounts.Manager, block *types.Block, chainDb ethdb.Database, eb common.Address) error {
|
func CreateTransactionSign(chainConfig *params.ChainConfig, pool *txpool.TxPool, manager *accounts.Manager, block *types.Block, chainDb ethdb.Database, eb common.Address) error {
|
||||||
TxSignMu.Lock()
|
TxSignMu.Lock()
|
||||||
defer TxSignMu.Unlock()
|
defer TxSignMu.Unlock()
|
||||||
if chainConfig.XDPoS != nil {
|
if chainConfig.XDPoS != nil {
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,9 @@ var (
|
||||||
CheckpointCh = make(chan int)
|
CheckpointCh = make(chan int)
|
||||||
ErrNoGenesis = errors.New("Genesis not found in chain")
|
ErrNoGenesis = errors.New("Genesis not found in chain")
|
||||||
|
|
||||||
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
|
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
|
||||||
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
||||||
blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil)
|
blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil)
|
||||||
blockReorgInvalidatedTx = metrics.NewRegisteredMeter("chain/reorg/invalidTx", nil)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -1440,7 +1439,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
|
||||||
defer close(abort)
|
defer close(abort)
|
||||||
|
|
||||||
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
||||||
senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain)
|
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain)
|
||||||
|
|
||||||
// Iterate over the blocks and insert when the verifier permits
|
// Iterate over the blocks and insert when the verifier permits
|
||||||
for i, block := range chain {
|
for i, block := range chain {
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,13 @@ var (
|
||||||
// ErrKnownBlock is returned when a block to import is already known locally.
|
// ErrKnownBlock is returned when a block to import is already known locally.
|
||||||
ErrKnownBlock = errors.New("block already known")
|
ErrKnownBlock = errors.New("block already known")
|
||||||
|
|
||||||
// ErrGasLimitReached is returned by the gas pool if the amount of gas required
|
|
||||||
// by a transaction is higher than what's left in the block.
|
|
||||||
ErrGasLimitReached = errors.New("gas limit reached")
|
|
||||||
|
|
||||||
// ErrBlacklistedHash is returned if a block to import is on the blacklist.
|
// ErrBlacklistedHash is returned if a block to import is on the blacklist.
|
||||||
ErrBlacklistedHash = errors.New("blacklisted hash")
|
ErrBlacklistedHash = errors.New("blacklisted hash")
|
||||||
|
|
||||||
|
// ErrNonceTooLow is returned if the nonce of a transaction is lower than the
|
||||||
|
// one present in the local chain.
|
||||||
|
ErrNonceTooLow = errors.New("nonce too low")
|
||||||
|
|
||||||
// ErrNonceTooHigh is returned if the nonce of a transaction is higher than the
|
// ErrNonceTooHigh is returned if the nonce of a transaction is higher than the
|
||||||
// next one expected based on the local chain.
|
// next one expected based on the local chain.
|
||||||
ErrNonceTooHigh = errors.New("nonce too high")
|
ErrNonceTooHigh = errors.New("nonce too high")
|
||||||
|
|
@ -41,19 +41,25 @@ var (
|
||||||
// maximum allowed value and would become invalid if incremented.
|
// maximum allowed value and would become invalid if incremented.
|
||||||
ErrNonceMax = errors.New("nonce has max value")
|
ErrNonceMax = errors.New("nonce has max value")
|
||||||
|
|
||||||
ErrNotXDPoS = errors.New("XDPoS not found in config")
|
// ErrGasLimitReached is returned by the gas pool if the amount of gas required
|
||||||
|
// by a transaction is higher than what's left in the block.
|
||||||
|
ErrGasLimitReached = errors.New("gas limit reached")
|
||||||
|
|
||||||
ErrNotFoundM1 = errors.New("list M1 not found ")
|
// ErrInsufficientFunds is returned if the total cost of executing a transaction
|
||||||
|
// is higher than the balance of the user's account.
|
||||||
|
ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")
|
||||||
|
|
||||||
ErrStopPreparingBlock = errors.New("stop calculating a block not verified by M2")
|
// ErrGasUintOverflow is returned when calculating gas usage.
|
||||||
|
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
||||||
|
|
||||||
|
// ErrIntrinsicGas is returned if the transaction is specified to use less gas
|
||||||
|
// than required to start the invocation.
|
||||||
|
ErrIntrinsicGas = errors.New("intrinsic gas too low")
|
||||||
|
|
||||||
// ErrTxTypeNotSupported is returned if a transaction is not supported in the
|
// ErrTxTypeNotSupported is returned if a transaction is not supported in the
|
||||||
// current network configuration.
|
// current network configuration.
|
||||||
ErrTxTypeNotSupported = types.ErrTxTypeNotSupported
|
ErrTxTypeNotSupported = types.ErrTxTypeNotSupported
|
||||||
|
|
||||||
// ErrGasUintOverflow is returned when calculating gas usage.
|
|
||||||
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
|
||||||
|
|
||||||
// ErrTipAboveFeeCap is a sanity error to ensure no one is able to specify a
|
// ErrTipAboveFeeCap is a sanity error to ensure no one is able to specify a
|
||||||
// transaction with a tip higher than the total fee cap.
|
// transaction with a tip higher than the total fee cap.
|
||||||
ErrTipAboveFeeCap = errors.New("max priority fee per gas higher than max fee per gas")
|
ErrTipAboveFeeCap = errors.New("max priority fee per gas higher than max fee per gas")
|
||||||
|
|
@ -72,4 +78,10 @@ var (
|
||||||
|
|
||||||
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
|
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
|
||||||
ErrSenderNoEOA = errors.New("sender not an eoa")
|
ErrSenderNoEOA = errors.New("sender not an eoa")
|
||||||
|
|
||||||
|
ErrNotXDPoS = errors.New("XDPoS not found in config")
|
||||||
|
|
||||||
|
ErrNotFoundM1 = errors.New("list M1 not found ")
|
||||||
|
|
||||||
|
ErrStopPreparingBlock = errors.New("stop calculating a block not verified by M2")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
// Copyright 2014 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"container/list"
|
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/event"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Implement our EthTest Manager
|
|
||||||
type TestManager struct {
|
|
||||||
// stateManager *StateManager
|
|
||||||
eventMux *event.TypeMux
|
|
||||||
|
|
||||||
db ethdb.Database
|
|
||||||
txPool *TxPool
|
|
||||||
blockChain *BlockChain
|
|
||||||
Blocks []*types.Block
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TestManager) IsListening() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TestManager) IsMining() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TestManager) PeerCount() int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TestManager) Peers() *list.List {
|
|
||||||
return list.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TestManager) BlockChain() *BlockChain {
|
|
||||||
return tm.blockChain
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TestManager) TxPool() *TxPool {
|
|
||||||
return tm.txPool
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (tm *TestManager) StateManager() *StateManager {
|
|
||||||
// return tm.stateManager
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (tm *TestManager) EventMux() *event.TypeMux {
|
|
||||||
return tm.eventMux
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (tm *TestManager) KeyManager() *crypto.KeyManager {
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (tm *TestManager) Db() ethdb.Database {
|
|
||||||
return tm.db
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTestManager() *TestManager {
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
|
||||||
|
|
||||||
testManager := &TestManager{}
|
|
||||||
testManager.eventMux = new(event.TypeMux)
|
|
||||||
testManager.db = db
|
|
||||||
// testManager.txPool = NewTxPool(testManager)
|
|
||||||
// testManager.blockChain = NewBlockChain(testManager)
|
|
||||||
// testManager.stateManager = NewStateManager(testManager)
|
|
||||||
|
|
||||||
return testManager
|
|
||||||
}
|
|
||||||
|
|
@ -22,8 +22,8 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// senderCacher is a concurrent tranaction sender recoverer anc cacher.
|
// SenderCacher is a concurrent transaction sender recoverer and cacher.
|
||||||
var senderCacher = newTxSenderCacher(runtime.NumCPU())
|
var SenderCacher = newTxSenderCacher(runtime.NumCPU())
|
||||||
|
|
||||||
// txSenderCacherRequest is a request for recovering transaction senders with a
|
// txSenderCacherRequest is a request for recovering transaction senders with a
|
||||||
// specific signature scheme and caching it into the transactions themselves.
|
// specific signature scheme and caching it into the transactions themselves.
|
||||||
|
|
@ -67,10 +67,10 @@ func (cacher *txSenderCacher) cache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recover recovers the senders from a batch of transactions and caches them
|
// Recover recovers the senders from a batch of transactions and caches them
|
||||||
// back into the same data structures. There is no validation being done, nor
|
// back into the same data structures. There is no validation being done, nor
|
||||||
// any reaction to invalid signatures. That is up to calling code later.
|
// any reaction to invalid signatures. That is up to calling code later.
|
||||||
func (cacher *txSenderCacher) recover(signer types.Signer, txs []*types.Transaction) {
|
func (cacher *txSenderCacher) Recover(signer types.Signer, txs []*types.Transaction) {
|
||||||
// If there's nothing to recover, abort
|
// If there's nothing to recover, abort
|
||||||
if len(txs) == 0 {
|
if len(txs) == 0 {
|
||||||
return
|
return
|
||||||
|
|
@ -89,10 +89,10 @@ func (cacher *txSenderCacher) recover(signer types.Signer, txs []*types.Transact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recoverFromBlocks recovers the senders from a batch of blocks and caches them
|
// RecoverFromBlocks recovers the senders from a batch of blocks and caches them
|
||||||
// back into the same data structures. There is no validation being done, nor
|
// back into the same data structures. There is no validation being done, nor
|
||||||
// any reaction to invalid signatures. That is up to calling code later.
|
// any reaction to invalid signatures. That is up to calling code later.
|
||||||
func (cacher *txSenderCacher) recoverFromBlocks(signer types.Signer, blocks []*types.Block) {
|
func (cacher *txSenderCacher) RecoverFromBlocks(signer types.Signer, blocks []*types.Block) {
|
||||||
count := 0
|
count := 0
|
||||||
for _, block := range blocks {
|
for _, block := range blocks {
|
||||||
count += len(block.Transactions())
|
count += len(block.Transactions())
|
||||||
|
|
@ -101,5 +101,5 @@ func (cacher *txSenderCacher) recoverFromBlocks(signer types.Signer, blocks []*t
|
||||||
for _, block := range blocks {
|
for _, block := range blocks {
|
||||||
txs = append(txs, block.Transactions()...)
|
txs = append(txs, block.Transactions()...)
|
||||||
}
|
}
|
||||||
cacher.recover(signer, txs)
|
cacher.Recover(signer, txs)
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
@ -40,23 +40,23 @@ type devNull struct{}
|
||||||
func (*devNull) Write(p []byte) (n int, err error) { return len(p), nil }
|
func (*devNull) Write(p []byte) (n int, err error) { return len(p), nil }
|
||||||
func (*devNull) Close() error { return nil }
|
func (*devNull) Close() error { return nil }
|
||||||
|
|
||||||
// txJournal is a rotating log of transactions with the aim of storing locally
|
// journal is a rotating log of transactions with the aim of storing locally
|
||||||
// created transactions to allow non-executed ones to survive node restarts.
|
// created transactions to allow non-executed ones to survive node restarts.
|
||||||
type txJournal struct {
|
type journal struct {
|
||||||
path string // Filesystem path to store the transactions at
|
path string // Filesystem path to store the transactions at
|
||||||
writer io.WriteCloser // Output stream to write new transactions into
|
writer io.WriteCloser // Output stream to write new transactions into
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTxJournal creates a new transaction journal to
|
// newTxJournal creates a new transaction journal to
|
||||||
func newTxJournal(path string) *txJournal {
|
func newTxJournal(path string) *journal {
|
||||||
return &txJournal{
|
return &journal{
|
||||||
path: path,
|
path: path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load parses a transaction journal dump from disk, loading its contents into
|
// load parses a transaction journal dump from disk, loading its contents into
|
||||||
// the specified pool.
|
// the specified pool.
|
||||||
func (journal *txJournal) load(add func([]*types.Transaction) []error) error {
|
func (journal *journal) load(add func([]*types.Transaction) []error) error {
|
||||||
// Skip the parsing if the journal file doens't exist at all
|
// Skip the parsing if the journal file doens't exist at all
|
||||||
if _, err := os.Stat(journal.path); os.IsNotExist(err) {
|
if _, err := os.Stat(journal.path); os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -116,7 +116,7 @@ func (journal *txJournal) load(add func([]*types.Transaction) []error) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert adds the specified transaction to the local disk journal.
|
// insert adds the specified transaction to the local disk journal.
|
||||||
func (journal *txJournal) insert(tx *types.Transaction) error {
|
func (journal *journal) insert(tx *types.Transaction) error {
|
||||||
if journal.writer == nil {
|
if journal.writer == nil {
|
||||||
return errNoActiveJournal
|
return errNoActiveJournal
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +128,7 @@ func (journal *txJournal) insert(tx *types.Transaction) error {
|
||||||
|
|
||||||
// rotate regenerates the transaction journal based on the current contents of
|
// rotate regenerates the transaction journal based on the current contents of
|
||||||
// the transaction pool.
|
// the transaction pool.
|
||||||
func (journal *txJournal) rotate(all map[common.Address]types.Transactions) error {
|
func (journal *journal) rotate(all map[common.Address]types.Transactions) error {
|
||||||
// Close the current journal (if any is open)
|
// Close the current journal (if any is open)
|
||||||
if journal.writer != nil {
|
if journal.writer != nil {
|
||||||
if err := journal.writer.Close(); err != nil {
|
if err := journal.writer.Close(); err != nil {
|
||||||
|
|
@ -168,7 +168,7 @@ func (journal *txJournal) rotate(all map[common.Address]types.Transactions) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// close flushes the transaction journal contents to disk and closes the file.
|
// close flushes the transaction journal contents to disk and closes the file.
|
||||||
func (journal *txJournal) close() error {
|
func (journal *journal) close() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if journal.writer != nil {
|
if journal.writer != nil {
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/event"
|
"github.com/XinFinOrg/XDPoSChain/event"
|
||||||
|
|
@ -75,7 +76,7 @@ type blockChainLending interface {
|
||||||
GetBlock(hash common.Hash, number uint64) *types.Block
|
GetBlock(hash common.Hash, number uint64) *types.Block
|
||||||
LendingStateAt(block *types.Block) (*lendingstate.LendingStateDB, error)
|
LendingStateAt(block *types.Block) (*lendingstate.LendingStateDB, error)
|
||||||
StateAt(root common.Hash) (*state.StateDB, error)
|
StateAt(root common.Hash) (*state.StateDB, error)
|
||||||
SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription
|
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
||||||
Engine() consensus.Engine
|
Engine() consensus.Engine
|
||||||
// GetHeader returns the hash corresponding to their hash.
|
// GetHeader returns the hash corresponding to their hash.
|
||||||
GetHeader(common.Hash, uint64) *types.Header
|
GetHeader(common.Hash, uint64) *types.Header
|
||||||
|
|
@ -124,7 +125,7 @@ type LendingPool struct {
|
||||||
|
|
||||||
txFeed event.Feed
|
txFeed event.Feed
|
||||||
scope event.SubscriptionScope
|
scope event.SubscriptionScope
|
||||||
chainHeadCh chan ChainHeadEvent
|
chainHeadCh chan core.ChainHeadEvent
|
||||||
chainHeadSub event.Subscription
|
chainHeadSub event.Subscription
|
||||||
signer types.LendingSigner
|
signer types.LendingSigner
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
@ -161,7 +162,7 @@ func NewLendingPool(chainconfig *params.ChainConfig, chain blockChainLending) *L
|
||||||
queue: make(map[common.Address]*lendingtxList),
|
queue: make(map[common.Address]*lendingtxList),
|
||||||
beats: make(map[common.Address]time.Time),
|
beats: make(map[common.Address]time.Time),
|
||||||
all: make(map[common.Hash]*types.LendingTransaction),
|
all: make(map[common.Hash]*types.LendingTransaction),
|
||||||
chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize),
|
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
||||||
}
|
}
|
||||||
pool.locals = newLendingAccountSet(pool.signer)
|
pool.locals = newLendingAccountSet(pool.signer)
|
||||||
pool.reset(nil, chain.CurrentBlock())
|
pool.reset(nil, chain.CurrentBlock())
|
||||||
|
|
@ -334,7 +335,7 @@ func (pool *LendingPool) Stop() {
|
||||||
|
|
||||||
// SubscribeTxPreEvent registers a subscription of TxPreEvent and
|
// SubscribeTxPreEvent registers a subscription of TxPreEvent and
|
||||||
// starts sending event to the given channel.
|
// starts sending event to the given channel.
|
||||||
func (pool *LendingPool) SubscribeTxPreEvent(ch chan<- LendingTxPreEvent) event.Subscription {
|
func (pool *LendingPool) SubscribeTxPreEvent(ch chan<- core.LendingTxPreEvent) event.Subscription {
|
||||||
return pool.scope.Track(pool.txFeed.Subscribe(ch))
|
return pool.scope.Track(pool.txFeed.Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -514,7 +515,7 @@ func (pool *LendingPool) validateTopupLending(cloneStateDb *state.StateDB, clone
|
||||||
func (pool *LendingPool) validateBalance(cloneStateDb *state.StateDB, cloneLendingStateDb *lendingstate.LendingStateDB, tx *types.LendingTransaction, collateralToken common.Address) error {
|
func (pool *LendingPool) validateBalance(cloneStateDb *state.StateDB, cloneLendingStateDb *lendingstate.LendingStateDB, tx *types.LendingTransaction, collateralToken common.Address) error {
|
||||||
XDPoSEngine, ok := pool.chain.Engine().(*XDPoS.XDPoS)
|
XDPoSEngine, ok := pool.chain.Engine().(*XDPoS.XDPoS)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrNotXDPoS
|
return core.ErrNotXDPoS
|
||||||
}
|
}
|
||||||
XDCXServ := XDPoSEngine.GetXDCXService()
|
XDCXServ := XDPoSEngine.GetXDCXService()
|
||||||
lendingServ := XDPoSEngine.GetLendingService()
|
lendingServ := XDPoSEngine.GetLendingService()
|
||||||
|
|
@ -641,10 +642,10 @@ func (pool *LendingPool) validateTx(tx *types.LendingTransaction, local bool) er
|
||||||
}
|
}
|
||||||
// Ensure the transaction adheres to nonce lending
|
// Ensure the transaction adheres to nonce lending
|
||||||
if pool.currentLendingState.GetNonce(from.Hash()) > tx.Nonce() {
|
if pool.currentLendingState.GetNonce(from.Hash()) > tx.Nonce() {
|
||||||
return ErrNonceTooLow
|
return core.ErrNonceTooLow
|
||||||
}
|
}
|
||||||
if pool.pendingState.GetNonce(from.Hash())+common.LimitThresholdNonceInQueue < tx.Nonce() {
|
if pool.pendingState.GetNonce(from.Hash())+common.LimitThresholdNonceInQueue < tx.Nonce() {
|
||||||
return ErrNonceTooHigh
|
return core.ErrNonceTooHigh
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -778,7 +779,7 @@ func (pool *LendingPool) promoteTx(addr common.Address, hash common.Hash, tx *ty
|
||||||
pool.beats[addr] = time.Now()
|
pool.beats[addr] = time.Now()
|
||||||
pool.pendingState.SetNonce(addr.Hash(), tx.Nonce()+1)
|
pool.pendingState.SetNonce(addr.Hash(), tx.Nonce()+1)
|
||||||
|
|
||||||
go pool.txFeed.Send(LendingTxPreEvent{tx})
|
go pool.txFeed.Send(core.LendingTxPreEvent{Tx: tx})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddLocal enqueues a single transaction into the pool if it is valid, marking
|
// AddLocal enqueues a single transaction into the pool if it is valid, marking
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/heap"
|
"container/heap"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/heap"
|
"container/heap"
|
||||||
|
|
@ -49,30 +49,30 @@ func (h *nonceHeap) Pop() interface{} {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
// txSortedMap is a nonce->transaction hash map with a heap based index to allow
|
// sortedMap is a nonce->transaction hash map with a heap based index to allow
|
||||||
// iterating over the contents in a nonce-incrementing way.
|
// iterating over the contents in a nonce-incrementing way.
|
||||||
type txSortedMap struct {
|
type sortedMap struct {
|
||||||
items map[uint64]*types.Transaction // Hash map storing the transaction data
|
items map[uint64]*types.Transaction // Hash map storing the transaction data
|
||||||
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
|
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
|
||||||
cache types.Transactions // Cache of the transactions already sorted
|
cache types.Transactions // Cache of the transactions already sorted
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTxSortedMap creates a new nonce-sorted transaction map.
|
// newSortedMap creates a new nonce-sorted transaction map.
|
||||||
func newTxSortedMap() *txSortedMap {
|
func newSortedMap() *sortedMap {
|
||||||
return &txSortedMap{
|
return &sortedMap{
|
||||||
items: make(map[uint64]*types.Transaction),
|
items: make(map[uint64]*types.Transaction),
|
||||||
index: new(nonceHeap),
|
index: new(nonceHeap),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get retrieves the current transactions associated with the given nonce.
|
// Get retrieves the current transactions associated with the given nonce.
|
||||||
func (m *txSortedMap) Get(nonce uint64) *types.Transaction {
|
func (m *sortedMap) Get(nonce uint64) *types.Transaction {
|
||||||
return m.items[nonce]
|
return m.items[nonce]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put inserts a new transaction into the map, also updating the map's nonce
|
// Put inserts a new transaction into the map, also updating the map's nonce
|
||||||
// index. If a transaction already exists with the same nonce, it's overwritten.
|
// index. If a transaction already exists with the same nonce, it's overwritten.
|
||||||
func (m *txSortedMap) Put(tx *types.Transaction) {
|
func (m *sortedMap) Put(tx *types.Transaction) {
|
||||||
nonce := tx.Nonce()
|
nonce := tx.Nonce()
|
||||||
if m.items[nonce] == nil {
|
if m.items[nonce] == nil {
|
||||||
heap.Push(m.index, nonce)
|
heap.Push(m.index, nonce)
|
||||||
|
|
@ -83,7 +83,7 @@ func (m *txSortedMap) Put(tx *types.Transaction) {
|
||||||
// Forward removes all transactions from the map with a nonce lower than the
|
// Forward removes all transactions from the map with a nonce lower than the
|
||||||
// provided threshold. Every removed transaction is returned for any post-removal
|
// provided threshold. Every removed transaction is returned for any post-removal
|
||||||
// maintenance.
|
// maintenance.
|
||||||
func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
|
func (m *sortedMap) Forward(threshold uint64) types.Transactions {
|
||||||
var removed types.Transactions
|
var removed types.Transactions
|
||||||
|
|
||||||
// Pop off heap items until the threshold is reached
|
// Pop off heap items until the threshold is reached
|
||||||
|
|
@ -104,7 +104,7 @@ func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
|
||||||
// Filter, as opposed to 'filter', re-initialises the heap after the operation is done.
|
// Filter, as opposed to 'filter', re-initialises the heap after the operation is done.
|
||||||
// If you want to do several consecutive filterings, it's therefore better to first
|
// If you want to do several consecutive filterings, it's therefore better to first
|
||||||
// do a .filter(func1) followed by .Filter(func2) or reheap()
|
// do a .filter(func1) followed by .Filter(func2) or reheap()
|
||||||
func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
|
func (m *sortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
|
||||||
removed := m.filter(filter)
|
removed := m.filter(filter)
|
||||||
// If transactions were removed, the heap and cache are ruined
|
// If transactions were removed, the heap and cache are ruined
|
||||||
if len(removed) > 0 {
|
if len(removed) > 0 {
|
||||||
|
|
@ -113,7 +113,7 @@ func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transac
|
||||||
return removed
|
return removed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *txSortedMap) reheap() {
|
func (m *sortedMap) reheap() {
|
||||||
*m.index = make([]uint64, 0, len(m.items))
|
*m.index = make([]uint64, 0, len(m.items))
|
||||||
for nonce := range m.items {
|
for nonce := range m.items {
|
||||||
*m.index = append(*m.index, nonce)
|
*m.index = append(*m.index, nonce)
|
||||||
|
|
@ -124,7 +124,7 @@ func (m *txSortedMap) reheap() {
|
||||||
|
|
||||||
// filter is identical to Filter, but **does not** regenerate the heap. This method
|
// filter is identical to Filter, but **does not** regenerate the heap. This method
|
||||||
// should only be used if followed immediately by a call to Filter or reheap()
|
// should only be used if followed immediately by a call to Filter or reheap()
|
||||||
func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transactions {
|
func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transactions {
|
||||||
var removed types.Transactions
|
var removed types.Transactions
|
||||||
|
|
||||||
// Collect all the transactions to filter out
|
// Collect all the transactions to filter out
|
||||||
|
|
@ -142,7 +142,7 @@ func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transac
|
||||||
|
|
||||||
// Cap places a hard limit on the number of items, returning all transactions
|
// Cap places a hard limit on the number of items, returning all transactions
|
||||||
// exceeding that limit.
|
// exceeding that limit.
|
||||||
func (m *txSortedMap) Cap(threshold int) types.Transactions {
|
func (m *sortedMap) Cap(threshold int) types.Transactions {
|
||||||
// Short circuit if the number of items is under the limit
|
// Short circuit if the number of items is under the limit
|
||||||
if len(m.items) <= threshold {
|
if len(m.items) <= threshold {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -167,7 +167,7 @@ func (m *txSortedMap) Cap(threshold int) types.Transactions {
|
||||||
|
|
||||||
// Remove deletes a transaction from the maintained map, returning whether the
|
// Remove deletes a transaction from the maintained map, returning whether the
|
||||||
// transaction was found.
|
// transaction was found.
|
||||||
func (m *txSortedMap) Remove(nonce uint64) bool {
|
func (m *sortedMap) Remove(nonce uint64) bool {
|
||||||
// Short circuit if no transaction is present
|
// Short circuit if no transaction is present
|
||||||
_, ok := m.items[nonce]
|
_, ok := m.items[nonce]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -193,7 +193,7 @@ func (m *txSortedMap) Remove(nonce uint64) bool {
|
||||||
// Note, all transactions with nonces lower than start will also be returned to
|
// Note, all transactions with nonces lower than start will also be returned to
|
||||||
// prevent getting into and invalid state. This is not something that should ever
|
// prevent getting into and invalid state. This is not something that should ever
|
||||||
// happen but better to be self correcting than failing!
|
// happen but better to be self correcting than failing!
|
||||||
func (m *txSortedMap) Ready(start uint64) types.Transactions {
|
func (m *sortedMap) Ready(start uint64) types.Transactions {
|
||||||
// Short circuit if no transactions are available
|
// Short circuit if no transactions are available
|
||||||
if m.index.Len() == 0 || (*m.index)[0] > start {
|
if m.index.Len() == 0 || (*m.index)[0] > start {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -211,11 +211,11 @@ func (m *txSortedMap) Ready(start uint64) types.Transactions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the length of the transaction map.
|
// Len returns the length of the transaction map.
|
||||||
func (m *txSortedMap) Len() int {
|
func (m *sortedMap) Len() int {
|
||||||
return len(m.items)
|
return len(m.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *txSortedMap) flatten() types.Transactions {
|
func (m *sortedMap) flatten() types.Transactions {
|
||||||
// If the sorting was not cached yet, create and cache it
|
// If the sorting was not cached yet, create and cache it
|
||||||
if m.cache == nil {
|
if m.cache == nil {
|
||||||
m.cache = make(types.Transactions, 0, len(m.items))
|
m.cache = make(types.Transactions, 0, len(m.items))
|
||||||
|
|
@ -230,7 +230,7 @@ func (m *txSortedMap) flatten() types.Transactions {
|
||||||
// Flatten creates a nonce-sorted slice of transactions based on the loosely
|
// Flatten creates a nonce-sorted slice of transactions based on the loosely
|
||||||
// sorted internal representation. The result of the sorting is cached in case
|
// sorted internal representation. The result of the sorting is cached in case
|
||||||
// it's requested again before any modifications are made to the contents.
|
// it's requested again before any modifications are made to the contents.
|
||||||
func (m *txSortedMap) Flatten() types.Transactions {
|
func (m *sortedMap) Flatten() types.Transactions {
|
||||||
// Copy the cache to prevent accidental modifications
|
// Copy the cache to prevent accidental modifications
|
||||||
cache := m.flatten()
|
cache := m.flatten()
|
||||||
txs := make(types.Transactions, len(cache))
|
txs := make(types.Transactions, len(cache))
|
||||||
|
|
@ -240,36 +240,36 @@ func (m *txSortedMap) Flatten() types.Transactions {
|
||||||
|
|
||||||
// LastElement returns the last element of a flattened list, thus, the
|
// LastElement returns the last element of a flattened list, thus, the
|
||||||
// transaction with the highest nonce
|
// transaction with the highest nonce
|
||||||
func (m *txSortedMap) LastElement() *types.Transaction {
|
func (m *sortedMap) LastElement() *types.Transaction {
|
||||||
cache := m.flatten()
|
cache := m.flatten()
|
||||||
return cache[len(cache)-1]
|
return cache[len(cache)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// txList is a "list" of transactions belonging to an account, sorted by account
|
// list is a "list" of transactions belonging to an account, sorted by account
|
||||||
// nonce. The same type can be used both for storing contiguous transactions for
|
// nonce. The same type can be used both for storing contiguous transactions for
|
||||||
// the executable/pending queue; and for storing gapped transactions for the non-
|
// the executable/pending queue; and for storing gapped transactions for the non-
|
||||||
// executable/future queue, with minor behavioral changes.
|
// executable/future queue, with minor behavioral changes.
|
||||||
type txList struct {
|
type list struct {
|
||||||
strict bool // Whether nonces are strictly continuous or not
|
strict bool // Whether nonces are strictly continuous or not
|
||||||
txs *txSortedMap // Heap indexed sorted hash map of the transactions
|
txs *sortedMap // Heap indexed sorted hash map of the transactions
|
||||||
|
|
||||||
costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
|
costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
|
||||||
gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
|
gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTxList create a new transaction list for maintaining nonce-indexable fast,
|
// newList create a new transaction list for maintaining nonce-indexable fast,
|
||||||
// gapped, sortable transaction lists.
|
// gapped, sortable transaction lists.
|
||||||
func newTxList(strict bool) *txList {
|
func newList(strict bool) *list {
|
||||||
return &txList{
|
return &list{
|
||||||
strict: strict,
|
strict: strict,
|
||||||
txs: newTxSortedMap(),
|
txs: newSortedMap(),
|
||||||
costcap: new(big.Int),
|
costcap: new(big.Int),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlaps returns whether the transaction specified has the same nonce as one
|
// Overlaps returns whether the transaction specified has the same nonce as one
|
||||||
// already contained within the list.
|
// already contained within the list.
|
||||||
func (l *txList) Overlaps(tx *types.Transaction) bool {
|
func (l *list) Overlaps(tx *types.Transaction) bool {
|
||||||
return l.txs.Get(tx.Nonce()) != nil
|
return l.txs.Get(tx.Nonce()) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -278,7 +278,7 @@ func (l *txList) Overlaps(tx *types.Transaction) bool {
|
||||||
//
|
//
|
||||||
// If the new transaction is accepted into the list, the lists' cost and gas
|
// If the new transaction is accepted into the list, the lists' cost and gas
|
||||||
// thresholds are also potentially updated.
|
// thresholds are also potentially updated.
|
||||||
func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
|
func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
|
||||||
// If there's an older better transaction, abort
|
// If there's an older better transaction, abort
|
||||||
old := l.txs.Get(tx.Nonce())
|
old := l.txs.Get(tx.Nonce())
|
||||||
if old != nil && old.IsSpecialTransaction() {
|
if old != nil && old.IsSpecialTransaction() {
|
||||||
|
|
@ -319,7 +319,7 @@ func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Tran
|
||||||
// Forward removes all transactions from the list with a nonce lower than the
|
// Forward removes all transactions from the list with a nonce lower than the
|
||||||
// provided threshold. Every removed transaction is returned for any post-removal
|
// provided threshold. Every removed transaction is returned for any post-removal
|
||||||
// maintenance.
|
// maintenance.
|
||||||
func (l *txList) Forward(threshold uint64) types.Transactions {
|
func (l *list) Forward(threshold uint64) types.Transactions {
|
||||||
return l.txs.Forward(threshold)
|
return l.txs.Forward(threshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,7 +332,7 @@ func (l *txList) Forward(threshold uint64) types.Transactions {
|
||||||
// a point in calculating all the costs or if the balance covers all. If the threshold
|
// a point in calculating all the costs or if the balance covers all. If the threshold
|
||||||
// is lower than the costgas cap, the caps will be reset to a new high after removing
|
// is lower than the costgas cap, the caps will be reset to a new high after removing
|
||||||
// the newly invalidated transactions.
|
// the newly invalidated transactions.
|
||||||
func (l *txList) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[common.Address]*big.Int, number *big.Int) (types.Transactions, types.Transactions) {
|
func (l *list) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[common.Address]*big.Int, number *big.Int) (types.Transactions, types.Transactions) {
|
||||||
// If all transactions are below the threshold, short circuit
|
// If all transactions are below the threshold, short circuit
|
||||||
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
|
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -371,14 +371,14 @@ func (l *txList) Filter(costLimit *big.Int, gasLimit uint64, trc21Issuers map[co
|
||||||
|
|
||||||
// Cap places a hard limit on the number of items, returning all transactions
|
// Cap places a hard limit on the number of items, returning all transactions
|
||||||
// exceeding that limit.
|
// exceeding that limit.
|
||||||
func (l *txList) Cap(threshold int) types.Transactions {
|
func (l *list) Cap(threshold int) types.Transactions {
|
||||||
return l.txs.Cap(threshold)
|
return l.txs.Cap(threshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove deletes a transaction from the maintained list, returning whether the
|
// Remove deletes a transaction from the maintained list, returning whether the
|
||||||
// transaction was found, and also returning any transaction invalidated due to
|
// transaction was found, and also returning any transaction invalidated due to
|
||||||
// the deletion (strict mode only).
|
// the deletion (strict mode only).
|
||||||
func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) {
|
func (l *list) Remove(tx *types.Transaction) (bool, types.Transactions) {
|
||||||
// Remove the transaction from the set
|
// Remove the transaction from the set
|
||||||
nonce := tx.Nonce()
|
nonce := tx.Nonce()
|
||||||
if removed := l.txs.Remove(nonce); !removed {
|
if removed := l.txs.Remove(nonce); !removed {
|
||||||
|
|
@ -398,30 +398,30 @@ func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) {
|
||||||
// Note, all transactions with nonces lower than start will also be returned to
|
// Note, all transactions with nonces lower than start will also be returned to
|
||||||
// prevent getting into and invalid state. This is not something that should ever
|
// prevent getting into and invalid state. This is not something that should ever
|
||||||
// happen but better to be self correcting than failing!
|
// happen but better to be self correcting than failing!
|
||||||
func (l *txList) Ready(start uint64) types.Transactions {
|
func (l *list) Ready(start uint64) types.Transactions {
|
||||||
return l.txs.Ready(start)
|
return l.txs.Ready(start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the length of the transaction list.
|
// Len returns the length of the transaction list.
|
||||||
func (l *txList) Len() int {
|
func (l *list) Len() int {
|
||||||
return l.txs.Len()
|
return l.txs.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty returns whether the list of transactions is empty or not.
|
// Empty returns whether the list of transactions is empty or not.
|
||||||
func (l *txList) Empty() bool {
|
func (l *list) Empty() bool {
|
||||||
return l.Len() == 0
|
return l.Len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flatten creates a nonce-sorted slice of transactions based on the loosely
|
// Flatten creates a nonce-sorted slice of transactions based on the loosely
|
||||||
// sorted internal representation. The result of the sorting is cached in case
|
// sorted internal representation. The result of the sorting is cached in case
|
||||||
// it's requested again before any modifications are made to the contents.
|
// it's requested again before any modifications are made to the contents.
|
||||||
func (l *txList) Flatten() types.Transactions {
|
func (l *list) Flatten() types.Transactions {
|
||||||
return l.txs.Flatten()
|
return l.txs.Flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastElement returns the last element of a flattened list, thus, the
|
// LastElement returns the last element of a flattened list, thus, the
|
||||||
// transaction with the highest nonce
|
// transaction with the highest nonce
|
||||||
func (l *txList) LastElement() *types.Transaction {
|
func (l *list) LastElement() *types.Transaction {
|
||||||
return l.txs.LastElement()
|
return l.txs.LastElement()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -477,7 +477,7 @@ func (h *priceHeap) Pop() interface{} {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
// txPricedList is a price-sorted heap to allow operating on transactions pool
|
// pricedList is a price-sorted heap to allow operating on transactions pool
|
||||||
// contents in a price-incrementing way. It's built opon the all transactions
|
// contents in a price-incrementing way. It's built opon the all transactions
|
||||||
// in txpool but only interested in the remote part. It means only remote transactions
|
// in txpool but only interested in the remote part. It means only remote transactions
|
||||||
// will be considered for tracking, sorting, eviction, etc.
|
// will be considered for tracking, sorting, eviction, etc.
|
||||||
|
|
@ -488,8 +488,8 @@ func (h *priceHeap) Pop() interface{} {
|
||||||
// In some cases (during a congestion, when blocks are full) the urgent heap can provide
|
// In some cases (during a congestion, when blocks are full) the urgent heap can provide
|
||||||
// better candidates for inclusion while in other cases (at the top of the baseFee peak)
|
// better candidates for inclusion while in other cases (at the top of the baseFee peak)
|
||||||
// the floating heap is better. When baseFee is decreasing they behave similarly.
|
// the floating heap is better. When baseFee is decreasing they behave similarly.
|
||||||
type txPricedList struct {
|
type pricedList struct {
|
||||||
all *txLookup // Pointer to the map of all transactions
|
all *lookup // Pointer to the map of all transactions
|
||||||
urgent, floating priceHeap // Heaps of prices of all the stored **remote** transactions
|
urgent, floating priceHeap // Heaps of prices of all the stored **remote** transactions
|
||||||
stales int64 // Number of stale price points to (re-heap trigger)
|
stales int64 // Number of stale price points to (re-heap trigger)
|
||||||
reheapMu sync.Mutex // Mutex asserts that only one routine is reheaping the list
|
reheapMu sync.Mutex // Mutex asserts that only one routine is reheaping the list
|
||||||
|
|
@ -501,15 +501,15 @@ const (
|
||||||
floatingRatio = 1
|
floatingRatio = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// newTxPricedList creates a new price-sorted transaction heap.
|
// newPricedList creates a new price-sorted transaction heap.
|
||||||
func newTxPricedList(all *txLookup) *txPricedList {
|
func newPricedList(all *lookup) *pricedList {
|
||||||
return &txPricedList{
|
return &pricedList{
|
||||||
all: all,
|
all: all,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put inserts a new transaction into the heap.
|
// Put inserts a new transaction into the heap.
|
||||||
func (l *txPricedList) Put(tx *types.Transaction, local bool) {
|
func (l *pricedList) Put(tx *types.Transaction, local bool) {
|
||||||
if local {
|
if local {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -520,7 +520,7 @@ func (l *txPricedList) Put(tx *types.Transaction, local bool) {
|
||||||
// Removed notifies the prices transaction list that an old transaction dropped
|
// Removed notifies the prices transaction list that an old transaction dropped
|
||||||
// from the pool. The list will just keep a counter of stale objects and update
|
// from the pool. The list will just keep a counter of stale objects and update
|
||||||
// the heap if a large enough ratio of transactions go stale.
|
// the heap if a large enough ratio of transactions go stale.
|
||||||
func (l *txPricedList) Removed(count int) {
|
func (l *pricedList) Removed(count int) {
|
||||||
// Bump the stale counter, but exit if still too low (< 25%)
|
// Bump the stale counter, but exit if still too low (< 25%)
|
||||||
stales := atomic.AddInt64(&l.stales, int64(count))
|
stales := atomic.AddInt64(&l.stales, int64(count))
|
||||||
if int(stales) <= (len(l.urgent.list)+len(l.floating.list))/4 {
|
if int(stales) <= (len(l.urgent.list)+len(l.floating.list))/4 {
|
||||||
|
|
@ -532,7 +532,7 @@ func (l *txPricedList) Removed(count int) {
|
||||||
|
|
||||||
// Underpriced checks whether a transaction is cheaper than (or as cheap as) the
|
// Underpriced checks whether a transaction is cheaper than (or as cheap as) the
|
||||||
// lowest priced (remote) transaction currently being tracked.
|
// lowest priced (remote) transaction currently being tracked.
|
||||||
func (l *txPricedList) Underpriced(tx *types.Transaction) bool {
|
func (l *pricedList) Underpriced(tx *types.Transaction) bool {
|
||||||
// Note: with two queues, being underpriced is defined as being worse than the worst item
|
// Note: with two queues, being underpriced is defined as being worse than the worst item
|
||||||
// in all non-empty queues if there is any. If both queues are empty then nothing is underpriced.
|
// in all non-empty queues if there is any. If both queues are empty then nothing is underpriced.
|
||||||
return (l.underpricedFor(&l.urgent, tx) || len(l.urgent.list) == 0) &&
|
return (l.underpricedFor(&l.urgent, tx) || len(l.urgent.list) == 0) &&
|
||||||
|
|
@ -542,7 +542,7 @@ func (l *txPricedList) Underpriced(tx *types.Transaction) bool {
|
||||||
|
|
||||||
// underpricedFor checks whether a transaction is cheaper than (or as cheap as) the
|
// underpricedFor checks whether a transaction is cheaper than (or as cheap as) the
|
||||||
// lowest priced (remote) transaction in the given heap.
|
// lowest priced (remote) transaction in the given heap.
|
||||||
func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool {
|
func (l *pricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool {
|
||||||
// Discard stale price points if found at the heap start
|
// Discard stale price points if found at the heap start
|
||||||
for len(h.list) > 0 {
|
for len(h.list) > 0 {
|
||||||
head := h.list[0]
|
head := h.list[0]
|
||||||
|
|
@ -566,7 +566,7 @@ func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool
|
||||||
// priced list and returns them for further removal from the entire pool.
|
// priced list and returns them for further removal from the entire pool.
|
||||||
//
|
//
|
||||||
// Note local transaction won't be considered for eviction.
|
// Note local transaction won't be considered for eviction.
|
||||||
func (l *txPricedList) Discard(slots int, force bool) (types.Transactions, bool) {
|
func (l *pricedList) Discard(slots int, force bool) (types.Transactions, bool) {
|
||||||
drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop
|
drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop
|
||||||
for slots > 0 {
|
for slots > 0 {
|
||||||
if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio || floatingRatio == 0 {
|
if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio || floatingRatio == 0 {
|
||||||
|
|
@ -605,7 +605,7 @@ func (l *txPricedList) Discard(slots int, force bool) (types.Transactions, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reheap forcibly rebuilds the heap based on the current remote transaction set.
|
// Reheap forcibly rebuilds the heap based on the current remote transaction set.
|
||||||
func (l *txPricedList) Reheap() {
|
func (l *pricedList) Reheap() {
|
||||||
l.reheapMu.Lock()
|
l.reheapMu.Lock()
|
||||||
defer l.reheapMu.Unlock()
|
defer l.reheapMu.Unlock()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
@ -633,7 +633,7 @@ func (l *txPricedList) Reheap() {
|
||||||
|
|
||||||
// SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not
|
// SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not
|
||||||
// necessary to call right before SetBaseFee when processing a new block.
|
// necessary to call right before SetBaseFee when processing a new block.
|
||||||
func (l *txPricedList) SetBaseFee(baseFee *big.Int) {
|
func (l *pricedList) SetBaseFee(baseFee *big.Int) {
|
||||||
l.urgent.baseFee = baseFee
|
l.urgent.baseFee = baseFee
|
||||||
l.Reheap()
|
l.Reheap()
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -27,7 +27,7 @@ import (
|
||||||
|
|
||||||
// Tests that transactions can be added to strict lists and list contents and
|
// Tests that transactions can be added to strict lists and list contents and
|
||||||
// nonce boundaries are correctly maintained.
|
// nonce boundaries are correctly maintained.
|
||||||
func TestStrictTxListAdd(t *testing.T) {
|
func TestStrictListAdd(t *testing.T) {
|
||||||
// Generate a list of transactions to insert
|
// Generate a list of transactions to insert
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
|
|
||||||
|
|
@ -36,9 +36,9 @@ func TestStrictTxListAdd(t *testing.T) {
|
||||||
txs[i] = transaction(uint64(i), 0, key)
|
txs[i] = transaction(uint64(i), 0, key)
|
||||||
}
|
}
|
||||||
// Insert the transactions in a random order
|
// Insert the transactions in a random order
|
||||||
list := newTxList(true)
|
list := newList(true)
|
||||||
for _, v := range rand.Perm(len(txs)) {
|
for _, v := range rand.Perm(len(txs)) {
|
||||||
list.Add(txs[v], DefaultTxPoolConfig.PriceBump)
|
list.Add(txs[v], DefaultConfig.PriceBump)
|
||||||
}
|
}
|
||||||
// Verify internal state
|
// Verify internal state
|
||||||
if len(list.txs.items) != len(txs) {
|
if len(list.txs.items) != len(txs) {
|
||||||
|
|
@ -51,7 +51,7 @@ func TestStrictTxListAdd(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkTxListAdd(t *testing.B) {
|
func BenchmarkListAdd(t *testing.B) {
|
||||||
// Generate a list of transactions to insert
|
// Generate a list of transactions to insert
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
|
|
||||||
|
|
@ -60,11 +60,11 @@ func BenchmarkTxListAdd(t *testing.B) {
|
||||||
txs[i] = transaction(uint64(i), 0, key)
|
txs[i] = transaction(uint64(i), 0, key)
|
||||||
}
|
}
|
||||||
// Insert the transactions in a random order
|
// Insert the transactions in a random order
|
||||||
list := newTxList(true)
|
list := newList(true)
|
||||||
priceLimit := big.NewInt(int64(DefaultTxPoolConfig.PriceLimit))
|
priceLimit := big.NewInt(int64(DefaultConfig.PriceLimit))
|
||||||
t.ResetTimer()
|
t.ResetTimer()
|
||||||
for _, v := range rand.Perm(len(txs)) {
|
for _, v := range rand.Perm(len(txs)) {
|
||||||
list.Add(txs[v], DefaultTxPoolConfig.PriceBump)
|
list.Add(txs[v], DefaultConfig.PriceBump)
|
||||||
list.Filter(priceLimit, DefaultTxPoolConfig.PriceBump, nil, nil)
|
list.Filter(priceLimit, DefaultConfig.PriceBump, nil, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -23,18 +23,18 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
// txNoncer is a tiny virtual state database to manage the executable nonces of
|
// noncer is a tiny virtual state database to manage the executable nonces of
|
||||||
// accounts in the pool, falling back to reading from a real state database if
|
// accounts in the pool, falling back to reading from a real state database if
|
||||||
// an account is unknown.
|
// an account is unknown.
|
||||||
type txNoncer struct {
|
type noncer struct {
|
||||||
fallback *state.StateDB
|
fallback *state.StateDB
|
||||||
nonces map[common.Address]uint64
|
nonces map[common.Address]uint64
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTxNoncer creates a new virtual state database to track the pool nonces.
|
// newNoncer creates a new virtual state database to track the pool nonces.
|
||||||
func newTxNoncer(statedb *state.StateDB) *txNoncer {
|
func newNoncer(statedb *state.StateDB) *noncer {
|
||||||
return &txNoncer{
|
return &noncer{
|
||||||
fallback: statedb.Copy(),
|
fallback: statedb.Copy(),
|
||||||
nonces: make(map[common.Address]uint64),
|
nonces: make(map[common.Address]uint64),
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ func newTxNoncer(statedb *state.StateDB) *txNoncer {
|
||||||
|
|
||||||
// get returns the current nonce of an account, falling back to a real state
|
// get returns the current nonce of an account, falling back to a real state
|
||||||
// database if the account is unknown.
|
// database if the account is unknown.
|
||||||
func (txn *txNoncer) get(addr common.Address) uint64 {
|
func (txn *noncer) get(addr common.Address) uint64 {
|
||||||
// We use mutex for get operation is the underlying
|
// We use mutex for get operation is the underlying
|
||||||
// state will mutate db even for read access.
|
// state will mutate db even for read access.
|
||||||
txn.lock.Lock()
|
txn.lock.Lock()
|
||||||
|
|
@ -58,7 +58,7 @@ func (txn *txNoncer) get(addr common.Address) uint64 {
|
||||||
|
|
||||||
// set inserts a new virtual nonce into the virtual state database to be returned
|
// set inserts a new virtual nonce into the virtual state database to be returned
|
||||||
// whenever the pool requests it instead of reaching into the real state database.
|
// whenever the pool requests it instead of reaching into the real state database.
|
||||||
func (txn *txNoncer) set(addr common.Address, nonce uint64) {
|
func (txn *noncer) set(addr common.Address, nonce uint64) {
|
||||||
txn.lock.Lock()
|
txn.lock.Lock()
|
||||||
defer txn.lock.Unlock()
|
defer txn.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ func (txn *txNoncer) set(addr common.Address, nonce uint64) {
|
||||||
|
|
||||||
// setIfLower updates a new virtual nonce into the virtual state database if the
|
// setIfLower updates a new virtual nonce into the virtual state database if the
|
||||||
// the new one is lower.
|
// the new one is lower.
|
||||||
func (txn *txNoncer) setIfLower(addr common.Address, nonce uint64) {
|
func (txn *noncer) setIfLower(addr common.Address, nonce uint64) {
|
||||||
txn.lock.Lock()
|
txn.lock.Lock()
|
||||||
defer txn.lock.Unlock()
|
defer txn.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ func (txn *txNoncer) setIfLower(addr common.Address, nonce uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setAll sets the nonces for all accounts to the given map.
|
// setAll sets the nonces for all accounts to the given map.
|
||||||
func (txn *txNoncer) setAll(all map[common.Address]uint64) {
|
func (txn *noncer) setAll(all map[common.Address]uint64) {
|
||||||
txn.lock.Lock()
|
txn.lock.Lock()
|
||||||
defer txn.lock.Unlock()
|
defer txn.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/event"
|
"github.com/XinFinOrg/XDPoSChain/event"
|
||||||
|
|
@ -84,7 +85,7 @@ type blockChainXDCx interface {
|
||||||
GetBlock(hash common.Hash, number uint64) *types.Block
|
GetBlock(hash common.Hash, number uint64) *types.Block
|
||||||
OrderStateAt(block *types.Block) (*tradingstate.TradingStateDB, error)
|
OrderStateAt(block *types.Block) (*tradingstate.TradingStateDB, error)
|
||||||
StateAt(root common.Hash) (*state.StateDB, error)
|
StateAt(root common.Hash) (*state.StateDB, error)
|
||||||
SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription
|
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
||||||
Engine() consensus.Engine
|
Engine() consensus.Engine
|
||||||
// GetHeader returns the hash corresponding to their hash.
|
// GetHeader returns the hash corresponding to their hash.
|
||||||
GetHeader(common.Hash, uint64) *types.Header
|
GetHeader(common.Hash, uint64) *types.Header
|
||||||
|
|
@ -133,7 +134,7 @@ type OrderPool struct {
|
||||||
|
|
||||||
txFeed event.Feed
|
txFeed event.Feed
|
||||||
scope event.SubscriptionScope
|
scope event.SubscriptionScope
|
||||||
chainHeadCh chan ChainHeadEvent
|
chainHeadCh chan core.ChainHeadEvent
|
||||||
chainHeadSub event.Subscription
|
chainHeadSub event.Subscription
|
||||||
signer types.OrderSigner
|
signer types.OrderSigner
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
@ -170,7 +171,7 @@ func NewOrderPool(chainconfig *params.ChainConfig, chain blockChainXDCx) *OrderP
|
||||||
queue: make(map[common.Address]*ordertxList),
|
queue: make(map[common.Address]*ordertxList),
|
||||||
beats: make(map[common.Address]time.Time),
|
beats: make(map[common.Address]time.Time),
|
||||||
all: make(map[common.Hash]*types.OrderTransaction),
|
all: make(map[common.Hash]*types.OrderTransaction),
|
||||||
chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize),
|
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
||||||
}
|
}
|
||||||
pool.locals = newOrderAccountSet(pool.signer)
|
pool.locals = newOrderAccountSet(pool.signer)
|
||||||
pool.reset(nil, chain.CurrentBlock())
|
pool.reset(nil, chain.CurrentBlock())
|
||||||
|
|
@ -340,7 +341,7 @@ func (pool *OrderPool) Stop() {
|
||||||
|
|
||||||
// SubscribeTxPreEvent registers a subscription of TxPreEvent and
|
// SubscribeTxPreEvent registers a subscription of TxPreEvent and
|
||||||
// starts sending event to the given channel.
|
// starts sending event to the given channel.
|
||||||
func (pool *OrderPool) SubscribeTxPreEvent(ch chan<- OrderTxPreEvent) event.Subscription {
|
func (pool *OrderPool) SubscribeTxPreEvent(ch chan<- core.OrderTxPreEvent) event.Subscription {
|
||||||
return pool.scope.Track(pool.txFeed.Subscribe(ch))
|
return pool.scope.Track(pool.txFeed.Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -464,7 +465,7 @@ func (pool *OrderPool) validateOrder(tx *types.OrderTransaction) error {
|
||||||
if orderType == OrderTypeLimit {
|
if orderType == OrderTypeLimit {
|
||||||
XDPoSEngine, ok := pool.chain.Engine().(*XDPoS.XDPoS)
|
XDPoSEngine, ok := pool.chain.Engine().(*XDPoS.XDPoS)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrNotXDPoS
|
return core.ErrNotXDPoS
|
||||||
}
|
}
|
||||||
XDCXServ := XDPoSEngine.GetXDCXService()
|
XDCXServ := XDPoSEngine.GetXDCXService()
|
||||||
if XDCXServ == nil {
|
if XDCXServ == nil {
|
||||||
|
|
@ -550,10 +551,10 @@ func (pool *OrderPool) validateTx(tx *types.OrderTransaction, local bool) error
|
||||||
}
|
}
|
||||||
// Ensure the transaction adheres to nonce ordering
|
// Ensure the transaction adheres to nonce ordering
|
||||||
if pool.currentOrderState.GetNonce(from.Hash()) > tx.Nonce() {
|
if pool.currentOrderState.GetNonce(from.Hash()) > tx.Nonce() {
|
||||||
return ErrNonceTooLow
|
return core.ErrNonceTooLow
|
||||||
}
|
}
|
||||||
if pool.pendingState.GetNonce(from.Hash())+common.LimitThresholdNonceInQueue < tx.Nonce() {
|
if pool.pendingState.GetNonce(from.Hash())+common.LimitThresholdNonceInQueue < tx.Nonce() {
|
||||||
return ErrNonceTooHigh
|
return core.ErrNonceTooHigh
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -603,7 +604,7 @@ func (pool *OrderPool) add(tx *types.OrderTransaction, local bool) (bool, error)
|
||||||
pool.journalTx(from, tx)
|
pool.journalTx(from, tx)
|
||||||
|
|
||||||
log.Debug("Pooled new executable transaction", "hash", hash, "useraddress", tx.UserAddress().Hex(), "nonce", tx.Nonce(), "status", tx.Status(), "orderid", tx.OrderID())
|
log.Debug("Pooled new executable transaction", "hash", hash, "useraddress", tx.UserAddress().Hex(), "nonce", tx.Nonce(), "status", tx.Status(), "orderid", tx.OrderID())
|
||||||
go pool.txFeed.Send(OrderTxPreEvent{tx})
|
go pool.txFeed.Send(core.OrderTxPreEvent{Tx: tx})
|
||||||
return old != nil, nil
|
return old != nil, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -690,7 +691,7 @@ func (pool *OrderPool) promoteTx(addr common.Address, hash common.Hash, tx *type
|
||||||
pool.beats[addr] = time.Now()
|
pool.beats[addr] = time.Now()
|
||||||
pool.pendingState.SetNonce(addr.Hash(), tx.Nonce()+1)
|
pool.pendingState.SetNonce(addr.Hash(), tx.Nonce()+1)
|
||||||
log.Debug("promoteTx txFeed.Send", "addr", tx.UserAddress().Hex(), "nonce", tx.Nonce(), "ohash", tx.OrderHash().Hex(), "status", tx.Status(), "orderid", tx.OrderID())
|
log.Debug("promoteTx txFeed.Send", "addr", tx.UserAddress().Hex(), "nonce", tx.Nonce(), "ohash", tx.OrderHash().Hex(), "status", tx.Status(), "orderid", tx.OrderID())
|
||||||
go pool.txFeed.Send(OrderTxPreEvent{tx})
|
go pool.txFeed.Send(core.OrderTxPreEvent{Tx: tx})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddLocal enqueues a single transaction into the pool if it is valid, marking
|
// AddLocal enqueues a single transaction into the pool if it is valid, marking
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/heap"
|
"container/heap"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/event"
|
"github.com/XinFinOrg/XDPoSChain/event"
|
||||||
|
|
@ -63,10 +64,6 @@ var (
|
||||||
// ErrInvalidSender is returned if the transaction contains an invalid signature.
|
// ErrInvalidSender is returned if the transaction contains an invalid signature.
|
||||||
ErrInvalidSender = errors.New("invalid sender")
|
ErrInvalidSender = errors.New("invalid sender")
|
||||||
|
|
||||||
// ErrNonceTooLow is returned if the nonce of a transaction is lower than the
|
|
||||||
// one present in the local chain.
|
|
||||||
ErrNonceTooLow = errors.New("nonce too low")
|
|
||||||
|
|
||||||
// ErrUnderpriced is returned if a transaction's gas price is below the minimum
|
// ErrUnderpriced is returned if a transaction's gas price is below the minimum
|
||||||
// configured for the transaction pool.
|
// configured for the transaction pool.
|
||||||
ErrUnderpriced = errors.New("transaction underpriced")
|
ErrUnderpriced = errors.New("transaction underpriced")
|
||||||
|
|
@ -79,14 +76,6 @@ var (
|
||||||
// with a different one without the required price bump.
|
// with a different one without the required price bump.
|
||||||
ErrReplaceUnderpriced = errors.New("replacement transaction underpriced")
|
ErrReplaceUnderpriced = errors.New("replacement transaction underpriced")
|
||||||
|
|
||||||
// ErrInsufficientFunds is returned if the total cost of executing a transaction
|
|
||||||
// is higher than the balance of the user's account.
|
|
||||||
ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")
|
|
||||||
|
|
||||||
// ErrIntrinsicGas is returned if the transaction is specified to use less gas
|
|
||||||
// than required to start the invocation.
|
|
||||||
ErrIntrinsicGas = errors.New("intrinsic gas too low")
|
|
||||||
|
|
||||||
// ErrGasLimit is returned if a transaction's requested gas limit exceeds the
|
// ErrGasLimit is returned if a transaction's requested gas limit exceeds the
|
||||||
// maximum allowance of the current block.
|
// maximum allowance of the current block.
|
||||||
ErrGasLimit = errors.New("exceeds block gas limit")
|
ErrGasLimit = errors.New("exceeds block gas limit")
|
||||||
|
|
@ -134,6 +123,7 @@ var (
|
||||||
invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil)
|
invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil)
|
||||||
underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil)
|
underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil)
|
||||||
overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil)
|
overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil)
|
||||||
|
|
||||||
// throttleTxMeter counts how many transactions are rejected due to too-many-changes between
|
// throttleTxMeter counts how many transactions are rejected due to too-many-changes between
|
||||||
// txpool reorgs.
|
// txpool reorgs.
|
||||||
throttleTxMeter = metrics.NewRegisteredMeter("txpool/throttle", nil)
|
throttleTxMeter = metrics.NewRegisteredMeter("txpool/throttle", nil)
|
||||||
|
|
@ -167,7 +157,7 @@ type blockChain interface {
|
||||||
CurrentBlock() *types.Block
|
CurrentBlock() *types.Block
|
||||||
GetBlock(hash common.Hash, number uint64) *types.Block
|
GetBlock(hash common.Hash, number uint64) *types.Block
|
||||||
StateAt(root common.Hash) (*state.StateDB, error)
|
StateAt(root common.Hash) (*state.StateDB, error)
|
||||||
SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription
|
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
||||||
|
|
||||||
// Engine retrieves the chain's consensus engine.
|
// Engine retrieves the chain's consensus engine.
|
||||||
Engine() consensus.Engine
|
Engine() consensus.Engine
|
||||||
|
|
@ -182,8 +172,8 @@ type blockChain interface {
|
||||||
Config() *params.ChainConfig
|
Config() *params.ChainConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxPoolConfig are the configuration parameters of the transaction pool.
|
// Config are the configuration parameters of the transaction pool.
|
||||||
type TxPoolConfig struct {
|
type Config struct {
|
||||||
Locals []common.Address // Addresses that should be treated by default as local
|
Locals []common.Address // Addresses that should be treated by default as local
|
||||||
NoLocals bool // Whether local transaction handling should be disabled
|
NoLocals bool // Whether local transaction handling should be disabled
|
||||||
Journal string // Journal of local transactions to survive node restarts
|
Journal string // Journal of local transactions to survive node restarts
|
||||||
|
|
@ -200,9 +190,9 @@ type TxPoolConfig struct {
|
||||||
Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
|
Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultTxPoolConfig contains the default configurations for the transaction
|
// DefaultConfig contains the default configurations for the transaction
|
||||||
// pool.
|
// pool.
|
||||||
var DefaultTxPoolConfig = TxPoolConfig{
|
var DefaultConfig = Config{
|
||||||
Journal: "transactions.rlp",
|
Journal: "transactions.rlp",
|
||||||
Rejournal: time.Hour,
|
Rejournal: time.Hour,
|
||||||
|
|
||||||
|
|
@ -219,39 +209,39 @@ var DefaultTxPoolConfig = TxPoolConfig{
|
||||||
|
|
||||||
// sanitize checks the provided user configurations and changes anything that's
|
// sanitize checks the provided user configurations and changes anything that's
|
||||||
// unreasonable or unworkable.
|
// unreasonable or unworkable.
|
||||||
func (config *TxPoolConfig) sanitize() TxPoolConfig {
|
func (config *Config) sanitize() Config {
|
||||||
conf := *config
|
conf := *config
|
||||||
if conf.Rejournal < time.Second {
|
if conf.Rejournal < time.Second {
|
||||||
log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second)
|
log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second)
|
||||||
conf.Rejournal = time.Second
|
conf.Rejournal = time.Second
|
||||||
}
|
}
|
||||||
if conf.PriceLimit < 1 {
|
if conf.PriceLimit < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit)
|
log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultConfig.PriceLimit)
|
||||||
conf.PriceLimit = DefaultTxPoolConfig.PriceLimit
|
conf.PriceLimit = DefaultConfig.PriceLimit
|
||||||
}
|
}
|
||||||
if conf.PriceBump < 1 {
|
if conf.PriceBump < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultTxPoolConfig.PriceBump)
|
log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultConfig.PriceBump)
|
||||||
conf.PriceBump = DefaultTxPoolConfig.PriceBump
|
conf.PriceBump = DefaultConfig.PriceBump
|
||||||
}
|
}
|
||||||
if conf.AccountSlots < 1 {
|
if conf.AccountSlots < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool account slots", "provided", conf.AccountSlots, "updated", DefaultTxPoolConfig.AccountSlots)
|
log.Warn("Sanitizing invalid txpool account slots", "provided", conf.AccountSlots, "updated", DefaultConfig.AccountSlots)
|
||||||
conf.AccountSlots = DefaultTxPoolConfig.AccountSlots
|
conf.AccountSlots = DefaultConfig.AccountSlots
|
||||||
}
|
}
|
||||||
if conf.GlobalSlots < 1 {
|
if conf.GlobalSlots < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool global slots", "provided", conf.GlobalSlots, "updated", DefaultTxPoolConfig.GlobalSlots)
|
log.Warn("Sanitizing invalid txpool global slots", "provided", conf.GlobalSlots, "updated", DefaultConfig.GlobalSlots)
|
||||||
conf.GlobalSlots = DefaultTxPoolConfig.GlobalSlots
|
conf.GlobalSlots = DefaultConfig.GlobalSlots
|
||||||
}
|
}
|
||||||
if conf.AccountQueue < 1 {
|
if conf.AccountQueue < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool account queue", "provided", conf.AccountQueue, "updated", DefaultTxPoolConfig.AccountQueue)
|
log.Warn("Sanitizing invalid txpool account queue", "provided", conf.AccountQueue, "updated", DefaultConfig.AccountQueue)
|
||||||
conf.AccountQueue = DefaultTxPoolConfig.AccountQueue
|
conf.AccountQueue = DefaultConfig.AccountQueue
|
||||||
}
|
}
|
||||||
if conf.GlobalQueue < 1 {
|
if conf.GlobalQueue < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool global queue", "provided", conf.GlobalQueue, "updated", DefaultTxPoolConfig.GlobalQueue)
|
log.Warn("Sanitizing invalid txpool global queue", "provided", conf.GlobalQueue, "updated", DefaultConfig.GlobalQueue)
|
||||||
conf.GlobalQueue = DefaultTxPoolConfig.GlobalQueue
|
conf.GlobalQueue = DefaultConfig.GlobalQueue
|
||||||
}
|
}
|
||||||
if conf.Lifetime < 1 {
|
if conf.Lifetime < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultTxPoolConfig.Lifetime)
|
log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultConfig.Lifetime)
|
||||||
conf.Lifetime = DefaultTxPoolConfig.Lifetime
|
conf.Lifetime = DefaultConfig.Lifetime
|
||||||
}
|
}
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +254,7 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig {
|
||||||
// current state) and future transactions. Transactions move between those
|
// current state) and future transactions. Transactions move between those
|
||||||
// two states over time as they are received and processed.
|
// two states over time as they are received and processed.
|
||||||
type TxPool struct {
|
type TxPool struct {
|
||||||
config TxPoolConfig
|
config Config
|
||||||
chainconfig *params.ChainConfig
|
chainconfig *params.ChainConfig
|
||||||
chain blockChain
|
chain blockChain
|
||||||
gasPrice *big.Int
|
gasPrice *big.Int
|
||||||
|
|
@ -277,19 +267,19 @@ type TxPool struct {
|
||||||
eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions.
|
eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions.
|
||||||
|
|
||||||
currentState *state.StateDB // Current state in the blockchain head
|
currentState *state.StateDB // Current state in the blockchain head
|
||||||
pendingNonces *txNoncer // Pending state tracking virtual nonces
|
pendingNonces *noncer // Pending state tracking virtual nonces
|
||||||
currentMaxGas uint64 // Current gas limit for transaction caps
|
currentMaxGas uint64 // Current gas limit for transaction caps
|
||||||
|
|
||||||
locals *accountSet // Set of local transaction to exempt from eviction rules
|
locals *accountSet // Set of local transaction to exempt from eviction rules
|
||||||
journal *txJournal // Journal of local transaction to back up to disk
|
journal *journal // Journal of local transaction to back up to disk
|
||||||
|
|
||||||
pending map[common.Address]*txList // All currently processable transactions
|
pending map[common.Address]*list // All currently processable transactions
|
||||||
queue map[common.Address]*txList // 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 *txLookup // All transactions to allow lookups
|
all *lookup // All transactions to allow lookups
|
||||||
priced *txPricedList // All transactions sorted by price
|
priced *pricedList // All transactions sorted by price
|
||||||
|
|
||||||
chainHeadCh chan ChainHeadEvent
|
chainHeadCh chan core.ChainHeadEvent
|
||||||
chainHeadSub event.Subscription
|
chainHeadSub event.Subscription
|
||||||
reqResetCh chan *txpoolResetRequest
|
reqResetCh chan *txpoolResetRequest
|
||||||
reqPromoteCh chan *accountSet
|
reqPromoteCh chan *accountSet
|
||||||
|
|
@ -311,7 +301,7 @@ type txpoolResetRequest struct {
|
||||||
|
|
||||||
// NewTxPool creates a new transaction pool to gather, sort and filter inbound
|
// NewTxPool creates a new transaction pool to gather, sort and filter inbound
|
||||||
// transactions from the network.
|
// transactions from the network.
|
||||||
func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool {
|
func NewTxPool(config Config, chainconfig *params.ChainConfig, chain blockChain) *TxPool {
|
||||||
// Sanitize the input to ensure no vulnerable gas prices are set
|
// Sanitize the input to ensure no vulnerable gas prices are set
|
||||||
config = (&config).sanitize()
|
config = (&config).sanitize()
|
||||||
|
|
||||||
|
|
@ -321,11 +311,11 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
|
||||||
chainconfig: chainconfig,
|
chainconfig: chainconfig,
|
||||||
chain: chain,
|
chain: chain,
|
||||||
signer: types.LatestSigner(chainconfig),
|
signer: types.LatestSigner(chainconfig),
|
||||||
pending: make(map[common.Address]*txList),
|
pending: make(map[common.Address]*list),
|
||||||
queue: make(map[common.Address]*txList),
|
queue: make(map[common.Address]*list),
|
||||||
beats: make(map[common.Address]time.Time),
|
beats: make(map[common.Address]time.Time),
|
||||||
all: newTxLookup(),
|
all: newLookup(),
|
||||||
chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize),
|
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
||||||
reqResetCh: make(chan *txpoolResetRequest),
|
reqResetCh: make(chan *txpoolResetRequest),
|
||||||
reqPromoteCh: make(chan *accountSet),
|
reqPromoteCh: make(chan *accountSet),
|
||||||
queueTxEventCh: make(chan *types.Transaction),
|
queueTxEventCh: make(chan *types.Transaction),
|
||||||
|
|
@ -340,7 +330,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
|
||||||
log.Info("Setting new local account", "address", addr)
|
log.Info("Setting new local account", "address", addr)
|
||||||
pool.locals.add(addr)
|
pool.locals.add(addr)
|
||||||
}
|
}
|
||||||
pool.priced = newTxPricedList(pool.all)
|
pool.priced = newPricedList(pool.all)
|
||||||
pool.reset(nil, chain.CurrentBlock().Header())
|
pool.reset(nil, chain.CurrentBlock().Header())
|
||||||
|
|
||||||
// Start the reorg loop early so it can handle requests generated during journal loading.
|
// Start the reorg loop early so it can handle requests generated during journal loading.
|
||||||
|
|
@ -463,7 +453,7 @@ func (pool *TxPool) Stop() {
|
||||||
|
|
||||||
// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and
|
// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and
|
||||||
// starts sending event to the given channel.
|
// starts sending event to the given channel.
|
||||||
func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- NewTxsEvent) event.Subscription {
|
func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
|
||||||
return pool.scope.Track(pool.txFeed.Subscribe(ch))
|
return pool.scope.Track(pool.txFeed.Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -630,11 +620,11 @@ func (pool *TxPool) GetSender(tx *types.Transaction) (common.Address, error) {
|
||||||
func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
// Accept only legacy transactions until EIP-2718/2930 activates.
|
// Accept only legacy transactions until EIP-2718/2930 activates.
|
||||||
if !pool.eip2718 && tx.Type() != types.LegacyTxType {
|
if !pool.eip2718 && tx.Type() != types.LegacyTxType {
|
||||||
return ErrTxTypeNotSupported
|
return core.ErrTxTypeNotSupported
|
||||||
}
|
}
|
||||||
// Reject dynamic fee transactions until EIP-1559 activates.
|
// Reject dynamic fee transactions until EIP-1559 activates.
|
||||||
if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType {
|
if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType {
|
||||||
return ErrTxTypeNotSupported
|
return core.ErrTxTypeNotSupported
|
||||||
}
|
}
|
||||||
// Reject transactions over defined size to prevent DOS attacks
|
// Reject transactions over defined size to prevent DOS attacks
|
||||||
if uint64(tx.Size()) > txMaxSize {
|
if uint64(tx.Size()) > txMaxSize {
|
||||||
|
|
@ -659,14 +649,14 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
}
|
}
|
||||||
// Sanity check for extremely large numbers
|
// Sanity check for extremely large numbers
|
||||||
if tx.GasFeeCap().BitLen() > 256 {
|
if tx.GasFeeCap().BitLen() > 256 {
|
||||||
return ErrFeeCapVeryHigh
|
return core.ErrFeeCapVeryHigh
|
||||||
}
|
}
|
||||||
if tx.GasTipCap().BitLen() > 256 {
|
if tx.GasTipCap().BitLen() > 256 {
|
||||||
return ErrTipVeryHigh
|
return core.ErrTipVeryHigh
|
||||||
}
|
}
|
||||||
// Ensure gasFeeCap is greater than or equal to gasTipCap.
|
// Ensure gasFeeCap is greater than or equal to gasTipCap.
|
||||||
if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 {
|
if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 {
|
||||||
return ErrTipAboveFeeCap
|
return core.ErrTipAboveFeeCap
|
||||||
}
|
}
|
||||||
// Make sure the transaction is signed properly.
|
// Make sure the transaction is signed properly.
|
||||||
from, err := types.Sender(pool.signer, tx)
|
from, err := types.Sender(pool.signer, tx)
|
||||||
|
|
@ -681,10 +671,10 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
}
|
}
|
||||||
// Ensure the transaction adheres to nonce ordering
|
// Ensure the transaction adheres to nonce ordering
|
||||||
if pool.currentState.GetNonce(from) > tx.Nonce() {
|
if pool.currentState.GetNonce(from) > tx.Nonce() {
|
||||||
return ErrNonceTooLow
|
return core.ErrNonceTooLow
|
||||||
}
|
}
|
||||||
if pool.pendingNonces.get(from)+common.LimitThresholdNonceInQueue < tx.Nonce() {
|
if pool.pendingNonces.get(from)+common.LimitThresholdNonceInQueue < tx.Nonce() {
|
||||||
return ErrNonceTooHigh
|
return core.ErrNonceTooHigh
|
||||||
}
|
}
|
||||||
// Transactor should have enough funds to cover the costs
|
// Transactor should have enough funds to cover the costs
|
||||||
// cost == V + GP * GL
|
// cost == V + GP * GL
|
||||||
|
|
@ -701,24 +691,24 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
if value, ok := pool.trc21FeeCapacity[*tx.To()]; ok {
|
if value, ok := pool.trc21FeeCapacity[*tx.To()]; ok {
|
||||||
feeCapacity = value
|
feeCapacity = value
|
||||||
if !state.ValidateTRC21Tx(pool.currentState, from, *tx.To(), tx.Data()) {
|
if !state.ValidateTRC21Tx(pool.currentState, from, *tx.To(), tx.Data()) {
|
||||||
return ErrInsufficientFunds
|
return core.ErrInsufficientFunds
|
||||||
}
|
}
|
||||||
cost = tx.TxCost(number)
|
cost = tx.TxCost(number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if new(big.Int).Add(balance, feeCapacity).Cmp(cost) < 0 {
|
if new(big.Int).Add(balance, feeCapacity).Cmp(cost) < 0 {
|
||||||
return ErrInsufficientFunds
|
return core.ErrInsufficientFunds
|
||||||
}
|
}
|
||||||
|
|
||||||
if tx.To() == nil || (tx.To() != nil && !tx.IsSpecialTransaction()) {
|
if tx.To() == nil || (tx.To() != nil && !tx.IsSpecialTransaction()) {
|
||||||
// Ensure the transaction has more gas than the basic tx fee.
|
// Ensure the transaction has more gas than the basic tx fee.
|
||||||
intrGas, err := IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true)
|
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Exclude check smart contract sign address.
|
// Exclude check smart contract sign address.
|
||||||
if tx.Gas() < intrGas {
|
if tx.Gas() < intrGas {
|
||||||
return ErrIntrinsicGas
|
return core.ErrIntrinsicGas
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check zero gas price.
|
// Check zero gas price.
|
||||||
|
|
@ -742,13 +732,13 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
// validate minFee slot for XDCZ
|
// validate minFee slot for XDCZ
|
||||||
if tx.IsXDCZApplyTransaction() {
|
if tx.IsXDCZApplyTransaction() {
|
||||||
copyState := pool.currentState.Copy()
|
copyState := pool.currentState.Copy()
|
||||||
return ValidateXDCZApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:]))
|
return core.ValidateXDCZApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate balance slot, token decimal for XDCX
|
// validate balance slot, token decimal for XDCX
|
||||||
if tx.IsXDCXApplyTransaction() {
|
if tx.IsXDCXApplyTransaction() {
|
||||||
copyState := pool.currentState.Copy()
|
copyState := pool.currentState.Copy()
|
||||||
return ValidateXDCXApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:]))
|
return core.ValidateXDCXApplyTransaction(pool.chain, nil, copyState, common.BytesToAddress(tx.Data()[4:]))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -870,7 +860,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction, local boo
|
||||||
// Try to insert the transaction into the future queue
|
// Try to insert the transaction into the future queue
|
||||||
from, _ := types.Sender(pool.signer, tx) // already validated
|
from, _ := types.Sender(pool.signer, tx) // already validated
|
||||||
if pool.queue[from] == nil {
|
if pool.queue[from] == nil {
|
||||||
pool.queue[from] = newTxList(false)
|
pool.queue[from] = newList(false)
|
||||||
}
|
}
|
||||||
inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump)
|
inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump)
|
||||||
if !inserted {
|
if !inserted {
|
||||||
|
|
@ -922,7 +912,7 @@ func (pool *TxPool) journalTx(from common.Address, tx *types.Transaction) {
|
||||||
func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) bool {
|
func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) bool {
|
||||||
// Try to insert the transaction into the pending queue
|
// Try to insert the transaction into the pending queue
|
||||||
if pool.pending[addr] == nil {
|
if pool.pending[addr] == nil {
|
||||||
pool.pending[addr] = newTxList(true)
|
pool.pending[addr] = newList(true)
|
||||||
}
|
}
|
||||||
list := pool.pending[addr]
|
list := pool.pending[addr]
|
||||||
|
|
||||||
|
|
@ -955,7 +945,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T
|
||||||
func (pool *TxPool) promoteSpecialTx(addr common.Address, tx *types.Transaction, isLocal bool) (bool, error) {
|
func (pool *TxPool) promoteSpecialTx(addr common.Address, tx *types.Transaction, isLocal bool) (bool, error) {
|
||||||
// Try to insert the transaction into the pending queue
|
// Try to insert the transaction into the pending queue
|
||||||
if pool.pending[addr] == nil {
|
if pool.pending[addr] == nil {
|
||||||
pool.pending[addr] = newTxList(true)
|
pool.pending[addr] = newList(true)
|
||||||
}
|
}
|
||||||
list := pool.pending[addr]
|
list := pool.pending[addr]
|
||||||
|
|
||||||
|
|
@ -986,7 +976,7 @@ func (pool *TxPool) promoteSpecialTx(addr common.Address, tx *types.Transaction,
|
||||||
// Set the potentially new pending nonce and notify any subsystems of the new tx
|
// Set the potentially new pending nonce and notify any subsystems of the new tx
|
||||||
pool.beats[addr] = time.Now()
|
pool.beats[addr] = time.Now()
|
||||||
pool.pendingNonces.set(addr, tx.Nonce()+1)
|
pool.pendingNonces.set(addr, tx.Nonce()+1)
|
||||||
go pool.txFeed.Send(NewTxsEvent{types.Transactions{tx}})
|
go pool.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1228,7 +1218,7 @@ func (pool *TxPool) scheduleReorgLoop() {
|
||||||
launchNextRun bool
|
launchNextRun bool
|
||||||
reset *txpoolResetRequest
|
reset *txpoolResetRequest
|
||||||
dirtyAccounts *accountSet
|
dirtyAccounts *accountSet
|
||||||
queuedEvents = make(map[common.Address]*txSortedMap)
|
queuedEvents = make(map[common.Address]*sortedMap)
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
// Launch next background reorg if needed
|
// Launch next background reorg if needed
|
||||||
|
|
@ -1241,7 +1231,7 @@ func (pool *TxPool) scheduleReorgLoop() {
|
||||||
launchNextRun = false
|
launchNextRun = false
|
||||||
|
|
||||||
reset, dirtyAccounts = nil, nil
|
reset, dirtyAccounts = nil, nil
|
||||||
queuedEvents = make(map[common.Address]*txSortedMap)
|
queuedEvents = make(map[common.Address]*sortedMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
|
@ -1270,7 +1260,7 @@ func (pool *TxPool) scheduleReorgLoop() {
|
||||||
// request one later if they want the events sent.
|
// request one later if they want the events sent.
|
||||||
addr, _ := types.Sender(pool.signer, tx)
|
addr, _ := types.Sender(pool.signer, tx)
|
||||||
if _, ok := queuedEvents[addr]; !ok {
|
if _, ok := queuedEvents[addr]; !ok {
|
||||||
queuedEvents[addr] = newTxSortedMap()
|
queuedEvents[addr] = newSortedMap()
|
||||||
}
|
}
|
||||||
queuedEvents[addr].Put(tx)
|
queuedEvents[addr].Put(tx)
|
||||||
|
|
||||||
|
|
@ -1289,7 +1279,7 @@ func (pool *TxPool) scheduleReorgLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop.
|
// runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop.
|
||||||
func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*txSortedMap) {
|
func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*sortedMap) {
|
||||||
defer func(t0 time.Time) {
|
defer func(t0 time.Time) {
|
||||||
reorgDurationTimer.Update(time.Since(t0))
|
reorgDurationTimer.Update(time.Since(t0))
|
||||||
}(time.Now())
|
}(time.Now())
|
||||||
|
|
@ -1352,7 +1342,7 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt
|
||||||
for _, tx := range promoted {
|
for _, tx := range promoted {
|
||||||
addr, _ := types.Sender(pool.signer, tx)
|
addr, _ := types.Sender(pool.signer, tx)
|
||||||
if _, ok := events[addr]; !ok {
|
if _, ok := events[addr]; !ok {
|
||||||
events[addr] = newTxSortedMap()
|
events[addr] = newSortedMap()
|
||||||
}
|
}
|
||||||
events[addr].Put(tx)
|
events[addr].Put(tx)
|
||||||
}
|
}
|
||||||
|
|
@ -1361,7 +1351,7 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt
|
||||||
for _, set := range events {
|
for _, set := range events {
|
||||||
txs = append(txs, set.Flatten()...)
|
txs = append(txs, set.Flatten()...)
|
||||||
}
|
}
|
||||||
pool.txFeed.Send(NewTxsEvent{txs})
|
pool.txFeed.Send(core.NewTxsEvent{Txs: txs})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1388,7 +1378,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
|
||||||
if rem == nil {
|
if rem == nil {
|
||||||
// This can happen if a setHead is performed, where we simply discard the old
|
// This can happen if a setHead is performed, where we simply discard the old
|
||||||
// head from the chain.
|
// head from the chain.
|
||||||
// If that is the case, we don't have the lost transactions any more, and
|
// If that is the case, we don't have the lost transactions anymore, and
|
||||||
// there's nothing to add
|
// there's nothing to add
|
||||||
if newNum >= oldNum {
|
if newNum >= oldNum {
|
||||||
// If we reorged to a same or higher number, then it's not a case of setHead
|
// If we reorged to a same or higher number, then it's not a case of setHead
|
||||||
|
|
@ -1442,12 +1432,12 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
|
||||||
}
|
}
|
||||||
pool.currentState = statedb
|
pool.currentState = statedb
|
||||||
pool.trc21FeeCapacity = state.GetTRC21FeeCapacityFromStateWithCache(newHead.Root, statedb)
|
pool.trc21FeeCapacity = state.GetTRC21FeeCapacityFromStateWithCache(newHead.Root, statedb)
|
||||||
pool.pendingNonces = newTxNoncer(statedb)
|
pool.pendingNonces = newNoncer(statedb)
|
||||||
pool.currentMaxGas = newHead.GasLimit
|
pool.currentMaxGas = newHead.GasLimit
|
||||||
|
|
||||||
// Inject any transactions discarded due to reorgs
|
// Inject any transactions discarded due to reorgs
|
||||||
log.Debug("Reinjecting stale transactions", "count", len(reinject))
|
log.Debug("Reinjecting stale transactions", "count", len(reinject))
|
||||||
senderCacher.recover(pool.signer, reinject)
|
core.SenderCacher.Recover(pool.signer, reinject)
|
||||||
pool.addTxsLocked(reinject, false)
|
pool.addTxsLocked(reinject, false)
|
||||||
|
|
||||||
// Update all fork indicator by next pending block number.
|
// Update all fork indicator by next pending block number.
|
||||||
|
|
@ -1718,8 +1708,6 @@ func (pool *TxPool) demoteUnexecutables() {
|
||||||
pool.enqueueTx(hash, tx, false, false)
|
pool.enqueueTx(hash, tx, false, false)
|
||||||
}
|
}
|
||||||
pendingGauge.Dec(int64(len(gapped)))
|
pendingGauge.Dec(int64(len(gapped)))
|
||||||
// This might happen in a reorg, so log it to the metering
|
|
||||||
blockReorgInvalidatedTx.Mark(int64(len(gapped)))
|
|
||||||
}
|
}
|
||||||
// Delete the entire pending entry if it became empty.
|
// Delete the entire pending entry if it became empty.
|
||||||
if list.Empty() {
|
if list.Empty() {
|
||||||
|
|
@ -1814,7 +1802,7 @@ func (as *accountSet) merge(other *accountSet) {
|
||||||
as.cache = nil
|
as.cache = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// txLookup is used internally by TxPool to track transactions while allowing
|
// lookup is used internally by TxPool to track transactions while allowing
|
||||||
// lookup without mutex contention.
|
// lookup without mutex contention.
|
||||||
//
|
//
|
||||||
// Note, although this type is properly protected against concurrent access, it
|
// Note, although this type is properly protected against concurrent access, it
|
||||||
|
|
@ -1826,16 +1814,16 @@ func (as *accountSet) merge(other *accountSet) {
|
||||||
//
|
//
|
||||||
// This lookup set combines the notion of "local transactions", which is useful
|
// This lookup set combines the notion of "local transactions", which is useful
|
||||||
// to build upper-level structure.
|
// to build upper-level structure.
|
||||||
type txLookup struct {
|
type lookup struct {
|
||||||
slots int
|
slots int
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
locals map[common.Hash]*types.Transaction
|
locals map[common.Hash]*types.Transaction
|
||||||
remotes map[common.Hash]*types.Transaction
|
remotes map[common.Hash]*types.Transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTxLookup returns a new txLookup structure.
|
// newLookup returns a new lookup structure.
|
||||||
func newTxLookup() *txLookup {
|
func newLookup() *lookup {
|
||||||
return &txLookup{
|
return &lookup{
|
||||||
locals: make(map[common.Hash]*types.Transaction),
|
locals: make(map[common.Hash]*types.Transaction),
|
||||||
remotes: make(map[common.Hash]*types.Transaction),
|
remotes: make(map[common.Hash]*types.Transaction),
|
||||||
}
|
}
|
||||||
|
|
@ -1844,7 +1832,7 @@ func newTxLookup() *txLookup {
|
||||||
// Range calls f on each key and value present in the map. The callback passed
|
// Range calls f on each key and value present in the map. The callback passed
|
||||||
// should return the indicator whether the iteration needs to be continued.
|
// should return the indicator whether the iteration needs to be continued.
|
||||||
// Callers need to specify which set (or both) to be iterated.
|
// Callers need to specify which set (or both) to be iterated.
|
||||||
func (t *txLookup) Range(f func(hash common.Hash, tx *types.Transaction, local bool) bool, local bool, remote bool) {
|
func (t *lookup) Range(f func(hash common.Hash, tx *types.Transaction, local bool) bool, local bool, remote bool) {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1865,7 +1853,7 @@ func (t *txLookup) Range(f func(hash common.Hash, tx *types.Transaction, local b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns a transaction if it exists in the lookup, or nil if not found.
|
// Get returns a transaction if it exists in the lookup, or nil if not found.
|
||||||
func (t *txLookup) Get(hash common.Hash) *types.Transaction {
|
func (t *lookup) Get(hash common.Hash) *types.Transaction {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1876,7 +1864,7 @@ func (t *txLookup) Get(hash common.Hash) *types.Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLocal returns a transaction if it exists in the lookup, or nil if not found.
|
// GetLocal returns a transaction if it exists in the lookup, or nil if not found.
|
||||||
func (t *txLookup) GetLocal(hash common.Hash) *types.Transaction {
|
func (t *lookup) GetLocal(hash common.Hash) *types.Transaction {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1884,7 +1872,7 @@ func (t *txLookup) GetLocal(hash common.Hash) *types.Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRemote returns a transaction if it exists in the lookup, or nil if not found.
|
// GetRemote returns a transaction if it exists in the lookup, or nil if not found.
|
||||||
func (t *txLookup) GetRemote(hash common.Hash) *types.Transaction {
|
func (t *lookup) GetRemote(hash common.Hash) *types.Transaction {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1892,7 +1880,7 @@ func (t *txLookup) GetRemote(hash common.Hash) *types.Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the current number of transactions in the lookup.
|
// Count returns the current number of transactions in the lookup.
|
||||||
func (t *txLookup) Count() int {
|
func (t *lookup) Count() int {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1900,7 +1888,7 @@ func (t *txLookup) Count() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalCount returns the current number of local transactions in the lookup.
|
// LocalCount returns the current number of local transactions in the lookup.
|
||||||
func (t *txLookup) LocalCount() int {
|
func (t *lookup) LocalCount() int {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1908,7 +1896,7 @@ func (t *txLookup) LocalCount() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteCount returns the current number of remote transactions in the lookup.
|
// RemoteCount returns the current number of remote transactions in the lookup.
|
||||||
func (t *txLookup) RemoteCount() int {
|
func (t *lookup) RemoteCount() int {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1916,7 +1904,7 @@ func (t *txLookup) RemoteCount() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slots returns the current number of slots used in the lookup.
|
// Slots returns the current number of slots used in the lookup.
|
||||||
func (t *txLookup) Slots() int {
|
func (t *lookup) Slots() int {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
@ -1924,7 +1912,7 @@ func (t *txLookup) Slots() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a transaction to the lookup.
|
// Add adds a transaction to the lookup.
|
||||||
func (t *txLookup) Add(tx *types.Transaction, local bool) {
|
func (t *lookup) Add(tx *types.Transaction, local bool) {
|
||||||
t.lock.Lock()
|
t.lock.Lock()
|
||||||
defer t.lock.Unlock()
|
defer t.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -1939,7 +1927,7 @@ func (t *txLookup) Add(tx *types.Transaction, local bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes a transaction from the lookup.
|
// Remove removes a transaction from the lookup.
|
||||||
func (t *txLookup) Remove(hash common.Hash) {
|
func (t *lookup) Remove(hash common.Hash) {
|
||||||
t.lock.Lock()
|
t.lock.Lock()
|
||||||
defer t.lock.Unlock()
|
defer t.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -1960,7 +1948,7 @@ func (t *txLookup) Remove(hash common.Hash) {
|
||||||
|
|
||||||
// RemoteToLocals migrates the transactions belongs to the given locals to locals
|
// RemoteToLocals migrates the transactions belongs to the given locals to locals
|
||||||
// set. The assumption is held the locals set is thread-safe to be used.
|
// set. The assumption is held the locals set is thread-safe to be used.
|
||||||
func (t *txLookup) RemoteToLocals(locals *accountSet) int {
|
func (t *lookup) RemoteToLocals(locals *accountSet) int {
|
||||||
t.lock.Lock()
|
t.lock.Lock()
|
||||||
defer t.lock.Unlock()
|
defer t.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -1976,7 +1964,7 @@ func (t *txLookup) RemoteToLocals(locals *accountSet) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemotesBelowTip finds all remote transactions below the given tip threshold.
|
// RemotesBelowTip finds all remote transactions below the given tip threshold.
|
||||||
func (t *txLookup) RemotesBelowTip(threshold *big.Int) types.Transactions {
|
func (t *lookup) RemotesBelowTip(threshold *big.Int) types.Transactions {
|
||||||
found := make(types.Transactions, 0, 128)
|
found := make(types.Transactions, 0, 128)
|
||||||
t.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool {
|
t.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool {
|
||||||
if tx.GasTipCapIntCmp(threshold) < 0 {
|
if tx.GasTipCapIntCmp(threshold) < 0 {
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
|
@ -39,14 +40,14 @@ import (
|
||||||
var (
|
var (
|
||||||
// testTxPoolConfig is a transaction pool configuration without stateful disk
|
// testTxPoolConfig is a transaction pool configuration without stateful disk
|
||||||
// sideeffects used during testing.
|
// sideeffects used during testing.
|
||||||
testTxPoolConfig TxPoolConfig
|
testTxPoolConfig Config
|
||||||
|
|
||||||
// eip1559Config is a chain config with EIP-1559 enabled at block 0.
|
// eip1559Config is a chain config with EIP-1559 enabled at block 0.
|
||||||
eip1559Config *params.ChainConfig
|
eip1559Config *params.ChainConfig
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
testTxPoolConfig = DefaultTxPoolConfig
|
testTxPoolConfig = DefaultConfig
|
||||||
testTxPoolConfig.Journal = ""
|
testTxPoolConfig.Journal = ""
|
||||||
|
|
||||||
cpy := *params.TestChainConfig
|
cpy := *params.TestChainConfig
|
||||||
|
|
@ -91,7 +92,7 @@ func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
|
||||||
return bc.statedb, nil
|
return bc.statedb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription {
|
func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
|
||||||
return bc.chainHeadFeed.Subscribe(ch)
|
return bc.chainHeadFeed.Subscribe(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,11 +128,11 @@ func dynamicFeeTx(nonce uint64, gaslimit uint64, gasFee *big.Int, tip *big.Int,
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
func setupPool() (*TxPool, *ecdsa.PrivateKey) {
|
||||||
return setupTxPoolWithConfig(params.TestChainConfig)
|
return setupPoolWithConfig(params.TestChainConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupTxPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) {
|
func setupPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) {
|
||||||
diskdb := rawdb.NewMemoryDatabase()
|
diskdb := rawdb.NewMemoryDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(diskdb))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(diskdb))
|
||||||
blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)}
|
blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)}
|
||||||
|
|
@ -144,8 +145,8 @@ func setupTxPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateK
|
||||||
return pool, key
|
return pool, key
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateTxPoolInternals checks various consistency invariants within the pool.
|
// validatePoolInternals checks various consistency invariants within the pool.
|
||||||
func validateTxPoolInternals(pool *TxPool) error {
|
func validatePoolInternals(pool *TxPool) error {
|
||||||
pool.mu.RLock()
|
pool.mu.RLock()
|
||||||
defer pool.mu.RUnlock()
|
defer pool.mu.RUnlock()
|
||||||
|
|
||||||
|
|
@ -177,7 +178,7 @@ func validateTxPoolInternals(pool *TxPool) error {
|
||||||
|
|
||||||
// validateEvents checks that the correct number of transaction addition events
|
// validateEvents checks that the correct number of transaction addition events
|
||||||
// were fired on the pool's event feed.
|
// were fired on the pool's event feed.
|
||||||
func validateEvents(events chan NewTxsEvent, count int) error {
|
func validateEvents(events chan core.NewTxsEvent, count int) error {
|
||||||
var received []*types.Transaction
|
var received []*types.Transaction
|
||||||
|
|
||||||
for len(received) < count {
|
for len(received) < count {
|
||||||
|
|
@ -235,7 +236,7 @@ func (c *testChain) State() (*state.StateDB, error) {
|
||||||
// This test simulates a scenario where a new block is imported during a
|
// This test simulates a scenario where a new block is imported during a
|
||||||
// state reset and tests whether the pending state is in sync with the
|
// state reset and tests whether the pending state is in sync with the
|
||||||
// block head event that initiated the resetState().
|
// block head event that initiated the resetState().
|
||||||
func TestStateChangeDuringTransactionPoolReset(t *testing.T) {
|
func TestStateChangeDuringReset(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -293,28 +294,28 @@ func testSetNonce(pool *TxPool, addr common.Address, nonce uint64) {
|
||||||
func TestInvalidTransactions(t *testing.T) {
|
func TestInvalidTransactions(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
tx := transaction(0, 100, key)
|
tx := transaction(0, 100, key)
|
||||||
from, _ := deriveSender(tx)
|
from, _ := deriveSender(tx)
|
||||||
|
|
||||||
testAddBalance(pool, from, big.NewInt(1))
|
testAddBalance(pool, from, big.NewInt(1))
|
||||||
if err := pool.AddRemote(tx); err != ErrInsufficientFunds {
|
if err := pool.AddRemote(tx); err != core.ErrInsufficientFunds {
|
||||||
t.Error("expected", ErrInsufficientFunds)
|
t.Error("expected", core.ErrInsufficientFunds)
|
||||||
}
|
}
|
||||||
|
|
||||||
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()))
|
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()))
|
||||||
testAddBalance(pool, from, balance)
|
testAddBalance(pool, from, balance)
|
||||||
if err := pool.AddRemote(tx); err != ErrIntrinsicGas {
|
if err := pool.AddRemote(tx); err != core.ErrIntrinsicGas {
|
||||||
t.Error("expected", ErrIntrinsicGas, "got", err)
|
t.Error("expected", core.ErrIntrinsicGas, "got", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
testSetNonce(pool, from, 1)
|
testSetNonce(pool, from, 1)
|
||||||
testAddBalance(pool, from, big.NewInt(0xffffffffffffff))
|
testAddBalance(pool, from, big.NewInt(0xffffffffffffff))
|
||||||
tx = transaction(0, 100000, key)
|
tx = transaction(0, 100000, key)
|
||||||
if err := pool.AddRemote(tx); err != ErrNonceTooLow {
|
if err := pool.AddRemote(tx); err != core.ErrNonceTooLow {
|
||||||
t.Error("expected", ErrNonceTooLow)
|
t.Error("expected", core.ErrNonceTooLow)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx = transaction(1, 100000, key)
|
tx = transaction(1, 100000, key)
|
||||||
|
|
@ -327,10 +328,10 @@ func TestInvalidTransactions(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionQueue(t *testing.T) {
|
func TestQueue(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
tx := transaction(0, 100, key)
|
tx := transaction(0, 100, key)
|
||||||
|
|
@ -359,10 +360,10 @@ func TestTransactionQueue(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionQueue2(t *testing.T) {
|
func TestQueue2(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
tx1 := transaction(0, 100, key)
|
tx1 := transaction(0, 100, key)
|
||||||
|
|
@ -385,10 +386,10 @@ func TestTransactionQueue2(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionNegativeValue(t *testing.T) {
|
func TestNegativeValue(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key)
|
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key)
|
||||||
|
|
@ -399,43 +400,43 @@ func TestTransactionNegativeValue(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionTipAboveFeeCap(t *testing.T) {
|
func TestTipAboveFeeCap(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPoolWithConfig(eip1559Config)
|
pool, key := setupPoolWithConfig(eip1559Config)
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key)
|
tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key)
|
||||||
|
|
||||||
if err := pool.AddRemote(tx); err != ErrTipAboveFeeCap {
|
if err := pool.AddRemote(tx); err != core.ErrTipAboveFeeCap {
|
||||||
t.Error("expected", ErrTipAboveFeeCap, "got", err)
|
t.Error("expected", core.ErrTipAboveFeeCap, "got", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionVeryHighValues(t *testing.T) {
|
func TestVeryHighValues(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPoolWithConfig(eip1559Config)
|
pool, key := setupPoolWithConfig(eip1559Config)
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
veryBigNumber := big.NewInt(1)
|
veryBigNumber := big.NewInt(1)
|
||||||
veryBigNumber.Lsh(veryBigNumber, 300)
|
veryBigNumber.Lsh(veryBigNumber, 300)
|
||||||
|
|
||||||
tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key)
|
tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key)
|
||||||
if err := pool.AddRemote(tx); err != ErrTipVeryHigh {
|
if err := pool.AddRemote(tx); err != core.ErrTipVeryHigh {
|
||||||
t.Error("expected", ErrTipVeryHigh, "got", err)
|
t.Error("expected", core.ErrTipVeryHigh, "got", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key)
|
tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key)
|
||||||
if err := pool.AddRemote(tx2); err != ErrFeeCapVeryHigh {
|
if err := pool.AddRemote(tx2); err != core.ErrFeeCapVeryHigh {
|
||||||
t.Error("expected", ErrFeeCapVeryHigh, "got", err)
|
t.Error("expected", core.ErrFeeCapVeryHigh, "got", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionChainFork(t *testing.T) {
|
func TestChainFork(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -462,10 +463,10 @@ func TestTransactionChainFork(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionDoubleNonce(t *testing.T) {
|
func TestDoubleNonce(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -514,10 +515,10 @@ func TestTransactionDoubleNonce(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionMissingNonce(t *testing.T) {
|
func TestMissingNonce(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -537,11 +538,11 @@ func TestTransactionMissingNonce(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionNonceRecovery(t *testing.T) {
|
func TestNonceRecovery(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
const n = 10
|
const n = 10
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -563,11 +564,11 @@ func TestTransactionNonceRecovery(t *testing.T) {
|
||||||
|
|
||||||
// Tests that if an account runs out of funds, any pending and queued transactions
|
// Tests that if an account runs out of funds, any pending and queued transactions
|
||||||
// are dropped.
|
// are dropped.
|
||||||
func TestTransactionDropping(t *testing.T) {
|
func TestDropping(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create a test account and fund it
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -667,7 +668,7 @@ func TestTransactionDropping(t *testing.T) {
|
||||||
// Tests that if a transaction is dropped from the current pending pool (e.g. out
|
// Tests that if a transaction is dropped from the current pending pool (e.g. out
|
||||||
// of fund), all consecutive (still valid, but not executable) transactions are
|
// of fund), all consecutive (still valid, but not executable) transactions are
|
||||||
// postponed back into the future queue to prevent broadcasting them.
|
// postponed back into the future queue to prevent broadcasting them.
|
||||||
func TestTransactionPostponing(t *testing.T) {
|
func TestPostponing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the postponing with
|
// Create the pool to test the postponing with
|
||||||
|
|
@ -782,18 +783,18 @@ func TestTransactionPostponing(t *testing.T) {
|
||||||
// Tests that if the transaction pool has both executable and non-executable
|
// Tests that if the transaction pool has both executable and non-executable
|
||||||
// transactions from an origin account, filling the nonce gap moves all queued
|
// transactions from an origin account, filling the nonce gap moves all queued
|
||||||
// ones into the pending pool.
|
// ones into the pending pool.
|
||||||
func TestTransactionGapFilling(t *testing.T) {
|
func TestGapFilling(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create a test account and fund it
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
testAddBalance(pool, account, big.NewInt(1000000))
|
testAddBalance(pool, account, big.NewInt(1000000))
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5)
|
events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -812,7 +813,7 @@ func TestTransactionGapFilling(t *testing.T) {
|
||||||
if err := validateEvents(events, 1); err != nil {
|
if err := validateEvents(events, 1); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Fill the nonce gap and ensure all transactions become pending
|
// Fill the nonce gap and ensure all transactions become pending
|
||||||
|
|
@ -829,18 +830,18 @@ func TestTransactionGapFilling(t *testing.T) {
|
||||||
if err := validateEvents(events, 2); err != nil {
|
if err := validateEvents(events, 2); err != nil {
|
||||||
t.Fatalf("gap-filling event firing failed: %v", err)
|
t.Fatalf("gap-filling event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that if the transaction count belonging to a single account goes above
|
// Tests that if the transaction count belonging to a single account goes above
|
||||||
// some threshold, the higher transactions are dropped to prevent DOS attacks.
|
// some threshold, the higher transactions are dropped to prevent DOS attacks.
|
||||||
func TestTransactionQueueAccountLimiting(t *testing.T) {
|
func TestQueueAccountLimiting(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create a test account and fund it
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -874,14 +875,14 @@ func TestTransactionQueueAccountLimiting(t *testing.T) {
|
||||||
//
|
//
|
||||||
// This logic should not hold for local transactions, unless the local tracking
|
// This logic should not hold for local transactions, unless the local tracking
|
||||||
// mechanism is disabled.
|
// mechanism is disabled.
|
||||||
func TestTransactionQueueGlobalLimiting(t *testing.T) {
|
func TestQueueGlobalLimiting(t *testing.T) {
|
||||||
testTransactionQueueGlobalLimiting(t, false)
|
testQueueGlobalLimiting(t, false)
|
||||||
}
|
}
|
||||||
func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) {
|
func TestQueueGlobalLimitingNoLocals(t *testing.T) {
|
||||||
testTransactionQueueGlobalLimiting(t, true)
|
testQueueGlobalLimiting(t, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
|
|
@ -966,12 +967,12 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||||
//
|
//
|
||||||
// This logic should not hold for local transactions, unless the local tracking
|
// This logic should not hold for local transactions, unless the local tracking
|
||||||
// mechanism is disabled.
|
// mechanism is disabled.
|
||||||
func TestTransactionQueueTimeLimiting(t *testing.T) { testTransactionQueueTimeLimiting(t, false) }
|
func TestQueueTimeLimiting(t *testing.T) { testQueueTimeLimiting(t, false) }
|
||||||
func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) {
|
func TestQueueTimeLimitingNoLocals(t *testing.T) {
|
||||||
testTransactionQueueTimeLimiting(t, true)
|
testQueueTimeLimiting(t, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
common.MinGasPrice = big.NewInt(0)
|
common.MinGasPrice = big.NewInt(0)
|
||||||
// Reduce the eviction interval to a testable amount
|
// Reduce the eviction interval to a testable amount
|
||||||
defer func(old time.Duration) { evictionInterval = old }(evictionInterval)
|
defer func(old time.Duration) { evictionInterval = old }(evictionInterval)
|
||||||
|
|
@ -1010,7 +1011,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
if queued != 2 {
|
if queued != 2 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1025,7 +1026,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
if queued != 2 {
|
if queued != 2 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1045,7 +1046,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1062,7 +1063,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
if queued != 0 {
|
if queued != 0 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1092,7 +1093,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
if queued != 2 {
|
if queued != 2 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1111,7 +1112,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1119,18 +1120,18 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
// Tests that even if the transaction count belonging to a single account goes
|
// Tests that even if the transaction count belonging to a single account goes
|
||||||
// above some threshold, as long as the transactions are executable, they are
|
// above some threshold, as long as the transactions are executable, they are
|
||||||
// accepted.
|
// accepted.
|
||||||
func TestTransactionPendingLimiting(t *testing.T) {
|
func TestPendingLimiting(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create a test account and fund it
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
testAddBalance(pool, account, big.NewInt(1000000))
|
testAddBalance(pool, account, big.NewInt(1000000))
|
||||||
testTxPoolConfig.AccountQueue = 10
|
testTxPoolConfig.AccountQueue = 10
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue)
|
events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -1152,7 +1153,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
|
||||||
if err := validateEvents(events, int(testTxPoolConfig.AccountQueue)); err != nil {
|
if err := validateEvents(events, int(testTxPoolConfig.AccountQueue)); err != nil {
|
||||||
t.Fatalf("event firing failed: %v", err)
|
t.Fatalf("event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1160,7 +1161,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
|
||||||
// Tests that if the transaction count belonging to multiple accounts go above
|
// Tests that if the transaction count belonging to multiple accounts go above
|
||||||
// some hard threshold, the higher transactions are dropped to prevent DOS
|
// some hard threshold, the higher transactions are dropped to prevent DOS
|
||||||
// attacks.
|
// attacks.
|
||||||
func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
func TestPendingGlobalLimiting(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
|
|
@ -1201,7 +1202,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
||||||
if pending > int(config.GlobalSlots) {
|
if pending > int(config.GlobalSlots) {
|
||||||
t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots)
|
t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1209,11 +1210,11 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
||||||
// Test the limit on transaction size is enforced correctly.
|
// Test the limit on transaction size is enforced correctly.
|
||||||
// This test verifies every transaction having allowed size
|
// This test verifies every transaction having allowed size
|
||||||
// is added to the pool, and longer transactions are rejected.
|
// is added to the pool, and longer transactions are rejected.
|
||||||
func TestTransactionAllowedTxSize(t *testing.T) {
|
func TestAllowedTxSize(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create a test account and fund it
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -1257,13 +1258,13 @@ func TestTransactionAllowedTxSize(t *testing.T) {
|
||||||
if queued != 0 {
|
if queued != 0 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that if transactions start being capped, transactions are also removed from 'all'
|
// Tests that if transactions start being capped, transactions are also removed from 'all'
|
||||||
func TestTransactionCapClearsFromAll(t *testing.T) {
|
func TestCapClearsFromAll(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
|
|
@ -1290,7 +1291,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Import the batch and verify that limits have been enforced
|
// Import the batch and verify that limits have been enforced
|
||||||
pool.AddRemotes(txs)
|
pool.AddRemotes(txs)
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1298,7 +1299,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
|
||||||
// Tests that if the transaction count belonging to multiple accounts go above
|
// Tests that if the transaction count belonging to multiple accounts go above
|
||||||
// some hard threshold, if they are under the minimum guaranteed slot count then
|
// some hard threshold, if they are under the minimum guaranteed slot count then
|
||||||
// the transactions are still kept.
|
// the transactions are still kept.
|
||||||
func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
func TestPendingMinimumAllowance(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
|
|
@ -1337,7 +1338,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
||||||
t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots)
|
t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1347,7 +1348,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
||||||
// from the pending pool to the queue.
|
// from the pending pool to the queue.
|
||||||
//
|
//
|
||||||
// Note, local transactions are never allowed to be dropped.
|
// Note, local transactions are never allowed to be dropped.
|
||||||
func TestTransactionPoolRepricing(t *testing.T) {
|
func TestRepricing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
|
|
@ -1359,7 +1360,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, 32)
|
events := make(chan core.NewTxsEvent, 32)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -1400,7 +1401,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 7); err != nil {
|
if err := validateEvents(events, 7); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Reprice the pool and check that underpriced transactions get dropped
|
// Reprice the pool and check that underpriced transactions get dropped
|
||||||
|
|
@ -1416,7 +1417,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 0); err != nil {
|
if err := validateEvents(events, 0); err != nil {
|
||||||
t.Fatalf("reprice event firing failed: %v", err)
|
t.Fatalf("reprice event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Check that we can't add the old transactions back
|
// Check that we can't add the old transactions back
|
||||||
|
|
@ -1432,7 +1433,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 0); err != nil {
|
if err := validateEvents(events, 0); err != nil {
|
||||||
t.Fatalf("post-reprice event firing failed: %v", err)
|
t.Fatalf("post-reprice event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// However we can add local underpriced transactions
|
// However we can add local underpriced transactions
|
||||||
|
|
@ -1446,7 +1447,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 1); err != nil {
|
if err := validateEvents(events, 1); err != nil {
|
||||||
t.Fatalf("post-reprice local event firing failed: %v", err)
|
t.Fatalf("post-reprice local event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// And we can fill gaps with properly priced transactions
|
// And we can fill gaps with properly priced transactions
|
||||||
|
|
@ -1462,7 +1463,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 5); err != nil {
|
if err := validateEvents(events, 5); err != nil {
|
||||||
t.Fatalf("post-reprice event firing failed: %v", err)
|
t.Fatalf("post-reprice event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1472,15 +1473,15 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
// gapped transactions back from the pending pool to the queue.
|
// gapped transactions back from the pending pool to the queue.
|
||||||
//
|
//
|
||||||
// Note, local transactions are never allowed to be dropped.
|
// Note, local transactions are never allowed to be dropped.
|
||||||
func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
|
func TestRepricingDynamicFee(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
pool, _ := setupTxPoolWithConfig(eip1559Config)
|
pool, _ := setupPoolWithConfig(eip1559Config)
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, 32)
|
events := make(chan core.NewTxsEvent, 32)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -1521,7 +1522,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 7); err != nil {
|
if err := validateEvents(events, 7); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Reprice the pool and check that underpriced transactions get dropped
|
// Reprice the pool and check that underpriced transactions get dropped
|
||||||
|
|
@ -1537,7 +1538,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 0); err != nil {
|
if err := validateEvents(events, 0); err != nil {
|
||||||
t.Fatalf("reprice event firing failed: %v", err)
|
t.Fatalf("reprice event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Check that we can't add the old transactions back
|
// Check that we can't add the old transactions back
|
||||||
|
|
@ -1556,7 +1557,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 0); err != nil {
|
if err := validateEvents(events, 0); err != nil {
|
||||||
t.Fatalf("post-reprice event firing failed: %v", err)
|
t.Fatalf("post-reprice event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// However we can add local underpriced transactions
|
// However we can add local underpriced transactions
|
||||||
|
|
@ -1570,7 +1571,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 1); err != nil {
|
if err := validateEvents(events, 1); err != nil {
|
||||||
t.Fatalf("post-reprice local event firing failed: %v", err)
|
t.Fatalf("post-reprice local event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// And we can fill gaps with properly priced transactions
|
// And we can fill gaps with properly priced transactions
|
||||||
|
|
@ -1589,14 +1590,14 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 5); err != nil {
|
if err := validateEvents(events, 5); err != nil {
|
||||||
t.Fatalf("post-reprice event firing failed: %v", err)
|
t.Fatalf("post-reprice event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that setting the transaction pool gas price to a higher value does not
|
// Tests that setting the transaction pool gas price to a higher value does not
|
||||||
// remove local transactions (legacy & dynamic fee).
|
// remove local transactions (legacy & dynamic fee).
|
||||||
func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
|
func TestRepricingKeepsLocals(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
|
|
@ -1649,7 +1650,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1671,7 +1672,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
|
||||||
// pending transactions are moved into the queue.
|
// pending transactions are moved into the queue.
|
||||||
//
|
//
|
||||||
// Note, local transactions are never allowed to be dropped.
|
// Note, local transactions are never allowed to be dropped.
|
||||||
func TestTransactionPoolUnderpricing(t *testing.T) {
|
func TestPoolUnderpricing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
|
|
@ -1687,7 +1688,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, 32)
|
events := make(chan core.NewTxsEvent, 32)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -1721,7 +1722,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 3); err != nil {
|
if err := validateEvents(events, 3); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure that adding an underpriced transaction on block limit fails
|
// Ensure that adding an underpriced transaction on block limit fails
|
||||||
|
|
@ -1748,7 +1749,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 1); err != nil {
|
if err := validateEvents(events, 1); err != nil {
|
||||||
t.Fatalf("additional event firing failed: %v", err)
|
t.Fatalf("additional event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure that adding local transactions can push out even higher priced ones
|
// Ensure that adding local transactions can push out even higher priced ones
|
||||||
|
|
@ -1770,7 +1771,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 2); err != nil {
|
if err := validateEvents(events, 2); err != nil {
|
||||||
t.Fatalf("local event firing failed: %v", err)
|
t.Fatalf("local event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1778,7 +1779,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
|
||||||
// Tests that more expensive transactions push out cheap ones from the pool, but
|
// Tests that more expensive transactions push out cheap ones from the pool, but
|
||||||
// without producing instability by creating gaps that start jumping transactions
|
// without producing instability by creating gaps that start jumping transactions
|
||||||
// back and forth between queued/pending.
|
// back and forth between queued/pending.
|
||||||
func TestTransactionPoolStableUnderpricing(t *testing.T) {
|
func TestPoolStableUnderpricing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
|
|
@ -1795,7 +1796,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, 32)
|
events := make(chan core.NewTxsEvent, 32)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -1822,7 +1823,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
|
||||||
if err := validateEvents(events, int(config.GlobalSlots)); err != nil {
|
if err := validateEvents(events, int(config.GlobalSlots)); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap
|
// Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap
|
||||||
|
|
@ -1839,7 +1840,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
|
||||||
if err := validateEvents(events, 1); err != nil {
|
if err := validateEvents(events, 1); err != nil {
|
||||||
t.Fatalf("additional event firing failed: %v", err)
|
t.Fatalf("additional event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1849,17 +1850,17 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
|
||||||
// expensive ones and any gapped pending transactions are moved into the queue.
|
// expensive ones and any gapped pending transactions are moved into the queue.
|
||||||
//
|
//
|
||||||
// Note, local transactions are never allowed to be dropped.
|
// Note, local transactions are never allowed to be dropped.
|
||||||
func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
|
func TestPoolUnderpricingDynamicFee(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, _ := setupTxPoolWithConfig(eip1559Config)
|
pool, _ := setupPoolWithConfig(eip1559Config)
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
pool.config.GlobalSlots = 2
|
pool.config.GlobalSlots = 2
|
||||||
pool.config.GlobalQueue = 2
|
pool.config.GlobalQueue = 2
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, 32)
|
events := make(chan core.NewTxsEvent, 32)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -1893,7 +1894,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 3); err != nil {
|
if err := validateEvents(events, 3); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1927,7 +1928,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 1); err != nil {
|
if err := validateEvents(events, 1); err != nil {
|
||||||
t.Fatalf("additional event firing failed: %v", err)
|
t.Fatalf("additional event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure that adding local transactions can push out even higher priced ones
|
// Ensure that adding local transactions can push out even higher priced ones
|
||||||
|
|
@ -1949,7 +1950,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
|
||||||
if err := validateEvents(events, 2); err != nil {
|
if err := validateEvents(events, 2); err != nil {
|
||||||
t.Fatalf("local event firing failed: %v", err)
|
t.Fatalf("local event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1959,7 +1960,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
|
||||||
func TestDualHeapEviction(t *testing.T) {
|
func TestDualHeapEviction(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
pool, _ := setupTxPoolWithConfig(eip1559Config)
|
pool, _ := setupPoolWithConfig(eip1559Config)
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
pool.config.GlobalSlots = 10
|
pool.config.GlobalSlots = 10
|
||||||
|
|
@ -2006,13 +2007,13 @@ func TestDualHeapEviction(t *testing.T) {
|
||||||
check(highTip, "effective tip")
|
check(highTip, "effective tip")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the pool rejects duplicate transactions.
|
// Tests that the pool rejects duplicate transactions.
|
||||||
func TestTransactionDeduplication(t *testing.T) {
|
func TestDeduplication(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
|
|
@ -2071,14 +2072,14 @@ func TestTransactionDeduplication(t *testing.T) {
|
||||||
if queued != 0 {
|
if queued != 0 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the pool rejects replacement transactions that don't meet the minimum
|
// Tests that the pool rejects replacement transactions that don't meet the minimum
|
||||||
// price bump required.
|
// price bump required.
|
||||||
func TestTransactionReplacement(t *testing.T) {
|
func TestReplacement(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
|
|
@ -2090,7 +2091,7 @@ func TestTransactionReplacement(t *testing.T) {
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, 32)
|
events := make(chan core.NewTxsEvent, 32)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -2152,23 +2153,23 @@ func TestTransactionReplacement(t *testing.T) {
|
||||||
if err := validateEvents(events, 0); err != nil {
|
if err := validateEvents(events, 0); err != nil {
|
||||||
t.Fatalf("queued replacement event firing failed: %v", err)
|
t.Fatalf("queued replacement event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the pool rejects replacement dynamic fee transactions that don't
|
// Tests that the pool rejects replacement dynamic fee transactions that don't
|
||||||
// meet the minimum price bump required.
|
// meet the minimum price bump required.
|
||||||
func TestTransactionReplacementDynamicFee(t *testing.T) {
|
func TestReplacementDynamicFee(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
pool, key := setupTxPoolWithConfig(eip1559Config)
|
pool, key := setupPoolWithConfig(eip1559Config)
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000))
|
testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000))
|
||||||
|
|
||||||
// Keep track of transaction events to ensure all executables get announced
|
// Keep track of transaction events to ensure all executables get announced
|
||||||
events := make(chan NewTxsEvent, 32)
|
events := make(chan core.NewTxsEvent, 32)
|
||||||
sub := pool.txFeed.Subscribe(events)
|
sub := pool.txFeed.Subscribe(events)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
|
@ -2262,15 +2263,15 @@ func TestTransactionReplacementDynamicFee(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that local transactions are journaled to disk, but remote transactions
|
// Tests that local transactions are journaled to disk, but remote transactions
|
||||||
// get discarded between restarts.
|
// get discarded between restarts.
|
||||||
func TestTransactionJournaling(t *testing.T) { testTransactionJournaling(t, false) }
|
func TestJournaling(t *testing.T) { testTransactionJournaling(t, false) }
|
||||||
func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) }
|
func TestJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) }
|
||||||
|
|
||||||
func testTransactionJournaling(t *testing.T, nolocals bool) {
|
func testTransactionJournaling(t *testing.T, nolocals bool) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
@ -2326,7 +2327,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
|
||||||
if queued != 0 {
|
if queued != 0 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive
|
// Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive
|
||||||
|
|
@ -2349,7 +2350,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Bump the nonce temporarily and ensure the newly invalidated transaction is removed
|
// Bump the nonce temporarily and ensure the newly invalidated transaction is removed
|
||||||
|
|
@ -2375,7 +2376,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
pool.Stop()
|
pool.Stop()
|
||||||
|
|
@ -2383,7 +2384,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
|
||||||
|
|
||||||
// TestTransactionStatusCheck tests that the pool can correctly retrieve the
|
// TestTransactionStatusCheck tests that the pool can correctly retrieve the
|
||||||
// pending status of individual transactions.
|
// pending status of individual transactions.
|
||||||
func TestTransactionStatusCheck(t *testing.T) {
|
func TestStatusCheck(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the status retrievals with
|
// Create the pool to test the status retrievals with
|
||||||
|
|
@ -2418,7 +2419,7 @@ func TestTransactionStatusCheck(t *testing.T) {
|
||||||
if queued != 2 {
|
if queued != 2 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
||||||
}
|
}
|
||||||
if err := validateTxPoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Retrieve the status of each transaction and validate them
|
// Retrieve the status of each transaction and validate them
|
||||||
|
|
@ -2439,7 +2440,7 @@ func TestTransactionStatusCheck(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the transaction slots consumption is computed correctly
|
// Test the transaction slots consumption is computed correctly
|
||||||
func TestTransactionSlotCount(t *testing.T) {
|
func TestSlotCount(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
|
|
@ -2464,7 +2465,7 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1
|
||||||
|
|
||||||
func benchmarkPendingDemotion(b *testing.B, size int) {
|
func benchmarkPendingDemotion(b *testing.B, size int) {
|
||||||
// Add a batch of transactions to a pool one by one
|
// Add a batch of transactions to a pool one by one
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -2489,7 +2490,7 @@ func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 1
|
||||||
|
|
||||||
func benchmarkFuturePromotion(b *testing.B, size int) {
|
func benchmarkFuturePromotion(b *testing.B, size int) {
|
||||||
// Add a batch of transactions to a pool one by one
|
// Add a batch of transactions to a pool one by one
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -2507,17 +2508,17 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmarks the speed of batched transaction insertion.
|
// Benchmarks the speed of batched transaction insertion.
|
||||||
func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100, false) }
|
func BenchmarkBatchInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, false) }
|
||||||
func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000, false) }
|
func BenchmarkBatchInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, false) }
|
||||||
func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000, false) }
|
func BenchmarkBatchInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, false) }
|
||||||
|
|
||||||
func BenchmarkPoolBatchLocalInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100, true) }
|
func BenchmarkBatchLocalInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, true) }
|
||||||
func BenchmarkPoolBatchLocalInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000, true) }
|
func BenchmarkBatchLocalInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, true) }
|
||||||
func BenchmarkPoolBatchLocalInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000, true) }
|
func BenchmarkBatchLocalInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, true) }
|
||||||
|
|
||||||
func benchmarkPoolBatchInsert(b *testing.B, size int, local bool) {
|
func benchmarkBatchInsert(b *testing.B, size int, local bool) {
|
||||||
// Generate a batch of transactions to enqueue into the pool
|
// Generate a batch of transactions to enqueue into the pool
|
||||||
pool, key := setupTxPool()
|
pool, key := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
|
|
||||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -2561,7 +2562,7 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) {
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
pool, _ := setupTxPool()
|
pool, _ := setupPool()
|
||||||
testAddBalance(pool, account, big.NewInt(100000000))
|
testAddBalance(pool, account, big.NewInt(100000000))
|
||||||
for _, local := range locals {
|
for _, local := range locals {
|
||||||
pool.AddLocal(local)
|
pool.AddLocal(local)
|
||||||
|
|
@ -2577,9 +2578,9 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmarks the speed of batch transaction insertion in case of multiple accounts.
|
// Benchmarks the speed of batch transaction insertion in case of multiple accounts.
|
||||||
func BenchmarkPoolMultiAccountBatchInsert(b *testing.B) {
|
func BenchmarkMultiAccountBatchInsert(b *testing.B) {
|
||||||
// Generate a batch of transactions to enqueue into the pool
|
// Generate a batch of transactions to enqueue into the pool
|
||||||
pool, _ := setupTxPool()
|
pool, _ := setupPool()
|
||||||
defer pool.Stop()
|
defer pool.Stop()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
batches := make(types.Transactions, b.N)
|
batches := make(types.Transactions, b.N)
|
||||||
|
|
@ -37,6 +37,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/contracts"
|
"github.com/XinFinOrg/XDPoSChain/contracts"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
|
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||||
|
|
@ -72,9 +73,9 @@ type Ethereum struct {
|
||||||
shutdownChan chan bool // Channel for shutting down the ethereum
|
shutdownChan chan bool // Channel for shutting down the ethereum
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
txPool *core.TxPool
|
txPool *txpool.TxPool
|
||||||
orderPool *core.OrderPool
|
orderPool *txpool.OrderPool
|
||||||
lendingPool *core.LendingPool
|
lendingPool *txpool.LendingPool
|
||||||
blockchain *core.BlockChain
|
blockchain *core.BlockChain
|
||||||
protocolManager *ProtocolManager
|
protocolManager *ProtocolManager
|
||||||
lesServer LesServer
|
lesServer LesServer
|
||||||
|
|
@ -186,9 +187,9 @@ func New(ctx *node.ServiceContext, config *ethconfig.Config, XDCXServ *XDCx.XDCX
|
||||||
if config.TxPool.Journal != "" {
|
if config.TxPool.Journal != "" {
|
||||||
config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal)
|
config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal)
|
||||||
}
|
}
|
||||||
eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain)
|
eth.txPool = txpool.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain)
|
||||||
eth.orderPool = core.NewOrderPool(eth.chainConfig, eth.blockchain)
|
eth.orderPool = txpool.NewOrderPool(eth.chainConfig, eth.blockchain)
|
||||||
eth.lendingPool = core.NewLendingPool(eth.chainConfig, eth.blockchain)
|
eth.lendingPool = txpool.NewLendingPool(eth.chainConfig, eth.blockchain)
|
||||||
if common.RollbackHash != (common.Hash{}) {
|
if common.RollbackHash != (common.Hash{}) {
|
||||||
curBlock := eth.blockchain.CurrentBlock()
|
curBlock := eth.blockchain.CurrentBlock()
|
||||||
if curBlock == nil {
|
if curBlock == nil {
|
||||||
|
|
@ -517,7 +518,7 @@ func (e *Ethereum) Miner() *miner.Miner { return e.miner }
|
||||||
|
|
||||||
func (e *Ethereum) AccountManager() *accounts.Manager { return e.accountManager }
|
func (e *Ethereum) AccountManager() *accounts.Manager { return e.accountManager }
|
||||||
func (e *Ethereum) BlockChain() *core.BlockChain { return e.blockchain }
|
func (e *Ethereum) BlockChain() *core.BlockChain { return e.blockchain }
|
||||||
func (e *Ethereum) TxPool() *core.TxPool { return e.txPool }
|
func (e *Ethereum) TxPool() *txpool.TxPool { return e.txPool }
|
||||||
func (e *Ethereum) EventMux() *event.TypeMux { return e.eventMux }
|
func (e *Ethereum) EventMux() *event.TypeMux { return e.eventMux }
|
||||||
func (e *Ethereum) Engine() consensus.Engine { return e.engine }
|
func (e *Ethereum) Engine() consensus.Engine { return e.engine }
|
||||||
func (e *Ethereum) ChainDb() ethdb.Database { return e.chainDb }
|
func (e *Ethereum) ChainDb() ethdb.Database { return e.chainDb }
|
||||||
|
|
@ -591,7 +592,7 @@ func (e *Ethereum) GetXDCX() *XDCx.XDCX {
|
||||||
return e.XDCX
|
return e.XDCX
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Ethereum) OrderPool() *core.OrderPool {
|
func (e *Ethereum) OrderPool() *txpool.OrderPool {
|
||||||
return e.orderPool
|
return e.orderPool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -600,6 +601,6 @@ func (e *Ethereum) GetXDCXLending() *XDCxlending.Lending {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LendingPool geth eth lending pool
|
// LendingPool geth eth lending pool
|
||||||
func (e *Ethereum) LendingPool() *core.LendingPool {
|
func (e *Ethereum) LendingPool() *txpool.LendingPool {
|
||||||
return e.lendingPool
|
return e.lendingPool
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/gasprice"
|
"github.com/XinFinOrg/XDPoSChain/eth/gasprice"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
|
@ -72,7 +73,7 @@ var Defaults = Config{
|
||||||
FilterLogCacheSize: 32,
|
FilterLogCacheSize: 32,
|
||||||
GasPrice: big.NewInt(0.25 * params.Shannon),
|
GasPrice: big.NewInt(0.25 * params.Shannon),
|
||||||
|
|
||||||
TxPool: core.DefaultTxPoolConfig,
|
TxPool: txpool.DefaultConfig,
|
||||||
RPCGasCap: 50000000,
|
RPCGasCap: 50000000,
|
||||||
GPO: FullNodeGPO,
|
GPO: FullNodeGPO,
|
||||||
RPCTxFeeCap: 1, // 1 ether
|
RPCTxFeeCap: 1, // 1 ether
|
||||||
|
|
@ -129,7 +130,7 @@ type Config struct {
|
||||||
Ethash ethash.Config
|
Ethash ethash.Config
|
||||||
|
|
||||||
// Transaction pool options
|
// Transaction pool options
|
||||||
TxPool core.TxPoolConfig
|
TxPool txpool.Config
|
||||||
|
|
||||||
// Gas Price Oracle options
|
// Gas Price Oracle options
|
||||||
GPO gasprice.Config
|
GPO gasprice.Config
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/gasprice"
|
"github.com/XinFinOrg/XDPoSChain/eth/gasprice"
|
||||||
)
|
)
|
||||||
|
|
@ -33,7 +34,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
GasPrice *big.Int
|
GasPrice *big.Int
|
||||||
FilterLogCacheSize int
|
FilterLogCacheSize int
|
||||||
Ethash ethash.Config
|
Ethash ethash.Config
|
||||||
TxPool core.TxPoolConfig
|
TxPool txpool.Config
|
||||||
GPO gasprice.Config
|
GPO gasprice.Config
|
||||||
EnablePreimageRecording bool
|
EnablePreimageRecording bool
|
||||||
DocRoot string `toml:"-"`
|
DocRoot string `toml:"-"`
|
||||||
|
|
@ -87,7 +88,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
GasPrice *big.Int
|
GasPrice *big.Int
|
||||||
FilterLogCacheSize *int
|
FilterLogCacheSize *int
|
||||||
Ethash *ethash.Config
|
Ethash *ethash.Config
|
||||||
TxPool *core.TxPoolConfig
|
TxPool *txpool.Config
|
||||||
GPO *gasprice.Config
|
GPO *gasprice.Config
|
||||||
EnablePreimageRecording *bool
|
EnablePreimageRecording *bool
|
||||||
DocRoot *string `toml:"-"`
|
DocRoot *string `toml:"-"`
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,12 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
|
|
@ -92,7 +92,7 @@ type BlockChain interface {
|
||||||
type txPool interface {
|
type txPool interface {
|
||||||
AddRemotes(txs []*types.Transaction) []error
|
AddRemotes(txs []*types.Transaction) []error
|
||||||
AddRemotesSync(txs []*types.Transaction) []error
|
AddRemotesSync(txs []*types.Transaction) []error
|
||||||
Status(hashes []common.Hash) []core.TxStatus
|
Status(hashes []common.Hash) []txpool.TxStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProtocolManager struct {
|
type ProtocolManager struct {
|
||||||
|
|
@ -1044,7 +1044,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
||||||
}
|
}
|
||||||
stats := pm.txStatus(hashes)
|
stats := pm.txStatus(hashes)
|
||||||
for i, stat := range stats {
|
for i, stat := range stats {
|
||||||
if stat.Status == core.TxStatusUnknown {
|
if stat.Status == txpool.TxStatusUnknown {
|
||||||
if errs := pm.txpool.AddRemotes([]*types.Transaction{req.Txs[i]}); errs[0] != nil {
|
if errs := pm.txpool.AddRemotes([]*types.Transaction{req.Txs[i]}); errs[0] != nil {
|
||||||
stats[i].Error = errs[0].Error()
|
stats[i].Error = errs[0].Error()
|
||||||
continue
|
continue
|
||||||
|
|
@ -1160,9 +1160,9 @@ func (pm *ProtocolManager) txStatus(hashes []common.Hash) []txStatus {
|
||||||
stats[i].Status = stat
|
stats[i].Status = stat
|
||||||
|
|
||||||
// If the transaction is unknown to the pool, try looking it up locally
|
// If the transaction is unknown to the pool, try looking it up locally
|
||||||
if stat == core.TxStatusUnknown {
|
if stat == txpool.TxStatusUnknown {
|
||||||
if block, number, index := core.GetTxLookupEntry(pm.chainDb, hashes[i]); block != (common.Hash{}) {
|
if block, number, index := core.GetTxLookupEntry(pm.chainDb, hashes[i]); block != (common.Hash{}) {
|
||||||
stats[i].Status = core.TxStatusIncluded
|
stats[i].Status = txpool.TxStatusIncluded
|
||||||
stats[i].Lookup = &core.TxLookupEntry{BlockHash: block, BlockIndex: number, Index: index}
|
stats[i].Lookup = &core.TxLookupEntry{BlockHash: block, BlockIndex: number, Index: index}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package les
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -27,6 +26,8 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||||
|
|
@ -493,10 +494,10 @@ func TestTransactionStatusLes2(t *testing.T) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
pm := newTestProtocolManagerMust(t, false, 0, nil, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, 0, nil, nil, nil, db)
|
||||||
chain := pm.blockchain.(*core.BlockChain)
|
chain := pm.blockchain.(*core.BlockChain)
|
||||||
config := core.DefaultTxPoolConfig
|
config := txpool.DefaultConfig
|
||||||
config.Journal = ""
|
config.Journal = ""
|
||||||
txpool := core.NewTxPool(config, params.TestChainConfig, chain)
|
txPool := txpool.NewTxPool(config, params.TestChainConfig, chain)
|
||||||
pm.txpool = txpool
|
pm.txpool = txPool
|
||||||
peer, _ := newTestPeer(t, "peer", 2, pm, true)
|
peer, _ := newTestPeer(t, "peer", 2, pm, true)
|
||||||
defer peer.close()
|
defer peer.close()
|
||||||
|
|
||||||
|
|
@ -520,20 +521,20 @@ func TestTransactionStatusLes2(t *testing.T) {
|
||||||
|
|
||||||
// test error status by sending an underpriced transaction
|
// test error status by sending an underpriced transaction
|
||||||
tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
|
tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
|
||||||
test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced.Error()})
|
test(tx0, true, txStatus{Status: txpool.TxStatusUnknown, Error: txpool.ErrUnderpriced.Error()})
|
||||||
|
|
||||||
tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
|
tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
|
||||||
test(tx1, false, txStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown
|
test(tx1, false, txStatus{Status: txpool.TxStatusUnknown}) // query before sending, should be unknown
|
||||||
test(tx1, true, txStatus{Status: core.TxStatusPending}) // send valid processable tx, should return pending
|
test(tx1, true, txStatus{Status: txpool.TxStatusPending}) // send valid processable tx, should return pending
|
||||||
test(tx1, true, txStatus{Status: core.TxStatusPending}) // adding it again should not return an error
|
test(tx1, true, txStatus{Status: txpool.TxStatusPending}) // adding it again should not return an error
|
||||||
|
|
||||||
tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
|
tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
|
||||||
tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
|
tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
|
||||||
// send transactions in the wrong order, tx3 should be queued
|
// send transactions in the wrong order, tx3 should be queued
|
||||||
test(tx3, true, txStatus{Status: core.TxStatusQueued})
|
test(tx3, true, txStatus{Status: txpool.TxStatusQueued})
|
||||||
test(tx2, true, txStatus{Status: core.TxStatusPending})
|
test(tx2, true, txStatus{Status: txpool.TxStatusPending})
|
||||||
// query again, now tx3 should be pending too
|
// query again, now tx3 should be pending too
|
||||||
test(tx3, false, txStatus{Status: core.TxStatusPending})
|
test(tx3, false, txStatus{Status: txpool.TxStatusPending})
|
||||||
|
|
||||||
// generate and add a block with tx1 and tx2 included
|
// generate and add a block with tx1 and tx2 included
|
||||||
gchain, _ := core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) {
|
gchain, _ := core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) {
|
||||||
|
|
@ -545,19 +546,19 @@ func TestTransactionStatusLes2(t *testing.T) {
|
||||||
}
|
}
|
||||||
// wait until TxPool processes the inserted block
|
// wait until TxPool processes the inserted block
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
if pending, _ := txpool.Stats(); pending == 1 {
|
if pending, _ := txPool.Stats(); pending == 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
if pending, _ := txpool.Stats(); pending != 1 {
|
if pending, _ := txPool.Stats(); pending != 1 {
|
||||||
t.Fatalf("pending count mismatch: have %d, want 1", pending)
|
t.Fatalf("pending count mismatch: have %d, want 1", pending)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if their status is included now
|
// check if their status is included now
|
||||||
block1hash := core.GetCanonicalHash(db, 1)
|
block1hash := core.GetCanonicalHash(db, 1)
|
||||||
test(tx1, false, txStatus{Status: core.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}})
|
test(tx1, false, txStatus{Status: txpool.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}})
|
||||||
test(tx2, false, txStatus{Status: core.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}})
|
test(tx2, false, txStatus{Status: txpool.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}})
|
||||||
|
|
||||||
// create a reorg that rolls them back
|
// create a reorg that rolls them back
|
||||||
gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 2, func(i int, block *core.BlockGen) {})
|
gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 2, func(i int, block *core.BlockGen) {})
|
||||||
|
|
@ -566,15 +567,15 @@ func TestTransactionStatusLes2(t *testing.T) {
|
||||||
}
|
}
|
||||||
// wait until TxPool processes the reorg
|
// wait until TxPool processes the reorg
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
if pending, _ := txpool.Stats(); pending == 3 {
|
if pending, _ := txPool.Stats(); pending == 3 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
if pending, _ := txpool.Stats(); pending != 3 {
|
if pending, _ := txPool.Stats(); pending != 3 {
|
||||||
t.Fatalf("pending count mismatch: have %d, want 3", pending)
|
t.Fatalf("pending count mismatch: have %d, want 3", pending)
|
||||||
}
|
}
|
||||||
// check if their status is pending again
|
// check if their status is pending again
|
||||||
test(tx1, false, txStatus{Status: core.TxStatusPending})
|
test(tx1, false, txStatus{Status: txpool.TxStatusPending})
|
||||||
test(tx2, false, txStatus{Status: core.TxStatusPending})
|
test(tx2, false, txStatus{Status: txpool.TxStatusPending})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
|
"github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
|
||||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||||
|
|
@ -223,7 +224,7 @@ type CodeData []struct {
|
||||||
type proofsData [][]rlp.RawValue
|
type proofsData [][]rlp.RawValue
|
||||||
|
|
||||||
type txStatus struct {
|
type txStatus struct {
|
||||||
Status core.TxStatus
|
Status txpool.TxStatus
|
||||||
Lookup *core.TxLookupEntry `rlp:"nil"`
|
Lookup *core.TxLookupEntry `rlp:"nil"`
|
||||||
Error string
|
Error string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/event"
|
"github.com/XinFinOrg/XDPoSChain/event"
|
||||||
|
|
@ -378,7 +379,7 @@ func (p *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error {
|
||||||
// Validate the transaction sender and it's sig. Throw
|
// Validate the transaction sender and it's sig. Throw
|
||||||
// if the from fields is invalid.
|
// if the from fields is invalid.
|
||||||
if from, err = types.Sender(p.signer, tx); err != nil {
|
if from, err = types.Sender(p.signer, tx); err != nil {
|
||||||
return core.ErrInvalidSender
|
return txpool.ErrInvalidSender
|
||||||
}
|
}
|
||||||
// Last but not least check for nonce errors
|
// Last but not least check for nonce errors
|
||||||
currentState := p.currentState(ctx)
|
currentState := p.currentState(ctx)
|
||||||
|
|
@ -390,14 +391,14 @@ func (p *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error {
|
||||||
// block limit gas.
|
// block limit gas.
|
||||||
header := p.chain.GetHeaderByHash(p.head)
|
header := p.chain.GetHeaderByHash(p.head)
|
||||||
if header.GasLimit < tx.Gas() {
|
if header.GasLimit < tx.Gas() {
|
||||||
return core.ErrGasLimit
|
return txpool.ErrGasLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transactions can't be negative. This may never happen
|
// Transactions can't be negative. This may never happen
|
||||||
// using RLP decoded transactions but may occur if you create
|
// using RLP decoded transactions but may occur if you create
|
||||||
// a transaction using the RPC for example.
|
// a transaction using the RPC for example.
|
||||||
if tx.Value().Sign() < 0 {
|
if tx.Value().Sign() < 0 {
|
||||||
return core.ErrNegativeValue
|
return txpool.ErrNegativeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transactor should have enough funds to cover the costs
|
// Transactor should have enough funds to cover the costs
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/XDCxlending"
|
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/XDCxlending"
|
||||||
"github.com/XinFinOrg/XDPoSChain/accounts"
|
"github.com/XinFinOrg/XDPoSChain/accounts"
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
|
|
@ -41,11 +41,11 @@ import (
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
AccountManager() *accounts.Manager
|
AccountManager() *accounts.Manager
|
||||||
BlockChain() *core.BlockChain
|
BlockChain() *core.BlockChain
|
||||||
TxPool() *core.TxPool
|
TxPool() *txpool.TxPool
|
||||||
ChainDb() ethdb.Database
|
ChainDb() ethdb.Database
|
||||||
GetXDCX() *XDCx.XDCX
|
GetXDCX() *XDCx.XDCX
|
||||||
OrderPool() *core.OrderPool
|
OrderPool() *txpool.OrderPool
|
||||||
LendingPool() *core.LendingPool
|
LendingPool() *txpool.LendingPool
|
||||||
GetXDCXLending() *XDCxlending.Lending
|
GetXDCXLending() *XDCxlending.Lending
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1048,7 +1048,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
|
||||||
w.tcount++
|
w.tcount++
|
||||||
txs.Shift()
|
txs.Shift()
|
||||||
|
|
||||||
case errors.Is(err, core.ErrTxTypeNotSupported):
|
case errors.Is(err, types.ErrTxTypeNotSupported):
|
||||||
// Pop the unsupported transaction without shifting in the next from the account
|
// Pop the unsupported transaction without shifting in the next from the account
|
||||||
log.Trace("Skipping unsupported transaction type", "sender", from, "type", tx.Type())
|
log.Trace("Skipping unsupported transaction type", "sender", from, "type", tx.Type())
|
||||||
txs.Pop()
|
txs.Pop()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue