wallet: fix scanning progress calculation for single block range #20344

pull theStack wants to merge 1 commits into bitcoin:master from theStack:20201108-wallet-avoid_div_by_zero_on_single_block_rescan changing 2 files +5 −2
  1. theStack commented at 6:59 PM on November 8, 2020: member

    If the blockchain is rescanned for a single block (i.e. start and stop hashes are equal, and with that also the estimated start/stop verification progress values) the progress calculation could lead to a NaN value caused by a division by zero (0.0/0.0), resulting in an invalid JSON result for the getwalletinfo RPC. This PR fixes this behaviour by setting the progress to zero in that special case. Fixes #20297.

    The behaviour can easily be reproduced by continuously running single block rescans in an endless loop, e.g. via

    #!/bin/bash
    while true
    do
        bitcoin-cli rescanblockchain $(bitcoin-cli getblockcount)
    done
    

    and at the same time perform some getwalletinfo RPCs.

    On the master branch, this leads to frequent invalid responses (tested on mainchain):

    $ bitcoin-cli getwalletinfo
    error: couldn't parse reply from server
    $ curl --user `cat ~/.bitcoin/.cookie` --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getwalletinfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
    {"result":{"walletname":"","walletversion":169900,"format":"bdb","balance":0.00000000,"unconfirmed_balance":0.00000000,"immature_balance":0.00000000,"txcount":0,"keypoololdest":1603677276,"keypoolsize":1000,"hdseedid":"3196e33ecb47c7130e6ca60f2f895f9259860dca","keypoolsize_hd_internal":1000,"paytxfee":0.00000000,"private_keys_enabled":true,"avoid_reuse":false,"scanning":{"duration":0,"progress":},"descriptors":false},"error":null,"id":"curltest"}
    

    (note that missing value for "progress" in the JSON result).

    On the PR branch, the behaviour doesn't occur anymore.

  2. practicalswift commented at 7:44 PM on November 8, 2020: contributor

    ACK 4771bac85b3924f118d326afb05347992815514d, but consider getting rid of the UBSan suppression that is no longer needed after this change :)

    FWIW I've tried getting rid of this and all other float divide by zeros in our code base before (see PR #17208), but I had to close that PR due to lack of reviewer interest back then :)

    Please consider taking on the other cases from #17208 when you're done with this one. I'd be glad to review :)

  3. DrahtBot added the label Wallet on Nov 8, 2020
  4. kristapsk approved
  5. kristapsk commented at 2:02 AM on November 10, 2020: contributor

    ACK 4771bac85b3924f118d326afb05347992815514d

  6. MarcoFalke added this to the milestone 0.21.0 on Nov 10, 2020
  7. MarcoFalke commented at 9:19 AM on November 11, 2020: member

    Please remove the unused suppression:

    diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan
    index 75257d886..784273952 100644
    --- a/test/sanitizer_suppressions/ubsan
    +++ b/test/sanitizer_suppressions/ubsan
    @@ -1,7 +1,6 @@
     # -fsanitize=undefined suppressions
     # =================================
     float-divide-by-zero:validation.cpp
    -float-divide-by-zero:wallet/wallet.cpp
     
     # -fsanitize=integer suppressions
     # ===============================
    
  8. hebasto commented at 9:45 AM on November 11, 2020: member

    Approach ACK 4771bac85b3924f118d326afb05347992815514d, tested on Linux Mint 20 (x86_64).

    Still addressing of #20344 (comment) is anticipated :)

  9. fanquake added the label Waiting for author on Nov 11, 2020
  10. wallet: fix scanning progress calculation for single block range
    If the blockchain is rescanned for a single block (i.e. start and stop hashes
    are equal, and with that also the estimated verification progress) the progress
    calculation could lead to a NaN value caused by a division by zero, resulting in
    an invalid JSON result for the getwalletinfo RPC.  Fixed by setting the progress
    to zero in that special case.
    
    Co-authored-by: MarcoFalke <falke.marco@gmail.com>
    5e146022da
  11. theStack force-pushed on Nov 11, 2020
  12. fanquake removed the label Waiting for author on Nov 11, 2020
  13. theStack commented at 12:24 PM on November 11, 2020: member

    Force-pushed with the UBSan suppression removal as suggested by practicalswift and MarcoFalke.

    Please consider taking on the other cases from #17208 when you're done with this one. I'd be glad to review :)

    Thanks for the suggestion and review offer, will definitely take a look into it.

  14. in src/wallet/wallet.cpp:1781 in 5e146022da
    1777 | @@ -1778,7 +1778,11 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
    1778 |      double progress_current = progress_begin;
    1779 |      int block_height = start_height;
    1780 |      while (!fAbortRescan && !chain().shutdownRequested()) {
    1781 | -        m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
    


    promag commented at 12:42 PM on November 11, 2020:

    nit, one time check:

    // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
    double progress_ratio = progress_end > progress_begin ? progress_end - progress_begin : 1;
    while (...) {
        m_scanning_progress = (progress_current - progress_begin) / progress_ratio;
    

    wait, progress_end can change in the loop, never mind then.

  15. promag commented at 12:45 PM on November 11, 2020: member

    Core review ACK 5e146022daa4336de94447e5b8e5418296286927.

  16. MarcoFalke commented at 3:09 PM on November 11, 2020: member

    review ACK 5e146022daa4336de94447e5b8e5418296286927

  17. MarcoFalke merged this on Nov 11, 2020
  18. MarcoFalke closed this on Nov 11, 2020

  19. sidhujag referenced this in commit 952dd90c65 on Nov 11, 2020
  20. fanquake commented at 11:27 AM on November 12, 2020: member

    @jonasschnelli reported on IRC that builds have been failing on his CI since this PR was merged. https://bitcoinbuilds.org/index.php?job=ffb7d59f-379f-4f27-a273-a5595b8c5f07:

    ********* Start testing of WalletTests *********
    Config: Using QtTest library 5.9.5, Qt 5.9.5 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 7.4.0)
    PASS   : WalletTests::initTestCase()
    QDEBUG : WalletTests::walletTests() TransactionTablePriv::refreshWallet
    wallet/wallet.cpp:3113:51: runtime error: division by zero
        [#0](/bitcoin-bitcoin/0/) 0x55d52a716807 in CWallet::CreateTransactionInternal(std::vector<CRecipient, std::allocator<CRecipient> > const&, std::shared_ptr<CTransaction const>&, long&, int&, bilingual_str&, CCoinControl const&, FeeCalculation&, bool) /home/ubuntu/src/src/wallet/wallet.cpp:3113:51
        [#1](/bitcoin-bitcoin/1/) 0x55d52a710290 in CWallet::CreateTransaction(std::vector<CRecipient, std::allocator<CRecipient> > const&, std::shared_ptr<CTransaction const>&, long&, int&, bilingual_str&, CCoinControl const&, FeeCalculation&, bool) /home/ubuntu/src/src/wallet/wallet.cpp:3133:16
        [#2](/bitcoin-bitcoin/2/) 0x55d52a470eaa in interfaces::(anonymous namespace)::WalletImpl::createTransaction(std::vector<CRecipient, std::allocator<CRecipient> > const&, CCoinControl const&, bool, int&, long&, bilingual_str&) /home/ubuntu/src/src/interfaces/wallet.cpp:235:24
        [#3](/bitcoin-bitcoin/3/) 0x55d5294ff6b5 in WalletModel::prepareTransaction(WalletModelTransaction&, CCoinControl const&) /home/ubuntu/src/src/qt/walletmodel.cpp:203:27
        [#4](/bitcoin-bitcoin/4/) 0x55d5294351fd in SendCoinsDialog::PrepareSendText(QString&, QString&, QString&) /home/ubuntu/src/src/qt/sendcoinsdialog.cpp:267:28
        [#5](/bitcoin-bitcoin/5/) 0x55d52943a961 in SendCoinsDialog::on_sendButton_clicked() /home/ubuntu/src/src/qt/sendcoinsdialog.cpp:377:10
        [#6](/bitcoin-bitcoin/6/) 0x55d52957527d in SendCoinsDialog::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) /home/ubuntu/src/src/qt/moc_sendcoinsdialog.cpp:203:21
        [#7](/bitcoin-bitcoin/7/) 0x7f6344f9d002 in QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (/usr/lib/x86_64-linux-gnu/libQt5Core.so.5+0x29b002)
        [#8](/bitcoin-bitcoin/8/) 0x7f6344f9f47c in QMetaObject::invokeMethod(QObject*, char const*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) (/usr/lib/x86_64-linux-gnu/libQt5Core.so.5+0x29d47c)
        [#9](/bitcoin-bitcoin/9/) 0x55d52914357c in QMetaObject::invokeMethod(QObject*, char const*, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs.h:466:16
        [#10](/bitcoin-bitcoin/10/) 0x55d52914357c in (anonymous namespace)::SendCoins(CWallet&, SendCoinsDialog&, boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> const&, long, bool) /home/ubuntu/src/src/qt/test/wallettests.cpp:76
        [#11](/bitcoin-bitcoin/11/) 0x55d52913c42f in (anonymous namespace)::TestGUI(interfaces::Node&) /home/ubuntu/src/src/qt/test/wallettests.cpp:187:21
        [#12](/bitcoin-bitcoin/12/) 0x55d529139c98 in WalletTests::walletTests() /home/ubuntu/src/src/qt/test/wallettests.cpp:285:5
        [#13](/bitcoin-bitcoin/13/) 0x55d52916ba22 in WalletTests::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) /home/ubuntu/src/src/qt/test/moc_wallettests.cpp:70:21
        [#14](/bitcoin-bitcoin/14/) 0x7f6344f9d002 in QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (/usr/lib/x86_64-linux-gnu/libQt5Core.so.5+0x29b002)
        [#15](/bitcoin-bitcoin/15/) 0x7f6344adb799  (/usr/lib/x86_64-linux-gnu/libQt5Test.so.5+0x13799)
        [#16](/bitcoin-bitcoin/16/) 0x7f6344adc4ef  (/usr/lib/x86_64-linux-gnu/libQt5Test.so.5+0x144ef)
        [#17](/bitcoin-bitcoin/17/) 0x7f6344adca60  (/usr/lib/x86_64-linux-gnu/libQt5Test.so.5+0x14a60)
        [#18](/bitcoin-bitcoin/18/) 0x7f6344add02a in QTest::qExec(QObject*, int, char**) (/usr/lib/x86_64-linux-gnu/libQt5Test.so.5+0x1502a)
        [#19](/bitcoin-bitcoin/19/) 0x55d5290e42fc in main /home/ubuntu/src/src/qt/test/test_main.cpp:94:9
        [#20](/bitcoin-bitcoin/20/) 0x7f634172db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
        [#21](/bitcoin-bitcoin/21/) 0x55d528fecd89 in _start (/home/ubuntu/src/src/qt/test/test_bitcoin-qt+0x2633d89)
    
    SUMMARY: UndefinedBehaviorSanitizer: float-divide-by-zero wallet/wallet.cpp:3113:51 in 
    FAIL qt/test/test_bitcoin-qt (exit status: 1)
    
  21. jonasschnelli commented at 11:44 AM on November 12, 2020: contributor

    This triggers at least a dev-by-0 here (https://github.com/bitcoin/bitcoin/blob/9bd1316697292251ed5690390794fc64517fc86b/src/wallet/wallet.cpp#L3110)

    Maybe at other places?

    How could this not trigger a travis error? I guess we run the qt tests there as well?

  22. MarcoFalke commented at 12:00 PM on November 12, 2020: member
  23. theStack deleted the branch on Nov 12, 2020
  24. practicalswift commented at 1:25 PM on November 12, 2020: contributor

    @fanquake @jonasschnelli Feel free to cherry-pick in 0201cbcd866f1527b3b097823ad522662a4d84ad from #17208.

  25. jonasschnelli referenced this in commit 543693b92b on Nov 13, 2020
  26. sidhujag referenced this in commit 91c2657380 on Nov 13, 2020
  27. PastaPastaPasta referenced this in commit 0b48bfa01e on Jun 27, 2021
  28. PastaPastaPasta referenced this in commit da38a0c378 on Jun 28, 2021
  29. PastaPastaPasta referenced this in commit abc732e280 on Jun 29, 2021
  30. PastaPastaPasta referenced this in commit 11f6aae2ba on Jul 1, 2021
  31. PastaPastaPasta referenced this in commit 04e5e42713 on Jul 1, 2021
  32. PastaPastaPasta referenced this in commit 81a867cbe0 on Jul 15, 2021
  33. PastaPastaPasta referenced this in commit 4e0744fb2b on Jul 15, 2021
  34. PastaPastaPasta referenced this in commit e8a9c28c82 on Jul 16, 2021
  35. gabriel-bjg referenced this in commit a1858222f0 on Jul 16, 2021
  36. Fabcien referenced this in commit b4aac05e71 on Sep 28, 2021
  37. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:14 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me