rpc: add optional blockhash to waitfornewblock, unhide in help #30635

pull Sjors wants to merge 2 commits into bitcoin:master from Sjors:2024/08/waitforblock changing 3 files +27 −6
  1. Sjors commented at 11:42 am on August 12, 2024: member

    The waitfornewblock is inherently racy as the tip may have changed since the last RPC call, and can even change during initial processing of this call.

    Add an optional blockhash argument so the caller can specify their current tip. Return immediately if our tip is different.

    I’ve made it fail if LookupBlockIndex fails. This should never happen if the user got the block hash from our RPC in the first place.

    Finally, waitfornewblock is no longer hidden in help.

  2. DrahtBot commented at 11:42 am on August 12, 2024: contributor

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

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/30635.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Stale ACK ryanofsky

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    No conflicts as of last run.

  3. DrahtBot added the label RPC/REST/ZMQ on Aug 12, 2024
  4. Sjors force-pushed on Aug 12, 2024
  5. Sjors force-pushed on Aug 12, 2024
  6. Sjors force-pushed on Aug 12, 2024
  7. Sjors force-pushed on Aug 13, 2024
  8. DrahtBot added the label Needs rebase on Sep 2, 2024
  9. Sjors force-pushed on Sep 3, 2024
  10. DrahtBot removed the label Needs rebase on Sep 3, 2024
  11. DrahtBot added the label Needs rebase on Sep 3, 2024
  12. Sjors force-pushed on Sep 4, 2024
  13. DrahtBot removed the label Needs rebase on Sep 4, 2024
  14. DrahtBot added the label CI failed on Sep 7, 2024
  15. DrahtBot removed the label CI failed on Sep 9, 2024
  16. DrahtBot added the label Needs rebase on Sep 9, 2024
  17. Sjors force-pushed on Sep 10, 2024
  18. DrahtBot removed the label Needs rebase on Sep 10, 2024
  19. DrahtBot added the label CI failed on Sep 10, 2024
  20. DrahtBot added the label Needs rebase on Sep 12, 2024
  21. Sjors force-pushed on Sep 17, 2024
  22. DrahtBot removed the label Needs rebase on Sep 17, 2024
  23. DrahtBot removed the label CI failed on Sep 17, 2024
  24. Sjors force-pushed on Sep 26, 2024
  25. Sjors commented at 8:14 am on September 26, 2024: member
    Now that #30409 landed this is a single commit, and ready for review.
  26. Sjors marked this as ready for review on Sep 26, 2024
  27. Panga9309 approved
  28. in src/rpc/blockchain.cpp:303 in 13b867fb9b outdated
    298+            block.hash = block_index->GetBlockHash();
    299+            block.height = block_index->nHeight;
    300+        }
    301+    }
    302+
    303     if (IsRPCRunning()) {
    


    maflcko commented at 8:23 am on September 27, 2024:
    unrelated bug: But the GUI never sets this, unless -server is passed. So no code will run and what was passed in will be returned, incorrectly.

    Sjors commented at 11:05 am on September 27, 2024:
    So this effects GUI users that use the console, rather than bitcoin-cli?

    Sjors commented at 3:50 pm on November 19, 2024:

    The latest version gets rid of this check entirely.

    IIUC it wasn’t needed here in the first place. The other waitfor RPC calls use this to see if they need to break out of their while loop each time a new block comes in (or interrupt happened).

  29. in src/rpc/blockchain.cpp:265 in 13b867fb9b outdated
    261@@ -262,6 +262,7 @@ static RPCHelpMan waitfornewblock()
    262                 "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
    263                 {
    264                     {"timeout", RPCArg::Type::NUM, RPCArg::Default{0}, "Time in milliseconds to wait for a response. 0 indicates no timeout."},
    265+                    {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "Last known block hash. Returns immediately if the tip is different."},
    


    ryanofsky commented at 2:55 pm on October 8, 2024:

    In commit “rpc: add optional blockhash to waitfornewblock” (13b867fb9b37fef3f14732904172e4ecba6fc973)

    Maybe use phrasing from fa4c0750331f36121ba92bbc2f22c615b7934e52 and say “Method waits for the chain tip to differ from this.” I think that’s a little better because it describes behavior in general instead of describing a specific case where it returns immediately. I think it would also be better to call this current_tip instead of blockhash like the other variable, to be more descriptive.

  30. in src/rpc/blockchain.cpp:305 in 13b867fb9b outdated
    300+        }
    301+    }
    302+
    303     if (IsRPCRunning()) {
    304         block = timeout ? miner.waitTipChanged(block.hash, std::chrono::milliseconds(timeout)) : miner.waitTipChanged(block.hash);
    305     }
    


    ryanofsky commented at 3:20 pm on October 8, 2024:

    I think it would be good to simplify all of this to just:

    0    // Use tip as reference block, unless a block hash was provided.
    1    uint256 current_tip{request.params[1].isNull()
    2        ? miner.getTip().value_or(BlockRef{}).hash
    3        : ParseHashV(request.params[1], "blockhash")};
    4
    5    BlockRef block{timeout > 0
    6        ? miner.waitTipChanged(current_tip, std::chrono::milliseconds(timeout))
    7        : miner.waitTipChanged(current_tip)};
    

    In addition to being simpler, this would fix a number of problems and inconveniences of the current implementation:

    • If an unrecognized block hash was passed, it would make the RPC return the current block tip instead of throwing an exception.
    • If no block hash was passed and tip was null, it would make the RPC wait for a block to be connected instead of throwing an exception.
    • It would fix the bug marco described #30635 (review) where this function does not wait in the GUI console.
  31. ryanofsky approved
  32. ryanofsky commented at 3:25 pm on October 8, 2024: contributor
    Code review ACK 13b867fb9b37fef3f14732904172e4ecba6fc973. I think implementation could be a ilttle simpler and more friendly though (see suggestion below)
  33. in src/rpc/blockchain.cpp:300 in 13b867fb9b outdated
    295+            if (!block_index) {
    296+                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
    297+            }
    298+            block.hash = block_index->GetBlockHash();
    299+            block.height = block_index->nHeight;
    300+        }
    


    luke-jr commented at 9:50 pm on November 14, 2024:
    Why do all this? Can’t we just compare hash to block and return?
  34. Sjors commented at 8:24 am on November 15, 2024: member
    @ryanofsky & @luke-jr thanks for reviewing, will address feedback soon(tm).
  35. Sjors force-pushed on Nov 19, 2024
  36. Sjors commented at 3:47 pm on November 19, 2024: member
    I took @ryanofsky’s suggestion: #30635 (review)
  37. in src/rpc/blockchain.cpp:302 in c305ad5b06 outdated
    290-        block = timeout ? miner.waitTipChanged(block.hash, std::chrono::milliseconds(timeout)) : miner.waitTipChanged(block.hash);
    291-    }
    292+    // Use tip as reference block, unless a block hash was provided.
    293+    uint256 current_tip{request.params[1].isNull()
    294+        ? miner.getTip().value_or(BlockRef{}).hash
    295+        : ParseHashV(request.params[1], "current_tip")};
    


    ryanofsky commented at 1:15 am on November 21, 2024:

    In commit “rpc: add optional blockhash to waitfornewblock” (c305ad5b06545497752b2f12d8d9f72e8a6c2941)

    Might be useful if comment explained the different cases here. Maybe: // If caller provided a current_tip value, pass it to waitTipChanged. If the caller did not provide a current tip hash, call getTip() to get one and wait for the tip to be different from this value. (This mode is less reliable because if the tip changed between waitfornewblock calls, it will need to change a second time before this call returns.) If getTip() returns null, which can happen during startup, pass 0 to waitTipChanged() so it will wait for any tip hash to be set.


    Sjors commented at 12:35 pm on November 21, 2024:
    Added
  38. in src/rpc/blockchain.cpp:287 in c305ad5b06 outdated
    284@@ -283,10 +285,14 @@ static RPCHelpMan waitfornewblock()
    285     NodeContext& node = EnsureAnyNodeContext(request.context);
    286     Mining& miner = EnsureMining(node);
    287 
    288-    auto block{CHECK_NONFATAL(miner.getTip()).value()};
    289-    if (IsRPCRunning()) {
    


    ryanofsky commented at 1:27 am on November 21, 2024:

    In commit “rpc: add optional blockhash to waitfornewblock” (c305ad5b06545497752b2f12d8d9f72e8a6c2941)

    Note: dropping IsRPCRunning call is a minor change in behavior, but probably a good one, as it should let the waitfornewblock function in the GUI console even if the RPC server is not enabled. In any case it is safe to drop this because waitTipChanged already will return if the node is shutting down.


    Sjors commented at 12:26 pm on November 21, 2024:

    Good point. Just tested that that’s indeed the case. I’ll mention that in the commit message.

    cc @hebasto

  39. ryanofsky approved
  40. ryanofsky commented at 1:29 am on November 21, 2024: contributor
    Code review ACK c305ad5b06545497752b2f12d8d9f72e8a6c2941. This is a nice change that should make the RPC (and test) more reliable, and the implementation seems to be pretty simple now.
  41. rpc: add optional blockhash to waitfornewblock
    This RPC method now also works in the GUI console when the RPC
    server is not enabled.
    5153dbd114
  42. Sjors force-pushed on Nov 21, 2024
  43. Sjors commented at 12:36 pm on November 21, 2024: member
    Rebased, added comment and expanded commit message to note the GUI improvement.
  44. rpc: unhide waitfornewblock
    This method is not dangerous and since the previous commit it no longer requires GUI users to enable the RPC server.
    1f8808d411
  45. Sjors commented at 12:53 pm on November 21, 2024: member

    I added a commit to make waitfornewblock visible in help. It was introduced in 2016 by #8680 as a quick fix to deal with CI failures.

    At this point is seem mature enough, no longer has weird quirks like requiring GUI users to enable the RPC server, it’s probably actually useful and at least one library uses it anyway. So it seems fine to list it.

  46. Sjors renamed this:
    rpc: add optional blockhash to waitfornewblock
    rpc: add optional blockhash to waitfornewblock, unhide in help
    on Nov 21, 2024

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-21 15:12 UTC

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