mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
Add Broadcast TxoState (#2735)
* Add broadcast TxoState * Update scaladoc
This commit is contained in:
parent
1daba85ddf
commit
12bff309c2
@ -19,7 +19,12 @@ object TxoState extends StringFactory[TxoState] {
|
|||||||
*/
|
*/
|
||||||
final case object ImmatureCoinbase extends TxoState
|
final case object ImmatureCoinbase extends TxoState
|
||||||
|
|
||||||
/** Means we have received funds to this utxo, but they are not confirmed */
|
/** Means we have received funds to this utxo, and they have not been confirmed in a block */
|
||||||
|
final case object BroadcastReceived extends ReceivedState
|
||||||
|
|
||||||
|
/** Means we have received funds to this utxo, and they have some confirmations but
|
||||||
|
* have not reached our confirmation threshold
|
||||||
|
*/
|
||||||
final case object PendingConfirmationsReceived extends ReceivedState
|
final case object PendingConfirmationsReceived extends ReceivedState
|
||||||
|
|
||||||
/** Means we have received funds and they are fully confirmed for this utxo */
|
/** Means we have received funds and they are fully confirmed for this utxo */
|
||||||
@ -28,33 +33,49 @@ object TxoState extends StringFactory[TxoState] {
|
|||||||
/** Means we have not spent this utxo yet, but will be used in a future transaction */
|
/** Means we have not spent this utxo yet, but will be used in a future transaction */
|
||||||
final case object Reserved extends SpentState
|
final case object Reserved extends SpentState
|
||||||
|
|
||||||
/** Means we have spent this utxo, but it is not fully confirmed */
|
/** Means we have spent this utxo, and they have not been confirmed in a block */
|
||||||
|
final case object BroadcastSpent extends SpentState
|
||||||
|
|
||||||
|
/** Means we have spent this utxo, and they have some confirmations but
|
||||||
|
* have not reached our confirmation threshold
|
||||||
|
*/
|
||||||
final case object PendingConfirmationsSpent extends SpentState
|
final case object PendingConfirmationsSpent extends SpentState
|
||||||
|
|
||||||
/** Means we have spent this utxo, and it is fully confirmed */
|
/** Means we have spent this utxo, and it is fully confirmed */
|
||||||
final case object ConfirmedSpent extends SpentState
|
final case object ConfirmedSpent extends SpentState
|
||||||
|
|
||||||
val pendingConfStates: Set[TxoState] =
|
val pendingConfStates: Set[TxoState] =
|
||||||
Set(TxoState.ImmatureCoinbase,
|
Set(BroadcastSpent,
|
||||||
TxoState.PendingConfirmationsReceived,
|
BroadcastReceived,
|
||||||
TxoState.PendingConfirmationsSpent)
|
ImmatureCoinbase,
|
||||||
|
PendingConfirmationsReceived,
|
||||||
|
PendingConfirmationsSpent)
|
||||||
|
|
||||||
val confirmedStates: Set[TxoState] =
|
val confirmedStates: Set[TxoState] =
|
||||||
Set(TxoState.ConfirmedReceived, TxoState.ConfirmedSpent)
|
Set(TxoState.ConfirmedReceived, TxoState.ConfirmedSpent)
|
||||||
|
|
||||||
val receivedStates: Set[TxoState] =
|
val receivedStates: Set[TxoState] =
|
||||||
Set(PendingConfirmationsReceived, ConfirmedReceived)
|
Set(PendingConfirmationsReceived, ConfirmedReceived, BroadcastReceived)
|
||||||
|
|
||||||
val spentStates: Set[TxoState] =
|
val spentStates: Set[TxoState] =
|
||||||
Set(PendingConfirmationsSpent, TxoState.ConfirmedSpent, Reserved)
|
Set(PendingConfirmationsSpent,
|
||||||
|
TxoState.ConfirmedSpent,
|
||||||
|
Reserved,
|
||||||
|
BroadcastSpent)
|
||||||
|
|
||||||
val all: Vector[TxoState] = Vector(DoesNotExist,
|
val broadcastStates: Set[TxoState] = Set(BroadcastReceived, BroadcastSpent)
|
||||||
ImmatureCoinbase,
|
|
||||||
PendingConfirmationsReceived,
|
val all: Vector[TxoState] = Vector(
|
||||||
ConfirmedReceived,
|
DoesNotExist,
|
||||||
Reserved,
|
ImmatureCoinbase,
|
||||||
PendingConfirmationsSpent,
|
BroadcastReceived,
|
||||||
ConfirmedSpent)
|
PendingConfirmationsReceived,
|
||||||
|
ConfirmedReceived,
|
||||||
|
Reserved,
|
||||||
|
BroadcastSpent,
|
||||||
|
PendingConfirmationsSpent,
|
||||||
|
ConfirmedSpent
|
||||||
|
)
|
||||||
|
|
||||||
override def fromStringOpt(str: String): Option[TxoState] = {
|
override def fromStringOpt(str: String): Option[TxoState] = {
|
||||||
all.find(state => str.toLowerCase() == state.toString.toLowerCase)
|
all.find(state => str.toLowerCase() == state.toString.toLowerCase)
|
||||||
|
@ -25,7 +25,7 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
withFundedWalletAndBitcoind(test, getBIP39PasswordOpt())
|
withFundedWalletAndBitcoind(test, getBIP39PasswordOpt())
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "track a utxo state change to pending spent" in { param =>
|
it should "track a utxo state change to broadcast spent" in { param =>
|
||||||
val WalletWithBitcoindRpc(wallet, _) = param
|
val WalletWithBitcoindRpc(wallet, _) = param
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -35,7 +35,7 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
updatedCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
updatedCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
||||||
newTransactions <- wallet.listTransactions()
|
newTransactions <- wallet.listTransactions()
|
||||||
} yield {
|
} yield {
|
||||||
assert(updatedCoins.forall(_.state == TxoState.PendingConfirmationsSpent))
|
assert(updatedCoins.forall(_.state == TxoState.BroadcastSpent))
|
||||||
assert(updatedCoins.forall(_.spendingTxIdOpt.contains(tx.txIdBE)))
|
assert(updatedCoins.forall(_.spendingTxIdOpt.contains(tx.txIdBE)))
|
||||||
assert(!oldTransactions.map(_.transaction).contains(tx))
|
assert(!oldTransactions.map(_.transaction).contains(tx))
|
||||||
assert(newTransactions.map(_.transaction).contains(tx))
|
assert(newTransactions.map(_.transaction).contains(tx))
|
||||||
@ -51,7 +51,7 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
|
|
||||||
updatedCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
updatedCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
||||||
newTransactions <- wallet.listTransactions()
|
newTransactions <- wallet.listTransactions()
|
||||||
_ = assert(updatedCoins.forall(_.state == PendingConfirmationsSpent))
|
_ = assert(updatedCoins.forall(_.state == BroadcastSpent))
|
||||||
_ = assert(!oldTransactions.map(_.transaction).contains(tx))
|
_ = assert(!oldTransactions.map(_.transaction).contains(tx))
|
||||||
_ = assert(newTransactions.map(_.transaction).contains(tx))
|
_ = assert(newTransactions.map(_.transaction).contains(tx))
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
hash <- bitcoind.getBestBlockHash
|
hash <- bitcoind.getBestBlockHash
|
||||||
_ <- wallet.processTransaction(tx, Some(hash))
|
_ <- wallet.processTransaction(tx, Some(hash))
|
||||||
|
|
||||||
pendingCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
|
||||||
_ <- wallet.updateUtxoPendingStates()
|
_ <- wallet.updateUtxoPendingStates()
|
||||||
|
pendingCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
||||||
_ = assert(pendingCoins.forall(_.state == PendingConfirmationsSpent))
|
_ = assert(pendingCoins.forall(_.state == PendingConfirmationsSpent))
|
||||||
|
|
||||||
// Put confirmations on top of the tx's block
|
// Put confirmations on top of the tx's block
|
||||||
@ -85,14 +85,14 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
Some(SatoshisPerByte.one))
|
Some(SatoshisPerByte.one))
|
||||||
|
|
||||||
coins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
coins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
||||||
_ = assert(coins.forall(_.state == PendingConfirmationsSpent))
|
_ = assert(coins.forall(_.state == BroadcastSpent))
|
||||||
_ = assert(coins.forall(_.spendingTxIdOpt.contains(tx.txIdBE)))
|
_ = assert(coins.forall(_.spendingTxIdOpt.contains(tx.txIdBE)))
|
||||||
|
|
||||||
rbf <- wallet.bumpFeeRBF(tx.txIdBE, SatoshisPerByte.fromLong(3))
|
rbf <- wallet.bumpFeeRBF(tx.txIdBE, SatoshisPerByte.fromLong(3))
|
||||||
_ <- wallet.processTransaction(rbf, None)
|
_ <- wallet.processTransaction(rbf, None)
|
||||||
rbfCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(rbf)
|
rbfCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(rbf)
|
||||||
} yield {
|
} yield {
|
||||||
assert(rbfCoins.forall(_.state == PendingConfirmationsSpent))
|
assert(rbfCoins.forall(_.state == BroadcastSpent))
|
||||||
assert(rbfCoins.forall(_.spendingTxIdOpt.contains(rbf.txIdBE)))
|
assert(rbfCoins.forall(_.spendingTxIdOpt.contains(rbf.txIdBE)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
|
|
||||||
updatedCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
updatedCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
||||||
newTransactions <- wallet.listTransactions()
|
newTransactions <- wallet.listTransactions()
|
||||||
_ = assert(updatedCoins.forall(_.state == PendingConfirmationsSpent))
|
_ = assert(updatedCoins.forall(_.state == BroadcastSpent))
|
||||||
_ = assert(!oldTransactions.map(_.transaction).contains(tx))
|
_ = assert(!oldTransactions.map(_.transaction).contains(tx))
|
||||||
_ = assert(newTransactions.map(_.transaction).contains(tx))
|
_ = assert(newTransactions.map(_.transaction).contains(tx))
|
||||||
|
|
||||||
@ -138,8 +138,8 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
hash <- bitcoind.getBestBlockHash
|
hash <- bitcoind.getBestBlockHash
|
||||||
_ <- wallet.processTransaction(tx, Some(hash))
|
_ <- wallet.processTransaction(tx, Some(hash))
|
||||||
|
|
||||||
pendingCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
|
||||||
_ <- wallet.updateUtxoPendingStates()
|
_ <- wallet.updateUtxoPendingStates()
|
||||||
|
pendingCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
|
||||||
_ = assert(pendingCoins.forall(_.state == PendingConfirmationsSpent))
|
_ = assert(pendingCoins.forall(_.state == PendingConfirmationsSpent))
|
||||||
|
|
||||||
// Put confirmations on top of the tx's block
|
// Put confirmations on top of the tx's block
|
||||||
@ -191,7 +191,7 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
} yield res
|
} yield res
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "track a utxo state change to pending received" in { param =>
|
it should "track a utxo state change to broadcast received" in { param =>
|
||||||
val WalletWithBitcoindRpc(wallet, bitcoind) = param
|
val WalletWithBitcoindRpc(wallet, bitcoind) = param
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -210,9 +210,44 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
updatedCoin <-
|
updatedCoin <-
|
||||||
wallet.spendingInfoDAO.findByScriptPubKey(addr.scriptPubKey)
|
wallet.spendingInfoDAO.findByScriptPubKey(addr.scriptPubKey)
|
||||||
newTransactions <- wallet.listTransactions()
|
newTransactions <- wallet.listTransactions()
|
||||||
|
} yield {
|
||||||
|
assert(updatedCoin.forall(_.state == TxoState.BroadcastReceived))
|
||||||
|
assert(!oldTransactions.map(_.transaction).contains(tx))
|
||||||
|
assert(newTransactions.map(_.transaction).contains(tx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it should "track a utxo state change to pending received" in { param =>
|
||||||
|
val WalletWithBitcoindRpc(wallet, bitcoind) = param
|
||||||
|
|
||||||
|
for {
|
||||||
|
oldTransactions <- wallet.listTransactions()
|
||||||
|
addr <- wallet.getNewAddress()
|
||||||
|
|
||||||
|
txId <- bitcoind.sendToAddress(addr, Satoshis(3000))
|
||||||
|
tx <- bitcoind.getRawTransactionRaw(txId)
|
||||||
|
_ <- wallet.processOurTransaction(transaction = tx,
|
||||||
|
feeRate = SatoshisPerByte(Satoshis(3)),
|
||||||
|
inputAmount = Satoshis(4000),
|
||||||
|
sentAmount = Satoshis(3000),
|
||||||
|
blockHashOpt = None,
|
||||||
|
newTags = Vector.empty)
|
||||||
|
|
||||||
|
updatedCoin <-
|
||||||
|
wallet.spendingInfoDAO.findByScriptPubKey(addr.scriptPubKey)
|
||||||
|
newTransactions <- wallet.listTransactions()
|
||||||
|
_ = assert(updatedCoin.forall(_.state == TxoState.BroadcastReceived))
|
||||||
|
|
||||||
|
hash <- bitcoind.getNewAddress
|
||||||
|
.flatMap(bitcoind.generateToAddress(1, _))
|
||||||
|
.map(_.head)
|
||||||
|
_ <- wallet.processTransaction(tx, Some(hash))
|
||||||
|
|
||||||
|
pendingCoins <-
|
||||||
|
wallet.spendingInfoDAO.findByScriptPubKey(addr.scriptPubKey)
|
||||||
} yield {
|
} yield {
|
||||||
assert(
|
assert(
|
||||||
updatedCoin.forall(_.state == TxoState.PendingConfirmationsReceived))
|
pendingCoins.forall(_.state == TxoState.PendingConfirmationsReceived))
|
||||||
assert(!oldTransactions.map(_.transaction).contains(tx))
|
assert(!oldTransactions.map(_.transaction).contains(tx))
|
||||||
assert(newTransactions.map(_.transaction).contains(tx))
|
assert(newTransactions.map(_.transaction).contains(tx))
|
||||||
}
|
}
|
||||||
@ -376,5 +411,4 @@ class UTXOLifeCycleTest extends BitcoinSWalletTest {
|
|||||||
assert(newTransactions.map(_.transaction).contains(tx))
|
assert(newTransactions.map(_.transaction).contains(tx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ class WalletIntegrationTest extends BitcoinSWalletTest {
|
|||||||
_ <- wallet.processTransaction(signedTx, None)
|
_ <- wallet.processTransaction(signedTx, None)
|
||||||
newCoinbaseUtxos <- wallet.listUtxos(TxoState.ImmatureCoinbase)
|
newCoinbaseUtxos <- wallet.listUtxos(TxoState.ImmatureCoinbase)
|
||||||
_ = assert(newCoinbaseUtxos.isEmpty)
|
_ = assert(newCoinbaseUtxos.isEmpty)
|
||||||
spentUtxos <- wallet.listUtxos(TxoState.PendingConfirmationsSpent)
|
spentUtxos <- wallet.listUtxos(TxoState.BroadcastSpent)
|
||||||
_ = assert(spentUtxos.size == 1)
|
_ = assert(spentUtxos.size == 1)
|
||||||
|
|
||||||
// Assert spending tx valid to bitcoind
|
// Assert spending tx valid to bitcoind
|
||||||
|
@ -31,10 +31,7 @@ import org.bitcoins.core.wallet.keymanagement.{
|
|||||||
KeyManagerParams,
|
KeyManagerParams,
|
||||||
KeyManagerUnlockError
|
KeyManagerUnlockError
|
||||||
}
|
}
|
||||||
import org.bitcoins.core.wallet.utxo.TxoState.{
|
import org.bitcoins.core.wallet.utxo.TxoState._
|
||||||
ConfirmedReceived,
|
|
||||||
PendingConfirmationsReceived
|
|
||||||
}
|
|
||||||
import org.bitcoins.core.wallet.utxo._
|
import org.bitcoins.core.wallet.utxo._
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
import org.bitcoins.keymanager.bip39.{BIP39KeyManager, BIP39LockedKeyManager}
|
import org.bitcoins.keymanager.bip39.{BIP39KeyManager, BIP39LockedKeyManager}
|
||||||
@ -267,11 +264,11 @@ abstract class Wallet
|
|||||||
.map { txo =>
|
.map { txo =>
|
||||||
txo.state match {
|
txo.state match {
|
||||||
case TxoState.PendingConfirmationsReceived |
|
case TxoState.PendingConfirmationsReceived |
|
||||||
TxoState.ConfirmedReceived =>
|
TxoState.ConfirmedReceived | TxoState.BroadcastReceived =>
|
||||||
txo.output.value
|
txo.output.value
|
||||||
case TxoState.Reserved | TxoState.PendingConfirmationsSpent |
|
case TxoState.Reserved | TxoState.PendingConfirmationsSpent |
|
||||||
TxoState.ConfirmedSpent | TxoState.DoesNotExist |
|
TxoState.ConfirmedSpent | TxoState.BroadcastSpent |
|
||||||
TxoState.ImmatureCoinbase =>
|
TxoState.DoesNotExist | TxoState.ImmatureCoinbase =>
|
||||||
CurrencyUnits.zero
|
CurrencyUnits.zero
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,10 +304,12 @@ abstract class Wallet
|
|||||||
}
|
}
|
||||||
|
|
||||||
override def getUnconfirmedBalance(): Future[CurrencyUnit] = {
|
override def getUnconfirmedBalance(): Future[CurrencyUnit] = {
|
||||||
filterThenSum(_.state == PendingConfirmationsReceived).map { balance =>
|
filterThenSum(utxo =>
|
||||||
logger.trace(s"Unconfirmed balance=${balance.satoshis}")
|
utxo.state == PendingConfirmationsReceived || utxo.state == BroadcastReceived)
|
||||||
balance
|
.map { balance =>
|
||||||
}
|
logger.trace(s"Unconfirmed balance=${balance.satoshis}")
|
||||||
|
balance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def getUnconfirmedBalance(
|
override def getUnconfirmedBalance(
|
||||||
@ -320,7 +319,7 @@ abstract class Wallet
|
|||||||
} yield {
|
} yield {
|
||||||
val confirmedUtxos = allUnspent.filter { utxo =>
|
val confirmedUtxos = allUnspent.filter { utxo =>
|
||||||
HDAccount.isSameAccount(utxo.privKeyPath.path, account) &&
|
HDAccount.isSameAccount(utxo.privKeyPath.path, account) &&
|
||||||
utxo.state == PendingConfirmationsReceived
|
utxo.state == PendingConfirmationsReceived || utxo.state == BroadcastReceived
|
||||||
}
|
}
|
||||||
confirmedUtxos.foldLeft(CurrencyUnits.zero)(_ + _.output.value)
|
confirmedUtxos.foldLeft(CurrencyUnits.zero)(_ + _.output.value)
|
||||||
}
|
}
|
||||||
@ -328,7 +327,8 @@ abstract class Wallet
|
|||||||
|
|
||||||
override def getUnconfirmedBalance(tag: AddressTag): Future[CurrencyUnit] = {
|
override def getUnconfirmedBalance(tag: AddressTag): Future[CurrencyUnit] = {
|
||||||
spendingInfoDAO.findAllUnspentForTag(tag).map { allUnspent =>
|
spendingInfoDAO.findAllUnspentForTag(tag).map { allUnspent =>
|
||||||
val confirmed = allUnspent.filter(_.state == PendingConfirmationsReceived)
|
val confirmed = allUnspent.filter(utxo =>
|
||||||
|
utxo.state == PendingConfirmationsReceived || utxo.state == BroadcastReceived)
|
||||||
confirmed.foldLeft(CurrencyUnits.zero)(_ + _.output.value)
|
confirmed.foldLeft(CurrencyUnits.zero)(_ + _.output.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import org.bitcoins.core.protocol.blockchain.Block
|
|||||||
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutput}
|
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutput}
|
||||||
import org.bitcoins.core.util.TimeUtil
|
import org.bitcoins.core.util.TimeUtil
|
||||||
import org.bitcoins.core.wallet.fee.FeeUnit
|
import org.bitcoins.core.wallet.fee.FeeUnit
|
||||||
|
import org.bitcoins.core.wallet.utxo.TxoState._
|
||||||
import org.bitcoins.core.wallet.utxo.{AddressTag, TxoState}
|
import org.bitcoins.core.wallet.utxo.{AddressTag, TxoState}
|
||||||
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
|
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
|
||||||
import org.bitcoins.wallet._
|
import org.bitcoins.wallet._
|
||||||
@ -267,10 +268,11 @@ private[wallet] trait TransactionProcessing extends WalletLogger {
|
|||||||
out: SpendingInfoDb,
|
out: SpendingInfoDb,
|
||||||
spendingTxId: DoubleSha256DigestBE): Future[Option[SpendingInfoDb]] = {
|
spendingTxId: DoubleSha256DigestBE): Future[Option[SpendingInfoDb]] = {
|
||||||
out.state match {
|
out.state match {
|
||||||
case TxoState.ConfirmedReceived | TxoState.PendingConfirmationsReceived =>
|
case ConfirmedReceived | PendingConfirmationsReceived |
|
||||||
|
BroadcastReceived =>
|
||||||
val updated =
|
val updated =
|
||||||
out
|
out
|
||||||
.copyWithState(state = TxoState.PendingConfirmationsSpent)
|
.copyWithState(state = BroadcastSpent)
|
||||||
.copyWithSpendingTxId(spendingTxId)
|
.copyWithSpendingTxId(spendingTxId)
|
||||||
val updatedF =
|
val updatedF =
|
||||||
spendingInfoDAO.update(updated)
|
spendingInfoDAO.update(updated)
|
||||||
@ -278,7 +280,8 @@ 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 | TxoState.PendingConfirmationsSpent |
|
||||||
|
BroadcastSpent =>
|
||||||
val updated =
|
val updated =
|
||||||
out.copyWithSpendingTxId(spendingTxId)
|
out.copyWithSpendingTxId(spendingTxId)
|
||||||
val updatedF =
|
val updatedF =
|
||||||
@ -345,7 +348,8 @@ private[wallet] trait TransactionProcessing extends WalletLogger {
|
|||||||
case TxoState.PendingConfirmationsReceived |
|
case TxoState.PendingConfirmationsReceived |
|
||||||
TxoState.ConfirmedReceived |
|
TxoState.ConfirmedReceived |
|
||||||
TxoState.PendingConfirmationsSpent | TxoState.ConfirmedSpent |
|
TxoState.PendingConfirmationsSpent | TxoState.ConfirmedSpent |
|
||||||
TxoState.DoesNotExist | TxoState.ImmatureCoinbase =>
|
TxoState.DoesNotExist | TxoState.ImmatureCoinbase |
|
||||||
|
BroadcastReceived | BroadcastSpent =>
|
||||||
foundTxo
|
foundTxo
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +381,7 @@ private[wallet] trait TransactionProcessing extends WalletLogger {
|
|||||||
Seq[SpendingInfoDb]] = {
|
Seq[SpendingInfoDb]] = {
|
||||||
val stateF: Future[TxoState] = blockHashOpt match {
|
val stateF: Future[TxoState] = blockHashOpt match {
|
||||||
case None =>
|
case None =>
|
||||||
Future.successful(TxoState.PendingConfirmationsReceived)
|
Future.successful(TxoState.BroadcastReceived)
|
||||||
case Some(blockHash) =>
|
case Some(blockHash) =>
|
||||||
chainQueryApi.getNumberOfConfirmations(blockHash).map {
|
chainQueryApi.getNumberOfConfirmations(blockHash).map {
|
||||||
case None =>
|
case None =>
|
||||||
|
@ -116,9 +116,10 @@ private[wallet] trait UtxoHandling extends WalletLogger {
|
|||||||
val blockHashMap = txDbs.map(db => db.txIdBE -> db.blockHashOpt).toMap
|
val blockHashMap = txDbs.map(db => db.txIdBE -> db.blockHashOpt).toMap
|
||||||
val blockHashAndDb = spendingInfoDbs.map { txo =>
|
val blockHashAndDb = spendingInfoDbs.map { txo =>
|
||||||
val txToUse = txo.state match {
|
val txToUse = txo.state match {
|
||||||
case _: ReceivedState | DoesNotExist | ImmatureCoinbase | Reserved =>
|
case _: ReceivedState | DoesNotExist | ImmatureCoinbase |
|
||||||
|
Reserved | BroadcastReceived =>
|
||||||
txo.txid
|
txo.txid
|
||||||
case PendingConfirmationsSpent | ConfirmedSpent =>
|
case PendingConfirmationsSpent | ConfirmedSpent | BroadcastSpent =>
|
||||||
txo.spendingTxIdOpt.get
|
txo.spendingTxIdOpt.get
|
||||||
}
|
}
|
||||||
(blockHashMap(txToUse), txo)
|
(blockHashMap(txToUse), txo)
|
||||||
@ -143,14 +144,14 @@ private[wallet] trait UtxoHandling extends WalletLogger {
|
|||||||
else
|
else
|
||||||
txo.copyWithState(TxoState.PendingConfirmationsReceived)
|
txo.copyWithState(TxoState.PendingConfirmationsReceived)
|
||||||
} else txo
|
} else txo
|
||||||
case TxoState.PendingConfirmationsReceived =>
|
case TxoState.PendingConfirmationsReceived | BroadcastReceived =>
|
||||||
if (confs >= walletConfig.requiredConfirmations)
|
if (confs >= walletConfig.requiredConfirmations)
|
||||||
txo.copyWithState(TxoState.ConfirmedReceived)
|
txo.copyWithState(TxoState.ConfirmedReceived)
|
||||||
else txo
|
else txo.copyWithState(PendingConfirmationsReceived)
|
||||||
case TxoState.PendingConfirmationsSpent =>
|
case TxoState.PendingConfirmationsSpent | BroadcastSpent =>
|
||||||
if (confs >= walletConfig.requiredConfirmations)
|
if (confs >= walletConfig.requiredConfirmations)
|
||||||
txo.copyWithState(TxoState.ConfirmedSpent)
|
txo.copyWithState(TxoState.ConfirmedSpent)
|
||||||
else txo
|
else txo.copyWithState(PendingConfirmationsSpent)
|
||||||
case TxoState.Reserved =>
|
case TxoState.Reserved =>
|
||||||
// We should keep the utxo as reserved so it is not used in
|
// We should keep the utxo as reserved so it is not used in
|
||||||
// a future transaction that it should not be in
|
// a future transaction that it should not be in
|
||||||
|
Loading…
Reference in New Issue
Block a user