mirror of
https://github.com/btcsuite/btcd.git
synced 2025-01-19 05:33:36 +01:00
mempool: Create and use mempoolPolicy. (#571)
mempoolPolicy contains the values that configure the mempool policy. This decouples the values from the internals of btcd to move closer to a mempool package.
This commit is contained in:
parent
5ff5fc5fa2
commit
123ff368f4
46
config.go
46
config.go
@ -26,27 +26,29 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultConfigFilename = "btcd.conf"
|
defaultConfigFilename = "btcd.conf"
|
||||||
defaultDataDirname = "data"
|
defaultDataDirname = "data"
|
||||||
defaultLogLevel = "info"
|
defaultLogLevel = "info"
|
||||||
defaultLogDirname = "logs"
|
defaultLogDirname = "logs"
|
||||||
defaultLogFilename = "btcd.log"
|
defaultLogFilename = "btcd.log"
|
||||||
defaultMaxPeers = 125
|
defaultMaxPeers = 125
|
||||||
defaultBanDuration = time.Hour * 24
|
defaultBanDuration = time.Hour * 24
|
||||||
defaultBanThreshold = 100
|
defaultBanThreshold = 100
|
||||||
defaultMaxRPCClients = 10
|
defaultMaxRPCClients = 10
|
||||||
defaultMaxRPCWebsockets = 25
|
defaultMaxRPCWebsockets = 25
|
||||||
defaultVerifyEnabled = false
|
defaultVerifyEnabled = false
|
||||||
defaultDbType = "leveldb"
|
defaultDbType = "leveldb"
|
||||||
defaultFreeTxRelayLimit = 15.0
|
defaultFreeTxRelayLimit = 15.0
|
||||||
defaultBlockMinSize = 0
|
defaultBlockMinSize = 0
|
||||||
defaultBlockMaxSize = 750000
|
defaultBlockMaxSize = 750000
|
||||||
blockMaxSizeMin = 1000
|
blockMaxSizeMin = 1000
|
||||||
blockMaxSizeMax = wire.MaxBlockPayload - 1000
|
blockMaxSizeMax = wire.MaxBlockPayload - 1000
|
||||||
defaultBlockPrioritySize = 50000
|
defaultBlockPrioritySize = 50000
|
||||||
defaultGenerate = false
|
defaultGenerate = false
|
||||||
defaultAddrIndex = false
|
defaultAddrIndex = false
|
||||||
defaultSigCacheMaxSize = 50000
|
defaultMaxOrphanTransactions = 1000
|
||||||
|
defaultMaxOrphanTxSize = 5000
|
||||||
|
defaultSigCacheMaxSize = 50000
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -341,8 +343,8 @@ func loadConfig() (*config, []string, error) {
|
|||||||
BlockMinSize: defaultBlockMinSize,
|
BlockMinSize: defaultBlockMinSize,
|
||||||
BlockMaxSize: defaultBlockMaxSize,
|
BlockMaxSize: defaultBlockMaxSize,
|
||||||
BlockPrioritySize: defaultBlockPrioritySize,
|
BlockPrioritySize: defaultBlockPrioritySize,
|
||||||
|
MaxOrphanTxs: defaultMaxOrphanTransactions,
|
||||||
SigCacheMaxSize: defaultSigCacheMaxSize,
|
SigCacheMaxSize: defaultSigCacheMaxSize,
|
||||||
MaxOrphanTxs: maxOrphanTransactions,
|
|
||||||
Generate: defaultGenerate,
|
Generate: defaultGenerate,
|
||||||
AddrIndex: defaultAddrIndex,
|
AddrIndex: defaultAddrIndex,
|
||||||
}
|
}
|
||||||
|
91
mempool.go
91
mempool.go
@ -26,20 +26,6 @@ const (
|
|||||||
// mempoolHeight is the height used for the "block" height field of the
|
// mempoolHeight is the height used for the "block" height field of the
|
||||||
// contextual transaction information provided in a transaction store.
|
// contextual transaction information provided in a transaction store.
|
||||||
mempoolHeight = 0x7fffffff
|
mempoolHeight = 0x7fffffff
|
||||||
|
|
||||||
// maxOrphanTransactions is the maximum number of orphan transactions
|
|
||||||
// that can be queued.
|
|
||||||
maxOrphanTransactions = 1000
|
|
||||||
|
|
||||||
// maxOrphanTxSize is the maximum size allowed for orphan transactions.
|
|
||||||
// This helps prevent memory exhaustion attacks from sending a lot of
|
|
||||||
// of big orphans.
|
|
||||||
maxOrphanTxSize = 5000
|
|
||||||
|
|
||||||
// maxSigOpsPerTx is the maximum number of signature operations
|
|
||||||
// in a single transaction we will relay or mine. It is a fraction
|
|
||||||
// of the max signature operations for a block.
|
|
||||||
maxSigOpsPerTx = blockchain.MaxSigOpsPerBlock / 5
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// mempoolTxDesc is a descriptor containing a transaction in the mempool along
|
// mempoolTxDesc is a descriptor containing a transaction in the mempool along
|
||||||
@ -54,10 +40,6 @@ type mempoolTxDesc struct {
|
|||||||
|
|
||||||
// mempoolConfig is a descriptor containing the memory pool configuration.
|
// mempoolConfig is a descriptor containing the memory pool configuration.
|
||||||
type mempoolConfig struct {
|
type mempoolConfig struct {
|
||||||
// DisableRelayPriority defines whether to relay free or low-fee
|
|
||||||
// transactions that do not have enough priority to be relayed.
|
|
||||||
DisableRelayPriority bool
|
|
||||||
|
|
||||||
// EnableAddrIndex defines whether the address index should be enabled.
|
// EnableAddrIndex defines whether the address index should be enabled.
|
||||||
EnableAddrIndex bool
|
EnableAddrIndex bool
|
||||||
|
|
||||||
@ -65,21 +47,13 @@ type mempoolConfig struct {
|
|||||||
// transacation information.
|
// transacation information.
|
||||||
FetchTransactionStore func(*btcutil.Tx, bool) (blockchain.TxStore, error)
|
FetchTransactionStore func(*btcutil.Tx, bool) (blockchain.TxStore, error)
|
||||||
|
|
||||||
// FreeTxRelayLimit defines the given amount in thousands of bytes
|
|
||||||
// per minute that transactions with no fee are rate limited to.
|
|
||||||
FreeTxRelayLimit float64
|
|
||||||
|
|
||||||
// MaxOrphanTxs defines the maximum number of orphan transactions to
|
|
||||||
// keep in memory.
|
|
||||||
MaxOrphanTxs int
|
|
||||||
|
|
||||||
// MinRelayTxFee defines the minimum transaction fee in BTC/kB to be
|
|
||||||
// considered a non-zero fee.
|
|
||||||
MinRelayTxFee btcutil.Amount
|
|
||||||
|
|
||||||
// NewestSha defines the function to retrieve the newest sha
|
// NewestSha defines the function to retrieve the newest sha
|
||||||
NewestSha func() (*wire.ShaHash, int32, error)
|
NewestSha func() (*wire.ShaHash, int32, error)
|
||||||
|
|
||||||
|
// Policy defines the various mempool configuration options related
|
||||||
|
// to policy.
|
||||||
|
Policy mempoolPolicy
|
||||||
|
|
||||||
// RelayNtfnChan defines the channel to send newly accepted transactions
|
// RelayNtfnChan defines the channel to send newly accepted transactions
|
||||||
// to. If unset or set to nil, notifications will not be sent.
|
// to. If unset or set to nil, notifications will not be sent.
|
||||||
RelayNtfnChan chan *btcutil.Tx
|
RelayNtfnChan chan *btcutil.Tx
|
||||||
@ -91,6 +65,36 @@ type mempoolConfig struct {
|
|||||||
TimeSource blockchain.MedianTimeSource
|
TimeSource blockchain.MedianTimeSource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mempoolPolicy houses the policy (configuration parameters) which is used to
|
||||||
|
// control the mempool.
|
||||||
|
type mempoolPolicy struct {
|
||||||
|
// DisableRelayPriority defines whether to relay free or low-fee
|
||||||
|
// transactions that do not have enough priority to be relayed.
|
||||||
|
DisableRelayPriority bool
|
||||||
|
|
||||||
|
// FreeTxRelayLimit defines the given amount in thousands of bytes
|
||||||
|
// per minute that transactions with no fee are rate limited to.
|
||||||
|
FreeTxRelayLimit float64
|
||||||
|
|
||||||
|
// MaxOrphanTxs is the maximum number of orphan transactions
|
||||||
|
// that can be queued.
|
||||||
|
MaxOrphanTxs int
|
||||||
|
|
||||||
|
// MaxOrphanTxSize is the maximum size allowed for orphan transactions.
|
||||||
|
// This helps prevent memory exhaustion attacks from sending a lot of
|
||||||
|
// of big orphans.
|
||||||
|
MaxOrphanTxSize int
|
||||||
|
|
||||||
|
// MaxSigOpsPerTx is the maximum number of signature operations
|
||||||
|
// in a single transaction we will relay or mine. It is a fraction
|
||||||
|
// of the max signature operations for a block.
|
||||||
|
MaxSigOpsPerTx int
|
||||||
|
|
||||||
|
// MinRelayTxFee defines the minimum transaction fee in BTC/kB to be
|
||||||
|
// considered a non-zero fee.
|
||||||
|
MinRelayTxFee btcutil.Amount
|
||||||
|
}
|
||||||
|
|
||||||
// txMemPool is used as a source of transactions that need to be mined into
|
// 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
|
// blocks and relayed to other peers. It is safe for concurrent access from
|
||||||
// multiple peers.
|
// multiple peers.
|
||||||
@ -156,7 +160,9 @@ func (mp *txMemPool) RemoveOrphan(txHash *wire.ShaHash) {
|
|||||||
//
|
//
|
||||||
// This function MUST be called with the mempool lock held (for writes).
|
// This function MUST be called with the mempool lock held (for writes).
|
||||||
func (mp *txMemPool) limitNumOrphans() error {
|
func (mp *txMemPool) limitNumOrphans() error {
|
||||||
if len(mp.orphans)+1 > mp.cfg.MaxOrphanTxs && mp.cfg.MaxOrphanTxs > 0 {
|
if len(mp.orphans)+1 > mp.cfg.Policy.MaxOrphanTxs &&
|
||||||
|
mp.cfg.Policy.MaxOrphanTxs > 0 {
|
||||||
|
|
||||||
// Generate a cryptographically random hash.
|
// Generate a cryptographically random hash.
|
||||||
randHashBytes := make([]byte, wire.HashSize)
|
randHashBytes := make([]byte, wire.HashSize)
|
||||||
_, err := rand.Read(randHashBytes)
|
_, err := rand.Read(randHashBytes)
|
||||||
@ -222,13 +228,13 @@ func (mp *txMemPool) maybeAddOrphan(tx *btcutil.Tx) error {
|
|||||||
//
|
//
|
||||||
// Note that the number of orphan transactions in the orphan pool is
|
// Note that the number of orphan transactions in the orphan pool is
|
||||||
// also limited, so this equates to a maximum memory used of
|
// also limited, so this equates to a maximum memory used of
|
||||||
// maxOrphanTxSize * mp.cfg.MaxOrphanTxs (which is ~5MB using the default
|
// mp.cfg.Policy.MaxOrphanTxSize * mp.cfg.Policy.MaxOrphanTxs (which is ~5MB
|
||||||
// values at the time this comment was written).
|
// using the default values at the time this comment was written).
|
||||||
serializedLen := tx.MsgTx().SerializeSize()
|
serializedLen := tx.MsgTx().SerializeSize()
|
||||||
if serializedLen > maxOrphanTxSize {
|
if serializedLen > mp.cfg.Policy.MaxOrphanTxSize {
|
||||||
str := fmt.Sprintf("orphan transaction size of %d bytes is "+
|
str := fmt.Sprintf("orphan transaction size of %d bytes is "+
|
||||||
"larger than max allowed size of %d bytes",
|
"larger than max allowed size of %d bytes",
|
||||||
serializedLen, maxOrphanTxSize)
|
serializedLen, mp.cfg.Policy.MaxOrphanTxSize)
|
||||||
return txRuleError(wire.RejectNonstandard, str)
|
return txRuleError(wire.RejectNonstandard, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,7 +660,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
|
|||||||
// forbid their relaying.
|
// forbid their relaying.
|
||||||
if !activeNetParams.RelayNonStdTxs {
|
if !activeNetParams.RelayNonStdTxs {
|
||||||
err := checkTransactionStandard(tx, nextBlockHeight,
|
err := checkTransactionStandard(tx, nextBlockHeight,
|
||||||
mp.cfg.TimeSource, mp.cfg.MinRelayTxFee)
|
mp.cfg.TimeSource, mp.cfg.Policy.MinRelayTxFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Attempt to extract a reject code from the error so
|
// Attempt to extract a reject code from the error so
|
||||||
// it can be retained. When not possible, fall back to
|
// it can be retained. When not possible, fall back to
|
||||||
@ -767,9 +773,9 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
numSigOps += blockchain.CountSigOps(tx)
|
numSigOps += blockchain.CountSigOps(tx)
|
||||||
if numSigOps > maxSigOpsPerTx {
|
if numSigOps > mp.cfg.Policy.MaxSigOpsPerTx {
|
||||||
str := fmt.Sprintf("transaction %v has too many sigops: %d > %d",
|
str := fmt.Sprintf("transaction %v has too many sigops: %d > %d",
|
||||||
txHash, numSigOps, maxSigOpsPerTx)
|
txHash, numSigOps, mp.cfg.Policy.MaxSigOpsPerTx)
|
||||||
return nil, txRuleError(wire.RejectNonstandard, str)
|
return nil, txRuleError(wire.RejectNonstandard, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,7 +791,8 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
|
|||||||
// transaction does not exceeed 1000 less than the reserved space for
|
// transaction does not exceeed 1000 less than the reserved space for
|
||||||
// high-priority transactions, don't require a fee for it.
|
// high-priority transactions, don't require a fee for it.
|
||||||
serializedSize := int64(tx.MsgTx().SerializeSize())
|
serializedSize := int64(tx.MsgTx().SerializeSize())
|
||||||
minFee := calcMinRequiredTxRelayFee(serializedSize, mp.cfg.MinRelayTxFee)
|
minFee := calcMinRequiredTxRelayFee(serializedSize,
|
||||||
|
mp.cfg.Policy.MinRelayTxFee)
|
||||||
if serializedSize >= (defaultBlockPrioritySize-1000) && txFee < minFee {
|
if serializedSize >= (defaultBlockPrioritySize-1000) && txFee < minFee {
|
||||||
str := fmt.Sprintf("transaction %v has %d fees which is under "+
|
str := fmt.Sprintf("transaction %v has %d fees which is under "+
|
||||||
"the required amount of %d", txHash, txFee,
|
"the required amount of %d", txHash, txFee,
|
||||||
@ -797,7 +804,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
|
|||||||
// in the next block. Transactions which are being added back to the
|
// in the next block. Transactions which are being added back to the
|
||||||
// memory pool from blocks that have been disconnected during a reorg
|
// memory pool from blocks that have been disconnected during a reorg
|
||||||
// are exempted.
|
// are exempted.
|
||||||
if isNew && !mp.cfg.DisableRelayPriority && txFee < minFee {
|
if isNew && !mp.cfg.Policy.DisableRelayPriority && txFee < minFee {
|
||||||
currentPriority := calcPriority(tx.MsgTx(), txStore,
|
currentPriority := calcPriority(tx.MsgTx(), txStore,
|
||||||
nextBlockHeight)
|
nextBlockHeight)
|
||||||
if currentPriority <= minHighPriority {
|
if currentPriority <= minHighPriority {
|
||||||
@ -819,7 +826,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
|
|||||||
mp.lastPennyUnix = nowUnix
|
mp.lastPennyUnix = nowUnix
|
||||||
|
|
||||||
// Are we still over the limit?
|
// Are we still over the limit?
|
||||||
if mp.pennyTotal >= mp.cfg.FreeTxRelayLimit*10*1000 {
|
if mp.pennyTotal >= mp.cfg.Policy.FreeTxRelayLimit*10*1000 {
|
||||||
str := fmt.Sprintf("transaction %v has been rejected "+
|
str := fmt.Sprintf("transaction %v has been rejected "+
|
||||||
"by the rate limiter due to low fees", txHash)
|
"by the rate limiter due to low fees", txHash)
|
||||||
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
||||||
@ -829,7 +836,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
|
|||||||
mp.pennyTotal += float64(serializedSize)
|
mp.pennyTotal += float64(serializedSize)
|
||||||
txmpLog.Tracef("rate limit: curTotal %v, nextTotal: %v, "+
|
txmpLog.Tracef("rate limit: curTotal %v, nextTotal: %v, "+
|
||||||
"limit %v", oldTotal, mp.pennyTotal,
|
"limit %v", oldTotal, mp.pennyTotal,
|
||||||
mp.cfg.FreeTxRelayLimit*10*1000)
|
mp.cfg.Policy.FreeTxRelayLimit*10*1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify crypto signatures for each input and reject the transaction if
|
// Verify crypto signatures for each input and reject the transaction if
|
||||||
|
18
server.go
18
server.go
@ -2480,16 +2480,20 @@ func newServer(listenAddrs []string, db database.Db, chainParams *chaincfg.Param
|
|||||||
s.blockManager = bm
|
s.blockManager = bm
|
||||||
|
|
||||||
txC := mempoolConfig{
|
txC := mempoolConfig{
|
||||||
DisableRelayPriority: cfg.NoRelayPriority,
|
|
||||||
EnableAddrIndex: cfg.AddrIndex,
|
EnableAddrIndex: cfg.AddrIndex,
|
||||||
FetchTransactionStore: s.blockManager.blockChain.FetchTransactionStore,
|
FetchTransactionStore: s.blockManager.blockChain.FetchTransactionStore,
|
||||||
FreeTxRelayLimit: cfg.FreeTxRelayLimit,
|
|
||||||
MaxOrphanTxs: cfg.MaxOrphanTxs,
|
|
||||||
MinRelayTxFee: cfg.minRelayTxFee,
|
|
||||||
NewestSha: s.db.NewestSha,
|
NewestSha: s.db.NewestSha,
|
||||||
RelayNtfnChan: s.relayNtfnChan,
|
Policy: mempoolPolicy{
|
||||||
SigCache: s.sigCache,
|
DisableRelayPriority: cfg.NoRelayPriority,
|
||||||
TimeSource: s.timeSource,
|
FreeTxRelayLimit: cfg.FreeTxRelayLimit,
|
||||||
|
MaxOrphanTxs: cfg.MaxOrphanTxs,
|
||||||
|
MaxOrphanTxSize: defaultMaxOrphanTxSize,
|
||||||
|
MaxSigOpsPerTx: blockchain.MaxSigOpsPerBlock / 5,
|
||||||
|
MinRelayTxFee: cfg.minRelayTxFee,
|
||||||
|
},
|
||||||
|
RelayNtfnChan: s.relayNtfnChan,
|
||||||
|
SigCache: s.sigCache,
|
||||||
|
TimeSource: s.timeSource,
|
||||||
}
|
}
|
||||||
s.txMemPool = newTxMemPool(&txC)
|
s.txMemPool = newTxMemPool(&txC)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user