2016-02-12 13:44:56 -05:00
|
|
|
// Copyright (c) 2013-2016 The btcsuite developers
|
2013-09-20 12:55:27 -05:00
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
package mempool
|
2013-09-20 12:55:27 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"container/list"
|
|
|
|
"fmt"
|
2014-07-02 15:50:08 +02:00
|
|
|
"math"
|
|
|
|
"sync"
|
2016-02-12 13:44:56 -05:00
|
|
|
"sync/atomic"
|
2014-07-02 15:50:08 +02:00
|
|
|
"time"
|
|
|
|
|
2015-01-30 16:25:42 -06:00
|
|
|
"github.com/btcsuite/btcd/blockchain"
|
2016-02-18 22:51:18 -06:00
|
|
|
"github.com/btcsuite/btcd/blockchain/indexers"
|
2016-08-19 11:08:37 -05:00
|
|
|
"github.com/btcsuite/btcd/btcjson"
|
2022-04-06 14:33:13 +02:00
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
2016-08-19 11:08:37 -05:00
|
|
|
"github.com/btcsuite/btcd/chaincfg"
|
2016-08-08 14:04:33 -05:00
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
2015-11-25 16:27:14 -06:00
|
|
|
"github.com/btcsuite/btcd/mining"
|
2015-01-30 12:14:33 -06:00
|
|
|
"github.com/btcsuite/btcd/txscript"
|
2015-02-05 15:16:39 -06:00
|
|
|
"github.com/btcsuite/btcd/wire"
|
2023-11-04 07:40:47 +08:00
|
|
|
"github.com/davecgh/go-spew/spew"
|
2013-09-20 12:55:27 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2016-08-19 11:08:37 -05:00
|
|
|
// 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 = 50000
|
|
|
|
|
2016-08-23 23:27:41 -05:00
|
|
|
// orphanTTL is the maximum amount of time an orphan is allowed to
|
|
|
|
// stay in the orphan pool before it expires and is evicted during the
|
|
|
|
// next scan.
|
|
|
|
orphanTTL = time.Minute * 15
|
|
|
|
|
|
|
|
// orphanExpireScanInterval is the minimum amount of time in between
|
|
|
|
// scans of the orphan pool to evict expired transactions.
|
|
|
|
orphanExpireScanInterval = time.Minute * 5
|
2019-05-02 19:44:51 -07:00
|
|
|
|
|
|
|
// MaxRBFSequence is the maximum sequence number an input can use to
|
|
|
|
// signal that the transaction spending it can be replaced using the
|
|
|
|
// Replace-By-Fee (RBF) policy.
|
|
|
|
MaxRBFSequence = 0xfffffffd
|
|
|
|
|
|
|
|
// MaxReplacementEvictions is the maximum number of transactions that
|
|
|
|
// can be evicted from the mempool when accepting a transaction
|
|
|
|
// replacement.
|
|
|
|
MaxReplacementEvictions = 100
|
2013-09-20 12:55:27 -05:00
|
|
|
)
|
|
|
|
|
2016-10-28 12:48:54 -05:00
|
|
|
// Tag represents an identifier to use for tagging orphan transactions. The
|
|
|
|
// caller may choose any scheme it desires, however it is common to use peer IDs
|
|
|
|
// so that orphans can be identified by which peer first relayed them.
|
|
|
|
type Tag uint64
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
// Config is a descriptor containing the memory pool configuration.
|
|
|
|
type Config struct {
|
2016-04-11 17:37:52 -04:00
|
|
|
// Policy defines the various mempool configuration options related
|
|
|
|
// to policy.
|
2016-08-19 11:08:37 -05:00
|
|
|
Policy Policy
|
|
|
|
|
|
|
|
// ChainParams identifies which chain parameters the txpool is
|
|
|
|
// associated with.
|
|
|
|
ChainParams *chaincfg.Params
|
2016-04-11 17:37:52 -04:00
|
|
|
|
2015-08-25 23:03:18 -05:00
|
|
|
// FetchUtxoView defines the function to use to fetch unspent
|
|
|
|
// transaction output information.
|
|
|
|
FetchUtxoView func(*btcutil.Tx) (*blockchain.UtxoViewpoint, error)
|
|
|
|
|
2016-08-21 00:04:43 -05:00
|
|
|
// BestHeight defines the function to use to access the block height of
|
2015-08-25 23:03:18 -05:00
|
|
|
// the current best chain.
|
2016-08-21 00:04:43 -05:00
|
|
|
BestHeight func() int32
|
2015-08-25 23:03:18 -05:00
|
|
|
|
2016-08-23 11:48:03 -07:00
|
|
|
// MedianTimePast defines the function to use in order to access the
|
|
|
|
// median time past calculated from the point-of-view of the current
|
|
|
|
// chain tip within the best chain.
|
|
|
|
MedianTimePast func() time.Time
|
|
|
|
|
2016-08-26 17:24:39 -07:00
|
|
|
// CalcSequenceLock defines the function to use in order to generate
|
|
|
|
// the current sequence lock for the given transaction using the passed
|
|
|
|
// utxo view.
|
|
|
|
CalcSequenceLock func(*btcutil.Tx, *blockchain.UtxoViewpoint) (*blockchain.SequenceLock, error)
|
|
|
|
|
2016-10-18 19:21:55 -07:00
|
|
|
// IsDeploymentActive returns true if the target deploymentID is
|
|
|
|
// active, and false otherwise. The mempool uses this function to gauge
|
|
|
|
// if transactions using new to be soft-forked rules should be allowed
|
|
|
|
// into the mempool or not.
|
|
|
|
IsDeploymentActive func(deploymentID uint32) (bool, error)
|
|
|
|
|
2015-11-20 22:12:17 -05:00
|
|
|
// SigCache defines a signature cache to use.
|
|
|
|
SigCache *txscript.SigCache
|
|
|
|
|
2016-10-18 19:21:55 -07:00
|
|
|
// HashCache defines the transaction hash mid-state cache to use.
|
|
|
|
HashCache *txscript.HashCache
|
|
|
|
|
2016-02-18 22:51:18 -06:00
|
|
|
// AddrIndex defines the optional address index instance to use for
|
|
|
|
// indexing the unconfirmed transactions in the memory pool.
|
|
|
|
// This can be nil if the address index is not enabled.
|
|
|
|
AddrIndex *indexers.AddrIndex
|
2017-11-13 22:37:35 -06:00
|
|
|
|
|
|
|
// FeeEstimatator provides a feeEstimator. If it is not nil, the mempool
|
|
|
|
// records all new transactions it observes into the feeEstimator.
|
|
|
|
FeeEstimator *FeeEstimator
|
2015-11-20 22:12:17 -05:00
|
|
|
}
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
// Policy houses the policy (configuration parameters) which is used to
|
2016-04-11 17:37:52 -04:00
|
|
|
// control the mempool.
|
2016-08-19 11:08:37 -05:00
|
|
|
type Policy struct {
|
2016-08-26 18:49:59 -07:00
|
|
|
// MaxTxVersion is the transaction version that the mempool should
|
|
|
|
// accept. All transactions above this version are rejected as
|
|
|
|
// non-standard.
|
|
|
|
MaxTxVersion int32
|
|
|
|
|
2016-04-11 17:37:52 -04:00
|
|
|
// DisableRelayPriority defines whether to relay free or low-fee
|
|
|
|
// transactions that do not have enough priority to be relayed.
|
|
|
|
DisableRelayPriority bool
|
|
|
|
|
2016-10-23 16:31:31 -05:00
|
|
|
// AcceptNonStd defines whether to accept non-standard transactions. If
|
|
|
|
// true, non-standard transactions will be accepted into the mempool.
|
|
|
|
// Otherwise, all non-standard transactions will be rejected.
|
|
|
|
AcceptNonStd bool
|
2016-08-22 17:59:28 -07:00
|
|
|
|
2016-04-11 17:37:52 -04:00
|
|
|
// 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
|
|
|
|
|
2016-10-18 19:21:55 -07:00
|
|
|
// MaxSigOpCostPerTx is the cumulative maximum cost of all the signature
|
|
|
|
// operations in a single transaction we will relay or mine. It is a
|
|
|
|
// fraction of the max signature operations for a block.
|
|
|
|
MaxSigOpCostPerTx int
|
2016-04-11 17:37:52 -04:00
|
|
|
|
|
|
|
// MinRelayTxFee defines the minimum transaction fee in BTC/kB to be
|
|
|
|
// considered a non-zero fee.
|
|
|
|
MinRelayTxFee btcutil.Amount
|
2019-05-02 19:44:51 -07:00
|
|
|
|
|
|
|
// RejectReplacement, if true, rejects accepting replacement
|
|
|
|
// transactions using the Replace-By-Fee (RBF) signaling policy into
|
|
|
|
// the mempool.
|
|
|
|
RejectReplacement bool
|
2016-04-11 17:37:52 -04:00
|
|
|
}
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2016-08-23 23:27:41 -05:00
|
|
|
// orphanTx is normal transaction that references an ancestor transaction
|
|
|
|
// that is not yet available. It also contains additional information related
|
|
|
|
// to it such as an expiration time to help prevent caching the orphan forever.
|
|
|
|
type orphanTx struct {
|
|
|
|
tx *btcutil.Tx
|
2016-10-28 12:48:54 -05:00
|
|
|
tag Tag
|
2016-08-23 23:27:41 -05:00
|
|
|
expiration time.Time
|
|
|
|
}
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
// 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 {
|
2016-02-12 13:44:56 -05:00
|
|
|
// The following variables must only be used atomically.
|
|
|
|
lastUpdated int64 // last time pool was updated
|
|
|
|
|
2016-08-23 14:59:48 -04:00
|
|
|
mtx sync.RWMutex
|
2016-08-19 11:08:37 -05:00
|
|
|
cfg Config
|
|
|
|
pool map[chainhash.Hash]*TxDesc
|
2016-08-23 23:27:41 -05:00
|
|
|
orphans map[chainhash.Hash]*orphanTx
|
2016-08-23 12:26:26 -05:00
|
|
|
orphansByPrev map[wire.OutPoint]map[chainhash.Hash]*btcutil.Tx
|
2015-02-05 15:16:39 -06:00
|
|
|
outpoints map[wire.OutPoint]*btcutil.Tx
|
2016-02-12 13:44:56 -05:00
|
|
|
pennyTotal float64 // exponentially decaying total for penny spends.
|
|
|
|
lastPennyUnix int64 // unix time of last ``penny spend''
|
2016-08-23 23:27:41 -05:00
|
|
|
|
|
|
|
// nextExpireScan is the time after which the orphan pool will be
|
|
|
|
// scanned in order to evict orphans. This is NOT a hard deadline as
|
|
|
|
// the scan will only run when an orphan is added to the pool as opposed
|
|
|
|
// to on an unconditional timer.
|
|
|
|
nextExpireScan time.Time
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
// Ensure the TxPool type implements the mining.TxSource interface.
|
|
|
|
var _ mining.TxSource = (*TxPool)(nil)
|
2015-11-25 13:30:44 -06:00
|
|
|
|
2023-11-29 16:47:18 +08:00
|
|
|
// Ensure the TxPool type implements the TxMemPool interface.
|
|
|
|
var _ TxMempool = (*TxPool)(nil)
|
|
|
|
|
2014-09-18 10:23:36 -04:00
|
|
|
// removeOrphan is the internal function which implements the public
|
|
|
|
// RemoveOrphan. See the comment for RemoveOrphan for more details.
|
2015-03-10 12:40:44 -04:00
|
|
|
//
|
2013-10-21 18:20:31 -05:00
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2016-08-23 12:26:26 -05:00
|
|
|
func (mp *TxPool) removeOrphan(tx *btcutil.Tx, removeRedeemers bool) {
|
2013-09-20 12:55:27 -05:00
|
|
|
// Nothing to do if passed tx is not an orphan.
|
2016-08-23 12:26:26 -05:00
|
|
|
txHash := tx.Hash()
|
2016-08-23 23:27:41 -05:00
|
|
|
otx, exists := mp.orphans[*txHash]
|
2013-09-20 12:55:27 -05:00
|
|
|
if !exists {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the reference from the previous orphan index.
|
2016-08-23 23:27:41 -05:00
|
|
|
for _, txIn := range otx.tx.MsgTx().TxIn {
|
2016-08-23 12:26:26 -05:00
|
|
|
orphans, exists := mp.orphansByPrev[txIn.PreviousOutPoint]
|
|
|
|
if exists {
|
|
|
|
delete(orphans, *txHash)
|
2013-09-20 12:55:27 -05:00
|
|
|
|
|
|
|
// Remove the map entry altogether if there are no
|
|
|
|
// longer any orphans which depend on it.
|
2015-11-12 17:25:03 -05:00
|
|
|
if len(orphans) == 0 {
|
2016-08-23 12:26:26 -05:00
|
|
|
delete(mp.orphansByPrev, txIn.PreviousOutPoint)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove any orphans that redeem outputs from this one if requested.
|
|
|
|
if removeRedeemers {
|
|
|
|
prevOut := wire.OutPoint{Hash: *txHash}
|
|
|
|
for txOutIdx := range tx.MsgTx().TxOut {
|
|
|
|
prevOut.Index = uint32(txOutIdx)
|
|
|
|
for _, orphan := range mp.orphansByPrev[prevOut] {
|
|
|
|
mp.removeOrphan(orphan, true)
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the transaction from the orphan pool.
|
|
|
|
delete(mp.orphans, *txHash)
|
|
|
|
}
|
|
|
|
|
2014-09-18 10:23:36 -04:00
|
|
|
// RemoveOrphan removes the passed orphan transaction from the orphan pool and
|
|
|
|
// previous orphan index.
|
2015-03-10 12:40:44 -04:00
|
|
|
//
|
2014-09-18 10:23:36 -04:00
|
|
|
// This function is safe for concurrent access.
|
2016-08-23 12:26:26 -05:00
|
|
|
func (mp *TxPool) RemoveOrphan(tx *btcutil.Tx) {
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Lock()
|
2016-08-23 12:26:26 -05:00
|
|
|
mp.removeOrphan(tx, false)
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Unlock()
|
2014-09-18 10:23:36 -04:00
|
|
|
}
|
|
|
|
|
2016-10-28 12:49:11 -05:00
|
|
|
// RemoveOrphansByTag removes all orphan transactions tagged with the provided
|
|
|
|
// identifier.
|
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
|
|
|
func (mp *TxPool) RemoveOrphansByTag(tag Tag) uint64 {
|
|
|
|
var numEvicted uint64
|
|
|
|
mp.mtx.Lock()
|
|
|
|
for _, otx := range mp.orphans {
|
|
|
|
if otx.tag == tag {
|
|
|
|
mp.removeOrphan(otx.tx, true)
|
|
|
|
numEvicted++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mp.mtx.Unlock()
|
|
|
|
return numEvicted
|
|
|
|
}
|
|
|
|
|
2013-09-20 12:55:27 -05:00
|
|
|
// limitNumOrphans limits the number of orphan transactions by evicting a random
|
|
|
|
// orphan if adding a new one would cause it to overflow the max allowed.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) limitNumOrphans() error {
|
2016-08-23 23:27:41 -05:00
|
|
|
// Scan through the orphan pool and remove any expired orphans when it's
|
|
|
|
// time. This is done for efficiency so the scan only happens
|
|
|
|
// periodically instead of on every orphan added to the pool.
|
|
|
|
if now := time.Now(); now.After(mp.nextExpireScan) {
|
|
|
|
origNumOrphans := len(mp.orphans)
|
|
|
|
for _, otx := range mp.orphans {
|
|
|
|
if now.After(otx.expiration) {
|
|
|
|
// Remove redeemers too because the missing
|
|
|
|
// parents are very unlikely to ever materialize
|
|
|
|
// since the orphan has already been around more
|
|
|
|
// than long enough for them to be delivered.
|
|
|
|
mp.removeOrphan(otx.tx, true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set next expiration scan to occur after the scan interval.
|
|
|
|
mp.nextExpireScan = now.Add(orphanExpireScanInterval)
|
|
|
|
|
|
|
|
numOrphans := len(mp.orphans)
|
|
|
|
if numExpired := origNumOrphans - numOrphans; numExpired > 0 {
|
|
|
|
log.Debugf("Expired %d %s (remaining: %d)", numExpired,
|
|
|
|
pickNoun(numExpired, "orphan", "orphans"),
|
|
|
|
numOrphans)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Nothing to do if adding another orphan will not cause the pool to
|
|
|
|
// exceed the limit.
|
2016-10-23 21:14:09 -05:00
|
|
|
if len(mp.orphans)+1 <= mp.cfg.Policy.MaxOrphanTxs {
|
|
|
|
return nil
|
|
|
|
}
|
2013-09-20 12:55:27 -05:00
|
|
|
|
2016-10-23 21:14:09 -05:00
|
|
|
// Remove a random entry from the map. For most compilers, Go's
|
|
|
|
// range statement iterates starting at a random item although
|
|
|
|
// that is not 100% guaranteed by the spec. The iteration order
|
|
|
|
// is not important here because an adversary would have to be
|
|
|
|
// able to pull off preimage attacks on the hashing function in
|
|
|
|
// order to target eviction of specific entries anyways.
|
2016-08-23 23:27:41 -05:00
|
|
|
for _, otx := range mp.orphans {
|
|
|
|
// Don't remove redeemers in the case of a random eviction since
|
|
|
|
// it is quite possible it might be needed again shortly.
|
|
|
|
mp.removeOrphan(otx.tx, false)
|
2016-10-23 21:14:09 -05:00
|
|
|
break
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// addOrphan adds an orphan transaction to the orphan pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2016-10-28 12:48:54 -05:00
|
|
|
func (mp *TxPool) addOrphan(tx *btcutil.Tx, tag Tag) {
|
2016-10-23 21:14:09 -05:00
|
|
|
// Nothing to do if no orphans are allowed.
|
|
|
|
if mp.cfg.Policy.MaxOrphanTxs <= 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-08-23 23:27:41 -05:00
|
|
|
// Limit the number orphan transactions to prevent memory exhaustion.
|
|
|
|
// This will periodically remove any expired orphans and evict a random
|
|
|
|
// orphan if space is still needed.
|
2013-09-20 12:55:27 -05:00
|
|
|
mp.limitNumOrphans()
|
|
|
|
|
2016-08-23 23:27:41 -05:00
|
|
|
mp.orphans[*tx.Hash()] = &orphanTx{
|
|
|
|
tx: tx,
|
2016-10-28 12:48:54 -05:00
|
|
|
tag: tag,
|
2016-08-23 23:27:41 -05:00
|
|
|
expiration: time.Now().Add(orphanTTL),
|
|
|
|
}
|
2013-10-28 15:44:38 -05:00
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
2016-08-23 12:26:26 -05:00
|
|
|
if _, exists := mp.orphansByPrev[txIn.PreviousOutPoint]; !exists {
|
|
|
|
mp.orphansByPrev[txIn.PreviousOutPoint] =
|
2016-08-08 14:04:33 -05:00
|
|
|
make(map[chainhash.Hash]*btcutil.Tx)
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
2016-08-23 12:26:26 -05:00
|
|
|
mp.orphansByPrev[txIn.PreviousOutPoint][*tx.Hash()] = tx
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
log.Debugf("Stored orphan transaction %v (total: %d)", tx.Hash(),
|
2013-09-20 12:55:27 -05:00
|
|
|
len(mp.orphans))
|
|
|
|
}
|
|
|
|
|
|
|
|
// maybeAddOrphan potentially adds an orphan to the orphan pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2016-10-28 12:48:54 -05:00
|
|
|
func (mp *TxPool) maybeAddOrphan(tx *btcutil.Tx, tag Tag) error {
|
2013-09-20 12:55:27 -05:00
|
|
|
// 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,
|
|
|
|
// it will ultimtely be rebroadcast after the parent transactions
|
|
|
|
// have been mined or otherwise received.
|
|
|
|
//
|
|
|
|
// Note that the number of orphan transactions in the orphan pool is
|
|
|
|
// also limited, so this equates to a maximum memory used of
|
2016-04-11 17:37:52 -04:00
|
|
|
// mp.cfg.Policy.MaxOrphanTxSize * mp.cfg.Policy.MaxOrphanTxs (which is ~5MB
|
|
|
|
// using the default values at the time this comment was written).
|
2013-10-31 00:28:37 -05:00
|
|
|
serializedLen := tx.MsgTx().SerializeSize()
|
2016-04-11 17:37:52 -04:00
|
|
|
if serializedLen > mp.cfg.Policy.MaxOrphanTxSize {
|
2013-10-04 13:30:50 -05:00
|
|
|
str := fmt.Sprintf("orphan transaction size of %d bytes is "+
|
2013-09-20 12:55:27 -05:00
|
|
|
"larger than max allowed size of %d bytes",
|
2016-04-11 17:37:52 -04:00
|
|
|
serializedLen, mp.cfg.Policy.MaxOrphanTxSize)
|
2015-02-05 15:16:39 -06:00
|
|
|
return txRuleError(wire.RejectNonstandard, str)
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add the orphan if the none of the above disqualified it.
|
2016-10-28 12:48:54 -05:00
|
|
|
mp.addOrphan(tx, tag)
|
2013-09-20 12:55:27 -05:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-08-23 12:26:26 -05:00
|
|
|
// removeOrphanDoubleSpends removes all orphans which spend outputs spent by the
|
|
|
|
// passed transaction from the orphan pool. Removing those orphans then leads
|
|
|
|
// to removing all orphans which rely on them, recursively. This is necessary
|
|
|
|
// when a transaction is added to the main pool because it may spend outputs
|
|
|
|
// that orphans also spend.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
|
|
|
func (mp *TxPool) removeOrphanDoubleSpends(tx *btcutil.Tx) {
|
|
|
|
msgTx := tx.MsgTx()
|
|
|
|
for _, txIn := range msgTx.TxIn {
|
|
|
|
for _, orphan := range mp.orphansByPrev[txIn.PreviousOutPoint] {
|
|
|
|
mp.removeOrphan(orphan, true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-21 18:20:31 -05:00
|
|
|
// isTransactionInPool returns whether or not the passed transaction already
|
|
|
|
// exists in the main pool.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) isTransactionInPool(hash *chainhash.Hash) bool {
|
2013-10-21 18:20:31 -05:00
|
|
|
if _, exists := mp.pool[*hash]; exists {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2013-10-08 10:47:00 -05:00
|
|
|
// IsTransactionInPool returns whether or not the passed transaction already
|
2013-10-11 14:12:40 -05:00
|
|
|
// exists in the main pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) IsTransactionInPool(hash *chainhash.Hash) bool {
|
2013-10-21 18:20:31 -05:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2016-04-12 21:19:13 -04:00
|
|
|
inPool := mp.isTransactionInPool(hash)
|
|
|
|
mp.mtx.RUnlock()
|
2013-09-20 12:55:27 -05:00
|
|
|
|
2016-04-12 21:19:13 -04:00
|
|
|
return inPool
|
2013-10-21 18:20:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// isOrphanInPool returns whether or not the passed transaction already exists
|
|
|
|
// in the orphan pool.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) isOrphanInPool(hash *chainhash.Hash) bool {
|
2013-10-21 18:20:31 -05:00
|
|
|
if _, exists := mp.orphans[*hash]; exists {
|
2013-09-20 12:55:27 -05:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2013-10-11 14:12:40 -05:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsOrphanInPool returns whether or not the passed transaction already exists
|
|
|
|
// in the orphan pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) IsOrphanInPool(hash *chainhash.Hash) bool {
|
2013-10-21 18:20:31 -05:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2016-04-12 21:19:13 -04:00
|
|
|
inPool := mp.isOrphanInPool(hash)
|
|
|
|
mp.mtx.RUnlock()
|
2013-10-11 14:12:40 -05:00
|
|
|
|
2016-04-12 21:19:13 -04:00
|
|
|
return inPool
|
2013-10-21 18:20:31 -05:00
|
|
|
}
|
2013-09-20 12:55:27 -05:00
|
|
|
|
2013-10-21 18:20:31 -05:00
|
|
|
// haveTransaction returns whether or not the passed transaction already exists
|
|
|
|
// in the main pool or in the orphan pool.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) haveTransaction(hash *chainhash.Hash) bool {
|
2013-10-21 18:20:31 -05:00
|
|
|
return mp.isTransactionInPool(hash) || mp.isOrphanInPool(hash)
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2013-10-11 14:12:40 -05:00
|
|
|
// HaveTransaction returns whether or not the passed transaction already exists
|
|
|
|
// in the main pool or in the orphan pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) HaveTransaction(hash *chainhash.Hash) bool {
|
2013-10-21 18:20:31 -05:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2016-04-12 21:19:13 -04:00
|
|
|
haveTx := mp.haveTransaction(hash)
|
|
|
|
mp.mtx.RUnlock()
|
2013-10-21 18:20:31 -05:00
|
|
|
|
2016-04-12 21:19:13 -04:00
|
|
|
return haveTx
|
2013-10-11 14:12:40 -05:00
|
|
|
}
|
|
|
|
|
2013-11-15 16:12:23 -06:00
|
|
|
// removeTransaction is the internal function which implements the public
|
|
|
|
// RemoveTransaction. See the comment for RemoveTransaction for more details.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) removeTransaction(tx *btcutil.Tx, removeRedeemers bool) {
|
2016-08-08 14:04:33 -05:00
|
|
|
txHash := tx.Hash()
|
2015-11-05 17:27:42 +01:00
|
|
|
if removeRedeemers {
|
|
|
|
// Remove any transactions which rely on this one.
|
|
|
|
for i := uint32(0); i < uint32(len(tx.MsgTx().TxOut)); i++ {
|
2016-08-23 12:26:26 -05:00
|
|
|
prevOut := wire.OutPoint{Hash: *txHash, Index: i}
|
|
|
|
if txRedeemer, exists := mp.outpoints[prevOut]; exists {
|
2015-11-05 17:27:42 +01:00
|
|
|
mp.removeTransaction(txRedeemer, true)
|
|
|
|
}
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-18 22:51:18 -06:00
|
|
|
// Remove the transaction if needed.
|
2013-12-11 17:32:16 +00:00
|
|
|
if txDesc, exists := mp.pool[*txHash]; exists {
|
2016-02-18 22:51:18 -06:00
|
|
|
// Remove unconfirmed address index entries associated with the
|
|
|
|
// transaction if enabled.
|
|
|
|
if mp.cfg.AddrIndex != nil {
|
|
|
|
mp.cfg.AddrIndex.RemoveUnconfirmedTx(txHash)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark the referenced outpoints as unspent by the pool.
|
2013-12-11 17:32:16 +00:00
|
|
|
for _, txIn := range txDesc.Tx.MsgTx().TxIn {
|
2014-10-01 16:34:30 +01:00
|
|
|
delete(mp.outpoints, txIn.PreviousOutPoint)
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
2013-10-28 15:44:38 -05:00
|
|
|
delete(mp.pool, *txHash)
|
2016-02-12 13:44:56 -05:00
|
|
|
atomic.StoreInt64(&mp.lastUpdated, time.Now().Unix())
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
2015-01-03 19:42:01 -06:00
|
|
|
}
|
|
|
|
|
2015-08-25 23:03:18 -05:00
|
|
|
// RemoveTransaction removes the passed transaction from the mempool. When the
|
2015-11-05 17:27:42 +01:00
|
|
|
// removeRedeemers flag is set, any transactions that redeem outputs from the
|
|
|
|
// removed transaction will also be removed recursively from the mempool, as
|
2015-08-25 23:03:18 -05:00
|
|
|
// they would otherwise become orphans.
|
2013-11-15 16:12:23 -06:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) RemoveTransaction(tx *btcutil.Tx, removeRedeemers bool) {
|
2013-11-15 16:12:23 -06:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Lock()
|
2015-11-05 17:27:42 +01:00
|
|
|
mp.removeTransaction(tx, removeRedeemers)
|
2016-04-12 21:19:13 -04:00
|
|
|
mp.mtx.Unlock()
|
2013-11-15 16:12:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveDoubleSpends removes all transactions which spend outputs spent by the
|
|
|
|
// passed transaction from the memory pool. Removing those transactions then
|
|
|
|
// leads to removing all transactions which rely on them, recursively. This is
|
|
|
|
// necessary when a block is connected to the main chain because the block may
|
2016-02-18 22:51:18 -06:00
|
|
|
// contain transactions which were previously unknown to the memory pool.
|
2013-11-15 16:12:23 -06:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) RemoveDoubleSpends(tx *btcutil.Tx) {
|
2013-11-15 16:12:23 -06:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Lock()
|
2013-11-15 16:12:23 -06:00
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
2014-10-01 16:34:30 +01:00
|
|
|
if txRedeemer, ok := mp.outpoints[txIn.PreviousOutPoint]; ok {
|
2016-08-08 14:04:33 -05:00
|
|
|
if !txRedeemer.Hash().IsEqual(tx.Hash()) {
|
2015-11-05 17:27:42 +01:00
|
|
|
mp.removeTransaction(txRedeemer, true)
|
2013-11-15 16:12:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-12 21:19:13 -04:00
|
|
|
mp.mtx.Unlock()
|
2013-11-15 16:12:23 -06:00
|
|
|
}
|
|
|
|
|
2013-09-20 12:55:27 -05:00
|
|
|
// addTransaction adds the passed transaction to the memory pool. It should
|
|
|
|
// not be called directly as it doesn't perform any validation. This is a
|
|
|
|
// helper for maybeAcceptTransaction.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2016-10-28 14:23:51 -04:00
|
|
|
func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32, fee int64) *TxDesc {
|
2013-09-20 12:55:27 -05:00
|
|
|
// Add the transaction to the pool and mark the referenced outpoints
|
|
|
|
// as spent by the pool.
|
2016-10-28 14:23:51 -04:00
|
|
|
txD := &TxDesc{
|
2015-11-25 16:27:14 -06:00
|
|
|
TxDesc: mining.TxDesc{
|
2016-10-28 12:50:08 -04:00
|
|
|
Tx: tx,
|
|
|
|
Added: time.Now(),
|
|
|
|
Height: height,
|
|
|
|
Fee: fee,
|
2018-02-15 16:06:20 +01:00
|
|
|
FeePerKB: fee * 1000 / GetTxVirtualSize(tx),
|
2015-11-25 13:30:44 -06:00
|
|
|
},
|
2016-10-25 22:48:57 -05:00
|
|
|
StartingPriority: mining.CalcPriority(tx.MsgTx(), utxoView, height),
|
2013-12-11 17:32:16 +00:00
|
|
|
}
|
2016-10-28 14:23:51 -04:00
|
|
|
|
2017-11-13 22:37:35 -06:00
|
|
|
mp.pool[*tx.Hash()] = txD
|
2013-10-28 15:44:38 -05:00
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
2014-10-01 16:34:30 +01:00
|
|
|
mp.outpoints[txIn.PreviousOutPoint] = tx
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
2016-02-12 13:44:56 -05:00
|
|
|
atomic.StoreInt64(&mp.lastUpdated, time.Now().Unix())
|
2016-02-18 22:51:18 -06:00
|
|
|
|
|
|
|
// Add unconfirmed address index entries associated with the transaction
|
|
|
|
// if enabled.
|
|
|
|
if mp.cfg.AddrIndex != nil {
|
|
|
|
mp.cfg.AddrIndex.AddUnconfirmedTx(tx, utxoView)
|
|
|
|
}
|
2016-10-28 14:23:51 -04:00
|
|
|
|
2017-11-13 22:37:35 -06:00
|
|
|
// Record this tx for fee estimation if enabled.
|
|
|
|
if mp.cfg.FeeEstimator != nil {
|
|
|
|
mp.cfg.FeeEstimator.ObserveTransaction(txD)
|
|
|
|
}
|
|
|
|
|
2016-10-28 14:23:51 -04:00
|
|
|
return txD
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// checkPoolDoubleSpend checks whether or not the passed transaction is
|
|
|
|
// attempting to spend coins already spent by other transactions in the pool.
|
2019-05-02 19:44:51 -07:00
|
|
|
// If it does, we'll check whether each of those transactions are signaling for
|
|
|
|
// replacement. If just one of them isn't, an error is returned. Otherwise, a
|
|
|
|
// boolean is returned signaling that the transaction is a replacement. Note it
|
|
|
|
// does not check for double spends against transactions already in the main
|
|
|
|
// chain.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
2019-05-02 19:44:51 -07:00
|
|
|
func (mp *TxPool) checkPoolDoubleSpend(tx *btcutil.Tx) (bool, error) {
|
|
|
|
var isReplacement bool
|
2013-10-28 15:44:38 -05:00
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
2019-05-02 19:44:51 -07:00
|
|
|
conflict, ok := mp.outpoints[txIn.PreviousOutPoint]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reject the transaction if we don't accept replacement
|
|
|
|
// transactions or if it doesn't signal replacement.
|
|
|
|
if mp.cfg.Policy.RejectReplacement ||
|
|
|
|
!mp.signalsReplacement(conflict, nil) {
|
2023-12-05 14:41:02 +08:00
|
|
|
str := fmt.Sprintf("output already spent in mempool: "+
|
|
|
|
"output=%v, tx=%v", txIn.PreviousOutPoint,
|
|
|
|
conflict.Hash())
|
2019-05-02 19:44:51 -07:00
|
|
|
return false, txRuleError(wire.RejectDuplicate, str)
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
2019-05-02 19:44:51 -07:00
|
|
|
|
|
|
|
isReplacement = true
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2019-05-02 19:44:51 -07:00
|
|
|
return isReplacement, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// signalsReplacement determines if a transaction is signaling that it can be
|
|
|
|
// replaced using the Replace-By-Fee (RBF) policy. This policy specifies two
|
|
|
|
// ways a transaction can signal that it is replaceable:
|
|
|
|
//
|
|
|
|
// Explicit signaling: A transaction is considered to have opted in to allowing
|
|
|
|
// replacement of itself if any of its inputs have a sequence number less than
|
|
|
|
// 0xfffffffe.
|
|
|
|
//
|
|
|
|
// Inherited signaling: Transactions that don't explicitly signal replaceability
|
|
|
|
// are replaceable under this policy for as long as any one of their ancestors
|
|
|
|
// signals replaceability and remains unconfirmed.
|
|
|
|
//
|
|
|
|
// The cache is optional and serves as an optimization to avoid visiting
|
|
|
|
// transactions we've already determined don't signal replacement.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
|
|
|
func (mp *TxPool) signalsReplacement(tx *btcutil.Tx,
|
|
|
|
cache map[chainhash.Hash]struct{}) bool {
|
|
|
|
|
|
|
|
// If a cache was not provided, we'll initialize one now to use for the
|
|
|
|
// recursive calls.
|
|
|
|
if cache == nil {
|
|
|
|
cache = make(map[chainhash.Hash]struct{})
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
|
|
|
if txIn.Sequence <= MaxRBFSequence {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
hash := txIn.PreviousOutPoint.Hash
|
|
|
|
unconfirmedAncestor, ok := mp.pool[hash]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we've already determined the transaction doesn't signal
|
|
|
|
// replacement, we can avoid visiting it again.
|
|
|
|
if _, ok := cache[hash]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if mp.signalsReplacement(unconfirmedAncestor.Tx, cache) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since the transaction doesn't signal replacement, we'll cache
|
|
|
|
// its result to ensure we don't attempt to determine so again.
|
|
|
|
cache[hash] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// txAncestors returns all of the unconfirmed ancestors of the given
|
|
|
|
// transaction. Given transactions A, B, and C where C spends B and B spends A,
|
|
|
|
// A and B are considered ancestors of C.
|
|
|
|
//
|
|
|
|
// The cache is optional and serves as an optimization to avoid visiting
|
|
|
|
// transactions we've already determined ancestors of.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
|
|
|
func (mp *TxPool) txAncestors(tx *btcutil.Tx,
|
|
|
|
cache map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx) map[chainhash.Hash]*btcutil.Tx {
|
|
|
|
|
|
|
|
// If a cache was not provided, we'll initialize one now to use for the
|
|
|
|
// recursive calls.
|
|
|
|
if cache == nil {
|
|
|
|
cache = make(map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx)
|
|
|
|
}
|
|
|
|
|
|
|
|
ancestors := make(map[chainhash.Hash]*btcutil.Tx)
|
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
|
|
|
parent, ok := mp.pool[txIn.PreviousOutPoint.Hash]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ancestors[*parent.Tx.Hash()] = parent.Tx
|
|
|
|
|
|
|
|
// Determine if the ancestors of this ancestor have already been
|
|
|
|
// computed. If they haven't, we'll do so now and cache them to
|
|
|
|
// use them later on if necessary.
|
|
|
|
moreAncestors, ok := cache[*parent.Tx.Hash()]
|
|
|
|
if !ok {
|
|
|
|
moreAncestors = mp.txAncestors(parent.Tx, cache)
|
|
|
|
cache[*parent.Tx.Hash()] = moreAncestors
|
|
|
|
}
|
|
|
|
|
|
|
|
for hash, ancestor := range moreAncestors {
|
|
|
|
ancestors[hash] = ancestor
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ancestors
|
|
|
|
}
|
|
|
|
|
|
|
|
// txDescendants returns all of the unconfirmed descendants of the given
|
|
|
|
// transaction. Given transactions A, B, and C where C spends B and B spends A,
|
|
|
|
// B and C are considered descendants of A. A cache can be provided in order to
|
|
|
|
// easily retrieve the descendants of transactions we've already determined the
|
|
|
|
// descendants of.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
|
|
|
func (mp *TxPool) txDescendants(tx *btcutil.Tx,
|
|
|
|
cache map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx) map[chainhash.Hash]*btcutil.Tx {
|
|
|
|
|
|
|
|
// If a cache was not provided, we'll initialize one now to use for the
|
|
|
|
// recursive calls.
|
|
|
|
if cache == nil {
|
|
|
|
cache = make(map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx)
|
|
|
|
}
|
|
|
|
|
|
|
|
// We'll go through all of the outputs of the transaction to determine
|
|
|
|
// if they are spent by any other mempool transactions.
|
|
|
|
descendants := make(map[chainhash.Hash]*btcutil.Tx)
|
|
|
|
op := wire.OutPoint{Hash: *tx.Hash()}
|
|
|
|
for i := range tx.MsgTx().TxOut {
|
|
|
|
op.Index = uint32(i)
|
|
|
|
descendant, ok := mp.outpoints[op]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
descendants[*descendant.Hash()] = descendant
|
|
|
|
|
|
|
|
// Determine if the descendants of this descendant have already
|
|
|
|
// been computed. If they haven't, we'll do so now and cache
|
|
|
|
// them to use them later on if necessary.
|
|
|
|
moreDescendants, ok := cache[*descendant.Hash()]
|
|
|
|
if !ok {
|
|
|
|
moreDescendants = mp.txDescendants(descendant, cache)
|
|
|
|
cache[*descendant.Hash()] = moreDescendants
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, moreDescendant := range moreDescendants {
|
|
|
|
descendants[*moreDescendant.Hash()] = moreDescendant
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return descendants
|
|
|
|
}
|
|
|
|
|
|
|
|
// txConflicts returns all of the unconfirmed transactions that would become
|
|
|
|
// conflicts if we were to accept the given transaction into the mempool. An
|
|
|
|
// unconfirmed conflict is known as a transaction that spends an output already
|
|
|
|
// spent by a different transaction within the mempool. Any descendants of these
|
|
|
|
// transactions are also considered conflicts as they would no longer exist.
|
|
|
|
// These are generally not allowed except for transactions that signal RBF
|
|
|
|
// support.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
|
|
|
func (mp *TxPool) txConflicts(tx *btcutil.Tx) map[chainhash.Hash]*btcutil.Tx {
|
|
|
|
conflicts := make(map[chainhash.Hash]*btcutil.Tx)
|
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
|
|
|
conflict, ok := mp.outpoints[txIn.PreviousOutPoint]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
conflicts[*conflict.Hash()] = conflict
|
|
|
|
for hash, descendant := range mp.txDescendants(conflict, nil) {
|
|
|
|
conflicts[hash] = descendant
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return conflicts
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2018-05-18 18:55:52 -07:00
|
|
|
// CheckSpend checks whether the passed outpoint is already spent by a
|
2018-03-23 15:11:20 +01:00
|
|
|
// transaction in the mempool. If that's the case the spending transaction will
|
|
|
|
// be returned, if not nil will be returned.
|
|
|
|
func (mp *TxPool) CheckSpend(op wire.OutPoint) *btcutil.Tx {
|
|
|
|
mp.mtx.RLock()
|
|
|
|
txR := mp.outpoints[op]
|
|
|
|
mp.mtx.RUnlock()
|
|
|
|
|
|
|
|
return txR
|
|
|
|
}
|
|
|
|
|
2015-08-25 23:03:18 -05:00
|
|
|
// fetchInputUtxos loads utxo details about the input transactions referenced by
|
|
|
|
// the passed transaction. First, it loads the details form the viewpoint of
|
|
|
|
// the main chain, then it adjusts them based upon the contents of the
|
|
|
|
// transaction pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) fetchInputUtxos(tx *btcutil.Tx) (*blockchain.UtxoViewpoint, error) {
|
2015-08-25 23:03:18 -05:00
|
|
|
utxoView, err := mp.cfg.FetchUtxoView(tx)
|
2013-09-20 12:55:27 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt to populate any missing inputs from the transaction pool.
|
multi: Rework utxoset/view to use outpoints.
This modifies the utxoset in the database and related UtxoViewpoint to
store and work with unspent transaction outputs on a per-output basis
instead of at a transaction level. This was inspired by similar recent
changes in Bitcoin Core.
The primary motivation is to simplify the code, pave the way for a
utxo cache, and generally focus on optimizing runtime performance.
The tradeoff is that this approach does somewhat increase the size of
the serialized utxoset since it means that the transaction hash is
duplicated for each output as a part of the key and some additional
details such as whether the containing transaction is a coinbase and the
block height it was a part of are duplicated in each output.
However, in practice, the size difference isn't all that large, disk
space is relatively cheap, certainly cheaper than memory, and it is much
more important to provide more efficient runtime operation since that is
the ultimate purpose of the daemon.
While performing this conversion, it also simplifies the code to remove
the transaction version information from the utxoset as well as the
spend journal. The logic for only serializing it under certain
circumstances is complicated and it isn't actually used anywhere aside
from the gettxout RPC where it also isn't used by anything important
either. Consequently, this also removes the version field of the
gettxout RPC result.
The utxos in the database are automatically migrated to the new format
with this commit and it is possible to interrupt and resume the
migration process.
Finally, it also updates the tests for the new format and adds a new
function to the tests to convert the old test data to the new format for
convenience. The data has already been converted and updated in the
commit.
An overview of the changes are as follows:
- Remove transaction version from both spent and unspent output entries
- Update utxo serialization format to exclude the version
- Modify the spend journal serialization format
- The old version field is now reserved and always stores zero and
ignores it when reading
- This allows old entries to be used by new code without having to
migrate the entire spend journal
- Remove version field from gettxout RPC result
- Convert UtxoEntry to represent a specific utxo instead of a
transaction with all remaining utxos
- Optimize for memory usage with an eye towards a utxo cache
- Combine details such as whether the txout was contained in a
coinbase, is spent, and is modified into a single packed field of
bit flags
- Align entry fields to eliminate extra padding since ultimately
there will be a lot of these in memory
- Introduce a free list for serializing an outpoint to the database
key format to significantly reduce pressure on the GC
- Update all related functions that previously dealt with transaction
hashes to accept outpoints instead
- Update all callers accordingly
- Only add individually requested outputs from the mempool when
constructing a mempool view
- Modify the spend journal to always store the block height and coinbase
information with every spent txout
- Introduce code to handle fetching the missing information from
another utxo from the same transaction in the event an old style
entry is encountered
- Make use of a database cursor with seek to do this much more
efficiently than testing every possible output
- Always decompress data loaded from the database now that a utxo entry
only consists of a specific output
- Introduce upgrade code to migrate the utxo set to the new format
- Store versions of the utxoset and spend journal buckets
- Allow migration process to be interrupted and resumed
- Update all tests to expect the correct encodings, remove tests that no
longer apply, and add new ones for the new expected behavior
- Convert old tests for the legacy utxo format deserialization code to
test the new function that is used during upgrade
- Update the utxostore test data and add function that was used to
convert it
- Introduce a few new functions on UtxoViewpoint
- AddTxOut for adding an individual txout versus all of them
- addTxOut to handle the common code between the new AddTxOut and
existing AddTxOuts
- RemoveEntry for removing an individual txout
- fetchEntryByHash for fetching any remaining utxo for a given
transaction hash
2017-09-03 02:59:15 -05:00
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
|
|
|
prevOut := &txIn.PreviousOutPoint
|
|
|
|
entry := utxoView.LookupEntry(*prevOut)
|
|
|
|
if entry != nil && !entry.IsSpent() {
|
2015-08-25 23:03:18 -05:00
|
|
|
continue
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
multi: Rework utxoset/view to use outpoints.
This modifies the utxoset in the database and related UtxoViewpoint to
store and work with unspent transaction outputs on a per-output basis
instead of at a transaction level. This was inspired by similar recent
changes in Bitcoin Core.
The primary motivation is to simplify the code, pave the way for a
utxo cache, and generally focus on optimizing runtime performance.
The tradeoff is that this approach does somewhat increase the size of
the serialized utxoset since it means that the transaction hash is
duplicated for each output as a part of the key and some additional
details such as whether the containing transaction is a coinbase and the
block height it was a part of are duplicated in each output.
However, in practice, the size difference isn't all that large, disk
space is relatively cheap, certainly cheaper than memory, and it is much
more important to provide more efficient runtime operation since that is
the ultimate purpose of the daemon.
While performing this conversion, it also simplifies the code to remove
the transaction version information from the utxoset as well as the
spend journal. The logic for only serializing it under certain
circumstances is complicated and it isn't actually used anywhere aside
from the gettxout RPC where it also isn't used by anything important
either. Consequently, this also removes the version field of the
gettxout RPC result.
The utxos in the database are automatically migrated to the new format
with this commit and it is possible to interrupt and resume the
migration process.
Finally, it also updates the tests for the new format and adds a new
function to the tests to convert the old test data to the new format for
convenience. The data has already been converted and updated in the
commit.
An overview of the changes are as follows:
- Remove transaction version from both spent and unspent output entries
- Update utxo serialization format to exclude the version
- Modify the spend journal serialization format
- The old version field is now reserved and always stores zero and
ignores it when reading
- This allows old entries to be used by new code without having to
migrate the entire spend journal
- Remove version field from gettxout RPC result
- Convert UtxoEntry to represent a specific utxo instead of a
transaction with all remaining utxos
- Optimize for memory usage with an eye towards a utxo cache
- Combine details such as whether the txout was contained in a
coinbase, is spent, and is modified into a single packed field of
bit flags
- Align entry fields to eliminate extra padding since ultimately
there will be a lot of these in memory
- Introduce a free list for serializing an outpoint to the database
key format to significantly reduce pressure on the GC
- Update all related functions that previously dealt with transaction
hashes to accept outpoints instead
- Update all callers accordingly
- Only add individually requested outputs from the mempool when
constructing a mempool view
- Modify the spend journal to always store the block height and coinbase
information with every spent txout
- Introduce code to handle fetching the missing information from
another utxo from the same transaction in the event an old style
entry is encountered
- Make use of a database cursor with seek to do this much more
efficiently than testing every possible output
- Always decompress data loaded from the database now that a utxo entry
only consists of a specific output
- Introduce upgrade code to migrate the utxo set to the new format
- Store versions of the utxoset and spend journal buckets
- Allow migration process to be interrupted and resumed
- Update all tests to expect the correct encodings, remove tests that no
longer apply, and add new ones for the new expected behavior
- Convert old tests for the legacy utxo format deserialization code to
test the new function that is used during upgrade
- Update the utxostore test data and add function that was used to
convert it
- Introduce a few new functions on UtxoViewpoint
- AddTxOut for adding an individual txout versus all of them
- addTxOut to handle the common code between the new AddTxOut and
existing AddTxOuts
- RemoveEntry for removing an individual txout
- fetchEntryByHash for fetching any remaining utxo for a given
transaction hash
2017-09-03 02:59:15 -05:00
|
|
|
if poolTxDesc, exists := mp.pool[prevOut.Hash]; exists {
|
|
|
|
// AddTxOut ignores out of range index values, so it is
|
|
|
|
// safe to call without bounds checking here.
|
|
|
|
utxoView.AddTxOut(poolTxDesc.Tx, prevOut.Index,
|
|
|
|
mining.UnminedHeight)
|
2015-08-25 23:03:18 -05:00
|
|
|
}
|
|
|
|
}
|
multi: Rework utxoset/view to use outpoints.
This modifies the utxoset in the database and related UtxoViewpoint to
store and work with unspent transaction outputs on a per-output basis
instead of at a transaction level. This was inspired by similar recent
changes in Bitcoin Core.
The primary motivation is to simplify the code, pave the way for a
utxo cache, and generally focus on optimizing runtime performance.
The tradeoff is that this approach does somewhat increase the size of
the serialized utxoset since it means that the transaction hash is
duplicated for each output as a part of the key and some additional
details such as whether the containing transaction is a coinbase and the
block height it was a part of are duplicated in each output.
However, in practice, the size difference isn't all that large, disk
space is relatively cheap, certainly cheaper than memory, and it is much
more important to provide more efficient runtime operation since that is
the ultimate purpose of the daemon.
While performing this conversion, it also simplifies the code to remove
the transaction version information from the utxoset as well as the
spend journal. The logic for only serializing it under certain
circumstances is complicated and it isn't actually used anywhere aside
from the gettxout RPC where it also isn't used by anything important
either. Consequently, this also removes the version field of the
gettxout RPC result.
The utxos in the database are automatically migrated to the new format
with this commit and it is possible to interrupt and resume the
migration process.
Finally, it also updates the tests for the new format and adds a new
function to the tests to convert the old test data to the new format for
convenience. The data has already been converted and updated in the
commit.
An overview of the changes are as follows:
- Remove transaction version from both spent and unspent output entries
- Update utxo serialization format to exclude the version
- Modify the spend journal serialization format
- The old version field is now reserved and always stores zero and
ignores it when reading
- This allows old entries to be used by new code without having to
migrate the entire spend journal
- Remove version field from gettxout RPC result
- Convert UtxoEntry to represent a specific utxo instead of a
transaction with all remaining utxos
- Optimize for memory usage with an eye towards a utxo cache
- Combine details such as whether the txout was contained in a
coinbase, is spent, and is modified into a single packed field of
bit flags
- Align entry fields to eliminate extra padding since ultimately
there will be a lot of these in memory
- Introduce a free list for serializing an outpoint to the database
key format to significantly reduce pressure on the GC
- Update all related functions that previously dealt with transaction
hashes to accept outpoints instead
- Update all callers accordingly
- Only add individually requested outputs from the mempool when
constructing a mempool view
- Modify the spend journal to always store the block height and coinbase
information with every spent txout
- Introduce code to handle fetching the missing information from
another utxo from the same transaction in the event an old style
entry is encountered
- Make use of a database cursor with seek to do this much more
efficiently than testing every possible output
- Always decompress data loaded from the database now that a utxo entry
only consists of a specific output
- Introduce upgrade code to migrate the utxo set to the new format
- Store versions of the utxoset and spend journal buckets
- Allow migration process to be interrupted and resumed
- Update all tests to expect the correct encodings, remove tests that no
longer apply, and add new ones for the new expected behavior
- Convert old tests for the legacy utxo format deserialization code to
test the new function that is used during upgrade
- Update the utxostore test data and add function that was used to
convert it
- Introduce a few new functions on UtxoViewpoint
- AddTxOut for adding an individual txout versus all of them
- addTxOut to handle the common code between the new AddTxOut and
existing AddTxOuts
- RemoveEntry for removing an individual txout
- fetchEntryByHash for fetching any remaining utxo for a given
transaction hash
2017-09-03 02:59:15 -05:00
|
|
|
|
2015-08-25 23:03:18 -05:00
|
|
|
return utxoView, nil
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2013-10-11 14:12:40 -05:00
|
|
|
// FetchTransaction returns the requested transaction from the transaction pool.
|
|
|
|
// This only fetches from the main transaction pool and does not include
|
|
|
|
// orphans.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) FetchTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error) {
|
2013-10-21 18:20:31 -05:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2016-04-12 21:19:13 -04:00
|
|
|
txDesc, exists := mp.pool[*txHash]
|
|
|
|
mp.mtx.RUnlock()
|
2013-10-11 14:12:40 -05:00
|
|
|
|
2016-04-12 21:19:13 -04:00
|
|
|
if exists {
|
2013-12-11 17:32:16 +00:00
|
|
|
return txDesc.Tx, nil
|
2013-10-11 14:12:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("transaction is not in the pool")
|
|
|
|
}
|
|
|
|
|
2019-05-02 19:44:51 -07:00
|
|
|
// validateReplacement determines whether a transaction is deemed as a valid
|
|
|
|
// replacement of all of its conflicts according to the RBF policy. If it is
|
|
|
|
// valid, no error is returned. Otherwise, an error is returned indicating what
|
|
|
|
// went wrong.
|
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for reads).
|
|
|
|
func (mp *TxPool) validateReplacement(tx *btcutil.Tx,
|
|
|
|
txFee int64) (map[chainhash.Hash]*btcutil.Tx, error) {
|
|
|
|
|
|
|
|
// First, we'll make sure the set of conflicting transactions doesn't
|
|
|
|
// exceed the maximum allowed.
|
|
|
|
conflicts := mp.txConflicts(tx)
|
|
|
|
if len(conflicts) > MaxReplacementEvictions {
|
2023-12-05 14:41:02 +08:00
|
|
|
str := fmt.Sprintf("%v: replacement transaction evicts more "+
|
2019-05-02 19:44:51 -07:00
|
|
|
"transactions than permitted: max is %v, evicts %v",
|
|
|
|
tx.Hash(), MaxReplacementEvictions, len(conflicts))
|
|
|
|
return nil, txRuleError(wire.RejectNonstandard, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The set of conflicts (transactions we'll replace) and ancestors
|
|
|
|
// should not overlap, otherwise the replacement would be spending an
|
|
|
|
// output that no longer exists.
|
|
|
|
for ancestorHash := range mp.txAncestors(tx, nil) {
|
|
|
|
if _, ok := conflicts[ancestorHash]; !ok {
|
|
|
|
continue
|
|
|
|
}
|
2023-12-05 14:41:02 +08:00
|
|
|
str := fmt.Sprintf("%v: replacement transaction spends parent "+
|
2019-05-02 19:44:51 -07:00
|
|
|
"transaction %v", tx.Hash(), ancestorHash)
|
|
|
|
return nil, txRuleError(wire.RejectInvalid, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The replacement should have a higher fee rate than each of the
|
|
|
|
// conflicting transactions and a higher absolute fee than the fee sum
|
|
|
|
// of all the conflicting transactions.
|
|
|
|
//
|
|
|
|
// We usually don't want to accept replacements with lower fee rates
|
|
|
|
// than what they replaced as that would lower the fee rate of the next
|
|
|
|
// block. Requiring that the fee rate always be increased is also an
|
|
|
|
// easy-to-reason about way to prevent DoS attacks via replacements.
|
|
|
|
var (
|
|
|
|
txSize = GetTxVirtualSize(tx)
|
|
|
|
txFeeRate = txFee * 1000 / txSize
|
|
|
|
conflictsFee int64
|
|
|
|
conflictsParents = make(map[chainhash.Hash]struct{})
|
|
|
|
)
|
|
|
|
for hash, conflict := range conflicts {
|
|
|
|
if txFeeRate <= mp.pool[hash].FeePerKB {
|
2023-12-05 14:41:02 +08:00
|
|
|
str := fmt.Sprintf("%v: replacement transaction has an "+
|
2019-05-02 19:44:51 -07:00
|
|
|
"insufficient fee rate: needs more than %v, "+
|
|
|
|
"has %v", tx.Hash(), mp.pool[hash].FeePerKB,
|
|
|
|
txFeeRate)
|
|
|
|
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
conflictsFee += mp.pool[hash].Fee
|
|
|
|
|
|
|
|
// We'll track each conflict's parents to ensure the replacement
|
|
|
|
// isn't spending any new unconfirmed inputs.
|
|
|
|
for _, txIn := range conflict.MsgTx().TxIn {
|
|
|
|
conflictsParents[txIn.PreviousOutPoint.Hash] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It should also have an absolute fee greater than all of the
|
|
|
|
// transactions it intends to replace and pay for its own bandwidth,
|
|
|
|
// which is determined by our minimum relay fee.
|
|
|
|
minFee := calcMinRequiredTxRelayFee(txSize, mp.cfg.Policy.MinRelayTxFee)
|
|
|
|
if txFee < conflictsFee+minFee {
|
2023-12-05 14:41:02 +08:00
|
|
|
str := fmt.Sprintf("%v: replacement transaction has an "+
|
2019-05-02 19:44:51 -07:00
|
|
|
"insufficient absolute fee: needs %v, has %v",
|
|
|
|
tx.Hash(), conflictsFee+minFee, txFee)
|
|
|
|
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, it should not spend any new unconfirmed outputs, other than
|
|
|
|
// the ones already included in the parents of the conflicting
|
|
|
|
// transactions it'll replace.
|
|
|
|
for _, txIn := range tx.MsgTx().TxIn {
|
|
|
|
if _, ok := conflictsParents[txIn.PreviousOutPoint.Hash]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// Confirmed outputs are valid to spend in the replacement.
|
|
|
|
if _, ok := mp.pool[txIn.PreviousOutPoint.Hash]; !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
str := fmt.Sprintf("replacement transaction spends new "+
|
|
|
|
"unconfirmed input %v not found in conflicting "+
|
|
|
|
"transactions", txIn.PreviousOutPoint)
|
|
|
|
return nil, txRuleError(wire.RejectInvalid, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
return conflicts, nil
|
|
|
|
}
|
|
|
|
|
2013-11-15 01:50:02 -06:00
|
|
|
// maybeAcceptTransaction is the internal function which implements the public
|
|
|
|
// MaybeAcceptTransaction. See the comment for MaybeAcceptTransaction for
|
|
|
|
// more details.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2023-11-04 07:40:47 +08:00
|
|
|
func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit,
|
|
|
|
rejectDupOrphans bool) ([]*chainhash.Hash, *TxDesc, error) {
|
2013-09-20 12:55:27 -05:00
|
|
|
|
2023-11-04 07:40:47 +08:00
|
|
|
txHash := tx.Hash()
|
2013-09-20 12:55:27 -05:00
|
|
|
|
2023-11-04 07:40:47 +08:00
|
|
|
// Check for mempool acceptance.
|
|
|
|
r, err := mp.checkMempoolAcceptance(
|
|
|
|
tx, isNew, rateLimit, rejectDupOrphans,
|
|
|
|
)
|
2014-08-14 10:44:26 -04:00
|
|
|
if err != nil {
|
2016-10-28 14:23:51 -04:00
|
|
|
return nil, nil, err
|
2014-08-14 10:44:26 -04:00
|
|
|
}
|
|
|
|
|
2023-11-04 07:40:47 +08:00
|
|
|
// Exit early if this transaction is missing parents.
|
|
|
|
if len(r.MissingParents) > 0 {
|
|
|
|
return r.MissingParents, nil, nil
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2019-05-02 19:44:51 -07:00
|
|
|
// Now that we've deemed the transaction as valid, we can add it to the
|
|
|
|
// mempool. If it ended up replacing any transactions, we'll remove them
|
|
|
|
// first.
|
2023-11-04 07:40:47 +08:00
|
|
|
for _, conflict := range r.Conflicts {
|
2019-05-02 19:44:51 -07:00
|
|
|
log.Debugf("Replacing transaction %v (fee_rate=%v sat/kb) "+
|
|
|
|
"with %v (fee_rate=%v sat/kb)\n", conflict.Hash(),
|
|
|
|
mp.pool[*conflict.Hash()].FeePerKB, tx.Hash(),
|
2023-11-04 07:40:47 +08:00
|
|
|
int64(r.TxFee)*1000/r.TxSize)
|
2019-05-02 19:44:51 -07:00
|
|
|
|
|
|
|
// The conflict set should already include the descendants for
|
|
|
|
// each one, so we don't need to remove the redeemers within
|
|
|
|
// this call as they'll be removed eventually.
|
|
|
|
mp.removeTransaction(conflict, false)
|
|
|
|
}
|
2023-11-04 07:40:47 +08:00
|
|
|
txD := mp.addTransaction(r.utxoView, tx, r.bestHeight, int64(r.TxFee))
|
2013-09-20 12:55:27 -05:00
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
log.Debugf("Accepted transaction %v (pool size: %v)", txHash,
|
2013-09-20 12:55:27 -05:00
|
|
|
len(mp.pool))
|
|
|
|
|
2016-10-28 14:23:51 -04:00
|
|
|
return nil, txD, nil
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2013-11-15 01:50:02 -06:00
|
|
|
// MaybeAcceptTransaction is the main workhorse for handling insertion of new
|
|
|
|
// free-standing transactions into a memory pool. It includes functionality
|
|
|
|
// such as rejecting duplicate transactions, ensuring transactions follow all
|
2015-01-06 19:26:26 -05:00
|
|
|
// rules, detecting orphan transactions, and insertion into the memory pool.
|
|
|
|
//
|
|
|
|
// If the transaction is an orphan (missing parent transactions), the
|
|
|
|
// transaction is NOT added to the orphan pool, but each unknown referenced
|
|
|
|
// parent is returned. Use ProcessTransaction instead if new orphans should
|
|
|
|
// be added to the orphan pool.
|
2013-11-15 01:50:02 -06:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-10-28 14:23:51 -04:00
|
|
|
func (mp *TxPool) MaybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit bool) ([]*chainhash.Hash, *TxDesc, error) {
|
2013-11-15 01:50:02 -06:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Lock()
|
2016-10-28 14:23:51 -04:00
|
|
|
hashes, txD, err := mp.maybeAcceptTransaction(tx, isNew, rateLimit, true)
|
2016-04-12 21:19:13 -04:00
|
|
|
mp.mtx.Unlock()
|
2013-11-15 01:50:02 -06:00
|
|
|
|
2016-10-28 14:23:51 -04:00
|
|
|
return hashes, txD, err
|
2013-11-15 01:50:02 -06:00
|
|
|
}
|
|
|
|
|
2015-03-10 12:40:44 -04:00
|
|
|
// processOrphans is the internal function which implements the public
|
|
|
|
// ProcessOrphans. See the comment for ProcessOrphans for more details.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function MUST be called with the mempool lock held (for writes).
|
2016-10-28 14:23:51 -04:00
|
|
|
func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*TxDesc {
|
|
|
|
var acceptedTxns []*TxDesc
|
2016-04-14 13:58:09 -04:00
|
|
|
|
2016-08-23 12:26:26 -05:00
|
|
|
// Start with processing at least the passed transaction.
|
|
|
|
processList := list.New()
|
|
|
|
processList.PushBack(acceptedTx)
|
|
|
|
for processList.Len() > 0 {
|
|
|
|
// Pop the transaction to process from the front of the list.
|
|
|
|
firstElement := processList.Remove(processList.Front())
|
|
|
|
processItem := firstElement.(*btcutil.Tx)
|
|
|
|
|
|
|
|
prevOut := wire.OutPoint{Hash: *processItem.Hash()}
|
|
|
|
for txOutIdx := range processItem.MsgTx().TxOut {
|
|
|
|
// Look up all orphans that redeem the output that is
|
|
|
|
// now available. This will typically only be one, but
|
|
|
|
// it could be multiple if the orphan pool contains
|
|
|
|
// double spends. While it may seem odd that the orphan
|
|
|
|
// pool would allow this since there can only possibly
|
|
|
|
// ultimately be a single redeemer, it's important to
|
|
|
|
// track it this way to prevent malicious actors from
|
|
|
|
// being able to purposely constructing orphans that
|
|
|
|
// would otherwise make outputs unspendable.
|
2015-01-06 19:26:26 -05:00
|
|
|
//
|
2016-08-23 12:26:26 -05:00
|
|
|
// Skip to the next available output if there are none.
|
|
|
|
prevOut.Index = uint32(txOutIdx)
|
|
|
|
orphans, exists := mp.orphansByPrev[prevOut]
|
|
|
|
if !exists {
|
2015-11-10 17:04:16 -05:00
|
|
|
continue
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2016-08-23 12:26:26 -05:00
|
|
|
// Potentially accept an orphan into the tx pool.
|
|
|
|
for _, tx := range orphans {
|
2016-10-28 14:23:51 -04:00
|
|
|
missing, txD, err := mp.maybeAcceptTransaction(
|
2016-08-23 12:26:26 -05:00
|
|
|
tx, true, true, false)
|
|
|
|
if err != nil {
|
|
|
|
// The orphan is now invalid, so there
|
|
|
|
// is no way any other orphans which
|
|
|
|
// redeem any of its outputs can be
|
|
|
|
// accepted. Remove them.
|
|
|
|
mp.removeOrphan(tx, true)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transaction is still an orphan. Try the next
|
|
|
|
// orphan which redeems this output.
|
|
|
|
if len(missing) > 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transaction was accepted into the main pool.
|
|
|
|
//
|
|
|
|
// Add it to the list of accepted transactions
|
|
|
|
// that are no longer orphans, remove it from
|
|
|
|
// the orphan pool, and add it to the list of
|
|
|
|
// transactions to process so any orphans that
|
|
|
|
// depend on it are handled too.
|
2016-10-28 14:23:51 -04:00
|
|
|
acceptedTxns = append(acceptedTxns, txD)
|
2016-08-23 12:26:26 -05:00
|
|
|
mp.removeOrphan(tx, false)
|
|
|
|
processList.PushBack(tx)
|
|
|
|
|
|
|
|
// Only one transaction for this outpoint can be
|
|
|
|
// accepted, so the rest are now double spends
|
|
|
|
// and are removed later.
|
|
|
|
break
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-14 13:58:09 -04:00
|
|
|
|
2016-08-23 12:26:26 -05:00
|
|
|
// Recursively remove any orphans that also redeem any outputs redeemed
|
|
|
|
// by the accepted transactions since those are now definitive double
|
|
|
|
// spends.
|
|
|
|
mp.removeOrphanDoubleSpends(acceptedTx)
|
2016-10-28 14:23:51 -04:00
|
|
|
for _, txD := range acceptedTxns {
|
|
|
|
mp.removeOrphanDoubleSpends(txD.Tx)
|
2016-08-23 12:26:26 -05:00
|
|
|
}
|
|
|
|
|
2016-04-14 13:58:09 -04:00
|
|
|
return acceptedTxns
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2015-03-10 12:40:44 -04:00
|
|
|
// ProcessOrphans determines if there are any orphans which depend on the passed
|
|
|
|
// transaction hash (it is possible that they are no longer orphans) and
|
|
|
|
// potentially accepts them to the memory pool. It repeats the process for the
|
|
|
|
// newly accepted transactions (to detect further orphans which may no longer be
|
|
|
|
// orphans) until there are no more.
|
|
|
|
//
|
2016-04-14 13:58:09 -04:00
|
|
|
// It returns a slice of transactions added to the mempool. A nil slice means
|
|
|
|
// no transactions were moved from the orphan pool to the mempool.
|
|
|
|
//
|
2015-03-10 12:40:44 -04:00
|
|
|
// This function is safe for concurrent access.
|
2016-10-28 14:23:51 -04:00
|
|
|
func (mp *TxPool) ProcessOrphans(acceptedTx *btcutil.Tx) []*TxDesc {
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Lock()
|
2016-08-23 12:26:26 -05:00
|
|
|
acceptedTxns := mp.processOrphans(acceptedTx)
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Unlock()
|
2016-04-14 13:58:09 -04:00
|
|
|
|
|
|
|
return acceptedTxns
|
2015-03-10 12:40:44 -04:00
|
|
|
}
|
|
|
|
|
2013-09-20 12:55:27 -05:00
|
|
|
// ProcessTransaction is the main workhorse for handling insertion of new
|
2013-12-25 12:28:54 -06:00
|
|
|
// free-standing transactions into the memory pool. It includes functionality
|
2013-09-20 12:55:27 -05:00
|
|
|
// such as rejecting duplicate transactions, ensuring transactions follow all
|
|
|
|
// rules, orphan transaction handling, and insertion into the memory pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
2016-04-14 13:58:09 -04:00
|
|
|
// It returns a slice of transactions added to the mempool. When the
|
|
|
|
// error is nil, the list will include the passed transaction itself along
|
2021-10-18 15:48:51 +08:00
|
|
|
// with any additional orphan transactions that were added as a result of
|
2016-04-14 13:58:09 -04:00
|
|
|
// the passed one being accepted.
|
|
|
|
//
|
2013-10-21 18:20:31 -05:00
|
|
|
// This function is safe for concurrent access.
|
2016-10-28 12:48:54 -05:00
|
|
|
func (mp *TxPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool, tag Tag) ([]*TxDesc, error) {
|
2016-04-12 21:19:13 -04:00
|
|
|
log.Tracef("Processing transaction %v", tx.Hash())
|
|
|
|
|
2013-10-21 18:20:31 -05:00
|
|
|
// Protect concurrent access.
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.Lock()
|
|
|
|
defer mp.mtx.Unlock()
|
2013-10-21 18:20:31 -05:00
|
|
|
|
2013-09-20 12:55:27 -05:00
|
|
|
// Potentially accept the transaction to the memory pool.
|
2016-10-28 14:23:51 -04:00
|
|
|
missingParents, txD, err := mp.maybeAcceptTransaction(tx, true, rateLimit,
|
2016-08-23 12:26:26 -05:00
|
|
|
true)
|
2013-09-20 12:55:27 -05:00
|
|
|
if err != nil {
|
2016-04-14 13:58:09 -04:00
|
|
|
return nil, err
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2015-01-06 19:26:26 -05:00
|
|
|
if len(missingParents) == 0 {
|
2013-09-20 12:55:27 -05:00
|
|
|
// Accept any orphan transactions that depend on this
|
2015-01-06 19:26:26 -05:00
|
|
|
// transaction (they may no longer be orphans if all inputs
|
|
|
|
// are now available) and repeat for those accepted
|
|
|
|
// transactions until there are no more.
|
2016-08-23 12:26:26 -05:00
|
|
|
newTxs := mp.processOrphans(tx)
|
2016-10-28 14:23:51 -04:00
|
|
|
acceptedTxs := make([]*TxDesc, len(newTxs)+1)
|
2016-04-14 13:58:09 -04:00
|
|
|
|
|
|
|
// Add the parent transaction first so remote nodes
|
|
|
|
// do not add orphans.
|
2016-10-28 14:23:51 -04:00
|
|
|
acceptedTxs[0] = txD
|
2016-04-14 13:58:09 -04:00
|
|
|
copy(acceptedTxs[1:], newTxs)
|
|
|
|
|
|
|
|
return acceptedTxs, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// The transaction is an orphan (has inputs missing). Reject
|
|
|
|
// it if the flag to allow orphans is not set.
|
|
|
|
if !allowOrphan {
|
|
|
|
// Only use the first missing parent transaction in
|
|
|
|
// the error message.
|
|
|
|
//
|
|
|
|
// NOTE: RejectDuplicate is really not an accurate
|
|
|
|
// reject code here, but it matches the reference
|
|
|
|
// implementation and there isn't a better choice due
|
|
|
|
// to the limited number of reject codes. Missing
|
|
|
|
// inputs is assumed to mean they are already spent
|
|
|
|
// which is not really always the case.
|
|
|
|
str := fmt.Sprintf("orphan transaction %v references "+
|
|
|
|
"outputs of unknown or fully-spent "+
|
2016-08-08 14:04:33 -05:00
|
|
|
"transaction %v", tx.Hash(), missingParents[0])
|
2016-04-14 13:58:09 -04:00
|
|
|
return nil, txRuleError(wire.RejectDuplicate, str)
|
|
|
|
}
|
2014-03-17 17:32:30 -05:00
|
|
|
|
2016-04-14 13:58:09 -04:00
|
|
|
// Potentially add the orphan transaction to the orphan pool.
|
2016-10-28 12:48:54 -05:00
|
|
|
err = mp.maybeAddOrphan(tx, tag)
|
2016-11-02 23:02:04 -05:00
|
|
|
return nil, err
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
|
2014-05-03 23:51:54 -05:00
|
|
|
// Count returns the number of transactions in the main pool. It does not
|
|
|
|
// include the orphan pool.
|
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) Count() int {
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2016-04-12 21:19:13 -04:00
|
|
|
count := len(mp.pool)
|
|
|
|
mp.mtx.RUnlock()
|
2014-05-03 23:51:54 -05:00
|
|
|
|
2016-04-12 21:19:13 -04:00
|
|
|
return count
|
2014-05-03 23:51:54 -05:00
|
|
|
}
|
|
|
|
|
2021-10-18 15:48:51 +08:00
|
|
|
// TxHashes returns a slice of hashes for all the transactions in the memory
|
2013-10-08 13:34:04 -05:00
|
|
|
// pool.
|
2013-10-21 18:20:31 -05:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) TxHashes() []*chainhash.Hash {
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2016-08-08 14:04:33 -05:00
|
|
|
hashes := make([]*chainhash.Hash, len(mp.pool))
|
2013-10-08 00:04:51 -05:00
|
|
|
i := 0
|
|
|
|
for hash := range mp.pool {
|
|
|
|
hashCopy := hash
|
|
|
|
hashes[i] = &hashCopy
|
|
|
|
i++
|
|
|
|
}
|
2016-04-12 21:19:13 -04:00
|
|
|
mp.mtx.RUnlock()
|
2013-10-08 00:04:51 -05:00
|
|
|
|
|
|
|
return hashes
|
|
|
|
}
|
|
|
|
|
2013-12-11 17:32:16 +00:00
|
|
|
// TxDescs returns a slice of descriptors for all the transactions in the pool.
|
|
|
|
// The descriptors are to be treated as read only.
|
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) TxDescs() []*TxDesc {
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2016-08-19 11:08:37 -05:00
|
|
|
descs := make([]*TxDesc, len(mp.pool))
|
2013-12-11 17:32:16 +00:00
|
|
|
i := 0
|
|
|
|
for _, desc := range mp.pool {
|
|
|
|
descs[i] = desc
|
|
|
|
i++
|
|
|
|
}
|
2016-04-12 21:19:13 -04:00
|
|
|
mp.mtx.RUnlock()
|
2013-12-11 17:32:16 +00:00
|
|
|
|
|
|
|
return descs
|
|
|
|
}
|
|
|
|
|
2015-11-25 13:30:44 -06:00
|
|
|
// MiningDescs returns a slice of mining descriptors for all the transactions
|
|
|
|
// in the pool.
|
|
|
|
//
|
2015-11-25 16:27:14 -06:00
|
|
|
// This is part of the mining.TxSource interface implementation and is safe for
|
2015-11-25 13:30:44 -06:00
|
|
|
// concurrent access as required by the interface contract.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) MiningDescs() []*mining.TxDesc {
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
2015-11-25 16:27:14 -06:00
|
|
|
descs := make([]*mining.TxDesc, len(mp.pool))
|
2015-11-25 13:30:44 -06:00
|
|
|
i := 0
|
|
|
|
for _, desc := range mp.pool {
|
2015-11-25 16:27:14 -06:00
|
|
|
descs[i] = &desc.TxDesc
|
2015-11-25 13:30:44 -06:00
|
|
|
i++
|
|
|
|
}
|
2016-04-12 21:19:13 -04:00
|
|
|
mp.mtx.RUnlock()
|
2015-11-25 13:30:44 -06:00
|
|
|
|
|
|
|
return descs
|
|
|
|
}
|
|
|
|
|
2021-10-18 15:48:51 +08:00
|
|
|
// RawMempoolVerbose returns all the entries in the mempool as a fully
|
2016-08-19 11:08:37 -05:00
|
|
|
// populated btcjson result.
|
|
|
|
//
|
|
|
|
// This function is safe for concurrent access.
|
|
|
|
func (mp *TxPool) RawMempoolVerbose() map[string]*btcjson.GetRawMempoolVerboseResult {
|
2016-08-23 14:59:48 -04:00
|
|
|
mp.mtx.RLock()
|
|
|
|
defer mp.mtx.RUnlock()
|
2016-08-19 11:08:37 -05:00
|
|
|
|
|
|
|
result := make(map[string]*btcjson.GetRawMempoolVerboseResult,
|
|
|
|
len(mp.pool))
|
2016-08-21 00:04:43 -05:00
|
|
|
bestHeight := mp.cfg.BestHeight()
|
2016-08-19 11:08:37 -05:00
|
|
|
|
|
|
|
for _, desc := range mp.pool {
|
|
|
|
// 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 {
|
2016-10-25 22:48:57 -05:00
|
|
|
currentPriority = mining.CalcPriority(tx.MsgTx(), utxos,
|
2016-08-21 00:04:43 -05:00
|
|
|
bestHeight+1)
|
2016-08-19 11:08:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
mpd := &btcjson.GetRawMempoolVerboseResult{
|
|
|
|
Size: int32(tx.MsgTx().SerializeSize()),
|
2016-10-18 18:21:33 -07:00
|
|
|
Vsize: int32(GetTxVirtualSize(tx)),
|
2019-09-26 08:19:03 +08:00
|
|
|
Weight: int32(blockchain.GetTransactionWeight(tx)),
|
2016-08-19 11:08:37 -05:00
|
|
|
Fee: btcutil.Amount(desc.Fee).ToBTC(),
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2014-03-20 02:06:10 -05:00
|
|
|
// 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.
|
2016-08-19 11:08:37 -05:00
|
|
|
func (mp *TxPool) LastUpdated() time.Time {
|
2016-02-12 13:44:56 -05:00
|
|
|
return time.Unix(atomic.LoadInt64(&mp.lastUpdated), 0)
|
2014-03-20 02:06:10 -05:00
|
|
|
}
|
|
|
|
|
2023-11-04 07:40:47 +08:00
|
|
|
// MempoolAcceptResult holds the result from mempool acceptance check.
|
|
|
|
type MempoolAcceptResult struct {
|
|
|
|
// TxFee is the fees paid in satoshi.
|
|
|
|
TxFee btcutil.Amount
|
|
|
|
|
|
|
|
// TxSize is the virtual size(vb) of the tx.
|
|
|
|
TxSize int64
|
|
|
|
|
|
|
|
// conflicts is a set of transactions whose inputs are spent by this
|
|
|
|
// transaction(RBF).
|
|
|
|
Conflicts map[chainhash.Hash]*btcutil.Tx
|
|
|
|
|
|
|
|
// MissingParents is a set of outpoints that are used by this
|
|
|
|
// transaction which cannot be found. Transaction is an orphan if any
|
|
|
|
// of the referenced transaction outputs don't exist or are already
|
|
|
|
// spent.
|
|
|
|
//
|
|
|
|
// NOTE: this field is mutually exclusive with other fields. If this
|
|
|
|
// field is not nil, then other fields must be empty.
|
|
|
|
MissingParents []*chainhash.Hash
|
|
|
|
|
|
|
|
// utxoView is a set of the unspent transaction outputs referenced by
|
|
|
|
// the inputs to this transaction.
|
|
|
|
utxoView *blockchain.UtxoViewpoint
|
|
|
|
|
|
|
|
// bestHeight is the best known height by the mempool.
|
|
|
|
bestHeight int32
|
|
|
|
}
|
|
|
|
|
|
|
|
// CheckMempoolAcceptance behaves similarly to bitcoind's `testmempoolaccept`
|
|
|
|
// RPC method. It will perform a series of checks to decide whether this
|
|
|
|
// transaction can be accepted to the mempool. If not, the specific error is
|
|
|
|
// returned and the caller needs to take actions based on it.
|
|
|
|
func (mp *TxPool) CheckMempoolAcceptance(tx *btcutil.Tx) (
|
|
|
|
*MempoolAcceptResult, error) {
|
|
|
|
|
|
|
|
mp.mtx.RLock()
|
|
|
|
defer mp.mtx.RUnlock()
|
|
|
|
|
|
|
|
// Call checkMempoolAcceptance with isNew=true and rateLimit=true,
|
|
|
|
// which has the effect that we always check the fee paid from this tx
|
|
|
|
// is greater than min relay fee. We also reject this tx if it's
|
|
|
|
// already an orphan.
|
|
|
|
result, err := mp.checkMempoolAcceptance(tx, true, true, true)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("CheckMempoolAcceptance: %v", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Tracef("Tx %v passed mempool acceptance check: %v", tx.Hash(),
|
|
|
|
spew.Sdump(result))
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkMempoolAcceptance performs a series of validations on the given
|
|
|
|
// transaction. It returns an error when the transaction fails to meet the
|
|
|
|
// mempool policy, otherwise a `mempoolAcceptResult` is returned.
|
|
|
|
func (mp *TxPool) checkMempoolAcceptance(tx *btcutil.Tx,
|
|
|
|
isNew, rateLimit, rejectDupOrphans bool) (*MempoolAcceptResult, error) {
|
|
|
|
|
|
|
|
txHash := tx.Hash()
|
|
|
|
|
|
|
|
// Check for segwit activeness.
|
|
|
|
if err := mp.validateSegWitDeployment(tx); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't accept the transaction if it already exists in the pool. This
|
|
|
|
// applies to orphan transactions as well when the reject duplicate
|
|
|
|
// orphans flag is set. This check is intended to be a quick check to
|
|
|
|
// weed out duplicates.
|
|
|
|
if mp.isTransactionInPool(txHash) || (rejectDupOrphans &&
|
|
|
|
mp.isOrphanInPool(txHash)) {
|
|
|
|
|
2023-12-05 14:41:02 +08:00
|
|
|
str := fmt.Sprintf("already have transaction in mempool %v",
|
|
|
|
txHash)
|
2023-11-04 07:40:47 +08:00
|
|
|
return nil, txRuleError(wire.RejectDuplicate, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform preliminary sanity checks on the transaction. This makes use
|
|
|
|
// of blockchain which contains the invariant rules for what
|
|
|
|
// transactions are allowed into blocks.
|
|
|
|
err := blockchain.CheckTransactionSanity(tx)
|
|
|
|
if err != nil {
|
|
|
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
|
|
|
return nil, chainRuleError(cerr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// A standalone transaction must not be a coinbase transaction.
|
|
|
|
if blockchain.IsCoinBase(tx) {
|
2023-12-05 14:41:02 +08:00
|
|
|
str := fmt.Sprintf("transaction is an individual coinbase %v",
|
2023-11-04 07:40:47 +08:00
|
|
|
txHash)
|
|
|
|
|
|
|
|
return nil, txRuleError(wire.RejectInvalid, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the current height of the main chain. A standalone transaction
|
|
|
|
// will be mined into the next block at best, so its height is at least
|
|
|
|
// one more than the current height.
|
|
|
|
bestHeight := mp.cfg.BestHeight()
|
|
|
|
nextBlockHeight := bestHeight + 1
|
|
|
|
|
|
|
|
medianTimePast := mp.cfg.MedianTimePast()
|
|
|
|
|
|
|
|
// The transaction may not use any of the same outputs as other
|
|
|
|
// transactions already in the pool as that would ultimately result in
|
|
|
|
// a double spend, unless those transactions signal for RBF. This check
|
|
|
|
// is intended to be quick and therefore only detects double spends
|
|
|
|
// within the transaction pool itself. The transaction could still be
|
|
|
|
// double spending coins from the main chain at this point. There is a
|
|
|
|
// more in-depth check that happens later after fetching the referenced
|
|
|
|
// transaction inputs from the main chain which examines the actual
|
|
|
|
// spend data and prevents double spends.
|
|
|
|
isReplacement, err := mp.checkPoolDoubleSpend(tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch all of the unspent transaction outputs referenced by the
|
|
|
|
// inputs to this transaction. This function also attempts to fetch the
|
|
|
|
// transaction itself to be used for detecting a duplicate transaction
|
|
|
|
// without needing to do a separate lookup.
|
|
|
|
utxoView, err := mp.fetchInputUtxos(tx)
|
|
|
|
if err != nil {
|
|
|
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
|
|
|
return nil, chainRuleError(cerr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't allow the transaction if it exists in the main chain and is
|
|
|
|
// already fully spent.
|
|
|
|
prevOut := wire.OutPoint{Hash: *txHash}
|
|
|
|
for txOutIdx := range tx.MsgTx().TxOut {
|
|
|
|
prevOut.Index = uint32(txOutIdx)
|
|
|
|
|
|
|
|
entry := utxoView.LookupEntry(prevOut)
|
|
|
|
if entry != nil && !entry.IsSpent() {
|
|
|
|
return nil, txRuleError(wire.RejectDuplicate,
|
2023-12-05 14:41:02 +08:00
|
|
|
"transaction already exists in blockchain")
|
2023-11-04 07:40:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
utxoView.RemoveEntry(prevOut)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transaction is an orphan if any of the referenced transaction
|
|
|
|
// outputs don't exist or are already spent. Adding orphans to the
|
|
|
|
// orphan pool is not handled by this function, and the caller should
|
|
|
|
// use maybeAddOrphan if this behavior is desired.
|
|
|
|
var missingParents []*chainhash.Hash
|
|
|
|
for outpoint, entry := range utxoView.Entries() {
|
|
|
|
if entry == nil || entry.IsSpent() {
|
|
|
|
// Must make a copy of the hash here since the iterator
|
|
|
|
// is replaced and taking its address directly would
|
|
|
|
// result in all the entries pointing to the same
|
|
|
|
// memory location and thus all be the final hash.
|
|
|
|
hashCopy := outpoint.Hash
|
|
|
|
missingParents = append(missingParents, &hashCopy)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exit early if this transaction is missing parents.
|
|
|
|
if len(missingParents) > 0 {
|
|
|
|
log.Debugf("Tx %v is an orphan with missing parents: %v",
|
|
|
|
txHash, missingParents)
|
|
|
|
|
|
|
|
return &MempoolAcceptResult{
|
|
|
|
MissingParents: missingParents,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform several checks on the transaction inputs using the invariant
|
|
|
|
// rules in blockchain for what transactions are allowed into blocks.
|
|
|
|
// Also returns the fees associated with the transaction which will be
|
|
|
|
// used later.
|
|
|
|
//
|
|
|
|
// NOTE: this check must be performed before `validateStandardness` to
|
|
|
|
// make sure a nil entry is not returned from `utxoView.LookupEntry`.
|
|
|
|
txFee, err := blockchain.CheckTransactionInputs(
|
|
|
|
tx, nextBlockHeight, utxoView, mp.cfg.ChainParams,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
|
|
|
return nil, chainRuleError(cerr)
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't allow non-standard transactions or non-standard inputs if the
|
|
|
|
// network parameters forbid their acceptance.
|
|
|
|
err = mp.validateStandardness(
|
|
|
|
tx, nextBlockHeight, medianTimePast, utxoView,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't allow the transaction into the mempool unless its sequence
|
|
|
|
// lock is active, meaning that it'll be allowed into the next block
|
|
|
|
// with respect to its defined relative lock times.
|
|
|
|
sequenceLock, err := mp.cfg.CalcSequenceLock(tx, utxoView)
|
|
|
|
if err != nil {
|
|
|
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
|
|
|
return nil, chainRuleError(cerr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !blockchain.SequenceLockActive(
|
|
|
|
sequenceLock, nextBlockHeight, medianTimePast,
|
|
|
|
) {
|
|
|
|
|
|
|
|
return nil, txRuleError(wire.RejectNonstandard,
|
|
|
|
"transaction's sequence locks on inputs not met")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't allow transactions with an excessive number of signature
|
|
|
|
// operations which would result in making it impossible to mine.
|
|
|
|
if err := mp.validateSigCost(tx, utxoView); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
txSize := GetTxVirtualSize(tx)
|
|
|
|
|
|
|
|
// Don't allow transactions with fees too low to get into a mined
|
|
|
|
// block.
|
|
|
|
err = mp.validateRelayFeeMet(
|
|
|
|
tx, txFee, txSize, utxoView, nextBlockHeight, isNew, rateLimit,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the transaction has any conflicts, and we've made it this far,
|
|
|
|
// then we're processing a potential replacement.
|
|
|
|
var conflicts map[chainhash.Hash]*btcutil.Tx
|
|
|
|
if isReplacement {
|
|
|
|
conflicts, err = mp.validateReplacement(tx, txFee)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify crypto signatures for each input and reject the transaction
|
|
|
|
// if any don't verify.
|
|
|
|
err = blockchain.ValidateTransactionScripts(tx, utxoView,
|
|
|
|
txscript.StandardVerifyFlags, mp.cfg.SigCache,
|
|
|
|
mp.cfg.HashCache)
|
|
|
|
if err != nil {
|
|
|
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
|
|
|
return nil, chainRuleError(cerr)
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
result := &MempoolAcceptResult{
|
|
|
|
TxFee: btcutil.Amount(txFee),
|
|
|
|
TxSize: txSize,
|
|
|
|
Conflicts: conflicts,
|
|
|
|
utxoView: utxoView,
|
|
|
|
bestHeight: bestHeight,
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// validateSegWitDeployment checks that when a transaction has witness data,
|
|
|
|
// segwit must be active.
|
|
|
|
func (mp *TxPool) validateSegWitDeployment(tx *btcutil.Tx) error {
|
|
|
|
// Exit early if this transaction doesn't have witness data.
|
|
|
|
if !tx.MsgTx().HasWitness() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// If a transaction has witness data, and segwit isn't active yet, then
|
|
|
|
// we won't accept it into the mempool as it can't be mined yet.
|
|
|
|
segwitActive, err := mp.cfg.IsDeploymentActive(
|
|
|
|
chaincfg.DeploymentSegwit,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exit early if segwit is active.
|
|
|
|
if segwitActive {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
simnetHint := ""
|
|
|
|
if mp.cfg.ChainParams.Net == wire.SimNet {
|
|
|
|
bestHeight := mp.cfg.BestHeight()
|
|
|
|
simnetHint = fmt.Sprintf(" (The threshold for segwit "+
|
|
|
|
"activation is 300 blocks on simnet, current best "+
|
|
|
|
"height is %d)", bestHeight)
|
|
|
|
}
|
|
|
|
str := fmt.Sprintf("transaction %v has witness data, "+
|
|
|
|
"but segwit isn't active yet%s", tx.Hash(), simnetHint)
|
|
|
|
|
|
|
|
return txRuleError(wire.RejectNonstandard, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// validateStandardness checks the transaction passes both transaction standard
|
|
|
|
// and input standard.
|
|
|
|
func (mp *TxPool) validateStandardness(tx *btcutil.Tx, nextBlockHeight int32,
|
|
|
|
medianTimePast time.Time, utxoView *blockchain.UtxoViewpoint) error {
|
|
|
|
|
|
|
|
// Exit early if we accept non-standard transactions.
|
|
|
|
//
|
|
|
|
// NOTE: if you modify this code to accept non-standard transactions,
|
|
|
|
// you should add code here to check that the transaction does a
|
|
|
|
// reasonable number of ECDSA signature verifications.
|
|
|
|
if mp.cfg.Policy.AcceptNonStd {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the transaction standard.
|
|
|
|
err := CheckTransactionStandard(
|
|
|
|
tx, nextBlockHeight, medianTimePast,
|
|
|
|
mp.cfg.Policy.MinRelayTxFee, mp.cfg.Policy.MaxTxVersion,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
// Attempt to extract a reject code from the error so it can be
|
|
|
|
// retained. When not possible, fall back to a non standard
|
|
|
|
// error.
|
|
|
|
rejectCode, found := extractRejectCode(err)
|
|
|
|
if !found {
|
|
|
|
rejectCode = wire.RejectNonstandard
|
|
|
|
}
|
|
|
|
str := fmt.Sprintf("transaction %v is not standard: %v",
|
|
|
|
tx.Hash(), err)
|
|
|
|
|
|
|
|
return txRuleError(rejectCode, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the inputs standard.
|
|
|
|
err = checkInputsStandard(tx, utxoView)
|
|
|
|
if err != nil {
|
|
|
|
// Attempt to extract a reject code from the error so it can be
|
|
|
|
// retained. When not possible, fall back to a non-standard
|
|
|
|
// error.
|
|
|
|
rejectCode, found := extractRejectCode(err)
|
|
|
|
if !found {
|
|
|
|
rejectCode = wire.RejectNonstandard
|
|
|
|
}
|
|
|
|
str := fmt.Sprintf("transaction %v has a non-standard "+
|
|
|
|
"input: %v", tx.Hash(), err)
|
|
|
|
|
|
|
|
return txRuleError(rejectCode, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// validateSigCost checks the cost to run the signature operations to make sure
|
|
|
|
// the number of singatures are sane.
|
|
|
|
func (mp *TxPool) validateSigCost(tx *btcutil.Tx,
|
|
|
|
utxoView *blockchain.UtxoViewpoint) error {
|
|
|
|
|
|
|
|
// Since the coinbase address itself can contain signature operations,
|
|
|
|
// the maximum allowed signature operations per transaction is less
|
|
|
|
// than the maximum allowed signature operations per block.
|
|
|
|
//
|
|
|
|
// TODO(roasbeef): last bool should be conditional on segwit activation
|
|
|
|
sigOpCost, err := blockchain.GetSigOpCost(
|
|
|
|
tx, false, utxoView, true, true,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
|
|
|
return chainRuleError(cerr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exit early if the sig cost is under limit.
|
|
|
|
if sigOpCost <= mp.cfg.Policy.MaxSigOpCostPerTx {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
str := fmt.Sprintf("transaction %v sigop cost is too high: %d > %d",
|
|
|
|
tx.Hash(), sigOpCost, mp.cfg.Policy.MaxSigOpCostPerTx)
|
|
|
|
|
|
|
|
return txRuleError(wire.RejectNonstandard, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// validateRelayFeeMet checks that the min relay fee is covered by this
|
|
|
|
// transaction.
|
|
|
|
func (mp *TxPool) validateRelayFeeMet(tx *btcutil.Tx, txFee, txSize int64,
|
|
|
|
utxoView *blockchain.UtxoViewpoint, nextBlockHeight int32,
|
|
|
|
isNew, rateLimit bool) error {
|
|
|
|
|
|
|
|
txHash := tx.Hash()
|
|
|
|
|
|
|
|
// Most miners allow a free transaction area in blocks they mine to go
|
|
|
|
// alongside the area used for high-priority transactions as well as
|
|
|
|
// transactions with fees. A transaction size of up to 1000 bytes is
|
|
|
|
// considered safe to go into this section. Further, the minimum fee
|
|
|
|
// calculated below on its own would encourage several small
|
|
|
|
// transactions to avoid fees rather than one single larger transaction
|
|
|
|
// which is more desirable. Therefore, as long as the size of the
|
|
|
|
// transaction does not exceed 1000 less than the reserved space for
|
|
|
|
// high-priority transactions, don't require a fee for it.
|
|
|
|
minFee := calcMinRequiredTxRelayFee(txSize, mp.cfg.Policy.MinRelayTxFee)
|
|
|
|
|
|
|
|
if txSize >= (DefaultBlockPrioritySize-1000) && txFee < minFee {
|
|
|
|
str := fmt.Sprintf("transaction %v has %d fees which is under "+
|
|
|
|
"the required amount of %d", txHash, txFee, minFee)
|
|
|
|
|
|
|
|
return txRuleError(wire.RejectInsufficientFee, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exit early if the min relay fee is met.
|
|
|
|
if txFee >= minFee {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exit early if this is neither a new tx or rate limited.
|
|
|
|
if !isNew && !rateLimit {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Require that free transactions have sufficient priority to be mined
|
|
|
|
// in the next block. Transactions which are being added back to the
|
|
|
|
// memory pool from blocks that have been disconnected during a reorg
|
|
|
|
// are exempted.
|
|
|
|
if isNew && !mp.cfg.Policy.DisableRelayPriority {
|
|
|
|
currentPriority := mining.CalcPriority(
|
|
|
|
tx.MsgTx(), utxoView, nextBlockHeight,
|
|
|
|
)
|
|
|
|
if currentPriority <= mining.MinHighPriority {
|
|
|
|
str := fmt.Sprintf("transaction %v has insufficient "+
|
|
|
|
"priority (%g <= %g)", txHash,
|
|
|
|
currentPriority, mining.MinHighPriority)
|
|
|
|
|
|
|
|
return txRuleError(wire.RejectInsufficientFee, str)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can only end up here when the rateLimit is true. Free-to-relay
|
|
|
|
// transactions are rate limited here to prevent penny-flooding with
|
|
|
|
// tiny transactions as a form of attack.
|
|
|
|
nowUnix := time.Now().Unix()
|
|
|
|
|
|
|
|
// Decay passed data with an exponentially decaying ~10 minute window -
|
|
|
|
// matches bitcoind handling.
|
|
|
|
mp.pennyTotal *= math.Pow(
|
|
|
|
1.0-1.0/600.0, float64(nowUnix-mp.lastPennyUnix),
|
|
|
|
)
|
|
|
|
mp.lastPennyUnix = nowUnix
|
|
|
|
|
|
|
|
// Are we still over the limit?
|
|
|
|
if mp.pennyTotal >= mp.cfg.Policy.FreeTxRelayLimit*10*1000 {
|
|
|
|
str := fmt.Sprintf("transaction %v has been rejected "+
|
|
|
|
"by the rate limiter due to low fees", txHash)
|
|
|
|
|
|
|
|
return txRuleError(wire.RejectInsufficientFee, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
oldTotal := mp.pennyTotal
|
|
|
|
mp.pennyTotal += float64(txSize)
|
|
|
|
log.Tracef("rate limit: curTotal %v, nextTotal: %v, limit %v",
|
|
|
|
oldTotal, mp.pennyTotal, mp.cfg.Policy.FreeTxRelayLimit*10*1000)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-08-19 11:08:37 -05:00
|
|
|
// New returns a new memory pool for validating and storing standalone
|
2013-09-20 12:55:27 -05:00
|
|
|
// transactions until they are mined into a block.
|
2016-08-19 11:08:37 -05:00
|
|
|
func New(cfg *Config) *TxPool {
|
|
|
|
return &TxPool{
|
2016-08-23 23:27:41 -05:00
|
|
|
cfg: *cfg,
|
|
|
|
pool: make(map[chainhash.Hash]*TxDesc),
|
|
|
|
orphans: make(map[chainhash.Hash]*orphanTx),
|
|
|
|
orphansByPrev: make(map[wire.OutPoint]map[chainhash.Hash]*btcutil.Tx),
|
|
|
|
nextExpireScan: time.Now().Add(orphanExpireScanInterval),
|
|
|
|
outpoints: make(map[wire.OutPoint]*btcutil.Tx),
|
2013-09-20 12:55:27 -05:00
|
|
|
}
|
|
|
|
}
|