mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 10:56:47 +00:00
mempool: Refactor mempool code to its own package.
Upstream commit 7fac099bee.
Also, the merge commit contains the necessary decred-specific
alterations, adds a new policy parameter for AllowOldVotes to keep with
the spirit of the merged commit, modifies the RawMempoolVerbose to
accept an optional filter type to retain that functionality, and various
other cleanup intended to bring the code bases more in line with one
another.
This commit is contained in:
commit
e9acb1d35b
@ -21,6 +21,7 @@ import (
|
||||
"github.com/decred/dcrd/chaincfg"
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
"github.com/decred/dcrd/database"
|
||||
"github.com/decred/dcrd/mempool"
|
||||
"github.com/decred/dcrd/wire"
|
||||
"github.com/decred/dcrutil"
|
||||
)
|
||||
@ -839,7 +840,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) {
|
||||
// simply rejected as opposed to something actually going wrong,
|
||||
// so log it as such. Otherwise, something really did go wrong,
|
||||
// so log it as an actual error.
|
||||
if _, ok := err.(RuleError); ok {
|
||||
if _, ok := err.(mempool.RuleError); ok {
|
||||
bmgrLog.Debugf("Rejected transaction %v from %s: %v",
|
||||
txHash, tmsg.peer, err)
|
||||
} else {
|
||||
@ -849,7 +850,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) {
|
||||
|
||||
// Convert the error into an appropriate reject message and
|
||||
// send it.
|
||||
code, reason := errToRejectErr(err)
|
||||
code, reason := mempool.ErrToRejectErr(err)
|
||||
tmsg.peer.PushRejectMsg(wire.CmdTx, code, reason, txHash,
|
||||
false)
|
||||
return
|
||||
@ -1140,7 +1141,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
|
||||
|
||||
// Convert the error into an appropriate reject message and
|
||||
// send it.
|
||||
code, reason := errToRejectErr(err)
|
||||
code, reason := mempool.ErrToRejectErr(err)
|
||||
bmsg.peer.PushRejectMsg(wire.CmdBlock, code, reason,
|
||||
blockHash, false)
|
||||
return
|
||||
@ -1205,7 +1206,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
|
||||
b.server.chainParams.StakeValidationHeight-1 {
|
||||
bmgrLog.Errorf("Failed to get next winning tickets: %v", err)
|
||||
|
||||
code, reason := errToRejectErr(err)
|
||||
code, reason := mempool.ErrToRejectErr(err)
|
||||
bmsg.peer.PushRejectMsg(wire.CmdBlock, code, reason,
|
||||
blockHash, false)
|
||||
return
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
"github.com/btcsuite/go-socks/socks"
|
||||
"github.com/decred/dcrd/database"
|
||||
_ "github.com/decred/dcrd/database/ffldb"
|
||||
"github.com/decred/dcrd/mempool"
|
||||
"github.com/decred/dcrd/wire"
|
||||
"github.com/decred/dcrutil"
|
||||
)
|
||||
@ -47,7 +48,6 @@ const (
|
||||
defaultBlockMaxSize = 375000
|
||||
blockMaxSizeMin = 1000
|
||||
blockMaxSizeMax = wire.MaxBlockPayload - 1000
|
||||
defaultBlockPrioritySize = 20000
|
||||
defaultAddrIndex = false
|
||||
defaultGenerate = false
|
||||
defaultNonAggressive = false
|
||||
@ -362,11 +362,11 @@ func loadConfig() (*config, []string, error) {
|
||||
DbType: defaultDbType,
|
||||
RPCKey: defaultRPCKeyFile,
|
||||
RPCCert: defaultRPCCertFile,
|
||||
MinRelayTxFee: defaultMinRelayTxFee.ToCoin(),
|
||||
MinRelayTxFee: mempool.DefaultMinRelayTxFee.ToCoin(),
|
||||
FreeTxRelayLimit: defaultFreeTxRelayLimit,
|
||||
BlockMinSize: defaultBlockMinSize,
|
||||
BlockMaxSize: defaultBlockMaxSize,
|
||||
BlockPrioritySize: defaultBlockPrioritySize,
|
||||
BlockPrioritySize: mempool.DefaultBlockPrioritySize,
|
||||
MaxOrphanTxs: defaultMaxOrphanTransactions,
|
||||
SigCacheMaxSize: defaultSigCacheMaxSize,
|
||||
Generate: defaultGenerate,
|
||||
|
||||
2
log.go
2
log.go
@ -17,6 +17,7 @@ import (
|
||||
"github.com/decred/dcrd/blockchain/indexers"
|
||||
"github.com/decred/dcrd/blockchain/stake"
|
||||
"github.com/decred/dcrd/database"
|
||||
"github.com/decred/dcrd/mempool"
|
||||
"github.com/decred/dcrd/peer"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
)
|
||||
@ -145,6 +146,7 @@ func useLogger(subsystemID string, logger btclog.Logger) {
|
||||
|
||||
case "TXMP":
|
||||
txmpLog = logger
|
||||
mempool.UseLogger(logger)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
23
mempool/README.md
Normal file
23
mempool/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
mempool
|
||||
=======
|
||||
|
||||
[]
|
||||
(https://travis-ci.org/decred/dcrd) [![ISC License]
|
||||
(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
|
||||
[]
|
||||
(http://godoc.org/github.com/decred/dcrd/mempool)
|
||||
|
||||
## Overview
|
||||
|
||||
This package is currently a work in progress.
|
||||
|
||||
## Installation and Updating
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/decred/dcrd/mempool
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Package mempool is licensed under the [copyfree](http://copyfree.org) ISC
|
||||
License.
|
||||
@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2014-2016 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"github.com/decred/dcrd/blockchain"
|
||||
@ -110,9 +110,9 @@ func extractRejectCode(err error) (wire.RejectCode, bool) {
|
||||
return wire.RejectInvalid, false
|
||||
}
|
||||
|
||||
// errToRejectErr examines the underlying type of the error and returns a reject
|
||||
// ErrToRejectErr examines the underlying type of the error and returns a reject
|
||||
// code and string appropriate to be sent in a wire.MsgReject message.
|
||||
func errToRejectErr(err error) (wire.RejectCode, string) {
|
||||
func ErrToRejectErr(err error) (wire.RejectCode, string) {
|
||||
// Return the reject code along with the error text if it can be
|
||||
// extracted from the error.
|
||||
rejectCode, found := extractRejectCode(err)
|
||||
33
mempool/log.go
Normal file
33
mempool/log.go
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Copyright (c) 2016 The decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
)
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
DisableLog()
|
||||
}
|
||||
|
||||
// DisableLog disables all library log output. Logging output is disabled
|
||||
// by default until either UseLogger or SetLogWriter are called.
|
||||
func DisableLog() {
|
||||
log = btclog.Disabled
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
// This should be used in preference to SetLogWriter if the caller is also
|
||||
// using btclog.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
@ -20,6 +20,7 @@ import (
|
||||
"github.com/decred/dcrd/blockchain/stake"
|
||||
"github.com/decred/dcrd/chaincfg"
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
"github.com/decred/dcrd/dcrjson"
|
||||
"github.com/decred/dcrd/mining"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
"github.com/decred/dcrd/wire"
|
||||
@ -27,6 +28,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultBlockPrioritySize is the default size in bytes for high-
|
||||
// priority / low-fee transactions. It is used to help determine which
|
||||
// are allowed into the mempool and consequently affects their relay and
|
||||
// inclusion when generating block templates.
|
||||
DefaultBlockPrioritySize = 20000
|
||||
|
||||
// MinHighPriority is the minimum priority value that allows a
|
||||
// transaction to be considered high priority.
|
||||
MinHighPriority = dcrutil.AtomsPerCoin * 144.0 / 250
|
||||
|
||||
// mempoolHeight is the height used for the "block" height field of the
|
||||
// contextual transaction information provided in a transaction view.
|
||||
mempoolHeight = 0x7fffffff
|
||||
@ -68,19 +79,13 @@ type VoteTx struct {
|
||||
Vote bool
|
||||
}
|
||||
|
||||
// mempoolTxDesc is a descriptor containing a transaction in the mempool along
|
||||
// with additional metadata.
|
||||
type mempoolTxDesc struct {
|
||||
mining.TxDesc
|
||||
// Config is a descriptor containing the memory pool configuration.
|
||||
type Config struct {
|
||||
// Policy defines the various mempool configuration options related
|
||||
// to policy.
|
||||
Policy Policy
|
||||
|
||||
// StartingPriority is the priority of the transaction when it was added
|
||||
// to the pool.
|
||||
StartingPriority float64
|
||||
}
|
||||
|
||||
// mempoolConfig is a descriptor containing the memory pool configuration.
|
||||
type mempoolConfig struct {
|
||||
// ChainParams identifies which chain parameters the mempool is
|
||||
// ChainParams identifies which chain parameters the txpool is
|
||||
// associated with.
|
||||
ChainParams *chaincfg.Params
|
||||
|
||||
@ -93,10 +98,6 @@ type mempoolConfig struct {
|
||||
// This function must be safe for concurrent access.
|
||||
NextStakeDifficulty func() (int64, error)
|
||||
|
||||
// Policy defines the various mempool configuration options related
|
||||
// to policy.
|
||||
Policy mempoolPolicy
|
||||
|
||||
// FetchUtxoView defines the function to use to fetch unspent
|
||||
// transaction output information.
|
||||
FetchUtxoView func(*dcrutil.Tx, bool) (*blockchain.UtxoViewpoint, error)
|
||||
@ -122,9 +123,9 @@ type mempoolConfig struct {
|
||||
ExistsAddrIndex *indexers.ExistsAddrIndex
|
||||
}
|
||||
|
||||
// mempoolPolicy houses the policy (configuration parameters) which is used to
|
||||
// Policy houses the policy (configuration parameters) which is used to
|
||||
// control the mempool.
|
||||
type mempoolPolicy struct {
|
||||
type Policy struct {
|
||||
// DisableRelayPriority defines whether to relay free or low-fee
|
||||
// transactions that do not have enough priority to be relayed.
|
||||
DisableRelayPriority bool
|
||||
@ -150,18 +151,32 @@ type mempoolPolicy struct {
|
||||
// MinRelayTxFee defines the minimum transaction fee in BTC/kB to be
|
||||
// considered a non-zero fee.
|
||||
MinRelayTxFee dcrutil.Amount
|
||||
|
||||
// AllowOldVotes defines whether or not votes on old blocks will be
|
||||
// admitted and relayed.
|
||||
AllowOldVotes bool
|
||||
}
|
||||
|
||||
// txMemPool is used as a source of transactions that need to be mined into
|
||||
// blocks and relayed to other peers. It is safe for concurrent access from
|
||||
// multiple peers.
|
||||
type txMemPool struct {
|
||||
// TxDesc is a descriptor containing a transaction in the mempool along with
|
||||
// additional metadata.
|
||||
type TxDesc struct {
|
||||
mining.TxDesc
|
||||
|
||||
// StartingPriority is the priority of the transaction when it was added
|
||||
// to the pool.
|
||||
StartingPriority float64
|
||||
}
|
||||
|
||||
// TxPool is used as a source of transactions that need to be mined into blocks
|
||||
// and relayed to other peers. It is safe for concurrent access from multiple
|
||||
// peers.
|
||||
type TxPool struct {
|
||||
// The following variables must only be used atomically.
|
||||
lastUpdated int64 // last time pool was updated.
|
||||
|
||||
sync.RWMutex
|
||||
cfg mempoolConfig
|
||||
pool map[chainhash.Hash]*mempoolTxDesc
|
||||
cfg Config
|
||||
pool map[chainhash.Hash]*TxDesc
|
||||
orphans map[chainhash.Hash]*dcrutil.Tx
|
||||
orphansByPrev map[chainhash.Hash]map[chainhash.Hash]*dcrutil.Tx
|
||||
addrindex map[string]map[chainhash.Hash]struct{} // maps address to txs
|
||||
@ -181,7 +196,7 @@ type txMemPool struct {
|
||||
// insertVote inserts a vote into the map of block votes.
|
||||
//
|
||||
// This function MUST be called with the vote mutex locked (for writes).
|
||||
func (mp *txMemPool) insertVote(ssgen *dcrutil.Tx) error {
|
||||
func (mp *TxPool) insertVote(ssgen *dcrutil.Tx) error {
|
||||
voteHash := ssgen.Hash()
|
||||
msgTx := ssgen.MsgTx()
|
||||
ticketHash := &msgTx.TxIn[1].PreviousOutPoint.Hash
|
||||
@ -212,9 +227,9 @@ func (mp *txMemPool) insertVote(ssgen *dcrutil.Tx) error {
|
||||
vote := dcrutil.IsFlagSet16(voteBits, dcrutil.BlockValid)
|
||||
mp.votes[blockHash] = append(vts, &VoteTx{*voteHash, *ticketHash, vote})
|
||||
|
||||
minrLog.Debugf("Accepted vote %v for block hash %v (height %v), "+
|
||||
"voting %v on the transaction tree",
|
||||
voteHash, blockHash, blockHeight, vote)
|
||||
log.Debugf("Accepted vote %v for block hash %v (height %v), voting "+
|
||||
"%v on the transaction tree", voteHash, blockHash, blockHeight,
|
||||
vote)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -223,7 +238,7 @@ func (mp *txMemPool) insertVote(ssgen *dcrutil.Tx) error {
|
||||
// hash that are currently available in the mempool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) VoteHashesForBlock(blockHash chainhash.Hash) []chainhash.Hash {
|
||||
func (mp *TxPool) VoteHashesForBlock(blockHash chainhash.Hash) []chainhash.Hash {
|
||||
mp.votesMtx.Lock()
|
||||
defer mp.votesMtx.Unlock()
|
||||
|
||||
@ -246,7 +261,7 @@ func (mp *txMemPool) VoteHashesForBlock(blockHash chainhash.Hash) []chainhash.Ha
|
||||
// block hashes that are currently available in the mempool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) VotesForBlocks(hashes []chainhash.Hash) [][]*VoteTx {
|
||||
func (mp *TxPool) VotesForBlocks(hashes []chainhash.Hash) [][]*VoteTx {
|
||||
result := make([][]*VoteTx, 0, len(hashes))
|
||||
mp.votesMtx.Lock()
|
||||
for _, hash := range hashes {
|
||||
@ -262,15 +277,15 @@ func (mp *txMemPool) VotesForBlocks(hashes []chainhash.Hash) [][]*VoteTx {
|
||||
|
||||
// TODO Pruning of the votes map DECRED
|
||||
|
||||
// Ensure the txMemPool type implements the mining.TxSource interface.
|
||||
var _ mining.TxSource = (*txMemPool)(nil)
|
||||
// Ensure the TxPool type implements the mining.TxSource interface.
|
||||
var _ mining.TxSource = (*TxPool)(nil)
|
||||
|
||||
// removeOrphan is the internal function which implements the public
|
||||
// RemoveOrphan. See the comment for RemoveOrphan for more details.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) removeOrphan(txHash *chainhash.Hash) {
|
||||
txmpLog.Tracef("Removing orphan transaction %v", txHash)
|
||||
func (mp *TxPool) removeOrphan(txHash *chainhash.Hash) {
|
||||
log.Tracef("Removing orphan transaction %v", txHash)
|
||||
|
||||
// Nothing to do if passed tx is not an orphan.
|
||||
tx, exists := mp.orphans[*txHash]
|
||||
@ -300,7 +315,7 @@ func (mp *txMemPool) removeOrphan(txHash *chainhash.Hash) {
|
||||
// previous orphan index.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) RemoveOrphan(txHash *chainhash.Hash) {
|
||||
func (mp *TxPool) RemoveOrphan(txHash *chainhash.Hash) {
|
||||
mp.Lock()
|
||||
mp.removeOrphan(txHash)
|
||||
mp.Unlock()
|
||||
@ -310,7 +325,7 @@ func (mp *txMemPool) RemoveOrphan(txHash *chainhash.Hash) {
|
||||
// orphan if adding a new one would cause it to overflow the max allowed.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) limitNumOrphans() error {
|
||||
func (mp *TxPool) limitNumOrphans() error {
|
||||
if len(mp.orphans)+1 > mp.cfg.Policy.MaxOrphanTxs &&
|
||||
mp.cfg.Policy.MaxOrphanTxs > 0 {
|
||||
|
||||
@ -348,7 +363,7 @@ func (mp *txMemPool) limitNumOrphans() error {
|
||||
// addOrphan adds an orphan transaction to the orphan pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) addOrphan(tx *dcrutil.Tx) {
|
||||
func (mp *TxPool) addOrphan(tx *dcrutil.Tx) {
|
||||
// Limit the number orphan transactions to prevent memory exhaustion. A
|
||||
// random orphan is evicted to make room if needed.
|
||||
mp.limitNumOrphans()
|
||||
@ -363,14 +378,14 @@ func (mp *txMemPool) addOrphan(tx *dcrutil.Tx) {
|
||||
mp.orphansByPrev[originTxHash][*tx.Hash()] = tx
|
||||
}
|
||||
|
||||
txmpLog.Debugf("Stored orphan transaction %v (total: %d)", tx.Hash(),
|
||||
log.Debugf("Stored orphan transaction %v (total: %d)", tx.Hash(),
|
||||
len(mp.orphans))
|
||||
}
|
||||
|
||||
// maybeAddOrphan potentially adds an orphan to the orphan pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) maybeAddOrphan(tx *dcrutil.Tx) error {
|
||||
func (mp *TxPool) maybeAddOrphan(tx *dcrutil.Tx) error {
|
||||
// Ignore orphan transactions that are too large. This helps avoid
|
||||
// a memory exhaustion attack based on sending a lot of really large
|
||||
// orphans. In the case there is a valid transaction larger than this,
|
||||
@ -399,7 +414,7 @@ func (mp *txMemPool) maybeAddOrphan(tx *dcrutil.Tx) error {
|
||||
// exists in the main pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) isTransactionInPool(hash *chainhash.Hash) bool {
|
||||
func (mp *TxPool) isTransactionInPool(hash *chainhash.Hash) bool {
|
||||
if _, exists := mp.pool[*hash]; exists {
|
||||
return true
|
||||
}
|
||||
@ -411,7 +426,7 @@ func (mp *txMemPool) isTransactionInPool(hash *chainhash.Hash) bool {
|
||||
// exists in the main pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) IsTransactionInPool(hash *chainhash.Hash) bool {
|
||||
func (mp *TxPool) IsTransactionInPool(hash *chainhash.Hash) bool {
|
||||
// Protect concurrent access.
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
@ -423,7 +438,7 @@ func (mp *txMemPool) IsTransactionInPool(hash *chainhash.Hash) bool {
|
||||
// in the orphan pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) isOrphanInPool(hash *chainhash.Hash) bool {
|
||||
func (mp *TxPool) isOrphanInPool(hash *chainhash.Hash) bool {
|
||||
if _, exists := mp.orphans[*hash]; exists {
|
||||
return true
|
||||
}
|
||||
@ -435,7 +450,7 @@ func (mp *txMemPool) isOrphanInPool(hash *chainhash.Hash) bool {
|
||||
// in the orphan pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) IsOrphanInPool(hash *chainhash.Hash) bool {
|
||||
func (mp *TxPool) IsOrphanInPool(hash *chainhash.Hash) bool {
|
||||
// Protect concurrent access.
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
@ -447,7 +462,7 @@ func (mp *txMemPool) IsOrphanInPool(hash *chainhash.Hash) bool {
|
||||
// in the main pool or in the orphan pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) haveTransaction(hash *chainhash.Hash) bool {
|
||||
func (mp *TxPool) haveTransaction(hash *chainhash.Hash) bool {
|
||||
return mp.isTransactionInPool(hash) || mp.isOrphanInPool(hash)
|
||||
}
|
||||
|
||||
@ -455,7 +470,7 @@ func (mp *txMemPool) haveTransaction(hash *chainhash.Hash) bool {
|
||||
// in the main pool or in the orphan pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) HaveTransaction(hash *chainhash.Hash) bool {
|
||||
func (mp *TxPool) HaveTransaction(hash *chainhash.Hash) bool {
|
||||
// Protect concurrent access.
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
@ -467,7 +482,7 @@ func (mp *txMemPool) HaveTransaction(hash *chainhash.Hash) bool {
|
||||
// in the main pool or in the orphan pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) haveTransactions(hashes []*chainhash.Hash) []bool {
|
||||
func (mp *TxPool) haveTransactions(hashes []*chainhash.Hash) []bool {
|
||||
have := make([]bool, len(hashes))
|
||||
for i := range hashes {
|
||||
have[i] = mp.haveTransaction(hashes[i])
|
||||
@ -479,7 +494,7 @@ func (mp *txMemPool) haveTransactions(hashes []*chainhash.Hash) []bool {
|
||||
// in the main pool or in the orphan pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) HaveTransactions(hashes []*chainhash.Hash) []bool {
|
||||
func (mp *TxPool) HaveTransactions(hashes []*chainhash.Hash) []bool {
|
||||
// Protect concurrent access.
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
@ -491,8 +506,8 @@ func (mp *txMemPool) HaveTransactions(hashes []*chainhash.Hash) []bool {
|
||||
// RemoveTransaction. See the comment for RemoveTransaction for more details.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) removeTransaction(tx *dcrutil.Tx, removeRedeemers bool) {
|
||||
txmpLog.Tracef("Removing transaction %v", tx.Hash())
|
||||
func (mp *TxPool) removeTransaction(tx *dcrutil.Tx, removeRedeemers bool) {
|
||||
log.Tracef("Removing transaction %v", tx.Hash())
|
||||
|
||||
msgTx := tx.MsgTx()
|
||||
txHash := tx.Hash()
|
||||
@ -536,7 +551,7 @@ func (mp *txMemPool) removeTransaction(tx *dcrutil.Tx, removeRedeemers bool) {
|
||||
// they would otherwise become orphans.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) RemoveTransaction(tx *dcrutil.Tx, removeRedeemers bool) {
|
||||
func (mp *TxPool) RemoveTransaction(tx *dcrutil.Tx, removeRedeemers bool) {
|
||||
// Protect concurrent access.
|
||||
mp.Lock()
|
||||
defer mp.Unlock()
|
||||
@ -551,7 +566,7 @@ func (mp *txMemPool) RemoveTransaction(tx *dcrutil.Tx, removeRedeemers bool) {
|
||||
// contain transactions which were previously unknown to the memory pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) RemoveDoubleSpends(tx *dcrutil.Tx) {
|
||||
func (mp *TxPool) RemoveDoubleSpends(tx *dcrutil.Tx) {
|
||||
// Protect concurrent access.
|
||||
mp.Lock()
|
||||
defer mp.Unlock()
|
||||
@ -570,12 +585,13 @@ func (mp *txMemPool) RemoveDoubleSpends(tx *dcrutil.Tx) {
|
||||
// helper for maybeAcceptTransaction.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) addTransaction(utxoView *blockchain.UtxoViewpoint,
|
||||
func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint,
|
||||
tx *dcrutil.Tx, txType stake.TxType, height int64, fee int64) {
|
||||
msgTx := tx.MsgTx()
|
||||
|
||||
// Add the transaction to the pool and mark the referenced outpoints
|
||||
// as spent by the pool.
|
||||
mp.pool[*tx.Hash()] = &mempoolTxDesc{
|
||||
msgTx := tx.MsgTx()
|
||||
mp.pool[*tx.Hash()] = &TxDesc{
|
||||
TxDesc: mining.TxDesc{
|
||||
Tx: tx,
|
||||
Type: txType,
|
||||
@ -583,7 +599,7 @@ func (mp *txMemPool) addTransaction(utxoView *blockchain.UtxoViewpoint,
|
||||
Height: height,
|
||||
Fee: fee,
|
||||
},
|
||||
StartingPriority: calcPriority(msgTx, utxoView, height),
|
||||
StartingPriority: CalcPriority(msgTx, utxoView, height),
|
||||
}
|
||||
for _, txIn := range msgTx.TxIn {
|
||||
mp.outpoints[txIn.PreviousOutPoint] = tx
|
||||
@ -606,9 +622,7 @@ func (mp *txMemPool) addTransaction(utxoView *blockchain.UtxoViewpoint,
|
||||
// main chain.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) checkPoolDoubleSpend(tx *dcrutil.Tx,
|
||||
txType stake.TxType) error {
|
||||
|
||||
func (mp *TxPool) checkPoolDoubleSpend(tx *dcrutil.Tx, txType stake.TxType) error {
|
||||
for i, txIn := range tx.MsgTx().TxIn {
|
||||
// We don't care about double spends of stake bases.
|
||||
if (txType == stake.TxTypeSSGen || txType == stake.TxTypeSSRtx) &&
|
||||
@ -628,7 +642,7 @@ func (mp *txMemPool) checkPoolDoubleSpend(tx *dcrutil.Tx,
|
||||
|
||||
// isTxTreeValid checks the map of votes for a block to see if the tx
|
||||
// tree regular for the block at HEAD is valid.
|
||||
func (mp *txMemPool) isTxTreeValid(newestHash *chainhash.Hash) bool {
|
||||
func (mp *TxPool) isTxTreeValid(newestHash *chainhash.Hash) bool {
|
||||
// There are no votes on the block currently; assume it's valid.
|
||||
vts := mp.votes[*newestHash]
|
||||
if len(vts) == 0 {
|
||||
@ -656,7 +670,7 @@ func (mp *txMemPool) isTxTreeValid(newestHash *chainhash.Hash) bool {
|
||||
}
|
||||
|
||||
// IsTxTreeValid calls isTxTreeValid, but makes it safe for concurrent access.
|
||||
func (mp *txMemPool) IsTxTreeValid(best *chainhash.Hash) bool {
|
||||
func (mp *TxPool) IsTxTreeValid(best *chainhash.Hash) bool {
|
||||
mp.votesMtx.Lock()
|
||||
defer mp.votesMtx.Unlock()
|
||||
isValid := mp.isTxTreeValid(best)
|
||||
@ -670,7 +684,7 @@ func (mp *txMemPool) IsTxTreeValid(best *chainhash.Hash) bool {
|
||||
// transaction pool.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for reads).
|
||||
func (mp *txMemPool) fetchInputUtxos(tx *dcrutil.Tx) (*blockchain.UtxoViewpoint, error) {
|
||||
func (mp *TxPool) fetchInputUtxos(tx *dcrutil.Tx) (*blockchain.UtxoViewpoint, error) {
|
||||
best := mp.cfg.Chain.BestSnapshot()
|
||||
tv := mp.IsTxTreeValid(best.Hash)
|
||||
utxoView, err := mp.cfg.FetchUtxoView(tx, tv)
|
||||
@ -698,7 +712,7 @@ func (mp *txMemPool) fetchInputUtxos(tx *dcrutil.Tx) (*blockchain.UtxoViewpoint,
|
||||
// orphans.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) FetchTransaction(txHash *chainhash.Hash, includeRecentBlock bool) (*dcrutil.Tx, error) {
|
||||
func (mp *TxPool) FetchTransaction(txHash *chainhash.Hash, includeRecentBlock bool) (*dcrutil.Tx, error) {
|
||||
// Protect concurrent access.
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
@ -737,7 +751,7 @@ func (mp *txMemPool) FetchTransaction(txHash *chainhash.Hash, includeRecentBlock
|
||||
// so that we can easily pick different stake tx types from the mempool later.
|
||||
// This should probably be done at the bottom using "IsSStx" etc functions.
|
||||
// It should also set the dcrutil tree type for the tx as well.
|
||||
func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, allowHighFees bool) ([]*chainhash.Hash, error) {
|
||||
func (mp *TxPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, allowHighFees bool) ([]*chainhash.Hash, error) {
|
||||
msgTx := tx.MsgTx()
|
||||
txHash := tx.Hash()
|
||||
// Don't accept the transaction if it already exists in the pool. This
|
||||
@ -794,7 +808,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
|
||||
// Don't allow non-standard transactions if the network parameters
|
||||
// forbid their relaying.
|
||||
if !activeNetParams.RelayNonStdTxs {
|
||||
if !mp.cfg.ChainParams.RelayNonStdTxs {
|
||||
err := checkTransactionStandard(tx, txType, nextBlockHeight,
|
||||
mp.cfg.TimeSource, mp.cfg.Policy.MinRelayTxFee)
|
||||
if err != nil {
|
||||
@ -886,7 +900,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
}
|
||||
|
||||
if (int64(voteHeight) < nextBlockHeight-maximumVoteAgeDelta) &&
|
||||
!cfg.AllowOldVotes {
|
||||
!mp.cfg.Policy.AllowOldVotes {
|
||||
str := fmt.Sprintf("transaction %v votes on old "+
|
||||
"block height of %v which is before the "+
|
||||
"current cutoff height of %v",
|
||||
@ -935,13 +949,13 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
// Prevent a panic in the logger by continuing here if the
|
||||
// transaction input is nil.
|
||||
if entry == nil {
|
||||
txmpLog.Tracef("Transaction %v uses unknown input %v "+
|
||||
log.Tracef("Transaction %v uses unknown input %v "+
|
||||
"and will be considered an orphan", txHash,
|
||||
txIn.PreviousOutPoint.Hash)
|
||||
continue
|
||||
}
|
||||
if entry.IsFullySpent() {
|
||||
txmpLog.Tracef("Transaction %v uses full spent input %v "+
|
||||
log.Tracef("Transaction %v uses full spent input %v "+
|
||||
"and will be considered an orphan", txHash,
|
||||
txIn.PreviousOutPoint.Hash)
|
||||
}
|
||||
@ -968,7 +982,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
|
||||
// Don't allow transactions with non-standard inputs if the network
|
||||
// parameters forbid their relaying.
|
||||
if !activeNetParams.RelayNonStdTxs {
|
||||
if !mp.cfg.ChainParams.RelayNonStdTxs {
|
||||
err := checkInputsStandard(tx, txType, utxoView)
|
||||
if err != nil {
|
||||
// Attempt to extract a reject code from the error so
|
||||
@ -1025,10 +1039,12 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
minFee := calcMinRequiredTxRelayFee(serializedSize,
|
||||
mp.cfg.Policy.MinRelayTxFee)
|
||||
if txType == stake.TxTypeRegular { // Non-stake only
|
||||
if serializedSize >= (defaultBlockPrioritySize-1000) && txFee < minFee {
|
||||
str := fmt.Sprintf("transaction %v has %v fees which is under "+
|
||||
"the required amount of %v", txHash, txFee,
|
||||
minFee)
|
||||
if serializedSize >= (DefaultBlockPrioritySize-1000) &&
|
||||
txFee < minFee {
|
||||
|
||||
str := fmt.Sprintf("transaction %v has %v fees which "+
|
||||
"is under the required amount of %v", txHash,
|
||||
txFee, minFee)
|
||||
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
||||
}
|
||||
}
|
||||
@ -1042,12 +1058,12 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
if isNew && !mp.cfg.Policy.DisableRelayPriority && txFee < minFee &&
|
||||
txType == stake.TxTypeRegular {
|
||||
|
||||
currentPriority := calcPriority(msgTx, utxoView,
|
||||
currentPriority := CalcPriority(msgTx, utxoView,
|
||||
nextBlockHeight)
|
||||
if currentPriority <= minHighPriority {
|
||||
if currentPriority <= MinHighPriority {
|
||||
str := fmt.Sprintf("transaction %v has insufficient "+
|
||||
"priority (%g <= %g)", txHash,
|
||||
currentPriority, minHighPriority)
|
||||
currentPriority, MinHighPriority)
|
||||
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
||||
}
|
||||
}
|
||||
@ -1057,8 +1073,8 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
// This applies to non-stake transactions only.
|
||||
if rateLimit && txFee < minFee && txType == stake.TxTypeRegular {
|
||||
nowUnix := time.Now().Unix()
|
||||
// we decay passed data with an exponentially decaying ~10
|
||||
// minutes window - matches bitcoind handling.
|
||||
// Decay passed data with an exponentially decaying ~10 minute
|
||||
// window.
|
||||
mp.pennyTotal *= math.Pow(1.0-1.0/600.0,
|
||||
float64(nowUnix-mp.lastPennyUnix))
|
||||
mp.lastPennyUnix = nowUnix
|
||||
@ -1072,7 +1088,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
oldTotal := mp.pennyTotal
|
||||
|
||||
mp.pennyTotal += float64(serializedSize)
|
||||
txmpLog.Tracef("rate limit: curTotal %v, nextTotal: %v, "+
|
||||
log.Tracef("rate limit: curTotal %v, nextTotal: %v, "+
|
||||
"limit %v", oldTotal, mp.pennyTotal,
|
||||
mp.cfg.Policy.FreeTxRelayLimit*10*1000)
|
||||
}
|
||||
@ -1096,7 +1112,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
// then they can AllowHighFees = true
|
||||
if !allowHighFees {
|
||||
maxFee := calcMinRequiredTxRelayFee(serializedSize*maxRelayFeeMultiplier,
|
||||
cfg.minRelayTxFee)
|
||||
mp.cfg.Policy.MinRelayTxFee)
|
||||
if txFee > maxFee {
|
||||
err = fmt.Errorf("transaction %v has %v fee which is above the "+
|
||||
"allowHighFee check threshold amount of %v", txHash,
|
||||
@ -1130,7 +1146,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
}
|
||||
}
|
||||
|
||||
txmpLog.Debugf("Accepted transaction %v (pool size: %v)", txHash,
|
||||
log.Debugf("Accepted transaction %v (pool size: %v)", txHash,
|
||||
len(mp.pool))
|
||||
|
||||
return nil, nil
|
||||
@ -1144,7 +1160,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit, al
|
||||
// or not the transaction is an orphan.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) MaybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit bool) ([]*chainhash.Hash, error) {
|
||||
func (mp *TxPool) MaybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit bool) ([]*chainhash.Hash, error) {
|
||||
// Protect concurrent access.
|
||||
mp.Lock()
|
||||
defer mp.Unlock()
|
||||
@ -1156,7 +1172,7 @@ func (mp *txMemPool) MaybeAcceptTransaction(tx *dcrutil.Tx, isNew, rateLimit boo
|
||||
// ProcessOrphans. See the comment for ProcessOrphans for more details.
|
||||
//
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *txMemPool) processOrphans(hash *chainhash.Hash) []*dcrutil.Tx {
|
||||
func (mp *TxPool) processOrphans(hash *chainhash.Hash) []*dcrutil.Tx {
|
||||
var acceptedTxns []*dcrutil.Tx
|
||||
|
||||
// Start with processing at least the passed hash.
|
||||
@ -1201,9 +1217,8 @@ func (mp *txMemPool) processOrphans(hash *chainhash.Hash) []*dcrutil.Tx {
|
||||
if err != nil {
|
||||
// TODO: Remove orphans that depend on this
|
||||
// failed transaction.
|
||||
txmpLog.Debugf("Unable to move "+
|
||||
"orphan transaction %v to mempool: %v",
|
||||
tx.Hash(), err)
|
||||
log.Debugf("Unable to move orphan transaction "+
|
||||
"%v to mempool: %v", tx.Hash(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
@ -1244,7 +1259,7 @@ func (mp *txMemPool) processOrphans(hash *chainhash.Hash) []*dcrutil.Tx {
|
||||
// stake difficulty is below the current required stake difficulty should be
|
||||
// pruned from mempool since they will never be mined. The same idea stands
|
||||
// for SSGen and SSRtx
|
||||
func (mp *txMemPool) PruneStakeTx(requiredStakeDifficulty, height int64) {
|
||||
func (mp *TxPool) PruneStakeTx(requiredStakeDifficulty, height int64) {
|
||||
// Protect concurrent access.
|
||||
mp.Lock()
|
||||
defer mp.Unlock()
|
||||
@ -1252,7 +1267,7 @@ func (mp *txMemPool) PruneStakeTx(requiredStakeDifficulty, height int64) {
|
||||
mp.pruneStakeTx(requiredStakeDifficulty, height)
|
||||
}
|
||||
|
||||
func (mp *txMemPool) pruneStakeTx(requiredStakeDifficulty, height int64) {
|
||||
func (mp *TxPool) pruneStakeTx(requiredStakeDifficulty, height int64) {
|
||||
for _, tx := range mp.pool {
|
||||
txType := stake.DetermineTxType(tx.Tx.MsgTx())
|
||||
if txType == stake.TxTypeSStx &&
|
||||
@ -1272,7 +1287,7 @@ func (mp *txMemPool) pruneStakeTx(requiredStakeDifficulty, height int64) {
|
||||
|
||||
// PruneExpiredTx prunes expired transactions from the mempool that may no longer
|
||||
// be able to be included into a block.
|
||||
func (mp *txMemPool) PruneExpiredTx(height int64) {
|
||||
func (mp *TxPool) PruneExpiredTx(height int64) {
|
||||
// Protect concurrent access.
|
||||
mp.Lock()
|
||||
defer mp.Unlock()
|
||||
@ -1280,12 +1295,12 @@ func (mp *txMemPool) PruneExpiredTx(height int64) {
|
||||
mp.pruneExpiredTx(height)
|
||||
}
|
||||
|
||||
func (mp *txMemPool) pruneExpiredTx(height int64) {
|
||||
func (mp *TxPool) pruneExpiredTx(height int64) {
|
||||
for _, tx := range mp.pool {
|
||||
if tx.Tx.MsgTx().Expiry != 0 {
|
||||
if height >= int64(tx.Tx.MsgTx().Expiry) {
|
||||
txmpLog.Debugf("Pruning expired transaction %v from the "+
|
||||
"mempool", tx.Tx.Hash())
|
||||
log.Debugf("Pruning expired transaction %v "+
|
||||
"from the mempool", tx.Tx.Hash())
|
||||
mp.removeTransaction(tx.Tx, true)
|
||||
}
|
||||
}
|
||||
@ -1302,7 +1317,7 @@ func (mp *txMemPool) pruneExpiredTx(height int64) {
|
||||
// no transactions were moved from the orphan pool to the mempool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) ProcessOrphans(hash *chainhash.Hash) []*dcrutil.Tx {
|
||||
func (mp *TxPool) ProcessOrphans(hash *chainhash.Hash) []*dcrutil.Tx {
|
||||
mp.Lock()
|
||||
acceptedTxns := mp.processOrphans(hash)
|
||||
mp.Unlock()
|
||||
@ -1321,20 +1336,19 @@ func (mp *txMemPool) ProcessOrphans(hash *chainhash.Hash) []*dcrutil.Tx {
|
||||
// the passed one being accepted.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) ProcessTransaction(tx *dcrutil.Tx, allowOrphan,
|
||||
rateLimit, allowHighFees bool) ([]*dcrutil.Tx, error) {
|
||||
func (mp *TxPool) ProcessTransaction(tx *dcrutil.Tx, allowOrphan, rateLimit, allowHighFees bool) ([]*dcrutil.Tx, error) {
|
||||
// Protect concurrent access.
|
||||
mp.Lock()
|
||||
defer mp.Unlock()
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
txmpLog.Tracef("Failed to process transaction %v: %s",
|
||||
log.Tracef("Failed to process transaction %v: %s",
|
||||
tx.Hash(), err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
txmpLog.Tracef("Processing transaction %v", tx.Hash())
|
||||
log.Tracef("Processing transaction %v", tx.Hash())
|
||||
|
||||
// Potentially accept the transaction to the memory pool.
|
||||
var missingParents []*chainhash.Hash
|
||||
@ -1392,7 +1406,7 @@ func (mp *txMemPool) ProcessTransaction(tx *dcrutil.Tx, allowOrphan,
|
||||
// include the orphan pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) Count() int {
|
||||
func (mp *TxPool) Count() int {
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
@ -1403,7 +1417,7 @@ func (mp *txMemPool) Count() int {
|
||||
// pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) TxHashes() []*chainhash.Hash {
|
||||
func (mp *TxPool) TxHashes() []*chainhash.Hash {
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
@ -1422,11 +1436,11 @@ func (mp *txMemPool) TxHashes() []*chainhash.Hash {
|
||||
// The descriptors are to be treated as read only.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) TxDescs() []*mempoolTxDesc {
|
||||
func (mp *TxPool) TxDescs() []*TxDesc {
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
descs := make([]*mempoolTxDesc, len(mp.pool))
|
||||
descs := make([]*TxDesc, len(mp.pool))
|
||||
i := 0
|
||||
for _, desc := range mp.pool {
|
||||
descs[i] = desc
|
||||
@ -1441,7 +1455,7 @@ func (mp *txMemPool) TxDescs() []*mempoolTxDesc {
|
||||
//
|
||||
// This is part of the mining.TxSource interface implementation and is safe for
|
||||
// concurrent access as required by the interface contract.
|
||||
func (mp *txMemPool) MiningDescs() []*mining.TxDesc {
|
||||
func (mp *TxPool) MiningDescs() []*mining.TxDesc {
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
@ -1455,11 +1469,65 @@ func (mp *txMemPool) MiningDescs() []*mining.TxDesc {
|
||||
return descs
|
||||
}
|
||||
|
||||
// RawMempoolVerbose returns all of the entries in the mempool filtered by the
|
||||
// provided stake type as a fully populated JSON result. The filter type can be
|
||||
// nil in which case all transactions will be returned.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *TxPool) RawMempoolVerbose(filterType *stake.TxType) map[string]*dcrjson.GetRawMempoolVerboseResult {
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
result := make(map[string]*dcrjson.GetRawMempoolVerboseResult,
|
||||
len(mp.pool))
|
||||
best := mp.cfg.Chain.BestSnapshot()
|
||||
|
||||
for _, desc := range mp.pool {
|
||||
// Skip entries that don't match the requested stake type if
|
||||
// specified.
|
||||
if filterType != nil && desc.Type != *filterType {
|
||||
continue
|
||||
}
|
||||
|
||||
// Calculate the current priority based on the inputs to
|
||||
// the transaction. Use zero if one or more of the
|
||||
// input transactions can't be found for some reason.
|
||||
tx := desc.Tx
|
||||
var currentPriority float64
|
||||
utxos, err := mp.fetchInputUtxos(tx)
|
||||
if err == nil {
|
||||
currentPriority = CalcPriority(tx.MsgTx(), utxos,
|
||||
best.Height+1)
|
||||
}
|
||||
|
||||
mpd := &dcrjson.GetRawMempoolVerboseResult{
|
||||
Size: int32(tx.MsgTx().SerializeSize()),
|
||||
Fee: dcrutil.Amount(desc.Fee).ToCoin(),
|
||||
Time: desc.Added.Unix(),
|
||||
Height: int64(desc.Height),
|
||||
StartingPriority: desc.StartingPriority,
|
||||
CurrentPriority: currentPriority,
|
||||
Depends: make([]string, 0),
|
||||
}
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
hash := &txIn.PreviousOutPoint.Hash
|
||||
if mp.haveTransaction(hash) {
|
||||
mpd.Depends = append(mpd.Depends,
|
||||
hash.String())
|
||||
}
|
||||
}
|
||||
|
||||
result[tx.Hash().String()] = mpd
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// LastUpdated returns the last time a transaction was added to or removed from
|
||||
// the main pool. It does not include the orphan pool.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) LastUpdated() time.Time {
|
||||
func (mp *TxPool) LastUpdated() time.Time {
|
||||
return time.Unix(atomic.LoadInt64(&mp.lastUpdated), 0)
|
||||
}
|
||||
|
||||
@ -1467,7 +1535,7 @@ func (mp *txMemPool) LastUpdated() time.Time {
|
||||
// and returns true if they all exist in the mempool, otherwise false.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *txMemPool) CheckIfTxsExist(hashes []chainhash.Hash) bool {
|
||||
func (mp *TxPool) CheckIfTxsExist(hashes []chainhash.Hash) bool {
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
|
||||
@ -1482,18 +1550,16 @@ func (mp *txMemPool) CheckIfTxsExist(hashes []chainhash.Hash) bool {
|
||||
return inPool
|
||||
}
|
||||
|
||||
// newTxMemPool returns a new memory pool for validating and storing standalone
|
||||
// New returns a new memory pool for validating and storing standalone
|
||||
// transactions until they are mined into a block.
|
||||
func newTxMemPool(cfg *mempoolConfig) *txMemPool {
|
||||
memPool := &txMemPool{
|
||||
func New(cfg *Config) *TxPool {
|
||||
return &TxPool{
|
||||
cfg: *cfg,
|
||||
pool: make(map[chainhash.Hash]*mempoolTxDesc),
|
||||
pool: make(map[chainhash.Hash]*TxDesc),
|
||||
orphans: make(map[chainhash.Hash]*dcrutil.Tx),
|
||||
orphansByPrev: make(map[chainhash.Hash]map[chainhash.Hash]*dcrutil.Tx),
|
||||
outpoints: make(map[wire.OutPoint]*dcrutil.Tx),
|
||||
votes: make(map[chainhash.Hash][]*VoteTx),
|
||||
subsidyCache: cfg.Chain.FetchSubsidyCache(),
|
||||
}
|
||||
|
||||
return memPool
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -39,12 +39,12 @@ const (
|
||||
// (1 + 15*74 + 3) + (15*34 + 3) + 23 = 1650
|
||||
maxStandardSigScriptSize = 1650
|
||||
|
||||
// defaultMinRelayTxFee is the minimum fee in satoshi that is required
|
||||
// for a transaction to be treated as free for relay and mining
|
||||
// purposes. It is also used to help determine if a transaction is
|
||||
// considered dust and as a base for calculating minimum required fees
|
||||
// for larger transactions. This value is in Satoshi/1000 bytes.
|
||||
defaultMinRelayTxFee = dcrutil.Amount(1e6)
|
||||
// DefaultMinRelayTxFee is the minimum fee in atoms that is required for
|
||||
// a transaction to be treated as free for relay and mining purposes.
|
||||
// It is also used to help determine if a transaction is considered dust
|
||||
// and as a base for calculating minimum required fees for larger
|
||||
// transactions. This value is in Atoms/1000 bytes.
|
||||
DefaultMinRelayTxFee = dcrutil.Amount(1e6)
|
||||
|
||||
// maxStandardMultiSigKeys is the maximum number of public keys allowed
|
||||
// in a multi-signature transaction output script for it to be
|
||||
@ -76,11 +76,11 @@ func calcMinRequiredTxRelayFee(serializedSize int64, minRelayTxFee dcrutil.Amoun
|
||||
return minFee
|
||||
}
|
||||
|
||||
// calcPriority returns a transaction priority given a transaction and the sum
|
||||
// CalcPriority returns a transaction priority given a transaction and the sum
|
||||
// of each of its input values multiplied by their age (# of confirmations).
|
||||
// Thus, the final formula for the priority is:
|
||||
// sum(inputValue * inputAge) / adjustedTxSize
|
||||
func calcPriority(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextBlockHeight int64) float64 {
|
||||
func CalcPriority(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextBlockHeight int64) float64 {
|
||||
// In order to encourage spending multiple old unspent transaction
|
||||
// outputs thereby reducing the total set, don't count the constant
|
||||
// overhead for each input as well as enough bytes of the signature
|
||||
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -39,17 +39,17 @@ func TestCalcMinRequiredTxRelayFee(t *testing.T) {
|
||||
{
|
||||
"1000 bytes with default minimum relay fee",
|
||||
1000,
|
||||
defaultMinRelayTxFee,
|
||||
DefaultMinRelayTxFee,
|
||||
1000000,
|
||||
},
|
||||
{
|
||||
"max standard tx size with default minimum relay fee",
|
||||
maxStandardTxSize,
|
||||
defaultMinRelayTxFee,
|
||||
DefaultMinRelayTxFee,
|
||||
100000000,
|
||||
},
|
||||
{
|
||||
"max standard tx size with max satoshi relay fee",
|
||||
"max standard tx size with max relay fee",
|
||||
maxStandardTxSize,
|
||||
dcrutil.MaxAmount,
|
||||
dcrutil.MaxAmount,
|
||||
@ -242,7 +242,7 @@ func TestDust(t *testing.T) {
|
||||
},
|
||||
{
|
||||
// Maximum allowed value is never dust.
|
||||
"max satoshi amount is never dust",
|
||||
"max amount is never dust",
|
||||
wire.TxOut{Value: dcrutil.MaxAmount, Version: 0, PkScript: pkScript},
|
||||
dcrutil.MaxAmount,
|
||||
false,
|
||||
@ -480,7 +480,7 @@ func TestCheckTransactionStandard(t *testing.T) {
|
||||
// Ensure standardness is as expected.
|
||||
tx := dcrutil.NewTx(&test.tx)
|
||||
err := checkTransactionStandard(tx, stake.DetermineTxType(&test.tx),
|
||||
test.height, timeSource, defaultMinRelayTxFee)
|
||||
test.height, timeSource, DefaultMinRelayTxFee)
|
||||
if err == nil && test.isStandard {
|
||||
// Test passes since function returned standard for a
|
||||
// transaction which is intended to be standard.
|
||||
24
mining.go
24
mining.go
@ -18,6 +18,7 @@ import (
|
||||
"github.com/decred/dcrd/blockchain/stake"
|
||||
"github.com/decred/dcrd/chaincfg"
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
"github.com/decred/dcrd/mempool"
|
||||
"github.com/decred/dcrd/mining"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
"github.com/decred/dcrd/wire"
|
||||
@ -323,7 +324,7 @@ func (b byNumberOfVotes) Less(i, j int) bool {
|
||||
// at least a majority number of votes) sorted by number of votes, descending.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func SortParentsByVotes(mp *txMemPool, currentTopBlock chainhash.Hash, blocks []chainhash.Hash, params *chaincfg.Params) []chainhash.Hash {
|
||||
func SortParentsByVotes(mp *mempool.TxPool, currentTopBlock chainhash.Hash, blocks []chainhash.Hash, params *chaincfg.Params) []chainhash.Hash {
|
||||
// Return now when no blocks were provided.
|
||||
lenBlocks := len(blocks)
|
||||
if lenBlocks == 0 {
|
||||
@ -363,7 +364,8 @@ func SortParentsByVotes(mp *txMemPool, currentTopBlock chainhash.Hash, blocks []
|
||||
// the same amount of votes as the current leader after the sort. After this
|
||||
// point, all blocks listed in sortedUsefulBlocks definitely also have the
|
||||
// minimum number of votes required.
|
||||
numTopBlockVotes := uint16(len(mp.votes[currentTopBlock]))
|
||||
curVoteMetadata := mp.VotesForBlocks([]chainhash.Hash{currentTopBlock})
|
||||
numTopBlockVotes := uint16(len(curVoteMetadata))
|
||||
if filtered[0].NumVotes == numTopBlockVotes && filtered[0].Hash !=
|
||||
currentTopBlock {
|
||||
|
||||
@ -1202,7 +1204,7 @@ func NewBlockTemplate(policy *mining.Policy, server *server,
|
||||
|
||||
// TODO: The mempool should be completely separated via the TxSource
|
||||
// interface so this function is fully decoupled.
|
||||
mempool := server.txMemPool
|
||||
mp := server.txMemPool
|
||||
|
||||
var txSource mining.TxSource = server.txMemPool
|
||||
blockManager := server.blockManager
|
||||
@ -1270,7 +1272,7 @@ func NewBlockTemplate(policy *mining.Policy, server *server,
|
||||
// Get the list of blocks that we can actually build on top of. If we're
|
||||
// not currently on the block that has the most votes, switch to that
|
||||
// block.
|
||||
eligibleParents := SortParentsByVotes(mempool, *prevHash, children,
|
||||
eligibleParents := SortParentsByVotes(mp, *prevHash, children,
|
||||
blockManager.server.chainParams)
|
||||
if len(eligibleParents) == 0 {
|
||||
minrLog.Debugf("Too few voters found on any HEAD block, " +
|
||||
@ -1295,13 +1297,13 @@ func NewBlockTemplate(policy *mining.Policy, server *server,
|
||||
|
||||
// Check to make sure we actually have the transactions
|
||||
// (votes) we need in the mempool.
|
||||
voteHashes := mempool.VoteHashesForBlock(newHead)
|
||||
voteHashes := mp.VoteHashesForBlock(newHead)
|
||||
if len(voteHashes) == 0 {
|
||||
return nil, fmt.Errorf("no vote metadata for block %v",
|
||||
newHead)
|
||||
}
|
||||
|
||||
if exist := mempool.CheckIfTxsExist(voteHashes); !exist {
|
||||
if exist := mp.CheckIfTxsExist(voteHashes); !exist {
|
||||
continue
|
||||
} else {
|
||||
prevHash = &newHead
|
||||
@ -1353,7 +1355,7 @@ func NewBlockTemplate(policy *mining.Policy, server *server,
|
||||
|
||||
minrLog.Debugf("Considering %d transactions for inclusion to new block",
|
||||
len(sourceTxns))
|
||||
treeValid := mempool.IsTxTreeValid(prevHash)
|
||||
treeValid := mp.IsTxTreeValid(prevHash)
|
||||
|
||||
mempoolLoop:
|
||||
for _, txDesc := range sourceTxns {
|
||||
@ -1450,7 +1452,7 @@ mempoolLoop:
|
||||
// Calculate the final transaction priority using the input
|
||||
// value age sum as well as the adjusted transaction size. The
|
||||
// formula is: sum(inputValue * inputAge) / adjustedTxSize
|
||||
prioItem.priority = calcPriority(tx.MsgTx(), utxos,
|
||||
prioItem.priority = mempool.CalcPriority(tx.MsgTx(), utxos,
|
||||
nextBlockHeight)
|
||||
|
||||
// Calculate the fee in Atoms/KB.
|
||||
@ -1628,13 +1630,13 @@ mempoolLoop:
|
||||
// the priority size or there are no more high-priority
|
||||
// transactions.
|
||||
if !sortedByFee && (blockPlusTxSize >= policy.BlockPrioritySize ||
|
||||
prioItem.priority <= minHighPriority) {
|
||||
prioItem.priority <= mempool.MinHighPriority) {
|
||||
|
||||
minrLog.Tracef("Switching to sort by fees per "+
|
||||
"kilobyte blockSize %d >= BlockPrioritySize "+
|
||||
"%d || priority %.2f <= minHighPriority %.2f",
|
||||
blockPlusTxSize, policy.BlockPrioritySize,
|
||||
prioItem.priority, minHighPriority)
|
||||
prioItem.priority, mempool.MinHighPriority)
|
||||
|
||||
sortedByFee = true
|
||||
priorityQueue.SetLessFunc(txPQByStakeAndFee)
|
||||
@ -1646,7 +1648,7 @@ mempoolLoop:
|
||||
// final one in the high-priority section, so just fall
|
||||
// though to the code below so it is added now.
|
||||
if blockPlusTxSize > policy.BlockPrioritySize ||
|
||||
prioItem.priority < minHighPriority {
|
||||
prioItem.priority < mempool.MinHighPriority {
|
||||
|
||||
heap.Push(priorityQueue, prioItem)
|
||||
continue
|
||||
|
||||
95
rpcserver.go
95
rpcserver.go
@ -34,7 +34,6 @@ import (
|
||||
"github.com/btcsuite/websocket"
|
||||
|
||||
"github.com/decred/bitset"
|
||||
|
||||
"github.com/decred/dcrd/blockchain"
|
||||
"github.com/decred/dcrd/blockchain/stake"
|
||||
"github.com/decred/dcrd/chaincfg"
|
||||
@ -42,10 +41,10 @@ import (
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
"github.com/decred/dcrd/database"
|
||||
"github.com/decred/dcrd/dcrjson"
|
||||
"github.com/decred/dcrd/mempool"
|
||||
"github.com/decred/dcrd/mining"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
"github.com/decred/dcrd/wire"
|
||||
|
||||
"github.com/decred/dcrutil"
|
||||
)
|
||||
|
||||
@ -3626,85 +3625,47 @@ func handleGetPeerInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{})
|
||||
// handleGetRawMempool implements the getrawmempool command.
|
||||
func handleGetRawMempool(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
c := cmd.(*dcrjson.GetRawMempoolCmd)
|
||||
mp := s.server.txMemPool
|
||||
descs := mp.TxDescs()
|
||||
var txType stake.TxType
|
||||
|
||||
// Choose the type to filter the results by based on the provided param.
|
||||
// A filter type of nil means no filtering.
|
||||
var filterType *stake.TxType
|
||||
if c.TxType != nil {
|
||||
switch *c.TxType {
|
||||
case string(dcrjson.GRMRegular):
|
||||
txType = stake.TxTypeRegular
|
||||
case string(dcrjson.GRMTickets):
|
||||
txType = stake.TxTypeSStx
|
||||
case string(dcrjson.GRMVotes):
|
||||
txType = stake.TxTypeSSGen
|
||||
case string(dcrjson.GRMRevocations):
|
||||
txType = stake.TxTypeSSRtx
|
||||
case string(dcrjson.GRMAll):
|
||||
switch dcrjson.GetRawMempoolTxTypeCmd(*c.TxType) {
|
||||
case dcrjson.GRMRegular:
|
||||
filterType = new(stake.TxType)
|
||||
*filterType = stake.TxTypeRegular
|
||||
case dcrjson.GRMTickets:
|
||||
filterType = new(stake.TxType)
|
||||
*filterType = stake.TxTypeSStx
|
||||
case dcrjson.GRMVotes:
|
||||
filterType = new(stake.TxType)
|
||||
*filterType = stake.TxTypeSSGen
|
||||
case dcrjson.GRMRevocations:
|
||||
filterType = new(stake.TxType)
|
||||
*filterType = stake.TxTypeSSRtx
|
||||
case dcrjson.GRMAll:
|
||||
// Nothing to do
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid transaction type")
|
||||
}
|
||||
}
|
||||
|
||||
// Return verbose results if requested.
|
||||
mp := s.server.txMemPool
|
||||
if c.Verbose != nil && *c.Verbose {
|
||||
result := make(map[string]*dcrjson.GetRawMempoolVerboseResult,
|
||||
len(descs))
|
||||
|
||||
best := s.chain.BestSnapshot()
|
||||
|
||||
mp.RLock()
|
||||
defer mp.RUnlock()
|
||||
for _, desc := range descs {
|
||||
if desc.Type != txType && c.TxType != nil &&
|
||||
*c.TxType != string(dcrjson.GRMAll) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Calculate the current priority based on the inputs to
|
||||
// the transaction. Use zero if one or more of the
|
||||
// input transactions can't be found for some reason.
|
||||
tx := desc.Tx
|
||||
var currentPriority float64
|
||||
utxos, err := mp.fetchInputUtxos(tx)
|
||||
if err == nil {
|
||||
currentPriority = calcPriority(tx.MsgTx(),
|
||||
utxos, best.Height+1)
|
||||
}
|
||||
|
||||
mpd := &dcrjson.GetRawMempoolVerboseResult{
|
||||
Size: int32(tx.MsgTx().SerializeSize()),
|
||||
Fee: dcrutil.Amount(desc.Fee).ToCoin(),
|
||||
Time: desc.Added.Unix(),
|
||||
Height: desc.Height,
|
||||
StartingPriority: desc.StartingPriority,
|
||||
CurrentPriority: currentPriority,
|
||||
Depends: make([]string, 0),
|
||||
}
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
hash := &txIn.PreviousOutPoint.Hash
|
||||
if s.server.txMemPool.haveTransaction(hash) {
|
||||
mpd.Depends = append(mpd.Depends,
|
||||
hash.String())
|
||||
}
|
||||
}
|
||||
|
||||
result[tx.Hash().String()] = mpd
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return mp.RawMempoolVerbose(filterType), nil
|
||||
}
|
||||
|
||||
// The response is simply an array of the transaction hashes if the
|
||||
// verbose flag is not set.
|
||||
descsLen := len(descs)
|
||||
hashStrings := make([]string, 0, descsLen)
|
||||
for i := 0; i < descsLen; i++ {
|
||||
if descs[i].Type != txType && c.TxType != nil &&
|
||||
*c.TxType != string(dcrjson.GRMAll) {
|
||||
descs := mp.TxDescs()
|
||||
hashStrings := make([]string, 0, len(descs))
|
||||
for i := range descs {
|
||||
if filterType != nil && descs[i].Type != *filterType {
|
||||
continue
|
||||
}
|
||||
hashStrings = append(hashStrings, descs[i].Tx.Hash().String())
|
||||
}
|
||||
|
||||
return hashStrings, nil
|
||||
}
|
||||
|
||||
@ -5050,7 +5011,7 @@ func handleSendRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan st
|
||||
// so log it as an actual error. In both cases, a JSON-RPC
|
||||
// error is returned to the client with the deserialization
|
||||
// error code (to match bitcoind behavior).
|
||||
if _, ok := err.(RuleError); ok {
|
||||
if _, ok := err.(mempool.RuleError); ok {
|
||||
rpcsLog.Debugf("Rejected transaction %v: %v", tx.Hash(),
|
||||
err)
|
||||
} else {
|
||||
|
||||
25
server.go
25
server.go
@ -27,6 +27,7 @@ import (
|
||||
"github.com/decred/dcrd/chaincfg"
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
"github.com/decred/dcrd/database"
|
||||
"github.com/decred/dcrd/mempool"
|
||||
"github.com/decred/dcrd/mining"
|
||||
"github.com/decred/dcrd/peer"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
@ -185,7 +186,7 @@ type server struct {
|
||||
sigCache *txscript.SigCache
|
||||
rpcServer *rpcServer
|
||||
blockManager *blockManager
|
||||
txMemPool *txMemPool
|
||||
txMemPool *mempool.TxPool
|
||||
cpuMiner *CPUMiner
|
||||
modifyRebroadcastInv chan interface{}
|
||||
pendingPeers chan *serverPeer
|
||||
@ -2597,7 +2598,16 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||
}
|
||||
s.blockManager = bm
|
||||
|
||||
txC := mempoolConfig{
|
||||
txC := mempool.Config{
|
||||
Policy: mempool.Policy{
|
||||
DisableRelayPriority: cfg.NoRelayPriority,
|
||||
FreeTxRelayLimit: cfg.FreeTxRelayLimit,
|
||||
MaxOrphanTxs: cfg.MaxOrphanTxs,
|
||||
MaxOrphanTxSize: defaultMaxOrphanTxSize,
|
||||
MaxSigOpsPerTx: blockchain.MaxSigOpsPerBlock / 5,
|
||||
MinRelayTxFee: cfg.minRelayTxFee,
|
||||
AllowOldVotes: cfg.AllowOldVotes,
|
||||
},
|
||||
ChainParams: chainParams,
|
||||
// EnableAddrIndex: !cfg.NoAddrIndex, TODO
|
||||
NewestHash: func() (*chainhash.Hash, int64, error) {
|
||||
@ -2613,15 +2623,6 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||
bm.chainState.Unlock()
|
||||
return sDiff, nil
|
||||
},
|
||||
|
||||
Policy: mempoolPolicy{
|
||||
DisableRelayPriority: cfg.NoRelayPriority,
|
||||
FreeTxRelayLimit: cfg.FreeTxRelayLimit,
|
||||
MaxOrphanTxs: cfg.MaxOrphanTxs,
|
||||
MaxOrphanTxSize: defaultMaxOrphanTxSize,
|
||||
MaxSigOpsPerTx: blockchain.MaxSigOpsPerBlock / 5,
|
||||
MinRelayTxFee: cfg.minRelayTxFee,
|
||||
},
|
||||
FetchUtxoView: s.blockManager.chain.FetchUtxoView,
|
||||
Chain: s.blockManager.chain,
|
||||
SigCache: s.sigCache,
|
||||
@ -2629,7 +2630,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||
AddrIndex: s.addrIndex,
|
||||
ExistsAddrIndex: s.existsAddrIndex,
|
||||
}
|
||||
s.txMemPool = newTxMemPool(&txC)
|
||||
s.txMemPool = mempool.New(&txC)
|
||||
|
||||
// Create the mining policy based on the configuration options.
|
||||
// NOTE: The CPU miner relies on the mempool, so the mempool has to be
|
||||
|
||||
Loading…
Reference in New Issue
Block a user