-
Notifications
You must be signed in to change notification settings - Fork 37k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rpc: getblockfrompeer #20295
rpc: getblockfrompeer #20295
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
@Sjors Please note that I'm very new to C++ and I'm here only to learn. Concept AKN, IMO can also be useful if the user need info about a pruned block. Not sure if Also, IMO Check if the node is connected Mark the block as in flight |
@Fi3 being able to (temporarily) retrieve pruned blocks is useful too indeed. It can be difficult to find nodes that still have a stale block, so I'd rather hold on to it. That also allows inspection using the regular methods, I also want to be able to fully validate the block. It's very time consuming, but it works: call |
1a192c4
to
f74c19e
Compare
Concept ACK This would be useful for https://forkmonitor.info/ to assess the validity of shorter chains |
Concept ACK This would be very useful for testing |
I agree, didn't consider it. |
Concept -1 I think it would be better to just do the right thing if you |
@luke-jr my thinking was to expand it later, to try all peers: In practice none of the existing peers might have it, so you'll have to:
This could get complicated, so a fresh RPC seemed like a more future proof approach. |
f74c19e
to
513e38f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tested ACK 9181e2e
I think this is ready to be merged as-is and my comments below can be addressed in a follow-up.
The documentation should be improved on how long users can expect this block to be around on a pruned node. If someone uses this on a prune=550
node, for example, this may become confusing for certain use cases. I made a suggestion in my comment but I can also propose this in a follow-up PR since it might require further discussion.
I also wrote an additional test for the pruned node use case here. Feel free to add it here if you have to retouch, otherwise, I will open a follow-up PR with it.
return RPCHelpMan{"getblockfrompeer", | ||
"\nAttempt to fetch block from a given peer.\n" | ||
"\nWe must have the header for this block, e.g. using submitheader.\n" | ||
"\nReturns {} if a block-request was successfully scheduled\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be good to add more information for pruned node users of how long the block will be around. If my understanding is correct, something like this: Note: On a pruned node this block will be pruned again when the pruneheight surpasses the blockheight at the time of fetching the block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even that is not guaranteed at the moment (albeit very likely to hold in practice).
Combined with #19463, the caller could set a prune lock to ensure it doesn't get re-pruned before the caller is done with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far I wasn't able to figure out in which cases this could not be guaranteed. I opened a follow-up PR in #23813. Please let me know if you have suggestions on improving the text there. Sure #19463 can be helpful but my aim with this for now is to just make sure that users don't get wrong expectations, like that the block would be available forever for example.
434dbbc
to
4edaf67
Compare
Co-authored-by: John Newbery <john@johnnewbery.com>
4edaf67
to
dce8c4c
Compare
ACK dce8c4c |
re-ACK dce8c4c |
@@ -1427,6 +1428,41 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex) | |||
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT); | |||
} | |||
|
|||
bool PeerManagerImpl::FetchBlock(NodeId id, const uint256& hash, const CBlockIndex& index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about returning the error string on failure std::optional<std::string>
?
The caller could then
if(const auto err{Fetch()}){
throw err.value();
}
This will make users and tests more happy
if (!state->fHaveWitness) return false; | ||
|
||
// Mark block as in-flight unless it already is | ||
if (!BlockRequested(id, index)) return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a comment that this will re-assign the block if it is in flight from another peer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll also update the RPC doc, because it looks like BLOCKTXN
are ignored entirely if they're no longer on the in flight list for a given peer.
hash.ToString(), id); | ||
} else { | ||
RemoveBlockRequest(hash); | ||
LogPrint(BCLog::NET, "Failed to request block %s from peer=%d\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems odd to log a failure to the debug log on an rpc call. I'd expect the error to go to the user instead. Also, shouldn't this say "peer not found"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already check that the peer exists above, so the failure would be "not fully connected"; changed...
|
||
// Check that the peer with nodeid exists | ||
if (!connman.ForNode(nodeid, [](CNode* node) {return true;})) { | ||
throw JSONRPCError(RPC_MISC_ERROR, strprintf("Peer nodeid %d does not exist", nodeid)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the FetchBlock call has to deal with this anyway, might be better to remove this code and let FetchBlock deal with it.
static RPCHelpMan getblockfrompeer() | ||
{ | ||
return RPCHelpMan{"getblockfrompeer", | ||
"\nAttempt to fetch block from a given peer.\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should also mention that this will disconnect the peer if the peer pretends to not have the block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems a bit too deep in the net_processing weeds?
@MarcoFalke thanks, working on a followup PR... |
could make sense to base on #23702 to avoid conflicts |
Followups in #23706 |
36b9fe1 rpc: getblockfrompeer (Sjors Provoost) 4aa9484 rpc: move Ensure* helpers to server_util.h (Sjors Provoost) Pull request description: This adds an RPC method to fetch a block directly from a peer. This can used to fetch stale blocks with lower proof of work that are normally ignored by the node (`headers-only` in `getchaintips`). Usage: ``` bitcoin-cli getblockfrompeer HASH peer_n ``` Closes #20155 Limitations: * you have to specify which peer to fetch the block from * the node must already have the header ACKs for top commit: jnewbery: ACK 36b9fe1 fjahr: re-ACK 36b9fe1 Tree-SHA512: 843ba2b7a308f640770d624d0aa3265fdc5c6ea48e8db32269b96a082b7420f7953d1d8d1ef2e6529392c7172dded9d15639fbc9c24e7bfa5cfb79e13a5498c8
923312f rpc: use peer_id, block_hash for FetchBlock (Sjors Provoost) 34d5399 rpc: more detailed errors for getblockfrompeer (Sjors Provoost) 60243ca rpc: turn already downloaded into error in getblockfrompeer (Sjors Provoost) 809d66b rpc: clarify getblockfrompeer behavior when called multiple times (Sjors Provoost) 0e3d7c5 refactor: drop redundant hash argument from FetchBlock (Sjors Provoost) 8d1a3e6 rpc: allow empty JSON object result (Sjors Provoost) bfbf91d test: fancier Python for getblockfrompeer (Sjors Provoost) Pull request description: Followups from bitcoin#20295. ACKs for top commit: jonatack: ACK 923312f 📦 fjahr: tested ACK 923312f Tree-SHA512: da9eca76e302e249409c9d7f0d16cca668ed981e2ab6ca2d1743dad0d830b94b1bc5ffb9028a00764b863201945c273cc8f4409a4c9ca3817830007dffa2bc20
…he block header Github-Pull: bitcoin#20295 Rebased-From: d0b5374
Summary: This is a partial backport of [[bitcoin/bitcoin#20295 | core#20295]] bitcoin/bitcoin@b884aba Depends on D12700 Test Plan: `ninja all check-all` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Subscribers: Fabien Differential Revision: https://reviews.bitcoinabc.org/D12701
Summary: This adds an RPC method to fetch a block directly from a peer. This can used to fetch stale blocks with lower proof of work that are normally ignored by the node (`headers-only` in `getchaintips`). Limitations: - you have to specify which peer to fetch the block from - the node must already have the header Co-authored-by: John Newbery <john@johnnewbery.com> This is a backport of [[bitcoin/bitcoin#20295 | core#20295]], [[bitcoin/bitcoin#23702 | core#23702]] and [[bitcoin/bitcoin#23706 | core#23706]] (partial) bitcoin/bitcoin@dce8c4c bitcoin/bitcoin@aaaa34e bitcoin/bitcoin@bfbf91d bitcoin/bitcoin@809d66b bitcoin/bitcoin@0e3d7c5 The main commit is the first one. The other commits are minor style & comments improvements, and one commit removing an unnecessary argument in the newly added `FetchBlock` function. Test Plan: `ninja all check-all` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Subscribers: Fabien Differential Revision: https://reviews.bitcoinabc.org/D12716
This adds an RPC method to fetch a block directly from a peer. This can used to fetch stale blocks with lower proof of work that are normally ignored by the node (
headers-only
ingetchaintips
).Usage:
Closes #20155
Limitations: