Refactor to not use filterThenSum() when calculating balances (#4562)

* Refactor to not use filterThenSum() when calculating balances

* Add await for balance as blocks are processed async

* Add more assertions, fix bad assertions I introduced
This commit is contained in:
Chris Stewart 2022-08-02 12:33:46 -05:00 committed by GitHub
parent b7c7cb8fc2
commit b1a7f92c67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 44 deletions

View File

@ -56,14 +56,13 @@ class ProcessBlockTest extends BitcoinSWalletTestCachedBitcoinV19 {
syncHeightOpt <- wallet.getSyncDescriptorOpt()
txDbOpt <- wallet.findByTxId(txId)
} yield {
assert(syncHeightOpt.contains(SyncHeightDescriptor(bestHash, height)))
assert(txDbOpt.isDefined)
assert(txDbOpt.get.blockHashOpt.contains(hash))
assert(utxos.size == 1)
assert(utxos.head.output.scriptPubKey == addr.scriptPubKey)
assert(utxos.head.output.value == 1.bitcoin)
assert(utxos.head.txid == txId)
assert(syncHeightOpt.contains(SyncHeightDescriptor(bestHash, height)))
}
}
@ -79,17 +78,22 @@ class ProcessBlockTest extends BitcoinSWalletTestCachedBitcoinV19 {
hashes <- bitcoind.generateToAddress(101, addr)
blocks <- FutureUtil.sequentially(hashes)(bitcoind.getBlockRaw)
_ <- FutureUtil.sequentially(blocks)(wallet.processBlock)
utxos <- wallet.listUtxos(TxoState.ImmatureCoinbase)
balance <- wallet.getBalance()
coinbaseUtxos <- wallet.listUtxos(TxoState.ImmatureCoinbase)
confirmedUtxos <- wallet.listUtxos(TxoState.ConfirmedReceived)
balance <- wallet.getConfirmedBalance()
height <- bitcoind.getBlockCount
bestHash <- bitcoind.getBestBlockHash
syncHeightOpt <- wallet.getSyncDescriptorOpt()
} yield {
assert(utxos.size == 100)
assert(balance == Bitcoins(50))
assert(syncHeightOpt.isDefined)
assert(syncHeightOpt.contains(SyncHeightDescriptor(bestHash, height)))
// note: 100 because the very first coinbase utxo is now confirmed
assert(coinbaseUtxos.size == 100)
//block reward is still 50 bitcoin per block
assert(balance == Bitcoins(50))
assert(confirmedUtxos.length == 1)
}
}
@ -108,17 +112,26 @@ class ProcessBlockTest extends BitcoinSWalletTestCachedBitcoinV19 {
bitcoind.getBlockFilter(_, FilterType.Basic))
filtersWithBlockHash = hashes.map(_.flip).zip(filters.map(_.filter))
_ <- wallet.processCompactFilters(filtersWithBlockHash)
utxos <- wallet.listUtxos(TxoState.ImmatureCoinbase)
balance <- wallet.getBalance()
coinbaseUtxos <- wallet.listUtxos(TxoState.ImmatureCoinbase)
confirmedUtxos <- wallet.listUtxos(TxoState.ConfirmedReceived)
balance <- wallet.getConfirmedBalance()
height <- bitcoind.getBlockCount
bestHash <- bitcoind.getBestBlockHash
syncHeightOpt <- wallet.getSyncDescriptorOpt()
} yield {
assert(utxos.size == 100)
assert(balance == Bitcoins(50))
assert(syncHeightOpt.isDefined)
assert(syncHeightOpt.contains(SyncHeightDescriptor(bestHash, height)))
// note: 100 because the very first coinbase utxo is now confirmed
assert(coinbaseUtxos.size == 100)
//note: This is 50 bitcoins because the block reward on regtest
//is now 25 bitcoin per block due to blocks being mined
//in prior test cases in this test suite.
assert(balance == Bitcoins(50))
assert(confirmedUtxos.length == 2)
}
}

View File

@ -307,38 +307,8 @@ abstract class Wallet
.map(_ => this)
}
/** Sums up the value of all unspent
* TXOs in the wallet, filtered by the given predicate
*/
private def filterThenSum(
predicate: SpendingInfoDb => Boolean): Future[CurrencyUnit] = {
for (
utxos <-
spendingInfoDAO.findAllUnspentForAccount(walletConfig.defaultAccount)
)
yield {
val filtered = utxos
.filter(predicate)
.map { txo =>
txo.state match {
case TxoState.PendingConfirmationsReceived |
TxoState.ConfirmedReceived | TxoState.BroadcastReceived =>
txo.output.value
case TxoState.Reserved | TxoState.PendingConfirmationsSpent |
TxoState.ConfirmedSpent | TxoState.BroadcastSpent |
TxoState.ImmatureCoinbase =>
CurrencyUnits.zero
}
}
filtered.fold(0.sats)(_ + _)
}
}
override def getConfirmedBalance(): Future[CurrencyUnit] = {
filterThenSum(_.state == ConfirmedReceived).map { balance =>
balance
}
getConfirmedBalance(walletConfig.defaultAccount)
}
override def getConfirmedBalance(account: HDAccount): Future[CurrencyUnit] = {
@ -362,7 +332,7 @@ abstract class Wallet
}
override def getUnconfirmedBalance(): Future[CurrencyUnit] = {
filterThenSum(utxo => TxoState.pendingReceivedStates.contains(utxo.state))
getUnconfirmedBalance(walletConfig.defaultAccount)
}
override def getUnconfirmedBalance(

View File

@ -416,7 +416,9 @@ private[bitcoins] trait TransactionProcessing extends WalletLogger {
)
_ = if (incoming.nonEmpty) {
logger.info(
s"Finished processing ${incoming.length} received outputs, it took=${TimeUtil.currentEpochMs - receivedStart}ms")
s"Finished processing ${incoming.length} received outputs, balance=${incoming
.map(_.output.value)
.sum} it took=${TimeUtil.currentEpochMs - receivedStart}ms")
}
spentSpendingInfoDbs <- spentSpendingInfoDbsF