mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-18 21:34:39 +01:00
2021 04 18 Reset txo state when overwriting spendingTxId (#2919)
* Add invariant to spendingInfoDb to that requires if the spendinginfodb is in a TxoState.spentStates, the SpendingInfoDb.spendingTxIdOpt is defined * Remove unused SpendingInfoDAO.updateTxoState() * Fix bug that doesn't revert TxoState to TxoState.BroadcastSpent when overwriting the spendingTxId * Remove unecessary transition from TxoState.Reserved -> TxoState.PendingConfirmationsReceived inside of processSpentUtxos() * Update TransactionProcessing.markAsSpent() to treat TxoState.PendingConfirmationsSpent and TxoState.ConfirmedSpent the same way * Remove unecessary comment
This commit is contained in:
parent
27992ed37d
commit
13fc3c2b4e
@ -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}"))
|
||||
|
Loading…
Reference in New Issue
Block a user