diff --git a/mempool.go b/mempool.go index 7cbda1924..c578bca13 100644 --- a/mempool.go +++ b/mempool.go @@ -47,7 +47,7 @@ type TxDesc struct { Added time.Time // Time when added to pool. Height int32 // Blockheight when added to pool. Fee int64 // Transaction fees. - startingPriority float64 // Priority when added to the pool. + StartingPriority float64 // Priority when added to the pool. } // txMemPool is used as a source of transactions that need to be mined into @@ -374,14 +374,15 @@ func (mp *txMemPool) RemoveDoubleSpends(tx *btcutil.Tx) { // helper for maybeAcceptTransaction. // // This function MUST be called with the mempool lock held (for writes). -func (mp *txMemPool) addTransaction(tx *btcutil.Tx, height int32, fee int64) { +func (mp *txMemPool) addTransaction(txStore blockchain.TxStore, tx *btcutil.Tx, height int32, fee int64) { // Add the transaction to the pool and mark the referenced outpoints // as spent by the pool. mp.pool[*tx.Sha()] = &TxDesc{ - Tx: tx, - Added: time.Now(), - Height: height, - Fee: fee, + Tx: tx, + Added: time.Now(), + Height: height, + Fee: fee, + StartingPriority: calcPriority(tx.MsgTx(), txStore, height), } for _, txIn := range tx.MsgTx().TxIn { mp.outpoints[txIn.PreviousOutPoint] = tx @@ -462,29 +463,6 @@ func (mp *txMemPool) indexScriptAddressToTx(pkScript []byte, tx *btcutil.Tx) err return nil } -// StartingPriority calculates the priority of this tx descriptor's underlying -// transaction relative to when it was first added to the mempool. The result -// is lazily computed and then cached for subsequent function calls. -func (txD *TxDesc) StartingPriority(txStore blockchain.TxStore) float64 { - // Return our cached result. - if txD.startingPriority != float64(0) { - return txD.startingPriority - } - - // Compute our starting priority caching the result. - inputAge := calcInputValueAge(txD, txStore, txD.Height) - txD.startingPriority = calcPriority(txD.Tx, inputAge) - - return txD.startingPriority -} - -// CurrentPriority calculates the current priority of this tx descriptor's -// underlying transaction relative to the next block height. -func (txD *TxDesc) CurrentPriority(txStore blockchain.TxStore, nextBlockHeight int32) float64 { - inputAge := calcInputValueAge(txD, txStore, nextBlockHeight) - return calcPriority(txD.Tx, inputAge) -} - // checkPoolDoubleSpend checks whether or not the passed transaction is // attempting to spend coins already spent by other transactions in the pool. // Note it does not check for double spends against transactions already in the @@ -772,13 +750,8 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo // memory pool from blocks that have been disconnected during a reorg // are exempted. if isNew && !cfg.NoRelayPriority && txFee < minFee { - txD := &TxDesc{ - Tx: tx, - Added: time.Now(), - Height: curHeight, - Fee: txFee, - } - currentPriority := txD.CurrentPriority(txStore, nextBlockHeight) + currentPriority := calcPriority(tx.MsgTx(), txStore, + nextBlockHeight) if currentPriority <= minHighPriority { str := fmt.Sprintf("transaction %v has insufficient "+ "priority (%g <= %g)", txHash, @@ -823,7 +796,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo } // Add to transaction pool. - mp.addTransaction(tx, curHeight, txFee) + mp.addTransaction(txStore, tx, curHeight, txFee) txmpLog.Debugf("Accepted transaction %v (pool size: %v)", txHash, len(mp.pool)) diff --git a/mining.go b/mining.go index b5445e68c..afa9fa579 100644 --- a/mining.go +++ b/mining.go @@ -540,7 +540,7 @@ mempoolLoop: // Calculate the final transaction priority using the input // value age sum as well as the adjusted transaction size. The // formula is: sum(inputValue * inputAge) / adjustedTxSize - prioItem.priority = txDesc.CurrentPriority(txStore, nextBlockHeight) + prioItem.priority = calcPriority(tx.MsgTx(), txStore, nextBlockHeight) // Calculate the fee in Satoshi/kB. txSize := tx.MsgTx().SerializeSize() diff --git a/policy.go b/policy.go index e8ddd6bf3..d585bc4d4 100644 --- a/policy.go +++ b/policy.go @@ -79,7 +79,7 @@ func calcMinRequiredTxRelayFee(serializedSize int64, minRelayTxFee btcutil.Amoun // of each of its input values multiplied by their age (# of confirmations). // Thus, the final formula for the priority is: // sum(inputValue * inputAge) / adjustedTxSize -func calcPriority(tx *btcutil.Tx, inputValueAge float64) float64 { +func calcPriority(tx *wire.MsgTx, txStore blockchain.TxStore, nextBlockHeight int32) float64 { // In order to encourage spending multiple old unspent transaction // outputs thereby reducing the total set, don't count the constant // overhead for each input as well as enough bytes of the signature @@ -101,16 +101,17 @@ func calcPriority(tx *btcutil.Tx, inputValueAge float64) float64 { // // Thus 1 + 73 + 1 + 1 + 33 + 1 = 110 overhead := 0 - for _, txIn := range tx.MsgTx().TxIn { + for _, txIn := range tx.TxIn { // Max inputs + size can't possibly overflow here. overhead += 41 + minInt(110, len(txIn.SignatureScript)) } - serializedTxSize := tx.MsgTx().SerializeSize() + serializedTxSize := tx.SerializeSize() if overhead >= serializedTxSize { return 0.0 } + inputValueAge := calcInputValueAge(tx, txStore, nextBlockHeight) return inputValueAge / float64(serializedTxSize-overhead) } @@ -120,9 +121,9 @@ func calcPriority(tx *btcutil.Tx, inputValueAge float64) float64 { // age is the sum of this value for each txin. Any inputs to the transaction // which are currently in the mempool and hence not mined into a block yet, // contribute no additional input age to the transaction. -func calcInputValueAge(txDesc *TxDesc, txStore blockchain.TxStore, nextBlockHeight int32) float64 { +func calcInputValueAge(tx *wire.MsgTx, txStore blockchain.TxStore, nextBlockHeight int32) float64 { var totalInputAge float64 - for _, txIn := range txDesc.Tx.MsgTx().TxIn { + for _, txIn := range tx.TxIn { originHash := &txIn.PreviousOutPoint.Hash originIndex := txIn.PreviousOutPoint.Index diff --git a/rpcserver.go b/rpcserver.go index 192523fc1..47e62f8dd 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2404,15 +2404,15 @@ func handleGetRawMempool(s *rpcServer, cmd interface{}, closeChan <-chan struct{ mp.RLock() defer mp.RUnlock() for _, desc := range descs { - // Calculate the starting and current priority from the - // the tx's inputs. Use zeros if one or more of the - // input transactions can't be found for some reason. - var startingPriority, currentPriority float64 - inputTxs, err := mp.fetchInputTransactions(desc.Tx, false) + // Calculate the current priority from the the tx's + // inputs. Use zero if one or more of the input + // transactions can't be found for some reason. + tx := desc.Tx + var currentPriority float64 + inputTxs, err := mp.fetchInputTransactions(tx, false) if err == nil { - startingPriority = desc.StartingPriority(inputTxs) - currentPriority = desc.CurrentPriority(inputTxs, - newestHeight+1) + currentPriority = calcPriority(tx.MsgTx(), + inputTxs, newestHeight+1) } mpd := &btcjson.GetRawMempoolVerboseResult{ @@ -2420,7 +2420,7 @@ func handleGetRawMempool(s *rpcServer, cmd interface{}, closeChan <-chan struct{ Fee: btcutil.Amount(desc.Fee).ToBTC(), Time: desc.Added.Unix(), Height: int64(desc.Height), - StartingPriority: startingPriority, + StartingPriority: desc.StartingPriority, CurrentPriority: currentPriority, Depends: make([]string, 0), }