From 5f8dbab47a1c8bed5b258775def83a03c94eb5b4 Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 5 May 2015 10:53:15 -0400 Subject: [PATCH] Add new option -maxorphantx The option -maxorphantx allows the user to specify the number of orphan transactions to keep in memory. Also, lower the default max orphan count from 10000 to 1000. --- blockmanager.go | 6 ++++-- config.go | 12 ++++++++++++ doc.go | 3 ++- mempool.go | 12 +++++------- sample-btcd.conf | 6 ++++++ 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index d3bd6087..911fcd1b 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -463,7 +463,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // NOTE: BitcoinJ, and possibly other wallets, don't follow the spec of // sending an inventory message and allowing the remote peer to decide // whether or not they want to request the transaction via a getdata - // message. Unfortuantely the reference implementation permits + // message. Unfortunately, the reference implementation permits // unrequested data, so it has allowed wallets that don't follow the // spec to proliferate. While this is not ideal, there is no check here // to disconnect peers for sending unsolicited transactions to provide @@ -471,7 +471,9 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // Process the transaction to include validation, insertion in the // memory pool, orphan handling, etc. - err := tmsg.peer.server.txMemPool.ProcessTransaction(tmsg.tx, true, true) + allowOrphans := cfg.MaxOrphanTxs > 0 + err := tmsg.peer.server.txMemPool.ProcessTransaction(tmsg.tx, + allowOrphans, true) // Remove transaction from request maps. Either the mempool/chain // already knows about it and as such we shouldn't have any more diff --git a/config.go b/config.go index 0b5d9248..eb603dc8 100644 --- a/config.go +++ b/config.go @@ -106,6 +106,7 @@ type config struct { Upnp bool `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"` FreeTxRelayLimit float64 `long:"limitfreerelay" description:"Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute"` NoRelayPriority bool `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"` + MaxOrphanTxs int `long:"maxorphantx" description:"Max number of orphan transactions to keep in memory"` Generate bool `long:"generate" description:"Generate (mine) bitcoins using the CPU"` MiningAddrs []string `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"` BlockMinSize uint32 `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"` @@ -319,6 +320,7 @@ func loadConfig() (*config, []string, error) { BlockMinSize: defaultBlockMinSize, BlockMaxSize: defaultBlockMaxSize, BlockPrioritySize: defaultBlockPrioritySize, + MaxOrphanTxs: maxOrphanTransactions, Generate: defaultGenerate, AddrIndex: defaultAddrIndex, } @@ -600,6 +602,16 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } + // Limit the max orphan count to a sane vlue. + if cfg.MaxOrphanTxs < 0 { + str := "%s: The maxorphantx option may not be less than 0 " + + "-- parsed [%d]" + err := fmt.Errorf(str, funcName, cfg.MaxOrphanTxs) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + // Limit the block priority and minimum block sizes to max block size. cfg.BlockPrioritySize = minUint32(cfg.BlockPrioritySize, cfg.BlockMaxSize) cfg.BlockMinSize = minUint32(cfg.BlockMinSize, cfg.BlockMaxSize) diff --git a/doc.go b/doc.go index f8705c36..fee4199c 100644 --- a/doc.go +++ b/doc.go @@ -81,7 +81,8 @@ Application Options: --limitfreerelay= Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute (15) - + --maxorphantx= Max number of orphan transactions to keep in memory + (1000) --generate= Generate (mine) bitcoins using the CPU --miningaddr= Add the specified payment address to the list of addresses to use for generated blocks -- At least diff --git a/mempool.go b/mempool.go index 1b0a51b6..ebcaf5f7 100644 --- a/mempool.go +++ b/mempool.go @@ -26,10 +26,8 @@ const ( mempoolHeight = 0x7fffffff // maxOrphanTransactions is the maximum number of orphan transactions - // that can be queued. At the time this comment was written, this - // equates to 10,000 transactions, but will increase if the max allowed - // block payload increases. - maxOrphanTransactions = wire.MaxBlockPayload / 100 + // 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 @@ -438,7 +436,7 @@ func (mp *txMemPool) RemoveOrphan(txHash *wire.ShaHash) { // // This function MUST be called with the mempool lock held (for writes). func (mp *txMemPool) limitNumOrphans() error { - if len(mp.orphans)+1 > maxOrphanTransactions { + if len(mp.orphans)+1 > cfg.MaxOrphanTxs && cfg.MaxOrphanTxs > 0 { // Generate a cryptographically random hash. randHashBytes := make([]byte, wire.HashSize) _, err := rand.Read(randHashBytes) @@ -503,8 +501,8 @@ func (mp *txMemPool) maybeAddOrphan(tx *btcutil.Tx) error { // // Note that the number of orphan transactions in the orphan pool is // also limited, so this equates to a maximum memory used of - // maxOrphanTxSize * maxOrphanTransactions (which is 500MB as of the - // time this comment was written). + // maxOrphanTxSize * cfg.MaxOrphanTxs (which is ~5MB using the default + // values at the time this comment was written). serializedLen := tx.MsgTx().SerializeSize() if serializedLen > maxOrphanTxSize { str := fmt.Sprintf("orphan transaction size of %d bytes is "+ diff --git a/sample-btcd.conf b/sample-btcd.conf index 14600a2b..c9ea886b 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -203,6 +203,12 @@ ; the default). ; notls=1 +; ------------------------------------------------------------------------------ +; Mempool Settings - The following options +; ------------------------------------------------------------------------------ +; Limit orphan transaction pool to 1000 transactions. +; maxorphantx=1000 + ; ------------------------------------------------------------------------------ ; Optional Transaction Indexes ; ------------------------------------------------------------------------------