mempool: Return type TxDesc instead of type btcutil.Tx
This will provide callers more information on the accepted transaction.
This commit is contained in:
parent
1a69eb0617
commit
2615fa0849
4 changed files with 61 additions and 57 deletions
|
@ -1185,7 +1185,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
|
||||||
// Reinsert all of the transactions (except the coinbase) into
|
// Reinsert all of the transactions (except the coinbase) into
|
||||||
// the transaction pool.
|
// the transaction pool.
|
||||||
for _, tx := range block.Transactions()[1:] {
|
for _, tx := range block.Transactions()[1:] {
|
||||||
_, err := b.server.txMemPool.MaybeAcceptTransaction(tx,
|
_, _, err := b.server.txMemPool.MaybeAcceptTransaction(tx,
|
||||||
false, false)
|
false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Remove the transaction and all transactions
|
// Remove the transaction and all transactions
|
||||||
|
|
|
@ -481,10 +481,10 @@ func (mp *TxPool) RemoveDoubleSpends(tx *btcutil.Tx) {
|
||||||
// helper for maybeAcceptTransaction.
|
// helper for maybeAcceptTransaction.
|
||||||
//
|
//
|
||||||
// This function MUST be called with the mempool lock held (for writes).
|
// This function MUST be called with the mempool lock held (for writes).
|
||||||
func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32, fee int64) {
|
func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32, fee int64) *TxDesc {
|
||||||
// Add the transaction to the pool and mark the referenced outpoints
|
// Add the transaction to the pool and mark the referenced outpoints
|
||||||
// as spent by the pool.
|
// as spent by the pool.
|
||||||
mp.pool[*tx.Hash()] = &TxDesc{
|
txD := &TxDesc{
|
||||||
TxDesc: mining.TxDesc{
|
TxDesc: mining.TxDesc{
|
||||||
Tx: tx,
|
Tx: tx,
|
||||||
Added: time.Now(),
|
Added: time.Now(),
|
||||||
|
@ -493,6 +493,8 @@ func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil
|
||||||
},
|
},
|
||||||
StartingPriority: mining.CalcPriority(tx.MsgTx(), utxoView, height),
|
StartingPriority: mining.CalcPriority(tx.MsgTx(), utxoView, height),
|
||||||
}
|
}
|
||||||
|
mp.pool[*tx.Hash()] = txD
|
||||||
|
|
||||||
for _, txIn := range tx.MsgTx().TxIn {
|
for _, txIn := range tx.MsgTx().TxIn {
|
||||||
mp.outpoints[txIn.PreviousOutPoint] = tx
|
mp.outpoints[txIn.PreviousOutPoint] = tx
|
||||||
}
|
}
|
||||||
|
@ -503,6 +505,8 @@ func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil
|
||||||
if mp.cfg.AddrIndex != nil {
|
if mp.cfg.AddrIndex != nil {
|
||||||
mp.cfg.AddrIndex.AddUnconfirmedTx(tx, utxoView)
|
mp.cfg.AddrIndex.AddUnconfirmedTx(tx, utxoView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return txD
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkPoolDoubleSpend checks whether or not the passed transaction is
|
// checkPoolDoubleSpend checks whether or not the passed transaction is
|
||||||
|
@ -572,7 +576,7 @@ func (mp *TxPool) FetchTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error)
|
||||||
// more details.
|
// more details.
|
||||||
//
|
//
|
||||||
// This function MUST be called with the mempool lock held (for writes).
|
// This function MUST be called with the mempool lock held (for writes).
|
||||||
func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejectDupOrphans bool) ([]*chainhash.Hash, error) {
|
func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejectDupOrphans bool) ([]*chainhash.Hash, *TxDesc, error) {
|
||||||
txHash := tx.Hash()
|
txHash := tx.Hash()
|
||||||
|
|
||||||
// Don't accept the transaction if it already exists in the pool. This
|
// Don't accept the transaction if it already exists in the pool. This
|
||||||
|
@ -583,7 +587,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
mp.isOrphanInPool(txHash)) {
|
mp.isOrphanInPool(txHash)) {
|
||||||
|
|
||||||
str := fmt.Sprintf("already have transaction %v", txHash)
|
str := fmt.Sprintf("already have transaction %v", txHash)
|
||||||
return nil, txRuleError(wire.RejectDuplicate, str)
|
return nil, nil, txRuleError(wire.RejectDuplicate, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform preliminary sanity checks on the transaction. This makes
|
// Perform preliminary sanity checks on the transaction. This makes
|
||||||
|
@ -592,16 +596,16 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
err := blockchain.CheckTransactionSanity(tx)
|
err := blockchain.CheckTransactionSanity(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cerr, ok := err.(blockchain.RuleError); ok {
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
||||||
return nil, chainRuleError(cerr)
|
return nil, nil, chainRuleError(cerr)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// A standalone transaction must not be a coinbase transaction.
|
// A standalone transaction must not be a coinbase transaction.
|
||||||
if blockchain.IsCoinBase(tx) {
|
if blockchain.IsCoinBase(tx) {
|
||||||
str := fmt.Sprintf("transaction %v is an individual coinbase",
|
str := fmt.Sprintf("transaction %v is an individual coinbase",
|
||||||
txHash)
|
txHash)
|
||||||
return nil, txRuleError(wire.RejectInvalid, str)
|
return nil, nil, txRuleError(wire.RejectInvalid, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't accept transactions with a lock time after the maximum int32
|
// Don't accept transactions with a lock time after the maximum int32
|
||||||
|
@ -611,7 +615,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
if tx.MsgTx().LockTime > math.MaxInt32 {
|
if tx.MsgTx().LockTime > math.MaxInt32 {
|
||||||
str := fmt.Sprintf("transaction %v has a lock time after "+
|
str := fmt.Sprintf("transaction %v has a lock time after "+
|
||||||
"2038 which is not accepted yet", txHash)
|
"2038 which is not accepted yet", txHash)
|
||||||
return nil, txRuleError(wire.RejectNonstandard, str)
|
return nil, nil, txRuleError(wire.RejectNonstandard, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current height of the main chain. A standalone transaction
|
// Get the current height of the main chain. A standalone transaction
|
||||||
|
@ -638,7 +642,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
}
|
}
|
||||||
str := fmt.Sprintf("transaction %v is not standard: %v",
|
str := fmt.Sprintf("transaction %v is not standard: %v",
|
||||||
txHash, err)
|
txHash, err)
|
||||||
return nil, txRuleError(rejectCode, str)
|
return nil, nil, txRuleError(rejectCode, str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,7 +656,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
// which examines the actual spend data and prevents double spends.
|
// which examines the actual spend data and prevents double spends.
|
||||||
err = mp.checkPoolDoubleSpend(tx)
|
err = mp.checkPoolDoubleSpend(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all of the unspent transaction outputs referenced by the inputs
|
// Fetch all of the unspent transaction outputs referenced by the inputs
|
||||||
|
@ -662,16 +666,16 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
utxoView, err := mp.fetchInputUtxos(tx)
|
utxoView, err := mp.fetchInputUtxos(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cerr, ok := err.(blockchain.RuleError); ok {
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
||||||
return nil, chainRuleError(cerr)
|
return nil, nil, chainRuleError(cerr)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow the transaction if it exists in the main chain and is not
|
// Don't allow the transaction if it exists in the main chain and is not
|
||||||
// not already fully spent.
|
// not already fully spent.
|
||||||
txEntry := utxoView.LookupEntry(txHash)
|
txEntry := utxoView.LookupEntry(txHash)
|
||||||
if txEntry != nil && !txEntry.IsFullySpent() {
|
if txEntry != nil && !txEntry.IsFullySpent() {
|
||||||
return nil, txRuleError(wire.RejectDuplicate,
|
return nil, nil, txRuleError(wire.RejectDuplicate,
|
||||||
"transaction already exists")
|
"transaction already exists")
|
||||||
}
|
}
|
||||||
delete(utxoView.Entries(), *txHash)
|
delete(utxoView.Entries(), *txHash)
|
||||||
|
@ -692,7 +696,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(missingParents) > 0 {
|
if len(missingParents) > 0 {
|
||||||
return missingParents, nil
|
return missingParents, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow the transaction into the mempool unless its sequence
|
// Don't allow the transaction into the mempool unless its sequence
|
||||||
|
@ -701,13 +705,13 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
sequenceLock, err := mp.cfg.CalcSequenceLock(tx, utxoView)
|
sequenceLock, err := mp.cfg.CalcSequenceLock(tx, utxoView)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cerr, ok := err.(blockchain.RuleError); ok {
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
||||||
return nil, chainRuleError(cerr)
|
return nil, nil, chainRuleError(cerr)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if !blockchain.SequenceLockActive(sequenceLock, nextBlockHeight,
|
if !blockchain.SequenceLockActive(sequenceLock, nextBlockHeight,
|
||||||
medianTimePast) {
|
medianTimePast) {
|
||||||
return nil, txRuleError(wire.RejectNonstandard,
|
return nil, nil, txRuleError(wire.RejectNonstandard,
|
||||||
"transaction's sequence locks on inputs not met")
|
"transaction's sequence locks on inputs not met")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,9 +723,9 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
utxoView, mp.cfg.ChainParams)
|
utxoView, mp.cfg.ChainParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cerr, ok := err.(blockchain.RuleError); ok {
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
||||||
return nil, chainRuleError(cerr)
|
return nil, nil, chainRuleError(cerr)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow transactions with non-standard inputs if the network
|
// Don't allow transactions with non-standard inputs if the network
|
||||||
|
@ -738,7 +742,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
}
|
}
|
||||||
str := fmt.Sprintf("transaction %v has a non-standard "+
|
str := fmt.Sprintf("transaction %v has a non-standard "+
|
||||||
"input: %v", txHash, err)
|
"input: %v", txHash, err)
|
||||||
return nil, txRuleError(rejectCode, str)
|
return nil, nil, txRuleError(rejectCode, str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,15 +758,15 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
numSigOps, err := blockchain.CountP2SHSigOps(tx, false, utxoView)
|
numSigOps, err := blockchain.CountP2SHSigOps(tx, false, utxoView)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cerr, ok := err.(blockchain.RuleError); ok {
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
||||||
return nil, chainRuleError(cerr)
|
return nil, nil, chainRuleError(cerr)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
numSigOps += blockchain.CountSigOps(tx)
|
numSigOps += blockchain.CountSigOps(tx)
|
||||||
if numSigOps > mp.cfg.Policy.MaxSigOpsPerTx {
|
if numSigOps > mp.cfg.Policy.MaxSigOpsPerTx {
|
||||||
str := fmt.Sprintf("transaction %v has too many sigops: %d > %d",
|
str := fmt.Sprintf("transaction %v has too many sigops: %d > %d",
|
||||||
txHash, numSigOps, mp.cfg.Policy.MaxSigOpsPerTx)
|
txHash, numSigOps, mp.cfg.Policy.MaxSigOpsPerTx)
|
||||||
return nil, txRuleError(wire.RejectNonstandard, str)
|
return nil, nil, txRuleError(wire.RejectNonstandard, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow transactions with fees too low to get into a mined block.
|
// Don't allow transactions with fees too low to get into a mined block.
|
||||||
|
@ -783,7 +787,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
str := fmt.Sprintf("transaction %v has %d fees which is under "+
|
str := fmt.Sprintf("transaction %v has %d fees which is under "+
|
||||||
"the required amount of %d", txHash, txFee,
|
"the required amount of %d", txHash, txFee,
|
||||||
minFee)
|
minFee)
|
||||||
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
return nil, nil, txRuleError(wire.RejectInsufficientFee, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Require that free transactions have sufficient priority to be mined
|
// Require that free transactions have sufficient priority to be mined
|
||||||
|
@ -797,7 +801,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
str := fmt.Sprintf("transaction %v has insufficient "+
|
str := fmt.Sprintf("transaction %v has insufficient "+
|
||||||
"priority (%g <= %g)", txHash,
|
"priority (%g <= %g)", txHash,
|
||||||
currentPriority, mining.MinHighPriority)
|
currentPriority, mining.MinHighPriority)
|
||||||
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
return nil, nil, txRuleError(wire.RejectInsufficientFee, str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,7 +819,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
if mp.pennyTotal >= mp.cfg.Policy.FreeTxRelayLimit*10*1000 {
|
if mp.pennyTotal >= mp.cfg.Policy.FreeTxRelayLimit*10*1000 {
|
||||||
str := fmt.Sprintf("transaction %v has been rejected "+
|
str := fmt.Sprintf("transaction %v has been rejected "+
|
||||||
"by the rate limiter due to low fees", txHash)
|
"by the rate limiter due to low fees", txHash)
|
||||||
return nil, txRuleError(wire.RejectInsufficientFee, str)
|
return nil, nil, txRuleError(wire.RejectInsufficientFee, str)
|
||||||
}
|
}
|
||||||
oldTotal := mp.pennyTotal
|
oldTotal := mp.pennyTotal
|
||||||
|
|
||||||
|
@ -831,18 +835,18 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
txscript.StandardVerifyFlags, mp.cfg.SigCache)
|
txscript.StandardVerifyFlags, mp.cfg.SigCache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cerr, ok := err.(blockchain.RuleError); ok {
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
||||||
return nil, chainRuleError(cerr)
|
return nil, nil, chainRuleError(cerr)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to transaction pool.
|
// Add to transaction pool.
|
||||||
mp.addTransaction(utxoView, tx, bestHeight, txFee)
|
txD := mp.addTransaction(utxoView, tx, bestHeight, txFee)
|
||||||
|
|
||||||
log.Debugf("Accepted transaction %v (pool size: %v)", txHash,
|
log.Debugf("Accepted transaction %v (pool size: %v)", txHash,
|
||||||
len(mp.pool))
|
len(mp.pool))
|
||||||
|
|
||||||
return nil, nil
|
return nil, txD, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaybeAcceptTransaction is the main workhorse for handling insertion of new
|
// MaybeAcceptTransaction is the main workhorse for handling insertion of new
|
||||||
|
@ -856,21 +860,21 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec
|
||||||
// be added to the orphan pool.
|
// be added to the orphan pool.
|
||||||
//
|
//
|
||||||
// This function is safe for concurrent access.
|
// This function is safe for concurrent access.
|
||||||
func (mp *TxPool) MaybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit bool) ([]*chainhash.Hash, error) {
|
func (mp *TxPool) MaybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit bool) ([]*chainhash.Hash, *TxDesc, error) {
|
||||||
// Protect concurrent access.
|
// Protect concurrent access.
|
||||||
mp.mtx.Lock()
|
mp.mtx.Lock()
|
||||||
hashes, err := mp.maybeAcceptTransaction(tx, isNew, rateLimit, true)
|
hashes, txD, err := mp.maybeAcceptTransaction(tx, isNew, rateLimit, true)
|
||||||
mp.mtx.Unlock()
|
mp.mtx.Unlock()
|
||||||
|
|
||||||
return hashes, err
|
return hashes, txD, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// processOrphans is the internal function which implements the public
|
// processOrphans is the internal function which implements the public
|
||||||
// ProcessOrphans. See the comment for ProcessOrphans for more details.
|
// ProcessOrphans. See the comment for ProcessOrphans for more details.
|
||||||
//
|
//
|
||||||
// This function MUST be called with the mempool lock held (for writes).
|
// This function MUST be called with the mempool lock held (for writes).
|
||||||
func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*btcutil.Tx {
|
func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*TxDesc {
|
||||||
var acceptedTxns []*btcutil.Tx
|
var acceptedTxns []*TxDesc
|
||||||
|
|
||||||
// Start with processing at least the passed transaction.
|
// Start with processing at least the passed transaction.
|
||||||
processList := list.New()
|
processList := list.New()
|
||||||
|
@ -901,7 +905,7 @@ func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*btcutil.Tx {
|
||||||
|
|
||||||
// Potentially accept an orphan into the tx pool.
|
// Potentially accept an orphan into the tx pool.
|
||||||
for _, tx := range orphans {
|
for _, tx := range orphans {
|
||||||
missing, err := mp.maybeAcceptTransaction(
|
missing, txD, err := mp.maybeAcceptTransaction(
|
||||||
tx, true, true, false)
|
tx, true, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The orphan is now invalid, so there
|
// The orphan is now invalid, so there
|
||||||
|
@ -925,7 +929,7 @@ func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*btcutil.Tx {
|
||||||
// the orphan pool, and add it to the list of
|
// the orphan pool, and add it to the list of
|
||||||
// transactions to process so any orphans that
|
// transactions to process so any orphans that
|
||||||
// depend on it are handled too.
|
// depend on it are handled too.
|
||||||
acceptedTxns = append(acceptedTxns, tx)
|
acceptedTxns = append(acceptedTxns, txD)
|
||||||
mp.removeOrphan(tx, false)
|
mp.removeOrphan(tx, false)
|
||||||
processList.PushBack(tx)
|
processList.PushBack(tx)
|
||||||
|
|
||||||
|
@ -941,8 +945,8 @@ func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*btcutil.Tx {
|
||||||
// by the accepted transactions since those are now definitive double
|
// by the accepted transactions since those are now definitive double
|
||||||
// spends.
|
// spends.
|
||||||
mp.removeOrphanDoubleSpends(acceptedTx)
|
mp.removeOrphanDoubleSpends(acceptedTx)
|
||||||
for _, tx := range acceptedTxns {
|
for _, txD := range acceptedTxns {
|
||||||
mp.removeOrphanDoubleSpends(tx)
|
mp.removeOrphanDoubleSpends(txD.Tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return acceptedTxns
|
return acceptedTxns
|
||||||
|
@ -958,7 +962,7 @@ func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*btcutil.Tx {
|
||||||
// no transactions were moved from the orphan pool to the mempool.
|
// no transactions were moved from the orphan pool to the mempool.
|
||||||
//
|
//
|
||||||
// This function is safe for concurrent access.
|
// This function is safe for concurrent access.
|
||||||
func (mp *TxPool) ProcessOrphans(acceptedTx *btcutil.Tx) []*btcutil.Tx {
|
func (mp *TxPool) ProcessOrphans(acceptedTx *btcutil.Tx) []*TxDesc {
|
||||||
mp.mtx.Lock()
|
mp.mtx.Lock()
|
||||||
acceptedTxns := mp.processOrphans(acceptedTx)
|
acceptedTxns := mp.processOrphans(acceptedTx)
|
||||||
mp.mtx.Unlock()
|
mp.mtx.Unlock()
|
||||||
|
@ -977,7 +981,7 @@ func (mp *TxPool) ProcessOrphans(acceptedTx *btcutil.Tx) []*btcutil.Tx {
|
||||||
// the passed one being accepted.
|
// the passed one being accepted.
|
||||||
//
|
//
|
||||||
// This function is safe for concurrent access.
|
// This function is safe for concurrent access.
|
||||||
func (mp *TxPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool) ([]*btcutil.Tx, error) {
|
func (mp *TxPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool) ([]*TxDesc, error) {
|
||||||
log.Tracef("Processing transaction %v", tx.Hash())
|
log.Tracef("Processing transaction %v", tx.Hash())
|
||||||
|
|
||||||
// Protect concurrent access.
|
// Protect concurrent access.
|
||||||
|
@ -985,7 +989,7 @@ func (mp *TxPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool
|
||||||
defer mp.mtx.Unlock()
|
defer mp.mtx.Unlock()
|
||||||
|
|
||||||
// Potentially accept the transaction to the memory pool.
|
// Potentially accept the transaction to the memory pool.
|
||||||
missingParents, err := mp.maybeAcceptTransaction(tx, true, rateLimit,
|
missingParents, txD, err := mp.maybeAcceptTransaction(tx, true, rateLimit,
|
||||||
true)
|
true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -997,11 +1001,11 @@ func (mp *TxPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool
|
||||||
// are now available) and repeat for those accepted
|
// are now available) and repeat for those accepted
|
||||||
// transactions until there are no more.
|
// transactions until there are no more.
|
||||||
newTxs := mp.processOrphans(tx)
|
newTxs := mp.processOrphans(tx)
|
||||||
acceptedTxs := make([]*btcutil.Tx, len(newTxs)+1)
|
acceptedTxs := make([]*TxDesc, len(newTxs)+1)
|
||||||
|
|
||||||
// Add the parent transaction first so remote nodes
|
// Add the parent transaction first so remote nodes
|
||||||
// do not add orphans.
|
// do not add orphans.
|
||||||
acceptedTxs[0] = tx
|
acceptedTxs[0] = txD
|
||||||
copy(acceptedTxs[1:], newTxs)
|
copy(acceptedTxs[1:], newTxs)
|
||||||
|
|
||||||
return acceptedTxs, nil
|
return acceptedTxs, nil
|
||||||
|
|
|
@ -442,10 +442,10 @@ func TestSimpleOrphanChain(t *testing.T) {
|
||||||
"length does not match expected -- got %d, want %d",
|
"length does not match expected -- got %d, want %d",
|
||||||
len(acceptedTxns), len(chainedTxns))
|
len(acceptedTxns), len(chainedTxns))
|
||||||
}
|
}
|
||||||
for _, tx := range acceptedTxns {
|
for _, txD := range acceptedTxns {
|
||||||
// Ensure the transaction is no longer in the orphan pool, is
|
// Ensure the transaction is no longer in the orphan pool, is
|
||||||
// now in the transaction pool, and is reported as available.
|
// now in the transaction pool, and is reported as available.
|
||||||
testPoolMembership(tc, tx, false, true)
|
testPoolMembership(tc, txD.Tx, false, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,10 +784,10 @@ func TestMultiInputOrphanDoubleSpend(t *testing.T) {
|
||||||
"length does not match expected -- got %d, want %d",
|
"length does not match expected -- got %d, want %d",
|
||||||
len(acceptedTxns), maxOrphans)
|
len(acceptedTxns), maxOrphans)
|
||||||
}
|
}
|
||||||
for _, tx := range acceptedTxns {
|
for _, txD := range acceptedTxns {
|
||||||
// Ensure the transaction is no longer in the orphan pool, is
|
// Ensure the transaction is no longer in the orphan pool, is
|
||||||
// in the transaction pool, and is reported as available.
|
// in the transaction pool, and is reported as available.
|
||||||
testPoolMembership(tc, tx, false, true)
|
testPoolMembership(tc, txD.Tx, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the double spending orphan is no longer in the orphan pool and
|
// Ensure the double spending orphan is no longer in the orphan pool and
|
||||||
|
|
16
server.go
16
server.go
|
@ -972,18 +972,18 @@ func (s *server) RemoveRebroadcastInventory(iv *wire.InvVect) {
|
||||||
// both websocket and getblocktemplate long poll clients of the passed
|
// both websocket and getblocktemplate long poll clients of the passed
|
||||||
// transactions. This function should be called whenever new transactions
|
// transactions. This function should be called whenever new transactions
|
||||||
// are added to the mempool.
|
// are added to the mempool.
|
||||||
func (s *server) AnnounceNewTransactions(newTxs []*btcutil.Tx) {
|
func (s *server) AnnounceNewTransactions(newTxs []*mempool.TxDesc) {
|
||||||
// Generate and relay inventory vectors for all newly accepted
|
// Generate and relay inventory vectors for all newly accepted
|
||||||
// transactions into the memory pool due to the original being
|
// transactions into the memory pool due to the original being
|
||||||
// accepted.
|
// accepted.
|
||||||
for _, tx := range newTxs {
|
for _, txD := range newTxs {
|
||||||
// Generate the inventory vector and relay it.
|
// Generate the inventory vector and relay it.
|
||||||
iv := wire.NewInvVect(wire.InvTypeTx, tx.Hash())
|
iv := wire.NewInvVect(wire.InvTypeTx, txD.Tx.Hash())
|
||||||
s.RelayInventory(iv, tx)
|
s.RelayInventory(iv, txD)
|
||||||
|
|
||||||
if s.rpcServer != nil {
|
if s.rpcServer != nil {
|
||||||
// Notify websocket clients about mempool transactions.
|
// Notify websocket clients about mempool transactions.
|
||||||
s.rpcServer.ntfnMgr.NotifyMempoolTx(tx, true)
|
s.rpcServer.ntfnMgr.NotifyMempoolTx(txD.Tx, true)
|
||||||
|
|
||||||
// Potentially notify any getblocktemplate long poll clients
|
// Potentially notify any getblocktemplate long poll clients
|
||||||
// about stale block templates due to the new transaction.
|
// about stale block templates due to the new transaction.
|
||||||
|
@ -1319,14 +1319,14 @@ func (s *server) handleRelayInvMsg(state *peerState, msg relayMsg) {
|
||||||
// Don't relay the transaction if there is a bloom
|
// Don't relay the transaction if there is a bloom
|
||||||
// filter loaded and the transaction doesn't match it.
|
// filter loaded and the transaction doesn't match it.
|
||||||
if sp.filter.IsLoaded() {
|
if sp.filter.IsLoaded() {
|
||||||
tx, ok := msg.data.(*btcutil.Tx)
|
txD, ok := msg.data.(*mempool.TxDesc)
|
||||||
if !ok {
|
if !ok {
|
||||||
peerLog.Warnf("Underlying data for tx" +
|
peerLog.Warnf("Underlying data for tx" +
|
||||||
" inv relay is not a transaction")
|
" inv relay is not a *mempool.TxDesc")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !sp.filter.MatchTxAndUpdate(tx) {
|
if !sp.filter.MatchTxAndUpdate(txD.Tx) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue