diff --git a/wallet/src/main/scala/org/bitcoins/wallet/internal/TransactionProcessing.scala b/wallet/src/main/scala/org/bitcoins/wallet/internal/TransactionProcessing.scala index 5df88bcb7a..48de150d6c 100644 --- a/wallet/src/main/scala/org/bitcoins/wallet/internal/TransactionProcessing.scala +++ b/wallet/src/main/scala/org/bitcoins/wallet/internal/TransactionProcessing.scala @@ -260,7 +260,10 @@ private[wallet] trait TransactionProcessing extends WalletLogger { Future.sequence(processedVec) } - protected def processOutgoingUtxos( + /** Searches for outputs on the given transaction that are + * being spent from our wallet + */ + protected def processSpentUtxos( transaction: Transaction, blockHashOpt: Option[DoubleSha256DigestBE]): Future[ Vector[SpendingInfoDb]] = { @@ -272,21 +275,9 @@ private[wallet] trait TransactionProcessing extends WalletLogger { insertTransaction(transaction, blockHashOpt) else Future.unit - // unreserved outputs now they are in a block - outputsToUse = blockHashOpt match { - case Some(_) => - outputsBeingSpent.map { out => - if (out.state == TxoState.Reserved) - out.copyWithState(TxoState.PendingConfirmationsReceived) - else out - } - case None => - outputsBeingSpent - } - processed <- Future .sequence { - outputsToUse.map(markAsSpent(_, transaction.txIdBE)) + outputsBeingSpent.map(markAsSpent(_, transaction.txIdBE)) } .map(_.toVector.flatten) @@ -309,7 +300,7 @@ private[wallet] trait TransactionProcessing extends WalletLogger { for { incoming <- processIncomingUtxos(transaction, blockHashOpt, newTags) - outgoing <- processOutgoingUtxos(transaction, blockHashOpt) + outgoing <- processSpentUtxos(transaction, blockHashOpt) _ <- walletCallbacks.executeOnTransactionProcessed(logger, transaction) } yield { ProcessTxResult(incoming, outgoing) @@ -335,17 +326,25 @@ private[wallet] trait TransactionProcessing extends WalletLogger { logger.debug( s"Marked utxo=${updated.toHumanReadableString} as state=${updated.state}")) updatedF.map(Some(_)) - case TxoState.Reserved | TxoState.PendingConfirmationsSpent | - BroadcastSpent => + case TxoState.Reserved => + val updated = + out + .copyWithSpendingTxId(spendingTxId) + .copyWithState(state = BroadcastSpent) + val updatedF = spendingInfoDAO.update(updated) + updatedF.map(Some(_)) + case TxoState.BroadcastSpent => + logger.warn( + s"Updating the spendingTxId of a transaction that is already spent, " + + s"old state=${TxoState.BroadcastSpent} old spendingTxId=${out.spendingTxIdOpt} new spendingTxId=${spendingTxId}") val updated = out.copyWithSpendingTxId(spendingTxId) - val updatedF = - spendingInfoDAO.update(updated) + val updatedF = spendingInfoDAO.update(updated) updatedF.map(Some(_)) case TxoState.ImmatureCoinbase => Future.failed(new RuntimeException( s"Attempting to spend an ImmatureCoinbase ${out.outPoint.hex}, this should not be possible until it is confirmed.")) - case TxoState.ConfirmedSpent => + case TxoState.ConfirmedSpent | TxoState.PendingConfirmationsSpent => if (!out.spendingTxIdOpt.contains(spendingTxId)) { Future.failed(new RuntimeException( s"Attempted to mark an already spent utxo ${out.outPoint.hex} with a new spending tx ${spendingTxId.hex}"))