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)
|
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,
|
transaction: Transaction,
|
||||||
blockHashOpt: Option[DoubleSha256DigestBE]): Future[
|
blockHashOpt: Option[DoubleSha256DigestBE]): Future[
|
||||||
Vector[SpendingInfoDb]] = {
|
Vector[SpendingInfoDb]] = {
|
||||||
@ -272,21 +275,9 @@ private[wallet] trait TransactionProcessing extends WalletLogger {
|
|||||||
insertTransaction(transaction, blockHashOpt)
|
insertTransaction(transaction, blockHashOpt)
|
||||||
else Future.unit
|
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
|
processed <- Future
|
||||||
.sequence {
|
.sequence {
|
||||||
outputsToUse.map(markAsSpent(_, transaction.txIdBE))
|
outputsBeingSpent.map(markAsSpent(_, transaction.txIdBE))
|
||||||
}
|
}
|
||||||
.map(_.toVector.flatten)
|
.map(_.toVector.flatten)
|
||||||
|
|
||||||
@ -309,7 +300,7 @@ private[wallet] trait TransactionProcessing extends WalletLogger {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
incoming <- processIncomingUtxos(transaction, blockHashOpt, newTags)
|
incoming <- processIncomingUtxos(transaction, blockHashOpt, newTags)
|
||||||
outgoing <- processOutgoingUtxos(transaction, blockHashOpt)
|
outgoing <- processSpentUtxos(transaction, blockHashOpt)
|
||||||
_ <- walletCallbacks.executeOnTransactionProcessed(logger, transaction)
|
_ <- walletCallbacks.executeOnTransactionProcessed(logger, transaction)
|
||||||
} yield {
|
} yield {
|
||||||
ProcessTxResult(incoming, outgoing)
|
ProcessTxResult(incoming, outgoing)
|
||||||
@ -335,17 +326,25 @@ private[wallet] trait TransactionProcessing extends WalletLogger {
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
s"Marked utxo=${updated.toHumanReadableString} as state=${updated.state}"))
|
s"Marked utxo=${updated.toHumanReadableString} as state=${updated.state}"))
|
||||||
updatedF.map(Some(_))
|
updatedF.map(Some(_))
|
||||||
case TxoState.Reserved | TxoState.PendingConfirmationsSpent |
|
case TxoState.Reserved =>
|
||||||
BroadcastSpent =>
|
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 =
|
val updated =
|
||||||
out.copyWithSpendingTxId(spendingTxId)
|
out.copyWithSpendingTxId(spendingTxId)
|
||||||
val updatedF =
|
val updatedF = spendingInfoDAO.update(updated)
|
||||||
spendingInfoDAO.update(updated)
|
|
||||||
updatedF.map(Some(_))
|
updatedF.map(Some(_))
|
||||||
case TxoState.ImmatureCoinbase =>
|
case TxoState.ImmatureCoinbase =>
|
||||||
Future.failed(new RuntimeException(
|
Future.failed(new RuntimeException(
|
||||||
s"Attempting to spend an ImmatureCoinbase ${out.outPoint.hex}, this should not be possible until it is confirmed."))
|
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)) {
|
if (!out.spendingTxIdOpt.contains(spendingTxId)) {
|
||||||
Future.failed(new RuntimeException(
|
Future.failed(new RuntimeException(
|
||||||
s"Attempted to mark an already spent utxo ${out.outPoint.hex} with a new spending tx ${spendingTxId.hex}"))
|
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