Remove uses of chainActive and mapBlockIndex in wallet code #14711

pull ryanofsky wants to merge 5 commits into bitcoin:master from ryanofsky:pr/wchain2 changing 11 files +486 −215
  1. ryanofsky commented at 7:35 pm on November 12, 2018: member

    This change removes uses of chainActive and mapBlockIndex globals in wallet code. It is a refactoring change which does not affect external behavior.

    This is the next step in the larger #10973 refactoring change, which removes all other accesses to node global variables from wallet code. Doing this is useful to provide a better defined interface between the wallet and node, and necessary to allow wallet and node code to run in separate processes in #10102.

  2. MarcoFalke commented at 10:09 pm on November 12, 2018: member
    Concept ACK. Though, I’d prefer if we first cleaned up the interface for ScanForWalletTransactions. I believe that right now it is relying on too much undefined behaviour that this refactoring could be meaningfully reviewed.
  3. MarcoFalke added the label Refactoring on Nov 12, 2018
  4. MarcoFalke added this to the milestone 0.18.0 on Nov 12, 2018
  5. ryanofsky commented at 10:34 pm on November 12, 2018: member

    too much undefined behaviour that this refactoring could be meaningfully reviewed.

    Are you talking about a small part of this PR or the whole thing? Most of the changes here don’t have anything to do with ScanForWalletTransactions. I could even drop the rescan changes and save them for a different PR if you are only worried about them.

  6. practicalswift commented at 10:16 am on November 13, 2018: contributor

    Concept ACK

    Nice readability and robustness improvement

  7. Empact commented at 10:21 am on November 13, 2018: member

    Concept ACK

    Would be easier/safer to review if split up. Like Marco, I’d like to see ScanFor improved first.

  8. DrahtBot commented at 3:20 pm on November 13, 2018: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #15129 (rpc: Added ability to remove watch only addresses by benthecarman)
    • #14942 (wallet: Return a ScanResult from CWallet::RescanFromTime by Empact)
    • #14533 (wallet: ensure wallet files are not reused across chains by mrwhythat)
    • #10973 (Refactor: separate wallet from node by ryanofsky)
    • #10102 ([experimental] Multiprocess bitcoin by ryanofsky)
    • #9381 (Remove CWalletTx merging logic from AddToWallet by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  9. in src/wallet/wallet.cpp:4193 in d568bdb151 outdated
    4172         {
    4173-            CBlockIndex *block = chainActive.Tip();
    4174-            while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
    4175-                block = block->pprev;
    4176+            int block_height = *tip_height;
    4177+            while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
    


    meshcollider commented at 10:37 am on November 14, 2018:
    Why not use findPruned(rescan_height, *tip_height)?

    ryanofsky commented at 10:13 pm on November 14, 2018:

    re: #14711 (review)

    Why not use findPruned

    I used haveBlockOnDisk here because I was doing a very literal translation and findPruned doesn’t have the block->pprev->nTx > 0 condition. If can drop that condition or add it to findPruned, though, if it would be an improvement.

  10. in src/wallet/wallet.cpp:1635 in d568bdb151 outdated
    1645- * defined by pindexStop
    1646+ * If stop_block is not null, the scan will stop at the block-index
    1647+ * defined by stop_block
    1648  *
    1649- * Caller needs to make sure pindexStop (and the optional pindexStart) are on
    1650+ * Caller needs to make sure stop_block (and the optional start_block) are on
    


    meshcollider commented at 10:50 am on November 14, 2018:
    I think this is where the earlier confusion arose, it is stop_block which is optional not start_block, so the comment is wrong, the names need to be switched

    ryanofsky commented at 10:24 pm on November 14, 2018:

    re: #14711 (review)

    the names need to be switched

    Good catch. I’ll probably just rewrite this comment if this isn’t fixed by another of the rescan PRs first. This comment never made sense to me even when it was first added in #11281 (review) / #11281 (review).

  11. meshcollider added the label Wallet on Nov 14, 2018
  12. in src/wallet/rpcdump.cpp:382 in d568bdb151 outdated
    365@@ -366,8 +366,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
    366     if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
    367 
    368         auto locked_chain = pwallet->chain().lock();
    369-        const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
    370-        if (!pindex || !chainActive.Contains(pindex)) {
    371+        if (!locked_chain->getBlockHeight(merkleBlock.header.GetHash())) {
    


    promag commented at 11:34 pm on November 14, 2018:
    This sounds wrong, as if it wants to discard genesis block (height == 0). Only got it after seeing the return type Optional<int>. IMO .contains(hash) would be preferable.

    Empact commented at 11:38 am on January 9, 2019:
    Could be more clear with a comparison with nullopt

    ryanofsky commented at 5:46 pm on January 10, 2019:

    re: #14711 (review)

    Could be more clear with a comparison with nullopt

    Took suggestion

  13. in src/wallet/rpcwallet.cpp:1579 in d568bdb151 outdated
    1528@@ -1526,24 +1529,18 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
    1529     auto locked_chain = pwallet->chain().lock();
    1530     LOCK(pwallet->cs_wallet);
    1531 
    1532-    const CBlockIndex* pindex = nullptr;    // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
    1533-    const CBlockIndex* paltindex = nullptr; // Block index of the specified block, even if it's in a deactivated chain.
    1534+    Optional<int> height;    // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
    


    promag commented at 0:16 am on November 15, 2018:

    Isn’t this change conceptually different? Even though the chain is locked, this can be copied and used without the lock and therefore can “point” to other block if a reorg occurs. This wouldn’t occur with CBlockIndex.

    Looks like you could either:

    • create interfaces::BlockIndex
    • replace CBlockIndex* with uint256.

    ryanofsky commented at 5:46 pm on January 10, 2019:

    re: #14711 (review)

    Isn’t this change conceptually different?

    I think so, a height is conceptually different from a block pointer.

    Looks like you could either:

    When the chain is locked, a height uniquely identifies a block, so many locked_chain methods take height arguments. I think it would good to eliminate these calls entirely (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269) and not very useful to tweak data types and just hide the fact that the chain is locked.

    But either way, I want the API to change in the future and become nicer, more minimal, and more useful over time. Right now the API just reflects how the wallet currently works, to keep changes to wallet code in this PR as minimal as possible.

  14. promag commented at 0:17 am on November 15, 2018: member
    Concept ACK.
  15. in src/wallet/wallet.h:899 in d568bdb151 outdated
    892@@ -896,7 +893,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
    893     void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
    894     void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
    895     int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
    896-    CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate = false);
    897+    uint256 ScanForWalletTransactions(const uint256& start_block, const uint256& stop_block, const WalletRescanReserver &reserver, bool fUpdate);
    


    MarcoFalke commented at 5:36 pm on November 15, 2018:
    Haven’t though about this too much, but maybe you could split out the changes in the wallet header that change the interface from taking a block index pointer to taking a block hash to a separate commit? Unless I am mistaken those type changes have the side effect of fixing the “issue” I tried to fix in #14712.
  16. DrahtBot added the label Needs rebase on Nov 30, 2018
  17. ryanofsky force-pushed on Dec 6, 2018
  18. DrahtBot removed the label Needs rebase on Dec 6, 2018
  19. in src/interfaces/chain.h:121 in 5cad675a8e outdated
    116+        CBlock* block = nullptr,
    117+        int64_t* time = nullptr,
    118+        int64_t* max_time = nullptr) = 0;
    119+
    120+    //! Estimate fraction of total transactions verified if blocks up to
    121+    //! given height are verified.
    


    MarcoFalke commented at 3:54 am on December 12, 2018:
    doc-nit: height is not given (at least not directly)

    ryanofsky commented at 5:46 pm on January 10, 2019:

    re: #14711 (review)

    doc-nit: height is not given (at least not directly)

    Thanks, fixed comment

  20. DrahtBot added the label Needs rebase on Dec 12, 2018
  21. jonasschnelli commented at 6:02 am on December 12, 2018: contributor
    Strong Concept ACK Plans to review…
  22. ryanofsky force-pushed on Dec 17, 2018
  23. DrahtBot removed the label Needs rebase on Dec 17, 2018
  24. DrahtBot added the label Needs rebase on Dec 18, 2018
  25. ryanofsky force-pushed on Dec 18, 2018
  26. DrahtBot removed the label Needs rebase on Dec 18, 2018
  27. laanwj added this to the "Blockers" column in a project

  28. Empact commented at 8:34 am on January 8, 2019: member
    @ryanofsky I went ahead and split this up into a few commits, found it easier to review. Built and ran tests on each commit. https://github.com/Empact/bitcoin/tree/pr/wchain2
  29. in src/interfaces/chain.cpp:16 in 939a400f3d outdated
    11+#include <uint256.h>
    12 #include <util/system.h>
    13 #include <validation.h>
    14 
    15 #include <memory>
    16+#include <unordered_map>
    


    Empact commented at 8:36 am on January 8, 2019:
    nit: I believe this belongs in validation.h, as unordered_map isn’t used directly here.

    ryanofsky commented at 6:19 pm on January 10, 2019:

    re: #14711 (review)

    nit: I believe this belongs in validation.h, as unordered_map isn’t used directly here.

    This was added by IWYU because unordered map methods are called here. In theory this allows validation.h to switch to forward declarations and drop its unordered_map include without this file having to change. I don’t think IWYU rationale is completely airtight (particularly in this case where validation.h might change mapBlockIndex into a different type of map with the same methods), but I like the IWYU tool, and don’t think its worth spending a lot of time to analyze its decisions absent a compelling reason.

  30. in src/interfaces/chain.cpp:154 in 939a400f3d outdated
    149@@ -35,6 +150,34 @@ class ChainImpl : public Chain
    150         return std::move(result);
    151     }
    152     std::unique_ptr<Chain::Lock> assumeLocked() override { return MakeUnique<LockImpl>(); }
    153+    bool findBlock(const uint256& hash, CBlock* block, int64_t* time, int64_t* time_max) override
    


    Empact commented at 8:43 am on January 8, 2019:
    nit: none of the callers use more than one of the out args, so splitting this up would make the call sites simpler/clearer.

    ryanofsky commented at 6:19 pm on January 10, 2019:

    re: #14711 (review)

    nit: none of the callers use more than one of the out args, so splitting this up would make the call sites simpler/clearer.

    There are many ways to design this API, and I just opted for one here that I thought would keep chain.h a little shorter and more organized, at the expense of being more verbose at call sites. If you have a specific alternative in mind and want to convince me or another reviewer that it’s better, I’d be happy to adopt it here, or review a followup PR.

  31. in src/wallet/rpcwallet.cpp:3437 in 939a400f3d outdated
    3442 
    3443-    const CBlockIndex *failed_block, *stopBlock;
    3444+    uint256 failed_block, stopBlock;
    3445     CWallet::ScanResult result =
    3446-        pwallet->ScanForWalletTransactions(pindexStart, pindexStop, reserver, failed_block, stopBlock, true);
    3447+        pwallet->ScanForWalletTransactions(start_block, stop_block, reserver, failed_block, stopBlock, true /* prune */);
    


    Empact commented at 8:45 am on January 8, 2019:
    stop_block and stopBlock are confusingly similar.

    ryanofsky commented at 6:19 pm on January 10, 2019:

    re: #14711 (review)

    stop_block and stopBlock are confusingly similar.

    Added more renames

  32. ryanofsky force-pushed on Jan 8, 2019
  33. ryanofsky commented at 3:48 pm on January 8, 2019: member

    Thanks @Empact! I reset the PR to your branch.


    Rebased d568bdb15173dd8dd7bf95cb0bd9c9b55dbb97f0 -> 5cad675a8e8beb0a97f95860a3017fd581bcc1e5 (pr/wchain2.1 -> pr/wchain2.2) due to conflict with #14380 Rebased 5cad675a8e8beb0a97f95860a3017fd581bcc1e5 -> 591c2c85e928441bf1f5b1f58c132e72ad4eb185 (pr/wchain2.2 -> pr/wchain2.3) due to conflict with #13076 Rebased 591c2c85e928441bf1f5b1f58c132e72ad4eb185 -> 939a400f3d632330e470c4b3e71ee822ae7be4c4 (pr/wchain2.3 -> pr/wchain2.4) due to conflict with #14957 Split 939a400f3d632330e470c4b3e71ee822ae7be4c4 -> 7a8727256c99dfbf739448fc72082ec568e14056 (pr/wchain2.4 -> pr/wchain2.5) resetting to Empact:pr/wchain2 (no diffs) Rebased 7a8727256c99dfbf739448fc72082ec568e14056 -> ca76bcc917dbc53a1b639acbdbb5d2faf28bbc52 (pr/wchain2.5 -> pr/wchain2.6) due to conflict with #15039

  34. DrahtBot added the label Needs rebase on Jan 10, 2019
  35. ryanofsky force-pushed on Jan 10, 2019
  36. DrahtBot removed the label Needs rebase on Jan 10, 2019
  37. ryanofsky force-pushed on Jan 10, 2019
  38. ryanofsky commented at 7:28 pm on January 10, 2019: member
    Updated ca76bcc917dbc53a1b639acbdbb5d2faf28bbc52 -> b5c5b202757e6b9322d28f4a1ac533622ab4db00 (pr/wchain2.6 -> pr/wchain2.7) with suggestions from review comments Rebased b5c5b202757e6b9322d28f4a1ac533622ab4db00 -> 5bc30a5083507fbc10691c7c26683afe7e768c88 (pr/wchain2.7 -> pr/wchain2.8) due to conflict with #14556.
  39. jamesob approved
  40. jamesob commented at 10:09 pm on January 14, 2019: member

    utACK https://github.com/bitcoin/bitcoin/commit/b5c5b202757e6b9322d28f4a1ac533622ab4db00

    My previous comments on a superset of this PR still hold:

    Reviewers will notice that dealing in the more primitive datatypes returned by chain methods (block heights and hashes as opposed to, say, full CBlockIndex values) results in more fiddling at callsites (null checks, arithmetic, subsequent lookups, etc.). This is an obvious drawback, but if we imagine that these calls are happening over a process boundary - as, god willing, they someday will - then the simpler the datatype the better. The stripped-down return types also more tightly accommodate the data requirements of the callers. For these two reasons, this changeset is a big step towards system decomposition IMO.

    • 5f71b83448 Add height, depth, and hash methods to the Chain interface

    • 909557ac65 Add time methods to the Chain interface

    • 7669e12075 Add findFork and findBlock to the Chain interface

    • 628f97b97e Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis

      Note for reviewers: “block” in Chain::Lock method names refers to a height. A height is assumed to uniquely identify a given block for the duration of Chain::Lock’s lifetime.

    • b5c5b20275 Remove remaining chainActive references from CWallet


    I’ll do some manual testing soon.

  41. Add height, depth, and hash methods to the Chain interface
    And use them to remove uses of chainActive and mapBlockIndex in wallet code
    
    This commit does not change behavior.
    
    Co-authored-by: Ben Woosley <ben.woosley@gmail.com>
    700c42b85d
  42. Add time methods to the Chain interface
    And use them to remove uses of chainActive and mapBlockIndex in wallet code
    
    This commit does not change behavior.
    
    Co-authored-by: Ben Woosley <ben.woosley@gmail.com>
    d93c4c1d6e
  43. Add findFork and findBlock to the Chain interface
    And use them to remove uses of chainActive and mapBlockIndex in wallet code
    
    This commit does not change behavior.
    
    Co-authored-by: Ben Woosley <ben.woosley@gmail.com>
    2ffb07929e
  44. Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis
    Only change in behavior is "Rescan started from block <height>" message
    replaced by "Rescan started from block <hash>" message in
    ScanForWalletTransactions.
    
    Co-authored-by: Ben Woosley <ben.woosley@gmail.com>
    db21f02648
  45. Remove remaining chainActive references from CWallet
    This commit does not change behavior.
    
    Co-authored-by: Ben Woosley <ben.woosley@gmail.com>
    44de1561aa
  46. DrahtBot added the label Needs rebase on Jan 15, 2019
  47. ryanofsky force-pushed on Jan 15, 2019
  48. in src/interfaces/chain.cpp:35 in 5bc30a5083 outdated
    30+        return nullopt;
    31+    }
    32+    Optional<int> getBlockHeight(const uint256& hash) override
    33+    {
    34+        auto it = ::mapBlockIndex.find(hash);
    35+        if (it != ::mapBlockIndex.end() && it->second && ::chainActive.Contains(it->second)) {
    


    MarcoFalke commented at 7:19 pm on January 15, 2019:

    in commit 13bc578ca9 Add height, depth, and hash methods to the Chain interface

    It seems confusing to check for nullptr if when the block hash was found in the map, since the value should never be a nullptr? Anyway, a neat way to avoid that is by avoiding ::mapBlockIndex and calling LookupBlockIndex?


    ryanofsky commented at 4:03 pm on January 17, 2019:

    re: #14711 (review)

    Switched to LookupBlockIndex

  49. DrahtBot removed the label Needs rebase on Jan 15, 2019
  50. in src/wallet/rpcwallet.cpp:1579 in 5bc30a5083 outdated
    1575@@ -1573,24 +1576,18 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
    1576     auto locked_chain = pwallet->chain().lock();
    1577     LOCK(pwallet->cs_wallet);
    1578 
    1579-    const CBlockIndex* pindex = nullptr;    // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
    1580-    const CBlockIndex* paltindex = nullptr; // Block index of the specified block, even if it's in a deactivated chain.
    1581+    Optional<int> height;    // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
    


    MarcoFalke commented at 7:34 pm on January 15, 2019:

    nit in commit 13bc578ca9 Add height, depth, and hash methods to the Chain interface

    height is added and not used in this commit

    (Hunk should probably be moved to commit 22abf4a61a Add findFork and findBlock to the Chain interface)


    ryanofsky commented at 4:03 pm on January 17, 2019:

    re: #14711 (review)

    height is added and not used in this commit

    Seems to have been a harmless artifact from splitting this PR up. Moved to the right place now.

  51. in src/interfaces/chain.cpp:104 in 5bc30a5083 outdated
     99+    Optional<int> findFork(const uint256& hash, Optional<int>* height) override
    100+    {
    101+        const CBlockIndex *block{nullptr}, *fork{nullptr};
    102+        auto it = ::mapBlockIndex.find(hash);
    103+        if (it != ::mapBlockIndex.end()) {
    104+            block = it->second;
    


    MarcoFalke commented at 7:54 pm on January 15, 2019:

    in commit 22abf4a61a Add findFork and findBlock to the Chain interface

    Doesn’t check for nullptr here? Seems inconsistent with getBlockHeight. Anyway, a neat way to avoid that is by avoiding ::mapBlockIndex and calling LookupBlockIndex?


    ryanofsky commented at 4:03 pm on January 17, 2019:

    re: #14711 (review)

    Switched to LookupBlockIndex

  52. in src/interfaces/chain.cpp:162 in 5bc30a5083 outdated
    157+            LOCK(cs_main);
    158+            auto it = ::mapBlockIndex.find(hash);
    159+            if (it == ::mapBlockIndex.end()) {
    160+                return false;
    161+            }
    162+            index = it->second;
    


    MarcoFalke commented at 8:06 pm on January 15, 2019:

    in commit 22abf4a61a Add findFork and findBlock to the Chain interface

    Same here (use LookupBlockIndex)


    ryanofsky commented at 4:03 pm on January 17, 2019:

    re: #14711 (review)

    Switched to LookupBlockIndex

  53. in src/wallet/rpcwallet.cpp:1623 in 5bc30a5083 outdated
    1619@@ -1622,9 +1620,9 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
    1620     // when a reorg'd block is requested, we also list any relevant transactions
    1621     // in the blocks of the chain that was detached
    1622     UniValue removed(UniValue::VARR);
    1623-    while (include_removed && paltindex && paltindex != pindex) {
    1624+    while (include_removed && altheight && *altheight > height.value_or(-1)) {
    


    MarcoFalke commented at 8:31 pm on January 15, 2019:

    in commit 22abf4a61a Add findFork and findBlock to the Chain interface

    Assuming that height can not be set makes no sense, since you moved the FindFork call to before the !height check. I’d prefer to write *height here.


    ryanofsky commented at 4:03 pm on January 17, 2019:

    re: #14711 (review)

    Assuming that height can not be set makes no sense

    Good catch, simplified this.

  54. in src/wallet/rpcwallet.cpp:1608 in 5bc30a5083 outdated
    1603@@ -1607,7 +1604,8 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
    1604 
    1605     bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
    1606 
    1607-    int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
    1608+    const Optional<int> tip_height = locked_chain->getHeight();
    1609+    int depth = tip_height && height ? (1 + *tip_height - *height) : -1;
    


    MarcoFalke commented at 8:31 pm on January 15, 2019:

    in commit 22abf4a Add findFork and findBlock to the Chain interface

    Same (I’d prefer to not check for height again, since that has already been done above as you moved the FindFork to before the height check.)


    ryanofsky commented at 4:03 pm on January 17, 2019:

    re: #14711 (review)

    I’d prefer to not check for height again

    Height can be unset here since the blockhash parameter is optional.


    MarcoFalke commented at 9:08 pm on January 28, 2019:
    Right, my bad.
  55. in src/interfaces/chain.cpp:179 in 5bc30a5083 outdated
    174+    }
    175+    double guessVerificationProgress(const uint256& block_hash) override
    176+    {
    177+        LOCK(cs_main);
    178+        auto it = ::mapBlockIndex.find(block_hash);
    179+        return GuessVerificationProgress(Params().TxData(), it != ::mapBlockIndex.end() ? it->second : nullptr);
    


    MarcoFalke commented at 8:37 pm on January 15, 2019:

    in commit 65861dff7c Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis

    LookupBlockIndex instead of access to the global mapBlockIndex?


    ryanofsky commented at 4:03 pm on January 17, 2019:

    re: #14711 (review)

    Switched to LookupBlockIndex

  56. MarcoFalke commented at 8:59 pm on January 15, 2019: member
    utACK 22abf4a61a
  57. laanwj commented at 12:21 pm on January 16, 2019: member

    Some (I think) new compile warnings with this PR:

     0/.../bitcoin/src/wallet/rpcwallet.cpp: In function UniValue rescanblockchain(const JSONRPCRequest&):
     1/.../bitcoin/src/wallet/rpcwallet.cpp:3408:49: warning: *((void*)& tip_height +4) may be used uninitialized in this function [-Wmaybe-uninitialized]
     2             if (*stop_height < 0 || !tip_height || *stop_height > *tip_height) {
     3                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     4In file included from /.../bitcoin/src/rpc/mining.h:10:0,
     5                 from /.../bitcoin/src/wallet/rpcwallet.cpp:21:
     6/.../bitcoin/src/univalue/include/univalue.h:59:42: warning: *((void*)& stop_height +4) may be used uninitialized in this function [-Wmaybe-uninitialized]
     7     bool setInt(int val_) { return setInt((int64_t)val_); }
     8                                    ~~~~~~^~~~~~~~~~~~~~~
     9/.../bitcoin/src/wallet/rpcwallet.cpp:3391:19: note: *((void*)& stop_height +4) was declared here
    10     Optional<int> stop_height;
    11                   ^~~~~~~~~~~
    12/.../bitcoin/src/wallet/rpcwallet.cpp: In function UniValue listsinceblock(const JSONRPCRequest&):
    13/.../bitcoin/src/wallet/rpcwallet.cpp:1579:19: warning: *((void*)& height +4) may be used uninitialized in this function [-Wmaybe-uninitialized]
    14     Optional<int> height;    // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
    15                   ^~~~~~
    16/.../bitcoin/src/wallet/wallet.cpp: In member function CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256&, const uint256&, const WalletRescanReserver&, uint256&, uint256&, bool):
    17/.../bitcoin/src/wallet/wallet.cpp:1709:58: warning: *((void*)& block_height +4) may be used uninitialized in this function [-Wmaybe-uninitialized]
    18                         block_height = prev_block_height + 1;
    19                                        ~~~~~~~~~~~~~~~~~~^~~
    
  58. promag commented at 12:25 pm on January 16, 2019: member
    utACK 5bc30a508, this really improves interfaces::Chain. I’m also curious why LookupBlockIndex is avoided.
  59. ryanofsky force-pushed on Jan 17, 2019
  60. ryanofsky commented at 6:43 pm on January 17, 2019: member

    Updated 5bc30a5083507fbc10691c7c26683afe7e768c88 -> 1da8b4648e6b5f01a90acfe487bcda6f7a5a0424 (pr/wchain2.8 -> pr/wchain2.9) to resolve comments.


    re: #14711 (comment)

    Some (I think) new compile warnings with this PR:

    These are spurious and should be fixed if you use a newer compiler: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47679

    It might also be possible to work around them (but awkward): https://stackoverflow.com/questions/21755206/how-to-get-around-gcc-void-b-4-may-be-used-uninitialized-in-this-funct


    re: #14711 (comment)

    I’m also curious why LookupBlockIndex is avoided.

    Wasn’t really avoided, it just didn’t exist when this code was written: #10973 < #11041.

  61. in src/wallet/rpcwallet.cpp:3441 in 4fe793787a outdated
    3461     }
    3462     UniValue response(UniValue::VOBJ);
    3463-    response.pushKV("start_height", pindexStart->nHeight);
    3464-    response.pushKV("stop_height", stopBlock->nHeight);
    3465+    response.pushKV("start_height", start_height);
    3466+    response.pushKV("stop_height", stop_height ? *stop_height : UniValue());
    


    Empact commented at 10:09 pm on January 18, 2019:
    I think you want stop_block here. stop_height will carry the height that we sought to scan to, stop_block will carry the block that it actually reached.

    ryanofsky commented at 10:00 pm on January 22, 2019:

    re: #14711 (review)

    It would be nice to include stop_block in the future, since it’s a hash not a height, but this is not changing the behavior at all. stop_height will always contain the height scanned to because if the scan fails or aborts there will have been an exception earlier.

  62. ryanofsky commented at 10:04 pm on January 22, 2019: member

    IRC mention

    [12:19:55] <wumpus> #14711 seems almost ready for merge for a while, really just waiting for ryanofsky to respond to empact’s comment on the test

    http://www.erisian.com.au/bitcoin-core-dev/log-2019-01-22.html#l-146

  63. in src/interfaces/chain.h:122 in 1da8b4648e outdated
    110+    //! or contents.
    111+    //!
    112+    //! If a block pointer is provided to retrieve the block contents, and the
    113+    //! block exists but doesn't have data (for example due to pruning), the
    114+    //! block will be empty and all fields set to null.
    115+    virtual bool findBlock(const uint256& hash,
    


    promag commented at 3:19 pm on January 23, 2019:
    Below you call findBlock while the chain is locked. So should this be in the Chain::Lock? Or will there be a new mutex for mapBlockIndex?

    promag commented at 3:25 pm on January 23, 2019:
    I see that the idea is to move away from locked chain so ignore my question above: https://github.com/bitcoin/bitcoin/blob/82cf6813a4ef1b4a5439eb6cddb1ab426f3c31a2/src/interfaces/chain.h#L23-L26
  64. jamesob commented at 6:29 pm on January 24, 2019: member
    Looks like we’re in good shape for merge.
  65. in src/interfaces/chain.h:85 in 1da8b4648e outdated
    80+        //! nothing if no block in the range is pruned. Range is inclusive.
    81+        virtual Optional<int> findPruned(int start_height = 0, Optional<int> stop_height = nullopt) = 0;
    82+
    83+        //! Return height of the highest block on the chain that is an ancestor
    84+        //! of the specified block. Also return the height of the specified
    85+        //! block as an optional output parameter.
    


    jnewbery commented at 10:00 pm on January 25, 2019:
    Nit: returning the height of the specified block is a bit of an odd interface, but saves a second lookup in ChainActive that getHeight() would require. Perhaps add that reasoning to this comment?

    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    Perhaps add that reasoning to this comment?

    done

  66. in src/interfaces/chain.h:52 in 1da8b4648e outdated
    47+
    48+        //! Get block depth. Returns 1 for chain tip, 2 for preceding block, and
    49+        //! so on. Returns 0 for a block not included in the current chain.
    50+        virtual int getBlockDepth(const uint256& hash) = 0;
    51+
    52+        //! Get block hash.
    


    jnewbery commented at 10:01 pm on January 25, 2019:
    Nit: add comment that this function will assert if provided a height that isn’t in the active chain (same for getBlockTime() and getMedianTimePast()).

    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    add comment that this function will assert

    done

  67. in src/interfaces/chain.h:84 in 1da8b4648e outdated
    79+        //! Return height of last block in the specified range which is pruned, or
    80+        //! nothing if no block in the range is pruned. Range is inclusive.
    81+        virtual Optional<int> findPruned(int start_height = 0, Optional<int> stop_height = nullopt) = 0;
    82+
    83+        //! Return height of the highest block on the chain that is an ancestor
    84+        //! of the specified block. Also return the height of the specified
    


    jnewbery commented at 10:04 pm on January 25, 2019:
    Nit: Perhaps add or nullopt if no common ancestor is found to “Return height of the highest block on the chain that is an ancestor of the specified block”

    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    Perhaps add or nullopt if no common ancestor is found

    added

  68. in src/interfaces/chain.h:39 in 1da8b4648e outdated
    33@@ -28,6 +34,67 @@ class Chain
    34     {
    35     public:
    36         virtual ~Lock() {}
    37+
    38+        //! Get current chain height, not including genesis block (returns 0 if
    39+        //! chain only contains genesis block, nothing if chain does not contain
    


    jnewbery commented at 10:04 pm on January 25, 2019:
    Nit: Slight preference for s/nothing/nullopt/ for all of these comments to be more precise.

    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    Slight preference for s/nothing/nullopt/

    replaced

  69. in src/interfaces/chain.h:77 in 1da8b4648e outdated
    69+
    70+        //! Return height of the first block in the chain with timestamp equal
    71+        //! or greater than the given time and height equal or greater than the
    72+        //! given height, or nothing if there is no such block.
    73+        //!
    74+        //! Calling this with height 0 is equivalent to calling
    


    jnewbery commented at 10:28 pm on January 25, 2019:

    Nit: seems like CChain::FindEarliestAtLeast() could quite easily be updated to take a height parameter and use it in the std::lower_bound() call.

    Perhaps a future PR could combine findFirstBlockWithTime() and findFirstBlockWithTimeAndHeight() and remove some of the logic from the interface?


    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    Perhaps a future PR could combine findFirstBlockWithTime() and findFirstBlockWithTimeAndHeight()

    This is a good suggestion. I just added a TODO to avoid introducing CChain changes in this PR, but I’m also happy to make the change here if you prefer.

  70. in src/qt/test/wallettests.cpp:152 in 1da8b4648e outdated
    146@@ -146,13 +147,12 @@ void TestGUI()
    147         auto locked_chain = wallet->chain().lock();
    148         WalletRescanReserver reserver(wallet.get());
    149         reserver.reserve();
    150-        const CBlockIndex* const null_block = nullptr;
    151-        const CBlockIndex *stop_block, *failed_block;
    152+        uint256 stop_block, failed_block;
    153         QCOMPARE(
    154-            wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, failed_block, stop_block, true /* fUpdate */),
    155+            wallet->ScanForWalletTransactions(locked_chain->getBlockHash(0), {} /* stop block */, reserver, failed_block, stop_block, true /* fUpdate */),
    


    jnewbery commented at 10:49 pm on January 25, 2019:
    nit: comment here should be /* last block */

    ryanofsky commented at 9:47 pm on January 28, 2019:

    re: #14711 (review)

    nit: comment here should be /* last block */

    fixed

  71. in src/wallet/wallet.cpp:1595 in 1da8b4648e outdated
    1593-        startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
    1594-        WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
    1595+        const Optional<int> start_height = locked_chain->findFirstBlockWithTime(startTime - TIMESTAMP_WINDOW);
    1596+        const Optional<int> tip_height = locked_chain->getHeight();
    1597+        WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
    1598+        if (start_height) start_block = locked_chain->getBlockHash(*start_height);
    


    jnewbery commented at 10:52 pm on January 25, 2019:
    Nit: could you save a second chainActive lookup here by returning both the height and hash from findFirstBlockWithTime()?

    ryanofsky commented at 9:47 pm on January 28, 2019:

    re: #14711 (review)

    Nit: could you save a second chainActive lookup here by returning both the height and hash from findFirstBlockWithTime()?

    done

  72. in src/wallet/wallet.cpp:1601 in 1da8b4648e outdated
    1603+    if (!start_block.IsNull()) {
    1604+        uint256 failed_block, stop_block;
    1605         // TODO: this should take into account failure by ScanResult::USER_ABORT
    1606-        if (ScanResult::FAILURE == ScanForWalletTransactions(startBlock, nullptr, reserver, failedBlock, stop_block, update)) {
    1607-            return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1;
    1608+        if (ScanResult::FAILURE == ScanForWalletTransactions(start_block, {} /* stop block */, reserver, failed_block, stop_block, update)) {
    


    jnewbery commented at 10:54 pm on January 25, 2019:
    Nit: comment should be /* last block */

    ryanofsky commented at 9:47 pm on January 28, 2019:

    re: #14711 (review)

    Nit: comment should be /* last block */

    fixed

  73. in src/wallet/wallet.cpp:1643 in 1da8b4648e outdated
    1648+    failed_block.SetNull();
    1649+    stop_block.SetNull();
    1650+    ScanResult result = ScanResult::SUCCESS;
    1651 
    1652-    if (pindex) WalletLogPrintf("Rescan started from block %d...\n", pindex->nHeight);
    1653+    WalletLogPrintf("Rescan started from block %s...\n", first_block.ToString());
    


    jnewbery commented at 11:00 pm on January 25, 2019:
    Behaviour change: This changes the log message from logging the height to logging the block hash. Is that intentional?

    ryanofsky commented at 9:06 pm on January 28, 2019:

    Behaviour change: This changes the log message from logging the height to logging the block hash. Is that intentional?

    This seemed like the easiest thing to print without acquiring cs_main. Added a note about the behavior change in the commit message, but could update the print instead if you think that’s a better idea.

  74. in src/wallet/wallet.cpp:1682 in 1da8b4648e outdated
    1699-                if (pindex && !chainActive.Contains(pindex)) {
    1700+                if (!locked_chain->getBlockHeight(block_hash)) {
    1701                     // Abort scan if current block is no longer active, to prevent
    1702                     // marking transactions as coming from the wrong block.
    1703-                    failed_block = pindex;
    1704+                    failed_block = block_hash;
    


    jnewbery commented at 11:19 pm on January 25, 2019:
    Behaviour change: I think in this case the function will return ScanResult::SUCCESS where previously it returned ScanResult::FAILURE

    ryanofsky commented at 9:05 pm on January 28, 2019:

    re: #14711 (review)

    Behaviour change: I think in this case the function will return ScanResult::SUCCESS where previously it returned ScanResult::FAILURE

    Great catch, this should be fixed now. I added a todo to change this to SUCCESS in the future though, since I think that is right thing to do (see #14711 (comment)).

  75. in src/wallet/rpcwallet.cpp:3429 in 1da8b4648e outdated
    3446 
    3447-    const CBlockIndex *failed_block, *stopBlock;
    3448+    uint256 failed_block, stop_block;
    3449     CWallet::ScanResult result =
    3450-        pwallet->ScanForWalletTransactions(pindexStart, pindexStop, reserver, failed_block, stopBlock, true);
    3451+        pwallet->ScanForWalletTransactions(first_block, last_block, reserver, failed_block, stop_block, true /* prune */);
    


    jnewbery commented at 11:28 pm on January 25, 2019:
    Nit: comment should be /* fUpdate */

    ryanofsky commented at 9:47 pm on January 28, 2019:

    re: #14711 (review)

    Nit: comment should be /* fUpdate */

    fixed

  76. in src/wallet/rpcwallet.cpp:3423 in 1da8b4648e outdated
    3438+            throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
    3439+        }
    3440+
    3441+        if (tip_height) {
    3442+            first_block = locked_chain->getBlockHash(start_height);
    3443+            last_block = locked_chain->getBlockHash(stop_height.value_or(*tip_height));
    


    jnewbery commented at 11:41 pm on January 25, 2019:

    Behaviour change: previously, calling rescanblockchain() without a stop_height would cause ScanForWalletTransactions() to be called without a pIndexStop. Since ScanForWalletTransactions() releases cs_main after every block scanned, if the tip advances during rescan, then ScanForWalletTransactions() will scan to the new tip.

    This change sets the last_block to the tip at the time that the RPC is called. That means that the rescan will not go all the way to the tip if the tip advances during rescan.


    ryanofsky commented at 9:05 pm on January 28, 2019:

    re: #14711 (review)

    the rescan will not go all the way to the tip if the tip advances during rescan

    Fixed, but after this change, it also wasn’t right to return the original tip_height as stop_height, so I changed ScanForWalletTransactions to return a stop_height, and moved all its return values into a struct to avoid having too many output parameters.

  77. in src/wallet/wallet.cpp:1708 in 1da8b4648e outdated
    1733-                pindex = chainActive.Next(pindex);
    1734-                progress_current = GuessVerificationProgress(chainParams.TxData(), pindex);
    1735-                if (pindexStop == nullptr && tip != chainActive.Tip()) {
    1736-                    tip = chainActive.Tip();
    1737+                if (Optional<int> tip_height = locked_chain->getHeight()) {
    1738+                    if (locked_chain->getBlockHeight(prev_block_hash) && prev_block_height < *tip_height) {
    


    jnewbery commented at 11:44 pm on January 25, 2019:

    Suggestion: invert the logic and add an explicit break here. It’s a bit convoluted that block_height is reset above, and then if these conditions hold, it’s updated, and then in the while condition if it’s still null, then we break. I think this is clearer:

    0if (!locked_chain->getBlockHeight(prev_block_hash) || !prev_block_height < *tip_height) {
    1    // rescan has reached the tip
    2    break;
    3}
    

    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    Suggestion: invert the logic and add an explicit break here

    Done, good suggestion

  78. in src/interfaces/chain.h:61 in 1da8b4648e outdated
    56+        virtual int64_t getBlockTime(int height) = 0;
    57+
    58+        //! Get block median time past.
    59+        virtual int64_t getBlockMedianTimePast(int height) = 0;
    60+
    61+        //! Check that the full block is available on disk (ie has not been
    


    jnewbery commented at 11:48 pm on January 25, 2019:
    Nit: remove the word ‘full’ here

    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    Nit: remove the word ‘full’ here

    done

  79. in src/interfaces/chain.h:96 in 1da8b4648e outdated
    91+        virtual bool isPotentialTip(const uint256& hash) = 0;
    92+
    93+        //! Get locator for the current chain tip.
    94+        virtual CBlockLocator getLocator() = 0;
    95+
    96+        //! Return height of block on the chain using locator.
    


    jnewbery commented at 11:57 pm on January 25, 2019:
    Nit: This comment isn’t quite right. The function returns “the latest block common to locator and chain”, which is guaranteed to be an ancestor of the block on the active chain.

    ryanofsky commented at 9:46 pm on January 28, 2019:

    re: #14711 (review)

    This comment isn’t quite right

    Added your correction

  80. jnewbery commented at 0:03 am on January 26, 2019: member

    A bunch of nits, which can be ignored or addressed in a follow-up PR.

    I do think you’ve changed the behaviour in a couple of places, notably in rescanblockchain(). That should be addressed before merge.

  81. MarcoFalke commented at 9:00 pm on January 28, 2019: member
    • re-utACK 2ffb07929e
    • utACK HEAD
  82. MarcoFalke commented at 10:40 pm on January 28, 2019: member
    Will review further after #14711 (review) has been fixed. Also, I clarified the documentation of the rpc in that we follow the chain in case it “runs ahead” during the rpc (https://github.com/bitcoin/bitcoin/pull/15279)
  83. ryanofsky commented at 11:21 pm on January 28, 2019: member

    John’s comment #14711 (review) made me realize there seems to be a minor race condition and inconsistent behavior in the current implementation of ScanForWalletTransactions. If there is a reorg while cs_main is unlocked, there are two different checks to handle the case that pindex is no longer on the new chain. One of these checks will return ScanResult::SUCCESS while the other will return ScanResult::FAILURE, and which check is hit will depend the on timing of ReadBlockFromDisk and SyncTransactions calls.

    The check after the ReadBlockFromDisk call leads to ScanResult::FAILURE:

    https://github.com/bitcoin/bitcoin/blob/d6e700e40f861ddd6743f4d13f0d6f6bc19093c2/src/wallet/wallet.cpp#L1677

    The check after the SyncTransactions loop leads to ScanResult::SUCCESS:

    https://github.com/bitcoin/bitcoin/blob/d6e700e40f861ddd6743f4d13f0d6f6bc19093c2/src/wallet/wallet.cpp#L1697 https://github.com/bitcoin/bitcoin/blob/d6e700e40f861ddd6743f4d13f0d6f6bc19093c2/src/wallet/wallet.cpp#L1664

    It seems like the better thing to do would be return SUCCESS in both cases, since any blocks attached in a reorg should already be scanned for wallet transactions. Returning SUCCESS in both cases is the behavior currently implemented in this PR, but I think I should add some comments about it to clarify and maybe open a separate PR to avoid changing the behavior here.

  84. MarcoFalke commented at 6:24 pm on January 29, 2019: member
    I’d prefer to keep this refactoring-only and would suggest to open a pr for that either before or after this one is merged.
  85. ryanofsky force-pushed on Jan 29, 2019
  86. ryanofsky commented at 8:49 pm on January 29, 2019: member

    Updated 1da8b4648e6b5f01a90acfe487bcda6f7a5a0424 -> 44de1561aaf7556bb8ae8b582c233742ff76767d (pr/wchain2.9 -> pr/wchain2.10, compare) implementing suggestions from John.


    re: #14711 (comment)

    I’d prefer to keep this refactoring-only and would suggest to open a pr for that either before or after this one is merged.

    Agreed. I just added a TODO referencing #14711 (comment). I was going to open a new PR too, but it turns out to be difficult to write a test for the new behavior, so I am putting it off for now.

  87. in src/wallet/rpcwallet.cpp:3419 in db21f02648 outdated
    3432+        // We can't rescan beyond non-pruned blocks, stop and throw an error
    3433+        if (locked_chain->findPruned(start_height, stop_height)) {
    3434+            throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
    3435+        }
    3436+
    3437+        if (tip_height) {
    


    MarcoFalke commented at 9:34 pm on January 29, 2019:

    In commit db21f02648 Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis

    nit: Not sure why you check for this. In current operation tip_height is never nullopt, and when that should change in the future, you might as well return with an early error instead of calling into ScanForWalletTransactions, whose documentation states that the start block is required to be set. (I know that it probably will pass through just fine even if it is not provided, but we shouldn’t rely on that. I also know that there is a unit test to check that behaviour, but it was probably added because of a misunderstanding of the documentation of ScanForWalletTransactions).


    ryanofsky commented at 9:13 pm on January 30, 2019:

    re: #14711 (review)

    nit: Not sure why you check for this

    In this case even though “documentation states” and “In current operation” the chain will never be empty, I think handling a rescan of an empty chain by just returning success is more natural than making assumptions about when the chain is initialized or what other code expects it to be initialized. If you think adding the assumption will simplify things, though, I’d be happy to take a specific suggestion or review a change.


    MarcoFalke commented at 7:24 pm on February 4, 2019:

    I think handling a rescan of an empty chain by just returning success …

    It would also report that the rescan started at block 0, which does not exist, since the chain was not initialized.

    A user calling this function assumes that the chain was initialized and should be notified that it wasn’t instead of returning {start_height=0, stop_height=null}, indicating success.

    Also, we already throw an error if the chain wasn’t initialized and the user supplies at least one of the optional parameters.

    I’d suggest the following code change:

     0diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
     1index c96a9b0aff..ba8d3750b5 100644
     2--- a/src/wallet/rpcwallet.cpp
     3+++ b/src/wallet/rpcwallet.cpp
     4@@ -3432,22 +3432,27 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
     5     uint256 start_block, stop_block;
     6     {
     7         auto locked_chain = pwallet->chain().lock();
     8-        Optional<int> tip_height = locked_chain->getHeight();
     9+        int tip_height;
    10+        if (Optional<int> tip_height_opt = locked_chain->getHeight()) {
    11+            tip_height = *tip_height_opt;
    12+        } else {
    13+            throw JSONRPCError(RPC_MISC_ERROR, "Chain not initialized, nothing to rescan");
    14+        }
    15 
    16         if (!request.params[0].isNull()) {
    17             start_height = request.params[0].get_int();
    18-            if (start_height < 0 || !tip_height || start_height > *tip_height) {
    19-                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
    20-            }
    21+        }
    22+        if (start_height < 0 || start_height > tip_height) {
    23+            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
    24         }
    25 
    26         Optional<int> stop_height;
    27         if (!request.params[1].isNull()) {
    28             stop_height = request.params[1].get_int();
    29-            if (*stop_height < 0 || !tip_height || *stop_height > *tip_height) {
    30+            if (*stop_height < 0 || *stop_height > tip_height) {
    31                 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
    32             }
    33-            else if (*stop_height < start_height) {
    34+            if (*stop_height < start_height) {
    35                 throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater than start_height");
    36             }
    37         }
    38@@ -3457,11 +3462,9 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
    39             throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
    40         }
    41 
    42-        if (tip_height) {
    43-            start_block = locked_chain->getBlockHash(start_height);
    44-            if (stop_height) {
    45-                stop_block = locked_chain->getBlockHash(*stop_height);
    46-            }
    47+        start_block = locked_chain->getBlockHash(start_height);
    48+        if (stop_height) {
    49+            stop_block = locked_chain->getBlockHash(*stop_height);
    50         }
    51     }
    52 
    
  88. in src/wallet/rpcwallet.cpp:3440 in db21f02648 outdated
    3460     }
    3461     UniValue response(UniValue::VOBJ);
    3462-    response.pushKV("start_height", pindexStart->nHeight);
    3463-    response.pushKV("stop_height", stopBlock->nHeight);
    3464+    response.pushKV("start_height", start_height);
    3465+    response.pushKV("stop_height", result.stop_height ? *result.stop_height : UniValue());
    


    MarcoFalke commented at 9:48 pm on January 29, 2019:

    db21f02648 Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis

    nit: In line with my previous comment, I’d prefer if we either assumed that stop_height is always set or we return an error. An alternative would be to adjust the documentation of the rpc result to mention that in (whatever obscure circumstances) stop_height might be null, but I’d prefer to throw an rpc error for such circumstances.


    ryanofsky commented at 8:39 pm on January 30, 2019:

    re: #14711 (review)

    An alternative would be to adjust the documentation of the rpc result to mention that in (whatever obscure circumstances) stop_height might be null

    Updated documentation, this could happen rarely during a reorg

  89. in src/wallet/wallet.cpp:1604 in db21f02648 outdated
    1606-            return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1;
    1607+        ScanResult result = ScanForWalletTransactions(start_block, {} /* stop_block */, reserver, update);
    1608+        if (result.status == ScanResult::FAILURE) {
    1609+            int64_t time_max;
    1610+            if (!chain().findBlock(result.failed_block, nullptr /* block */, nullptr /* time */, &time_max)) {
    1611+                throw std::logic_error("ScanForWalletTransactions returned invalid block hash");
    


    MarcoFalke commented at 9:59 pm on January 29, 2019:

    in commit db21f02648 Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis

    unrelated request: I’d prefer if we had some guideline on when to use assert vs std::logic_error. This seems like a condition that can never be hit unless there is a coding error, in which case an assert appears more appropriate.


    ryanofsky commented at 8:40 pm on January 30, 2019:

    re: #14711 (review)

    This seems like a condition that can never be hit unless there is a coding error, in which case an assert appears more appropriate.

    I don’t think logic_error means anything different from assert. https://en.cppreference.com/w/cpp/error/logic_error at least says “It reports errors that are a consequence of faulty logic within the program.” I would use an assert over a logic error only in cases where it seemed safer to abort the entire process than to just abort the current request. Or maybe to match preexisting code.

  90. in src/wallet/wallet.cpp:1618 in db21f02648 outdated
    1626- * @param[out] failed_block if FAILURE is returned, the most recent block
    1627- *     that could not be scanned, otherwise nullptr
    1628- * @param[out] stop_block the most recent block that could be scanned,
    1629- *     otherwise nullptr if no block could be scanned
    1630+ * @param[in] start_block if not null, the scan will start at this block instead
    1631+ *            of the genesis block
    


    MarcoFalke commented at 10:02 pm on January 29, 2019:

    in commit db21f02648 Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis

    Is this correct? It seems that without a start_block, we’d just “fall through” and return instead of starting at the genesis block.


    ryanofsky commented at 8:40 pm on January 30, 2019:

    re: #14711 (review)

    Is this correct?

    Good catch, fixed comment

  91. in src/wallet/wallet.cpp:1630 in 44de1561aa
    1640+ * @pre Caller needs to make sure start_block (and the optional stop_block) are on
    1641  * the main chain after to the addition of any new keys you want to detect
    1642  * transactions for.
    1643  */
    1644-CWallet::ScanResult CWallet::ScanForWalletTransactions(const CBlockIndex* const pindexStart, const CBlockIndex* const pindexStop, const WalletRescanReserver& reserver, const CBlockIndex*& failed_block, const CBlockIndex*& stop_block, bool fUpdate)
    1645+CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, const uint256& stop_block, const WalletRescanReserver& reserver, bool fUpdate)
    


    jnewbery commented at 10:08 pm on January 29, 2019:

    With this rename of the second parameter (last_block -> stop_block) we now have a parameter named stop_block and a member in the return object called stop_block which refer to different things. I think this should change back to last_block to match the header file, and the several inline comments should be updated to say last_block.

    EDIT: I see the RPC params are called start_block and stop_block, so this parameter naming does make sense. Could you rename the members of the return object and update the parameter names in the header file?


    ryanofsky commented at 8:40 pm on January 30, 2019:

    re: #14711 (review)

    Could you rename the members of the return object and update the parameter names in the header file?

    done

  92. in src/wallet/wallet.cpp:1621 in 44de1561aa
    1629+ * @param[in] start_block if not null, the scan will start at this block instead
    1630+ *            of the genesis block
    1631+ * @param[in] stop_block if not null, the scan will stop at this block instead
    1632+ *            of the chain tip
    1633  *
    1634  * @return ScanResult indicating success or failure of the scan. SUCCESS if
    


    jnewbery commented at 10:09 pm on January 29, 2019:
    Needs updating now that ScanResult is an object.

    ryanofsky commented at 8:40 pm on January 30, 2019:

    re: #14711 (review)

    Needs updating now that ScanResult is an object.

    done

  93. in src/wallet/wallet.cpp:1719 in db21f02648 outdated
    1765-            return ScanResult::USER_ABORT;
    1766-        } else if (pindex && ShutdownRequested()) {
    1767-            WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, progress_current);
    1768-            return ScanResult::USER_ABORT;
    1769+        if (block_height && fAbortRescan) {
    1770+            WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height.value_or(0), progress_current);
    


    MarcoFalke commented at 10:19 pm on January 29, 2019:

    in commit db21f02648 Convert CWallet::ScanForWalletTransactions and SyncTransaction to the new Chain apis

    nit: the condition checks for block_height, so the value_or is dead code and can be removed?


    ryanofsky commented at 8:40 pm on January 30, 2019:

    re: #14711 (review)

    the value_or is dead code and can be removed?

    Good catch, removed

  94. in src/wallet/wallet.cpp:1722 in db21f02648 outdated
    1768-            return ScanResult::USER_ABORT;
    1769+        if (block_height && fAbortRescan) {
    1770+            WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height.value_or(0), progress_current);
    1771+            result.status = ScanResult::USER_ABORT;
    1772+        } else if (block_height && ShutdownRequested()) {
    1773+            WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height.value_or(0), progress_current);
    


    MarcoFalke commented at 10:19 pm on January 29, 2019:
    same

    ryanofsky commented at 8:41 pm on January 30, 2019:

    re: #14711 (review)

    same

    now removed

  95. in src/wallet/rpcwallet.cpp:3421 in 44de1561aa
    3434+            throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
    3435+        }
    3436+
    3437+        if (tip_height) {
    3438+            start_block = locked_chain->getBlockHash(start_height);
    3439+            if (stop_height) {
    


    jnewbery commented at 10:25 pm on January 29, 2019:

    A comment here could prevent other people from falling into the same trap. Something like:

    0// If called with a stop_height, set the stop_height here to trigger a rescan to that height.
    1// If called without a stop height, leave stop_height as null here so rescan continues to the tip (even if the tip advances during rescan).
    

    ryanofsky commented at 8:39 pm on January 30, 2019:

    re: #14711 (review)

    A comment here could prevent other people from falling into the same trap. Something like:

    added

  96. in src/interfaces/chain.cpp:126 in 44de1561aa
    121+    {
    122+        if (::chainActive.Tip()->GetBlockHash() == hash) return true;
    123+        CBlockIndex* block = LookupBlockIndex(hash);
    124+        return block && block->GetAncestor(::chainActive.Height()) == ::chainActive.Tip();
    125+    }
    126+    CBlockLocator getLocator() override { return ::chainActive.GetLocator(); }
    


    MarcoFalke commented at 10:26 pm on January 29, 2019:

    in commit 44de1561aa

    Could say getTipLocator()?


    ryanofsky commented at 8:39 pm on January 30, 2019:

    re: #14711 (review)

    Could say getTipLocator()?

    fixed

  97. jnewbery commented at 10:37 pm on January 29, 2019: member

    (reviewing 44de1561aaf7556bb8ae8b582c233742ff76767d)

    Looks great. Thanks for being so receptive to my review comments! I have just three more inline, all to do with comments and naming.

    utACK 44de1561aaf7556bb8ae8b582c233742ff76767d. Comments can be cleaned up in a follow-up PR if necessary.

  98. MarcoFalke approved
  99. MarcoFalke commented at 10:48 pm on January 29, 2019: member

    utACK 44de1561aa

    Couldn’t find any issues with the code, just some questions on documentation and code-style.

  100. meshcollider merged this on Jan 30, 2019
  101. meshcollider closed this on Jan 30, 2019

  102. meshcollider referenced this in commit 72ca72e637 on Jan 30, 2019
  103. meshcollider commented at 0:05 am on January 30, 2019: contributor
    Agreed, any comments/nits can be addressed in followup
  104. ryanofsky commented at 12:13 pm on January 30, 2019: member

    Thanks for reviews, all! I will follow up with the remaining unaddressed comments.

    The next PR in the series is #15288 (which is much simpler than this PR)

  105. jnewbery removed this from the "Blockers" column in a project

  106. laanwj referenced this in commit cb77dc820f on Jan 30, 2019
  107. ryanofsky referenced this in commit 95a812b599 on Feb 4, 2019
  108. ryanofsky referenced this in commit a8d645c934 on Feb 4, 2019
  109. ryanofsky referenced this in commit db2d093233 on Feb 4, 2019
  110. ryanofsky referenced this in commit 2efa66b464 on Feb 4, 2019
  111. ryanofsky referenced this in commit 84adb206fc on Feb 4, 2019
  112. ryanofsky referenced this in commit 2c1fbaa771 on Feb 4, 2019
  113. ryanofsky referenced this in commit aebafd0edf on Feb 4, 2019
  114. ryanofsky commented at 4:49 pm on February 4, 2019: member
    Suggested changes are in #15342
  115. MarcoFalke referenced this in commit bbdcc0b0ff on Feb 5, 2019
  116. HashUnlimited referenced this in commit ba69c684cb on Feb 5, 2019
  117. HashUnlimited referenced this in commit a6e4e5decc on Feb 5, 2019
  118. HashUnlimited referenced this in commit 1ea954f43b on Feb 5, 2019
  119. HashUnlimited referenced this in commit db2c9bdda9 on Feb 5, 2019
  120. HashUnlimited referenced this in commit b0a934f0eb on Feb 5, 2019
  121. HashUnlimited referenced this in commit 2ab199d828 on Feb 5, 2019
  122. HashUnlimited referenced this in commit 0c4d9fe84f on Feb 5, 2019
  123. meshcollider referenced this in commit 2607d960a0 on Mar 21, 2019
  124. ariard referenced this in commit d43bff5e29 on Mar 26, 2019
  125. ariard referenced this in commit 765c0b364d on Mar 27, 2019
  126. MarcoFalke referenced this in commit 56376f3365 on Apr 19, 2019
  127. HashUnlimited referenced this in commit 5f4e8d36cb on Aug 30, 2019
  128. deadalnix referenced this in commit 28b138c1a9 on Apr 10, 2020
  129. ftrader referenced this in commit 807811743e on Aug 17, 2020
  130. kittywhiskers referenced this in commit 6486787f43 on Oct 16, 2021
  131. kittywhiskers referenced this in commit 5d1e8a12c5 on Oct 16, 2021
  132. PastaPastaPasta referenced this in commit 1ada50fee0 on Oct 23, 2021
  133. PastaPastaPasta referenced this in commit d5723b805a on Oct 23, 2021
  134. PastaPastaPasta referenced this in commit 3e8670d81a on Oct 24, 2021
  135. PastaPastaPasta referenced this in commit 0ad7780ae1 on Oct 24, 2021
  136. PastaPastaPasta referenced this in commit df0373cd76 on Oct 25, 2021
  137. PastaPastaPasta referenced this in commit b4a0369af8 on Oct 25, 2021
  138. PastaPastaPasta referenced this in commit 1834aa9a9a on Oct 25, 2021
  139. PastaPastaPasta referenced this in commit 75eea2cdb0 on Oct 25, 2021
  140. kittywhiskers referenced this in commit ce06a981f4 on Oct 31, 2021
  141. kittywhiskers referenced this in commit 348fe236f7 on Oct 31, 2021
  142. PastaPastaPasta referenced this in commit 75fda781df on Nov 1, 2021
  143. PastaPastaPasta referenced this in commit a941bfc417 on Nov 1, 2021
  144. PastaPastaPasta referenced this in commit 051bdef7f5 on Nov 1, 2021
  145. PastaPastaPasta referenced this in commit c77a227ab9 on Nov 1, 2021
  146. PastaPastaPasta referenced this in commit 48826b429d on Nov 3, 2021
  147. PastaPastaPasta referenced this in commit dfa040e9b9 on Nov 3, 2021
  148. pravblockc referenced this in commit a7a32011d3 on Nov 18, 2021
  149. pravblockc referenced this in commit 30cf1bbae2 on Nov 18, 2021
  150. DrahtBot locked this on Dec 16, 2021

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: 2024-11-17 06:12 UTC

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